generated from dopt-python/py311
Dev #7
@@ -4,12 +4,17 @@ import dataclasses as dc
|
|||||||
import enum
|
import enum
|
||||||
import uuid
|
import uuid
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from typing import Any, Final
|
from typing import TYPE_CHECKING, Any, Final, Generic, TypeVar
|
||||||
|
|
||||||
import babel
|
import babel
|
||||||
|
|
||||||
from wce_crm.custom_widget_registry import CUSTOM_WIDGET_NAMES
|
from wce_crm.custom_widget_registry import CUSTOM_WIDGET_NAMES
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from PySide6.QtWidgets import QWidget
|
||||||
|
|
||||||
|
T = TypeVar("T", bound="QWidget")
|
||||||
|
|
||||||
|
|
||||||
class FormFieldType(enum.StrEnum):
|
class FormFieldType(enum.StrEnum):
|
||||||
GROUP = enum.auto()
|
GROUP = enum.auto()
|
||||||
@@ -31,7 +36,7 @@ class FormFieldType(enum.StrEnum):
|
|||||||
|
|
||||||
|
|
||||||
@dc.dataclass(slots=True)
|
@dc.dataclass(slots=True)
|
||||||
class FormField:
|
class FormField(Generic[T]):
|
||||||
label: str
|
label: str
|
||||||
type: FormFieldType
|
type: FormFieldType
|
||||||
children: Sequence[FormField] = dc.field(default_factory=list)
|
children: Sequence[FormField] = dc.field(default_factory=list)
|
||||||
|
|||||||
+118
-51
@@ -12,7 +12,17 @@ from collections import defaultdict
|
|||||||
from collections.abc import Container, Iterable, Sequence
|
from collections.abc import Container, Iterable, Sequence
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import TYPE_CHECKING, Any, Final, Protocol, TypeAlias, TypedDict, TypeVar, cast
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
Final,
|
||||||
|
Literal,
|
||||||
|
Protocol,
|
||||||
|
TypeAlias,
|
||||||
|
TypedDict,
|
||||||
|
TypeVar,
|
||||||
|
cast,
|
||||||
|
)
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
|
||||||
from dopt_basics import datetime as dopt_dt
|
from dopt_basics import datetime as dopt_dt
|
||||||
@@ -92,6 +102,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
K = TypeVar("K")
|
K = TypeVar("K")
|
||||||
V = TypeVar("V")
|
V = TypeVar("V")
|
||||||
|
T = TypeVar("T", bound="QWidget")
|
||||||
|
|
||||||
|
|
||||||
DEBUG: bool = True
|
DEBUG: bool = True
|
||||||
@@ -274,7 +285,7 @@ class CustomWidget(QWidget):
|
|||||||
|
|
||||||
|
|
||||||
def _add_widget_to_layout(
|
def _add_widget_to_layout(
|
||||||
form_field: FormField,
|
form_field: FormField[T],
|
||||||
widget: QWidget,
|
widget: QWidget,
|
||||||
target_layout: QLayout,
|
target_layout: QLayout,
|
||||||
widget_only: bool = False,
|
widget_only: bool = False,
|
||||||
@@ -299,10 +310,10 @@ def _add_widget_to_layout(
|
|||||||
|
|
||||||
|
|
||||||
def build_and_add_widget(
|
def build_and_add_widget(
|
||||||
form_field: FormField,
|
form_field: FormField[T],
|
||||||
parent_layout: QLayout,
|
parent_layout: QLayout,
|
||||||
prefix: str = "",
|
prefix: str = "",
|
||||||
) -> tuple[str, QWidget]:
|
) -> tuple[str, T]:
|
||||||
no_scroll_filter = NoScrollFilter(parent_layout)
|
no_scroll_filter = NoScrollFilter(parent_layout)
|
||||||
if prefix and form_field.key:
|
if prefix and form_field.key:
|
||||||
full_key = f"{prefix}{COLUMN_SEP}{form_field.key}" if prefix else form_field.key
|
full_key = f"{prefix}{COLUMN_SEP}{form_field.key}" if prefix else form_field.key
|
||||||
@@ -311,7 +322,6 @@ def build_and_add_widget(
|
|||||||
else:
|
else:
|
||||||
full_key = form_field.key
|
full_key = form_field.key
|
||||||
|
|
||||||
widget: QWidget
|
|
||||||
layout_widget_only: bool = False
|
layout_widget_only: bool = False
|
||||||
install_no_scroll_filter: bool = True
|
install_no_scroll_filter: bool = True
|
||||||
|
|
||||||
@@ -496,7 +506,7 @@ def build_and_add_widget(
|
|||||||
|
|
||||||
_add_widget_to_layout(form_field, widget, parent_layout, widget_only=layout_widget_only)
|
_add_widget_to_layout(form_field, widget, parent_layout, widget_only=layout_widget_only)
|
||||||
|
|
||||||
return full_key, widget
|
return full_key, cast(T, widget)
|
||||||
|
|
||||||
|
|
||||||
def _build_ui_recursively(
|
def _build_ui_recursively(
|
||||||
@@ -711,13 +721,59 @@ def get_form_data(
|
|||||||
ignored_keys.append(key)
|
ignored_keys.append(key)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if form_field.type is FormFieldType.TEXT_DATE:
|
||||||
|
value = get_widget_value(widget, "date")
|
||||||
|
elif form_field.type is FormFieldType.TEXT_DATETIME:
|
||||||
|
value = get_widget_value(widget, "datetime")
|
||||||
|
else:
|
||||||
|
value = get_widget_value(widget)
|
||||||
|
|
||||||
|
# elif isinstance(widget, QDateEdit):
|
||||||
|
# qt_date = widget.date()
|
||||||
|
# value = qt_date.toPython()
|
||||||
|
# elif isinstance(widget, FlexibleDateInput):
|
||||||
|
# value = widget.get_pydate()
|
||||||
|
# elif isinstance(widget, FlexibleDateTimeInput):
|
||||||
|
# value = widget.get_pydatetime()
|
||||||
|
# elif isinstance(widget, QComboBox):
|
||||||
|
# value = widget.currentData()
|
||||||
|
# elif isinstance(
|
||||||
|
# widget,
|
||||||
|
# (
|
||||||
|
# DynamicListWidget,
|
||||||
|
# DynamicDropdownWidgetNumeric,
|
||||||
|
# DynamicDropdownWidgetOption,
|
||||||
|
# CustomWidget,
|
||||||
|
# ),
|
||||||
|
# ):
|
||||||
|
# # this is a special data structure with some assumptions of the widget's internals
|
||||||
|
# # DynamicListWidget: this is a list -> each dynamic list contains a list
|
||||||
|
# # of such dictionaries (handled below)
|
||||||
|
# value = widget.get_form_data()
|
||||||
|
|
||||||
|
if isinstance(value, dict):
|
||||||
|
raw_data.update(value)
|
||||||
|
else:
|
||||||
|
raw_data[key] = value
|
||||||
|
|
||||||
|
logger_get_data.debug("[base:get_form_data]>>>>> RAW DATA:\n%s", pformat(raw_data))
|
||||||
|
|
||||||
|
return raw_data
|
||||||
|
|
||||||
|
|
||||||
|
def get_widget_value(
|
||||||
|
widget: QWidget,
|
||||||
|
text_type: Literal["default", "date", "datetime"] = "default",
|
||||||
|
) -> Any:
|
||||||
|
value: Any | None = None
|
||||||
|
|
||||||
if isinstance(widget, QLineEdit):
|
if isinstance(widget, QLineEdit):
|
||||||
data = widget.text()
|
data = widget.text()
|
||||||
if data != "":
|
if data != "":
|
||||||
value = data
|
value = data
|
||||||
if form_field.type is FormFieldType.TEXT_DATE:
|
if text_type == "date":
|
||||||
value = datetime.datetime.strptime(value, DATE_FMT).date()
|
value = datetime.datetime.strptime(value, DATE_FMT).date()
|
||||||
elif form_field.type is FormFieldType.TEXT_DATETIME:
|
elif text_type == "datetime":
|
||||||
value = datetime.datetime.strptime(value, DATETIME_FMT)
|
value = datetime.datetime.strptime(value, DATETIME_FMT)
|
||||||
elif isinstance(widget, QPlainTextEdit):
|
elif isinstance(widget, QPlainTextEdit):
|
||||||
data = widget.toPlainText()
|
data = widget.toPlainText()
|
||||||
@@ -746,14 +802,7 @@ def get_form_data(
|
|||||||
# of such dictionaries (handled below)
|
# of such dictionaries (handled below)
|
||||||
value = widget.get_form_data()
|
value = widget.get_form_data()
|
||||||
|
|
||||||
if isinstance(value, dict):
|
return value
|
||||||
raw_data.update(value)
|
|
||||||
else:
|
|
||||||
raw_data[key] = value
|
|
||||||
|
|
||||||
logger_get_data.debug("[base:get_form_data]>>>>> RAW DATA:\n%s", pformat(raw_data))
|
|
||||||
|
|
||||||
return raw_data
|
|
||||||
|
|
||||||
|
|
||||||
def set_widget_value(
|
def set_widget_value(
|
||||||
@@ -3301,17 +3350,19 @@ class Session:
|
|||||||
|
|
||||||
@dc.dataclass(slots=True)
|
@dc.dataclass(slots=True)
|
||||||
class Page_Consulting_ConsultingSession_State:
|
class Page_Consulting_ConsultingSession_State:
|
||||||
user_id: UserId # must be set with the session (always known)
|
nutzer_id: UserId # must be set with the session (always known)
|
||||||
user_name: str # must be set with the session (always known)
|
nutzer_name: str # must be set with the session (always known)
|
||||||
cons_session_id: int | None = None # known and not known entries
|
beratung_id: int | None = None # known and not known entries
|
||||||
timestamp: datetime.datetime = dc.field(
|
zeitstempel: datetime.datetime = dc.field(
|
||||||
default_factory=lambda: datetime.datetime.now(tz=datetime.UTC)
|
default_factory=lambda: datetime.datetime.now(tz=datetime.UTC)
|
||||||
)
|
)
|
||||||
partner: str = ""
|
ansprechpartner: str | None = None
|
||||||
interaction_scheme: str = "" # set string like in other dropdowns or use integer (enum)
|
interaction_scheme: str | None = None
|
||||||
topic: str = "" # TODO should be linked to something, target unclear (need specification by customer)
|
topic: str | None = (
|
||||||
notes: str = ""
|
None # TODO should be linked to something, target unclear (need specification by customer)
|
||||||
response: str = ""
|
)
|
||||||
|
anmerkungen: str | None = None
|
||||||
|
rueckmeldung: str | None = None
|
||||||
|
|
||||||
|
|
||||||
@dc.dataclass(slots=True)
|
@dc.dataclass(slots=True)
|
||||||
@@ -3614,23 +3665,38 @@ class Page_Consulting_ConsultingSession(QWidget):
|
|||||||
layout.setAlignment(Qt.AlignmentFlag.AlignVCenter)
|
layout.setAlignment(Qt.AlignmentFlag.AlignVCenter)
|
||||||
ROW_HEIGHT = 70
|
ROW_HEIGHT = 70
|
||||||
|
|
||||||
self.user_field = QLineEdit(
|
user_field_def = FormField[QLineEdit](
|
||||||
placeholderText="wird über aktiven Nutzer bei Anlage gesetzt"
|
"",
|
||||||
|
FormFieldType.TEXT,
|
||||||
|
readonly=True,
|
||||||
|
placeholder="wird über aktiven Nutzer bei Anlage gesetzt",
|
||||||
)
|
)
|
||||||
self.user_field.setReadOnly(True)
|
_, self.user_field = build_and_add_widget(user_field_def, layout)
|
||||||
self.user_field.setProperty("styleClass", "stempel")
|
|
||||||
# ?? date or datetime?
|
# ?? date or datetime?
|
||||||
# self.timestamp = FlexibleDateInput()
|
timestamp_def = FormField[FlexibleDateTimeInput]("", FormFieldType.DATETIME_FLEXIBLE)
|
||||||
# self.timestamp.set_pydate(datetime.datetime.now())
|
_, self.timestamp = build_and_add_widget(timestamp_def, layout)
|
||||||
self.timestamp = FlexibleDateTimeInput()
|
|
||||||
self.timestamp.set_pydatetime(datetime.datetime.now())
|
self.timestamp.set_pydatetime(datetime.datetime.now())
|
||||||
|
|
||||||
self.contact = QLineEdit(placeholderText="Freitext")
|
contact_def = FormField[QLineEdit]("", FormFieldType.TEXT, placeholder="Freitext")
|
||||||
self.contact_type = QLineEdit(placeholderText="sollte Dropdown sein") # Dropdown
|
_, self.contact = build_and_add_widget(contact_def, layout)
|
||||||
self.crm_link = QLineEdit(placeholderText="CRM Links")
|
|
||||||
|
|
||||||
self.plain_text = QPlainTextEdit()
|
contact_type_def = FormField[QComboBox](
|
||||||
self.response = QPlainTextEdit()
|
"",
|
||||||
|
FormFieldType.DROPDOWN,
|
||||||
|
placeholder="sollte Dropdown sein",
|
||||||
|
options=[("Persönlich", None), ("Telefon", None), ("Mail", None)],
|
||||||
|
)
|
||||||
|
_, self.contact_type = build_and_add_widget(contact_type_def, layout)
|
||||||
|
|
||||||
|
crm_link_def = FormField[QLineEdit]("", FormFieldType.TEXT, placeholder="CRM Links")
|
||||||
|
_, self.crm_link = build_and_add_widget(crm_link_def, layout)
|
||||||
|
|
||||||
|
plain_text_def = FormField[QPlainTextEdit]("", FormFieldType.LONGTEXT)
|
||||||
|
_, self.plain_text = build_and_add_widget(plain_text_def, layout)
|
||||||
|
|
||||||
|
response_def = FormField[QPlainTextEdit]("", FormFieldType.LONGTEXT)
|
||||||
|
_, self.response = build_and_add_widget(response_def, layout)
|
||||||
|
|
||||||
self.btn_delete = QPushButton("✕")
|
self.btn_delete = QPushButton("✕")
|
||||||
self.btn_delete.setFlat(True) # Entfernt den blockigen Rahmen
|
self.btn_delete.setFlat(True) # Entfernt den blockigen Rahmen
|
||||||
@@ -3639,6 +3705,7 @@ class Page_Consulting_ConsultingSession(QWidget):
|
|||||||
self.btn_delete.setStyleSheet("color: #cc0000; font-weight: bold;")
|
self.btn_delete.setStyleSheet("color: #cc0000; font-weight: bold;")
|
||||||
self.btn_delete.clicked.connect(lambda: self.delete_request.emit(self))
|
self.btn_delete.clicked.connect(lambda: self.delete_request.emit(self))
|
||||||
self.btn_delete.setFixedWidth(30)
|
self.btn_delete.setFixedWidth(30)
|
||||||
|
layout.addWidget(self.btn_delete)
|
||||||
|
|
||||||
widgets = (
|
widgets = (
|
||||||
self.user_field,
|
self.user_field,
|
||||||
@@ -3652,7 +3719,7 @@ class Page_Consulting_ConsultingSession(QWidget):
|
|||||||
)
|
)
|
||||||
for widget in widgets:
|
for widget in widgets:
|
||||||
widget.setFixedHeight(ROW_HEIGHT)
|
widget.setFixedHeight(ROW_HEIGHT)
|
||||||
layout.addWidget(widget)
|
# layout.addWidget(widget)
|
||||||
|
|
||||||
# column stretching: must be matched with header
|
# column stretching: must be matched with header
|
||||||
num_widgets = len(widgets)
|
num_widgets = len(widgets)
|
||||||
@@ -3676,22 +3743,22 @@ class Page_Consulting_ConsultingSession(QWidget):
|
|||||||
logger_page_consulting.debug(
|
logger_page_consulting.debug(
|
||||||
"[Page Consulting -- Consulting Session]: State = %s", self.STATE
|
"[Page Consulting -- Consulting Session]: State = %s", self.STATE
|
||||||
)
|
)
|
||||||
set_widget_value(self.user_field, self.STATE.user_name)
|
set_widget_value(self.user_field, self.STATE.nutzer_name)
|
||||||
set_widget_value(self.timestamp, self.STATE.timestamp.astimezone(TIMEZONE_CEST))
|
set_widget_value(self.timestamp, self.STATE.zeitstempel.astimezone(TIMEZONE_CEST))
|
||||||
set_widget_value(self.contact, self.STATE.partner)
|
set_widget_value(self.contact, self.STATE.ansprechpartner)
|
||||||
set_widget_value(self.contact_type, self.STATE.interaction_scheme)
|
set_widget_value(self.contact_type, self.STATE.interaction_scheme)
|
||||||
set_widget_value(self.crm_link, self.STATE.topic)
|
set_widget_value(self.crm_link, self.STATE.topic)
|
||||||
set_widget_value(self.plain_text, self.STATE.notes)
|
set_widget_value(self.plain_text, self.STATE.anmerkungen)
|
||||||
set_widget_value(self.response, self.STATE.response)
|
set_widget_value(self.response, self.STATE.rueckmeldung)
|
||||||
|
|
||||||
def _sync_gui_to_state(self) -> None:
|
def _sync_gui_to_state(self) -> None:
|
||||||
# TODO: get timestamp from custom field self.STATE.timestamp
|
# TODO: get timestamp from custom field self.STATE.timestamp
|
||||||
self.STATE.timestamp = self.timestamp.get_pydatetime()
|
self.STATE.zeitstempel = self.timestamp.get_pydatetime()
|
||||||
self.STATE.partner = self.contact.text()
|
self.STATE.ansprechpartner = get_widget_value(self.contact)
|
||||||
self.STATE.interaction_scheme = self.contact_type.text()
|
self.STATE.interaction_scheme = get_widget_value(self.contact_type)
|
||||||
self.STATE.topic = self.crm_link.text() # TODO: change to correct link
|
self.STATE.topic = get_widget_value(self.crm_link) # TODO: change to correct link
|
||||||
self.STATE.notes = self.plain_text.toPlainText()
|
self.STATE.anmerkungen = get_widget_value(self.plain_text)
|
||||||
self.STATE.response = self.response.toPlainText()
|
self.STATE.rueckmeldung = get_widget_value(self.response)
|
||||||
|
|
||||||
def get_data(self) -> Page_Consulting_ConsultingSession_State:
|
def get_data(self) -> Page_Consulting_ConsultingSession_State:
|
||||||
self._sync_gui_to_state()
|
self._sync_gui_to_state()
|
||||||
@@ -3873,8 +3940,8 @@ class Page_Consulting_Table(QWidget):
|
|||||||
) -> None:
|
) -> None:
|
||||||
if row_state is None:
|
if row_state is None:
|
||||||
row_state = Page_Consulting_ConsultingSession_State(
|
row_state = Page_Consulting_ConsultingSession_State(
|
||||||
user_id=self.SITE_STATE.session.user_id,
|
nutzer_id=self.SITE_STATE.session.user_id,
|
||||||
user_name=self.SITE_STATE.session.user_name,
|
nutzer_name=self.SITE_STATE.session.user_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
row = Page_Consulting_ConsultingSession(site_state=self.SITE_STATE, state=row_state)
|
row = Page_Consulting_ConsultingSession(site_state=self.SITE_STATE, state=row_state)
|
||||||
|
|||||||
Reference in New Issue
Block a user