From 04ad36e3a9845a401d95d35880deda5ea390e9dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michaela=20Br=C3=BCckner?= <brueckner@data-quest.de>
Date: Thu, 25 May 2023 14:05:36 +0000
Subject: [PATCH] closes #1327

Closes #1327

Merge request studip/studip!1147
---
 app/controllers/admin/courses.php             |    8 -
 app/controllers/course/room_requests.php      | 1181 +++++++----------
 app/controllers/course/timesrooms.php         |   41 +-
 .../_new_request_form_footer.php              |   41 +
 .../room_requests/_new_request_header.php     |   18 +
 .../room_requests/_request_edit_header.php    |   30 -
 .../room_requests/_request_form_footer.php    |   28 -
 .../room_requests/_request_form_header.php    |    4 -
 .../room_requests/_room_with_properties.php   |   10 +
 app/views/course/room_requests/index.php      |   12 +-
 app/views/course/room_requests/new.php        |   47 -
 .../{request_start.php => new_request.php}    |  101 +-
 .../request_find_available_properties.php     |  124 ++
 .../request_find_matching_rooms.php           |  134 ++
 .../request_select_properties.php             |   65 -
 .../room_requests/request_select_room.php     |   66 -
 .../room_requests/request_show_summary.php    |   88 ++
 .../course/room_requests/request_summary.php  |  100 --
 app/views/course/timesrooms/_cancel_form.php  |    1 +
 .../course/timesrooms/_regularEvents.php      |   11 +-
 app/views/course/timesrooms/_roomRequest.php  |  114 +-
 .../course/timesrooms/_roomRequestInfo.php    |    4 +-
 app/views/course/timesrooms/editDate.php      |    4 +-
 app/views/course/timesrooms/index.php         |   10 -
 .../ResourcePropertyDefinition.class.php      |   23 +-
 lib/modules/CoreAdmin.class.php               |    7 -
 .../javascripts/bootstrap/application.js      |    3 +
 resources/assets/stylesheets/scss/forms.scss  |    4 +-
 28 files changed, 1082 insertions(+), 1197 deletions(-)
 create mode 100644 app/views/course/room_requests/_new_request_form_footer.php
 create mode 100644 app/views/course/room_requests/_new_request_header.php
 delete mode 100644 app/views/course/room_requests/_request_edit_header.php
 delete mode 100644 app/views/course/room_requests/_request_form_footer.php
 delete mode 100644 app/views/course/room_requests/_request_form_header.php
 create mode 100644 app/views/course/room_requests/_room_with_properties.php
 delete mode 100644 app/views/course/room_requests/new.php
 rename app/views/course/room_requests/{request_start.php => new_request.php} (54%)
 create mode 100644 app/views/course/room_requests/request_find_available_properties.php
 create mode 100644 app/views/course/room_requests/request_find_matching_rooms.php
 delete mode 100644 app/views/course/room_requests/request_select_properties.php
 delete mode 100644 app/views/course/room_requests/request_select_room.php
 create mode 100644 app/views/course/room_requests/request_show_summary.php
 delete mode 100644 app/views/course/room_requests/request_summary.php

diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php
index 231099c1866..a683639e416 100644
--- a/app/controllers/admin/courses.php
+++ b/app/controllers/admin/courses.php
@@ -1055,14 +1055,6 @@ class Admin_CoursesController extends AuthenticatedController
             unset($actions[16]);
         }
 
-        if (Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
-            $actions[4] = [
-                'name'  => 'Raumanfragen',
-                'title' => _('Raumanfragen'),
-                'url'   => 'dispatch.php/course/room_requests/index?cid=%s&origin=admin_courses',
-                'attributes' => ['data-dialog' => 'size=big'],
-            ];
-        }
         ksort($actions);
 
         foreach (PluginManager::getInstance()->getPlugins('AdminCourseAction') as $plugin) {
diff --git a/app/controllers/course/room_requests.php b/app/controllers/course/room_requests.php
index 95163634c00..3250ba2d580 100644
--- a/app/controllers/course/room_requests.php
+++ b/app/controllers/course/room_requests.php
@@ -10,6 +10,7 @@
  *
  * @author      André Noack <noack@data-quest.de>
  * @author      Moritz Strohm <strohm@data-quest.de>
+ * @author      Michaela Brückner <brueckner@data-quest.de>
  * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
  * @category    Stud.IP
  * @package     admin
@@ -30,6 +31,10 @@ class Course_RoomRequestsController extends AuthenticatedController
         parent::before_filter($action, $args);
 
         $this->current_user = User::findCurrent();
+        $this->user_is_global_resource_admin = ResourceManager::userHasGlobalPermission(
+            $this->current_user,
+            'admin'
+        );
         $this->course_id = Request::option('cid', $args[0] ?? null);
         $pagetitle = '';
         //Navigation in der Veranstaltung:
@@ -48,6 +53,10 @@ class Course_RoomRequestsController extends AuthenticatedController
         $pagetitle .= Course::find($this->course_id)->getFullname() . ' - ';
         $pagetitle .= _('Verwalten von Raumanfragen');
         PageLayout::setTitle($pagetitle);
+
+        $this->available_room_categories = ResourceCategory::findByClass_name(Room::class);
+        $this->step = 0;
+        $this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
     }
 
     /**
@@ -101,520 +110,323 @@ class Course_RoomRequestsController extends AuthenticatedController
         $this->render_template('course/room_requests/_request.php', null);
     }
 
-
     /**
-     * create a new room request
+     * Start point to creating a new request
      */
-    public function new_action()
+    public function new_request_action($request_id = '')
     {
         if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
             throw new AccessDeniedException(
                 _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
             );
         }
-        $options = [];
-        $this->url_params = [];
-        if (Request::get('origin') !== null) {
-            $this->url_params['origin'] = Request::get('origin');
-        }
-        if (!RoomRequest::existsByCourse($this->course_id)) {
-            $options[] = [
-                'value' => 'course',
-                'name'  => _('alle regelmäßigen und unregelmäßigen Termine der Veranstaltung')
-            ];
-        }
-        foreach (SeminarCycleDate::findBySeminar($this->course_id) as $cycle) {
-            if (!RoomRequest::existsByMetadate($cycle->getId())) {
-                $name = _("alle Termine einer regelmäßigen Zeit");
-                $name .= ' (' . $cycle->toString('full') . ')';
-                $options[] = ['value' => 'cycle_' . $cycle->getId(), 'name' => $name];
-            }
-        }
-        foreach (CourseDate::findBySeminar_id($this->course_id) as $date) {
-            if (!RoomRequest::existsByDate($date['termin_id'])) {
-                $name = _("Einzeltermin der Veranstaltung");
-                $name .= ' (' . $date->getFullname() . ')';
-                $options[] = ['value' => 'date_' . $date['termin_id'], 'name' => $name];
-            }
-        }
-        $this->options = $options;
 
-        Helpbar::get()->addPlainText(_('Information'), _('Hier können Sie festlegen, welche Art von Raumanfrage Sie erstellen möchten.'));
-    }
+        Helpbar::get()->addPlainText(
+            _('Information'),
+            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
+        );
 
+        $this->request_id = $request_id;
 
