Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 191-use-round_to_precision-in-percent_to_hive_percent
  • 289-cli-working-watched-tracked-accounts-works-inconsistent-with-tui
  • bw_image_fixes
  • bw_image_fixes2
  • bw_protected_branch_job_fixes
  • bw_wip_demo_prototype
  • change-governance-data
  • develop
  • jziebinski/accounts-management-revolution
  • jziebinski/bump-schemas
  • jziebinski/fix-after-cli-governance
  • jziebinski/fix-dashboard
  • jziebinski/improve-governance
  • jziebinski/make-button-disabled
  • jziebinski/mkudela/fix-cart
  • jziebinski/mkudela/issue-173
  • jziebinski/mkudela/issue-233
  • jziebinski/mzebrak/119-update-profile-name-regex
  • jziebinski/prepare-hp-delegate
  • jziebinski/prepare-hp-full
  • jziebinski/prepare-hp-power-down
  • jziebinski/prepare-operations-ui
  • jziebinski/prepare-user-view
  • jziebinski/proposals-improvements
  • jziebinski/savings-demonstration
  • jziebinski/strike-through-tabs
  • jziebinski/textual-bump
  • jziebinski/user-info
  • jziebisnki/prepare-governance
  • kmochocki/add-mr-template
  • kmochocki/beekeepy-ready-to-merge
  • kmochocki/beekeepy-wip
  • kmochocki/ci-reuse-hived
  • kmochocki/kudmich/haf-filling-machine
  • kmochocki/menu-bar
  • kmochocki/optimize-update-node-data-async
  • kmochocki/ui-errors
  • kmochocki/update-hive-submodule
  • kmochocki/update-submodule
  • kmochocki/wup-check
  • kudmich/beekeeper_on_many_sessions_tests
  • kudmich/block_log_multi_sign_backup
  • kudmich/block_log_open_sign_backup
  • kudmich/block_log_single_sign
  • kudmich/block_log_single_sign_backup
  • kudmich/full_block_generator
  • kudmich/haf-filling-machine
  • kudmich/haf-filling-machine-copy_for_mzebrak
  • kudmich/haf-filling-machine_first_base
  • kudmich/prepared_block_logs
  • kudmich/update_block_log_with_open_sign
  • kudmich_full_block_generator_on_bk
  • marek/prepare-block_log
  • marek/tui-test-onboarding1
  • marek/tui-test-witness-votes
  • marek/tui-test-witness-votes-2
  • marek/tui-test-witness-votes-3
  • marek/tui-tests-key-press
  • marek/tui-tests-key-press-log-toasts
  • master
  • mkudela/authority
  • mkudela/fix_node_data_two_grouops
  • mkudela/generate_operations_script
  • mkudela/input_autofill
  • mkudela/issue-261
  • mkudela/issue-373
  • mkudela/modify_authority
  • mkudela/mzebrak/textual-bump
  • mkudela/refactor_transaction_summary
  • mkudela/test
  • msobczyk/343-missing-sign-option
  • msobczyk/377-error-messages-in-cli-tests
  • msobczyk/396-remove-bindings-from-the-bottom-menu
  • msobczyk/399-dont-cancel-ongoing-work
  • msobczyk/403-migration-better-storage
  • msobczyk/403-migration-better-storage-fixup
  • msobczyk/403-migration-better-storage-squashed
  • msobczyk/403-migration-better-storage-with-pydantic
  • msobczyk/add-faketime-to-embedded-testnet-image
  • msobczyk/apr_text
  • msobczyk/bash-tests
  • msobczyk/change_docker_image_tags
  • msobczyk/cli-authority-tests2
  • msobczyk/cli-claims
  • msobczyk/cli-claims-tests
  • msobczyk/cli-hive-power-management
  • msobczyk/cli-savings-management2
  • msobczyk/cli-witness-properties
  • msobczyk/collect-authority
  • msobczyk/conftest-do-not-merge
  • msobczyk/display-authority-tee-in-ui
  • msobczyk/display-authority-tree-in-tui
  • msobczyk/encrypt-profile-tmp
  • msobczyk/fix_crash_on_double_button
  • msobczyk/improve-cli-testing-interface
  • msobczyk/issue-374
  • msobczyk/kmochocki/beekeepy
  • msobczyk/mzebrak/bump-tools
  • msobczyk/mzebrak/fix-cli-tests-logs-in-output
  • msobczyk/mzebrak/fix-for-positional-cli
  • 1.27.5.0
  • test-tag
  • v1.27.5.0
  • v1.27.5.1
  • v1.27.5.10
  • v1.27.5.11
  • v1.27.5.12
  • v1.27.5.13
  • v1.27.5.14
  • v1.27.5.15
  • v1.27.5.16
  • v1.27.5.17
  • v1.27.5.17b4
  • v1.27.5.18
  • v1.27.5.19
  • v1.27.5.2
  • v1.27.5.20
  • v1.27.5.21
  • v1.27.5.3
  • v1.27.5.4
  • v1.27.5.5
  • v1.27.5.6
  • v1.27.5.7
  • v1.27.5.8
  • v1.27.5.9
125 results

Target

Select target project
  • hive/clive
