Add Dispatch_V0.1.1
This commit is contained in:
135
Dispatch_V0.1.1/ui/dialogs/task_refusal_dialog.py
Normal file
135
Dispatch_V0.1.1/ui/dialogs/task_refusal_dialog.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# hub/ticket/ui/dialogs/task_refusal_dialog.py
|
||||
|
||||
"""Диалог подтверждения отказа задачи Ticket."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from gui.components import Button, Dialog, Label, TextInput
|
||||
from gui.containers import HContainer, VContainer
|
||||
|
||||
from domain import TicketTaskSnapshot, parse_location_parts
|
||||
|
||||
|
||||
class TaskRefusalDialog(Dialog):
|
||||
"""Диалог ввода обязательной причины отказа по задаче."""
|
||||
|
||||
def __init__(self, task: TicketTaskSnapshot, parent=None):
|
||||
self._task = task
|
||||
self._reason_input: TextInput | None = None
|
||||
self._cancel_button: Button | None = None
|
||||
self._submit_button: Button | None = None
|
||||
super().__init__(
|
||||
title="Отказ в обслуживании",
|
||||
width=500,
|
||||
height=460,
|
||||
modal=True,
|
||||
parent=parent,
|
||||
)
|
||||
self._setup_ui()
|
||||
self._connect_signals()
|
||||
self._refresh_submit_state()
|
||||
|
||||
@property
|
||||
def refusal_reason(self) -> str:
|
||||
if self._reason_input is None:
|
||||
return ""
|
||||
return self._reason_input.get_text().strip()
|
||||
|
||||
def _setup_ui(self) -> None:
|
||||
# Root-контейнер окна отказа: предупреждение, контекст задачи, поле причины и actions.
|
||||
main_container = VContainer(margin=[24, 20, 24, 20], spacing=16)
|
||||
self.add_widget(main_container)
|
||||
main_container.add_widget(
|
||||
Label(
|
||||
"Вы уверены, что хотите отказать в обслуживании?",
|
||||
alignment="left",
|
||||
style="TICKET_REFUSAL_HEADING",
|
||||
)
|
||||
)
|
||||
main_container.add_widget(self._build_location_row())
|
||||
main_container.add_widget(
|
||||
Label(
|
||||
'Задача будет перемещена в колонку "Отказ"',
|
||||
alignment="left",
|
||||
style="TICKET_REFUSAL_WARNING",
|
||||
)
|
||||
)
|
||||
main_container.add_widget(
|
||||
Label(
|
||||
"Причина отказа",
|
||||
alignment="left",
|
||||
style="TICKET_REFUSAL_HEADING",
|
||||
)
|
||||
)
|
||||
main_container.add_widget_with_stretch(self._build_reason_input(), 1)
|
||||
main_container.add_widget(self._build_actions())
|
||||
|
||||
def _build_location_row(self) -> HContainer:
|
||||
# Location-row: показывает локацию задачи, чтобы отказ происходил в явном контексте.
|
||||
row = HContainer(spacing=10, content_fit=True)
|
||||
row.add_widget(
|
||||
Label(
|
||||
"Локация и кабинет:",
|
||||
alignment="left",
|
||||
style="TICKET_REFUSAL_LOCATION_TITLE",
|
||||
)
|
||||
)
|
||||
value_label = Label(
|
||||
self._build_location_text(),
|
||||
alignment="left",
|
||||
style="TICKET_REFUSAL_LOCATION_VALUE",
|
||||
)
|
||||
value_label.set_tooltip(self._build_location_text())
|
||||
row.add_widget_with_stretch(value_label, 1)
|
||||
return row
|
||||
|
||||
def _build_reason_input(self) -> TextInput:
|
||||
self._reason_input = TextInput(
|
||||
placeholder="Укажите причину отказа",
|
||||
style="TICKET_DOCUMENT_TEXTAREA",
|
||||
multiline=True,
|
||||
)
|
||||
self._reason_input.set_min_height(170)
|
||||
return self._reason_input
|
||||
|
||||
def _build_actions(self) -> HContainer:
|
||||
# Actions-row окна отказа: собирает кнопки отмены и финального подтверждения.
|
||||
actions = HContainer(spacing=18, content_fit=True)
|
||||
actions.add_stretch()
|
||||
self._cancel_button = Button(
|
||||
"Отмена",
|
||||
style="TICKET_DOCUMENT_CANCEL_BUTTON",
|
||||
content_fit=True,
|
||||
)
|
||||
self._submit_button = Button(
|
||||
"Подтвердить отказ",
|
||||
style="TICKET_DOCUMENT_SUBMIT_BUTTON",
|
||||
content_fit=True,
|
||||
)
|
||||
actions.add_widget(self._cancel_button)
|
||||
actions.add_widget(self._submit_button)
|
||||
return actions
|
||||
|
||||
def _connect_signals(self) -> None:
|
||||
if self._reason_input is not None:
|
||||
self._reason_input.text_changed.connect(self._refresh_submit_state)
|
||||
if self._cancel_button is not None:
|
||||
self._cancel_button.clicked.connect(self.reject)
|
||||
if self._submit_button is not None:
|
||||
self._submit_button.clicked.connect(self._handle_accept)
|
||||
|
||||
def _refresh_submit_state(self) -> None:
|
||||
if self._submit_button is not None:
|
||||
self._submit_button.set_enabled(bool(self.refusal_reason))
|
||||
|
||||
def _handle_accept(self) -> None:
|
||||
if not self.refusal_reason:
|
||||
return
|
||||
self.accept()
|
||||
|
||||
def _build_location_text(self) -> str:
|
||||
institution, room, _ = parse_location_parts(self._task.location or "")
|
||||
normalized_institution = institution or "Локация не указана"
|
||||
normalized_room = room or "Кабинет не указан"
|
||||
return f"{normalized_institution}, {normalized_room}"
|
||||
Reference in New Issue
Block a user