first commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
client/pages/settings/__pycache__/settings.cpython-313.pyc
Normal file
BIN
client/pages/settings/__pycache__/settings.cpython-313.pyc
Normal file
Binary file not shown.
BIN
client/pages/settings/__pycache__/users.cpython-313.pyc
Normal file
BIN
client/pages/settings/__pycache__/users.cpython-313.pyc
Normal file
Binary file not shown.
595
client/pages/settings/documente_juridice.py
Normal file
595
client/pages/settings/documente_juridice.py
Normal file
@@ -0,0 +1,595 @@
|
||||
import flet as ft
|
||||
import requests
|
||||
from helpers.roles import Roles
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
|
||||
@dataclass
|
||||
class State:
|
||||
|
||||
file_picker: ft.FilePicker | None = None
|
||||
picked_files: list[ft.FilePickerFile] = field(default_factory=list)
|
||||
|
||||
|
||||
state = State()
|
||||
|
||||
class DocumenteJuridice:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.editing_category_id = None
|
||||
self.category_id_to_delete = None
|
||||
self.document_id_to_delete = None
|
||||
self.current_category_id = None
|
||||
|
||||
self.search_bar = ft.TextField(
|
||||
label="Cauta",
|
||||
on_submit=self.on_search_bar_submit,
|
||||
expand=True
|
||||
)
|
||||
self.category_name = ft.TextField(
|
||||
label="Nume categorie",
|
||||
)
|
||||
|
||||
self.roles_checkboxes = [
|
||||
ft.Checkbox(label=role.upper())
|
||||
for role in [
|
||||
Roles.USER, Roles.PROPRIETAR, Roles.CENZOR,
|
||||
Roles.ADMINISTRATOR, Roles.PRESEDINTE, Roles.EXPERT
|
||||
]
|
||||
]
|
||||
|
||||
self.access_levels = ft.Column(
|
||||
controls=self.roles_checkboxes,
|
||||
height=200,
|
||||
scroll=ft.ScrollMode.AUTO
|
||||
)
|
||||
|
||||
self.add_categories_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Adauga Categorie"),
|
||||
content=ft.Column(
|
||||
[
|
||||
self.category_name,
|
||||
ft.Text("Nivele Acces:"),
|
||||
self.access_levels
|
||||
],
|
||||
height=300,
|
||||
tight=True
|
||||
),
|
||||
actions=[
|
||||
ft.FilledButton(
|
||||
"Salveaza",
|
||||
on_click=self.on_save_category_btn_click
|
||||
),
|
||||
ft.FilledButton(
|
||||
"Anuleaza",
|
||||
on_click=self.on_cancel_category_btn_click,
|
||||
bgcolor=ft.Colors.GREY,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
self.delete_confirmation_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Doriti sa stergeti categoria?"),
|
||||
content=ft.Text("Stergerea categoriei implica si stergerea tuturor documentelor din aceasta categorie."),
|
||||
actions=[
|
||||
ft.FilledButton(
|
||||
"Da",
|
||||
on_click=self.confirm_delete_category
|
||||
),
|
||||
ft.FilledButton(
|
||||
"Nu",
|
||||
bgcolor=ft.Colors.GREY,
|
||||
on_click=self.close_delete_dialog
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
self.delete_document_confirmation_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Doriti sa stergeti documentul?"),
|
||||
content=ft.Text("Aceasta actiune este permanenta."),
|
||||
actions=[
|
||||
ft.FilledButton(
|
||||
"Da",
|
||||
on_click=self.confirm_delete_document
|
||||
),
|
||||
ft.FilledButton(
|
||||
"Nu",
|
||||
bgcolor=ft.Colors.GREY,
|
||||
on_click=self.close_delete_document_dialog
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
self.all_categories = self.get_categories()
|
||||
self.category_list = ft.ListView(
|
||||
controls=self.create_category_list(
|
||||
self.all_categories,
|
||||
self.on_edit_category_btn_click,
|
||||
self.on_delete_category_btn_click
|
||||
),
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.add_document = ft.Button(
|
||||
"Adauga Document",
|
||||
icon=ft.Icons.ADD,
|
||||
on_click=self.add_new_document
|
||||
)
|
||||
|
||||
self.all_documents = []
|
||||
self.documents_list = ft.ListView(
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.category = ft.Dropdown(
|
||||
label="Selectează Categoria",
|
||||
options=[
|
||||
ft.dropdown.Option(key=str(cat['id']), text=cat['name'])
|
||||
for cat in self.all_categories
|
||||
]
|
||||
)
|
||||
|
||||
self.documenet_title = None
|
||||
self.documenet_displayed_title = ft.TextField(label="Document",read_only=True)
|
||||
self.add_new_document_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Adauga document"),
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.documenet_displayed_title,
|
||||
ft.Button(
|
||||
"Incarca",
|
||||
icon=ft.Icons.UPLOAD,
|
||||
on_click=self.handle_file_upload
|
||||
),
|
||||
]
|
||||
),
|
||||
self.category
|
||||
],
|
||||
height=160,
|
||||
),
|
||||
actions=[
|
||||
ft.FilledButton(
|
||||
"Salveaza",
|
||||
on_click=self.on_save_document_btn_click,
|
||||
|
||||
),
|
||||
ft.FilledButton(
|
||||
"Anuleaza",
|
||||
bgcolor=ft.Colors.GREY,
|
||||
on_click=self.on_cancel_save_dialog_btn_click,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def on_add_btn_click(self, e):
|
||||
self.editing_category_id = None
|
||||
self.category_name.value = ""
|
||||
for cb in self.roles_checkboxes:
|
||||
cb.value = False
|
||||
self.add_categories_dialog.title = ft.Text("Adauga Categorie")
|
||||
self.page.show_dialog(self.add_categories_dialog)
|
||||
self.page.update()
|
||||
|
||||
def on_save_category_btn_click(self, e):
|
||||
category = self.category_name.value
|
||||
access = ",".join([cb.label for cb in self.roles_checkboxes if cb.value])
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
|
||||
if self.editing_category_id:
|
||||
url = f'{base_url}/documents/categories/update/{self.editing_category_id}'
|
||||
method = requests.put
|
||||
else:
|
||||
url = f'{base_url}/documents/categories/add'
|
||||
method = requests.post
|
||||
|
||||
response = method(
|
||||
url,
|
||||
json={
|
||||
"name": category,
|
||||
"access": access
|
||||
},
|
||||
headers = {
|
||||
'Authorization': f'Bearer {token}',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
)
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
self.update_category_list()
|
||||
self.category_name.value = None
|
||||
self.editing_category_id = None
|
||||
self.page.pop_dialog()
|
||||
else:
|
||||
raise Exception("Operatiuna nu sa putut realiza, token-ul a expirat, va rugam sa va autentificati. Daca eroarea persita contactati echipa de IT!")
|
||||
|
||||
|
||||
def update_category_list(self):
|
||||
self.all_categories = self.get_categories()
|
||||
self.category_list.controls = self.create_category_list(
|
||||
self.all_categories,
|
||||
self.on_edit_category_btn_click,
|
||||
self.on_delete_category_btn_click
|
||||
)
|
||||
self.category_list.update()
|
||||
|
||||
# Actualizăm și opțiunile din dropdown-ul pentru documente
|
||||
self.category.options = [
|
||||
ft.dropdown.Option(key=str(cat['id']), text=cat['name'])
|
||||
for cat in self.all_categories
|
||||
]
|
||||
|
||||
def on_cancel_category_btn_click(self, e):
|
||||
self.category_name.value = None
|
||||
self.page.pop_dialog()
|
||||
|
||||
def on_search_bar_submit(self, e):
|
||||
# Luăm textul din search bar și îl convertim la litere mici pentru o căutare case-insensitive
|
||||
query = self.search_bar.value.strip().lower()
|
||||
|
||||
# Filtrăm lista de documente stocată în self.all_documents
|
||||
if not query:
|
||||
filtered_docs = self.all_documents
|
||||
else:
|
||||
filtered_docs = [
|
||||
doc for doc in self.all_documents
|
||||
if query in doc['name'].lower()
|
||||
]
|
||||
|
||||
# Actualizăm interfața cu lista filtrată
|
||||
self.documents_list.controls = self.create_documents_list(
|
||||
filtered_docs,
|
||||
lambda doc: self.page.run_task(self.on_download_document_btn_click, doc),
|
||||
self.on_delete_document_btn_click
|
||||
)
|
||||
self.documents_list.update()
|
||||
|
||||
def add_new_document(self, e):
|
||||
self.page.show_dialog(self.add_new_document_dialog)
|
||||
|
||||
async def handle_file_upload(self, e: ft.Event[ft.Button]):
|
||||
print('File uploaded')
|
||||
try:
|
||||
state.file_picker = ft.FilePicker()
|
||||
files = await state.file_picker.pick_files(allow_multiple=False)
|
||||
print("Picked file:", files)
|
||||
|
||||
state.picked_files = files
|
||||
uploaded_file_name = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{state.picked_files[0].name}"
|
||||
await state.file_picker.upload(
|
||||
files=[
|
||||
ft.FilePickerUploadFile(
|
||||
name=file.name,
|
||||
upload_url=self.page.get_upload_url(uploaded_file_name, 60),
|
||||
|
||||
)
|
||||
|
||||
for file in state.picked_files
|
||||
]
|
||||
)
|
||||
self.documenet_title = uploaded_file_name
|
||||
self.documenet_displayed_title.value = uploaded_file_name.split("_")[1]
|
||||
self.documenet_displayed_title.update()
|
||||
return f'{uploaded_file_name}'
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def on_save_document_btn_click(self, e):
|
||||
if not self.category.value or not self.documenet_title:
|
||||
# Opțional: Poți adăuga un mesaj de eroare vizibil pentru utilizator
|
||||
return
|
||||
|
||||
selected_cat_id = int(self.category.value)
|
||||
# Identificăm obiectul categoriei pentru a-i moșteni accesul și numele
|
||||
category = next((cat for cat in self.all_categories if cat['id'] == selected_cat_id), None)
|
||||
|
||||
if not category:
|
||||
return
|
||||
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
|
||||
# Construim path-ul relativ (Categorie/NumeFisier)
|
||||
dest_path = f"{category['name']}/{self.documenet_title}"
|
||||
|
||||
payload = {
|
||||
"category_id": selected_cat_id,
|
||||
"name": self.documenet_displayed_title.value,
|
||||
"path": dest_path,
|
||||
"access": category.get('access', '') # Moștenim accesul de la categorie
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
f"{base_url}/documents/standards/add",
|
||||
json=payload,
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
|
||||
if response.status_code == 201:
|
||||
self.page.pop_dialog()
|
||||
self.list_all_category_documents(selected_cat_id)
|
||||
# Resetăm câmpurile după salvarea cu succes
|
||||
self.documenet_title = None
|
||||
self.documenet_displayed_title.value = ""
|
||||
|
||||
def on_cancel_save_dialog_btn_click(self, e):
|
||||
self.documenet_title = None
|
||||
self.documenet_displayed_title.value = ""
|
||||
self.page.pop_dialog()
|
||||
|
||||
def create_category_list(self, items, on_click_handler, on_click_handler2):
|
||||
"""Helper to create list items for a column."""
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item['name'])
|
||||
]
|
||||
),
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, id=item: on_click_handler(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.REFRESH,
|
||||
on_click=lambda e, id=item['id']: self.on_refresh_category_click(id),
|
||||
icon_color=ft.Colors.BLUE_400,
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.DELETE,
|
||||
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||
icon_color=ft.Colors.RED,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
expand=True,
|
||||
bgcolor=ft.Colors.BLUE_50,
|
||||
border = ft.Border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
ink=True,
|
||||
on_click=lambda e, cid=item['id']: self.list_all_category_documents(cid)
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def on_edit_category_btn_click(self, category):
|
||||
self.editing_category_id = category['id']
|
||||
self.category_name.value = category['name']
|
||||
|
||||
access_list = category.get('access', '').split(',')
|
||||
for cb in self.roles_checkboxes:
|
||||
cb.value = cb.label in access_list
|
||||
|
||||
self.add_categories_dialog.title = ft.Text("Editeaza Categorie")
|
||||
self.page.show_dialog(self.add_categories_dialog)
|
||||
self.page.update()
|
||||
|
||||
def on_refresh_category_click(self, category_id):
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
f'{base_url}/documents/categories/refresh/{category_id}',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
added = response.json().get("added", 0)
|
||||
# Daca suntem in categoria care s-a improspatat, reincarcam lista de documente
|
||||
if self.current_category_id == category_id:
|
||||
self.list_all_category_documents(category_id)
|
||||
|
||||
# Notificare succes
|
||||
self.page.snack_bar = ft.SnackBar(
|
||||
content=ft.Text(f"Refresh complet. S-au adaugat {added} documente."),
|
||||
bgcolor=ft.Colors.GREEN_400
|
||||
)
|
||||
self.page.snack_bar.open = True
|
||||
self.page.update()
|
||||
except Exception as e:
|
||||
print(f"Error during category refresh: {e}")
|
||||
|
||||
def on_delete_category_btn_click(self, category_id):
|
||||
self.category_id_to_delete = category_id
|
||||
self.page.show_dialog(self.delete_confirmation_dialog)
|
||||
self.page.update()
|
||||
|
||||
def confirm_delete_category(self, e):
|
||||
if self.category_id_to_delete:
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
|
||||
response = requests.delete(
|
||||
f'{base_url}/documents/categories/delete/{self.category_id_to_delete}',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
# Dacă categoria ștearsă este cea ale cărei documente sunt afișate, golim lista
|
||||
if self.current_category_id == self.category_id_to_delete:
|
||||
self.documents_list.controls = []
|
||||
self.documents_list.update()
|
||||
self.current_category_id = None
|
||||
|
||||
self.update_category_list()
|
||||
|
||||
self.category_id_to_delete = None
|
||||
self.page.pop_dialog()
|
||||
|
||||
def close_delete_dialog(self, e):
|
||||
self.category_id_to_delete = None
|
||||
self.page.pop_dialog()
|
||||
|
||||
def get_categories(self):
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
try:
|
||||
response = requests.get(
|
||||
f'{base_url}/documents/categories',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Error fetching categories: {e}")
|
||||
return []
|
||||
|
||||
def list_all_category_documents(self, category_id):
|
||||
self.current_category_id = category_id
|
||||
self.all_documents = self.get_all_documents(category_id) or []
|
||||
self.documents_list.controls = self.create_documents_list(
|
||||
self.all_documents,
|
||||
lambda doc: self.page.run_task(self.on_download_document_btn_click, doc),
|
||||
self.on_delete_document_btn_click
|
||||
)
|
||||
self.documents_list.update()
|
||||
|
||||
async def on_download_document_btn_click(self, document):
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
# Deschidem link-ul de download în browser
|
||||
# path în document este de forma "NumeCategorie/fisier.ext"
|
||||
download_url = f"{base_url}/documents/download?path={document['path']}&token={token}"
|
||||
await self.page.launch_url(download_url)
|
||||
|
||||
def on_delete_document_btn_click(self, doc_id):
|
||||
self.document_id_to_delete = doc_id
|
||||
self.page.show_dialog(self.delete_document_confirmation_dialog)
|
||||
self.page.update()
|
||||
|
||||
def confirm_delete_document(self, e):
|
||||
if self.document_id_to_delete:
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
|
||||
response = requests.delete(
|
||||
f'{base_url}/documents/standards/delete/{self.document_id_to_delete}',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
if hasattr(self, 'current_category_id'):
|
||||
self.list_all_category_documents(self.current_category_id)
|
||||
|
||||
self.document_id_to_delete = None
|
||||
self.page.pop_dialog()
|
||||
|
||||
def close_delete_document_dialog(self, e):
|
||||
self.document_id_to_delete = None
|
||||
self.page.pop_dialog()
|
||||
|
||||
def get_all_documents(self, category_id):
|
||||
base_url = self.page.session.store.get('api_base_url')
|
||||
token = self.page.session.store.get('token')
|
||||
try:
|
||||
response = requests.get(
|
||||
f'{base_url}/documents/standards/category/{category_id}',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Error fetching documents: {e}")
|
||||
return []
|
||||
|
||||
def create_documents_list(self, items, on_click_handler, on_click_handler2):
|
||||
"""Helper to create list items for a column."""
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item['name'])
|
||||
]
|
||||
),
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.DOWNLOAD,
|
||||
on_click=lambda e, id=item: on_click_handler(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.DELETE,
|
||||
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||
icon_color=ft.Colors.RED,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
expand=True,
|
||||
bgcolor=ft.Colors.BLUE_50,
|
||||
border = ft.Border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
ft.Button(
|
||||
"Adauga Categori",
|
||||
icon=ft.Icons.ADD,
|
||||
on_click=self.on_add_btn_click,
|
||||
width=300
|
||||
),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.CENTER
|
||||
),
|
||||
self.category_list
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.START,
|
||||
width = 350,
|
||||
),
|
||||
ft.VerticalDivider(width=1),
|
||||
ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.add_document
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.END
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
self.search_bar
|
||||
]
|
||||
),
|
||||
self.documents_list
|
||||
],
|
||||
expand=True
|
||||
)
|
||||
],
|
||||
),
|
||||
expand=True
|
||||
)
|
||||
351
client/pages/settings/payment_and_subscription.py
Normal file
351
client/pages/settings/payment_and_subscription.py
Normal file
@@ -0,0 +1,351 @@
|
||||
import flet as ft
|
||||
import requests
|
||||
from helpers.payment_type import PaymentType
|
||||
|
||||
class PaymentAndSubscription:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.base_url = self.page.session.store.get('api_base_url')
|
||||
self.token = self.page.session.store.get('token')
|
||||
self.selected_payment_id = None
|
||||
self.selected_sub_id = None
|
||||
|
||||
self.payment_type = [
|
||||
PaymentType().ONE_TIME_ONLY,
|
||||
PaymentType().SUBSCRIPTION.lower()
|
||||
]
|
||||
|
||||
# Pre-fetch data as in users.py
|
||||
self.all_payments = self.get_payments_data()
|
||||
self.all_subscriptions = self.get_subscriptions_data()
|
||||
|
||||
self.name = ft.TextField(label = "Denumire")
|
||||
self.amount = ft.TextField(label="Valoare", suffix="Lei")
|
||||
self.type = ft.RadioGroup(
|
||||
content=ft.Row(
|
||||
[ft.Radio(value=payment, label=payment.upper()) for payment in self.payment_type]
|
||||
)
|
||||
)
|
||||
self.error_text = ft.Text(color=ft.Colors.RED)
|
||||
|
||||
self.payments_list = ft.ListView(
|
||||
controls=self.create_payment_list(self.all_payments, self.on_edit_payment_click),
|
||||
spacing=10,
|
||||
expand=True,
|
||||
padding=10
|
||||
)
|
||||
|
||||
# Elemente pentru Abonamente
|
||||
self.sub_name = ft.TextField(label="Nume Abonament", width=350)
|
||||
self.payment_dropdown = ft.Dropdown(
|
||||
label="Selecteaza Plata",
|
||||
width=350,
|
||||
options=[
|
||||
ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)")
|
||||
for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower()
|
||||
]
|
||||
)
|
||||
self.months_dropdown = ft.Dropdown(
|
||||
label="Numar luni",
|
||||
width=350,
|
||||
options=[ft.dropdown.Option(str(i)) for i in range(1, 13)]
|
||||
)
|
||||
self.sub_error_text = ft.Text(color=ft.Colors.RED)
|
||||
self.subs_list = ft.ListView(
|
||||
controls=self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click),
|
||||
spacing=10,
|
||||
expand=True,
|
||||
padding=10
|
||||
)
|
||||
|
||||
self.add_payment_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Detalii Plata"),
|
||||
content=ft.Column(
|
||||
[
|
||||
self.name,
|
||||
self.amount,
|
||||
ft.Text("Tip plata:", weight=ft.FontWeight.BOLD),
|
||||
self.type,
|
||||
self.error_text
|
||||
],
|
||||
height=250,
|
||||
tight=True
|
||||
),
|
||||
actions=[
|
||||
ft.FilledButton("Salveaza", on_click=self.on_save_btn_click),
|
||||
ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY)
|
||||
]
|
||||
)
|
||||
|
||||
self.add_sub_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Detalii Abonament"),
|
||||
content=ft.Column(
|
||||
[
|
||||
self.sub_name,
|
||||
self.payment_dropdown,
|
||||
self.months_dropdown,
|
||||
self.sub_error_text
|
||||
],
|
||||
height=280,
|
||||
tight=True
|
||||
),
|
||||
actions=[
|
||||
ft.FilledButton("Salveaza", on_click=self.on_save_sub_click),
|
||||
ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY)
|
||||
]
|
||||
)
|
||||
|
||||
# --- LOGICA PLATI ---
|
||||
|
||||
def add_new_payment_btn_click(self, e):
|
||||
self.selected_payment_id = None
|
||||
self.name.value = ''
|
||||
self.amount.value = ''
|
||||
self.type.value = None
|
||||
self.error_text.value = ''
|
||||
self.add_payment_dialog.title = ft.Text("Adauga plata noua")
|
||||
self.page.show_dialog(self.add_payment_dialog)
|
||||
self.page.update()
|
||||
|
||||
def on_edit_payment_click(self, payment):
|
||||
self.selected_payment_id = payment['id']
|
||||
self.name.value = payment['name']
|
||||
self.amount.value = str(payment['amount'])
|
||||
self.type.value = payment['type']
|
||||
self.error_text.value = ''
|
||||
self.add_payment_dialog.title = ft.Text("Editeaza plata")
|
||||
self.page.show_dialog(self.add_payment_dialog)
|
||||
self.page.update()
|
||||
|
||||
def get_payments_data(self):
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.base_url}/payments/",
|
||||
headers={'Authorization': f'Bearer {self.token}'}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Error fetching payments: {e}")
|
||||
return []
|
||||
|
||||
def get_payments(self):
|
||||
self.all_payments = self.get_payments_data()
|
||||
self.payments_list.controls = self.create_payment_list(self.all_payments, self.on_edit_payment_click)
|
||||
if self.payments_list.page:
|
||||
self.payments_list.update()
|
||||
|
||||
# Actualizăm și opțiunile dropdown-ului pentru abonamente
|
||||
self.payment_dropdown.options = [
|
||||
ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)")
|
||||
for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower()
|
||||
]
|
||||
if self.payment_dropdown.page:
|
||||
self.payment_dropdown.update()
|
||||
|
||||
def create_payment_list(self, items, on_click_handler):
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Column(
|
||||
[
|
||||
ft.Text(p['name'], weight=ft.FontWeight.BOLD),
|
||||
ft.Text(f"{p['amount']} Lei - {p['type'].upper()}", size=12),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, payment=p: on_click_handler(payment)
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
bgcolor=ft.Colors.BLUE_50,
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
border=ft.Border.all(1, ft.Colors.GREY_300),
|
||||
ink=True
|
||||
)
|
||||
for p in items
|
||||
]
|
||||
|
||||
def on_save_btn_click(self, e):
|
||||
if not self.name.value or not self.amount.value or not self.type.value:
|
||||
self.error_text.value = "Toate campurile sunt obligatorii!"
|
||||
self.error_text.update()
|
||||
return
|
||||
|
||||
print(self.amount.value)
|
||||
|
||||
try:
|
||||
payload = {
|
||||
"name": self.name.value,
|
||||
"amount": float(self.amount.value),
|
||||
"type": self.type.value
|
||||
}
|
||||
|
||||
if self.selected_payment_id:
|
||||
# Update
|
||||
url = f"{self.base_url}/payments/update/{self.selected_payment_id}"
|
||||
response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
|
||||
else:
|
||||
# Create
|
||||
url = f"{self.base_url}/payments/add"
|
||||
response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
self.page.pop_dialog()
|
||||
self.get_payments()
|
||||
else:
|
||||
self.error_text.value = "Eroare la salvare"
|
||||
self.error_text.update()
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
self.error_text.value = "Valoarea trebuie sa fie un numar!"
|
||||
self.error_text.update()
|
||||
|
||||
# --- LOGICA ABONAMENTE ---
|
||||
|
||||
def add_new_sub_btn_click(self, e):
|
||||
self.selected_sub_id = None
|
||||
self.sub_name.value = ""
|
||||
# Resetăm dropdown-urile la starea default (fără selecție)
|
||||
self.payment_dropdown.value = ""
|
||||
self.months_dropdown.value = ""
|
||||
self.sub_error_text.value = ""
|
||||
self.add_sub_dialog.title = ft.Text("Adauga Abonament Nou")
|
||||
|
||||
# Forțăm afișarea dialogului cu valorile proaspăt resetate
|
||||
self.page.show_dialog(self.add_sub_dialog)
|
||||
self.page.update()
|
||||
|
||||
def on_edit_sub_click(self, sub):
|
||||
self.selected_sub_id = sub['id']
|
||||
self.sub_name.value = sub['name']
|
||||
self.payment_dropdown.value = str(sub['pay_and_subs_id'])
|
||||
self.months_dropdown.value = str(sub['mounts'])
|
||||
self.sub_error_text.value = ""
|
||||
self.add_sub_dialog.title = ft.Text("Editeaza Abonament")
|
||||
self.page.show_dialog(self.add_sub_dialog)
|
||||
self.page.update()
|
||||
|
||||
def get_subscriptions_data(self):
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.base_url}/subscriptions/",
|
||||
headers={'Authorization': f'Bearer {self.token}'}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Error fetching subscriptions: {e}")
|
||||
return []
|
||||
|
||||
def get_subscriptions(self):
|
||||
self.all_subscriptions = self.get_subscriptions_data()
|
||||
self.subs_list.controls = self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click)
|
||||
if self.subs_list.page:
|
||||
self.subs_list.update()
|
||||
|
||||
def create_subscription_list(self, items, on_click_handler):
|
||||
controls = []
|
||||
for s in items:
|
||||
# Gasim plata asociata pentru a calcula totalul
|
||||
payment = next((p for p in self.all_payments if p['id'] == s['pay_and_subs_id']), None)
|
||||
amount = payment['amount'] if payment else 0
|
||||
total = amount * (s['mounts'] or 0)
|
||||
controls.append(
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Column(
|
||||
[
|
||||
ft.Text(s['name'], weight=ft.FontWeight.BOLD),
|
||||
ft.Text(f"{s['mounts']} luni x {amount} Lei = {total} Lei Total", size=12, color=ft.Colors.BLUE_700),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, sub=s: on_click_handler(sub)
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
bgcolor=ft.Colors.GREEN_50,
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
border=ft.Border.all(1, ft.Colors.GREEN_200),
|
||||
ink=True
|
||||
)
|
||||
)
|
||||
return controls
|
||||
|
||||
def on_save_sub_click(self, e):
|
||||
if not self.sub_name.value or not self.payment_dropdown.value or not self.months_dropdown.value:
|
||||
self.sub_error_text.value = "Toate campurile sunt obligatorii!"
|
||||
self.sub_error_text.update()
|
||||
return
|
||||
|
||||
payload = {
|
||||
"name": self.sub_name.value,
|
||||
"pay_and_subs_id": int(self.payment_dropdown.value),
|
||||
"mounts": int(self.months_dropdown.value)
|
||||
}
|
||||
|
||||
if self.selected_sub_id:
|
||||
url = f"{self.base_url}/subscriptions/update/{self.selected_sub_id}"
|
||||
response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
|
||||
else:
|
||||
url = f"{self.base_url}/subscriptions/add"
|
||||
response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
self.page.pop_dialog()
|
||||
self.get_subscriptions()
|
||||
else:
|
||||
self.sub_error_text.value = "Eroare la salvare abonament"
|
||||
self.sub_error_text.update()
|
||||
|
||||
def on_cancel_btn_click(self, e):
|
||||
self.page.pop_dialog()
|
||||
|
||||
def build(self):
|
||||
|
||||
return ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
# Coloana Stanga: Plati
|
||||
ft.Column(
|
||||
[
|
||||
ft.Row([
|
||||
ft.Text("Configurare Plati", size=18, weight=ft.FontWeight.BOLD),
|
||||
ft.IconButton(ft.Icons.ADD_CIRCLE, on_click=self.add_new_payment_btn_click, icon_color=ft.Colors.BLUE)
|
||||
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
||||
ft.Divider(),
|
||||
self.payments_list
|
||||
],
|
||||
expand=1
|
||||
),
|
||||
ft.VerticalDivider(width=1),
|
||||
# Coloana Dreapta: Abonamente
|
||||
ft.Column(
|
||||
[
|
||||
ft.Row([
|
||||
ft.Text("Gestiune Abonamente", size=18, weight=ft.FontWeight.BOLD),
|
||||
ft.IconButton(ft.Icons.ADD_TASK, on_click=self.add_new_sub_btn_click, icon_color=ft.Colors.GREEN)
|
||||
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
||||
ft.Divider(),
|
||||
self.subs_list
|
||||
],
|
||||
expand=1
|
||||
)
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
expand=True,
|
||||
padding=20
|
||||
)
|
||||
77
client/pages/settings/settings.py
Normal file
77
client/pages/settings/settings.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import flet as ft
|
||||
from pages.settings.documente_juridice import DocumenteJuridice
|
||||
from pages.settings.users import UsersSettings
|
||||
from pages.settings.payment_and_subscription import PaymentAndSubscription
|
||||
|
||||
class Settings:
|
||||
def __init__(self, page: ft.Page, home):
|
||||
self.page = page
|
||||
self.home = home
|
||||
|
||||
self.doc_juridice = DocumenteJuridice(self.page)
|
||||
self.users_settings = UsersSettings(self.page)
|
||||
self.payment_and_subscription = PaymentAndSubscription(self.page)
|
||||
|
||||
def build(self):
|
||||
return ft.Tabs(
|
||||
selected_index=0,
|
||||
length=8,
|
||||
expand=True,
|
||||
content=ft.Column(
|
||||
expand=True,
|
||||
controls=[
|
||||
ft.TabBar(
|
||||
tabs=[
|
||||
ft.Tab(label="Documente Juridice Standard", icon=ft.Icons.BALANCE),
|
||||
ft.Tab(label="Articole si Publicatii", icon=ft.Icons.ARTICLE),
|
||||
ft.Tab(label="Comunicare", icon=ft.Icons.CHAT),
|
||||
ft.Tab(label="Consultanta", icon=ft.Icons.HANDSHAKE),
|
||||
ft.Tab(label="Convocator", icon=ft.Icons.BUSINESS),
|
||||
ft.Tab(label="Licitatii si Lucrari", icon=ft.Icons.ASSIGNMENT_TURNED_IN),
|
||||
ft.Tab(label="Abonamente si Plati", icon=ft.Icons.REPEAT_ON),
|
||||
ft.Tab(label="Utilizatori", icon=ft.Icons.ADMIN_PANEL_SETTINGS),
|
||||
]
|
||||
),
|
||||
ft.TabBarView(
|
||||
# expand=True,
|
||||
height=300,
|
||||
controls=[
|
||||
ft.Container(
|
||||
content=self.doc_juridice.build(),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
expand=True
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Text("This is Tab 2"),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Text("This is Tab 3"),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Text("This is Tab 4"),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Text("This is Tab 5"),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=ft.Text("This is Tab 6"),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=self.payment_and_subscription.build(),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
ft.Container(
|
||||
content=self.users_settings.build(),
|
||||
alignment=ft.Alignment.CENTER,
|
||||
),
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
256
client/pages/settings/users.py
Normal file
256
client/pages/settings/users.py
Normal file
@@ -0,0 +1,256 @@
|
||||
import flet as ft
|
||||
import requests
|
||||
from helpers.roles import Roles
|
||||
|
||||
import flet as ft
|
||||
|
||||
class UsersSettings:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.base_url = self.page.session.store.get('api_base_url')
|
||||
self.token = self.page.session.store.get('token')
|
||||
self.selected_user_id = None
|
||||
|
||||
self.user_roles = [
|
||||
'toti',
|
||||
Roles.USER,
|
||||
Roles.PROPRIETAR,
|
||||
Roles.CENZOR,
|
||||
Roles.ADMINISTRATOR,
|
||||
Roles.PRESEDINTE,
|
||||
Roles.EXPERT,
|
||||
Roles.BA,
|
||||
]
|
||||
|
||||
self.all_roles_list = ft.ListView(
|
||||
controls=self.create_list(self.user_roles, self.on_role_btn_click),
|
||||
spacing=10,
|
||||
width=350
|
||||
)
|
||||
self.all_users = self.get_all_users()
|
||||
self.role_users = ft.ListView(
|
||||
controls=self.create_users_list(self.all_users, self.on_user_btn_click),
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.placeholder = ft.Container(
|
||||
margin=ft.Margin.only(top=5),
|
||||
content=self.role_users,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.email = ft.TextField(label="Email", read_only=True, expand=True)
|
||||
self.first_name = ft.TextField(label="Prenume", expand=True)
|
||||
self.last_name = ft.TextField(label = "Nume", expand=True)
|
||||
self.address = ft.TextField(label="Adresa", expand=True)
|
||||
self.profession = ft.TextField(label="Profesie", expand=True)
|
||||
self.role = ft.RadioGroup(
|
||||
content=ft.Row(
|
||||
[ft.Radio(value=role, label=role.upper()) for role in self.user_roles if role != "toti"]
|
||||
)
|
||||
)
|
||||
self.status = ft.TextField(label="Status", expand=True)
|
||||
self.profile_pic = ft.TextField(label="Poza profil", read_only=True, expand=True)
|
||||
self.created_at = ft.TextField(label="Data creare cont",read_only=True, expand=True)
|
||||
self.active = ft.TextField(label="Active: 0-Nu, 1-Da", expand=True)
|
||||
self.error = ft.Text(color=ft.Colors.RED)
|
||||
|
||||
self.user_details = ft.Column(
|
||||
[
|
||||
ft.Text("Detalii utilizator", weight=ft.FontWeight.BOLD),
|
||||
self.email,
|
||||
self.first_name,
|
||||
self.last_name,
|
||||
self.address,
|
||||
self.profession,
|
||||
ft.Text("Rol:", weight=ft.FontWeight.BOLD),
|
||||
self.role,
|
||||
#self.status,
|
||||
#self.profile_pic,
|
||||
self.active,
|
||||
self.created_at,
|
||||
self.error,
|
||||
ft.Row(
|
||||
[
|
||||
ft.FilledButton("Salveaza", on_click=self.on_save_btn_click)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.CENTER
|
||||
),
|
||||
ft.Text()
|
||||
],
|
||||
scroll=ft.ScrollMode.ADAPTIVE
|
||||
)
|
||||
|
||||
self.search_bar = ft.TextField(
|
||||
label="Cauta",
|
||||
on_submit=self.on_search_bar_submit,
|
||||
expand=True
|
||||
)
|
||||
|
||||
def on_role_btn_click(self, role):
|
||||
self.placeholder.content = self.role_users
|
||||
self.placeholder.update()
|
||||
self.role_users.controls.clear()
|
||||
users = self.users_by_role(role) if role != 'toti' else self.all_users
|
||||
self.role_users.controls = self.create_users_list(users, self.on_user_btn_click)
|
||||
self.role_users.update()
|
||||
|
||||
def on_user_btn_click(self, user):
|
||||
self.selected_user_id = user['id']
|
||||
self.email.value = user['email']
|
||||
self.first_name.value = user['first_name']
|
||||
self.last_name.value = user['last_name']
|
||||
self.address.value = user['address']
|
||||
self.profession.value = user['profession']
|
||||
self.role.value = user['role']
|
||||
self.status.value = user['status']
|
||||
self.profile_pic.value = user['profile_pic']
|
||||
self.active.value = str(user['active'])
|
||||
self.created_at.value = user['created_at']
|
||||
self.error.value = ""
|
||||
self.placeholder.content = self.user_details
|
||||
self.placeholder.update()
|
||||
|
||||
def create_list(self, items, on_click_handler):
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item.upper())
|
||||
]
|
||||
),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
expand=True,
|
||||
bgcolor=ft.Colors.BLUE_50,
|
||||
border = ft.Border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
ink=True,
|
||||
on_click=lambda e, cid=item: on_click_handler(cid)
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def create_users_list(self, items, on_click_handler):
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item['email'])
|
||||
]
|
||||
),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
expand=True,
|
||||
bgcolor=ft.Colors.BLUE_50,
|
||||
border = ft.Border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
ink=True,
|
||||
on_click=lambda e, cid=item: on_click_handler(cid)
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def get_all_users(self):
|
||||
payload = {}
|
||||
response = requests.get(
|
||||
f"{self.base_url}/users/",
|
||||
json=payload,
|
||||
headers={'Authorization': f'Bearer {self.token}'}
|
||||
)
|
||||
print(response.text)
|
||||
return response.json()
|
||||
|
||||
def users_by_role(self, role):
|
||||
users = []
|
||||
for user in self.all_users:
|
||||
if user['role']==role:
|
||||
users.append(user)
|
||||
print(users)
|
||||
return users
|
||||
|
||||
def on_save_btn_click(self, e):
|
||||
if self.selected_user_id is None:
|
||||
return
|
||||
|
||||
payload = {
|
||||
"first_name": self.first_name.value,
|
||||
"last_name": self.last_name.value,
|
||||
"address": self.address.value,
|
||||
"profession": self.profession.value,
|
||||
"role": self.role.value,
|
||||
"status": self.status.value,
|
||||
"active": int(self.active.value) if str(self.active.value).isdigit() else 1
|
||||
}
|
||||
|
||||
response = requests.put(
|
||||
f"{self.base_url}/users/update/{self.selected_user_id}",
|
||||
json=payload,
|
||||
headers={'Authorization': f'Bearer {self.token}'}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
self.error.value = "Modificări salvate cu succes!"
|
||||
self.error.color = ft.Colors.GREEN
|
||||
self.all_users = self.get_all_users() # Refresh lista locală
|
||||
else:
|
||||
self.error.value = response.json().get("error", "Eroare la salvarea datelor")
|
||||
self.error.color = ft.Colors.RED
|
||||
|
||||
self.error.update()
|
||||
|
||||
def on_search_bar_submit(self, e):
|
||||
search = self.search_bar.value
|
||||
self.placeholder.content = self.role_users
|
||||
self.placeholder.update()
|
||||
self.role_users.controls.clear()
|
||||
users = [user for user in self.all_users if search in user['email']]
|
||||
self.role_users.controls = self.create_users_list(users, self.on_user_btn_click)
|
||||
self.role_users.update()
|
||||
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.all_roles_list,
|
||||
ft.VerticalDivider(width=1),
|
||||
ft.Container(
|
||||
content = ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.search_bar
|
||||
]
|
||||
),
|
||||
#ft.Divider(height=1),
|
||||
self.placeholder
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
padding=5,
|
||||
expand=True
|
||||
)
|
||||
],
|
||||
expand=True
|
||||
)
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
expand=True
|
||||
)
|
||||
Reference in New Issue
Block a user