Compare commits

..

No commits in common. "37940d633a79bcc7b4c0577d35bb8013bb51c1bb" and "654a1e7191123ffa4d289fa9a0fc08d4d9fac030" have entirely different histories.

5 changed files with 30 additions and 229 deletions

View File

@ -1,37 +0,0 @@
from __future__ import annotations
import uuid
import file_widgets
from PyQt6.QtWidgets import QLineEdit, QMessageBox, QPushButton, QVBoxLayout, QWidget
from request_client import RequestClient
class CreateFolderWidget(QWidget):
def __init__(self, folder_id: uuid.UUID, file_list: file_widgets.FileListWidget):
super().__init__()
self.folder_id = folder_id
self.file_list = file_list
self.setWindowTitle("Folder creation")
layout = QVBoxLayout()
self.edit = QLineEdit()
layout.addWidget(self.edit)
button = QPushButton("Submit")
button.clicked.connect(self.submit)
layout.addWidget(button)
self.setLayout(layout)
def submit(self):
response = RequestClient().client.post(
"/folders",
json={
"folder_name": self.edit.text(),
"parent_folder_id": str(self.folder_id),
},
)
if not response.is_success:
QMessageBox.warning(None, "Error creating folder", response.text)
else:
QMessageBox.information(None, "Folder created", "Folder created")
self.file_list.update_response()
self.close()

View File

@ -1,22 +1,23 @@
from __future__ import annotations from __future__ import annotations
import dataclasses
import datetime import datetime
import os import os
import uuid import uuid
from typing import Protocol, Self from typing import Protocol, Self
import create_folder_widget
import httpx import httpx
import pydantic import pydantic
import state import state
import user
from PyQt6.QtCore import QPoint, Qt from PyQt6.QtCore import QPoint, Qt
from PyQt6.QtGui import QAction, QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon from PyQt6.QtGui import (
QAction,
QDragEnterEvent,
QDragMoveEvent,
QDropEvent,
QIcon,
)
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QFileDialog,
QHBoxLayout, QHBoxLayout,
QLabel,
QListWidget, QListWidget,
QListWidgetItem, QListWidgetItem,
QMenu, QMenu,
@ -24,6 +25,8 @@ from PyQt6.QtWidgets import (
QPushButton, QPushButton,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
QLabel,
QFileDialog,
) )
from request_client import RequestClient from request_client import RequestClient
@ -57,15 +60,15 @@ class File(pydantic.BaseModel):
return self.file_name return self.file_name
def delete(self) -> None: def delete(self) -> None:
RequestClient().client.delete("/files", params={"file_id": self.file_id}) RequestClient().client.delete(
"/files", params={"file_id": self.file_id}
)
def details(self, list: FileListWidget) -> QWidget: def details(self, list: FileListWidget) -> QWidget:
del list del list
file_size = self._format_bytes(self.file_size)
file_size_text = f"{file_size[0]:.2f} {file_size[1]}"
details = ( details = (
f"file id: {self.file_id}\nfile_name: {self.file_name}\n" f"file id: {self.file_id}\nfile_name: {self.file_name}\n"
+ f"file_size: {file_size_text}\n" + f"file_size: {self._format_bytes(self.file_size)}\n"
+ f"created at: {self.created_at}\nupdated at: {self.updated_at}" + f"created at: {self.created_at}\nupdated at: {self.updated_at}"
) )
label = QLabel() label = QLabel()
@ -77,7 +80,7 @@ class File(pydantic.BaseModel):
def _format_bytes(size: int): def _format_bytes(size: int):
power = 2**10 power = 2**10
n = 0 n = 0
power_labels = {0: "", 1: "kibi", 2: "mebi", 3: "gibi", 4: "tebi"} power_labels = {0: "", 1: "kilo", 2: "mega", 3: "giga", 4: "tera"}
while size > power and n < 4: while size > power and n < 4:
size /= power size /= power
n += 1 n += 1
@ -114,10 +117,8 @@ class Folder(pydantic.BaseModel):
return self.folder_name return self.folder_name
def delete(self) -> None: def delete(self) -> None:
print( RequestClient().client.delete(
RequestClient() "/folders", params={"folder_id": self.folder_id}
.client.delete("/folders", params={"folder_id": self.folder_id})
.text
) )
def details(self, list: FileListWidget) -> QWidget: def details(self, list: FileListWidget) -> QWidget:
@ -139,9 +140,6 @@ class ResponseProtocol(Protocol):
def update(self) -> ResponseProtocol: def update(self) -> ResponseProtocol:
raise NotImplementedError raise NotImplementedError
def create_folder(self) -> QWidget | None:
raise NotImplementedError
class ListResponse(pydantic.BaseModel): class ListResponse(pydantic.BaseModel):
folder_id: uuid.UUID folder_id: uuid.UUID
@ -163,32 +161,6 @@ class ListResponse(pydantic.BaseModel):
def update(self) -> ResponseProtocol: def update(self) -> ResponseProtocol:
return self.get(self.folder_id) return self.get(self.folder_id)
def create_folder(self, file_list: FileListWidget):
return create_folder_widget.CreateFolderWidget(self.folder_id, file_list)
@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()
def create_folder(self):
return # Not much to do
class FileListWidget(QListWidget): class FileListWidget(QListWidget):
def __init__(self, state: state.State): def __init__(self, state: state.State):
@ -241,7 +213,9 @@ class FileListWidget(QListWidget):
response = RequestClient().client.post( response = RequestClient().client.post(
"http://localhost:3000/files", "http://localhost:3000/files",
files=files, files=files,
params={"parent_folder": self.current_response().folder_id}, params={
"parent_folder": self.current_response().folder_id
},
) )
if response.is_success: if response.is_success:
QMessageBox.information( QMessageBox.information(
@ -297,56 +271,26 @@ 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
self.folder_widget = None
layout = QVBoxLayout() layout = QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
buttons = [ # Add your sidebar buttons here
("User info", self.get_user), for i in range(5): # Example buttons
("Log out", self.logout), btn = QPushButton(f"Button {i+1}")
("Go back", self.go_back), layout.addWidget(btn)
("Go root", self.go_root),
("Get permitted", self.get_tlp),
("Sync", self.sync),
("Create folder", self.create_folder),
]
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
...
def create_folder(self):
self.folder_widget = self.file_list.current_response().create_folder(
self.file_list
)
if self.folder_widget is not None:
self.folder_widget.show()
class MainFileWidget(QWidget): class MainFileWidget(QWidget):

View File

@ -19,10 +19,6 @@ 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,8 +42,3 @@ 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()

View File

@ -1,97 +0,0 @@
from __future__ import annotations
import pydantic
import state
from PyQt6.QtWidgets import (
QHBoxLayout,
QLabel,
QLineEdit,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
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()