1 result
Select Git revision
  • 191-use-round_to_precision-in-percent_to_hive_percent
  • 289-cli-working-watched-tracked-accounts-works-inconsistent-with-tui
  • bw_image_fixes
  • bw_image_fixes2
  • bw_protected_branch_job_fixes
  • bw_wip_demo_prototype
  • change-governance-data
  • develop
  • jziebinski/accounts-management-revolution
  • jziebinski/bump-schemas
  • jziebinski/fix-after-cli-governance
  • jziebinski/fix-dashboard
  • jziebinski/improve-governance
  • jziebinski/make-button-disabled
  • jziebinski/mkudela/fix-cart
  • jziebinski/mkudela/issue-173
  • jziebinski/mkudela/issue-233
  • jziebinski/mzebrak/119-update-profile-name-regex
  • jziebinski/prepare-hp-delegate
  • jziebinski/prepare-hp-full
  • jziebinski/prepare-hp-power-down
  • jziebinski/prepare-operations-ui
  • jziebinski/prepare-user-view
  • jziebinski/proposals-improvements
  • jziebinski/savings-demonstration
  • jziebinski/strike-through-tabs
  • jziebinski/textual-bump
  • jziebinski/user-info
  • jziebisnki/prepare-governance
  • kmochocki/add-mr-template
  • kmochocki/beekeepy-ready-to-merge
  • kmochocki/beekeepy-wip
  • kmochocki/ci-reuse-hived
  • kmochocki/kudmich/haf-filling-machine
  • kmochocki/menu-bar
  • kmochocki/optimize-update-node-data-async
  • kmochocki/ui-errors
  • kmochocki/update-hive-submodule
  • kmochocki/update-submodule
  • kmochocki/wup-check
  • kudmich/beekeeper_on_many_sessions_tests
  • kudmich/block_log_multi_sign_backup
  • kudmich/block_log_open_sign_backup
  • kudmich/block_log_single_sign
  • kudmich/block_log_single_sign_backup
  • kudmich/full_block_generator
  • kudmich/haf-filling-machine
  • kudmich/haf-filling-machine-copy_for_mzebrak
  • kudmich/haf-filling-machine_first_base
  • kudmich/prepared_block_logs
  • kudmich/update_block_log_with_open_sign
  • kudmich_full_block_generator_on_bk
  • marek/prepare-block_log
  • marek/tui-test-onboarding1
  • marek/tui-test-witness-votes
  • marek/tui-test-witness-votes-2
  • marek/tui-test-witness-votes-3
  • marek/tui-tests-key-press
  • marek/tui-tests-key-press-log-toasts
  • master
  • mkudela/authority
  • mkudela/fix_node_data_two_grouops
  • mkudela/generate_operations_script
  • mkudela/input_autofill
  • mkudela/issue-261
  • mkudela/issue-373
  • mkudela/modify_authority
  • mkudela/mzebrak/textual-bump
  • mkudela/refactor_transaction_summary
  • mkudela/test
  • msobczyk/343-missing-sign-option
  • msobczyk/377-error-messages-in-cli-tests
  • msobczyk/396-remove-bindings-from-the-bottom-menu
  • msobczyk/399-dont-cancel-ongoing-work
  • msobczyk/403-migration-better-storage
  • msobczyk/403-migration-better-storage-fixup
  • msobczyk/403-migration-better-storage-squashed
  • msobczyk/403-migration-better-storage-with-pydantic
  • msobczyk/add-faketime-to-embedded-testnet-image
  • msobczyk/apr_text
  • msobczyk/bash-tests
  • msobczyk/change_docker_image_tags
  • msobczyk/cli-authority-tests2
  • msobczyk/cli-claims
  • msobczyk/cli-claims-tests
  • msobczyk/cli-hive-power-management
  • msobczyk/cli-savings-management2
  • msobczyk/cli-witness-properties
  • msobczyk/collect-authority
  • msobczyk/conftest-do-not-merge
  • msobczyk/display-authority-tee-in-ui
  • msobczyk/display-authority-tree-in-tui
  • msobczyk/encrypt-profile-tmp
  • msobczyk/fix_crash_on_double_button
  • msobczyk/improve-cli-testing-interface
  • msobczyk/issue-374
  • msobczyk/kmochocki/beekeepy
  • msobczyk/mzebrak/bump-tools
  • msobczyk/mzebrak/fix-cli-tests-logs-in-output
  • msobczyk/mzebrak/fix-for-positional-cli
  • 1.27.5.0
  • test-tag
  • v1.27.5.0
  • v1.27.5.1
  • v1.27.5.10
  • v1.27.5.11
  • v1.27.5.12
  • v1.27.5.13
  • v1.27.5.14
  • v1.27.5.15
  • v1.27.5.16
  • v1.27.5.17
  • v1.27.5.17b4
  • v1.27.5.18
  • v1.27.5.19
  • v1.27.5.2
  • v1.27.5.20
  • v1.27.5.21
  • v1.27.5.3
  • v1.27.5.4
  • v1.27.5.5
  • v1.27.5.6
  • v1.27.5.7
  • v1.27.5.8
  • v1.27.5.9
