-
{roomName}
+
{`${roomName} ${hidden ? "(hidden room)" : ""}`}
Members:{" "}
{members
diff --git a/app/client/components/rooms/RoomMembersCount.tsx b/app/client/components/rooms/card/RoomMembersCount.tsx
similarity index 100%
rename from app/client/components/rooms/RoomMembersCount.tsx
rename to app/client/components/rooms/card/RoomMembersCount.tsx
diff --git a/app/client/templates/AdminRoomsImport.tsx b/app/client/templates/AdminRoomsImport.tsx
new file mode 100644
index 00000000..e6bae0e7
--- /dev/null
+++ b/app/client/templates/AdminRoomsImport.tsx
@@ -0,0 +1,83 @@
+import { AdminCenteredFormContainer } from "@client/components/admin/layout/AdminCenteredFormContainer";
+import { AdminLayout } from "@client/components/admin/layout/AdminLayout";
+import { BasicFormField } from "@client/components/forms/BasicFormField";
+import { BasicFormWithCustomFields } from "@client/components/forms/BasicFormWithCustomFields";
+import { PageTitle } from "@client/components/PageTitle";
+import { templates, useForm } from "@reactivated";
+import React from "react";
+
+const exampleCsvFile = `Name,Description,Hidden,AvailableBedsSingle,AvailableBedsDouble,ActualBedsSingle,ActualBedsDouble
+189,Ladny pokoj na koncu korytarza,False,3,0,3,0
+213,Z balkonem,False,2,1,2,1
+217,Z jacuzzi,True,1,0,0,1
+304,Poddasze,False,4,1,5,1`;
+
+export const Template = (props: templates.AdminRoomsImport) => {
+ const form = useForm({ form: props.form });
+
+ return (
+
+ Import rooms
+
+
+
+
+
Please upload a CSV file which looks like the example below:
+
{exampleCsvFile}
+
+
+
+ Name |
+ Description |
+ Hidden |
+ AvailableBedsSingle |
+ AvailableBedsDouble |
+ ActualBedsSingle |
+ ActualBedsDouble |
+
+
+
+
+ 189 |
+ Ladny pokoj na koncu korytarz |
+ False |
+ 3 |
+ 0 |
+ 3 |
+ 0 |
+
+
+ 213 |
+ Z balkonem |
+ False |
+ 2 |
+ 1 |
+ 2 |
+ 1 |
+
+
+ 217 |
+ Z jacuzzi |
+ True |
+ 1 |
+ 0 |
+ 0 |
+ 1 |
+
+
+ 304 |
+ Poddasze |
+ False |
+ 4 |
+ 1 |
+ 5 |
+ 1 |
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/client/templates/AdminRoomsList.tsx b/app/client/templates/AdminRoomsList.tsx
new file mode 100644
index 00000000..8f0a359e
--- /dev/null
+++ b/app/client/templates/AdminRoomsList.tsx
@@ -0,0 +1,21 @@
+import { AdminCenteredContainer } from "@client/components/admin/layout/AdminCenteredContainer";
+import { AdminLayout } from "@client/components/admin/layout/AdminLayout";
+import { PageTitle } from "@client/components/PageTitle";
+import { Rooms } from "@client/components/rooms/Rooms";
+import { createRoomDataFromTemplateProps } from "@client/utils/roomData";
+import { templates } from "@reactivated";
+import React from "react";
+
+export const Template = (props: templates.AdminRoomsList) => {
+ return (
+
+ Rooms Admin
+
+
+
+
+ );
+};
diff --git a/app/client/templates/Rooms.tsx b/app/client/templates/Rooms.tsx
index e30ad5d6..6fa20e2f 100644
--- a/app/client/templates/Rooms.tsx
+++ b/app/client/templates/Rooms.tsx
@@ -1,35 +1,17 @@
import { CenteredContainer } from "@client/components/containers/CenteredContainer";
import { Layout } from "@client/components/Layout";
import { PageTitle } from "@client/components/PageTitle";
-import { RoomCards } from "@client/components/rooms/RoomCards";
-import { RoomsBar, RoomsSortBy } from "@client/components/rooms/RoomsBar";
+import { Rooms } from "@client/components/rooms/Rooms";
import { createRoomDataFromTemplateProps } from "@client/utils/roomData";
import { templates } from "@reactivated";
-import React, { useState } from "react";
+import React from "react";
export const Template = (props: templates.Rooms) => {
- const [searchText, setSearchText] = useState("");
- const [hideFullRooms, setHideFullRooms] = useState(false);
- const [sortRoomsBy, setSortRoomsBy] = useState("roomNumber");
-
return (
Rooms
-
-
+
);
diff --git a/app/client/templates/SignupRules.tsx b/app/client/templates/SignupRules.tsx
index f590117f..5e1a0fb6 100644
--- a/app/client/templates/SignupRules.tsx
+++ b/app/client/templates/SignupRules.tsx
@@ -6,28 +6,13 @@ import Markdown from "react-markdown";
const signupRulesMarkdown = `
## Instrukcja zapisów
-1. Stwórz konto za pomocą przycisku "Sign up". Jako Email podaj
+Stwórz konto za pomocą przycisku "Sign up". Jako Email podaj
adres w domenie **cs.uni.wroc.pl** lub dowolnej innej*.
Konta zakładane na naszej stronie w przeszłości zostały usunięte.
-2. By zarejestrować się na najbliższą edycję ZOSI na stronie głównej
-lub w swoim profilu w zakładce ZOSIA kliknij przycisk **REGISTER**.
-
-3. Uzupełnij kwestionariusz. W polu **Information** koniecznie wpisz
-swoje preferencje przy wyborze pokoju. Potrzebujemy wiedzieć czy
-wolisz pokój z łóżkiem podwójnym, a może pokój jednoosobowy, czy
-wolisz pokój w cichym zakątku hotelu, czy masz już wybraną osobę
-współlokatorską, wolisz wybrać ją później, czy może jest Ci to
-obojętne. Prosimy o uzupełnienie tego pola.
-
-4. Wyślij formularz i gotowe!
-
Jako osoba zaproszona posiadasz specjalny priorytet i możesz wybrać
-pokój przed resztą uczestników. Do 31 grudnia mamy najwięcej
-możliwości, by pomóc Ci w wyborze pokoju. Po podanej dacie dalej
-jesteśmy do Twojej dyspozji i zawsze służymy pomocą. Natomiast im
-bliżej do daty rozpoczęcia Konferencji, tym nasz zasób pokoi będzie
-coraz bardziej ograniczony.
+pokój przed resztą uczestników. Wcześniejsze zapisy startują
+na początku grudnia. O ich początku poinformujemy mailowo.
W razie jakichkolwiek pytań lub problemów, zachęcamy do kontaktu:
[ksi@cs.uni.wroc.pl](mailto:ksi@cs.uni.wroc.pl)
diff --git a/app/client/utils/roomData.ts b/app/client/utils/roomData.ts
index 3ccbda8b..b793501f 100644
--- a/app/client/utils/roomData.ts
+++ b/app/client/utils/roomData.ts
@@ -19,6 +19,24 @@ export interface RoomApiData {
} | null;
available_beds_single: number;
available_beds_double: number;
+ beds_single: number;
+ beds_double: number;
+ hidden: boolean;
+}
+
+/** Data used to create a new room */
+export interface RoomCreateApiData {
+ name: string;
+ description: string;
+ available_beds_single: number;
+ available_beds_double: number;
+ beds_single: number;
+ beds_double: number;
+ hidden: boolean;
+}
+
+export interface RoomEditApiData extends RoomCreateApiData {
+ id: number;
}
interface RoomApiUserData {
@@ -40,6 +58,9 @@ export interface RoomData {
};
availableBedsSingle: number;
availableBedsDouble: number;
+ bedsSingle: number;
+ bedsDouble: number;
+ hidden: boolean;
}
export interface RoomMember {
@@ -71,10 +92,15 @@ export const convertRoomApiDataToRoomData = (room: RoomApiData): RoomData => {
: undefined,
availableBedsSingle: room.available_beds_single,
availableBedsDouble: room.available_beds_double,
+ bedsSingle: room.beds_single,
+ bedsDouble: room.beds_double,
+ hidden: room.hidden,
};
};
-export const createRoomDataFromTemplateProps = (props: templates.Rooms) => {
+export const createRoomDataFromTemplateProps = (
+ props: templates.Rooms | templates.AdminRoomsList,
+): RoomData[] => {
return props.rooms.map((room) => ({
id: room.id,
name: room.name,
@@ -92,6 +118,7 @@ export const createRoomDataFromTemplateProps = (props: templates.Rooms) => {
lastName: room.lock.user.last_name,
},
password:
+ "user_room_lock" in props &&
props.user_room_lock?.id === room.lock.id
? props.user_room_lock.password
: undefined,
@@ -100,5 +127,8 @@ export const createRoomDataFromTemplateProps = (props: templates.Rooms) => {
: undefined,
availableBedsSingle: room.available_beds_single,
availableBedsDouble: room.available_beds_double,
+ bedsSingle: room.beds_single,
+ bedsDouble: room.beds_double,
+ hidden: room.hidden,
}));
};
diff --git a/app/client/utils/userData.ts b/app/client/utils/userData.ts
new file mode 100644
index 00000000..499caf46
--- /dev/null
+++ b/app/client/utils/userData.ts
@@ -0,0 +1,9 @@
+export interface UserApiData {
+ id: number;
+ email: string;
+ first_name: string;
+ last_name: string;
+ is_active: boolean;
+ is_staff: boolean;
+ date_joined: string;
+}
diff --git a/app/client/utils/zosiaApi.ts b/app/client/utils/zosiaApi.ts
index a5f58fee..d80dc5f4 100644
--- a/app/client/utils/zosiaApi.ts
+++ b/app/client/utils/zosiaApi.ts
@@ -15,7 +15,10 @@ export const zosiaApiRoutes = {
organizations: "api/v1/users/organizations/",
addLectureDurations: reverse("load_durations"),
+ users: "api/v1/users/",
+
rooms: "api/v2/rooms/",
+ room: (id: number) => `api/v2/rooms/${id}/`,
roomMember: (roomId: number) => `api/v2/rooms/${roomId}/member/`,
lockRoom: (roomId: number) => `api/v2/rooms/${roomId}/lock/`,
diff --git a/app/scripts/createsuperuser.sh b/app/scripts/createsuperuser.sh
index 6f527fa4..2401bdee 100755
--- a/app/scripts/createsuperuser.sh
+++ b/app/scripts/createsuperuser.sh
@@ -5,5 +5,7 @@ set -eu
# DJANGO_SUPERUSER_USERNAME
# DJANGO_SUPERUSER_EMAIL
# DJANGO_SUPERUSER_PASSWORD
+# DJANGO_SUPERUSER_FIRST_NAME
+# DJANGO_SUPERUSER_LAST_NAME
python manage.py createsuperuser --noinput
\ No newline at end of file
diff --git a/app/server/conferences/urls.py b/app/server/conferences/urls.py
index b5b12f72..da9518c4 100644
--- a/app/server/conferences/urls.py
+++ b/app/server/conferences/urls.py
@@ -32,5 +32,5 @@
path('place/add/', views.place_add, name='place_add'),
path('place//update/', views.place_add, name='place_update'),
path('statistics/', views.statistics, name='statistics'),
- path('signup_rules/', views.sign_up_rules_for_invited, name='invited'),
+ path('zapisy/', views.sign_up_rules_for_invited, name='invited'),
]
diff --git a/app/server/rooms/templates.py b/app/server/rooms/templates.py
index e70d923a..8e9e137c 100644
--- a/app/server/rooms/templates.py
+++ b/app/server/rooms/templates.py
@@ -1,29 +1,45 @@
from typing import List, Literal, NamedTuple
from reactivated import Pick, template
+from .forms import UploadFileForm
from .models import Room, RoomLock
+ROOM_DATA = List[
+ Pick[
+ Room,
+ Literal[
+ "id",
+ "name",
+ "description",
+ "available_beds_single",
+ "available_beds_double",
+ "beds_single",
+ "beds_double",
+ "hidden",
+ "members.id",
+ "members.first_name",
+ "members.last_name",
+ "lock.id",
+ "lock.user.id",
+ "lock.user.first_name",
+ "lock.user.last_name",
+ "lock.expiration_date",
+ ],
+ ]
+]
+
@template
class Rooms(NamedTuple):
- rooms: List[
- Pick[
- Room,
- Literal[
- "id",
- "name",
- "description",
- "available_beds_single",
- "available_beds_double",
- "members.id",
- "members.first_name",
- "members.last_name",
- "lock.id",
- "lock.user.id",
- "lock.user.first_name",
- "lock.user.last_name",
- "lock.expiration_date",
- ],
- ]
- ]
+ rooms: ROOM_DATA
user_room_lock: Pick[RoomLock, Literal["id", "password"]]
+
+
+@template
+class AdminRoomsList(NamedTuple):
+ rooms: ROOM_DATA
+
+
+@template
+class AdminRoomsImport(NamedTuple):
+ form: UploadFileForm
diff --git a/app/server/rooms/urls.py b/app/server/rooms/urls.py
index 6790762d..fcdba5a4 100644
--- a/app/server/rooms/urls.py
+++ b/app/server/rooms/urls.py
@@ -4,6 +4,7 @@
urlpatterns = [
path('', views.index, name='rooms_index'),
+ path('admin', views.admin_rooms_list, name='admin_rooms_list'),
path('list/room_by_user', views.list_csv_room_by_user, name='list_csv_room_by_user'),
path('list/room_by_member', views.list_csv_room_by_member, name='list_csv_room_by_member'),
path('list/members_by_room', views.list_csv_members_by_room,
diff --git a/app/server/rooms/views.py b/app/server/rooms/views.py
index bcf670a6..1a9c95e1 100644
--- a/app/server/rooms/views.py
+++ b/app/server/rooms/views.py
@@ -16,7 +16,7 @@
from server.conferences.models import Zosia
from .forms import UploadFileForm
from .models import Room
-from .templates import Rooms
+from .templates import AdminRoomsImport, AdminRoomsList, Rooms
from server.users.models import UserPreferences
from server.utils.views import csv_response, validation_format
@@ -61,7 +61,8 @@ def index(request):
messages.error(request, _('Room registration is over'))
return redirect(reverse('accounts_profile'))
- rooms = Room.objects.all_visible().prefetch_related('members').all()
+ rooms = Room.objects.all() if preferences.user.is_staff else Room.objects.all_visible()
+ rooms = rooms.prefetch_related('members').all()
rooms = sorted(rooms, key=lambda x: x.pk)
user_lock = request.user.locks.all().first()
@@ -122,6 +123,15 @@ def handle_uploaded_file(csvfile):
code="invalid")
+@staff_member_required
+@require_http_methods(['GET'])
+def admin_rooms_list(request):
+ rooms = Room.objects.all().prefetch_related('members').all()
+ rooms = sorted(rooms, key=lambda x: x.pk)
+
+ return AdminRoomsList(rooms=rooms).render(request)
+
+
@staff_member_required
@require_http_methods(['GET', 'POST'])
def import_room(request):
@@ -139,8 +149,8 @@ def import_room(request):
messages.error(request, _("There were errors when adding rooms"))
else:
messages.success(request, _("Rooms have been successfully added"))
- return HttpResponseRedirect(reverse('admin'))
+ return HttpResponseRedirect(reverse('admin_rooms_list'))
else:
form = UploadFileForm()
- return render(request, 'rooms/import.html', {'form': form})
+ return AdminRoomsImport(form=form).render(request)
diff --git a/app/static/imgs/TSG_vertical_logo.svg b/app/static/imgs/TSG_vertical_logo.svg
new file mode 100644
index 00000000..7cdbc2e6
--- /dev/null
+++ b/app/static/imgs/TSG_vertical_logo.svg
@@ -0,0 +1,36 @@
+
+
\ No newline at end of file