Merge branch 'markdown' into api
This commit is contained in:
commit
415582e084
25
admin.py
25
admin.py
@ -272,7 +272,7 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
timestamps_of_this_day[i])
|
||||
time_sum = time_sum + time_delta
|
||||
|
||||
ui.markdown(convert_seconds_to_hours(time_sum))
|
||||
ui.markdown(convert_seconds_to_hours(time_sum)).classes('text-right')
|
||||
else:
|
||||
ui.markdown("Kein")
|
||||
|
||||
@ -282,7 +282,7 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
if hours_to_work < 0:
|
||||
ui.space()
|
||||
else:
|
||||
ui.markdown(f"{convert_seconds_to_hours(int(hours_to_work) * 3600)}")
|
||||
ui.markdown(f"{convert_seconds_to_hours(int(hours_to_work) * 3600)}").classes('text-right')
|
||||
if int(hours_to_work) == 0:
|
||||
day_type.content = "**Kein Arbeitstag**"
|
||||
day_type.set_visibility(True)
|
||||
@ -307,9 +307,9 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
pass
|
||||
|
||||
general_saldo = general_saldo + saldo
|
||||
ui.markdown(convert_seconds_to_hours(saldo))
|
||||
ui.markdown(convert_seconds_to_hours(saldo)).classes('text-right')
|
||||
else:
|
||||
ui.markdown("-")
|
||||
ui.markdown("-").classes('text-center')
|
||||
|
||||
def add_entry(day):
|
||||
with ui.dialog() as add_dialog, ui.card():
|
||||
@ -425,18 +425,13 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
#ui.button("Eintrag hinzufügen", on_click=lambda day=day: add_entry(day))
|
||||
|
||||
#4x leer und dann Gesamtsaldo
|
||||
for i in range(4):
|
||||
ui.space()
|
||||
ui.markdown(f"{convert_seconds_to_hours(general_saldo)}")
|
||||
for i in range(4):
|
||||
ui.space()
|
||||
ui.markdown("Stunden aus Vormonat")
|
||||
ui.space().classes('col-span-4')
|
||||
ui.markdown(f"{convert_seconds_to_hours(general_saldo)}").classes('text-right')
|
||||
ui.markdown("Stunden aus Vormonat").classes('col-span-4 text-right')
|
||||
last_months_overtime = current_user.get_last_months_overtime(select_year.value, select_month.value)
|
||||
ui.markdown(f"{convert_seconds_to_hours(last_months_overtime)}")
|
||||
for i in range(4):
|
||||
ui.space()
|
||||
ui.markdown("Gesamtsaldo")
|
||||
ui.markdown(f"**<ins>{convert_seconds_to_hours(general_saldo + last_months_overtime)}</ins>**")
|
||||
ui.markdown(f"{convert_seconds_to_hours(last_months_overtime)}").classes('text-right')
|
||||
ui.markdown("Gesamtsaldo").classes('col-span-4 text-right')
|
||||
ui.markdown(f"**<ins>{convert_seconds_to_hours(general_saldo + last_months_overtime)}</ins>**").classes('text-right')
|
||||
table_grid.move(calendar_card)
|
||||
update_month_and_year()
|
||||
|
||||
|
305
api.py
305
api.py
@ -2,7 +2,9 @@ import sys
|
||||
from logging import exception
|
||||
|
||||
from nicegui import *
|
||||
from samba.graph import pad_char
|
||||
|
||||
import ui
|
||||
from definitions import *
|
||||
from web_ui import *
|
||||
from users import *
|
||||
@ -22,179 +24,196 @@ def page(username: str, year: int, month: int):
|
||||
ui.space()
|
||||
ui.markdown(f'#Bericht für {current_user.fullname} für {calendar.month_name[month]} {year}')
|
||||
|
||||
columns = [
|
||||
{'name': 'date', 'label': 'Datum', 'field': 'date', 'required': True, 'align': 'left'},
|
||||
{'name:': 'bookings', 'label': 'Buchungen', 'field': 'bookings', 'align': 'left'},
|
||||
{'name:': 'is_time', 'label': 'Ist', 'field': 'is_time', 'align': 'left'},
|
||||
{'name:': 'target_time', 'label': 'Soll', 'field': 'target_time', 'align': 'left'},
|
||||
{'name:': 'total', 'label': 'Saldo', 'field': 'total', 'align': 'left'}
|
||||
]
|
||||
pad_x = 4
|
||||
pad_y = 0
|
||||
|
||||
rows = [ ]
|
||||
color_weekend = "gray-100"
|
||||
color_holiday = "gray-100"
|
||||
|
||||
# Timestamp in ein Array schreiben
|
||||
timestamps = current_user.get_timestamps(year, month)
|
||||
timestamps.sort()
|
||||
def overview_table():
|
||||
# Timestamp in ein Array schreiben
|
||||
timestamps = current_user.get_timestamps(year, month)
|
||||
timestamps.sort()
|
||||
|
||||
# Abwesenheitsdaten in ein Dict schreiben
|
||||
user_absent = current_user.get_absence(year, month)
|
||||
# Abwesenheitsdaten in ein Dict schreiben
|
||||
user_absent = current_user.get_absence(year, month)
|
||||
|
||||
# Dictionary für sortierte Timestamps
|
||||
timestamps_dict = { }
|
||||
# Dictionary für sortierte Timestamps
|
||||
timestamps_dict = { }
|
||||
|
||||
# Dictionary mit zunächst leeren Tageinträgen befüllen
|
||||
for day in range(1, monthrange(year, month)[1] + 1):
|
||||
# Jeder Tag bekommt eine leere Liste
|
||||
timestamps_dict[day] = [ ]
|
||||
# Dictionary mit zunächst leeren Tageinträgen befüllen
|
||||
for day in range(1, monthrange(year, month)[1] + 1):
|
||||
# Jeder Tag bekommt eine leere Liste
|
||||
timestamps_dict[day] = [ ]
|
||||
|
||||
# Timestamps den Monatstagen zuordnen
|
||||
for stamp in timestamps:
|
||||
day_of_month_of_timestamp = datetime.fromtimestamp(int(stamp)).day
|
||||
timestamps_dict[day_of_month_of_timestamp].append(int(stamp))
|
||||
timestamps_dict[day_of_month_of_timestamp].append(int(stamp))
|
||||
# Timestamps den Monatstagen zuordnen
|
||||
for stamp in timestamps:
|
||||
day_of_month_of_timestamp = datetime.fromtimestamp(int(stamp)).day
|
||||
timestamps_dict[day_of_month_of_timestamp].append(int(stamp))
|
||||
timestamps_dict[day_of_month_of_timestamp].append(int(stamp))
|
||||
|
||||
general_saldo = 0
|
||||
general_saldo = 0
|
||||
|
||||
# Gehe jeden einzelnen Tag des Dictionaries für die Timestamps durch
|
||||
for day in list(timestamps_dict):
|
||||
booking_text = ""
|
||||
current_day_date = f"{datetime(year, month, day).strftime('%a')}, {day}.{month}.{year}"
|
||||
with ui.grid(columns='auto auto 1fr 1fr 1fr').classes(f'gap-0 border px-0 py-0'):
|
||||
ui.markdown("**Datum**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Buchungen**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Ist**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Soll**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Saldo**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
|
||||
# Abwesenheitseinträge
|
||||
try:
|
||||
# Abwesenheitszeiten behandeln
|
||||
for i in list(user_absent):
|
||||
if int(i) == day:
|
||||
booking_text += absence_entries[user_absent[i]]["name"] + " "
|
||||
except:
|
||||
pass
|
||||
# Gehe jeden einzelnen Tag des Dictionaries für die Timestamps durch
|
||||
for day in list(timestamps_dict):
|
||||
booking_text = ""
|
||||
color_day = 'inherit'
|
||||
if datetime(year, month, day).strftime('%w') in ["0", "6"]:
|
||||
color_day = color_weekend
|
||||
|
||||
# Buchungen behandeln
|
||||
for i in range(len(timestamps_dict[day])):
|
||||
try:
|
||||
temp_pair = [timestamps_dict[day][i], timestamps_dict[day][i + 1]]
|
||||
booking_text = booking_text + str(datetime.fromtimestamp(temp_pair[0]).strftime('%H:%M')) + "-" + str(datetime.fromtimestamp(temp_pair[1]).strftime('%H:%M')) + "\n"
|
||||
current_day_date = f"{datetime(year, month, day).strftime('%a')}, {day}.{month}.{year}"
|
||||
day_text_element = ui.markdown(current_day_date).classes(f'border px-{pad_x} py-{pad_y} bg-{color_day}')
|
||||
|
||||
except:
|
||||
if len(timestamps_dict[day]) % 2 != 0:
|
||||
booking_text += datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M')
|
||||
|
||||
# Ist-Zeiten berechnen
|
||||
timestamps_of_this_day = []
|
||||
|
||||
# Suche mir alle timestamps für diesen Tag
|
||||
for i in timestamps:
|
||||
actual_timestamp = datetime.fromtimestamp(int(i))
|
||||
timestamp_day = actual_timestamp.strftime('%-d')
|
||||
|
||||
if int(timestamp_day) == int(day):
|
||||
timestamps_of_this_day.append(i)
|
||||
|
||||
timestamps_of_this_day.sort()
|
||||
time_sum = 0
|
||||
if len(timestamps_of_this_day) > 1:
|
||||
|
||||
if len(timestamps_of_this_day) % 2 == 0:
|
||||
for i in range(0, len(timestamps_of_this_day), 2):
|
||||
time_delta = int(
|
||||
timestamps_of_this_day[i + 1]) - int(
|
||||
timestamps_of_this_day[i])
|
||||
time_sum = time_sum + time_delta
|
||||
else:
|
||||
for i in range(0, len(timestamps_of_this_day) - 1, 2):
|
||||
time_delta = int(
|
||||
timestamps_of_this_day[i + 1]) - int(
|
||||
timestamps_of_this_day[i])
|
||||
time_sum = time_sum + time_delta
|
||||
|
||||
is_time = convert_seconds_to_hours(time_sum) + " h"
|
||||
else:
|
||||
is_time = "Kein"
|
||||
|
||||
# Sollzeit bestimmen
|
||||
|
||||
hours_to_work = int(current_user.get_day_workhours(year, month, day))
|
||||
|
||||
if hours_to_work < 0:
|
||||
target_time = ""
|
||||
else:
|
||||
target_time = f"{convert_seconds_to_hours(int(hours_to_work) * 3600)} h"
|
||||
if int(hours_to_work) == 0:
|
||||
booking_text = "Kein Arbeitstag"
|
||||
|
||||
# Saldo für den Tag berechnen
|
||||
day_in_list = datetime(year, month, day)
|
||||
if time.time() > day_in_list.timestamp():
|
||||
|
||||
time_duty = int(current_user.get_day_workhours(year, month, day)) * 3600
|
||||
if time_duty < 0:
|
||||
saldo = 0
|
||||
total = ""
|
||||
booking_text = "Kein Arbeitsverhältnis"
|
||||
else:
|
||||
saldo = int(time_sum) - int(time_duty)
|
||||
# Nach Abwesenheitseinträgen suchen
|
||||
# Abwesenheitseinträge
|
||||
booking_color = "inherit"
|
||||
booking_text_color = "inherit"
|
||||
try:
|
||||
# Abwesenheitszeiten behandeln
|
||||
for i in list(user_absent):
|
||||
if int(i) == day and user_absent[i] != "UU":
|
||||
saldo = 0
|
||||
if int(i) == day:
|
||||
booking_text += absence_entries[user_absent[i]]["name"] + "<br>"
|
||||
booking_color = absence_entries[user_absent[i]]["color"]
|
||||
booking_text_color = absence_entries[user_absent[i]]["text-color"]
|
||||
except:
|
||||
pass
|
||||
|
||||
general_saldo = general_saldo + saldo
|
||||
total = f"{convert_seconds_to_hours(saldo)} h"
|
||||
else:
|
||||
total = "-"
|
||||
# Buchungen behandeln
|
||||
for i in range(len(timestamps_dict[day])):
|
||||
try:
|
||||
temp_pair = [timestamps_dict[day][i], timestamps_dict[day][i + 1]]
|
||||
booking_text = booking_text + str(datetime.fromtimestamp(temp_pair[0]).strftime('%H:%M')) + "-" + str(datetime.fromtimestamp(temp_pair[1]).strftime('%H:%M')) + "<br>"
|
||||
|
||||
rows.append({'date': current_day_date, 'bookings': booking_text, 'is_time': is_time, 'target_time': target_time, 'total': total})
|
||||
except:
|
||||
if len(timestamps_dict[day]) % 2 != 0:
|
||||
booking_text += datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M')
|
||||
print(booking_text)
|
||||
|
||||
overview_table = ui.table(columns=columns, rows=rows, row_key='date').classes('w-full')
|
||||
booking_text_element = ui.markdown(booking_text).classes(f'border px-{pad_x} py-{pad_y} bg-{booking_color} text-{booking_text_color}')
|
||||
|
||||
# Zeilenumbruch umsetzen
|
||||
overview_table.add_slot('body-cell', r'''
|
||||
<td :props="props" :style="{'white-space':'pre-line'}">{{ props.value }}</td>
|
||||
''')
|
||||
# Überstundenzusammenfassung
|
||||
# Ist-Zeiten berechnen
|
||||
timestamps_of_this_day = []
|
||||
|
||||
with ui.grid(columns=2).classes('w-full gap-0'):
|
||||
ui.markdown("Überstunden aus Vormonat:")
|
||||
last_months_overtime = current_user.get_last_months_overtime(year, month)
|
||||
ui.markdown(f"{convert_seconds_to_hours(last_months_overtime)} h")
|
||||
ui.markdown("Überstunden diesen Monat:")
|
||||
ui.markdown(f"{convert_seconds_to_hours(general_saldo)} h")
|
||||
ui.markdown("**Überstunden Gesamt:**")
|
||||
overtime_overall = last_months_overtime + general_saldo
|
||||
ui.markdown(f"**{convert_seconds_to_hours(overtime_overall)} h**")
|
||||
# Suche mir alle timestamps für diesen Tag
|
||||
for i in timestamps:
|
||||
actual_timestamp = datetime.fromtimestamp(int(i))
|
||||
timestamp_day = actual_timestamp.strftime('%-d')
|
||||
|
||||
absences_this_month = current_user.get_absence(year, month)
|
||||
absence_dict = { }
|
||||
if int(timestamp_day) == int(day):
|
||||
timestamps_of_this_day.append(i)
|
||||
|
||||
for abbr in list(absence_entries):
|
||||
absence_dict[abbr] = 0
|
||||
timestamps_of_this_day.sort()
|
||||
time_sum = 0
|
||||
if len(timestamps_of_this_day) > 1:
|
||||
|
||||
for key, value in absences_this_month.items():
|
||||
if value in list(absence_dict):
|
||||
absence_dict[value] += 1
|
||||
if len(timestamps_of_this_day) % 2 == 0:
|
||||
for i in range(0, len(timestamps_of_this_day), 2):
|
||||
time_delta = int(
|
||||
timestamps_of_this_day[i + 1]) - int(
|
||||
timestamps_of_this_day[i])
|
||||
time_sum = time_sum + time_delta
|
||||
else:
|
||||
for i in range(0, len(timestamps_of_this_day) - 1, 2):
|
||||
time_delta = int(
|
||||
timestamps_of_this_day[i + 1]) - int(
|
||||
timestamps_of_this_day[i])
|
||||
time_sum = time_sum + time_delta
|
||||
|
||||
total_absence_days = 0
|
||||
for key, value in absence_dict.items():
|
||||
total_absence_days += absence_dict[key]
|
||||
is_time = convert_seconds_to_hours(time_sum) + " h"
|
||||
else:
|
||||
is_time = "Kein"
|
||||
|
||||
if total_absence_days > 0:
|
||||
ui.markdown("###Abwesenheitstage diesen Monat:")
|
||||
a_columns = [
|
||||
{'name': 'type', 'label': 'Typ', 'field': 'type', 'required': True, 'align': 'left'},
|
||||
{'name': 'sum', 'label': 'Tage', 'field': 'sum', 'required': True, 'align': 'left'},
|
||||
]
|
||||
ui.markdown(is_time).classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
# Sollzeit bestimmen
|
||||
|
||||
a_row = [ ]
|
||||
hours_to_work = int(current_user.get_day_workhours(year, month, day))
|
||||
|
||||
for key,value in absence_dict.items():
|
||||
if value > 0:
|
||||
a_row.append({'type': absence_entries[key]['name'], 'sum': value})
|
||||
if hours_to_work < 0:
|
||||
target_time = ""
|
||||
else:
|
||||
target_time = f"{convert_seconds_to_hours(int(hours_to_work) * 3600)} h"
|
||||
if int(hours_to_work) == 0:
|
||||
booking_text = "Kein Arbeitstag"
|
||||
booking_text_element.set_content(booking_text)
|
||||
|
||||
absence_table = ui.table(columns=a_columns, rows=a_row)
|
||||
ui.markdown(target_time).classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
|
||||
# Saldo für den Tag berechnen
|
||||
day_in_list = datetime(year, month, day)
|
||||
if time.time() > day_in_list.timestamp():
|
||||
|
||||
time_duty = int(current_user.get_day_workhours(year, month, day)) * 3600
|
||||
if time_duty < 0:
|
||||
saldo = 0
|
||||
total = ""
|
||||
booking_text = "Kein Arbeitsverhältnis"
|
||||
booking_text_element.set_content(booking_text)
|
||||
else:
|
||||
saldo = int(time_sum) - int(time_duty)
|
||||
# Nach Abwesenheitseinträgen suchen
|
||||
try:
|
||||
for i in list(user_absent):
|
||||
if int(i) == day and user_absent[i] != "UU":
|
||||
saldo = 0
|
||||
except:
|
||||
pass
|
||||
|
||||
general_saldo = general_saldo + saldo
|
||||
total = f"{convert_seconds_to_hours(saldo)} h"
|
||||
|
||||
else:
|
||||
total = "-"
|
||||
if total == "-":
|
||||
total_class = 'text-center'
|
||||
else:
|
||||
total_class = 'text-right'
|
||||
ui.markdown(total).classes(total_class).classes(f'border px-{pad_x} py-{pad_y}')
|
||||
|
||||
# Überstundenzusammenfassung
|
||||
ui.markdown("Überstunden aus Vormonat:").classes(f'col-span-4 text-right border px-{pad_x} py-{pad_y}')
|
||||
last_months_overtime = current_user.get_last_months_overtime(year, month)
|
||||
ui.markdown(f"{convert_seconds_to_hours(last_months_overtime)} h").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("Überstunden diesen Monat:").classes(f'col-span-4 text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown(f"{convert_seconds_to_hours(general_saldo)} h").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Überstunden Gesamt:**").classes(f'col-span-4 text-right border px-{pad_x} py-{pad_y}')
|
||||
overtime_overall = last_months_overtime + general_saldo
|
||||
ui.markdown(f"**{convert_seconds_to_hours(overtime_overall)} h**").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
|
||||
overview_table()
|
||||
|
||||
def absence_table():
|
||||
absences_this_month = current_user.get_absence(year, month)
|
||||
absence_dict = { }
|
||||
|
||||
for abbr in list(absence_entries):
|
||||
absence_dict[abbr] = 0
|
||||
|
||||
for key, value in absences_this_month.items():
|
||||
if value in list(absence_dict):
|
||||
absence_dict[value] += 1
|
||||
|
||||
total_absence_days = 0
|
||||
for key, value in absence_dict.items():
|
||||
total_absence_days += absence_dict[key]
|
||||
|
||||
if total_absence_days > 0:
|
||||
ui.markdown("###Abwesenheitstage diesen Monat:")
|
||||
|
||||
with ui.grid(columns='auto 20%').classes(f'gap-0 border px-0 py-0'):
|
||||
|
||||
for key,value in absence_dict.items():
|
||||
if value > 0:
|
||||
ui.markdown(absence_entries[key]['name']).classes(f"border px-{pad_x} py-{pad_y}")
|
||||
ui.markdown(str(value)).classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
|
||||
absence_table()
|
||||
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
|
@ -23,14 +23,21 @@ status_out = "ausgestempelt"
|
||||
# Abesenheiten
|
||||
|
||||
absence_entries = {"U": { "name": "Urlaub",
|
||||
"color": "green"},
|
||||
"color": "green",
|
||||
"text-color": "black"},
|
||||
"K": { "name": "Krankheit",
|
||||
"color": "red"},
|
||||
"color": "red",
|
||||
"text-color": "white"},
|
||||
"KK": { "name": "Krankheit Kind",
|
||||
"color": "orange"},
|
||||
"color": "orange",
|
||||
"text-color": "black"},
|
||||
"UU": { "name": "Urlaub aus Überstunden",
|
||||
"color": "green"},
|
||||
"color": "green",
|
||||
"text-color": "black"},
|
||||
"F": { "name": "Fortbildung",
|
||||
"color": "black"},
|
||||
"color": "black",
|
||||
"text-color": "white"},
|
||||
"EZ": { "name": "Elternzeit",
|
||||
"color": "purple"}}
|
||||
"color": "purple",
|
||||
"text-color": "white"}
|
||||
}
|
||||
|
14
playgound.py
14
playgound.py
@ -1,16 +1,8 @@
|
||||
from nicegui import ui
|
||||
|
||||
columns=[
|
||||
{'name': 'name', 'label': 'Name', 'field': 'name', 'align': 'left', 'style': 'text-wrap: wrap'},
|
||||
{'name': 'age', 'label': 'Age', 'field': 'age'},
|
||||
]
|
||||
rows=[
|
||||
{'name': 'Alice', 'age': 18},
|
||||
{'name': 'Bob', 'age': 21},
|
||||
{'name': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec purus nec nunc ultricies'},
|
||||
]
|
||||
|
||||
ui.table(columns=columns, rows=rows).classes('w-80')
|
||||
test = ('Eintrag 1')
|
||||
|
||||
ui.markdown(test)
|
||||
ui.markdown('Nächstes Element')
|
||||
|
||||
ui.run(language="de-DE", port=9000)
|
18
users.py
18
users.py
@ -288,6 +288,24 @@ class user:
|
||||
hours_to_work = -1
|
||||
return hours_to_work
|
||||
|
||||
def get_vacation_claim(self, year, month, day):
|
||||
workhour_entries = list(self.workhours)
|
||||
workhour_entries.sort()
|
||||
day_to_check = datetime.datetime(int(year), int(month), int(day))
|
||||
|
||||
claim = -1
|
||||
|
||||
for entry in reversed(workhour_entries):
|
||||
|
||||
entry_split = entry.split("-")
|
||||
entry_dt = datetime.datetime(int(entry_split[0]), int(entry_split[1]), int(entry_split[2]))
|
||||
|
||||
if entry_dt <= day_to_check:
|
||||
claim = self.workhours[entry]["vacation"]
|
||||
break
|
||||
|
||||
return claim
|
||||
|
||||
def delete_photo(self):
|
||||
os.remove(self.photofile)
|
||||
|
||||
|
@ -3,8 +3,10 @@
|
||||
"overtime": 0,
|
||||
"absence": {
|
||||
"7": "U",
|
||||
"8": "U",
|
||||
"9": "U",
|
||||
"10": "U"
|
||||
"8": "K",
|
||||
"9": "KK",
|
||||
"10": "UU",
|
||||
"11": "F",
|
||||
"14": "EZ"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user