125 results
Show changes
Commits on Source (8)
Showing
with 305 additions and 204 deletions
......@@ -7,6 +7,7 @@ NEXT_SCREEN_BINDING_KEY: Final[str] = "ctrl+n"
PREVIOUS_SCREEN_BINDING_KEY: Final[str] = "ctrl+p"
FINALIZE_TRANSACTION_BINDING_KEY: Final[str] = "f6"
SAVE_TRANSACTION_TO_FILE_BINDING_KEY: Final[str] = "f2"
ADD_OPERATION_TO_CART_BINDING_KEY: Final[str] = "f2"
BROADCAST_TRANSACTION_BINDING_KEY: Final[str] = "f6"
LOAD_TRANSACTION_FROM_FILE_BINDING_KEY: Final[str] = "f3"
REFRESH_TRANSACTION_METADATA_BINDING_KEY: Final[str] = "f5"
......@@ -2,7 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from textual.binding import Binding
from clive.__private.ui.dialogs.clive_base_dialogs import CliveActionDialog
......@@ -16,7 +15,7 @@ if TYPE_CHECKING:
class AddTrackedAccountDialog(CliveActionDialog):
CSS_PATH = [get_relative_css_path(__file__)]
BINDINGS = [Binding("escape,f4", "cancel", "Quit")]
BINDINGS = [Binding("escape,f4", "cancel", "Cancel")]
AUTO_FOCUS = "Input"
def __init__(self) -> None:
......@@ -27,8 +26,6 @@ class AddTrackedAccountDialog(CliveActionDialog):
yield AccountManagementReference()
yield self._add_account_container
@on(CliveActionDialog.Confirmed)
async def save_account(self) -> None:
async def _perform_confirmation(self) -> bool:
is_account_saved = await self._add_account_container.save_account()
if is_account_saved:
self.app.pop_screen()
return is_account_saved # noqa: RET504
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Literal
from textual import on
......@@ -20,7 +20,6 @@ from clive.__private.ui.widgets.inputs.clive_input import CliveInput
if TYPE_CHECKING:
from textual.app import ComposeResult
CliveDialogVariant = Literal["default", "error"]
......@@ -102,8 +101,8 @@ class CliveBaseDialog(ModalScreen[ScreenResultT], CliveWidget, AbstractClassMess
"""Yield all the content with buttons."""
class CliveActionDialog(CliveBaseDialog[ScreenResultT]):
BINDINGS = [Binding("escape", "cancel", "Quit")]
class CliveActionDialog(CliveBaseDialog[ScreenResultT], ABC):
BINDINGS = [Binding("escape", "cancel", "Cancel")]
class Confirmed(Message):
"""Inform the dialog that it should be confirmed."""
......@@ -123,22 +122,58 @@ class CliveActionDialog(CliveBaseDialog[ScreenResultT]):
yield ConfirmOneLineButton(self._confirm_button_text)
yield CancelOneLineButton()
async def confirm_dialog(self) -> None:
"""Confirm the dialog which means try to perform the action and close the dialog if successful."""
is_confirmed = await self._perform_confirmation()
if is_confirmed:
self.post_message(self.Confirmed())
self._close_when_confirmed()
async def cancel_dialog(self) -> None:
"""Cancel the dialog which means close the dialog without performing any action."""
self._close_when_cancelled()
async def _perform_confirmation(self) -> bool:
"""Perform the action of the dialog and return True if it was successful."""
return True
def _close_when_confirmed(self) -> None:
self.dismiss()
def _close_when_cancelled(self) -> None:
self.dismiss()
@on(CliveInput.Submitted)
@on(ConfirmOneLineButton.Pressed)
async def confirm_dialog(self) -> None:
self.post_message(self.Confirmed())
async def _confirm_with_event(self) -> None:
"""By default, pressing the confirm button or submitting the input will confirm the dialog."""
await self.confirm_dialog()
@on(CancelOneLineButton.Pressed)
def action_cancel(self) -> None:
self.app.pop_screen()
async def _cancel_with_button(self) -> None:
"""By default, pressing the cancel button will cancel the dialog."""
await self.cancel_dialog()
async def _action_cancel(self) -> None:
"""By default, pressing the cancel key binding will cancel the dialog."""
await self.cancel_dialog()
class CliveInfoDialog(CliveBaseDialog[ScreenResultT]):
BINDINGS = [Binding("escape", "close", "Quit")]
class CliveInfoDialog(CliveBaseDialog[None], ABC):
BINDINGS = [Binding("escape", "close", "Close")]
def create_buttons_content(self) -> ComposeResult:
yield CloseOneLineButton()
async def _close(self) -> None:
"""Close the dialog without performing any action."""
self.dismiss()
@on(CloseOneLineButton.Pressed)
def action_close(self) -> None:
self.app.pop_screen()
async def _close_with_button(self) -> None:
"""By default, pressing the close button will close the dialog."""
await self._close()
async def _action_close(self) -> None:
"""By default, pressing the close key binding will close the dialog."""
await self._close()
......@@ -2,12 +2,10 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from textual.widgets import Static
from clive.__private.ui.dialogs.clive_base_dialogs import CliveActionDialog, CliveDialogVariant
from clive.__private.ui.get_css import get_relative_css_path
from clive.__private.ui.widgets.buttons import CancelOneLineButton, ConfirmOneLineButton
from clive.__private.ui.widgets.section import Section
if TYPE_CHECKING:
......@@ -39,12 +37,8 @@ class ConfirmActionDialog(CliveActionDialog[bool]):
with Section():
yield Static(self._confirm_question, id="confirm-question")
@on(ConfirmOneLineButton.Pressed)
async def confirm_dialog(self) -> None:
def _close_when_confirmed(self) -> None:
self.dismiss(result=True)
@on(CancelOneLineButton.Pressed)
def action_cancel(self, event: CancelOneLineButton.Pressed | None = None) -> None:
if event is not None:
event.prevent_default()
def _close_when_cancelled(self) -> None:
self.dismiss(result=False)
......@@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from clive.__private.ui.dialogs.confirm_action_dialog import ConfirmActionDialog
if TYPE_CHECKING:
......@@ -26,9 +24,9 @@ class MarkAlarmAsHarmlessDialog(ConfirmActionDialog):
def alarm_info(self) -> str:
return self._alarm.get_alarm_basic_info()
@on(ConfirmActionDialog.Confirmed)
def mark_alarm_as_harmless(self) -> None:
async def _perform_confirmation(self) -> bool:
self._alarm.is_harmless = True
self.notify(f"Alarm `{self.alarm_info}` was marked as harmless.")
self.app.trigger_profile_watchers()
self.app.pop_screen()
self.call_later(self.app.pop_screen) # pop the underlying AlarmInfoDialog
return True
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING
from clive.__private.models.schemas import AccountWitnessProxyOperation
from clive.__private.ui.screens.operations.operation_summary.operation_summary import OperationSummary
from clive.__private.ui.dialogs.operation_summary.operation_summary_base_dialog import OperationSummaryBaseDialog
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
if TYPE_CHECKING:
......@@ -12,11 +12,9 @@ if TYPE_CHECKING:
from clive.__private.core.accounts.accounts import Account
class AccountWitnessProxy(OperationSummary):
SECTION_TITLE: ClassVar[str] = "Account witness proxy"
class AccountWitnessProxyDialog(OperationSummaryBaseDialog[bool]):
def __init__(self, *, new_proxy: str | None) -> None:
super().__init__()
super().__init__("Account witness proxy")
self._new_proxy = new_proxy
@property
......@@ -29,12 +27,18 @@ class AccountWitnessProxy(OperationSummary):
return ""
return self._new_proxy
def content(self) -> ComposeResult:
def create_dialog_content(self) -> ComposeResult:
yield LabelizedInput("Account name", self.working_account_name)
yield LabelizedInput("New proxy", self._new_proxy if self._new_proxy is not None else "Proxy will be removed")
def get_account_to_be_marked_as_known(self) -> str | Account | None:
return self._new_proxy
def _close_when_cancelled(self) -> None:
self.dismiss(result=False)
def _close_when_confirmed(self) -> None:
self.dismiss(result=True)
def _create_operation(self) -> AccountWitnessProxyOperation:
return AccountWitnessProxyOperation(account=self.working_account_name, proxy=self.proxy_to_be_set)
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING
from clive.__private.core.constants.node import VESTS_TO_REMOVE_POWER_DOWN
from clive.__private.core.formatters.humanize import humanize_datetime
from clive.__private.models import Asset
from clive.__private.models.schemas import WithdrawVestingOperation
from clive.__private.ui.screens.operations.operation_summary.operation_summary import OperationSummary
from clive.__private.ui.dialogs.operation_summary.operation_summary_base_dialog import OperationSummaryBaseDialog
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
if TYPE_CHECKING:
......@@ -17,15 +17,13 @@ if TYPE_CHECKING:
from clive.__private.models import HpVestsBalance
class CancelPowerDown(OperationSummary):
SECTION_TITLE: ClassVar[str] = "Cancel power down"
class CancelPowerDownDialog(OperationSummaryBaseDialog):
def __init__(self, next_power_down_date: datetime, next_power_down: HpVestsBalance) -> None:
super().__init__()
super().__init__("Cancel power down")
self._next_power_down_date = next_power_down_date
self._next_power_down = next_power_down
def content(self) -> ComposeResult:
def create_dialog_content(self) -> ComposeResult:
yield LabelizedInput("Next power down", humanize_datetime(self._next_power_down_date))
yield LabelizedInput("Power down [HP]", Asset.pretty_amount(self._next_power_down.hp_balance))
yield LabelizedInput("Power down [VESTS]", Asset.pretty_amount(self._next_power_down.vests_balance))
......
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING
from clive.__private.core.formatters import humanize
from clive.__private.models.schemas import CancelTransferFromSavingsOperation
from clive.__private.ui.screens.operations.operation_summary.operation_summary import OperationSummary
from clive.__private.ui.dialogs.operation_summary.operation_summary_base_dialog import OperationSummaryBaseDialog
from clive.__private.ui.screens.operations.bindings import OperationActionBindings
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
if TYPE_CHECKING:
......@@ -13,11 +14,9 @@ if TYPE_CHECKING:
from clive.__private.models.schemas import SavingsWithdrawal
class CancelTransferFromSavings(OperationSummary):
SECTION_TITLE: ClassVar[str] = "Cancel transfer from savings"
class CancelTransferFromSavingsDialog(OperationSummaryBaseDialog, OperationActionBindings):
def __init__(self, transfer: SavingsWithdrawal) -> None:
super().__init__()
super().__init__("Cancel transfer from savings")
self._transfer = transfer
@property
......@@ -28,7 +27,7 @@ class CancelTransferFromSavings(OperationSummary):
def realized_on(self) -> str:
return humanize.humanize_datetime(self._transfer.complete)
def content(self) -> ComposeResult:
def create_dialog_content(self) -> ComposeResult:
yield LabelizedInput("Request id", str(self._transfer.request_id))
yield LabelizedInput("Realized on", self.realized_on)
yield LabelizedInput("From", self.from_account)
......
from __future__ import annotations
from abc import ABC
from typing import TYPE_CHECKING
from textual import on
from clive.__private.ui.clive_screen import ScreenResultT
from clive.__private.ui.dialogs.clive_base_dialogs import CliveActionDialog
from clive.__private.ui.get_css import get_relative_css_path
from clive.__private.ui.screens.operations.bindings import OperationActionBindings
from clive.__private.ui.widgets.buttons import (
AddToCartButton,
CancelOneLineButton,
FinalizeTransactionButton,
)
if TYPE_CHECKING:
from textual.app import ComposeResult
class OperationSummaryBaseDialog(CliveActionDialog[ScreenResultT], OperationActionBindings, ABC):
"""Base class for operation summary dialogs. Confirmation means that operation was added to cart or finalized."""
CSS_PATH = [get_relative_css_path(__file__)]
ALLOW_THE_SAME_OPERATION_IN_CART_MULTIPLE_TIMES = False
def create_buttons_content(self) -> ComposeResult:
yield AddToCartButton()
yield FinalizeTransactionButton()
yield CancelOneLineButton()
async def action_add_to_cart(self) -> None:
await super().action_add_to_cart()
await self.confirm_dialog()
async def action_finalize_transaction(self) -> None:
await super().action_finalize_transaction()
await self.confirm_dialog()
@on(AddToCartButton.Pressed)
async def _add_to_cart_with_button(self, event: AddToCartButton.Pressed) -> None:
event.prevent_default()
await self.action_add_to_cart()
@on(FinalizeTransactionButton.Pressed)
async def _finalize_transaction_with_button(self, event: FinalizeTransactionButton.Pressed) -> None:
event.prevent_default()
await self.action_finalize_transaction()
OperationSummaryBaseDialog {
CliveDialogContent {
width: 70%;
}
LabelizedInput {
margin-bottom: 1;
}
#buttons-container {
margin-top: 0;
}
}
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING
from clive.__private.core.constants.node import VESTS_TO_REMOVE_DELEGATION
from clive.__private.models import Asset
from clive.__private.models.schemas import DelegateVestingSharesOperation
from clive.__private.ui.screens.operations.operation_summary.operation_summary import OperationSummary
from clive.__private.ui.dialogs.operation_summary.operation_summary_base_dialog import OperationSummaryBaseDialog
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
if TYPE_CHECKING:
......@@ -14,13 +14,11 @@ if TYPE_CHECKING:
from clive.__private.models.schemas import VestingDelegation
class RemoveDelegation(OperationSummary):
"""Screen to remove delegation."""
SECTION_TITLE: ClassVar[str] = "Remove delegation"
class RemoveDelegationDialog(OperationSummaryBaseDialog):
"""Dialog to remove delegation."""
def __init__(self, delegation: VestingDelegation[Asset.Vests], pretty_hp_amount: str) -> None:
super().__init__()
super().__init__("Remove delegation")
self._delegation = delegation
self._pretty_hp_amount = pretty_hp_amount
......@@ -28,7 +26,7 @@ class RemoveDelegation(OperationSummary):
def working_account_name(self) -> str:
return self.profile.accounts.working.name
def content(self) -> ComposeResult:
def create_dialog_content(self) -> ComposeResult:
yield LabelizedInput("Delegator", self.working_account_name)
yield LabelizedInput("Delegate", self._delegation.delegatee)
yield LabelizedInput(
......
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar
from typing import TYPE_CHECKING
from clive.__private.core.constants.node import PERCENT_TO_REMOVE_WITHDRAW_ROUTE
from clive.__private.core.constants.precision import HIVE_PERCENT_PRECISION
from clive.__private.core.formatters.humanize import humanize_bool
from clive.__private.models.schemas import SetWithdrawVestingRouteOperation
from clive.__private.ui.screens.operations.operation_summary.operation_summary import OperationSummary
from clive.__private.ui.dialogs.operation_summary.operation_summary_base_dialog import OperationSummaryBaseDialog
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
if TYPE_CHECKING:
......@@ -15,20 +15,18 @@ if TYPE_CHECKING:
from clive.__private.models.schemas import WithdrawRoute
class RemoveWithdrawVestingRoute(OperationSummary):
"""Screen to remove withdraw vesting route."""
SECTION_TITLE: ClassVar[str] = "Remove withdraw vesting route"
class RemoveWithdrawVestingRouteDialog(OperationSummaryBaseDialog):
"""Dialog to remove withdraw vesting route."""
def __init__(self, withdraw_route: WithdrawRoute) -> None:
super().__init__()
super().__init__("Remove withdraw vesting route")
self._withdraw_route = withdraw_route
@property
def working_account_name(self) -> str:
return self.profile.accounts.working.name
def content(self) -> ComposeResult:
def create_dialog_content(self) -> ComposeResult:
yield LabelizedInput("From account", self.working_account_name)
yield LabelizedInput("To account", self._withdraw_route.to_account)
yield LabelizedInput("Percent", f"{self._withdraw_route.percent / HIVE_PERCENT_PRECISION :.2f} %")
......
......@@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from clive.__private.ui.dialogs.confirm_action_dialog import ConfirmActionDialog
if TYPE_CHECKING:
......@@ -27,8 +25,8 @@ class RemoveKeyAliasDialog(ConfirmActionDialog):
def key_alias(self) -> str:
return self._public_key.alias
@on(ConfirmActionDialog.Confirmed)
def remove_key_alias(self) -> None:
async def _perform_confirmation(self) -> bool:
self.profile.keys.remove(self._public_key)
self.notify(f"Key alias `{self.key_alias}` was removed.")
self.app.trigger_profile_watchers()
return True
......@@ -2,11 +2,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from clive.__private.ui.dialogs.clive_base_dialogs import CliveActionDialog
from clive.__private.ui.get_css import get_relative_css_path
from clive.__private.ui.widgets.buttons import ConfirmButton
from clive.__private.ui.widgets.node_widgets import NodesList, SelectedNodeAddress
from clive.__private.ui.widgets.section import Section
......@@ -25,11 +22,6 @@ class SwitchNodeAddressDialog(CliveActionDialog):
yield SelectedNodeAddress(self.node.http_endpoint)
yield NodesList()
@on(ConfirmButton.Pressed)
async def switch_node_address(self) -> None:
await self._switch_node_address()
async def _switch_node_address(self) -> None:
async def _perform_confirmation(self) -> bool:
change_node_succeeded = await self.query_exactly_one(NodesList).save_selected_node_address()
if change_node_succeeded:
self.dismiss()
return change_node_succeeded # noqa: RET504
......@@ -2,7 +2,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from textual import on
from textual.binding import Binding
from clive.__private.ui.dialogs.clive_base_dialogs import CliveActionDialog
......@@ -18,7 +17,7 @@ if TYPE_CHECKING:
class SwitchWorkingAccountDialog(CliveActionDialog):
CSS_PATH = [get_relative_css_path(__file__)]
BINDINGS = [Binding("escape,f3", "cancel", "Quit")]
BINDINGS = [Binding("escape,f3", "cancel", "Cancel")]
AUTO_FOCUS = "RadioSet"
def __init__(self) -> None:
......@@ -29,7 +28,6 @@ class SwitchWorkingAccountDialog(CliveActionDialog):
yield AccountManagementReference()
yield self._switch_working_account_container
@on(CliveActionDialog.Confirmed)
def confirm_selected_working_account(self) -> None:
async def _perform_confirmation(self) -> bool:
self._switch_working_account_container.confirm_selected_working_account()
self.app.pop_screen()
return True
......@@ -10,7 +10,10 @@ from textual.css.query import NoMatches
from clive.__private.abstract_class import AbstractClassMessagePump
from clive.__private.core import iwax
from clive.__private.core.constants.tui.bindings import FINALIZE_TRANSACTION_BINDING_KEY
from clive.__private.core.constants.tui.bindings import (
ADD_OPERATION_TO_CART_BINDING_KEY,
FINALIZE_TRANSACTION_BINDING_KEY,
)
from clive.__private.ui.clive_widget import CliveWidget
from clive.__private.ui.dialogs.confirm_action_dialog_with_known_exchange import ConfirmActionDialogWithKnownExchange
from clive.__private.ui.screens.transaction_summary import TransactionSummary
......@@ -40,7 +43,7 @@ class OperationActionBindings(CliveWidget, AbstractClassMessagePump):
"""Class to provide access to methods related with operations to not just screens."""
BINDINGS = [
Binding("f2", "add_to_cart", "Add to cart"),
Binding(ADD_OPERATION_TO_CART_BINDING_KEY, "add_to_cart", "Add to cart"),
Binding(FINALIZE_TRANSACTION_BINDING_KEY, "finalize_transaction", "Finalize transaction"),
]
ALLOW_THE_SAME_OPERATION_IN_CART_MULTIPLE_TIMES: ClassVar[bool] = True
......@@ -50,7 +53,7 @@ class OperationActionBindings(CliveWidget, AbstractClassMessagePump):
# Multiple inheritance friendly, passes arguments to next object in MRO.
super().__init__(*args, **kwargs)
self.__check_if_correctly_implemented()
self._check_if_correctly_implemented()
def _create_operation(self) -> OperationUnion | None | _NotImplemented:
"""Return a new operation based on the data from screen or None."""
......@@ -111,78 +114,53 @@ class OperationActionBindings(CliveWidget, AbstractClassMessagePump):
def create_operations(self) -> list[OperationUnion] | None:
return self._validate_and_notify(self._create_operations)
@on(FinalizeTransactionButton.Pressed)
async def action_finalize_transaction(self) -> None:
async def finalize() -> None:
if self._add_to_cart():
self._add_account_to_known_after_action()
self.profile.transaction_file_path = None
if self.profile.transaction.is_signed:
self._send_cleared_signatures_notification()
await self.commands.update_transaction_metadata(transaction=self.profile.transaction)
self._clear_inputs()
self._actions_after_clearing_inputs()
await self.app.push_screen(TransactionSummary())
async def finalize_cb(confirm: bool | None) -> None:
if confirm:
await finalize()
async def action_add_to_cart(self) -> None:
await self._handle_add_to_cart_request()
if not self._can_proceed_operation(): # For faster validation feedback to the user
return
if self._check_is_known_exchange_in_input():
await self.app.push_screen(ConfirmActionDialogWithKnownExchange(), finalize_cb)
else:
await finalize()
@on(AddToCartButton.Pressed)
async def add_to_cart_by_button(self) -> None:
await self._handle_add_to_cart_request()
@on(CliveInput.Submitted)
@on(AddToCartButton.Pressed)
def action_add_to_cart(self) -> None:
def add_to_cart() -> None:
if self._add_to_cart():
if self.profile.transaction.is_signed:
self.profile.transaction.unsign()
self._send_cleared_signatures_notification()
self.profile.transaction_file_path = None
self._add_account_to_known_after_action()
if self.POP_SCREEN_AFTER_ADDING_TO_CART:
self.app.pop_screen()
self._clear_inputs()
self._actions_after_clearing_inputs()
self.notify("The operation was added to the cart.")
def add_to_cart_cb(confirm: bool | None) -> None:
if confirm:
add_to_cart()
async def add_to_cart_with_event(self) -> None:
await self._handle_add_to_cart_request()
if not self._can_proceed_operation(): # For faster validation feedback to the user
return
async def action_finalize_transaction(self) -> None:
await self._handle_finalize_transaction_request()
if self._check_is_known_exchange_in_input():
self.app.push_screen(ConfirmActionDialogWithKnownExchange(), add_to_cart_cb)
else:
add_to_cart()
@on(FinalizeTransactionButton.Pressed)
async def finalize_transaction_by_button(self) -> None:
await self._handle_finalize_transaction_request()
def get_account_to_be_marked_as_known(self) -> str | Account | None:
def check_is_known_exchange_in_input(self) -> bool | None:
"""
Return the account (if overwritten) that should have been marked as known after action like add to cart.
Check if the account name input (action receiver) is a known exchange account (if overwritten).
Notice:
_______
If this method is not overridden, the account from the account name input (action receiver),
will be marked as known.
will be checked for being a known exchange.
"""
return None
def check_is_known_exchange_in_input(self) -> bool | None:
def ensure_operations_list(self) -> list[OperationUnion]:
operation = self.create_operation()
if operation is not None:
return [operation]
operations = self.create_operations()
if operations is not None:
return operations
return []
def get_account_to_be_marked_as_known(self) -> str | Account | None:
"""
Check if the account name input (action receiver) is a known exchange account (if overwritten).
Return the account (if overwritten) that should have been marked as known after action like add to cart.
Notice:
_______
If this method is not overridden, the account from the account name input (action receiver),
will be checked for being a known exchange.
will be marked as known.
"""
return None
......@@ -196,32 +174,55 @@ class OperationActionBindings(CliveWidget, AbstractClassMessagePump):
self._additional_actions_after_clearing_inputs()
def _add_account_to_known_after_action(self) -> None:
"""Add account that is given via parameter. If not given - add all accounts from the account name inputs."""
account = self.get_account_to_be_marked_as_known()
if account is not None:
if not self.profile.accounts.is_account_known(account):
self.profile.accounts.known.add(account)
return
with contextlib.suppress(NoMatches):
self.query_exactly_one(AccountNameInput).add_account_to_known()
def _actions_after_adding_to_cart(self) -> None:
"""It's performing all actions needed after adding operation to cart."""
if self.profile.transaction.is_signed:
self.profile.transaction.unsign()
self._send_cleared_signatures_notification()
self.profile.transaction_file_path = None
self._add_account_to_known_after_action()
self._clear_inputs()
self._actions_after_clearing_inputs()
def _add_to_cart(self, operations: list[OperationUnion], *, notify: bool = True) -> None:
"""Just adds given operations to cart."""
self.profile.add_operation(*operations)
self.app.trigger_profile_watchers()
if notify:
self.notify("The operation was added to the cart.")
def _can_proceed_operation(self) -> bool:
if not self.create_operation() and not self.create_operations():
self.notify(INVALID_OPERATION_WARNING, severity="warning")
return False
return True
def _add_to_cart(self) -> bool:
"""
Create a new operation and adds it to the cart.
Returns
-------
True if the operation was added to the cart successfully, False otherwise.
"""
operations = self.ensure_operations_list()
assert operations, "when calling '_add_to_cart', operations must not be empty"
def _check_if_correctly_implemented(self) -> None:
with self.app.suppressed_notifications():
try:
create_operation_missing = isinstance(self._create_operation(), _NotImplemented)
except Exception: # noqa: BLE001
create_operation_missing = False
if not self.ALLOW_THE_SAME_OPERATION_IN_CART_MULTIPLE_TIMES:
for operation in operations:
if operation in self.profile.transaction:
self.notify("Operation already in the cart", severity="error")
return False
try:
create_operations_missing = isinstance(self._create_operations(), _NotImplemented)
except Exception: # noqa: BLE001
create_operations_missing = False
self.profile.add_operation(*operations)
self.app.trigger_profile_watchers()
return True
if sum([create_operation_missing, create_operations_missing]) != 1:
raise RuntimeError("One and only one of `_create_operation` or `_create_operations` should be implemented.")
def _check_is_known_exchange_in_input(self) -> bool:
is_known_exchange_in_input = self.check_is_known_exchange_in_input()
......@@ -235,50 +236,71 @@ class OperationActionBindings(CliveWidget, AbstractClassMessagePump):
return False
def _add_account_to_known_after_action(self) -> None:
"""Add account that is given via parameter. If not given - add all accounts from the account name inputs."""
account = self.get_account_to_be_marked_as_known()
if account is not None:
if not self.profile.accounts.is_account_known(account):
self.profile.accounts.known.add(account)
return
with contextlib.suppress(NoMatches):
self.query_exactly_one(AccountNameInput).add_account_to_known()
def _clear_inputs(self) -> None:
inputs = self.query(CliveValidatedInput) # type: ignore[type-abstract]
for widget in inputs:
widget.clear_validation()
async def _handle_add_to_cart_request(self) -> None:
def add_operation_to_cart_and_perform_post_actions() -> None:
self._add_to_cart(operations_to_add)
self._actions_after_adding_to_cart()
if self.POP_SCREEN_AFTER_ADDING_TO_CART:
self.app.pop_screen()
def cb(confirm: bool | None) -> None:
if confirm:
add_operation_to_cart_and_perform_post_actions()
if not self._can_proceed_operation(): # For faster validation feedback to the user
return
operations_to_add = self.ensure_operations_list()
assert operations_to_add, "when calling '_add_to_cart', operations must not be empty"
if self._validate_operations_already_in_the_cart(operations_to_add):
return
if self._check_is_known_exchange_in_input():
self.app.push_screen(ConfirmActionDialogWithKnownExchange(), cb)
else:
add_operation_to_cart_and_perform_post_actions()
async def _handle_finalize_transaction_request(self) -> None:
async def finalize_and_perform_post_actions() -> None:
self._add_to_cart(operations_to_add, notify=False)
self._actions_after_adding_to_cart()
await self.commands.update_transaction_metadata(transaction=self.profile.transaction)
await self.app.push_screen(TransactionSummary())
async def cb(confirm: bool | None) -> None:
if confirm:
await finalize_and_perform_post_actions()
if not self._can_proceed_operation(): # For faster validation feedback to the user
return
operations_to_add = self.ensure_operations_list()
assert operations_to_add, "when calling '_add_to_cart', operations must not be empty"
if self._validate_operations_already_in_the_cart(operations_to_add):
return
if self._check_is_known_exchange_in_input():
await self.app.push_screen(ConfirmActionDialogWithKnownExchange(), cb)
else:
await finalize_and_perform_post_actions()
def _send_cleared_signatures_notification(self) -> None:
self.notify(
"Transaction signatures were removed since you changed the transaction content.",
severity="warning",
)
def ensure_operations_list(self) -> list[OperationUnion]:
operation = self.create_operation()
if operation is not None:
return [operation]
operations = self.create_operations()
if operations is not None:
return operations
return []
def __check_if_correctly_implemented(self) -> None:
with self.app.suppressed_notifications():
try:
create_operation_missing = isinstance(self._create_operation(), _NotImplemented)
except Exception: # noqa: BLE001
create_operation_missing = False
try:
create_operations_missing = isinstance(self._create_operations(), _NotImplemented)
except Exception: # noqa: BLE001
create_operations_missing = False
if sum([create_operation_missing, create_operations_missing]) != 1:
raise RuntimeError("One and only one of `_create_operation` or `_create_operations` should be implemented.")
def _validate_operations_already_in_the_cart(self, operations: list[OperationUnion]) -> bool:
if not self.ALLOW_THE_SAME_OPERATION_IN_CART_MULTIPLE_TIMES and any(
operation in self.profile.transaction for operation in operations
):
self.notify("Operation already in the cart", severity="error")
return True
return False
......@@ -7,8 +7,8 @@ from textual.containers import Container, Horizontal
from textual.widgets import TabPane
from clive.__private.ui.clive_widget import CliveWidget
from clive.__private.ui.dialogs.operation_summary.account_witness_proxy_dialog import AccountWitnessProxyDialog
from clive.__private.ui.get_css import get_css_from_relative_path
from clive.__private.ui.screens.operations.operation_summary.account_witness_proxy import AccountWitnessProxy
from clive.__private.ui.widgets.buttons import OneLineButton
from clive.__private.ui.widgets.inputs.labelized_input import LabelizedInput
from clive.__private.ui.widgets.inputs.proxy_input import ProxyInput
......@@ -100,11 +100,11 @@ class Proxy(TabPane, CliveWidget):
return
new_proxy = self.new_proxy_input.value_or_error # already validated
self.app.push_screen(AccountWitnessProxy(new_proxy=new_proxy))
self.app.push_screen(AccountWitnessProxyDialog(new_proxy=new_proxy), self._proxy_dialog_cb)
@on(OneLineButton.Pressed, "#remove-proxy-button")
def remove_proxy(self) -> None:
self.app.push_screen(AccountWitnessProxy(new_proxy=None))
self.app.push_screen(AccountWitnessProxyDialog(new_proxy=None), self._proxy_dialog_cb)
def sync_when_proxy_changed(self) -> None:
proxy_profile = self.profile.accounts.working.data.proxy
......@@ -116,3 +116,10 @@ class Proxy(TabPane, CliveWidget):
with self.app.batch_update():
self.query_exactly_one(ProxyBaseContainer).remove()
self.query_exactly_one("#scrollable-for-proxy").mount(content)
def _clear_proxy_input(self) -> None:
self.new_proxy_input.clear_validation()
def _proxy_dialog_cb(self, confirm: bool | None) -> None:
if confirm:
self._clear_proxy_input()
......@@ -10,10 +10,10 @@ from clive.__private.core.constants.tui.class_names import CLIVE_CHECKERBOARD_HE
from clive.__private.core.ensure_vests import ensure_vests
from clive.__private.models.schemas import DelegateVestingSharesOperation
from clive.__private.ui.data_providers.hive_power_data_provider import HivePowerDataProvider
from clive.__private.ui.dialogs.operation_summary.remove_delegation_dialog import RemoveDelegationDialog
from clive.__private.ui.get_css import get_css_from_relative_path
from clive.__private.ui.not_updated_yet import NotUpdatedYet
from clive.__private.ui.screens.operations.bindings import OperationActionBindings
from clive.__private.ui.screens.operations.operation_summary.remove_delegation import RemoveDelegation
from clive.__private.ui.widgets.buttons import CliveButton, OneLineButton
from clive.__private.ui.widgets.clive_basic import (
CliveCheckerboardTable,
......@@ -71,7 +71,7 @@ class Delegation(CliveCheckerboardTableRow):
@on(CliveButton.Pressed, "#remove-delegation-button")
def push_operation_summary_screen(self) -> None:
self.app.push_screen(RemoveDelegation(self._delegation, self._aligned_hp_amount))
self.app.push_screen(RemoveDelegationDialog(self._delegation, self._aligned_hp_amount))
class DelegationsTable(CliveCheckerboardTable):
......
......@@ -15,10 +15,10 @@ from clive.__private.models import Asset
from clive.__private.models.schemas import WithdrawVestingOperation
from clive.__private.ui.clive_widget import CliveWidget
from clive.__private.ui.data_providers.hive_power_data_provider import HivePowerDataProvider
from clive.__private.ui.dialogs.operation_summary.cancel_power_down_dialog import CancelPowerDownDialog
from clive.__private.ui.get_css import get_css_from_relative_path
from clive.__private.ui.not_updated_yet import NotUpdatedYet, is_not_updated_yet
from clive.__private.ui.screens.operations.bindings.operation_action_bindings import OperationActionBindings
from clive.__private.ui.screens.operations.operation_summary.cancel_power_down import CancelPowerDown
from clive.__private.ui.widgets.buttons import CancelOneLineButton, GenerousButton
from clive.__private.ui.widgets.clive_basic import (
CliveCheckerboardTable,
......@@ -108,7 +108,7 @@ class PendingPowerDown(CliveCheckerboardTable):
@on(CancelOneLineButton.Pressed)
def push_operation_summary_screen(self) -> None:
self.app.push_screen(
CancelPowerDown(
CancelPowerDownDialog(
self.object_to_watch.content.next_vesting_withdrawal, self.object_to_watch.content.next_power_down
)
)
......