User info widgets

This commit is contained in:
StNicolay 2024-08-09 22:50:20 +03:00
parent cb3b5a3c27
commit b0f20680b4
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
4 changed files with 162 additions and 13 deletions

View File

@ -1,5 +1,7 @@
from __future__ import annotations from __future__ import annotations
import dataclasses
import user
import datetime import datetime
import os import os
import uuid import uuid
@ -17,7 +19,9 @@ from PyQt6.QtGui import (
QIcon, QIcon,
) )
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QFileDialog,
QHBoxLayout, QHBoxLayout,
QLabel,
QListWidget, QListWidget,
QListWidgetItem, QListWidgetItem,
QMenu, QMenu,
@ -25,8 +29,6 @@ from PyQt6.QtWidgets import (
QPushButton, QPushButton,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
QLabel,
QFileDialog,
) )
from request_client import RequestClient from request_client import RequestClient
@ -273,26 +275,67 @@ class Sidebar(QWidget):
super().__init__() super().__init__()
self.state = state self.state = state
self.file_list = file_list self.file_list = file_list
self.user_widget = None
layout = QVBoxLayout() layout = QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
# Add your sidebar buttons here buttons = [
for i in range(5): # Example buttons ("User info", self.get_user),
btn = QPushButton(f"Button {i+1}") ("Log out", self.logout),
layout.addWidget(btn) ("Go back", self.go_back),
("Go root", self.go_root),
("Get permitted", self.get_tlp),
("Sync", self.sync),
]
for text, func in buttons:
button = QPushButton(text)
button.clicked.connect(func)
layout.addWidget(button)
layout.addStretch() layout.addStretch()
def get_user(self): ... def get_user(self):
self.user_widget = user.UserWidget(self.state)
self.user_widget.show()
def logout(self): ... def logout(self):
self.state.logout()
def go_back(self): ... def go_back(self):
if len(self.file_list.responses) >= 2:
self.file_list.responses.pop()
self.file_list.update()
def go_root(self): ... def go_root(self):
self.file_list.responses.append(ListResponse.get())
self.file_list.update()
def get_tlp(self): def get_tlp(self):
"""Get top level permitted folders""" """Get top level permitted folders"""
self.file_list.responses.append(TlpResponse.get())
self.file_list.update()
def sync(self): ... def sync(self):
# TODO
...
@dataclasses.dataclass(slots=True)
class TlpResponse:
folders: list[Folder]
@staticmethod
def get() -> Self:
url = "/permissions/get_top_level_permitted_folders"
return TlpResponse(
pydantic.TypeAdapter(list[Folder]).validate_json(
RequestClient().client.get(url).text
)
)
def items(self) -> list[DisplayProtocol]:
return self.folders
def update(self) -> ResponseProtocol:
return self.get()
class MainFileWidget(QWidget): class MainFileWidget(QWidget):

View File

@ -19,6 +19,10 @@ class RequestClient:
def set_token(cls, token: str): def set_token(cls, token: str):
cls._client.headers = {"Authorization": f"Bearer {token}"} cls._client.headers = {"Authorization": f"Bearer {token}"}
@classmethod
def delete_token(cls):
cls._client.headers = {}
@property @property
def client(self) -> httpx.Client: def client(self) -> httpx.Client:
return self._client return self._client

View File

@ -27,8 +27,8 @@ class State(QMainWindow):
password = keyring.get_credential("auth_app", "access_token") password = keyring.get_credential("auth_app", "access_token")
if password is None: if password is None:
self.switch_to_login() # Start with the login widget self.switch_to_login() # Start with the login widget
else:
self.login(password.password) self.login(password.password)
def switch_to_login(self): def switch_to_login(self):
self.stack.setCurrentWidget(self.login_widget) self.stack.setCurrentWidget(self.login_widget)
@ -42,3 +42,8 @@ class State(QMainWindow):
self.file_widget = file_widgets.MainFileWidget(self) self.file_widget = file_widgets.MainFileWidget(self)
self.stack.addWidget(self.file_widget) self.stack.addWidget(self.file_widget)
self.stack.setCurrentWidget(self.file_widget) self.stack.setCurrentWidget(self.file_widget)
def logout(self):
keyring.delete_password("auth_app", "access_token")
request_client.RequestClient().delete_token()
self.switch_to_login()

97
desktop_client/user.py Normal file
View File

@ -0,0 +1,97 @@
from __future__ import annotations
import pydantic
import state
from PyQt6.QtWidgets import (
QWidget,
QLineEdit,
QLabel,
QVBoxLayout,
QPushButton,
QHBoxLayout,
QMessageBox,
)
from request_client import RequestClient
class User(pydantic.BaseModel):
user_id: int | None = None
username: str
email: str
@staticmethod
def get(user_id: int | None = None) -> User:
params = {}
if user_id:
url = "/users"
params["user_id"] = user_id
else:
url = "/users/current"
return User.model_validate_json(
RequestClient().client.get(url, params=params).text
)
@staticmethod
def delete():
if not RequestClient().client.delete("/users").is_success:
raise Exception("Error deleting user")
def put(self):
response = RequestClient().client.put(
"/users", json={"username": self.username, "email": self.email}
)
if not response.is_success:
QMessageBox.warning(None, "Error updating user", response.text)
return
QMessageBox.information(None, "User updated", "User updated")
class UserSearch(User):
similarity: float
@staticmethod
def search(search_str: str) -> list[UserSearch]:
return pydantic.TypeAdapter(list[UserSearch]).validate_json(
RequestClient()
.client.get("/users/search", params={"search_string": search_str})
.text
)
class UserWidget(QWidget):
def __init__(self, state: state.State):
super().__init__()
self.state = state
self.setWindowTitle("User information")
self.user = User.get()
main_layout = QVBoxLayout()
lines = [("username", self.user.username), ("email", self.user.email)]
edits = []
for line in lines:
layout = QHBoxLayout()
label = QLabel(line[0])
edit = QLineEdit(line[1])
layout.addWidget(label)
layout.addWidget(edit)
main_layout.addLayout(layout)
edits.append(edit)
self.username: QLineEdit = edits[0]
self.email: QLineEdit = edits[1]
button_layout = QHBoxLayout()
buttons = [("Update", self.update_user), ("Delete", self.delete_user)]
for text, func in buttons:
button = QPushButton(text)
button.clicked.connect(func)
button_layout.addWidget(button)
main_layout.addLayout(button_layout)
self.setLayout(main_layout)
def delete_user(self):
User.delete()
self.close()
self.state.logout()
def update_user(self):
self.user.username = self.username.text()
self.user.email = self.email.text()
self.user.put()