-    /**
-     * Returns a reference to the session data array for the
-     * specified request-ID.
-     */
-    protected function &getRequestSessionData($request_id = null)
-    {
-        $result = null;
-        if ($request_id) {
-            if (!isset($_SESSION['course_room_request'])) {
-                $_SESSION['course_room_request'] = [];
-            }
-            if (!isset($_SESSION['course_room_request'][$request_id])) {
-                $_SESSION['course_room_request'][$request_id] = [];
-            }
-            $result =& $_SESSION['course_room_request'][$request_id];
+        if (Request::submitted('request_id')) {
+            $this->request_id = Request::get('request_id');
+        }
+        if (!$this->request_id) {
+            $this->request_id = md5(uniqid('RoomRequest'));
         }
-        return $result;
-    }
 
+        // e.g. cycle, course, date
+        $this->request_range = Request::get('range_str');
 
-    /**
-     * Returns a request instance that gets all its data set from the session.
-     * This is useful if a new request is being created.
-     */
-    protected function getRequestInstanceFromSession($request_id)
-    {
-        $session_data = &$this->getRequestSessionData($request_id);
-        $request = new RoomRequest($request_id);
-        if ($session_data['range'] == 'date-multiple') {
-            $request->setRangeFields($session_data['range'], $session_data['range_ids']);
-        } else {
-            $request->setRangeFields($session_data['range'], [$session_data['range_id']]);
+        // multiple dates
+        $this->request_range_ids = Request::getArray('range_ids') ?: $_SESSION[$this->request_id]['range_ids'] ?? [];
+        // a single date or whole course
+        $this->request_range_id = Request::get('range_id', Context::getId());
+
+        if (!isset($_SESSION[$this->request_id])) {
+            $_SESSION[$this->request_id] = [];
         }
-        $request->course_id = $this->course_id;
+        $_SESSION[$this->request_id]['range'] = $this->request_range ?: $_SESSION[$this->request_id]['range'] ?? null;
+        $_SESSION[$this->request_id]['range_ids'] = $this->request_range_ids ?: [$this->request_range_id];
+        $_SESSION[$this->request_id]['search_by'] = '';
+        $_SESSION[$this->request_id]['room_category_id'] = '';
+        $_SESSION[$this->request_id]['room_id'] = '';
+        $_SESSION[$this->request_id]['room_name'] = '';
+        $_SESSION[$this->request_id]['selected_properties'] = [];
 
-        return $request;
-    }
+        $this->request = null;
 
+        // look for existing request or create a new one
+        $this->request = new RoomRequest($this->request_id);
+        // time ranges (start date, end date)
+        $this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
+        $this->request_time_intervals = $this->request->getTimeIntervals();
 
-    /**
-     * This method loads data for the request editing actions.
-     * Depending on the editing step, more or less data have to
-     * be loaded.
-     *
-     * @param array $session_data Request data stored in the session.
-     *
-     * @param int $step The editing step:
-     *     1 = request_start
-     *     2 = request_select_properties
-     *     3 = request_select_room
-     *     4 = request_overview
-     */
-    protected function loadData($session_data, $step = 1)
-    {
-        $this->available_room_categories = [];
-        $this->room_name = '';
-        $this->category_id = '';
-        $this->category = null;
-        $this->available_properties = [];
-        $this->selected_properties = [];
-        $this->seats = '';
-        $this->comment = '';
-        $this->reply_lecturers = false;
-        $this->preparation_time = 0;
-
-        $this->course_id = Context::getId();
-        $this->user_is_global_resource_admin = ResourceManager::userHasGlobalPermission(
-            $this->current_user,
-            'admin'
-        );
-        $this->config = Config::get();
-        $this->direct_room_requests_only = $this->config->RESOURCES_DIRECT_ROOM_REQUESTS_ONLY;
-        if ($step >= 1) {
-            //Load all available room categories:
-            $this->available_room_categories = ResourceCategory::findByClass_name(
-                'Room'
-            );
-        }
-        if ($step >= 2) {
-            if (!empty($session_data['category_id'])) {
-                $this->category = ResourceCategory::find($session_data['category_id']);
-                if ($this->category) {
-                    //Get all available properties for the category:
-                    $this->available_properties = $this->category->getRequestableProperties();
-                }
-            }
-            $this->room_name = $session_data['room_name'] ?? '';
-            $this->category_id = $session_data['category_id'] ?? '';
-            $this->preparation_time = $session_data['preparation_time'] ?? '0';
-        }
-        if ($step >= 3) {
-            if ($this->category) {
-                $this->selected_properties = $session_data['selected_properties'] ?? [];
-            }
-        }
-        if ($step >= 4) {
-            $this->seats = $session_data['selected_properties']['seats'] ?? '0';
-            $this->comment = $session_data['comment']?? '';
-            $this->reply_lecturers = $session_data['reply_lecturers'] ?? '';
-            $this->preparation_time = $session_data['preparation_time'] ?? '';
-        }
     }
 
-
     /**
-     * This action is the entry point for adding properties to a room request.
+     * Step 1: Either selecting a room category or searching for a room name initially
+     * @param String $request_id ID of the request
      */
-    public function request_start_action($request_id = '')
+    public function request_first_step_action($request_id)
     {
         if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
             throw new AccessDeniedException(
                 _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
             );
         }
-        Helpbar::get()->addPlainText(
-            _('Information'),
-            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
-        );
 
         $this->request_id = $request_id;
-        if (Request::submitted('request_id')) {
-            $this->request_id = Request::get('request_id');
-        }
-        if (!$this->request_id) {
-            $this->request_id = md5(uniqid('RoomRequest'));
-        }
-
-        $session_data = &$this->getRequestSessionData($this->request_id);
 
-        $this->loadData($session_data, 1);
+        if (Request::isPost()) {
+            CSRFProtection::verifyUnsafeRequest();
 
-        $this->request = null;
+            $this->step = 1;
 
-        //Check if a request exists and set its ID in the session,
-        //it is needed later.
-        $this->request = RoomRequest::find(Request::get('request_id'));
-        if ($this->request instanceof RoomRequest) {
-            $session_data['request_id'] = $this->request->id;
-            $this->request_id = $this->request->id;
-        } elseif ($session_data['request_id']) {
-            //It is a new request that isn't stored yet. Load its basic data
-            //from the session and create a request object:
-            $this->request_id = $session_data['request_id'];
-            $this->request = $this->getRequestInstanceFromSession($this->request_id);
-        } else {
-            //A new request shall be created.
-            //Get the range from URL parameters.
-            $range = null;
-            $range_id = null;
-            $range_ids = [];
-            if (Request::submitted('range_str')) {
-                $range_str = explode('_', Request::get('range_str'));
-                $range = $range_str[0];
-                if ($range == 'course') {
-                    $range_id = $range_str[1];
-                    if (!$range_id) {
-                        $range_id = Context::getId();
-                    }
-                } else {
-                    if (count($range_str) > 2) {
-                        //More than one ID has been specified.
-                        $range_ids = array_slice($range_str, 1);
-                    } else {
-                        $range_id = $range_str[1];
-                    }
-                }
-            } else {
-                $range = Request::get('range');
-                $range_id = Request::get('range_id');
-                $range_ids = Request::getArray('range_ids');
-            }
-            $session_data['range'] = $range;
-            $session_data['range_id'] = $range_id;
-            $session_data['range_ids'] = $range_ids;
-            $session_data['request_id'] = $this->request_id;
-
-            //Create a request object:
-            $this->request = new RoomRequest($session_data['request_id']);
-            if ($range == 'date-multiple') {
-                $this->request->setRangeFields($range, $range_ids);
-            } else {
-                $this->request->setRangeFields($range, [$range_id]);
+            $this->category_id = Request::get('category_id');
+            $this->search_by_category = Request::submitted('search_by_category');
+            if (!isset($_SESSION[$request_id])) {
+                $_SESSION[$request_id] = [];
             }
-            $this->request->course_id = $this->course_id;
-        }
-        $available_rooms = RoomManager::countRequestableRooms();
-        if (($available_rooms < 51) && !Request::submitted('select_properties')) {
-            //Redirect to the room selection page:
-            $session_data['request_id'] = $this->request_id;
-            $this->redirect(
-                'course/room_requests/request_select_room/' . $this->request_id
-            );
-            return;
-        }
+            $_SESSION[$request_id]['room_category_id'] = $this->category_id;
 
-        if (Request::isPost()) {
-            CSRFProtection::verifyUnsafeRequest();
             $this->room_name = Request::get('room_name');
-            $this->category_id = Request::get('category_id');
-            if (Request::submitted('search_by_name')) {
-                if (!$this->room_name) {
-                    PageLayout::postError(
-                        _('Es wurde kein Raumname angegeben!')
-                    );
-                    return;
-                }
-                $session_data['room_name'] = $this->room_name;
-                $session_data['request_id'] = $this->request_id;
-                //Redirect to the room selection action.
+            $this->search_by_roomname = Request::submitted('search_by_name');
+            $_SESSION[$request_id]['room_name'] = $this->room_name;
+
+            // user selects a room category OR enters a room name
+            if ($this->category_id !== null && $this->search_by_category) {
+                $_SESSION[$request_id]['search_by'] = 'category';
                 $this->redirect(
-                    'course/room_requests/request_select_room/' . $this->request_id
+                    'course/room_requests/request_find_available_properties/' . $this->request_id . '/' . $this->step . '/category'
                 );
-            } elseif (Request::submitted('select_properties')) {
-                if (!$this->category_id) {
-                    PageLayout::postError(
-                        _('Es wurde keine Raumkategorie ausgewählt!')
-                    );
-                    return;
-                }
-                foreach ($this->available_room_categories as $category) {
-                    if ($category->id == $this->category_id) {
-                        //The selected category is in the array of
-                        //available categories.
-                        $session_data['request_id'] = $this->request_id;
-                        $session_data['category_id'] = $this->category_id;
-                        $session_data['room_name'] = $this->room_name;
-                        //Redirect to the property selection page:
-                        $this->redirect(
-                            'course/room_requests/request_select_properties/' . $this->request_id
-                           );
-                        return;
-                    }
-                }
-
-                //If this point is reached, then the selected room category ID
-                //is not in the array of available room categories.
-                PageLayout::postError(
-                    _('Die gewählte Raumkategorie wurde nicht gefunden!')
+            } elseif ($this->room_name && $this->search_by_roomname) {
+                $_SESSION[$request_id]['search_by'] = 'roomname';
+                $this->redirect(
+                    'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step . '/roomname'
+                );
+            } else {
+                $this->redirect(
+                    'course/room_requests/new_request/' . $this->request_id
                 );
             }
         }
-    }
 
+    }
 
     /**
-     * This action is called from request_start in the case that a
-     * resource category has been selected.
+     * Searching for (a) matching room(s) via room name, e.g. 'hör%'
+     * @param String $request_id ID of the request
+     * @param String $step
+     * @return void
      */
-    public function request_select_properties_action($request_id = '')
+    public function request_find_matching_rooms_action($request_id, $step)
     {
         if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
             throw new AccessDeniedException(
                 _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
             );
         }
-        Helpbar::get()->addPlainText(
-            _('Information'),
-            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
-        );
-
-        $this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
 
         $this->request_id = $request_id;
-        $session_data = &$this->getRequestSessionData($this->request_id);
-        $this->loadData($session_data, 2);
+        $this->step = (int)$step;
+        $this->room_name = $_SESSION[$request_id]['room_name'];
 
-        if ($this->direct_room_requests_only) {
-            throw new AccessDeniedException(
-                _('Das Erstellen von Raumanfragen anhand von Eigenschaften ist nicht erlaubt!')
-            );
+        $this->request = new RoomRequest($this->request_id);
+        $this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
+
+        $search_properties = $_SESSION[$request_id]['selected_properties'] ?? [];
+
+        if (!empty($_SESSION[$request_id]['room_category_id'])) {
+            $search_properties['room_category_id'] = $_SESSION[$request_id]['room_category_id'];
         }
 
-        $this->selected_properties = [];
-        $this->request = RoomRequest::find($this->request_id);
-        if ($this->request instanceof RoomRequest) {
-            //It is an existing request. If no properties have been selected
-            //via HTTP POST, set them from the request itself:
-            foreach ($this->request->properties as $property) {
-                $this->selected_properties[$property->name] = $property->state;
-            }
-            $this->category = $this->request->category;
-            $this->category_id = $this->request->category_id;
-            $this->seats = $this->request->seats;
-            $this->comment = $this->request->comment;
-            $this->reply_lecturers = $this->request->reply_recipients == 'lecturer';
-        } else {
-            //It is a new request. Create the request object and do nothing else.
-            $this->request = $this->getRequestInstanceFromSession($this->request_id);
-            $this->category_id = Request::get('category_id', $session_data['category_id']);
-            $this->category = ResourceCategory::find($this->category_id);
+        if (!empty($search_properties['seats'])) {
+            //The seats property value is a minimum.
+            $search_properties['seats'] = [
+                $search_properties['seats'],
+                null
+            ];
         }
 
-        if (!($this->category instanceof ResourceCategory)) {
-            PageLayout::postError(
-                _('Die gewählte Raumkategorie wurde nicht gefunden!')
+        // find rooms matching to selected properties
+        $this->available_rooms = RoomManager::findRooms(
+            $this->room_name,
+            null,
+            null,
+            $search_properties,
+            [],
+            'name ASC, mkdate ASC'
+        );
+
+        // small icons in front of room name to show whether they are bookable or not
+        $this->available_room_icons = $this->getRoomBookingIcons($this->available_rooms);
+
+        // selected room and its category
+        $this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?: $this->request->resource_id);
+
+        $this->selected_room_category_id = $this->selected_room->category_id ?: $_SESSION[$request_id]['room_category_id'];
+
+        $_SESSION[$request_id]['room_category_id'] = $_SESSION[$request_id]['room_category_id'] ?: $this->selected_room->category_id;
+
+        // after selecting a room, go to next step or stay here if no room was selected at all
+        if (Request::submitted('select_room')) {
+            $this->selected_room_id = Request::get('selected_room_id');
+            $_SESSION[$request_id]['room_id'] = $this->selected_room_id;
+            $_SESSION[$request_id]['select_room'] = true;
+
+            $this->redirect(
+                'course/room_requests/request_check_properties/' . $this->request_id
             );
             return;
         }
 
-        $this->available_properties = $this->category->getRequestableProperties();
+        // we might also search for new rooms and stay within step 1
+        else if (Request::get('room_name') && Request::submitted('search_by_name')) {
+            $_SESSION[$request_id]['room_name'] = Request::get('room_name');
+            $this->redirect(
+                'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
+            );
+            return;
+        }
 
-        if (empty($session_data['selected_properties']['seats'])) {
-            $this->course = Course::find($this->course_id);
-            $admission_turnout = $this->course->admission_turnout;
-            $this->selected_properties['seats'] =
-                $admission_turnout ?: Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
+        // or we filter via category
+        else if (Request::get('category_id') && Request::submitted('select_properties')) {
+            $_SESSION[$request_id]['search_by'] = 'category';
+            $_SESSION[$request_id]['room_category_id'] = Request::get('category_id');
+            $this->redirect(
+                'course/room_requests/request_find_available_properties/' . $this->request_id . '/' . $this->step
+            );
+            return;
+        } else if (Request::submitted('reset_category')) {
+            //Delete all selected properties from the session since the category is reset
+            $_SESSION[$request_id]['selected_properties'] = [];
+            $_SESSION[$request_id]['room_category_id'] = '';
+            $_SESSION[$request_id]['room_name'] = '';
+            $_SESSION[$request_id]['room_id'] = '';
+            $this->redirect('course/room_requests/request_find_available_properties/' . $this->request_id . '/1');
+            return;
         }
 
-        if (Request::isPost()) {
-            CSRFProtection::verifyUnsafeRequest();
-            $this->selected_properties = Request::getArray('selected_properties');
-            //Filter the selected properties so that only those properties
-            //that are available for the room category can be used.
-            $filtered_selected_properties = [];
-            foreach ($this->available_properties as $property) {
-                if (in_array($property->name, array_keys($this->selected_properties))) {
-                    //Filter out all empty properties:
-                    if ($this->selected_properties[$property->name]) {
-                        $filtered_selected_properties[$property->name] =
-                            $this->selected_properties[$property->name];
+        // for step 2: after choosing a specific room OR searching via properties
+        if ($this->step === 2) {
+            if ($_SESSION[$request_id]['search_by'] == 'roomname') {
+                // find category via room
+                $this->category = ResourceCategory::find($this->selected_room_category_id);
+                if ($this->category) {
+                    $this->available_properties = $this->category->getRequestableProperties();
+                }
+
+                $this->selected_properties = $_SESSION[$request_id]['selected_properties'];
+                $this->room = Room::find($_SESSION[$request_id]['room_id']);
+                $this->selected_properties['seats'] = $_SESSION[$request_id]['selected_properties']['seats']
+                    ?: $this->course->admission_turnout
+                    ?: Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
+                $_SESSION[$request_id]['selected_properties']['seats'] = $this->selected_properties['seats'];
+            } else if ($_SESSION[$request_id]['search_by'] === 'category') {
+                $this->room = Room::find($_SESSION[$request_id]['room_id']);
+                if ($this->room) {
+                    $this->grouped_properties = $this->room->getGroupedProperties();
+                    foreach ($this->grouped_properties as $properties) {
+                        foreach ($properties as $property) {
+                            $this->selected_properties[$property->name] = $property->state;
+                        }
                     }
                 }
+
             }
-            $this->selected_properties = $filtered_selected_properties;
-            $this->preparation_time = Request::get('preparation_time');
-            if ($this->preparation_time > $this->max_preparation_time) {
-                PageLayout::postError(
-                    sprintf(
-                        _('Die eingegebene Rüstzeit überschreitet das erlaubte Maximum von %d Minuten!'),
-                        $this->max_preparation_time
-                    )
-                );
-                return;
-            }
-            $session_data['preparation_time'] = $this->preparation_time;
-            $session_data['category_id'] = $this->category_id;
-
-            if (Request::submitted('search_by_name')) {
-                //Delete all selected properties from the session since the
-                //search by name (name only) has been used.
-                $session_data['selected_properties'] = [];
-                $session_data['room_name'] = Request::get('room_name');
-                $this->redirect(
-                    'course/room_requests/request_select_room/' . $this->request_id
-                );
-            } elseif (Request::submitted('reset_category')) {
-                //Delete all selected properties from the session since the
-                //category is reset:
-                $session_data['selected_properties'] = [];
-                $this->redirect(
-                    'course/room_requests/request_start/' . $this->request_id
-                );
-            } elseif (Request::submitted('search_rooms')) {
-                //Store the selected properties in the session and redirect.
-                $session_data['selected_properties'] = $this->selected_properties;
-                $this->redirect(
-                    'course/room_requests/request_select_room/' . $this->request_id
-                );
-            } elseif (Request::submitted('save') || Request::submitted('save_and_close')) {
-                //Save the request and stay on the page (save) or return
-                //to the overview page (save_and_close).
 
-                if ($this->selected_properties['seats'] < 1) {
+            // find rooms fitting to category and properties
+            if (Request::submitted('search_rooms')) {
+                $this->selected_properties = Request::getArray('selected_properties');
+                $_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
+
+                // no min number of seats
+                if (
+                    (!$_SESSION[$request_id]['selected_properties']['seats'] || $_SESSION[$request_id]['selected_properties']['seats'] < 1)
+                    && $_SESSION[$request_id]['search_by'] === 'category'
+                ) {
                     PageLayout::postError(
-                        _('Es wurde keine Anzahl an gewünschten Sitzplätzen angegeben!')
+                        _('Die Mindestanzahl der Sitzplätze beträgt 1!')
+                    );
+                    $this->redirect(
+                        'course/room_requests/request_find_matching_rooms/' . $request_id . '/' . $this->step
                     );
                     return;
-                }
-
-                $this->request->category_id = $session_data['category_id'];
-                if ($this->request->isNew()) {
-                    //Set the requester:
-                    $this->request->user_id = $this->current_user->id;
-                } else {
-                    //Do another thing: Delete all previously set properties:
-                    $this->request->properties->delete();
-                }
-                $this->request->preparation_time = $this->preparation_time * 60;
-                $this->request->comment = Request::get('comment');
-                if (Request::get('reply_lecturers')) {
-                    $this->request->reply_recipients = 'lecturer';
-                } else {
-                    $this->request->reply_recipients = 'requester';
-                }
-
-                if ($this->request->isDirty()) {
-                    $storing_successful = $this->request->store();
                 } else {
-                    $storing_successful = true;
-                }
-
-                if ($storing_successful) {
-                    //Store the properties:
-                    foreach ($this->selected_properties as $name => $state) {
-                        $result = $this->request->setProperty($name, $state);
-                    }
-                    $this->request->store();
-                    //Delete the session data:
-                    $session_data = [];
-                    PageLayout::postSuccess(_('Die Anfrage wurde gespeichert!'));
-                    if (Request::submitted('save_and_close')) {
-                        $this->relocate('course/room_requests/index');
-                    }
-                } else {
-                    PageLayout::postError(
-                        _('Die Anfrage konnte nicht gespeichert werden!')
+                    $this->redirect(
+                        'course/room_requests/request_find_matching_rooms/' . $request_id . '/' . $this->step
                     );
+                    return;
                 }
             }
+
+            // let's find all the properties belonging to the selected category
+            $this->room_category_id = $_SESSION[$request_id]['room_category_id'];
+            $this->category = ResourceCategory::find($this->room_category_id);
+            $this->available_properties = $this->category->getRequestableProperties();
+
+            // properties, like 'Sitzplätze', 'behindertengerecht' etc
+            $this->selected_properties = $_SESSION[$request_id]['selected_properties'];
+            $this->preparation_time = $_SESSION[$request_id]['preparation_time'];
+            $this->comment = $_SESSION[$request_id]['comment'];
+            $this->request->category_id = $_SESSION[$request_id]['room_category_id'];
+
+            // finally we want to show a summary
+            if (Request::submitted('show_summary')) {
+                $this->selected_room_id = Request::get('selected_room_id');
+                $_SESSION[$request_id]['room_id'] = $this->selected_room_id;
+                $_SESSION[$request_id]['selected_properties'] = Request::getArray('selected_properties');
+                $this->redirect('course/room_requests/request_show_summary/' . $this->request_id );
+            }
         }
     }
 
-
     /**
-     * This action is called either directly from request_start
-     * (in case a room name is set but no resource category) or after
-     * selecting properties in request_select_properties.
-     * It searches for rooms depending on the selected properties
-     * or the selected name.
+     * Searching for (a) matching room(s) by initially selecting a room category, e.g. 'Hörsaal'
+     * @param String $request_id ID of the request
+     * @param String $step
+     * @return void
      */
-    public function request_select_room_action($request_id)
+    public function request_find_available_properties_action($request_id, $step)
     {
         if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
             throw new AccessDeniedException(
                 _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
             );
         }
-        Helpbar::get()->addPlainText(
-            _('Information'),
-            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
-        );
 
         $this->request_id = $request_id;
-        $session_data = &$this->getRequestSessionData($this->request_id);
-        $this->max_preparation_time = Config::get()->RESOURCES_MAX_PREPARATION_TIME;
-        $this->loadData($session_data, 3);
+        $this->step = (int)$step;
 
-        $this->request = RoomRequest::find($this->request_id);
-        if (!($this->request instanceof RoomRequest)) {
-            //It is a new request. Create the request object and do nothing else.
-            $this->request = $this->getRequestInstanceFromSession($this->request_id);
-        } else {
-            $this->seats = $this->request->seats;
-            $this->comment = $this->request->comment;
-            $this->reply_lecturers = $this->request->reply_recipients == 'lecturer';
-        }
+        $this->request = new RoomRequest($this->request_id);
+        $this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
 
-        $search_properties = $this->selected_properties ?? [];
-        if (!empty($session_data['category_id'])) {
-            $search_properties['room_category_id'] = $session_data['category_id'];
-        }
-        if (!empty($search_properties['seats'])) {
-            //The seats property value is a minimum.
+        // let's find all the properties belonging to the selected category
+        $this->room_category_id = $_SESSION[$request_id]['room_category_id'] ?: $this->request->category_id;
+        $this->room_name = $_SESSION[$request_id]['room_name'];
+        $this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?: $this->request->resource_id);
+        $this->category = $this->room_category_id ? ResourceCategory::find($this->room_category_id) : '';
+        $this->available_properties = $this->room_category_id ? $this->category->getRequestableProperties() : '';
+        $this->selected_properties = $_SESSION[$request_id]['selected_properties'];
+
+        $this->course = Course::find($this->course_id);
+        $this->selected_properties['seats'] = $_SESSION[$request_id]['selected_properties']['seats']
+            ?: $this->course->admission_turnout
+            ?: Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
+
+        $this->preparation_time = $_SESSION[$request_id]['preparation_time'];
+        $this->comment = $_SESSION[$request_id]['comment'];
+
+        // when searching for a room name, list found room
+        if ($_SESSION[$request_id]['room_name'] !== '') {
+            $search_properties['room_category_id'] = $this->room_category_id;
             $search_properties['seats'] = [
-                $search_properties['seats'],
+                1,
                 null
             ];
-        }
-        $this->matching_rooms = [];
-        if (!$this->room_name && !$this->selected_properties) {
-            //Load all requestable rooms:
-            $this->matching_rooms = RoomManager::findRooms(
-                '',
-                null,
-                null,
-                [],
-                [],
-                'name ASC, mkdate ASC'
-            );
-        } else {
-            //Search rooms by the selected properties:
-            $this->matching_rooms = RoomManager::findRooms(
+
+            $this->available_rooms = RoomManager::findRooms(
                 $this->room_name,
                 null,
                 null,
@@ -622,374 +434,267 @@ class Course_RoomRequestsController extends AuthenticatedController
                 [],
                 'name ASC, mkdate ASC'
             );
-        }
-        $this->available_room_icons = [];
-        $request_time_intervals = $this->request->getTimeIntervals();
-        foreach ($this->matching_rooms as $room) {
-            $request_dates_booked = 0;
-            foreach ($request_time_intervals as $interval) {
-                $booked = ResourceBookingInterval::countBySql(
-                    'resource_id = :room_id AND begin < :end AND end > :begin',
-                    [
-                        'room_id' => $room->id,
-                        'begin' => $interval['begin'],
-                        'end' => $interval['end']
-                    ]
-                ) > 0;
-                if ($booked) {
-                    $request_dates_booked++;
-                }
-            }
-            if ($request_dates_booked == 0) {
-                $this->available_room_icons[$room->id] =
-                    Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(
-                        [
-                            'class' => 'text-bottom',
-                            'title' => _('freier Raum')
-                        ]
-                    );
-                $this->available_rooms[] = $room;
-            } elseif ($request_dates_booked < $request_time_intervals) {
-                $this->available_room_icons[$room->id] =
-                    Icon::create('exclaim-circle', Icon::ROLE_STATUS_YELLOW)->asImg(
-                        [
-                            'class' => 'text-bottom',
-                            'title' => _('teilweise belegter Raum')
-                        ]
-                    );
-                $this->available_rooms[] = $room;
-            }
+
+            // small icons in front of room name to show whether they are bookable or not
+            $this->available_room_icons = $this->getRoomBookingIcons($this->available_rooms);
         }
 
-        if (Request::isPost()) {
-            CSRFProtection::verifyUnsafeRequest();
+    }
 
-            $this->room_name = Request::get('room_name');
-            $session_data['room_name'] = $this->room_name;
+    /**
+     * Check desired properties for a room category to go to step 2
+     * @param String $request_id ID of the request
+     * @return void
+     *
+     */
+    public function request_check_properties_action($request_id)
+    {
+        if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
+            throw new AccessDeniedException(
+                _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
+            );
+        }
 
+        $this->request_id = $request_id;
+
+        // select a room, search for a room name or search for rooms matching properties
+        if (Request::submitted('select_room')) {
             $this->selected_room_id = Request::get('selected_room_id');
-            if ($this->selected_room_id) {
-                $room_found = false;
-                foreach ($this->available_rooms as $room) {
-                    if ($this->selected_room_id == $room->id) {
-                        $room_found = true;
-                        break;
-                    }
-                }
-                if (!$room_found) {
-                    //The room could not be found in the list of available rooms.
-                    PageLayout::postError(_('Der gewählte Raum wurde nicht gefunden!'));
-                    return;
-                }
-            }
-            if (Request::submitted('search_by_name')) {
-                if (!$this->room_name) {
-                    PageLayout::postError(
-                        _('Es wurde kein Raumname angegeben!')
-                    );
-                    return;
-                }
-                $session_data['room_name'] = $this->room_name;
-                $session_data['request_id'] = $this->request_id;
-                //Redirect to the room selection action.
+            $_SESSION[$request_id]['room_id'] = $this->selected_room_id;
+            $_SESSION[$request_id]['select_room'] = true;
+            $this->step = 2;
+            $this->request = new RoomRequest($this->request_id);
+            $this->redirect(
+                'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
+            );
+        } else if (Request::get('room_name') && Request::submitted('search_by_name')) {
+            $this->selected_properties = Request::getArray('selected_properties');
+            $this->category_id = Request::get('category_id');
+            $_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
+            $_SESSION[$request_id]['room_category_id'] = $this->category_id;
+            $_SESSION[$request_id]['comment'] = $this->comment;
+            $_SESSION[$request_id]['room_name'] = Request::get('room_name');
+            $this->request = new RoomRequest($this->request_id);
+            $this->redirect(
+                'course/room_requests/request_find_available_properties/' . $this->request_id . '/1/category'
+            );
+
+        } else if (Request::submitted('search_rooms')) {
+            $this->selected_properties = Request::getArray('selected_properties');
+            $this->category_id = Request::get('category_id');
+            $_SESSION[$request_id]['room_category_id'] = $this->category_id;
+            $_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
+            $_SESSION[$request_id]['room_name'] = '';
+
+            // no min number of seats
+            if (
+                (!$_SESSION[$request_id]['selected_properties']['seats'] || $_SESSION[$request_id]['selected_properties']['seats'] < 1)
+                && $_SESSION[$request_id]['search_by'] === 'category'
+            ) {
+                PageLayout::postError(
+                    _('Die Mindestanzahl der Sitzplätze beträgt 1!')
+                );
+
                 $this->redirect(
-                    'course/room_requests/request_select_room/' . $this->request_id
+                    'course/room_requests/request_find_available_properties/' . $request_id . '/1/category'
                 );
-            } elseif (Request::submitted('search_rooms')) {
-                //Store the form data in the session and reload.
-                $session_data['selected_properties'] = Request::getArray('selected_properties');
-                $this->redirect('course/room_requests/request_select_room/' . $this->request_id);
-            } elseif (Request::submitted('select_room')) {
-                $session_data['selected_properties'] = Request::getArray('selected_properties');
-                $session_data['selected_room_id'] = $this->selected_room_id;
-                $this->redirect('course/room_requests/request_summary/' . $this->request_id);
-            } elseif (Request::submitted('select_properties')) {
-                $this->category_id = Request::get('category_id');
-                if (!$this->category_id) {
-                    PageLayout::postError(
-                        _('Es wurde keine Raumkategorie ausgewählt!')
-                    );
-                    return;
-                }
-                foreach ($this->available_room_categories as $category) {
-                    if ($category->id == $this->category_id) {
-                        //The selected category is in the array of
-                        //available categories.
-                        $session_data['request_id'] = $this->request_id;
-                        $session_data['category_id'] = $this->category_id;
-                        $session_data['room_name'] = $this->room_name;
-                        //Redirect to the property selection page:
-                        $this->redirect(
-                            'course/room_requests/request_select_properties/' . $this->request_id
-                           );
-                        return;
-                    }
-                }
-            } elseif (Request::submitted('reset_category')) {
-                //Delete all selected properties from the session since the
-                //category is reset:
-                $session_data['selected_properties'] = [];
-                $session_data['selected_room_id'] = $this->selected_room_id;
-                $session_data['category_id'] = '';
-                $session_data['room_name'] = '';
-                $this->redirect('course/room_requests/request_start/' . $this->request_id);
-            } elseif (Request::submitted('save') || Request::submitted('save_and_close')) {
-                $session_data['selected_properties'] = Request::getArray('selected_properties');
-                if ($session_data['selected_properties']['seats'] < 1) {
-                    PageLayout::postError(
-                        _('Es wurde keine Anzahl an gewünschten Sitzplätzen angegeben!')
+            } else {
+                $this->step = 2;
+                $this->request = new RoomRequest($this->request_id);
+                $this->redirect(
+                        'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
                     );
-                    return;
-                }
-                $session_data['selected_room_id'] = $this->selected_room_id;
-                //Store all request data from the session in the request:
-                $this->request->category_id = $session_data['category_id'];
-                $this->request->updateProperties($session_data['selected_properties']);
-                $this->request->resource_id = (
-                    $this->selected_room_id ?: ''
-                );
-                $this->request->comment = Request::get('comment');
-                if (Request::get('reply_lecturers')) {
-                    $this->request->reply_recipients = 'lecturer';
-                } else {
-                    $this->request->reply_recipients = 'requester';
-                }
+            }
+        } else if (Request::submitted('reset_category')) {
+            //Delete all selected properties from the session since the category is reset
+            $_SESSION[$request_id]['selected_properties'] = [];
+            $_SESSION[$request_id]['room_category_id'] = '';
+            $this->redirect('course/room_requests/request_find_available_properties/' . $this->request_id . '/1');
+        } else if (Request::submitted('search_by_category')) {
+            if (Request::get('category_id') === '0') {
+                $_SESSION[$request_id]['room_category_id'] = '';
+            } else {
+                $_SESSION[$request_id]['room_category_id'] = Request::get('category_id');
+            }
 
-                if ($this->request->isNew()) {
-                    //Set the requester:
-                    $this->request->user_id = $this->current_user->id;
-                }
+            $this->redirect(
+                'course/room_requests/request_find_available_properties/' . $this->request_id . '/1'  . '/category'
+            );
+        } else if (Request::submitted('show_summary')) {
+            $this->request = new RoomRequest($this->request_id);
+            $this->selected_properties = Request::getArray('selected_properties');
 
-                if ($this->request->isDirty()) {
-                    $storing_successful = $this->request->store();
-                } else {
-                    $storing_successful = true;
-                }
+            $_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
+            $this->selected_room_id = Request::get('selected_room_id');
+            $_SESSION[$request_id]['room_id'] = $this->selected_room_id;
 
-                if ($storing_successful) {
-                    //Delete the session data:
-                    $session_data = [];
-                    PageLayout::postSuccess(_('Die Anfrage wurde gespeichert!'));
-                    if (Request::submitted('save_and_close')) {
-                        $this->relocate('course/room_requests/index');
-                    }
-                } else {
-                    PageLayout::postError(
-                        _('Die Anfrage konnte nicht gespeichert werden!')
-                    );
-                }
-            }
+            $this->redirect('course/room_requests/request_show_summary/' . $this->request_id  );
+        } else {
+            $this->step = 2;
+            $this->request = new RoomRequest($this->request_id);
+            $this->redirect(
+                'course/room_requests/request_find_matching_rooms/' . $this->request_id . '/' . $this->step
+            );
         }
-    }
 
+    }
 
     /**
-     * This action is either called from request_select_room after a room
-     * has been selected, from request_select_properties after properties
-     * have been selected or when an existing request shall be edited.
+     * Show a summary of all request properties before storing; we have the possibility of going back and
+     * editing if necessary. This action is also used for editing a request via action menu
+     * @param String $request_id ID of the request
+     * @return void
+     *
      */
-    public function request_summary_action($request_id = null)
+    public function request_show_summary_action($request_id)
     {
         if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
             throw new AccessDeniedException(
                 _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
             );
         }
-        Helpbar::get()->addPlainText(
-            _('Information'),
-            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
-        );
-
-        $this->course = Course::find($this->course_id);
 
         $this->request_id = $request_id;
-        $session_data = &$this->getRequestSessionData($this->request_id);
+        $this->step = 3;
+
         if (Request::submitted('clear_cache')) {
-            $session_data = [];
+            $_SESSION[$request_id] = [];
         }
-        $this->loadData($session_data, 4);
-
-        $this->max_preparation_time = $this->config->RESOURCES_MAX_PREPARATION_TIME;
-
-        $this->request = RoomRequest::find($this->request_id);
-        $selected_room = null;
-        $this->seats = null;
-        if (($this->request instanceof RoomRequest) && !isset($session_data['request_id'])) {
-            //It is an existing request that hasn't been modified yet.
-            //Load its data directly.
-            if ($this->request->resource_id) {
-                $selected_room = Resource::find($this->request->resource_id);
-            }
 
-            $this->seats = $this->request->seats;
-            $this->comment = $this->request->comment;
-            $this->reply_lecturers = $this->request->reply_recipients == 'lecturer';
-            $this->preparation_time = intval($this->request->preparation_time / 60);
-            $this->category_id = $this->request->category->id;
-        } else {
-            //It is a new request or an existing request that is being modified.
-            //Create the request object from the session and do nothing else.
-            $this->request = $this->getRequestInstanceFromSession($this->request_id);
-            if ($session_data['selected_room_id']) {
-                $selected_room = Resource::find($session_data['selected_room_id']);
-            }
-            $this->seats = $session_data['selected_properties']['seats'];
-        }
-        if ($selected_room instanceof Resource) {
-            $this->selected_room = $selected_room->getDerivedClassInstance();
-            if (!($this->selected_room instanceof Room)) {
-                PageLayout::postWarning(
-                    _('Die ausgewählte Ressource ist kein Raum!')
-                );
+        $this->request = new RoomRequest($this->request_id);
+        $this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
+
+        $this->selected_room_category = ResourceCategory::find($_SESSION[$request_id]['room_category_id'] ?: $this->request->category_id);
+
+        $this->selected_room = Resource::find($_SESSION[$request_id]['room_id'] ?: $this->request->resource_id);
+
+        $this->room_id = $_SESSION[$request_id]['room_id'] ?: $this->request->resource_id;
+        $this->available_properties = $this->selected_room_category->getRequestableProperties();
+
+        $this->selected_properties = $_SESSION[$request_id]['selected_properties'] ?: [];
+        $this->request_properties = $this->request->properties;
+
+        // either properties from stored request or those from session
+        if ($this->request_properties && !$_SESSION[$request_id]['selected_properties']) {
+            foreach ($this->request_properties as $property) {
+                $this->selected_properties[$property->name] = $property->state;
             }
+            $_SESSION[$request_id]['selected_properties'] = $this->selected_properties;
         }
 
-        if (!$this->seats) {
-            $admission_turnout = $this->course->admission_turnout;
-            $this->seats = $admission_turnout ?: Config::get()->RESOURCES_ROOM_REQUEST_DEFAULT_SEATS;
+        $this->preparation_time = intval($this->request->preparation_time / 60);
+        $this->reply_lecturers = $this->request->reply_recipients === 'lecturer';
+        $this->comment = $this->request->comment;
+
+        $_SESSION[$request_id]['search_by'] = $this->selected_room ? 'roomname' : 'category';
+        $_SESSION[$request_id]['room_category_id'] = $this->selected_room_category->id;
+        $_SESSION[$request_id]['room_id'] = $this->selected_room->id;
+    }
+
+    public function store_request_action($request_id)
+    {
+        if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
+            throw new AccessDeniedException(
+                _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
+            );
         }
 
+        $this->request_id = $request_id;
+        $this->request = new RoomRequest($this->request_id);
+        $this->request->setRangeFields($_SESSION[$this->request_id]['range'], $_SESSION[$this->request_id]['range_ids']);
+
         if (Request::isPost()) {
             CSRFProtection::verifyUnsafeRequest();
 
-            $this->seats = Request::get('seats');
-            $this->comment = Request::get('comment');
-            $this->reply_lecturers = Request::get('reply_lecturers');
-            $this->confirmed_selected_room_id = Request::get('confirmed_selected_room_id');
+            $this->request->user_id = $this->current_user->id;
             $this->preparation_time = Request::get('preparation_time');
+            $this->request->preparation_time = $this->preparation_time * 60;
+            $this->request->comment = Request::get('comment');
 
-            if (Request::submitted('select_other_room') || Request::submitted('select_properties')
-                || Request::submitted('reset_category')) {
-                //The checks for the values of the seats property, the amount of
-                //preparation time and the other fields are skipped here since
-                //the request isn't stored. Even if it gets stored in one of
-                //the other steps that allow storing the request, the data
-                //from this step won't be stored with the request.
-                $session_data['selected_properties']['seats'] = $this->seats;
-                $session_data['comment'] = $this->comment;
-                $session_data['reply_lecturers'] = $this->reply_lecturers;
-                $session_data['preparation_time'] = $this->preparation_time;
-                $session_data['category_id'] = $this->category_id;
-                //Set the request-ID in the session to make it clear that the request has been modified:
-                $session_data['request_id'] = $this->request->id;
-                if (Request::submitted('select_other_room')) {
-                    $this->redirect('course/room_requests/request_select_room/' . $this->request_id);
-                } elseif (Request::submitted('reset_category')) {
-                    //Delete all selected properties from the session since the
-                    //category is reset:
-                    $session_data['selected_properties'] = [];
-                    unset($session_data['category_id']);
-                    $this->redirect('course/room_requests/request_start/' . $this->request_id);
-                } else {
-                    $this->redirect('course/room_requests/request_select_properties/' . $this->request_id);
-                }
-                return;
-            } elseif (Request::submitted('save') || Request::submitted('save_and_close')) {
-                // if a closed request is stored again, reopen it
-
-                if ($this->seats < 1) {
-                    PageLayout::postError(
-                        _('Es wurde keine Anzahl an Sitzplätzen angegeben!')
-                    );
-                    return;
-                }
-                if ($this->preparation_time > $this->max_preparation_time) {
-                    PageLayout::postError(
-                        sprintf(
-                            _('Die eingegebene Rüstzeit überschreitet das erlaubte Maximum von %d Minuten!'),
-                            $this->max_preparation_time
-                        )
-                    );
-                    return;
-                }
-
-                if ($this->request->isNew()) {
-                    //Set the requester:
-                    $this->request->user_id = $this->current_user->id;
-                }
-
-                $this->request->comment = $this->comment;
-                if ($this->reply_lecturers) {
-                    $this->request->reply_recipients = 'lecturer';
-                } else {
-                    $this->request->reply_recipients = 'requester';
-                }
-                $this->request->preparation_time = (int)$this->preparation_time * 60;
+            if (Request::get('reply_lecturers')) {
+                $this->request->reply_recipients = 'lecturer';
+            } else {
+                $this->request->reply_recipients = 'requester';
+            }
+            $this->request->category_id = $_SESSION[$request_id]['room_category_id'] ?: $this->request->category_id;
 
-                $this->request->course_id = $this->course_id;
-                $this->request->last_modified_by = $this->current_user->id;
+            $this->request->resource_id = $_SESSION[$request_id]['room_id'] ?: $this->request->resource_id;
+            $this->request->course_id = Context::getId();
+            $this->request->last_modified_by = $this->current_user->id;
 
-                if ($this->selected_room) {
-                    $this->request->resource_id = $this->selected_room->id;
-                    $this->request->category_id = $this->selected_room->category_id;
-                } else {
-                    $this->request->resource_id = '';
-                    $this->request->category_id = $this->category_id;
-                }
+            $this->request->store();
 
-                if ($this->request->closed != 0) {
-                    PageLayout::postInfo(_('Die Raumanfrage wurde wieder geöffnet und damit erneut gestellt.'));
-                    $this->request->closed = 0;
-                }
-
-                if ($this->request->isDirty()) {
-                    $storing_successful = $this->request->store();
-                } else {
-                    $storing_successful = true;
-                }
+            //Store the properties:
+            foreach ($_SESSION[$request_id]['selected_properties'] as $name => $state) {
+                $this->request->setProperty($name, $state);
+            }
 
-                if ($storing_successful) {
-                    //Store the properties:
-                    $selected_properties = $session_data['selected_properties'];
-                    if ($selected_properties) {
-                        $selected_properties['seats'] = $this->seats;
-                        foreach ($selected_properties as $name => $state) {
-                            $result = $this->request->setProperty($name, $state);
-                        }
-                    } else {
-                        $result = $this->request->setProperty('seats', $this->seats);
-                    }
-                    $this->request->store();
-                    //Delete the session data:
-                    $session_data = [];
-                    PageLayout::postSuccess(_('Die Anfrage wurde gespeichert!'));
+            // once stored, we can delete the session data for this request
+            $_SESSION[$this->request_id] = [];
 
-                    if (Request::submitted('save_and_close')) {
-                        $this->relocate('course/room_requests/index');
-                    }
-                } else {
-                    PageLayout::postError(
-                        _('Die Anfrage konnte nicht gespeichert werden!')
-                    );
-                }
-            }
+            PageLayout::postSuccess(_('Die Anfrage wurde gespeichert!'));
+            $this->relocate('course/timesrooms/');
         }
     }
 
-
     /**
-     * Stores the request. This is called from request_summary,
-     * request_select_room and request_select_properties after the user
-     * clicked on "save" or "save and close".
+     * Store a request and its properties
+     * @param string $request ID of the request
+     * @param array $properties desired properties
+     * @return void
      */
-    public function request_store_action()
+    private function storeRequest($request, $properties)
     {
-        if (!Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
-            throw new AccessDeniedException(
-                _('Das Erstellen von Raumanfragen ist nicht erlaubt!')
-            );
-        }
-        Helpbar::get()->addPlainText(
-            _('Information'),
-            _('Hier können Sie Angaben zu gewünschten Raumeigenschaften machen.')
-        );
+        // once stored, we can delete the session data for this request
+        $request->store();
+        $_SESSION[$request->id] = [];
 
-        $this->user_is_global_resource_admin = ResourceManager::userHasGlobalPermission(
-            $this->current_user,
-            'admin'
-        );
+        //Store the properties:
+        foreach ($properties as $name => $state) {
+            $request->setProperty($name, $state);
+        }
     }
 
+    private function getRoomBookingIcons($available_rooms)
+    {
+        $this->available_room_icons = [];
+
+        $request_time_intervals = $this->request->getTimeIntervals();
+
+        foreach ($available_rooms as $room) {
+            $request_dates_booked = 0;
+            foreach ($request_time_intervals as $interval) {
+                $booked = ResourceBookingInterval::countBySql(
+                    'resource_id = :room_id AND begin < :end AND end > :begin',
+                    [
+                        'room_id' => $room->id,
+                        'begin' => $interval['begin'],
+                        'end' => $interval['end']
+                    ]
+                ) > 0;
+                if ($booked) {
+                    $request_dates_booked++;
+                }
+            }
+            if ($request_dates_booked === 0) {
+                $this->available_room_icons[$room->id] =
+                    Icon::create('check-circle', Icon::ROLE_STATUS_GREEN)->asImg(
+                        [
+                            'class' => 'text-bottom',
+                            'title' => _('freier Raum')
+                        ]
+                    );
+                $available_rooms[] = $room;
+            } elseif ($request_dates_booked < $request_time_intervals) {
+                $this->available_room_icons[$room->id] = Icon::create('exclaim-circle', Icon::ROLE_STATUS_YELLOW)->asImg([
+                    'class' => 'text-bottom',
+                    'title' => _('teilweise belegter Raum')
+                ]);
+                $available_rooms[] = $room;
+            }
+        }
+        return $this->available_room_icons;
+    }
 
     /**
      * delete one room request
@@ -1012,6 +717,6 @@ class Course_RoomRequestsController extends AuthenticatedController
                 }
             }
         }
-        $this->redirect('course/room_requests/index');
+        $this->redirect('course/timesrooms/index');
     }
 }
diff --git a/app/controllers/course/timesrooms.php b/app/controllers/course/timesrooms.php
index 3f72420bf3f..a00e266b2cc 100644
--- a/app/controllers/course/timesrooms.php
+++ b/app/controllers/course/timesrooms.php
@@ -130,7 +130,7 @@ class Course_TimesroomsController extends AuthenticatedController
             $this->show = [
                 'regular'     => true,
                 'irregular'   => true,
-                'roomRequest' => false,
+                'roomRequest' => true,
             ];
         }
         $this->linkAttributes   = ['fromDialog' => Request::isXhr() ? 1 : 0];
@@ -187,7 +187,22 @@ class Course_TimesroomsController extends AuthenticatedController
 
         $dates = $this->course->getDatesWithExdates();
 
+        $this->current_user = User::findCurrent();
+        $this->user_has_permissions = ResourceManager::userHasGlobalPermission($this->current_user, 'admin');
+
         $check_room_requests = Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS;
+        $this->room_requests = RoomRequest::findBySQL(
+            'course_id = :course_id
+            ORDER BY course_id, metadate_id, termin_id',
+            [
+                'course_id' => $this->course->id
+            ]
+        );
+
+        $this->global_requests = $this->course->room_requests->filter(function (RoomRequest $request) {
+            return $request->closed < 2 && !$request->termin_id;
+        });
+
         $single_dates  = [];
         $this->single_date_room_request_c = 0;
         foreach ($dates as $val) {
@@ -793,9 +808,10 @@ class Course_TimesroomsController extends AuthenticatedController
         }
 
         $this->redirect(
-            'course/room_requests/request_start',
+            'course/room_requests/new_request',
             [
                 'range' => 'date-multiple',
+                'range_str' => 'date-multiple',
                 'range_ids' => $appointment_ids
             ]
         );
@@ -1471,9 +1487,23 @@ class Course_TimesroomsController extends AuthenticatedController
         }
         Sidebar::Get()->addWidget($widget);
 
-        if ($GLOBALS['perm']->have_studip_perm('admin', $this->course->id)) {
-            $widget = new CourseManagementSelectWidget();
-            Sidebar::Get()->addWidget($widget);
+        if ($GLOBALS['perm']->have_perm('admin')) {
+            $list = new SelectWidget(
+                _('Veranstaltungen'),
+                $this->indexURL(),
+                'cid'
+            );
+
+            foreach (AdminCourseFilter::get()->getCoursesForAdminWidget() as $seminar) {
+                $list->addElement(new SelectElement(
+                    $seminar['Seminar_id'],
+                    $seminar['Name'],
+                    $seminar['Seminar_id'] === Context::getId(),
+                    $seminar['VeranstaltungsNummer'] . ' ' . $seminar['Name']
+                ));
+            }
+            $list->size = 8;
+            Sidebar::Get()->addWidget($list);
         }
     }
 
@@ -1661,6 +1691,7 @@ class Course_TimesroomsController extends AuthenticatedController
                     ];
                 }
             }
+            $this->selectable_rooms = [];
             $rooms_with_booking_permissions = 0;
             if ($current_user_is_resource_admin) {
                 $rooms_with_booking_permissions = Room::countAll();
diff --git a/app/views/course/room_requests/_new_request_form_footer.php b/app/views/course/room_requests/_new_request_form_footer.php
new file mode 100644
index 00000000000..4b847905002
--- /dev/null
+++ b/app/views/course/room_requests/_new_request_form_footer.php
@@ -0,0 +1,41 @@
+    <br>
+    <footer data-dialog-button>
+        <? if ($step !== 3) : ?>
+            <?= \Studip\LinkButton::create(
+                _('Zurück auf Anfang'),
+                $controller->url_for('course/room_requests/new_request/' . $request_id),
+                ['data-dialog' => 'size=big']
+            ) ?>
+        <? else: ?>
+                <?= \Studip\LinkButton::create(
+                    _('Angaben bearbeiten'),
+                    $controller->url_for('course/room_requests/request_find_available_properties/' . $request_id . '/1'),
+                    ['data-dialog' => 'size=big']
+                ) ?>
+
+        <? endif ?>
+
+        <? if ($step === 1 || $step === 2) : ?>
+                <? if ($_SESSION[$request_id]['search_by'] !== 'category') : ?>
+                    <? \Studip\Button::create(_('Raum auswählen'), 'select_room') ?>
+            <? endif ?>
+        <? endif ?>
+
+        <? if (($step === 1 && $_SESSION[$request_id]['room_category_id'] !== '0')
+            || $step === 2) : ?>
+            <?= \Studip\Button::create(_('Weiter'), 'show_summary') ?>
+        <? endif ?>
+
+        <? if ($step === 3) : ?>
+            <?= \Studip\Button::create(_('Raumanfrage speichern'), 'save_request') ?>
+        <? endif ?>
+
+        <?= \Studip\LinkButton::createCancel(
+            _('Abbrechen'),
+            $controller->url_for('course/room_requests/index/' . $course_id),
+            [
+                'title' => _('Abbrechen')
+            ]
+        ) ?>
+    </footer>
+</form>
diff --git a/app/views/course/room_requests/_new_request_header.php b/app/views/course/room_requests/_new_request_header.php
new file mode 100644
index 00000000000..cd0d381545a
--- /dev/null
+++ b/app/views/course/room_requests/_new_request_header.php
@@ -0,0 +1,18 @@
+<section class="resources-grid">
+    <section class="contentbox">
+        <header><h1><?= _('Anfrage') ?></h1></header>
+        <section>
+            <?= htmlready($request->getTypeString(), 1, 1) ?>
+            <? if ($request->getType() == 'course'): ?>
+                <?
+                $dates = $request->getDateString(true);
+                ?>
+                <?= tooltipHtmlIcon(implode('<br>', $dates)) ?>
+            <? endif ?>
+        </section>
+    </section>
+    <section class="contentbox">
+        <header><h1><?= _('Bearbeitungsstatus') ?></h1></header>
+        <section><?= htmlReady($request->getStatusText()) ?></section>
+    </section>
+</section>
diff --git a/app/views/course/room_requests/_request_edit_header.php b/app/views/course/room_requests/_request_edit_header.php
deleted file mode 100644
index 89790d6ab00..00000000000
--- a/app/views/course/room_requests/_request_edit_header.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<? if ($direct_room_requests_only): ?>
-    <?= MessageBox::info(
-        _('Geben Sie bitte den gewünschten Raum an. Ihre Raumanfrage wird von der zuständigen Raumvergabe bearbeitet.'),
-        [_('<strong>Achtung:</strong> Geben Sie bitte immer die notwendige Sitzplatzanzahl mit an!')]
-    )?>
-<? else: ?>
-    <?= MessageBox::info(
-        _('Geben Sie den gewünschten Raum und/oder Raumeigenschaften an. Ihre Raumanfrage wird von der zuständigen Raumvergabe bearbeitet.'),
-        [_('<strong>Achtung:</strong> Um später einen passenden Raum für Ihre Veranstaltung zu bekommen, geben Sie bitte immer die gewünschten Eigenschaften mit an!')]
-    )?>
-<? endif ?>
-<section class="resources-grid">
-    <section class="contentbox">
-        <header><h1><?= _('Anfrage') ?></h1></header>
-        <section>
-            <?= htmlready($request->getTypeString(), 1, 1) ?>
-            <? if ($request->getType() == 'course'): ?>
-                <?
-                $dates = $request->getDateString(true);
-                ?>
-                <?= tooltipHtmlIcon(implode('<br>', $dates)) ?>
-            <? endif ?>
-        </section>
-    </section>
-    <section class="contentbox">
-        <header><h1><?= _('Bearbeitungsstatus') ?></h1></header>
-        <section><?= htmlReady($request->getStatusText()) ?></section>
-    </section>
-</section>
-
diff --git a/app/views/course/room_requests/_request_form_footer.php b/app/views/course/room_requests/_request_form_footer.php
deleted file mode 100644
index bfcd3e93620..00000000000
--- a/app/views/course/room_requests/_request_form_footer.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<footer data-dialog-button>
-    <? if ($room_search_button) : ?>
-        <?= \Studip\Button::create(
-            _('Räume suchen'),
-            'search_rooms',
-            [
-                'title' => _('Startet die Suche von Räumen anhand der gewählten Eigenschaften.')
-            ]
-        ) ?>
-    <? endif ?>
-    <? if ($room_select_button) : ?>
-        <?= \Studip\Button::create(_('Raum auswählen'), 'select_room') ?>
-    <? endif ?>
-    <? if ($save_buttons) : ?>
-        <?= \Studip\Button::create(_('Speichern'), 'save_and_close') ?>
-    <? endif ?>
-    <? if ($select_properties_button) : ?>
-        <?= \Studip\Button::create(_('Eigenschaften wählen'), 'select_properties') ?>
-    <? endif ?>
-    <?= \Studip\LinkButton::createCancel(
-        _('Abbrechen'),
-        $controller->link_for('course/room_requests/index/' . $course_id),
-        [
-            'title' => _('Abbrechen')
-        ]
-    ) ?>
-</footer>
-</form>
diff --git a/app/views/course/room_requests/_request_form_header.php b/app/views/course/room_requests/_request_form_header.php
deleted file mode 100644
index cdfe7bca72a..00000000000
--- a/app/views/course/room_requests/_request_form_header.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<form method="post" name="room_request" class="default"
-      action="<?= $action ?>" <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
-    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
-    <?= CSRFProtection::tokenTag() ?>
diff --git a/app/views/course/room_requests/_room_with_properties.php b/app/views/course/room_requests/_room_with_properties.php
new file mode 100644
index 00000000000..13ec336f68e
--- /dev/null
+++ b/app/views/course/room_requests/_room_with_properties.php
@@ -0,0 +1,10 @@
+<? if ($selected_room): ?>
+    <label>
+        <?= _('Ausgewählter Raum') ?>
+        <input type="hidden" name="selected_room_id"
+               value="<?= htmlReady($selected_room->id) ?>">
+        <br>
+
+        <strong><?= htmlReady($selected_room->name) ?></strong>
+    </label>
+<? endif ?>
diff --git a/app/views/course/room_requests/index.php b/app/views/course/room_requests/index.php
index 3f13b05a7dc..0f746b8bd51 100644
--- a/app/views/course/room_requests/index.php
+++ b/app/views/course/room_requests/index.php
@@ -14,12 +14,12 @@ echo $flash['message'];
             <col style="width: 50px">
         </colgroup>
         <thead>
-        <tr>
-            <th><?= _('Art der Anfrage') ?></th>
-            <th><?= _('Anfragender') ?></th>
-            <th><?= _('Bearbeitungsstatus') ?></th>
-            <th></th>
-        </tr>
+            <tr>
+                <th><?= _('Art der Anfrage') ?></th>
+                <th><?= _('Anfragender') ?></th>
+                <th><?= _('Bearbeitungsstatus') ?></th>
+                <th></th>
+            </tr>
         </thead>
         <tbody>
         <? foreach ($room_requests as $rr): ?>
diff --git a/app/views/course/room_requests/new.php b/app/views/course/room_requests/new.php
deleted file mode 100644
index 18edbdcf5cc..00000000000
--- a/app/views/course/room_requests/new.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<form method="POST" class="default" name="new_room_request"
-      action="<?= $this->controller->link_for('course/room_requests/request_start') ?>"
-    <?= Request::isXhr() ? 'data-dialog="size=big"' : '' ?>>
-    <?= CSRFProtection::tokenTag() ?>
-
-    <fieldset>
-        <legend><?= _("Raumanfrage erstellen") ?></legend>
-        <? if (count($options)): ?>
-            <label>
-                <?= _("Art der Raumanfrage:") ?>
-                <select id="new_room_request_type" name="range_str">
-                    <? foreach ($options as $one) : ?>
-                        <option value="<?= $one['value'] ?>">
-                            <?= htmlReady($one['name']) ?>
-                        </option>
-                    <? endforeach ?>
-                </select>
-            </label>
-
-            <div class="text-center" data-dialog-button>
-            </div>
-        <? else : ?>
-            <?= MessageBox::info(
-                _("In dieser Veranstaltung können keine weiteren Raumanfragen gestellt werden.")
-            ) ?>
-        <? endif ?>
-    </fieldset>
-
-    <footer data-dialog-button>
-        <? if (count($options)): ?>
-            <?= Studip\Button::create(
-                _('Erstellen'),
-                'create_room_request'
-            ) ?>
-            <?= Studip\LinkButton::createCancel(
-                _('Abbrechen'),
-                $controller->link_for('course/room_requests/index/' . $course_id)
-            ) ?>
-        <? else: ?>
-            <?= Studip\LinkButton::create(
-                _('Zurück zur Übersicht'),
-                $controller->link_for('course/room_requests/index/' . $course_id),
-                ['data-dialog' => 'size=big']
-            ) ?>
-        <? endif ?>
-    </footer>
-</form>
diff --git a/app/views/course/room_requests/request_start.php b/app/views/course/room_requests/new_request.php
similarity index 54%
rename from app/views/course/room_requests/request_start.php
rename to app/views/course/room_requests/new_request.php
index 763ef5ae95b..948db054208 100644
--- a/app/views/course/room_requests/request_start.php
+++ b/app/views/course/room_requests/new_request.php
@@ -1,45 +1,17 @@
-<? if (!$embedded) : ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_form_header',
-        [
-            'action'     => $this->controller->link_for('course/room_requests/request_start/' . $request_id),
-            'request_id' => $request_id
-        ]
-    ) ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_edit_header',
-        ['request' => $request]
-    ) ?>
-<? endif ?>
-<section class="resources-grid">
-    <div>
-        <fieldset>
-            <legend><?= _('Raum suchen') ?></legend>
-            <label>
-                <?= _('Raumname') ?>
-                <span class="flex-row">
-                    <input type="text" name="room_name" value="<?= htmlReady($room_name) ?>">
-                    <?= Icon::create('search', Icon::ROLE_CLICKABLE)->asInput(
-                        [
-                            'name'  => 'search_by_name',
-                            'class' => 'text-bottom',
-                            'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
-                        ]
-                    ) ?>
-                    <? if ($room_name) : ?>
-                    <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['title' => _('alle Angaben zurücksetzen')])->asInput(
-                        [
-                            'type'  => 'image',
-                            'class' => 'text-bottom',
-                            'name'  => 'reset_category',
-                            'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
-                        ]
-                    ) ?>
-                    <? endif?>
-                </span>
-            </label>
+<form method="post" name="room_request" class="default"
+      action="<?= $controller->link_for('course/room_requests/request_first_step/' . $request_id) ?>"
+    <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+    <?= CSRFProtection::tokenTag() ?>
+
+    <?= $this->render_partial('course/room_requests/_new_request_header') ?>
+
+    <section class="resources-grid">
+        <div>
+            <fieldset>
+                <legend><?= _('Suche nach Raumkategorie und Eigenschaften') ?></legend>
+
             <? if ($available_room_categories): ?>
-                <strong><p><?= _('Wünschbare Eigenschaften') ?></p></strong>
                 <label>
                     <?= _('Raumkategorie') ?>
                     <span class="flex-row">
@@ -47,16 +19,17 @@
                         <option value=""><?= _('bitte auswählen') ?></option>
                         <? foreach ($available_room_categories as $rc): ?>
                             <option value="<?= htmlReady($rc->id) ?>"
-                                    <?= ($category_id == $rc->id)
-                                        ? 'selected="selected"'
+                                    <?= $_SESSION[$request_id]['room_category'] === $rc->id
+                                        ? 'selected'
                                         : '' ?>>
                         <?= htmlReady($rc->name) ?>
                         </option>
                         <? endforeach ?>
                     </select>
                     <? if ($category) : ?>
-                        <?= Icon::create('refresh', Icon::ROLE_CLICKABLE, ['title' => _('alle Angaben zurücksetzen')])->asInput(
+                        <?= Icon::create('decline')->asInput(
                             [
+                                'title' => _('alle Angaben zurücksetzen'),
                                 'type'  => 'image',
                                 'class' => 'text-bottom',
                                 'name'  => 'reset_category',
@@ -64,11 +37,12 @@
                             ]
                         ) ?>
                     <? else : ?>
-                        <?= Icon::create('accept', Icon::ROLE_CLICKABLE, ['title' => _('Raumtyp auswählen')])->asInput(
+                        <?= Icon::create('accept')->asInput(
                             [
+                                'title' => _('Raumtyp auswählen'),
                                 'type'  => 'image',
                                 'class' => 'text-bottom',
-                                'name'  => 'select_properties',
+                                'name'  => 'search_by_category',
                                 'value' => _('Raumtyp auswählen'),
                                 'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
                             ]
@@ -80,6 +54,39 @@
             <? if (!$embedded) : ?>
         </fieldset>
     </div>
+
+    <div>
+        <fieldset>
+            <legend><?= _('Raumsuche') ?></legend>
+            <label>
+                <?= _('Raumname') ?>
+                <span class="flex-row">
+                    <input type="text" name="room_name" value="<?= htmlReady($_SESSION[$request_id]['room_name']) ?>">
+                    <?= Icon::create('search')->asInput(
+                        [
+                            'title' => _('Räume suchen'),
+                            'name'  => 'search_by_name',
+                            'class' => 'text-bottom',
+                            'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                        ]
+                    ) ?>
+                    <? if ($room_name) : ?>
+                        <?= Icon::create('decline')->asInput(
+                            [
+                                'title' => _('alle Angaben zurücksetzen'),
+                                'type'  => 'image',
+                                'class' => 'text-bottom',
+                                'name'  => 'reset_name',
+                                'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                            ]
+                        ) ?>
+                    <? endif?>
+                </span>
+            </label>
+
+        </fieldset>
+
+    </div>
 </section>
-<?= $this->render_partial('course/room_requests/_request_form_footer') ?>
+<?= $this->render_partial('course/room_requests/_new_request_form_footer', ['step' => $step]) ?>
 <? endif ?>
diff --git a/app/views/course/room_requests/request_find_available_properties.php b/app/views/course/room_requests/request_find_available_properties.php
new file mode 100644
index 00000000000..ea0767f2e6d
--- /dev/null
+++ b/app/views/course/room_requests/request_find_available_properties.php
@@ -0,0 +1,124 @@
+<form method="post" name="room_request" class="default"
+      action="<?= $controller->link_for('course/room_requests/request_check_properties/' . $request_id . '/' . $this->step) ?>"
+    <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+    <?= CSRFProtection::tokenTag() ?>
+
+    <?= $this->render_partial('course/room_requests/_new_request_header') ?>
+
+    <section class="resources-grid">
+        <div>
+            <fieldset class="request-fieldset">
+                <legend><?= _('Wünschbare Eigenschaften') ?></legend>
+
+                <? if ($step === 1 || $step === 2) : ?>
+                    <?= $this->render_partial('course/room_requests/_room_with_properties') ?>
+                <? endif ?>
+
+                <? if ($available_room_categories): ?>
+                    <label>
+                        <?= _('Raumkategorie') ?>
+                        <span class="flex-row">
+                            <select name="category_id" >
+                            <option value="0"><?= _('bitte auswählen') ?></option>
+                            <? foreach ($available_room_categories as $rc): ?>
+                                <option value="<?= htmlReady($rc->id) ?>"
+                                        <?= $room_category_id === $rc->id
+                                            ? 'selected'
+                                            : '' ?>>
+                                <?= htmlReady($rc->name) ?>
+                                </option>
+                            <? endforeach ?>
+                            </select>
+                            <?= Icon::create('accept')->asInput(
+                                [
+                                    'title' => _('Raumtyp auswählen'),
+                                    'type'  => 'image',
+                                    'class' => 'text-bottom',
+                                    'name'  => 'search_by_category',
+                                    'value' => _('Raumtyp auswählen'),
+                                    'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                                ]
+                            ) ?>
+                            <? if ($category) : ?>
+                            <?= Icon::create('decline')->asInput(
+                                [
+                                    'title' => _('alle Angaben zurücksetzen'),
+                                    'type'  => 'image',
+                                    'class' => 'text-bottom',
+                                    'name'  => 'reset_category',
+                                    'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                                ]
+                            ) ?>
+                            <? endif ?>
+                        </span>
+                    </label>
+                <? endif ?>
+
+                <!-- ROOM CATEGORY PROPERTIES -->
+                <? if ($available_properties) : ?>
+                    <? foreach ($available_properties as $property) : ?>
+                        <?= $property->toHtmlInput(
+                            $selected_properties[$property->name],
+                            'selected_properties[' . htmlReady($property->name) . ']',
+                            true,
+                            false
+                        ) ?>
+                    <? endforeach ?>
+
+                <div>
+                    <?= \Studip\Button::create(_('Räume suchen'), 'search_rooms') ?>
+                </div>
+                <? endif ?>
+
+            </fieldset>
+        </div>
+
+        <div>
+            <fieldset class="request-fieldset">
+                <legend><?= _('Raumsuche') ?></legend>
+                <label>
+                    <?= _('Raumname') ?>
+                    <span class="flex-row">
+                    <input type="text" name="room_name" value="<?= htmlReady($room_name) ?>" >
+                    <?= Icon::create('search')->asInput(
+                        [
+                            'title' => _('Räume suchen'),
+                            'name'  => 'search_by_name',
+                            'class' => 'text-bottom',
+                            'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                        ]
+                    ) ?>
+                </span>
+                </label>
+                    <? if ($available_rooms) : ?>
+                        <label><strong><?= _('Passende Räume') ?></strong>
+                            <section class="selectbox" id="room_select">
+                                <? foreach ($available_rooms as $room): ?>
+                                    <div class="flex-row">
+                                        <label class="horizontal">
+                                            <?= $available_room_icons[$room->id] ?>
+                                            <input type="radio" name="selected_room_id"
+                                                   data-activates="button[type='submit'][name='select_room']"
+                                                   value="<?= htmlReady($room->id) ?>"
+                                                <? if ($_SESSION[$request_id]['room_id'] === $room->id) echo 'checked' ?>>
+                                            <?= htmlReady(mila($room->name, 50)) . ' (' . $room['category']->name . ')'?>
+                                            <? if ($room->properties): ?>
+                                                <? $property_names = $room->getInfolabelProperties()
+                                                    ->pluck('fullname') ?>
+                                                <?= tooltipIcon(implode("\n", $property_names)) ?>
+                                            <? endif ?>
+                                        </label>
+                                    </div>
+                                <? endforeach ?>
+                            </section>
+                        </label>
+                        <?= \Studip\Button::create(_('Raum auswählen'), 'select_room') ?>
+                    <? else : ?>
+                    <? endif ?>
+            </fieldset>
+
+        </div>
+    </section>
+
+<?= $this->render_partial('course/room_requests/_new_request_form_footer', ['step' => $step, 'search_by' => 'category']) ?>
diff --git a/app/views/course/room_requests/request_find_matching_rooms.php b/app/views/course/room_requests/request_find_matching_rooms.php
new file mode 100644
index 00000000000..a474ab2a77a
--- /dev/null
+++ b/app/views/course/room_requests/request_find_matching_rooms.php
@@ -0,0 +1,134 @@
+<form method="post" name="room_request" class="default"
+      action="<?= $controller->link_for('course/room_requests/request_find_matching_rooms/' . $request_id . '/' . $this->step) ?>"
+    <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+    <?= CSRFProtection::tokenTag() ?>
+
+    <?= $this->render_partial('course/room_requests/_new_request_header') ?>
+
+    <section class="resources-grid">
+        <div>
+            <fieldset class="request-fieldset">
+                <legend><?= _('Wünschbare Eigenschaften') ?></legend>
+
+                <? if ($step === 1 || $step === 2) : ?>
+                    <?= $this->render_partial('course/room_requests/_room_with_properties') ?>
+                <? endif ?>
+
+                <? if ($available_room_categories): ?>
+                    <label>
+                        <?= _('Raumkategorie') ?>
+                        <span class="flex-row">
+                        <select name="category_id" >
+                            <option value="0"><?= _('bitte auswählen') ?></option>
+                        <? foreach ($available_room_categories as $rc): ?>
+                            <option value="<?= htmlReady($rc->id) ?>"
+                                <?= $_SESSION[$request_id]['room_category_id'] === $rc->id
+                                        ? 'selected'
+                                        : '' ?>>
+                            <?= htmlReady($rc->name) ?>
+                            </option>
+                        <? endforeach ?>
+                    </select>
+                        <?= Icon::create('accept')->asInput(
+                            [
+                                'title' => _('Raumtyp auswählen'),
+                                'type'  => 'image',
+                                'class' => 'text-bottom',
+                                'name'  => 'select_properties',
+                                'value' => _('Raumtyp auswählen'),
+                                'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                            ]
+                        ) ?>
+
+                            <? if ($category) : ?>
+                            <?= Icon::create('decline')->asInput(
+                                [
+                                    'title' => _('alle Angaben zurücksetzen'),
+                                    'type'  => 'image',
+                                    'class' => 'text-bottom',
+                                    'name'  => 'reset_category',
+                                    'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                                ]
+                            ) ?>
+                        <? endif ?>
+                    </span>
+                    </label>
+                <? endif ?>
+
+                <? if ($step === 2) : ?>
+                    <!-- After choosing a category or room -->
+                    <? if ($available_properties) : ?>
+                        <? foreach ($available_properties as $property) : ?>
+                            <?= $property->toHtmlInput(
+                                $selected_properties[$property->name],
+                                'selected_properties[' . htmlReady($property->name) . ']',
+                                true,
+                                false,
+                                false
+                            ) ?>
+                        <? endforeach ?>
+                    <? endif ?>
+
+                    <?= \Studip\Button::create(_('Räume suchen'), 'search_rooms') ?>
+
+                <? endif ?>
+
+                <? if (!$embedded) : ?>
+            </fieldset>
+
+        </div>
+
+        <div>
+            <fieldset class="request-fieldset">
+                <legend><?= _('Raumsuche') ?></legend>
+                <label>
+                    <?= _('Raumname') ?>
+                    <span class="flex-row">
+                    <input type="text" name="room_name" value="<?= htmlReady($_SESSION[$request_id]['room_name']) ?>">
+                    <?= Icon::create('search')->asInput(
+                        [
+                            'title' => _('Räume suchen'),
+                            'name'  => 'search_by_name',
+                            'class' => 'text-bottom',
+                            'style' => 'margin-left: 0.2em; margin-top: 0.6em;'
+                        ]
+                    ) ?>
+                    </span>
+                </label>
+                <? if ($available_rooms) : ?>
+                    <label>
+                        <strong><?= _('Passende Räume') ?></strong>
+                        <section class="selectbox" id="room_selection">
+                                <? foreach ($available_rooms as $room): ?>
+                                    <div class="flex-row">
+                                        <label class="horizontal">
+                                            <?= $available_room_icons[$room->id] ?>
+                                            <input type="radio" name="selected_room_id"
+                                                   data-activates="button[type='submit'][name='select_room']"
+                                                   value="<?= htmlReady($room->id) ?>"
+                                                <? if ($_SESSION[$request_id]['room_id'] === $room->id) echo 'checked' ?>>
+                                            <?= htmlReady(mila($room->name, 60)) . ' (' . $room['category']->name . ')'?>
+                                            <? if ($room->properties): ?>
+                                                <? $property_names = $room->getInfolabelProperties()
+                                                    ->pluck('fullname') ?>
+                                                <?= tooltipIcon(implode("\n", $property_names)) ?>
+                                            <? endif ?>
+                                        </label>
+                                    </div>
+                                <? endforeach ?>
+                        </section>
+                    </label>
+                    <?= \Studip\Button::create(_('Raum auswählen'), 'select_room') ?>
+
+                <? else : ?>
+                    <?= MessageBox::info(_('Es wurden keine passenden Räume gefunden!')) ?>
+                <? endif ?>
+
+            </fieldset>
+
+        </div>
+    </section>
+
+    <?= $this->render_partial('course/room_requests/_new_request_form_footer', ['step' => $step, 'search_by' => 'roomname']) ?>
+<? endif ?>
diff --git a/app/views/course/room_requests/request_select_properties.php b/app/views/course/room_requests/request_select_properties.php
deleted file mode 100644
index de45b117bc0..00000000000
--- a/app/views/course/room_requests/request_select_properties.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<? if (empty($embedded)) : ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_form_header',
-        [
-            'action'     => $this->controller->link_for('course/room_requests/request_select_properties/' . $request_id),
-            'request_id' => $request_id
-        ]
-    ) ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_edit_header',
-        ['request' => $request]
-    ) ?>
-    <?= $this->render_partial(
-        'course/room_requests/request_start',
-        ['embedded' => true]
-    ) ?>
-<? endif ?>
-
-<? if ($available_properties) : ?>
-        <? foreach ($available_properties as $property) : ?>
-            <?= $property->toHtmlInput(
-                $selected_properties[$property->name] ?? '',
-                'selected_properties[' . htmlReady($property->name) . ']',
-                true,
-                false
-            ) ?>
-        <? endforeach ?>
-<? endif ?>
-
-<label>
-    <?= _('Rüstzeit (in Minuten)') ?>
-    <input type="number" name="preparation_time"
-           value="<?= htmlReady($preparation_time) ?>"
-           min="0" max="<?= htmlReady($max_preparation_time) ?>">
-</label>
-
-<label>
-    <input type="checkbox" name="reply_lecturers" value="1"
-        <?= $reply_lecturers
-            ? 'checked="checked"'
-            : ''
-        ?>>
-    <?= _('Benachrichtigung bei Ablehnung der Raumanfrage auch an alle Lehrenden der Veranstaltung senden') ?>
-</label>
-
-
-    <label>
-        <?= _('Nachricht an die Raumvergabe') ?>
-    <textarea name="comment" cols="58" rows="4"
-              placeholder="<?= _('Weitere Wünsche oder Bemerkungen zur angefragten Raumbelegung') ?>"><?= htmlReady($comment) ?></textarea>
-    </label>
-
-<? if (empty($embedded)) : ?>
-    </div>
-    </section>
-    <?= $this->render_partial(
-        'course/room_requests/_request_form_footer',
-        [
-            'room_search_button'       => true,
-            'save_buttons'             => true,
-            'room_select_button'       => false,
-            'select_properties_button' => false
-        ]
-    ) ?>
-<? endif ?>
diff --git a/app/views/course/room_requests/request_select_room.php b/app/views/course/room_requests/request_select_room.php
deleted file mode 100644
index 752ad9898d9..00000000000
--- a/app/views/course/room_requests/request_select_room.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<? if (empty($embedded)) : ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_form_header',
-        [
-            'action'     => $this->controller->link_for('course/room_requests/request_select_room/' . $request_id),
-            'request_id' => $request_id
-        ]
-    ) ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_edit_header',
-        ['request' => $request]
-    ) ?>
-    <?= $this->render_partial(
-        'course/room_requests/request_start',
-        ['embedded' => true]
-    ) ?>
-    <? if (($category instanceof ResourceCategory) && !$direct_room_requests_only): ?>
-        <?= $this->render_partial(
-            'course/room_requests/request_select_properties',
-            ['embedded' => true]
-        ) ?>
-    <? endif ?>
-<? endif ?>
-</div>
-
-<div>
-<? if ($available_rooms) : ?>
-    <section class="contentbox">
-        <header><h1><?= _('Passende Räume') ?></h1></header>
-        <section class="selectbox">
-            <fieldset>
-                <? foreach ($available_rooms as $room): ?>
-                    <div class="flex-row">
-                        <label class="horizontal">
-                            <?= $available_room_icons[$room->id] ?>
-                            <input type="radio" name="selected_room_id"
-                                   data-activates="button[type='submit'][name='select_room']"
-                                   value="<?= htmlReady($room->id) ?>">
-                            <?= htmlReady(mb_substr($room->name, 0, 50)); ?>
-                            <? if ($room->properties): ?>
-                                <? $property_names = $room->getInfolabelProperties()
-                                    ->pluck('fullname') ?>
-                                <?= tooltipIcon(implode("\n", $property_names)) ?>
-                            <? endif ?>
-                        </label>
-                    </div>
-                <? endforeach ?>
-            </fieldset>
-        </section>
-    </section>
-    <? else : ?>
-        <?= MessageBox::info(_('Es wurden keine passenden Räume gefunden!')) ?>
-    <? endif ?>
-    </div>
-</section>
-<? if (empty($embedded)) : ?>
-    <?= $this->render_partial(
-        'course/room_requests/_request_form_footer',
-        [
-            'room_search_button' => true,
-            'room_select_button' => true,
-            'save_buttons' => true,
-            'select_properties_button' => false
-        ]
-    ) ?>
-<? endif ?>
diff --git a/app/views/course/room_requests/request_show_summary.php b/app/views/course/room_requests/request_show_summary.php
new file mode 100644
index 00000000000..732e2a4cb93
--- /dev/null
+++ b/app/views/course/room_requests/request_show_summary.php
@@ -0,0 +1,88 @@
+<form method="post" name="room_request" class="default"
+      action="<?= $controller->link_for('course/room_requests/store_request/' . $request_id) ?>"
+    <?= Request::isXhr() ? 'data-dialog="size=big"' : ''?>>
+    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
+    <?= CSRFProtection::tokenTag() ?>
+
+
+    <?= $this->render_partial('course/room_requests/_new_request_header') ?>
+    <section class="resources-grid">
+        <div>
+        <fieldset>
+            <legend>
+                <?= _('Zusammenfassung') ?>
+            </legend>
+            <label>
+                <?= _('Ausgewählte Raumkategorie') ?>
+                <input type="hidden" name="selected_room_id"
+                       value="<?= htmlReady($selected_room->id) ?>">
+                <br>
+
+                <strong><?= htmlReady($selected_room_category->name) ?></strong>
+            </label>
+
+            <label>
+                <?= _('Ausgewählter Raum') ?>
+                <? if ($selected_room): ?>
+                    <input type="hidden" name="selected_room_id"
+                           value="<?= htmlReady($selected_room->id) ?>">
+                    <br>
+
+                    <strong><?= htmlReady($selected_room->name) ?></strong>
+                <? else : ?>
+                    <br>
+
+                    <strong><?= _('Es wurde kein spezifischer Raum gewählt.') ?></strong>
+                <? endif ?>
+            </label>
+
+            <? foreach ($available_properties as $property) : ?>
+                <? foreach ($selected_properties as $key => $value) : ?>
+                    <? if ($property->name === $key) :  ?>
+                        <?= $property->toHtmlInput(
+                            $selected_properties[$property->name],
+                            'selected_properties[' . htmlReady($property->name) . ']',
+                            true,
+                            false,
+                            true
+                        ) ?>
+                    <? endif ?>
+                <? endforeach ?>
+            <? endforeach ?>
+
+        </fieldset>
+        </div>
+        <div>
+            <fieldset>
+                <legend>
+                    <?= _('Sonstiges') ?>
+                </legend>
+                <label>
+                    <?= _('Rüstzeit (in Minuten)') ?>
+                    <input type="number" name="preparation_time"
+                           value="<?= htmlReady($preparation_time) ?>"
+                           min="0" max="<?= htmlReady($max_preparation_time) ?>">
+                </label>
+
+                <? if ($user_is_global_resource_admin) : ?>
+                    <label>
+                        <input type="checkbox" name="reply_lecturers" value="1"
+                            <?= $reply_lecturers
+                                ? 'checked'
+                                : ''
+                            ?>>
+                        <?= _('Benachrichtigung bei Ablehnung der Raumanfrage auch an alle Lehrenden der Veranstaltung senden') ?>
+                    </label>
+                <? endif ?>
+
+                <label>
+                    <?= _('Nachricht an die Raumvergabe') ?>
+                    <textarea name="comment" cols="58" rows="4"
+                              placeholder="<?= _('Weitere Wünsche oder Bemerkungen zur angefragten Raumbelegung') ?>"><?= htmlReady($comment) ?></textarea>
+                </label>
+
+            </fieldset>
+        </div>
+
+    </section>
+    <?= $this->render_partial('course/room_requests/_new_request_form_footer', ['step' => $step, 'search_by' => 'roomname']) ?>
diff --git a/app/views/course/room_requests/request_summary.php b/app/views/course/room_requests/request_summary.php
deleted file mode 100644
index 4108deb16cc..00000000000
--- a/app/views/course/room_requests/request_summary.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<form method="post" name="room_request" class="default"
-      action="<?= $this->controller->link_for('course/room_requests/request_summary/' . $request_id) ?>">
-    <input type="hidden" name="request_id" value="<?= htmlReady($request_id) ?>">
-    <?= $this->render_partial(
-        'course/room_requests/_request_edit_header',
-        ['request' => $request]
-    ) ?>
-    <?= CSRFProtection::tokenTag() ?>
-    <section class="resources-grid">
-        <div>
-            <fieldset>
-                <legend><?= _('Ausgewählter Raum') ?></legend>
-                <? if (!empty($selected_room)): ?>
-                    <input type="hidden" name="selected_room_id"
-                           value="<?= htmlReady($selected_room->id) ?>">
-                    <input type="hidden" name="confirmed_selected_room_id"
-                           value="<?= htmlReady($selected_room->id) ?>">
-                    <?= htmlReady($selected_room->name) ?>
-                    <? if ($selected_room->properties): ?>
-                        <? $property_names = $selected_room->properties
-                            ->findBy('info_label', 1)
-                            ->findBy('state', '', '!=')
-                            ->pluck('fullname') ?>
-                        <?= tooltipIcon(
-                            implode("\n", $property_names)
-                        ) ?>
-                    <? endif ?>
-                    <?= Studip\Button::create(
-                        _('Anderen Raum wählen'),
-                        'select_other_room'
-                    ) ?>
-                <? else: ?>
-                    <?= MessageBox::info(
-                        _('Es wurde kein konkreter Raum ausgewählt!')
-                    ) ?>
-                    <?= Studip\Button::create(
-                        _('Eigenschaften neu wählen'),
-                        'select_properties'
-                    ) ?>
-                <? endif ?>
-                <? if ($request->properties): ?>
-                    <? foreach ($request->properties as $property): ?>
-                        <? if (!in_array($property->name, ['seats'])): ?>
-                            <dt><?= htmlReady($property->display_name) ?></dt>
-                            <dd><?= htmlReady($property->__toString()) ?></dd>
-                        <? endif ?>
-                    <? endforeach ?>
-                <? endif ?>
-                <? if ($request->category): ?>
-                    <dt><?= _('Gewünschter Raumtyp') ?>:</dt>
-                    <dd><?= htmlReady($request->category->name) ?></dd>
-                <? endif ?>
-                <label>
-                    <?= _('Erwartete Anzahl an Teilnehmenden') ?>:
-                    <input type="number" name="seats"
-                           value="<?= htmlReady($seats) ?>"
-                           min="1">
-                </label>
-                <label>
-                    <?= _('Rüstzeit (in Minuten)') ?>
-                    <input type="number" name="preparation_time"
-                           value="<?= htmlReady($preparation_time) ?>"
-                           min="0" max="<?= htmlReady($max_preparation_time) ?>">
-                </label>
-                <label>
-                    <input type="checkbox" name="reply_lecturers" value="1"
-                            <?= $reply_lecturers
-                                ? 'checked="checked"'
-                                : ''
-                            ?>>
-                    <?= _('Benachrichtigung bei Ablehnung der Raumanfrage auch an alle Lehrenden der Veranstaltung senden') ?>
-                </label>
-            </fieldset>
-        </div>
-        <div>
-            <fieldset>
-                <legend><?= _('Nachricht an die Raumvergabe') ?></legend>
-                <textarea name="comment" cols="58" rows="4"
-                          placeholder="<?= _('Weitere Wünsche oder Bemerkungen zur angefragten Raumbelegung') ?>"><?= htmlReady($comment) ?></textarea>
-            </fieldset>
-        </div>
-    </section>
-    <footer data-dialog-button>
-        <?= \Studip\Button::create(
-            _('Speichern'),
-            'save'
-        ) ?>
-        <?= \Studip\Button::create(
-            _('Speichern und zurück zur Übersicht'),
-            'save_and_close'
-        ) ?>
-        <?= \Studip\LinkButton::createCancel(
-            _('Abbrechen'),
-            $controller->link_for('course/room_requests/index/' . $course_id),
-            [
-                'title' => _('Abbrechen')
-            ]
-        ) ?>
-    </footer>
-</form>
diff --git a/app/views/course/timesrooms/_cancel_form.php b/app/views/course/timesrooms/_cancel_form.php
index 8a2b7067424..eaadaf19d6b 100644
--- a/app/views/course/timesrooms/_cancel_form.php
+++ b/app/views/course/timesrooms/_cancel_form.php
@@ -17,3 +17,4 @@ if (isset($termin) && $termin instanceof CourseExDate) {
     <input type="checkbox" id="cancel_send_message" name="cancel_send_message" value="1">
     <?= _('Benachrichtigung über ausfallende Termine an alle Teilnehmenden verschicken') ?>
 </label>
+
diff --git a/app/views/course/timesrooms/_regularEvents.php b/app/views/course/timesrooms/_regularEvents.php
index f2b1829b396..baaa2d8852b 100644
--- a/app/views/course/timesrooms/_regularEvents.php
+++ b/app/views/course/timesrooms/_regularEvents.php
@@ -89,18 +89,19 @@
                         <? if (Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) : ?>
                             <? $actionMenu->addLink(
                                 $controller->url_for(
-                                    'course/room_requests/request_start/',
+                                    'course/room_requests/new_request/',
                                     [
-                                        'range' => 'cycle',
-                                        'range_id' => $metadate_id
+                                        'cid'       => $course->id,
+                                        'range_str' => 'cycle',
+                                        'range_id'  => $metadate_id
                                     ]
                                 ),
-                                _('Raumanfrage erstellen'),
+                                _('Neue Raumanfrage'),
                                 Icon::create(
                                     'room-request',
                                     Icon::ROLE_CLICKABLE,
                                     [
-                                        'title' => _('Raumanfrage erstellen'),
+                                        'title' => _('Neue Raumanfrage'),
                                         'style' => 'vertical-align: middle;'
                                     ]
                                 ),
diff --git a/app/views/course/timesrooms/_roomRequest.php b/app/views/course/timesrooms/_roomRequest.php
index 3eecb3c46b1..9f80e9625cf 100644
--- a/app/views/course/timesrooms/_roomRequest.php
+++ b/app/views/course/timesrooms/_roomRequest.php
@@ -1,12 +1,7 @@
-<?php
-$global_requests = $course->room_requests->filter(function (RoomRequest $request) {
-    return $request->closed < 2 && !$request->termin_id;
-});
-?>
-<section class="contentbox">
+<section class="contentbox" id="request">
     <header>
         <h1>
-            <?= _('Raumanfrage für die gesamte Veranstaltung') ?>
+            <?= _('Raumanfragen für die gesamte Veranstaltung') ?>
         </h1>
 
         <nav>
@@ -14,7 +9,7 @@ $global_requests = $course->room_requests->filter(function (RoomRequest $request
                 _('Hier können Sie für die gesamte Veranstaltung, also für alle regelmäßigen und unregelmäßigen Termine, '
                     . 'eine Raumanfrage erstellen.')
             ) ?>
-            <a class="link-add" href="<?= $controller->url_for('course/room_requests/request_start',
+            <a class="link-add" href="<?= $controller->link_for('course/room_requests/new_request',
                 [
                     'cid'                 => $course->id,
                     'range_str'           => 'course',
@@ -29,13 +24,102 @@ $global_requests = $course->room_requests->filter(function (RoomRequest $request
         </nav>
     </header>
 
+    <?= $flash['message'] ?>
+
+    <? if (count($room_requests)) : ?>
     <section>
-        <? if (count($global_requests) > 0): ?>
-            <p><?= _('Für diese Veranstaltung liegt eine offene Raumanfrage vor') ?></p>
-            <?= Studip\LinkButton::create(_('Raumanfragen anzeigen'),
-                URLHelper::getURL('dispatch.php/course/room_requests/index/' . $course->getId())) ?>
-        <? else: ?>
-            <p><?= _('Keine Raumanfrage vorhanden') ?></p>
-        <? endif ?>
+        <table class="default sortable-table">
+            <colgroup>
+                <col style="width: 40%">
+                <col style="width: 20%">
+                <col>
+                <col style="width: 50px">
+            </colgroup>
+            <thead>
+            <tr class="sortable">
+                <th data-sort="text"><?= _('Art der Anfrage') ?></th>
+                <th data-sort="text"><?= _('Anfragender') ?></th>
+                <th data-sort="text"><?= _('Bearbeitungsstatus') ?></th>
+                <th></th>
+            </tr>
+            </thead>
+            <tbody>
+            <? foreach ($room_requests as $rr): ?>
+                <tr>
+                    <td>
+                        <?= htmlReady($rr->getTypeString(), 1, 1) ?>
+                    </td>
+                    <td>
+                        <?= htmlReady($rr->user ? $rr->user->getFullName() : '') ?>
+                    </td>
+                    <td>
+                        <?= htmlReady($rr->getStatusText()) ?>
+                    </td>
+                    <td class="actions">
+                        <a class="load-in-new-row"
+                           href="<?= $controller->link_for('course/room_requests/info/' . $rr->id) ?>"
+                            aria-expanded="false">
+                            <?= Icon::create('info')->asImg(['title' => _('Weitere Informationen einblenden')]) ?>
+                        </a>
+                        <? $params = [] ?>
+                        <? $dialog = []; ?>
+                        <? if (Request::isXhr()) : ?>
+                            <? $params['asDialog'] = true; ?>
+                            <? $dialog['data-dialog'] = 'size=big' ?>
+                        <? endif ?>
+
+                        <? $actionMenu = ActionMenu::get()->setContext($rr->getTypeString()) ?>
+                        <? $actionMenu->addLink(
+                            $controller->url_for('course/room_requests/request_show_summary/' . $rr->id, ['clear_cache' => 1]),
+                            _('Diese Anfrage bearbeiten'),
+                            Icon::create('edit'),
+                            ['title' => _('Diese Anfrage bearbeiten'), 'data-dialog' => 'size=big']
+                        ) ?>
+
+                        <?php
+                        if ($rr->room && !$user_has_permissions) {
+                            $user_has_permissions = $rr->room->userHasPermission($current_user, 'admin');
+                        }
+                        ?>
+
+                        <? if ($user_has_permissions && !$rr->closed): ?>
+                            <? $actionMenu->addLink(
+                                URLHelper::getURL(
+                                    'dispatch.php/resources/room_request/resolve/' . $rr->id,
+                                    [
+                                        'reload-on-close' => 1,
+                                        'single-request'  => 1
+                                    ]
+                                ),
+                                _('Diese Anfrage selbst auflösen'),
+                                Icon::create('admin'),
+                                ['title' => _('Diese Anfrage selbst auflösen')],
+                                ['data-dialog' => '1']
+                            ) ?>
+                        <? endif ?>
+                        <? $actionMenu->addLink(
+                            $controller->url_for('course/room_requests/delete/' . $rr->id),
+                            _('Diese Anfrage löschen'),
+                            Icon::create('trash'),
+                            ['title' => _('Diese Anfrage löschen')]
+                        ) ?>
+                        <?= $actionMenu->render() ?>
+                    </td>
+                </tr>
+            <? endforeach ?>
+            <? if ($request_id === $rr->id) : ?>
+                <tr>
+                    <td colspan="4">
+                        <?= $this->render_partial('course/room_requests/_request.php', ['request' => $rr]); ?>
+                    </td>
+                </tr>
+            <? endif ?>
+            </tbody>
+        </table>
     </section>
+    <? else : ?>
+        <?= MessageBox::info(_('Zu dieser Veranstaltung sind noch keine Raumanfragen vorhanden.')) ?>
+    <? endif ?>
+
+
 </section>
diff --git a/app/views/course/timesrooms/_roomRequestInfo.php b/app/views/course/timesrooms/_roomRequestInfo.php
index 7bc36603d5f..6b3315bb543 100644
--- a/app/views/course/timesrooms/_roomRequestInfo.php
+++ b/app/views/course/timesrooms/_roomRequestInfo.php
@@ -8,7 +8,5 @@ $open_requests = $course->room_requests->filter(function (RoomRequest $request)
             'Für diese Veranstaltung liegt eine offene Raumanfrage vor.',
             'Für diese Veranstaltung liegen %u offene Raumanfragen vor',
             count($open_requests)
-        ), count($open_requests)) . '<br>'
-        . Studip\LinkButton::create(_('Raumanfragen anzeigen'),
-                URLHelper::getURL('dispatch.php/course/room_requests/index/' . $course->getId()))) ?> 
+        ), count($open_requests))) ?>
 <? endif; ?>
diff --git a/app/views/course/timesrooms/editDate.php b/app/views/course/timesrooms/editDate.php
index 3be5e7c709f..a8dea31c655 100644
--- a/app/views/course/timesrooms/editDate.php
+++ b/app/views/course/timesrooms/editDate.php
@@ -228,8 +228,8 @@
                         'course/room_requests/request_summary/' . $request_id
                     )
                     :  $controller->url_for(
-                        'course/room_requests/request_start/' . $request_id,
-                        array_merge($params, ['range_str' => 'date_' . $date->id,'origin' => 'course_timesrooms'])
+                        'course/room_requests/new_request/' . $request_id,
+                        array_merge($params, ['range_str' => 'date', 'range_id' => $date->id])
                     )
                 ),
                 ['data-dialog' => 'size=big']) ?>
diff --git a/app/views/course/timesrooms/index.php b/app/views/course/timesrooms/index.php
index 8636ebbd658..e82409d973d 100644
--- a/app/views/course/timesrooms/index.php
+++ b/app/views/course/timesrooms/index.php
@@ -22,13 +22,3 @@
     <?= $this->render_partial('course/timesrooms/_roomRequest.php') ?>
 <? endif ?>
 
-<? if (Request::isXhr() && !$locked && Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS): ?>
-    <div data-dialog-button>
-    <?= Studip\LinkButton::create(
-        _('Raumanfrage erstellen'),
-        $controller->url_for('course/room_requests/request_start',
-        ['cid' => $course->id, 'range_str' => 'course', 'origin' => 'admin_courses']),
-        ['data-dialog' => 'size=big']
-    ) ?>
-    </div>
-<? endif ?>
diff --git a/lib/models/resources/ResourcePropertyDefinition.class.php b/lib/models/resources/ResourcePropertyDefinition.class.php
index 37fa89b95d3..c3a84d69fa6 100644
--- a/lib/models/resources/ResourcePropertyDefinition.class.php
+++ b/lib/models/resources/ResourcePropertyDefinition.class.php
@@ -140,7 +140,8 @@ class ResourcePropertyDefinition extends SimpleORMap
         $value = '',
         $special_name = '',
         $with_label = false,
-        $allow_boolean_false = true
+        $allow_boolean_false = true,
+        $disabled = false
     )
     {
         $label_html_classes = '';
@@ -155,16 +156,18 @@ class ResourcePropertyDefinition extends SimpleORMap
             //whether a false state shall be selectable or not.
             if ($allow_boolean_false) {
                 $input_html = sprintf(
-                    '<input type="hidden" name="%1$s" value="0" %2$s>'
+                    '<input type="hidden" name="%1$s" value="0" %2$s %3$s>'
                   . '<input type="checkbox" name="%1$s" value="1" %2$s>',
                     htmlReady($input_name),
-                    $value ? 'checked="checked"' : ''
+                    $value ? 'checked' : '',
+                    $disabled ? 'disabled' : ''
                 );
             } else {
                 $input_html = sprintf(
-                    '<input type="checkbox" name="%1$s" value="1" %2$s>',
+                    '<input type="checkbox" name="%1$s" value="1" %2$s %3$s>',
                     htmlReady($input_name),
-                    $value ? 'checked="checked"' : ''
+                    $value ? 'checked' : '',
+                    $disabled ? 'disabled' : ''
                 );
             }
             if ($with_label) {
@@ -254,7 +257,7 @@ class ResourcePropertyDefinition extends SimpleORMap
             }
             if ($with_label) {
                 return sprintf(
-                    '<label %1$s>%5$s<input type="%2$s" name="%3$s" value="%4$s"></label>',
+                    '<label %1$s>%5$s<input type="%2$s" name="%3$s" value="%4$s" %5$s></label>',
                     (
                         $label_html_classes
                         ? 'class="' . htmlReady($label_html_classes) . '"'
@@ -263,14 +266,16 @@ class ResourcePropertyDefinition extends SimpleORMap
                     $input_type,
                     htmlReady($input_name),
                     $value,
-                    htmlReady($this->__toString())
+                    htmlReady($this->__toString()),
+                    $disabled ? 'disabled' : ''
                 );
             } else {
                 return sprintf(
-                    '<input type="%1$s" name="%2$s" value="%3$s">',
+                    '<input type="%1$s" name="%2$s" value="%3$s" %4$s>',
                     $input_type,
                     htmlReady($input_name),
-                    $value
+                    $value,
+                    $disabled ? 'disabled' : ''
                 );
             }
         }
diff --git a/lib/modules/CoreAdmin.class.php b/lib/modules/CoreAdmin.class.php
index b02cf932e86..ada2af02aa2 100644
--- a/lib/modules/CoreAdmin.class.php
+++ b/lib/modules/CoreAdmin.class.php
@@ -63,13 +63,6 @@ class CoreAdmin extends CorePlugin implements StudipModule
                 $item->setDescription(_('Regelmäßige Veranstaltungszeiten, Einzeltermine und Ortsangaben ändern.'));
                 $navigation->addSubNavigation('dates', $item);
 
-                if (Config::get()->RESOURCES_ENABLE && Config::get()->RESOURCES_ALLOW_ROOM_REQUESTS) {
-                    $item = new Navigation(_('Raumanfragen'), 'dispatch.php/course/room_requests/index/' . $course_id);
-                    $item->setImage(Icon::create('resources'));
-                    $item->setDescription(_('Raumanfragen zu Veranstaltungszeiten verwalten.'));
-                    $navigation->addSubNavigation('room_requests', $item);
-                }
-
                 $item = new Navigation(_('Zugangsberechtigungen'), 'dispatch.php/course/admission');
                 $item->setImage(Icon::create('lock-locked'));
                 $item->setDescription(_('Zugangsbeschränkungen, Anmeldeverfahren oder einen Passwortschutz für diese Veranstaltung einrichten.'));
diff --git a/resources/assets/javascripts/bootstrap/application.js b/resources/assets/javascripts/bootstrap/application.js
index 1f0561e0ce5..d673455f733 100644
--- a/resources/assets/javascripts/bootstrap/application.js
+++ b/resources/assets/javascripts/bootstrap/application.js
@@ -122,6 +122,7 @@ STUDIP.domReady(function () {
 
         if ($(this).closest('tr').next().hasClass('loaded-details')) {
             $(this).closest('tr').next().remove();
+            $('a.load-in-new-row').attr('aria-expanded', 'false');
             return false;
         }
         $(this).showAjaxNotification().data('busy', true);
@@ -140,6 +141,8 @@ STUDIP.domReady(function () {
 
             $(that).data('busy', false);
             $('body').trigger('ajaxLoaded');
+            $('a.load-in-new-row').attr('aria-expanded', 'true');
+
         });
 
         return false;
diff --git a/resources/assets/stylesheets/scss/forms.scss b/resources/assets/stylesheets/scss/forms.scss
index bdd34df0f0b..d1336153c09 100644
--- a/resources/assets/stylesheets/scss/forms.scss
+++ b/resources/assets/stylesheets/scss/forms.scss
@@ -199,8 +199,8 @@ form.default {
     }
 
     .selectbox {
-        padding:5px;
-        max-height:200px;
+        padding: 5px;
+        max-height: 200px;
         overflow:auto;
 
         > fieldset {
-- 
GitLab