Skip to content

Commit

Permalink
CSCEXAM-1195 Change some dropdowns to typeaheads with reservation sea…
Browse files Browse the repository at this point in the history
…rchy
  • Loading branch information
Matti Lupari committed Nov 16, 2023
1 parent a88753d commit 2a3cf2b
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 180 deletions.
28 changes: 20 additions & 8 deletions app/controllers/ReservationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public class ReservationController extends BaseController {

@Authenticated
@Restrict({ @Group("ADMIN"), @Group("TEACHER") })
public Result getExams(Http.Request request) {
public Result getExams(Http.Request request, Optional<String> filter) {
User user = request.attrs().get(Attrs.AUTHENTICATED_USER);
PathProperties props = PathProperties.parse("(id, name)");
Query<Exam> q = DB.createQuery(Exam.class);
Expand All @@ -80,6 +80,9 @@ public Result getExams(Http.Request request) {
.where()
.isNull("parent") // only Exam prototypes
.eq("state", Exam.State.PUBLISHED);
if (filter.isPresent()) {
el = el.ilike("name", String.format("%%%s%%", filter.get()));
}
if (user.hasRole(Role.Name.TEACHER)) {
el =
el
Expand All @@ -91,7 +94,8 @@ public Result getExams(Http.Request request) {
.eq("shared", true)
.endJunction();
}
return ok(el.findList(), props);
List<Exam> exams = el.findList();
return ok(exams, props);
}

@Restrict({ @Group("ADMIN") })
Expand Down Expand Up @@ -119,15 +123,23 @@ private ArrayNode asJson(List<User> users) {
}

@Restrict({ @Group("ADMIN"), @Group("TEACHER") })
public Result getStudents() {
List<User> students = DB.find(User.class).where().eq("roles.name", "STUDENT").findList();
public Result getStudents(Optional<String> filter) {
ExpressionList<User> el = DB.find(User.class).where().eq("roles.name", "STUDENT");
if (filter.isPresent()) {
el = el.or().ilike("userIdentifier", String.format("%%%s%%", filter.get()));
el = applyUserFilter(null, el, filter.get()).endOr();
}
List<User> students = el.findList();
return ok(Json.toJson(asJson(students)));
}

@Restrict({ @Group("ADMIN") })
public Result getTeachers() {
List<User> teachers = DB.find(User.class).where().eq("roles.name", "TEACHER").findList();

public Result getTeachers(Optional<String> filter) {
ExpressionList<User> el = DB.find(User.class).where().eq("roles.name", "TEACHER");
if (filter.isPresent()) {
el = applyUserFilter(null, el.or(), filter.get()).endOr();
}
List<User> teachers = el.findList();
return ok(Json.toJson(asJson(teachers)));
}

Expand Down Expand Up @@ -155,7 +167,7 @@ public CompletionStage<Result> removeReservation(long id, Http.Request request)
}

Reservation reservation = enrolment.getReservation();
// Lets not send emails about historical reservations
// Let's not send emails about historical reservations
if (reservation.getEndAt().isAfter(DateTime.now())) {
User student = enrolment.getUser();
emailComposer.composeReservationCancellationNotification(student, reservation, msg, false, enrolment);
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/base/BaseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected <T> ExpressionList<T> applyUserFilter(String prefix, ExpressionList<T>
String fnField = prefix == null ? "firstName" : String.format("%s.firstName", prefix);
String lnField = prefix == null ? "lastName" : String.format("%s.lastName", prefix);
if (rawFilter.contains(" ")) {
// Possible that user provided us two names. Lets try out some combinations of first and last names
// Possible that user provided us two names. Let's try out some combinations of first and last names
String name1 = rawFilter.split(" ")[0];
String name2 = rawFilter.split(" ")[1];
result =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -71,10 +73,13 @@ Optional<URL> parseUrlWithSearchParam(String filter, boolean anonymous) {
if (filter == null) {
return Optional.empty();
}

String paramStr = String.format("?filter=%s&anonymous=%s", filter, anonymous);
String url = String.format("%s/api/exams/search%s", configReader.getIopHost(), paramStr);
return Optional.of(URI.create(url).toURL());
String paramStr = String.format(
"filter=%s&anonymous=%s",
URLEncoder.encode(filter, StandardCharsets.UTF_8),
anonymous
);
URI uri = URI.create(String.format("%s/api/exams/search?%s", configReader.getIopHost(), paramStr));
return Optional.of(uri.toURL());
} catch (MalformedURLException e) {
logger.error("Malformed URL", e);
return Optional.empty();
Expand Down
6 changes: 3 additions & 3 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,10 @@ GET /app/accessibility controlle

GET /app/draft/rooms controllers.RoomController.createExamRoomDraft

GET /app/reservations/students controllers.ReservationController.getStudents
GET /app/reservations/teachers controllers.ReservationController.getTeachers
GET /app/reservations/students controllers.ReservationController.getStudents(filter: java.util.Optional[String])
GET /app/reservations/teachers controllers.ReservationController.getTeachers(filter: java.util.Optional[String])
GET /app/reservations/examrooms controllers.ReservationController.getExamRooms
GET /app/reservations/exams controllers.ReservationController.getExams(request: Request)
GET /app/reservations/exams controllers.ReservationController.getExams(request: Request, filter: java.util.Optional[String])
GET /app/reservations controllers.ReservationController.getReservations(state: java.util.Optional[String], ownerId: java.util.Optional[java.lang.Long], studentId: java.util.Optional[java.lang.Long], roomId: java.util.Optional[java.lang.Long], machineId: java.util.Optional[java.lang.Long], examId: java.util.Optional[java.lang.Long], start: java.util.Optional[String], end: java.util.Optional[String], externalRef: java.util.Optional[String], request: Request)
GET /app/events controllers.ReservationController.getExaminationEvents(state: java.util.Optional[String], ownerId: java.util.Optional[java.lang.Long], studentId: java.util.Optional[java.lang.Long], examId: java.util.Optional[java.lang.Long], start: java.util.Optional[String], end: java.util.Optional[String], request: Request)
DELETE /app/reservations/:id controllers.ReservationController.removeReservation(id: Long, request: Request)
Expand Down
127 changes: 84 additions & 43 deletions ui/src/app/reservation/admin/admin-reservations.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,93 @@
</div>

<div class="reservation-border">
<div class="p-4 row">
<div class="ps-4 pe-4 pt-4 pb-2 row">
<div class="col-md-2">
<strong class="reservation-search-titles">{{ 'sitnet_student' | translate }}</strong>
<xm-dropdown-select
*ngIf="studentOptions"
[fullWidth]="true"
[options]="studentOptions"
(optionSelected)="studentChanged($event)"
placeholder="{{ 'sitnet_select' | translate }}"
>
</xm-dropdown-select>
<label for="student-search" class="reservation-search-titles form-label">{{
'sitnet_student' | translate
}}</label>
<div class="input-group">
<input
#studentInput
id="student-search"
type="text"
class="form-control"
[ngbTypeahead]="searchStudents$"
[resultFormatter]="nameFormatter"
[inputFormatter]="nameFormatter"
(selectItem)="studentSelected($event)"
[disabled]="student"
placeholder="{{ 'sitnet_select' | translate }}"
/>
<button class="btn btn-outline-secondary" type="reset" (click)="clearStudent()">
{{ 'sitnet_remove' | translate }}
</button>
</div>
</div>
<div class="col-md-3">
<strong class="reservation-search-titles">{{ 'sitnet_exam' | translate }}</strong>
<xm-dropdown-select
*ngIf="examOptions"
[fullWidth]="true"
[options]="examOptions"
(optionSelected)="examChanged($event)"
placeholder="{{ 'sitnet_select' | translate }}"
>
</xm-dropdown-select>
<label for="exam-search" class="reservation-search-titles form-label">{{
'sitnet_exam' | translate
}}</label>
<div class="input-group">
<input
#examInput
id="exam-search"
type="text"
class="form-control"
[ngbTypeahead]="searchExams$"
[resultFormatter]="nameFormatter"
[inputFormatter]="nameFormatter"
(selectItem)="examSelected($event)"
[disabled]="examId || externalRef"
placeholder="{{ 'sitnet_select' | translate }}"
/>
<button class="btn btn-outline-secondary" type="reset" (click)="clearExam()">
{{ 'sitnet_remove' | translate }}
</button>
</div>
</div>
<div class="col-md-2 pt-1 reservation-search-titles">
<strong class="reservation-search-titles">{{ 'sitnet_begin' | translate }}</strong>
<xm-date-picker (updated)="startDateChanged($event)"></xm-date-picker>
<label for="start-date-picker" class="reservation-search-titles form-label">{{
'sitnet_begin' | translate
}}</label>
<xm-date-picker id="start-date-picker" (updated)="startDateChanged($event)"></xm-date-picker>
</div>
<div class="col-md-2 pt-1 reservation-search-titles">
<strong class="reservation-search-titles">{{ 'sitnet_end' | translate }}</strong>
<xm-date-picker (updated)="endDateChanged($event)"></xm-date-picker>
<label for="end-date-picker" class="reservation-search-titles form-label">{{
'sitnet_end' | translate
}}</label>
<xm-date-picker id="end-date-picker" (updated)="endDateChanged($event)"></xm-date-picker>
</div>
</div>
<div class="p-4 row align-items-center">
<div class="row ps-4 pe-4 align-items-center">
<div class="col-md-2">
<strong class="reservation-search-titles">{{ 'sitnet_exam_owners' | translate }}</strong>
<xm-dropdown-select
*ngIf="teacherOptions"
[fullWidth]="true"
[options]="teacherOptions"
(optionSelected)="ownerChanged($event)"
placeholder="{{ 'sitnet_select' | translate }}"
>
</xm-dropdown-select>
<label for="owner-search" class="reservation-search-titles form-label">{{
'sitnet_exam_owners' | translate
}}</label>
<div class="input-group">
<input
#ownerInput
id="owner-search"
type="text"
class="form-control"
[ngbTypeahead]="searchOwners$"
[resultFormatter]="nameFormatter"
[inputFormatter]="nameFormatter"
(selectItem)="ownerSelected($event)"
[disabled]="owner"
placeholder="{{ 'sitnet_select' | translate }}"
/>
<button class="btn btn-outline-secondary" type="reset" (click)="clearOwner()">
{{ 'sitnet_remove' | translate }}
</button>
</div>
</div>
<div class="col-md-2">
<strong class="reservation-search-titles">{{ 'sitnet_room' | translate }}</strong>
<label for="room-search" class="reservation-search-titles form-label">{{
'sitnet_room' | translate
}}</label>
<xm-dropdown-select
id="room-search"
*ngIf="roomOptions"
[options]="roomOptions"
(optionSelected)="roomChanged($event)"
Expand All @@ -65,8 +105,11 @@
</xm-dropdown-select>
</div>
<div class="col-md-2">
<strong class="reservation-search-titles">{{ 'sitnet_exam_machine' | translate }}</strong>
<label for="machine-search" class="reservation-search-titles form-label">{{
'sitnet_exam_machine' | translate
}}</label>
<xm-dropdown-select
id="machine-search"
*ngIf="machineOptions"
[options]="machineOptions"
(optionSelected)="machineChanged($event)"
Expand All @@ -77,8 +120,11 @@
</xm-dropdown-select>
</div>
<div class="col-md-3">
<strong class="reservation-search-titles">{{ 'sitnet_exam_state' | translate }}</strong>
<label for="state-search" class="reservation-search-titles form-label">{{
'sitnet_exam_state' | translate
}}</label>
<xm-dropdown-select
id="state-search"
[options]="stateOptions"
[fullWidth]="true"
(optionSelected)="stateChanged($event)"
Expand All @@ -89,20 +135,15 @@
<div class="col-md-3">
<div class="checkbox">
<label>
<input
type="checkbox"
value=""
[(ngModel)]="externalReservationsOnly"
(change)="updateQuery()"
/>
<input type="checkbox" value="" [(ngModel)]="externalReservationsOnly" (change)="query()" />
<strong class="reservation-search-titles">
{{ 'sitnet_external_reservations_only' | translate }}
</strong>
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" value="" [(ngModel)]="byodExamsOnly" (change)="updateQuery()" />
<input type="checkbox" value="" [(ngModel)]="byodExamsOnly" (change)="query()" />
<strong class="reservation-search-titles">
{{ 'sitnet_byod_only' | translate }}
</strong>
Expand Down
Loading

0 comments on commit 2a3cf2b

Please sign in to comment.