Implemented calendar
Fixed bugs with reservations and rooms Created Dockerfile
This commit is contained in:
parent
ffa96152f0
commit
dd8057fdf4
7
Dockerfile
Normal file
7
Dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
FROM python:latest
|
||||
|
||||
COPY build/ .
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD python -m http.server 8000
|
@ -98,7 +98,7 @@ body {
|
||||
|
||||
<script src="Talkpal.js"></script>
|
||||
<script>
|
||||
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"ensureCrossOriginIsolationHeaders":true,"executable":"Talkpal","experimentalVK":true,"fileSizes":{"Talkpal.pck":6385104,"Talkpal.wasm":43016933},"focusCanvas":true,"gdextensionLibs":[],"serviceWorker":"Talkpal.service.worker.js"};
|
||||
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"ensureCrossOriginIsolationHeaders":true,"executable":"Talkpal","experimentalVK":true,"fileSizes":{"Talkpal.pck":6396960,"Talkpal.wasm":43016933},"focusCanvas":true,"gdextensionLibs":[],"serviceWorker":"Talkpal.service.worker.js"};
|
||||
const GODOT_THREADS_ENABLED = false;
|
||||
const engine = new Engine(GODOT_CONFIG);
|
||||
|
||||
|
Binary file not shown.
@ -4,7 +4,7 @@
|
||||
// Incrementing CACHE_VERSION will kick off the install event and force
|
||||
// previously cached resources to be updated from the network.
|
||||
/** @type {string} */
|
||||
const CACHE_VERSION = '1742239479|2606992692';
|
||||
const CACHE_VERSION = '1742472564|314520779';
|
||||
/** @type {string} */
|
||||
const CACHE_PREFIX = 'Talkpal-sw-cache-';
|
||||
const CACHE_NAME = CACHE_PREFIX + CACHE_VERSION;
|
||||
|
28
docker-compose.yaml
Normal file
28
docker-compose.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
version: '3.6'
|
||||
services:
|
||||
talkpal-backend:
|
||||
container_name: talkpal-backend
|
||||
ports:
|
||||
- 5004:5000
|
||||
image: talkpal-backend
|
||||
build: .
|
||||
network_mode: host
|
||||
volumes:
|
||||
- "./src:/app/src"
|
||||
talkpal-db:
|
||||
image: mongo:4.2.8
|
||||
container_name: mongo
|
||||
ports:
|
||||
- 5005:27017
|
||||
environment:
|
||||
- MONGO_INITDB_DATABASE=test
|
||||
- MONGO_INITDB_ROOT_USERNAME=admin
|
||||
- MONGO_INITDB_ROOT_PASSWORD=admin
|
||||
volumes:
|
||||
- ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
|
||||
- mongodb:/data/db
|
||||
- mongoconfig:/data/configdb
|
||||
|
||||
volumes:
|
||||
mongodb:
|
||||
mongoconfig:
|
@ -22,12 +22,17 @@ const ScheduleUpdateInterval := 1.0 # 5.0
|
||||
|
||||
var _date_update_timer := 0.0
|
||||
var _schedule_update_timer := 0.0
|
||||
var _blocked_after_loading := false
|
||||
var _block_reservation_creation := false
|
||||
|
||||
var _rooms : Array[RoomEntity] = []
|
||||
var _reservations_list : Array[ReservationEntity] = []
|
||||
|
||||
func _process(delta):
|
||||
_process_hour_size()
|
||||
_process_date(delta)
|
||||
_process_fonts()
|
||||
_process_schedule(delta)
|
||||
|
||||
func _process_hour_size():
|
||||
var hour_size = get_viewport_rect().size.y/15
|
||||
@ -38,11 +43,11 @@ func _process_hour_size():
|
||||
func _process_date(delta):
|
||||
_date_update_timer += delta
|
||||
if _date_update_timer >= DateUpdateInterval:
|
||||
_date.text = _main.get_date()
|
||||
update_date()
|
||||
_date_update_timer = 0.0
|
||||
|
||||
var date = Time.get_date_dict_from_system()
|
||||
_date.text = "%02d.%02d.%04d" % [date.day, date.month, date.year]
|
||||
func update_date():
|
||||
_date.text = _main.get_selected_date()
|
||||
|
||||
func _process_fonts():
|
||||
_process_font_size(_date, 35)
|
||||
@ -65,10 +70,14 @@ func _ready():
|
||||
_connect_signals()
|
||||
|
||||
_remove_time_slots()
|
||||
_remove_reservations()
|
||||
|
||||
_fill_with_slots()
|
||||
|
||||
await get_tree().create_timer(0.1, false).timeout
|
||||
_load_rooms()
|
||||
|
||||
update_date()
|
||||
|
||||
func _connect_signals():
|
||||
await _main.ready
|
||||
var event_handler = _main.get_event_handler()
|
||||
@ -77,6 +86,8 @@ func _connect_signals():
|
||||
_room.pressed.connect(_on_room_button_pressed)
|
||||
_rooms_menu.item_clicked.connect(_on_room_selected)
|
||||
|
||||
_date.pressed.connect(_on_date_button_pressed)
|
||||
|
||||
func _remove_time_slots():
|
||||
for time_slot in _timeline.get_children():
|
||||
time_slot.queue_free()
|
||||
@ -91,14 +102,42 @@ func _remove_reservations():
|
||||
for reservation in _reservations.get_children():
|
||||
reservation.queue_free()
|
||||
|
||||
func _load_rooms():
|
||||
var room_repo = _main.get_room_repo()
|
||||
if room_repo.get_selected_room():
|
||||
return
|
||||
|
||||
_rooms_menu.clear()
|
||||
|
||||
var rooms = await room_repo.list_rooms()
|
||||
for room in rooms:
|
||||
_rooms.append(room)
|
||||
_rooms_menu.add_item(room.title)
|
||||
|
||||
if len(rooms) < 0:
|
||||
print('Not enough rooms')
|
||||
|
||||
_rooms_menu.select(0)
|
||||
_on_room_selected(0, '')
|
||||
|
||||
func _update_schedule(reservations=null):
|
||||
if not _main.is_node_ready():
|
||||
await _main.ready
|
||||
|
||||
var repo = _main.get_reservation_repo()
|
||||
var reservation_repo = _main.get_reservation_repo()
|
||||
|
||||
if reservations == null:
|
||||
reservations = await repo.list_reservations({"date": _main.get_date()})
|
||||
var room = _main.get_selected_room()
|
||||
reservations = await reservation_repo.list_reservations({
|
||||
"date": _main.get_selected_date(),
|
||||
"room_id": room.id if room else ''
|
||||
})
|
||||
|
||||
if reservations_are_updated(reservations):
|
||||
return
|
||||
|
||||
_reservations_list = reservations
|
||||
_remove_reservations()
|
||||
|
||||
for reservation in reservations:
|
||||
var start_time_hours = reservation.start_time.hours
|
||||
@ -114,6 +153,25 @@ func _update_schedule(reservations=null):
|
||||
_compose_reservation(start_time, reservation_time, \
|
||||
reservation.title, reservation.color, reservation.id)
|
||||
|
||||
func reservations_are_updated(new_reservations: Array[ReservationEntity]) -> bool:
|
||||
if _reservations_list.size() == 0:
|
||||
return false
|
||||
|
||||
if _reservations_list.size() != new_reservations.size():
|
||||
return false
|
||||
|
||||
for i in range(_reservations_list.size()):
|
||||
var entity_a = _reservations_list[i]
|
||||
var entity_b = new_reservations[i]
|
||||
|
||||
if !(entity_a is ReservationEntity) || !(entity_b is ReservationEntity):
|
||||
return false
|
||||
|
||||
if !entity_a.is_identical(entity_b):
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func _compose_reservation(start_time, duration_time, title, color, id):
|
||||
if duration_time < MinimalMinutesToShowTitle:
|
||||
title = ""
|
||||
@ -131,7 +189,7 @@ func _compose_reservation(start_time, duration_time, title, color, id):
|
||||
reservation.set_font(reservation.Fonts.MEDIUM)
|
||||
|
||||
func _input(event):
|
||||
if not _main.get_current_page() == Main.Pages.Board:
|
||||
if _blocked_after_loading or not _main.get_current_page() == Main.Pages.Board:
|
||||
return
|
||||
|
||||
if event is InputEventScreenTouch or (event is InputEventMouseButton and event.pressed):
|
||||
@ -178,6 +236,11 @@ func _time_is_before_current_time(time):
|
||||
|
||||
return time_in_minutes < current_time_in_minutes
|
||||
|
||||
func _block_board_click_for(seconds: float):
|
||||
_blocked_after_loading = true
|
||||
await get_tree().create_timer(seconds, false).timeout
|
||||
_blocked_after_loading = false
|
||||
|
||||
func _on_room_button_pressed():
|
||||
if _rooms_menu.visible:
|
||||
_rooms_menu.hide()
|
||||
@ -186,17 +249,23 @@ func _on_room_button_pressed():
|
||||
_rooms_menu.show()
|
||||
|
||||
func _on_room_selected(idx, text):
|
||||
var room_repo = _main.get_room_repo()
|
||||
room_repo.set_selected_room(_rooms[idx])
|
||||
|
||||
_block_reservation_creation = true
|
||||
_room.text = text
|
||||
_room.text = _rooms[idx].title
|
||||
_rooms_menu.hide()
|
||||
|
||||
update()
|
||||
|
||||
func _on_date_button_pressed():
|
||||
print("emit change date signal")
|
||||
_main.load_page(Main.Pages.CalendarSetting)
|
||||
|
||||
func _on_reservations_updated(reservations):
|
||||
await get_tree().create_timer(0.1, false).timeout
|
||||
update()
|
||||
|
||||
func update():
|
||||
_block_board_click_for(0.25)
|
||||
_ready()
|
||||
_update_schedule()
|
||||
|
@ -3,12 +3,19 @@ extends VBoxContainer
|
||||
const WorkingDayStart = 8
|
||||
const WorkingDayEnd = 20
|
||||
|
||||
@onready var _main: Main = get_tree().get_current_scene()
|
||||
@onready var _bg := $Background
|
||||
|
||||
func _process(delta):
|
||||
_process_current_time()
|
||||
|
||||
func _process_current_time():
|
||||
if _main.is_current_date_selected():
|
||||
show()
|
||||
else:
|
||||
hide()
|
||||
return
|
||||
|
||||
var time = Time.get_time_dict_from_system()
|
||||
|
||||
if time.hour < WorkingDayStart or time.hour > WorkingDayEnd:
|
||||
|
@ -19,8 +19,14 @@ func _ready():
|
||||
func _connect_signals():
|
||||
_items.item_clicked.connect(_on_item_clicked)
|
||||
|
||||
func set_items(items: Array):
|
||||
pass
|
||||
func add_item(text: String):
|
||||
_items.add_item(text)
|
||||
|
||||
func clear():
|
||||
_items.clear()
|
||||
|
||||
func select(idx):
|
||||
_items.select(idx)
|
||||
|
||||
func _on_item_clicked(index, at_position, mouse_button_index):
|
||||
var text = _items.get_item_text(index)
|
||||
|
146
scenes/common/calendar/calendar_setting.gd
Normal file
146
scenes/common/calendar/calendar_setting.gd
Normal file
@ -0,0 +1,146 @@
|
||||
extends Control
|
||||
|
||||
signal date_selected(date: Calendar.DateObj)
|
||||
|
||||
@onready var _main: Main = get_tree().get_current_scene()
|
||||
@onready var _month_label: Label = $VBoxContainer/HBoxContainer/MonthLabel
|
||||
@onready var _days_grid: GridContainer = $VBoxContainer/DaysGrid
|
||||
@onready var _prev_month_button: Button = $VBoxContainer/HBoxContainer/PrevMonthButton
|
||||
@onready var _next_month_button: Button = $VBoxContainer/HBoxContainer/NextMonthButton
|
||||
@onready var _vertical_box: VBoxContainer = $VBoxContainer
|
||||
@onready var _horizontal_box: HBoxContainer = $VBoxContainer/HBoxContainer
|
||||
|
||||
var cal: Calendar = Calendar.new()
|
||||
var current_date: Calendar.DateObj = Calendar.DateObj.today()
|
||||
var selected_date_label: Label
|
||||
var weekdays_formatted: Array[String]
|
||||
var months_formatted: Array[String]
|
||||
|
||||
func _process(delta):
|
||||
_process_grid_size()
|
||||
_process_font_size(_month_label, 32)
|
||||
_process_font_size(_prev_month_button, 32)
|
||||
_process_font_size(_next_month_button, 32)
|
||||
|
||||
func _process_grid_size():
|
||||
for day_label in _days_grid.get_children():
|
||||
var font_size = day_label.label_settings.font_size
|
||||
var new_font_size = get_viewport_rect().size.y/32
|
||||
if font_size != new_font_size:
|
||||
day_label.label_settings.font_size = new_font_size
|
||||
|
||||
for selection in day_label.get_children():
|
||||
var selection_size = selection.size.x
|
||||
var new_selection_size = get_viewport_rect().size.y/32
|
||||
if selection_size != new_selection_size:
|
||||
selection.size.x = new_selection_size
|
||||
selection.size.y = new_selection_size
|
||||
|
||||
func _process_font_size(obj, k):
|
||||
var font_size = obj.get_theme_default_font_size()
|
||||
var new_font_size = get_viewport_rect().size.y/k
|
||||
if font_size != new_font_size:
|
||||
obj.add_theme_font_size_override("font_size", new_font_size)
|
||||
|
||||
func _ready() -> void:
|
||||
cal.set_calendar_locale("res://addons/calendar_library/demo/calendar_locale_RU.tres")
|
||||
cal.set_first_weekday(Time.WEEKDAY_MONDAY)
|
||||
cal.week_number_system = Calendar.WeekNumberSystem.WEEK_NUMBER_FOUR_DAY
|
||||
weekdays_formatted = cal.get_weekdays_formatted(Calendar.WeekdayFormat.WEEKDAY_FORMAT_SHORT)
|
||||
months_formatted = cal.get_months_formatted(Calendar.MonthFormat.MONTH_FORMAT_FULL)
|
||||
|
||||
_prev_month_button.pressed.connect(_on_prev_month_pressed)
|
||||
_next_month_button.pressed.connect(_on_next_month_pressed)
|
||||
|
||||
update_calendar()
|
||||
|
||||
func update_calendar() -> void:
|
||||
for child in _days_grid.get_children():
|
||||
child.queue_free()
|
||||
|
||||
_month_label.text = "%s %d" % [months_formatted[current_date.month - 1], current_date.year]
|
||||
|
||||
var month_calendar = cal.get_calendar_month(current_date.year, current_date.month, true)
|
||||
var today = Calendar.DateObj.today()
|
||||
|
||||
for weekday in weekdays_formatted:
|
||||
var label = CalendarLabel.new(weekday)
|
||||
_days_grid.add_child(label)
|
||||
|
||||
for week in month_calendar:
|
||||
for date_obj in week:
|
||||
var day_label = create_day_label(date_obj, today)
|
||||
_days_grid.add_child(day_label)
|
||||
|
||||
func create_day_label(date_obj: Calendar.DateObj, today: Calendar.DateObj) -> CalendarLabel:
|
||||
var label = CalendarLabel.new(str(date_obj.day), true)
|
||||
|
||||
if date_obj.month != current_date.month:
|
||||
label.label_settings.font_color = Color("#414853")
|
||||
else:
|
||||
if date_obj.is_equal(today):
|
||||
label.label_settings.font_color = Color("#70bafa")
|
||||
else:
|
||||
label.label_settings.font_color = Color("#cdced2")
|
||||
|
||||
if date_obj.is_equal(current_date):
|
||||
set_selected_state(label)
|
||||
selected_date_label = label
|
||||
|
||||
label.pressed.connect(_on_date_pressed.bind(date_obj, label))
|
||||
return label
|
||||
|
||||
func set_selected_state(label: Label) -> void:
|
||||
if selected_date_label and selected_date_label.get_child_count() > 0:
|
||||
selected_date_label.get_child(0).queue_free()
|
||||
|
||||
var selection = ColorRect.new()
|
||||
selection.size = Vector2(60, 60)
|
||||
selection.color = Color("#414853")
|
||||
selection.show_behind_parent = true
|
||||
label.add_child(selection)
|
||||
selected_date_label = label
|
||||
|
||||
func _on_date_pressed(date: Calendar.DateObj, label: Label) -> void:
|
||||
current_date = date
|
||||
set_selected_state(label)
|
||||
date_selected.emit(date)
|
||||
update_calendar()
|
||||
|
||||
_main.go_to_previous_page(true)
|
||||
|
||||
func _on_prev_month_pressed() -> void:
|
||||
current_date.add_months(-1)
|
||||
update_calendar()
|
||||
|
||||
func _on_next_month_pressed() -> void:
|
||||
current_date.add_months(1)
|
||||
update_calendar()
|
||||
|
||||
func update():
|
||||
pass
|
||||
|
||||
class CalendarLabel:
|
||||
extends Label
|
||||
signal pressed()
|
||||
|
||||
var clickable: bool = false
|
||||
|
||||
func _init(p_text: String, p_clickable: bool = false):
|
||||
text = p_text
|
||||
horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
mouse_filter = MOUSE_FILTER_PASS if p_text.is_empty() else MOUSE_FILTER_STOP
|
||||
|
||||
var settings = LabelSettings.new()
|
||||
settings.font_size = 46
|
||||
settings.font_color = Color.WHITE
|
||||
label_settings = settings
|
||||
|
||||
if p_clickable and not p_text.is_empty():
|
||||
clickable = true
|
||||
mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if clickable and event is InputEventMouseButton:
|
||||
if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
pressed.emit()
|
53
scenes/common/calendar/calendar_setting.tscn
Normal file
53
scenes/common/calendar/calendar_setting.tscn
Normal file
@ -0,0 +1,53 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bc4tcq608v5rx"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/common/calendar/calendar_setting.gd" id="1_k60tp"]
|
||||
[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="2_dde4w"]
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_k60tp")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -92.5
|
||||
offset_top = -38.0
|
||||
offset_right = 92.5
|
||||
offset_bottom = 38.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = ExtResource("2_dde4w")
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 10
|
||||
alignment = 1
|
||||
|
||||
[node name="PrevMonthButton" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = " < "
|
||||
|
||||
[node name="MonthLabel" type="Label" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="NextMonthButton" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = " > "
|
||||
|
||||
[node name="DaysGrid" type="GridContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_dde4w")
|
||||
theme_override_constants/h_separation = 15
|
||||
theme_override_constants/v_separation = 15
|
||||
columns = 7
|
@ -14,7 +14,7 @@ script = ExtResource("1_2wxyg")
|
||||
[node name="TimeEdit" type="LineEdit" parent="."]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "21:41 "
|
||||
text = "15:04 "
|
||||
placeholder_text = "hh:mm (a/p)m"
|
||||
script = ExtResource("2_7d4ae")
|
||||
current_time = true
|
||||
|
@ -15,9 +15,9 @@ enum State {
|
||||
@export var number_flash_time := 0.5
|
||||
|
||||
@onready var _main: Main = get_tree().get_current_scene()
|
||||
@onready var _hours_label = $VerticalBar/Time/Hours
|
||||
@onready var _minutes_label = $VerticalBar/Time/Minutes
|
||||
@onready var _time = $VerticalBar/Time
|
||||
@onready var _hours_label = $VerticalBar/Control/Time/Hours
|
||||
@onready var _minutes_label = $VerticalBar/Control/Time/Minutes
|
||||
@onready var _time = $VerticalBar/Control/Time
|
||||
@onready var _face = $VerticalBar/Circle/Face
|
||||
@onready var _arrow = $VerticalBar/Circle/Clock/Arrow
|
||||
@onready var _numbers = $VerticalBar/Circle/Clock/Numbers
|
||||
@ -28,6 +28,8 @@ var _minutes : int
|
||||
var _state := State.SettingHours
|
||||
var _time_after_last_flash := 0.0
|
||||
|
||||
var _blocked := false
|
||||
|
||||
signal time_is_set(hours: int, minutes: int)
|
||||
|
||||
func _ready():
|
||||
@ -85,7 +87,7 @@ func _clicked_on_time(pos: Vector2):
|
||||
(pos.y > time_position.y and pos.y < _time.size.y + time_position.y)
|
||||
|
||||
func _input(event):
|
||||
if not _main.get_current_page() == Main.Pages.TimeSetting:
|
||||
if _blocked or not _main.get_current_page() == Main.Pages.TimeSetting:
|
||||
return
|
||||
|
||||
if (event is InputEventScreenTouch and event.pressed) or \
|
||||
@ -171,5 +173,11 @@ func _start_minutes_setting():
|
||||
_fill_with_minutes()
|
||||
_update_time()
|
||||
|
||||
func _block_click_for(seconds: float):
|
||||
_blocked = true
|
||||
await get_tree().create_timer(seconds, false).timeout
|
||||
_blocked = false
|
||||
|
||||
func update():
|
||||
_ready()
|
||||
_block_click_for(0.25)
|
||||
|
@ -39,20 +39,27 @@ offset_bottom = 20.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Time" type="HBoxContainer" parent="VerticalBar"]
|
||||
[node name="Control" type="Control" parent="VerticalBar"]
|
||||
custom_minimum_size = Vector2(0, 30)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Time" type="HBoxContainer" parent="VerticalBar/Control"]
|
||||
layout_mode = 2
|
||||
offset_top = 4.0
|
||||
offset_right = 1024.0
|
||||
offset_bottom = 141.0
|
||||
theme = ExtResource("2_84auh")
|
||||
alignment = 1
|
||||
|
||||
[node name="Hours" type="Label" parent="VerticalBar/Time"]
|
||||
[node name="Hours" type="Label" parent="VerticalBar/Control/Time"]
|
||||
layout_mode = 2
|
||||
text = "_"
|
||||
|
||||
[node name="_" type="Label" parent="VerticalBar/Time"]
|
||||
[node name="_" type="Label" parent="VerticalBar/Control/Time"]
|
||||
layout_mode = 2
|
||||
text = ":"
|
||||
|
||||
[node name="Minutes" type="Label" parent="VerticalBar/Time"]
|
||||
[node name="Minutes" type="Label" parent="VerticalBar/Control/Time"]
|
||||
layout_mode = 2
|
||||
text = "00"
|
||||
|
||||
|
@ -5,7 +5,8 @@ enum Pages {
|
||||
Board,
|
||||
ReservationCreation,
|
||||
ReservationEdit,
|
||||
TimeSetting
|
||||
TimeSetting,
|
||||
CalendarSetting
|
||||
}
|
||||
|
||||
func get_current_page():
|
||||
@ -26,5 +27,14 @@ func get_event_handler() -> EventHandler:
|
||||
func get_reservation_service() -> ReservationService:
|
||||
return ReservationService.new()
|
||||
|
||||
func get_date() -> String:
|
||||
func get_room_repo() -> AbstractRoomRepo:
|
||||
return AbstractRoomRepo.new()
|
||||
|
||||
func get_selected_date() -> String:
|
||||
return ""
|
||||
|
||||
func get_selected_room() -> RoomEntity:
|
||||
return RoomEntity.new()
|
||||
|
||||
func is_current_date_selected() -> bool:
|
||||
return true
|
||||
|
@ -17,6 +17,7 @@ enum Status {
|
||||
}
|
||||
|
||||
@onready var _reservation_repo : AbstractReservationRepo = $Repos/Reservation
|
||||
@onready var _room_repo : AbstractRoomRepo = $Repos/Room
|
||||
@onready var _event_handler : EventHandler = $Repos/EventHandler
|
||||
@onready var _reservation_service : ReservationService = $Services/ReservationService
|
||||
@onready var _keyboard = $Keyboard/OnscreenKeyboard
|
||||
@ -30,7 +31,8 @@ enum Status {
|
||||
Pages.Board: $Left/Pages/Board,
|
||||
Pages.ReservationCreation: $Left/Pages/ReservationCreation,
|
||||
Pages.ReservationEdit: $Left/Pages/ReservationEdit,
|
||||
Pages.TimeSetting: $Left/Pages/TimeSetting
|
||||
Pages.TimeSetting: $Left/Pages/TimeSetting,
|
||||
Pages.CalendarSetting: $Left/Pages/CalendarSetting
|
||||
}
|
||||
@onready var _time_status_indent := $Left/TimeStatusContainer/Indent
|
||||
@onready var _time_label := $Left/TimeStatusContainer/TimeLabel
|
||||
@ -46,9 +48,12 @@ enum Status {
|
||||
|
||||
var _current_page := Pages.Board
|
||||
var _previous_page : Pages
|
||||
|
||||
var _status : Status
|
||||
var _status_check_timer := 0.0
|
||||
|
||||
var _selected_date := _get_current_date()
|
||||
|
||||
func _ready():
|
||||
initialize_signals()
|
||||
|
||||
@ -60,6 +65,8 @@ func initialize_signals():
|
||||
_45_min_button.pressed.connect(_on_45_min_button_pressed)
|
||||
_1_hour_button.pressed.connect(_on_1_hour_button_pressed)
|
||||
|
||||
_pages[Pages.CalendarSetting].date_selected.connect(_on_date_selected)
|
||||
|
||||
func _process(delta):
|
||||
_process_time_status_indent()
|
||||
_process_status(delta)
|
||||
@ -101,7 +108,11 @@ func _update_status(reservations=null):
|
||||
var current_time_in_minutes = time.hour*60 + time.minute
|
||||
|
||||
if reservations == null:
|
||||
reservations = await _reservation_repo.list_reservations({"date": get_date()})
|
||||
var room = get_selected_room()
|
||||
reservations = await _reservation_repo.list_reservations({
|
||||
"date": _get_current_date(),
|
||||
"room_id": room.id if room else ''
|
||||
})
|
||||
|
||||
for reservation in reservations:
|
||||
var start_time_in_minutes = reservation.start_time.hours*60 + reservation.start_time.minutes
|
||||
@ -174,6 +185,9 @@ func go_to_previous_page(with_update=true):
|
||||
func get_reservation_repo() -> AbstractReservationRepo:
|
||||
return _reservation_repo
|
||||
|
||||
func get_room_repo() -> AbstractRoomRepo:
|
||||
return _room_repo
|
||||
|
||||
func get_event_handler() -> EventHandler:
|
||||
return _event_handler
|
||||
|
||||
@ -205,7 +219,7 @@ func _create_default_reservation(minutes_of_reservation):
|
||||
dto.start_time = {"hours": datetime.hour, "minutes": datetime.minute}
|
||||
dto.finish_time = {"hours": finish_time_hours, "minutes": finish_time_minutes}
|
||||
dto.creator = ""
|
||||
dto.room_id = "" # TODO: make it listbox
|
||||
dto.room_id = _room_repo.get_selected_room().id
|
||||
dto.description = ""
|
||||
dto.color = randi_range(1, 3)
|
||||
|
||||
@ -234,9 +248,23 @@ func _on_45_min_button_pressed():
|
||||
func _on_1_hour_button_pressed():
|
||||
_create_default_reservation(60)
|
||||
|
||||
func get_date() -> String:
|
||||
func get_selected_date() -> String:
|
||||
return _selected_date
|
||||
|
||||
func _get_current_date() -> String:
|
||||
var date = Time.get_date_dict_from_system()
|
||||
return "%02d.%02d.%04d" % [date.day, date.month, date.year]
|
||||
|
||||
func is_current_date_selected() -> bool:
|
||||
return get_selected_date() == _get_current_date()
|
||||
|
||||
func get_selected_room() -> RoomEntity:
|
||||
var room_repo = get_room_repo()
|
||||
return room_repo.get_selected_room()
|
||||
|
||||
func hide_keyboard():
|
||||
_keyboard.hide()
|
||||
|
||||
func _on_date_selected(date: Calendar.DateObj):
|
||||
_selected_date = "%02d.%02d.%04d" % [date.day, date.month, date.year]
|
||||
_pages[Pages.Board].update_date()
|
||||
|
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=16 format=3 uid="uid://bkrvh8vjpgqot"]
|
||||
[gd_scene load_steps=18 format=3 uid="uid://bkrvh8vjpgqot"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/main/main_tablet.gd" id="1_fr6s5"]
|
||||
[ext_resource type="PackedScene" uid="uid://c431r28ef5edp" path="res://scenes/board/board.tscn" id="2_n47h4"]
|
||||
@ -6,12 +6,14 @@
|
||||
[ext_resource type="PackedScene" uid="uid://cu6e3hfdorwcg" path="res://scenes/reservation/reservation_edit.tscn" id="4_hyj5n"]
|
||||
[ext_resource type="PackedScene" uid="uid://cxs8xe5w32jo4" path="res://scenes/common/time/time_setting.tscn" id="4_wyf5q"]
|
||||
[ext_resource type="Theme" uid="uid://byopik87nb8vv" path="res://assets/themes/status_font.tres" id="5_atujq"]
|
||||
[ext_resource type="PackedScene" uid="uid://bc4tcq608v5rx" path="res://scenes/common/calendar/calendar_setting.tscn" id="6_c0c0t"]
|
||||
[ext_resource type="Theme" uid="uid://yn1nbokvmv6n" path="res://assets/themes/small.tres" id="6_nde4h"]
|
||||
[ext_resource type="Theme" uid="uid://b8tbd62jtmgdx" path="res://assets/themes/instant_button_font.tres" id="8_bmn8p"]
|
||||
[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="9_wpf8g"]
|
||||
[ext_resource type="Script" path="res://src/infra/repos/backend/reservation_http.gd" id="10_v7sup"]
|
||||
[ext_resource type="Script" path="res://src/domain/services/reservation.gd" id="11_5xy2x"]
|
||||
[ext_resource type="Script" path="res://src/infra/repos/backend/event_handler_ws.gd" id="11_de30t"]
|
||||
[ext_resource type="Script" path="res://src/infra/repos/backend/room_http.gd" id="12_efd55"]
|
||||
[ext_resource type="Script" path="res://addons/onscreenkeyboard/onscreen_keyboard.gd" id="12_mc4hf"]
|
||||
[ext_resource type="PackedScene" uid="uid://dt03kci5qbkg3" path="res://scenes/common/dialog_box.tscn" id="14_cvh6c"]
|
||||
|
||||
@ -67,20 +69,25 @@ visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="CalendarSetting" parent="Left/Pages" instance=ExtResource("6_c0c0t")]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="TimeStatusContainer" type="VBoxContainer" parent="Left"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 10
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="Indent" type="BoxContainer" parent="Left/TimeStatusContainer"]
|
||||
custom_minimum_size = Vector2(0, 195)
|
||||
custom_minimum_size = Vector2(0, 0.666667)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="TimeLabel" type="Label" parent="Left/TimeStatusContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("5_atujq")
|
||||
text = "11:31"
|
||||
text = "12:42"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="Left/TimeStatusContainer"]
|
||||
@ -145,7 +152,7 @@ grow_vertical = 0
|
||||
[node name="CreateReservationButton" type="Button" parent="RightBottom"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("9_wpf8g")
|
||||
theme_override_font_sizes/font_size = 16
|
||||
theme_override_font_sizes/font_size = 0
|
||||
text = " Забронировать "
|
||||
|
||||
[node name="Repos" type="Node" parent="."]
|
||||
@ -156,6 +163,9 @@ script = ExtResource("10_v7sup")
|
||||
[node name="EventHandler" type="Node" parent="Repos"]
|
||||
script = ExtResource("11_de30t")
|
||||
|
||||
[node name="Room" type="Node" parent="Repos"]
|
||||
script = ExtResource("12_efd55")
|
||||
|
||||
[node name="Keyboard" type="Control" parent="."]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
@ -81,17 +81,25 @@ func _load_info():
|
||||
_start_time_field.set_value(reservation.start_time)
|
||||
_finish_time_field.set_value(reservation.finish_time)
|
||||
|
||||
func _load_room():
|
||||
_room_field.set_value(_main.get_selected_room().title)
|
||||
|
||||
func _get_current_room_id():
|
||||
var room_repo = _main.get_room_repo()
|
||||
var room = room_repo.get_selected_room()
|
||||
return room.id if room != null else null
|
||||
|
||||
func _create_reservation():
|
||||
if not await _fields_are_correct():
|
||||
return
|
||||
|
||||
var dto = CreateReservationDTO.new()
|
||||
dto.title = _title_field.get_value()
|
||||
dto.date = _main.get_date()
|
||||
dto.date = _main.get_selected_date()
|
||||
dto.start_time = _start_time_field.get_value()
|
||||
dto.finish_time = _finish_time_field.get_value()
|
||||
dto.creator = _creator_field.get_value()
|
||||
dto.room_id = _room_field.get_value() # TODO: make it listbox
|
||||
dto.room_id = _get_current_room_id()
|
||||
dto.description = _description_field.get_value()
|
||||
dto.color = randi_range(1, 3)
|
||||
|
||||
@ -100,7 +108,7 @@ func _create_reservation():
|
||||
|
||||
dto.queue_free()
|
||||
|
||||
_main.load_page(Main.Pages.Board)
|
||||
_main.load_page(Main.Pages.Board, true)
|
||||
clean()
|
||||
|
||||
func _update_reservation():
|
||||
@ -113,7 +121,7 @@ func _update_reservation():
|
||||
dto.start_time = _start_time_field.get_value()
|
||||
dto.finish_time = _finish_time_field.get_value()
|
||||
dto.creator = _creator_field.get_value()
|
||||
dto.room_id = _room_field.get_value() # TODO: make it listbox
|
||||
dto.room_id = _get_current_room_id()
|
||||
dto.description = _description_field.get_value()
|
||||
dto.color = randi_range(1, 3)
|
||||
|
||||
@ -124,7 +132,7 @@ func _update_reservation():
|
||||
|
||||
dto.queue_free()
|
||||
|
||||
_main.load_page(Main.Pages.Board)
|
||||
_main.load_page(Main.Pages.Board, true)
|
||||
clean()
|
||||
|
||||
func _delete_reservation():
|
||||
@ -132,7 +140,7 @@ func _delete_reservation():
|
||||
var reservation_id = repo.get_selected_reservation_id()
|
||||
repo.cancel_reservation(reservation_id)
|
||||
|
||||
_main.load_page(Main.Pages.Board)
|
||||
_main.load_page(Main.Pages.Board, true)
|
||||
clean()
|
||||
|
||||
func _fields_are_correct():
|
||||
@ -191,6 +199,8 @@ func update():
|
||||
if type == Types.Edit:
|
||||
_load_info()
|
||||
|
||||
_load_room()
|
||||
|
||||
func clean():
|
||||
_title_field.clean()
|
||||
_start_time_field.clean()
|
||||
|
@ -1,20 +1,6 @@
|
||||
extends Node
|
||||
class_name ReservationEntity
|
||||
class_name RoomEntity
|
||||
|
||||
var id: String
|
||||
|
||||
@export var title: String
|
||||
|
||||
@export var description: String
|
||||
|
||||
@export var room_id: String
|
||||
|
||||
@export var creator: String
|
||||
|
||||
@export var date: String
|
||||
|
||||
@export var start_time: Dictionary # TODO: get rid of dictionaries if can
|
||||
|
||||
@export var finish_time: Dictionary
|
||||
|
||||
@export var color: int
|
||||
|
40
src/domain/entities/room.gd
Normal file
40
src/domain/entities/room.gd
Normal file
@ -0,0 +1,40 @@
|
||||
extends Node
|
||||
class_name ReservationEntity
|
||||
|
||||
var id: String
|
||||
|
||||
@export var title: String
|
||||
|
||||
@export var description: String
|
||||
|
||||
@export var room_id: String
|
||||
|
||||
@export var creator: String
|
||||
|
||||
@export var date: String
|
||||
|
||||
@export var start_time: Dictionary # TODO: get rid of dictionaries if can
|
||||
|
||||
@export var finish_time: Dictionary
|
||||
|
||||
@export var color: int
|
||||
|
||||
func is_identical(other: ReservationEntity) -> bool:
|
||||
if !(other is ReservationEntity):
|
||||
return false
|
||||
|
||||
return (
|
||||
id == other.id &&
|
||||
title == other.title &&
|
||||
description == other.description &&
|
||||
room_id == other.room_id &&
|
||||
creator == other.creator &&
|
||||
date == other.date &&
|
||||
_compare_time(start_time, other.start_time) &&
|
||||
_compare_time(finish_time, other.finish_time) &&
|
||||
color == other.color
|
||||
)
|
||||
|
||||
static func _compare_time(a: Dictionary, b: Dictionary) -> bool:
|
||||
return a.get("hours", -1) == b.get("hours", -2) and \
|
||||
a.get("minutes", -1) == b.get("minutes", -2)
|
@ -4,9 +4,14 @@ class_name ReservationService
|
||||
@onready var _main: Main = get_tree().get_current_scene()
|
||||
|
||||
func is_time_busy(new_start_time_minutes, new_finish_time_minutes):
|
||||
var repo = _main.get_reservation_repo()
|
||||
var reservations = await repo.list_reservations({"date": _main.get_date()})
|
||||
var selected_reservation_id = repo.get_selected_reservation_id()
|
||||
var selected_room = _main.get_selected_room()
|
||||
|
||||
var reservation_repo = _main.get_reservation_repo()
|
||||
var reservations = await reservation_repo.list_reservations({
|
||||
"date": _main.get_selected_date(),
|
||||
"room_id": selected_room.id
|
||||
})
|
||||
var selected_reservation_id = reservation_repo.get_selected_reservation_id()
|
||||
|
||||
for reservation in reservations:
|
||||
if reservation.id == selected_reservation_id:
|
||||
|
@ -20,8 +20,8 @@ func change_reservation(reservation_id, dto: UpdateReservationDTO):
|
||||
func get_reservation(reservation_id):
|
||||
pass
|
||||
|
||||
func list_reservations(filters: Dictionary = {}):
|
||||
pass
|
||||
func list_reservations(filters: Dictionary = {}) -> Array[ReservationEntity]:
|
||||
return []
|
||||
|
||||
func set_selected_reservation_id(value):
|
||||
_selected_reservation_id = value
|
||||
|
@ -5,5 +5,13 @@ class_name AbstractRoomRepo
|
||||
signal connected
|
||||
signal not_connected
|
||||
|
||||
func list_rooms():
|
||||
pass
|
||||
var _selected_room = null
|
||||
|
||||
func list_rooms() -> Array[RoomEntity]:
|
||||
return []
|
||||
|
||||
func set_selected_room(value):
|
||||
_selected_room = value
|
||||
|
||||
func get_selected_room():
|
||||
return _selected_room
|
||||
|
@ -2,7 +2,7 @@
|
||||
extends AbstractReservationRepo
|
||||
class_name ReservationRepoHTTP
|
||||
|
||||
const BASE_URL = "http://192.168.0.147:5000"
|
||||
const BASE_URL = "http://192.168.1.178:5000"
|
||||
const RESERVATION_ENDPOINT = "/reservation/"
|
||||
const HEALTH_ENDPOINT = "/health/"
|
||||
|
||||
@ -10,6 +10,11 @@ signal request_failed(error_message: String)
|
||||
|
||||
var _jwt_token: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTc0MDA0MDQzNywianRpIjoiOTM4NTUyMjMtMjhiNC00OWVhLWI3ZjUtZmYxMTg4YzI1Mjg2IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6InRlc3RfdXNlciIsIm5iZiI6MTc0MDA0MDQzNywiY3NyZiI6ImMwYzI2MTU0LTdkNjItNGYyZi04ZjBhLWI0MjA0ODJlMmEzZCIsImV4cCI6MTc0MDA0MTMzN30.esPRTXNxrtziuOc2dUsc9XqbedErjcyvPlL3aUZIaaA"
|
||||
var _timed_out := false
|
||||
var _http_client := HTTPTalkpalClient.new(BASE_URL)
|
||||
|
||||
func _init():
|
||||
add_child(_http_client)
|
||||
_http_client.request_failed.connect(_on_request_failed)
|
||||
|
||||
func _ready():
|
||||
if await _backend_is_accessible():
|
||||
@ -18,7 +23,7 @@ func _ready():
|
||||
not_connected.emit()
|
||||
|
||||
func _backend_is_accessible():
|
||||
var result = await _make_request(HEALTH_ENDPOINT, HTTPClient.METHOD_GET)
|
||||
var result = await _http_client.request(HEALTH_ENDPOINT, HTTPClient.METHOD_GET)
|
||||
|
||||
if not result:
|
||||
push_error("Server initialization failed")
|
||||
@ -31,26 +36,26 @@ func _backend_is_accessible():
|
||||
|
||||
#region Public Methods
|
||||
func create_reservation(dto: CreateReservationDTO) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT, HTTPClient.METHOD_POST, _dto_to_json(dto))
|
||||
_http_client.request(RESERVATION_ENDPOINT, HTTPClient.METHOD_POST, _dto_to_json(dto))
|
||||
|
||||
func cancel_reservation(reservation_id: String) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_DELETE)
|
||||
_http_client.request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_DELETE)
|
||||
|
||||
func change_reservation(reservation_id: String, dto: UpdateReservationDTO) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_PUT, _dto_to_json(dto))
|
||||
_http_client.request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_PUT, _dto_to_json(dto))
|
||||
|
||||
func get_reservation(reservation_id: String) -> ReservationEntity:
|
||||
var result = await _make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_GET)
|
||||
var result = await _http_client.request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_GET)
|
||||
return _parse_reservation_entity(result) if result is Dictionary else null
|
||||
|
||||
func list_reservations(filters: Dictionary = {}) -> Array:
|
||||
func list_reservations(filters: Dictionary = {}) -> Array[ReservationEntity]:
|
||||
var query = "?"
|
||||
for key in filters:
|
||||
query += "%s=%s&" % [key, filters[key]]
|
||||
query = query.rstrip("&") if filters else ""
|
||||
|
||||
var endpoint = RESERVATION_ENDPOINT + query
|
||||
var result = await _make_request(endpoint, HTTPClient.METHOD_GET)
|
||||
var result = await _http_client.request(endpoint, HTTPClient.METHOD_GET)
|
||||
var reservations = _parse_reservation_list(result) if result is Array else []
|
||||
|
||||
_set_current_reservation_id_from_reservations(reservations)
|
||||
@ -207,3 +212,6 @@ func _compare_reservations_by_start_time(a: ReservationEntity, b: ReservationEnt
|
||||
var time_b = b.start_time.get("hours", 0) * 60 + b.start_time.get("minutes", 0)
|
||||
return time_a < time_b
|
||||
#endregion
|
||||
|
||||
func _on_request_failed(error_message: String):
|
||||
request_failed.emit(error_message)
|
||||
|
@ -1,209 +1,36 @@
|
||||
@tool
|
||||
extends AbstractRoomRepo
|
||||
class_name RoomRepoHTTP
|
||||
|
||||
const BASE_URL = "http://192.168.1.178:5000"
|
||||
const RESERVATION_ENDPOINT = "/reservation/"
|
||||
const HEALTH_ENDPOINT = "/health/"
|
||||
|
||||
signal rooms_loaded(rooms: Array[RoomEntity])
|
||||
signal request_failed(error_message: String)
|
||||
|
||||
var _jwt_token: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTc0MDA0MDQzNywianRpIjoiOTM4NTUyMjMtMjhiNC00OWVhLWI3ZjUtZmYxMTg4YzI1Mjg2IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6InRlc3RfdXNlciIsIm5iZiI6MTc0MDA0MDQzNywiY3NyZiI6ImMwYzI2MTU0LTdkNjItNGYyZi04ZjBhLWI0MjA0ODJlMmEzZCIsImV4cCI6MTc0MDA0MTMzN30.esPRTXNxrtziuOc2dUsc9XqbedErjcyvPlL3aUZIaaA"
|
||||
var _timed_out := false
|
||||
const ROOM_ENDPOINT = "/room/"
|
||||
|
||||
func _ready():
|
||||
if await _backend_is_accessible():
|
||||
connected.emit()
|
||||
var _http_client := HTTPTalkpalClient.new(BASE_URL)
|
||||
|
||||
func _init():
|
||||
add_child(_http_client)
|
||||
_http_client.request_failed.connect(_on_request_failed)
|
||||
|
||||
func list_rooms() -> Array[RoomEntity]:
|
||||
var result = await _http_client.request(ROOM_ENDPOINT, HTTPClient.METHOD_GET)
|
||||
if result is Array:
|
||||
var rooms = _parse_room_list(result)
|
||||
return rooms
|
||||
else:
|
||||
not_connected.emit()
|
||||
emit_signal("request_failed", "Failed to load rooms")
|
||||
return []
|
||||
|
||||
func _backend_is_accessible():
|
||||
var result = await _make_request(HEALTH_ENDPOINT, HTTPClient.METHOD_GET)
|
||||
|
||||
if not result:
|
||||
push_error("Server initialization failed")
|
||||
return false
|
||||
if result.has("error"):
|
||||
push_error("Server initialization failed: " + result.error)
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
#region Public Methods
|
||||
func create_reservation(dto: CreateReservationDTO) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT, HTTPClient.METHOD_POST, _dto_to_json(dto))
|
||||
|
||||
func cancel_reservation(reservation_id: String) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_DELETE)
|
||||
|
||||
func change_reservation(reservation_id: String, dto: UpdateReservationDTO) -> void:
|
||||
_make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_PUT, _dto_to_json(dto))
|
||||
|
||||
func get_reservation(reservation_id: String) -> ReservationEntity:
|
||||
var result = await _make_request(RESERVATION_ENDPOINT + "%s" % reservation_id, HTTPClient.METHOD_GET)
|
||||
return _parse_reservation_entity(result) if result is Dictionary else null
|
||||
|
||||
func list_reservations(filters: Dictionary = {}) -> Array:
|
||||
var query = "?"
|
||||
for key in filters:
|
||||
query += "%s=%s&" % [key, filters[key]]
|
||||
query = query.rstrip("&") if filters else ""
|
||||
|
||||
var endpoint = RESERVATION_ENDPOINT + query
|
||||
var result = await _make_request(endpoint, HTTPClient.METHOD_GET)
|
||||
var reservations = _parse_reservation_list(result) if result is Array else []
|
||||
|
||||
_set_current_reservation_id_from_reservations(reservations)
|
||||
return reservations
|
||||
|
||||
func _set_current_reservation_id_from_reservations(reservations):
|
||||
var time = Time.get_time_dict_from_system()
|
||||
var current_time_in_minutes = time.hour*60 + time.minute
|
||||
|
||||
for reservation in reservations:
|
||||
var start_time_in_minutes = reservation.start_time.hours*60 + reservation.start_time.minutes
|
||||
var finish_time_in_minutes = reservation.finish_time.hours*60 + reservation.finish_time.minutes
|
||||
|
||||
if current_time_in_minutes >= start_time_in_minutes \
|
||||
and current_time_in_minutes < finish_time_in_minutes:
|
||||
_current_reservation = reservation
|
||||
return
|
||||
|
||||
_current_reservation = null
|
||||
|
||||
func set_selected_reservation_id(value):
|
||||
_selected_reservation_id = value
|
||||
|
||||
func get_selected_reservation_id():
|
||||
return _selected_reservation_id
|
||||
|
||||
func set_jwt_token(token: String):
|
||||
_jwt_token = token
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
func _get_headers() -> PackedStringArray:
|
||||
return PackedStringArray([
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Bearer %s" % _jwt_token
|
||||
])
|
||||
|
||||
func _dto_to_json(dto) -> String:
|
||||
var dict = {}
|
||||
match typeof(dto):
|
||||
TYPE_OBJECT when dto is CreateReservationDTO:
|
||||
dict = {
|
||||
"title": dto.title,
|
||||
"description": dto.description,
|
||||
"room_id": dto.room_id,
|
||||
"date": dto.date,
|
||||
"start_time": dto.start_time,
|
||||
"finish_time": dto.finish_time,
|
||||
"color": dto.color
|
||||
}
|
||||
TYPE_OBJECT when dto is UpdateReservationDTO:
|
||||
if dto.title: dict["title"] = dto.title
|
||||
if dto.description: dict["description"] = dto.description
|
||||
if dto.room_id: dict["room_id"] = dto.room_id
|
||||
if dto.date: dict["date"] = dto.date
|
||||
if dto.start_time: dict["start_time"] = dto.start_time
|
||||
if dto.finish_time: dict["finish_time"] = dto.finish_time
|
||||
if dto.color: dict["color"] = dto.color
|
||||
return JSON.stringify(dict)
|
||||
|
||||
func _time_dto_to_dict(time_dto: TimeDTO) -> Dictionary:
|
||||
return {"hours": time_dto.hours, "minutes": time_dto.minutes}
|
||||
|
||||
func _make_request(endpoint: String, method: int, body: String = "") -> Variant:
|
||||
var request = HTTPRequest.new()
|
||||
|
||||
add_child(request)
|
||||
|
||||
var url = BASE_URL + endpoint
|
||||
var error = request.request(url, _get_headers(), method, body)
|
||||
if error != OK:
|
||||
request.queue_free()
|
||||
emit_signal("request_failed", "Request creation failed: %d" % error)
|
||||
return null
|
||||
|
||||
var response = await _wait_for_request_or_timeout(request)
|
||||
|
||||
request.queue_free()
|
||||
|
||||
var result = response[0]
|
||||
var response_code = response[1]
|
||||
var response_body = response[3]
|
||||
|
||||
if result != HTTPRequest.RESULT_SUCCESS:
|
||||
emit_signal("request_failed", "HTTP request failed: %d" % result)
|
||||
return null
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_error = json.parse(response_body.get_string_from_utf8())
|
||||
|
||||
if parse_error != OK:
|
||||
emit_signal("request_failed", "JSON parse error: %d" % parse_error)
|
||||
return null
|
||||
|
||||
var response_data = json.get_data()
|
||||
|
||||
if response_code >= 400:
|
||||
emit_signal("request_failed", response_data.get("error", "Unknown error"))
|
||||
return null
|
||||
|
||||
return response_data
|
||||
|
||||
func _wait_for_request_or_timeout(request: HTTPRequest) -> Array:
|
||||
var timer = Timer.new()
|
||||
add_child(timer)
|
||||
|
||||
timer.wait_time = 5.0
|
||||
timer.one_shot = true
|
||||
|
||||
timer.timeout.connect(func():
|
||||
_timed_out = true
|
||||
if request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
||||
request.cancel_request()
|
||||
)
|
||||
|
||||
timer.start()
|
||||
|
||||
while true:
|
||||
if _timed_out:
|
||||
_timed_out = false
|
||||
timer.queue_free()
|
||||
return [HTTPRequest.RESULT_REQUEST_FAILED, 408, [], PackedByteArray()]
|
||||
if request.get_http_client_status() == HTTPClient.STATUS_REQUESTING:
|
||||
break
|
||||
await get_tree().process_frame
|
||||
|
||||
timer.queue_free()
|
||||
return await request.request_completed
|
||||
|
||||
func _parse_reservation_entity(data: Dictionary) -> ReservationEntity:
|
||||
var entity = ReservationEntity.new()
|
||||
entity.id = data.get("id", "")
|
||||
entity.title = data.get("title", "")
|
||||
entity.description = data.get("description", "")
|
||||
entity.room_id = data.get("room_id", "")
|
||||
entity.creator = data.get("creator", "")
|
||||
entity.date = data.get("date", "")
|
||||
entity.color = data.get("color", 0)
|
||||
entity.start_time = data.get("start_time", {})
|
||||
entity.finish_time = data.get("finish_time", {})
|
||||
|
||||
return entity
|
||||
|
||||
func _parse_reservation_list(data: Array) -> Array[ReservationEntity]:
|
||||
var entities: Array[ReservationEntity] = []
|
||||
func _parse_room_list(data: Array) -> Array[RoomEntity]:
|
||||
var rooms: Array[RoomEntity] = []
|
||||
for item in data:
|
||||
entities.append(_parse_reservation_entity(item))
|
||||
var room = RoomEntity.new()
|
||||
room.id = item.get("id")
|
||||
room.title = item.get("title")
|
||||
rooms.append(room)
|
||||
return rooms
|
||||
|
||||
entities.sort_custom(_compare_reservations_by_start_time)
|
||||
return entities
|
||||
|
||||
func _compare_reservations_by_start_time(a: ReservationEntity, b: ReservationEntity) -> int:
|
||||
var time_a = a.start_time.get("hours", 0) * 60 + a.start_time.get("minutes", 0)
|
||||
var time_b = b.start_time.get("hours", 0) * 60 + b.start_time.get("minutes", 0)
|
||||
return time_a < time_b
|
||||
#endregion
|
||||
func _on_request_failed(error_message: String):
|
||||
emit_signal("request_failed", error_message)
|
||||
|
@ -41,7 +41,7 @@ func change_reservation(reservation_id, dto: UpdateReservationDTO):
|
||||
func get_reservation(reservation_id):
|
||||
return _reservations[reservation_id]
|
||||
|
||||
func list_reservations(filters: Dictionary = {}):
|
||||
func list_reservations(filters: Dictionary = {}) -> Array[ReservationEntity]:
|
||||
var reservations = []
|
||||
|
||||
for key in _reservations:
|
||||
|
81
src/libs/http_client.gd
Normal file
81
src/libs/http_client.gd
Normal file
@ -0,0 +1,81 @@
|
||||
class_name HTTPTalkpalClient
|
||||
extends Node
|
||||
|
||||
signal request_failed(error_message: String)
|
||||
|
||||
var _base_url: String
|
||||
var _jwt_token: String = ""
|
||||
var _timed_out := false
|
||||
|
||||
func _init(_base_url: String):
|
||||
self._base_url = _base_url
|
||||
|
||||
func set__jwt_token(token: String):
|
||||
_jwt_token = token
|
||||
|
||||
func request(endpoint: String, method: int, body: String = "") -> Variant:
|
||||
var request = HTTPRequest.new()
|
||||
add_child(request)
|
||||
|
||||
var url = _base_url + endpoint
|
||||
var headers = PackedStringArray([
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Bearer %s" % _jwt_token
|
||||
])
|
||||
|
||||
var error = request.request(url, headers, method, body)
|
||||
if error != OK:
|
||||
request.queue_free()
|
||||
emit_signal("request_failed", "Request creation failed: %d" % error)
|
||||
print("request_failed", "Request creation failed: %d" % error)
|
||||
return null
|
||||
|
||||
var response = await _wait_for_request_or_timeout(request)
|
||||
request.queue_free()
|
||||
|
||||
var result = response[0]
|
||||
var response_code = response[1]
|
||||
var response_body = response[3]
|
||||
|
||||
if result != HTTPRequest.RESULT_SUCCESS:
|
||||
emit_signal("request_failed", "HTTP request failed: %d" % result)
|
||||
return null
|
||||
|
||||
var json = JSON.new()
|
||||
var parse_error = json.parse(response_body.get_string_from_utf8())
|
||||
|
||||
if parse_error != OK:
|
||||
emit_signal("request_failed", "JSON parse error: %d" % parse_error)
|
||||
return null
|
||||
|
||||
var response_data = json.get_data()
|
||||
|
||||
if response_code >= 400:
|
||||
emit_signal("request_failed", response_data.get("error", "Unknown error"))
|
||||
return null
|
||||
|
||||
return response_data
|
||||
|
||||
func _wait_for_request_or_timeout(request: HTTPRequest) -> Array:
|
||||
var timer = Timer.new()
|
||||
add_child(timer)
|
||||
timer.wait_time = 5.0
|
||||
timer.one_shot = true
|
||||
timer.timeout.connect(func():
|
||||
_timed_out = true
|
||||
if request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
||||
request.cancel_request()
|
||||
)
|
||||
timer.start()
|
||||
|
||||
while true:
|
||||
if _timed_out:
|
||||
_timed_out = false
|
||||
timer.queue_free()
|
||||
return [HTTPRequest.RESULT_REQUEST_FAILED, 408, [], PackedByteArray()]
|
||||
if request.get_http_client_status() == HTTPClient.STATUS_REQUESTING:
|
||||
break
|
||||
await get_tree().process_frame
|
||||
|
||||
timer.queue_free()
|
||||
return await request.request_completed
|
@ -230,7 +230,6 @@ func socketio_connect(name_space: String="/"):
|
||||
|
||||
# disconnect from socket.io server by namespace
|
||||
func socketio_disconnect(name_space: String="/"):
|
||||
print("FUCK")
|
||||
if _connection_state == ConnectionState.CONNECTED:
|
||||
# We should ONLY send disconnect packet when we're connected
|
||||
_socketio_send_packet(SocketIOPacketType.DISCONNECT, name_space)
|
||||
|
Loading…
x
Reference in New Issue
Block a user