mirror of
https://github.com/MAKS-IT-COM/maksit-lto-backup.git
synced 2026-09-30 00:28:10 +02:00
676 lines
37 KiB
XML
676 lines
37 KiB
XML
<Window xmlns="https://github.com/avaloniaui"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:controls="using:MaksIT.LTO.Backup.UI.Controls"
|
|
x:Class="MaksIT.LTO.Backup.UI.MainWindow"
|
|
Title="MaksIT.LTO.Backup"
|
|
Icon="/Assets/icon.ico"
|
|
Width="1100"
|
|
Height="760"
|
|
MinWidth="880"
|
|
MinHeight="620">
|
|
<Grid Margin="12">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
<RowDefinition Height="160" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<TextBlock Text="MaksIT.LTO.Backup" FontSize="18" FontWeight="SemiBold" Margin="0,0,12,0" VerticalAlignment="Bottom" />
|
|
<TextBlock Text="Operations console" Classes="hint" VerticalAlignment="Bottom" />
|
|
</StackPanel>
|
|
|
|
<Border Grid.Row="1" Classes="statusBar" Margin="0,0,0,8">
|
|
<DockPanel LastChildFill="True">
|
|
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" VerticalAlignment="Center">
|
|
<CheckBox Content="Live monitor"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,10,0"
|
|
IsChecked="{Binding LiveMonitorEnabled}" />
|
|
<TextBlock Text="Every" VerticalAlignment="Center" Margin="0,0,6,0" />
|
|
<ComboBox Width="64"
|
|
ItemsSource="{Binding MonitorIntervalOptions}"
|
|
SelectedItem="{Binding SelectedMonitorInterval}"
|
|
DisplayMemberBinding="{Binding Display}" />
|
|
<Button Content="Refresh now" Command="{Binding RefreshMonitorNowCommand}" Width="96" Margin="10,0,0,0" />
|
|
</StackPanel>
|
|
<TextBlock VerticalAlignment="Center"
|
|
TextWrapping="Wrap"
|
|
Text="{Binding HeaderStatusText}" />
|
|
</DockPanel>
|
|
</Border>
|
|
|
|
<TabControl Grid.Row="2">
|
|
<TabItem Header="Monitor">
|
|
<Grid Margin="8">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<controls:GroupBox Header="Tape drive">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="120" />
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="120" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Mode:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding MonitorDriveModeText}" Margin="0,0,12,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="2" Text="Topology:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="3" Text="{Binding MonitorDriveTopologyText}" Margin="0,0,0,4" />
|
|
|
|
<TextBlock Grid.Row="1" Text="State:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding MonitorDriveStateText}" FontWeight="SemiBold" Margin="0,0,0,4" />
|
|
|
|
<TextBlock Grid.Row="2" Text="Path:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding MonitorDrivePathText}" TextWrapping="Wrap" Margin="0,0,0,4" />
|
|
|
|
<TextBlock Grid.Row="3" Text="Status code:" />
|
|
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding MonitorDriveStatusCodeText}" Margin="0,0,12,0" />
|
|
<TextBlock Grid.Row="3" Grid.Column="2" Text="Abs. block:" />
|
|
<TextBlock Grid.Row="3" Grid.Column="3" Text="{Binding MonitorDriveBlockText}" />
|
|
</Grid>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Grid.Row="1" Header="Tape library" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<StackPanel>
|
|
<Grid Margin="0,0,0,6">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="120" />
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="120" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Mode:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding MonitorLibraryModeText}" Margin="0,0,12,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="2" Text="Summary:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="0" Grid.Column="3" Text="{Binding MonitorLibrarySummaryText}" FontWeight="SemiBold" Margin="0,0,0,4" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Path:" Margin="0,0,0,4" />
|
|
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="{Binding MonitorLibraryPathText}" TextWrapping="Wrap" Margin="0,0,0,4" />
|
|
|
|
<TextBlock Grid.Row="2" Text="Drives occupied:" />
|
|
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding MonitorLibraryDrivesText}" Margin="0,0,12,0" />
|
|
<TextBlock Grid.Row="2" Grid.Column="2" Text="Updated:" />
|
|
<TextBlock Grid.Row="2" Grid.Column="3" Text="{Binding MonitorUpdatedText}" />
|
|
</Grid>
|
|
<TextBlock Classes="warning" TextWrapping="Wrap" Text="{Binding MonitorLibraryErrorText}" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<DataGrid Grid.Row="2"
|
|
ItemsSource="{Binding MonitorInventory}"
|
|
IsVisible="{Binding IsTapeLibraryUi}"
|
|
AutoGenerateColumns="False"
|
|
IsReadOnly="True">
|
|
<DataGrid.Columns>
|
|
<DataGridTextColumn Header="Slot" Binding="{Binding Slot}" Width="90" />
|
|
<DataGridTextColumn Header="Type" Binding="{Binding ElementType}" Width="120" />
|
|
<DataGridTextColumn Header="Occupied" Binding="{Binding Occupied}" Width="90" />
|
|
<DataGridTextColumn Header="Barcode" Binding="{Binding Barcode}" Width="160" />
|
|
<DataGridTextColumn Header="Cartridge" Binding="{Binding CartridgeId}" Width="*" />
|
|
</DataGrid.Columns>
|
|
</DataGrid>
|
|
</Grid>
|
|
</TabItem>
|
|
|
|
<TabItem Header="Drive" IsVisible="{Binding IsStandaloneDriveUi}">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Margin="8">
|
|
<TextBlock Classes="hint"
|
|
Margin="0,0,0,8"
|
|
TextWrapping="Wrap"
|
|
Text="Standalone drive controls. Load/eject the tape in this drive, then use the Backup tab." />
|
|
|
|
<controls:GroupBox Header="Drive">
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Load tape" Command="{Binding LoadTapeCommand}" Width="110" Margin="0,0,8,0" />
|
|
<Button Content="Eject tape" Command="{Binding EjectTapeCommand}" Width="110" Margin="0,0,8,0" />
|
|
<Button Content="Get status" Command="{Binding GetStatusCommand}" Width="110" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Cartridge memory (MAM)">
|
|
<StackPanel>
|
|
<TextBlock Classes="hint"
|
|
Margin="0,0,0,8"
|
|
TextWrapping="Wrap"
|
|
Text="Applies to the tape currently in this standalone drive." />
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Read attributes" Command="{Binding ReadAttributesCommand}" Width="120" Margin="0,0,12,0" />
|
|
<TextBlock Text="Barcode:" VerticalAlignment="Center" Margin="0,0,6,0" />
|
|
<TextBox Text="{Binding StandaloneBarcodeText}" Width="200" Margin="0,0,12,0" />
|
|
<Button Content="Write barcode" Command="{Binding WriteStandaloneBarcodeCommand}" Width="110" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<TabItem Header="Library" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<Grid Margin="8">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Text="Library operations require Topology = TapeLibrary in Settings."
|
|
TextWrapping="Wrap"
|
|
Margin="0,0,0,8"
|
|
IsVisible="False" />
|
|
|
|
<controls:GroupBox Grid.Row="1" Header="Loaded cartridge" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,6">
|
|
<TextBlock Text="Active drive:" VerticalAlignment="Center" Margin="0,0,8,0" />
|
|
<ComboBox Width="460"
|
|
ItemsSource="{Binding OccupiedLibraryDrives}"
|
|
SelectedItem="{Binding SelectedOccupiedDrive}"
|
|
DisplayMemberBinding="{Binding Summary}" />
|
|
</StackPanel>
|
|
<TextBlock FontWeight="SemiBold"
|
|
Margin="0,0,0,4"
|
|
Text="{Binding LibraryLoadedSummaryText}" />
|
|
<TextBlock Classes="hint"
|
|
TextWrapping="Wrap"
|
|
Margin="0,0,0,8"
|
|
Text="{Binding LibraryLoadedHintText}" />
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Read MAM" Command="{Binding ReadAttributesCommand}" Width="100" Margin="0,0,12,0" />
|
|
<TextBlock Text="Barcode:" VerticalAlignment="Center" Margin="0,0,6,0" />
|
|
<TextBox Width="200"
|
|
Margin="0,0,12,0"
|
|
Text="{Binding LibraryBarcodeText}"
|
|
ToolTip.Tip="Writes MAM barcode for the cartridge in the selected drive bay" />
|
|
<Button Content="Assign barcode" Command="{Binding WriteLibraryBarcodeCommand}" Width="120" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Grid.Row="2" Header="Load / unload" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<StackPanel>
|
|
<Button Content="Refresh inventory" Command="{Binding RefreshInventoryCommand}" Width="140" HorizontalAlignment="Left" Margin="0,0,0,8" />
|
|
|
|
<Grid Margin="0,0,0,8">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="140" />
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Cartridge (source):" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="0" Grid.Column="1"
|
|
Margin="0,0,8,6"
|
|
ItemsSource="{Binding LoadSources}"
|
|
SelectedItem="{Binding SelectedLoadSource}"
|
|
DisplayMemberBinding="{Binding Display}"
|
|
ToolTip.Tip="Occupied storage slot or drive bay to take the cartridge from" />
|
|
<Button Grid.Row="0" Grid.Column="2"
|
|
Content="Load into drive"
|
|
Command="{Binding LoadIntoDriveCommand}"
|
|
Width="120"
|
|
Margin="0,0,0,6"
|
|
ToolTip.Tip="Move the selected cartridge into the selected empty drive bay" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Target drive bay:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="1" Grid.Column="1"
|
|
Margin="0,0,8,6"
|
|
ItemsSource="{Binding LoadDrives}"
|
|
SelectedItem="{Binding SelectedLoadDrive}"
|
|
DisplayMemberBinding="{Binding Display}"
|
|
ToolTip.Tip="Empty drive bay (e.g. 1000, 1001)" />
|
|
|
|
<TextBlock Grid.Row="2" Text="Unload from drive:" VerticalAlignment="Center" />
|
|
<ComboBox Grid.Row="2" Grid.Column="1"
|
|
Margin="0,0,8,0"
|
|
ItemsSource="{Binding UnloadDrives}"
|
|
SelectedItem="{Binding SelectedUnloadDrive}"
|
|
DisplayMemberBinding="{Binding Display}"
|
|
ToolTip.Tip="Drive bay that currently holds a cartridge" />
|
|
<Button Grid.Row="2" Grid.Column="2"
|
|
Content="Unload to storage"
|
|
Command="{Binding UnloadFromDriveCommand}"
|
|
Width="120"
|
|
ToolTip.Tip="Move the cartridge from the selected drive into the first empty storage slot" />
|
|
</Grid>
|
|
|
|
<Expander Header="Advanced: move any slot → any slot">
|
|
<StackPanel Margin="0,6,0,0">
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,4">
|
|
<TextBlock Text="From:" VerticalAlignment="Center" Margin="0,0,6,0" />
|
|
<ComboBox Width="300" Margin="0,0,12,0"
|
|
ItemsSource="{Binding SourceSlots}"
|
|
SelectedItem="{Binding SelectedSourceSlot}"
|
|
DisplayMemberBinding="{Binding Display}" />
|
|
<TextBlock Text="To:" VerticalAlignment="Center" Margin="0,0,6,0" />
|
|
<ComboBox Width="300" Margin="0,0,12,0"
|
|
ItemsSource="{Binding DestinationSlots}"
|
|
SelectedItem="{Binding SelectedDestinationSlot}"
|
|
DisplayMemberBinding="{Binding Display}" />
|
|
<Button Content="Move" Command="{Binding MoveMediumCommand}" Width="80" />
|
|
</StackPanel>
|
|
<TextBlock Classes="hint"
|
|
TextWrapping="Wrap"
|
|
Text="Use this for slot-to-slot moves that are not a simple load/unload." />
|
|
</StackPanel>
|
|
</Expander>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<TextBlock Grid.Row="3" Text="Inventory" FontWeight="SemiBold" Margin="0,0,0,4" IsVisible="{Binding IsTapeLibraryUi}" />
|
|
<DataGrid Grid.Row="4"
|
|
ItemsSource="{Binding LibraryInventory}"
|
|
IsVisible="{Binding IsTapeLibraryUi}"
|
|
AutoGenerateColumns="False"
|
|
IsReadOnly="True">
|
|
<DataGrid.Columns>
|
|
<DataGridTextColumn Header="Slot" Binding="{Binding Slot}" Width="100" />
|
|
<DataGridTextColumn Header="Type" Binding="{Binding ElementType}" Width="160" />
|
|
<DataGridTextColumn Header="Barcode" Binding="{Binding Barcode}" Width="200" />
|
|
<DataGridTextColumn Header="Cartridge" Binding="{Binding CartridgeId}" Width="*" />
|
|
</DataGrid.Columns>
|
|
</DataGrid>
|
|
</Grid>
|
|
</TabItem>
|
|
|
|
<TabItem Header="Backup">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Margin="8">
|
|
<controls:GroupBox Header="Loaded cartridge">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,6" IsVisible="{Binding IsSavedTapeLibrary}">
|
|
<TextBlock Text="Drive:" VerticalAlignment="Center" Margin="0,0,8,0" Width="64" />
|
|
<ComboBox Width="500"
|
|
ItemsSource="{Binding OccupiedLibraryDrives}"
|
|
SelectedItem="{Binding SelectedOccupiedDrive}"
|
|
DisplayMemberBinding="{Binding Summary}" />
|
|
</StackPanel>
|
|
<TextBlock FontWeight="SemiBold"
|
|
Margin="0,0,0,4"
|
|
Text="{Binding BackupLoadedSummaryText}" />
|
|
<TextBlock Classes="hint"
|
|
TextWrapping="Wrap"
|
|
Text="{Binding BackupLoadedHintText}" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Backup job">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,6">
|
|
<TextBlock Text="Job:" VerticalAlignment="Center" Margin="0,0,8,0" Width="64" />
|
|
<ComboBox Width="400"
|
|
ItemsSource="{Binding BackupJobs}"
|
|
SelectedItem="{Binding SelectedBackup}"
|
|
DisplayMemberBinding="{Binding Name}" />
|
|
</StackPanel>
|
|
<TextBlock Classes="hint"
|
|
TextWrapping="Wrap"
|
|
Text="{Binding JobSummaryText}" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Operations" IsEnabled="{Binding IsCartridgeLoaded}">
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Run backup" Command="{Binding RunBackupCommand}" Width="120" Margin="0,0,8,0" />
|
|
<Button Content="Run restore" Command="{Binding RunRestoreCommand}" Width="120" Margin="0,0,8,0" />
|
|
<Button Content="Short erase" Command="{Binding EraseCommand}" Width="100" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<TabItem Header="Settings">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Margin="8">
|
|
<TextBlock Classes="hint"
|
|
Margin="0,0,0,8"
|
|
TextWrapping="Wrap"
|
|
Text="Edits apply to configuration.json used by both console and Avalonia UI." />
|
|
|
|
<controls:GroupBox Header="Device">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Device mode:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="0" Grid.Column="1" Margin="0,0,0,6" Width="200" HorizontalAlignment="Left"
|
|
ItemsSource="{Binding DeviceModeOptions}"
|
|
SelectedItem="{Binding DeviceMode}" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Topology:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="1" Grid.Column="1" Margin="0,0,0,6" Width="200" HorizontalAlignment="Left"
|
|
ItemsSource="{Binding TopologyOptions}"
|
|
SelectedItem="{Binding SelectedTopology}" />
|
|
|
|
<TextBlock Grid.Row="2" Text="Tape path:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TapePathText}" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="3" Text="Library path:" VerticalAlignment="Center" Margin="0,0,0,6"
|
|
IsVisible="{Binding IsTapeLibraryUi}" />
|
|
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding LibraryPathText}" Margin="0,0,0,6"
|
|
IsVisible="{Binding IsTapeLibraryUi}" />
|
|
|
|
<TextBlock Grid.Row="4" Text="Write delay (ms):" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding WriteDelayText}" Width="100" HorizontalAlignment="Left" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="5" Text="Fail-fast checksum:" VerticalAlignment="Center" />
|
|
<CheckBox Grid.Row="5" Grid.Column="1" Content="Abort restore on checksum mismatch" VerticalAlignment="Center"
|
|
IsChecked="{Binding FailFastChecksum}" />
|
|
</Grid>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Emulator">
|
|
<StackPanel>
|
|
<Grid Margin="0,0,0,6">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock Text="Data directory:" VerticalAlignment="Center" />
|
|
<TextBox Grid.Column="1" Text="{Binding EmulatorDataDirText}" />
|
|
</Grid>
|
|
<Grid IsVisible="{Binding IsTapeLibraryUi}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Slots:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding EmulatorSlotCountText}" Width="100" HorizontalAlignment="Left" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Drives:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding EmulatorDriveCountText}" Width="100" HorizontalAlignment="Left" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="2" Text="I/E ports:" VerticalAlignment="Center" />
|
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding EmulatorIePortCountText}" Width="100" HorizontalAlignment="Left" />
|
|
</Grid>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Backup jobs">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<TextBlock Text="Job:" VerticalAlignment="Center" Margin="0,0,8,0" Width="64" />
|
|
<ComboBox Width="400"
|
|
ItemsSource="{Binding BackupJobs}"
|
|
SelectedItem="{Binding SelectedSettingsBackup}"
|
|
DisplayMemberBinding="{Binding Name}" />
|
|
<CheckBox Content="Disabled" Margin="16,0,0,0" VerticalAlignment="Center"
|
|
IsChecked="{Binding BackupDisabled}"
|
|
ToolTip.Tip="When checked, aggregations skip this job." />
|
|
</StackPanel>
|
|
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Name:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding BackupNameText}" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Barcode:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding BackupBarcodeText}" Margin="0,0,0,6"
|
|
ToolTip.Tip="Standalone / single-tape MAM label. Library pools use Tape rotation below." />
|
|
|
|
<TextBlock Grid.Row="2" Text="LTO generation:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="2" Grid.Column="1" Width="140" HorizontalAlignment="Left" Margin="0,0,0,6"
|
|
ItemsSource="{Binding LtoGenerationOptions}"
|
|
SelectedItem="{Binding BackupLtoGen}" />
|
|
|
|
<TextBlock Grid.Row="3" Text="Write mode:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<ComboBox Grid.Row="3" Grid.Column="1" Width="140" HorizontalAlignment="Left" Margin="0,0,0,6"
|
|
ItemsSource="{Binding WriteModeOptions}"
|
|
SelectedItem="{Binding BackupWriteMode}" />
|
|
|
|
<TextBlock Grid.Row="4" Text="Source path:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding BackupSourcePathText}" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="5" Text="Destination path:" VerticalAlignment="Center" />
|
|
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding BackupDestinationPathText}" />
|
|
</Grid>
|
|
|
|
<controls:GroupBox Header="Tape rotation (library)" Margin="0,12,0,0" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<StackPanel>
|
|
<TextBlock Classes="hint" TextWrapping="Wrap" Margin="0,0,0,6"
|
|
Text="Media pool for this job. Pick barcodes not assigned to other jobs. Never-used tapes first, then oldest LastUsedUtc. Drive claim is automatic." />
|
|
<DataGrid Height="120"
|
|
AutoGenerateColumns="False"
|
|
IsReadOnly="False"
|
|
Margin="0,0,0,6"
|
|
ItemsSource="{Binding TapeRows}"
|
|
SelectedItem="{Binding SelectedTapeRow}">
|
|
<DataGrid.Columns>
|
|
<DataGridTextColumn Header="Barcode" Binding="{Binding Barcode}" Width="*" />
|
|
<DataGridTextColumn Header="Last used (UTC)" Binding="{Binding LastUsedUtcDisplay}" Width="220" IsReadOnly="True" />
|
|
</DataGrid.Columns>
|
|
</DataGrid>
|
|
<StackPanel Orientation="Horizontal">
|
|
<ComboBox Width="320"
|
|
Margin="0,0,8,0"
|
|
PlaceholderText="Available library barcodes"
|
|
ItemsSource="{Binding AvailableTapes}"
|
|
SelectedItem="{Binding SelectedAvailableTape}"
|
|
DisplayMemberBinding="{Binding Display}" />
|
|
<Button Content="Refresh list" Command="{Binding RefreshAvailableTapesCommand}" Width="100" Margin="0,0,8,0"
|
|
ToolTip.Tip="Reload unassigned barcodes from library inventory" />
|
|
<Button Content="Add tape" Command="{Binding AddTapeCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Remove selected" Command="{Binding RemoveTapeCommand}" Width="120" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Aggregations (schedule waves)" IsVisible="{Binding IsTapeLibraryUi}">
|
|
<StackPanel>
|
|
<TextBlock Classes="hint" TextWrapping="Wrap" Margin="0,0,0,6"
|
|
Text="Worker schedules aggregations only. Each wave runs its jobs sequentially with exclusive lease and automatic drive claim/unload." />
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<TextBlock Text="Wave:" VerticalAlignment="Center" Margin="0,0,8,0" Width="64" />
|
|
<ComboBox Width="280"
|
|
ItemsSource="{Binding Aggregations}"
|
|
SelectedItem="{Binding SelectedAggregation}"
|
|
DisplayMemberBinding="{Binding Name}"
|
|
Margin="0,0,8,0" />
|
|
<CheckBox Content="Disabled" VerticalAlignment="Center" Margin="0,0,8,0"
|
|
IsChecked="{Binding AggregationDisabled}" />
|
|
<Button Content="Add wave" Command="{Binding AddAggregationCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Remove wave" Command="{Binding RemoveAggregationCommand}" Width="100" />
|
|
</StackPanel>
|
|
<Grid Margin="0,0,0,8">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock Text="Name:" VerticalAlignment="Center" />
|
|
<TextBox Grid.Column="1" Text="{Binding AggregationNameText}" />
|
|
</Grid>
|
|
<TextBlock Text="Jobs in this wave (ordered):" FontWeight="SemiBold" Margin="0,0,0,4" />
|
|
<ListBox Height="90" Margin="0,0,0,6"
|
|
ItemsSource="{Binding AggregationJobNames}"
|
|
SelectedItem="{Binding SelectedAggregationJobName}" />
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<ComboBox Width="280" Margin="0,0,8,0"
|
|
ItemsSource="{Binding BackupJobs}"
|
|
SelectedItem="{Binding SelectedAggregationAddJob}"
|
|
DisplayMemberBinding="{Binding Name}"
|
|
PlaceholderText="Backup job to add" />
|
|
<Button Content="Add job" Command="{Binding AggregationAddJobCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Remove job" Command="{Binding AggregationRemoveJobCommand}" Width="100" Margin="0,0,8,0" />
|
|
<Button Content="Move up" Command="{Binding AggregationMoveJobUpCommand}" Width="80" Margin="0,0,8,0" />
|
|
<Button Content="Move down" Command="{Binding AggregationMoveJobDownCommand}" Width="90" />
|
|
</StackPanel>
|
|
|
|
<controls:GroupBox Header="Months (empty = all months)">
|
|
<ItemsControl ItemsSource="{Binding MonthOptions}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<WrapPanel />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<CheckBox Content="{Binding Label}" IsChecked="{Binding IsChecked}" Margin="0,0,8,4" />
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Weekdays (empty = all days)">
|
|
<ItemsControl ItemsSource="{Binding WeekdayOptions}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<WrapPanel />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<CheckBox Content="{Binding Label}" IsChecked="{Binding IsChecked}" Margin="0,0,8,4" />
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Run Times (UTC)">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,6">
|
|
<TextBox Width="80" Text="{Binding NewRunTimeText}" Margin="0,0,8,0" />
|
|
<Button Content="Add" Command="{Binding AddRunTimeCommand}" Width="60" Margin="0,0,8,0" />
|
|
<Button Content="Remove" Command="{Binding RemoveRunTimeCommand}" Width="70" />
|
|
</StackPanel>
|
|
<ListBox Height="80"
|
|
ItemsSource="{Binding RunTimes}"
|
|
SelectedItem="{Binding SelectedRunTime}" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Minimum Interval">
|
|
<StackPanel Orientation="Horizontal">
|
|
<TextBox Width="60" Text="{Binding MinIntervalMinutesText}" Margin="0,0,8,0" />
|
|
<TextBlock Text="minutes between wave starts" VerticalAlignment="Center" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<TextBlock Classes="hint" Margin="0,6,0,0" Text="{Binding LastRunUtcText}" />
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
|
<Button Content="Save configuration" Command="{Binding SaveConfigurationCommand}" Width="140" Margin="0,0,8,0" />
|
|
<Button Content="Reload from disk" Command="{Binding ReloadConfigurationCommand}" Width="130" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
|
|
<TabItem Header="Service">
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
|
<StackPanel Margin="8">
|
|
<TextBlock Classes="hint" TextWrapping="Wrap" Margin="0,0,0,8"
|
|
Text="Install, start, and stop the LTO backup Worker (Windows service or systemd). Requires elevation for install/uninstall." />
|
|
|
|
<controls:GroupBox Header="Worker status">
|
|
<StackPanel>
|
|
<TextBlock FontWeight="SemiBold" Margin="0,0,0,6" Text="{Binding ServiceStatusText}" />
|
|
<TextBlock Classes="hint" TextWrapping="Wrap" Margin="0,0,0,8" Text="{Binding ServiceExePathText}" />
|
|
<StackPanel Orientation="Horizontal">
|
|
<Button Content="Refresh" Command="{Binding ServiceRefreshCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Install" Command="{Binding ServiceInstallCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Uninstall" Command="{Binding ServiceUninstallCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Start" Command="{Binding ServiceStartCommand}" Width="90" Margin="0,0,8,0" />
|
|
<Button Content="Stop" Command="{Binding ServiceStopCommand}" Width="90" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</controls:GroupBox>
|
|
|
|
<controls:GroupBox Header="Service settings">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="160" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
|
|
<TextBlock Grid.Row="0" Text="Service name:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ServiceNameText}" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="1" Text="Description:" VerticalAlignment="Center" Margin="0,0,0,6" />
|
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ServiceDescriptionText}" Margin="0,0,0,6" />
|
|
|
|
<TextBlock Grid.Row="2" Text="Executable path:" VerticalAlignment="Center" />
|
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding ServiceExePathSettingText}"
|
|
PlaceholderText="Optional override; empty = resolve next to UI" />
|
|
</Grid>
|
|
</controls:GroupBox>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</TabItem>
|
|
</TabControl>
|
|
|
|
<controls:GroupBox Grid.Row="3" Header="Log" Margin="0,8,0,0" Padding="6">
|
|
<TextBox Name="LogTextBox"
|
|
Text="{Binding LogText, Mode=OneWay}"
|
|
AcceptsReturn="True"
|
|
TextWrapping="Wrap"
|
|
IsReadOnly="True"
|
|
BorderThickness="0"
|
|
Background="Transparent" />
|
|
</controls:GroupBox>
|
|
</Grid>
|
|
</Window>
|