Shows a switch to include/skip MySQL restore when the selected target
has MySQL enabled. Hidden for targets without MySQL. Passes --skip-mysql
to CLI when toggled off.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Other OperationLog dialogs (crontab show, remote test, retention) no
longer display the spinner since they complete quickly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract schedule add/edit form into ScheduleEditScreen (follows target_edit pattern)
- Fix toggle active: now properly installs/removes crontab entries with error reporting
- Delete also syncs crontab to remove deleted schedule entries
- Handle case where all schedules deactivated (calls remove instead of install)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each schedule has SCHEDULE_ACTIVE field (yes/no). Table shows active
status with checkmark/cross. Toggle Active button flips state and
reinstalls crontab with only active schedules. Inactive schedules
are skipped during crontab install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch checks current crontab status on mount. Toggling ON runs
schedule install, toggling OFF runs schedule remove. Show crontab
button remains for inspection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Select a schedule in the table, click Edit to load its config into
the form. The Add button now works as Save (creates or updates).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses rich.spinner.Spinner with set_interval refresh instead of
Textual's LoadingIndicator which caused rendering failures.
Spinner shows dots animation while running, changes to checkmark on finish.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverts all spinner/loading indicator changes and debug code.
Restores the exact code from commit 0e02ba6 which was confirmed working.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LoadingIndicator was causing OperationLog ModalScreen to fail silently
during compose. Replaced with a simple Static emoji spinner (⏳→✅).
Reverted screen push patterns back to simple callback approach.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add wait_ready() to OperationLog and await it in all callers before
starting CLI commands. Ensures the modal with spinner is fully rendered
before streaming begins.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows an animated spinner next to the title while backup, restore,
retention, remote test, and schedule operations are running. Spinner
hides when the operation completes via finish().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Daily: multi-select checkboxes for days of week (empty = every day)
- Weekly: single dropdown for day of week
- Monthly: dropdown with 1st/7th/14th/21st/28th of the month
- Cron generation supports daily with specific days via SCHEDULE_DAY
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show "Schedule Hours" dropdown (1/2/3/4/6/8/12h) only for hourly type.
Show time field for hourly/daily/weekly/monthly. Show day field only
for weekly/monthly. Show cron field only for custom type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show checkable lists of existing targets and remotes instead of
free-text comma-separated inputs. Selected items are joined with
commas on save, empty selection means "all".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Default: /usr/local/gniza/workdir (root) or ~/.local/state/gniza/workdir
(user). MySQL dumps and rclone temp configs now use WORK_DIR. Configurable
via gniza.conf or TUI Settings screen. Created during install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hide all MySQL fields when MySQL is disabled. When enabled, show
databases input only for mode=select and exclude input only for
mode=all.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show only the SSH key path input (with Browse button) when auth method
is "key", and only the password input when auth method is "password".
Adds a FilePicker widget for browsing SSH key files, defaulting to
~/.ssh directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dump MySQL/MariaDB databases as part of backup snapshots. Each database
is dumped to a separate gzipped file under _mysql/ in the snapshot.
Supports all-databases mode with exclude list, or explicit database
selection. Includes TUI form fields for full configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds an input field and button to create a new folder inside the
currently selected directory, then refreshes the tree.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `is Select.BLANK` / `is not Select.BLANK` with isinstance
checks, as the sentinel identity varies across Textual versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove leading blank line from logo markup and add top margin
to menu so both start at the same visual row.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove verify screen, CLI subcommand, and all related functions.
Fix logo/menu height alignment on main menu screen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the Load Snapshots button. Snapshots are fetched
automatically when both target and remote have values,
triggered by Select.Changed events.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The worker starts streaming output before the modal screen finishes
composing. Buffer writes until on_mount fires, then flush.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use Text.from_markup() for strings containing Rich tags
so [red]...[/red] renders as colored text instead of raw tags.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
public_url="" caused IndexError in textual-serve URL builder.
Now auto-detects the machine's LAN IP when binding to 0.0.0.0
so the browser can connect to the correct WebSocket endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Setting public_url="" makes textual-serve generate relative
WebSocket URLs so the browser connects to the correct host
regardless of whether accessed via localhost or remote IP.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Install script now copies tui/ directory to install location
- Installs textual and textual-serve via pip after file copy
- __main__.py uses GNIZA_DIR env var for correct path resolution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
textual-serve shows the command string as the app title.
Set PYTHONPATH and GNIZA_DIR as real env vars so the spawned
subprocess inherits them. Add title="gniza" for clean display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
textual-serve spawns the app as a subprocess which doesn't
inherit PYTHONPATH. Bake the project root into the command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run `gniza web` or `gniza --web` to serve the TUI as a web app
on port 8080. Use --port to change. Requires textual-serve.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch widget was not rendering visibly. Use a Yes/No Select
dropdown instead which works reliably.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use full block-character logo from bin/gniza, place logo Static
and OptionList directly in Horizontal container without extra
nesting. Style with proper widths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use Horizontal container with logo-panel and menu-panel side by side,
centered vertically in the terminal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>