mirror of
https://github.com/openziti/desktop-edge-win.git
synced 2026-10-12 15:58:34 +00:00
+412
-10
@@ -1,7 +1,8 @@
|
||||
<Application x:Class="ZitiDesktopEdge.App"
|
||||
<Application
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ZitiDesktopEdge"
|
||||
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" x:Class="ZitiDesktopEdge.App"
|
||||
ShutdownMode="OnExplicitShutdown"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
@@ -18,7 +19,7 @@
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Grid x:Name="grid">
|
||||
<Border x:Name="border" CornerRadius="12" BorderThickness="0"></Border>
|
||||
<Border x:Name="border" CornerRadius="12" BorderThickness="0"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
@@ -33,7 +34,7 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="FrameworkElement" x:Key="VisibleAnimation">
|
||||
<Style TargetType="{x:Type FrameworkElement}" x:Key="VisibleAnimation">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Setter Property="Opacity" Value="0"/>
|
||||
<Style.Triggers>
|
||||
@@ -49,13 +50,13 @@
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MyButton" TargetType="Button">
|
||||
<Style x:Key="MyButton" TargetType="{x:Type Button}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
@@ -92,7 +93,8 @@
|
||||
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="true" />
|
||||
<Setter Property="Foreground" Value="#d4d9e2" />
|
||||
<Setter Property="Background" Value="#000F0F23" /> <!-- invalid on purpose -->
|
||||
<Setter Property="Background" Value="#000F0F23" />
|
||||
<!-- invalid on purpose -->
|
||||
<Setter Property="Width" Value="3" />
|
||||
<Setter Property="Opacity" Value="0.6"/>
|
||||
<Setter Property="Template">
|
||||
@@ -149,14 +151,14 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
|
||||
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<Grid>
|
||||
<Border CornerRadius="5,0,0,5"
|
||||
BorderThickness="1"
|
||||
<Border CornerRadius="7"
|
||||
BorderThickness="4"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="Black">
|
||||
<ScrollViewer x:Name="PART_ContentHost"/>
|
||||
@@ -167,5 +169,405 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="FocusVisual">
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle StrokeDashArray="1 2" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" Margin="2"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<LinearGradientBrush x:Key="ComboBox.Static.Background" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFFFFFFF" Offset="0.0"/>
|
||||
<GradientStop Color="#FFFFFFFF" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FFACACAC"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Editable.Background" Color="#FFFFFFFF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Editable.Border" Color="#FFABADB3"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Editable.Button.Background" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Editable.Button.Border" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="ComboBox.MouseOver.Glyph" Color="#FF000000"/>
|
||||
<LinearGradientBrush x:Key="ComboBox.MouseOver.Background" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFECF4FC" Offset="0.0"/>
|
||||
<GradientStop Color="#FFDCECFC" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="ComboBox.MouseOver.Border" Color="#FF7EB4EA"/>
|
||||
<SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Background" Color="#FFFFFFFF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Border" Color="#FF7EB4EA"/>
|
||||
<LinearGradientBrush x:Key="ComboBox.MouseOver.Editable.Button.Background" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFEBF4FC" Offset="0.0"/>
|
||||
<GradientStop Color="#FFDCECFC" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="ComboBox.MouseOver.Editable.Button.Border" Color="#FF7EB4EA"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Pressed.Glyph" Color="#FF000000"/>
|
||||
<LinearGradientBrush x:Key="ComboBox.Pressed.Background" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFDAECFC" Offset="0.0"/>
|
||||
<GradientStop Color="#FFC4E0FC" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="ComboBox.Pressed.Border" Color="#FF569DE5"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Pressed.Editable.Background" Color="#FFFFFFFF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Pressed.Editable.Border" Color="#FF569DE5"/>
|
||||
<LinearGradientBrush x:Key="ComboBox.Pressed.Editable.Button.Background" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFDAEBFC" Offset="0.0"/>
|
||||
<GradientStop Color="#FFC4E0FC" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="ComboBox.Pressed.Editable.Button.Border" Color="#FF569DE5"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Glyph" Color="#FFBFBFBF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Background" Color="#FFF0F0F0"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Border" Color="#FFD9D9D9"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Editable.Background" Color="#FFFFFFFF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Editable.Border" Color="#FFBFBFBF"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Editable.Button.Background" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Disabled.Editable.Button.Border" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="ComboBox.Static.Glyph" Color="#FF606060"/>
|
||||
<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Focusable" Value="false"/>
|
||||
<Setter Property="ClickMode" Value="Press"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Border x:Name="templateRoot" SnapsToDevicePixels="true" Background="{StaticResource ComboBox.Static.Background}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="7" BorderBrush="{StaticResource ComboBox.Static.Border}">
|
||||
<Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Transparent">
|
||||
<Path x:Name="arrow" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Fill="{StaticResource ComboBox.Static.Glyph}" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>
|
||||
</Border>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.MouseOver.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Pressed.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Disabled.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}">
|
||||
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
|
||||
<Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
|
||||
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
|
||||
<ScrollViewer x:Name="DropDownScrollViewer">
|
||||
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
|
||||
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
|
||||
</Canvas>
|
||||
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Themes:SystemDropShadowChrome>
|
||||
</Popup>
|
||||
<ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
|
||||
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
|
||||
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
|
||||
<Setter Property="Color" TargetName="shadow" Value="#71000000"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasItems" Value="false">
|
||||
<Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsGrouping" Value="true"/>
|
||||
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
|
||||
</MultiTrigger>
|
||||
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
|
||||
<Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
<Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<SolidColorBrush x:Key="TextBox.Static.Background" Color="#FFFFFFFF"/>
|
||||
<Style x:Key="ComboBoxEditableTextBox" TargetType="{x:Type TextBox}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="AllowDrop" Value="true"/>
|
||||
<Setter Property="MinWidth" Value="0"/>
|
||||
<Setter Property="MinHeight" Value="0"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<ScrollViewer x:Name="PART_ContentHost" Background="Transparent" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<ControlTemplate x:Key="ComboBoxEditableTemplate" TargetType="{x:Type ComboBox}">
|
||||
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
|
||||
<Themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
|
||||
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
|
||||
<ScrollViewer x:Name="DropDownScrollViewer">
|
||||
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
|
||||
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
|
||||
</Canvas>
|
||||
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Themes:SystemDropShadowChrome>
|
||||
</Popup>
|
||||
<ToggleButton x:Name="toggleButton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
|
||||
<Border x:Name="border" Background="{StaticResource TextBox.Static.Background}" Margin="{TemplateBinding BorderThickness}">
|
||||
<TextBox x:Name="PART_EditableTextBox" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" Margin="{TemplateBinding Padding}" Style="{StaticResource ComboBoxEditableTextBox}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsKeyboardFocusWithin" Value="true">
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
|
||||
<Setter Property="Margin" TargetName="shadow" Value="0,0,5,5"/>
|
||||
<Setter Property="Color" TargetName="shadow" Value="#71000000"/>
|
||||
</Trigger>
|
||||
<Trigger Property="HasItems" Value="false">
|
||||
<Setter Property="Height" TargetName="dropDownBorder" Value="95"/>
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsGrouping" Value="true"/>
|
||||
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
|
||||
</MultiTrigger>
|
||||
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
|
||||
<Setter Property="Canvas.Top" TargetName="opaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
<Setter Property="Canvas.Left" TargetName="opaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<Style x:Key="ComboStyle" TargetType="{x:Type ComboBox}">
|
||||
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
|
||||
<Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="Padding" Value="6,3,5,3"/>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEditable" Value="true">
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
<Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<LinearGradientBrush x:Key="ComboBox.Static.Background2" EndPoint="0,1" StartPoint="0,0">
|
||||
<GradientStop Color="#FFF0F0F0" Offset="0.0"/>
|
||||
<GradientStop Color="#FFE5E5E5" Offset="1.0"/>
|
||||
</LinearGradientBrush>
|
||||
<Style x:Key="ComboBoxToggleButton2" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="true"/>
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Focusable" Value="false"/>
|
||||
<Setter Property="ClickMode" Value="Press"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Border x:Name="templateRoot" CornerRadius="7" BorderThickness="0" Background="Gray" SnapsToDevicePixels="true">
|
||||
<Border x:Name="splitBorder" BorderBrush="Transparent" BorderThickness="1" HorizontalAlignment="Right" Margin="0" SnapsToDevicePixels="true" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
|
||||
<Path x:Name="arrow" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z" Fill="{StaticResource ComboBox.Static.Glyph}" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Static.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Static.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.MouseOver.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.MouseOver.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.MouseOver.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Pressed.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}" Value="true"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Pressed.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Pressed.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter Property="Fill" TargetName="arrow" Value="{StaticResource ComboBox.Disabled.Glyph}"/>
|
||||
</Trigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/>
|
||||
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource ComboBox.Disabled.Editable.Border}"/>
|
||||
<Setter Property="Background" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Background}"/>
|
||||
<Setter Property="BorderBrush" TargetName="splitBorder" Value="{StaticResource ComboBox.Disabled.Editable.Button.Border}"/>
|
||||
</MultiDataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="FilterComboStyle" TargetType="{x:Type ComboBox}">
|
||||
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
|
||||
<Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
|
||||
<Setter Property="Padding" Value="6,3,5,3"/>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
|
||||
<Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEditable" Value="true">
|
||||
<Setter Property="IsTabStop" Value="false"/>
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
<Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -202,7 +202,7 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<ScrollViewer Name="IdListScroller" MinHeight="60" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" CanContentScroll="True" ClipToBounds="True" PanningMode="VerticalOnly" PanningRatio=".1">
|
||||
<ScrollViewer Name="IdListScroller" MinHeight="60" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}" CanContentScroll="True" ClipToBounds="True" PanningMode="VerticalOnly" PanningRatio=".1">
|
||||
<StackPanel Name="IdList" Orientation="Vertical" IsItemsHost="False" LayoutUpdated="IdList_LayoutUpdated" FocusVisualStyle="{x:Null}"></StackPanel>
|
||||
</ScrollViewer>
|
||||
<Grid HorizontalAlignment="Stretch" Margin="0,20,0,10" Width="Auto">
|
||||
@@ -217,7 +217,7 @@
|
||||
<!-- Menu UI -->
|
||||
<local:MainMenu x:Name="MainMenu" Visibility="Collapsed"></local:MainMenu>
|
||||
<!-- ID Detail UI -->
|
||||
<local:IdentityDetails x:Name="IdentityMenu" Visibility="Collapsed" OnMFAToggled="MFAToggled" Authenticate="ShowAuthenticate" Recovery="ShowRecovery"></local:IdentityDetails>
|
||||
<local:IdentityDetails x:Name="IdentityMenu" Visibility="Collapsed" OnMFAToggled="MFAToggled" Authenticate="ShowAuthenticate" Recovery="ShowRecovery" OnLoading="DoLoading"></local:IdentityDetails>
|
||||
|
||||
<!-- Modal Background -->
|
||||
<Rectangle x:Name="ModalBg" Margin="10,10,10,10" Fill="Black" RadiusY="10" RadiusX="10" Opacity="0" Visibility="Collapsed"></Rectangle>
|
||||
@@ -247,7 +247,8 @@
|
||||
<RowDefinition Height="60"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Image Source="/Assets/Images/WarningRed.png" Grid.Column="0" Width="30" Grid.Row="1" Height="30" Margin="0,0,0,0"></Image>
|
||||
<Image x:Name="RedBlurb" Source="/Assets/Images/WarningRed.png" Grid.Column="0" Width="30" Grid.Row="1" Height="30" Margin="0,0,0,0"></Image>
|
||||
<Image x:Name="InfoBlurb" Visibility="Collapsed" Source="/Assets/Images/Warning.png" Grid.Column="0" Width="30" Grid.Row="1" Height="30" Margin="0,0,0,0"></Image>
|
||||
<Label x:Name="Blurb" Content="An Update is available!" MouseUp="BlurbAction" Grid.Column="1" Padding="0,0,0,0" Grid.Row="1" Margin="0,0,0,0" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="#000000" FontSize="12" Cursor="Hand" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
|
||||
<Image Source="/Assets/Images/closeBlack.png" Grid.Column="2" Width="10" Height="10" Grid.Row="1" Margin="0,0,0,0" Cursor="Hand" MouseUp="DoHideBlurb"></Image>
|
||||
</Grid>
|
||||
|
||||
@@ -156,6 +156,11 @@ namespace ZitiDesktopEdge {
|
||||
this.ShowMFA(identity, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show MFA for the identity and set the type of screen to show
|
||||
/// </summary>
|
||||
/// <param name="identity">The Identity that is currently active</param>
|
||||
/// <param name="type">The type of screen to show - 1 Setup, 2 Authenticate, 3 Remove MFA, 4 Regenerate Codes</param>
|
||||
private void ShowMFA(ZitiIdentity identity, int type) {
|
||||
MFASetup.Opacity = 0;
|
||||
MFASetup.Visibility = Visibility.Visible;
|
||||
@@ -342,10 +347,18 @@ namespace ZitiDesktopEdge {
|
||||
this.IdentityMenu.MainWindow = this;
|
||||
SetNotifyIcon("white");
|
||||
|
||||
this.PreviewKeyDown += KeyPressed;
|
||||
MFASetup.OnLoad += MFASetup_OnLoad;
|
||||
IdentityMenu.OnMessage += IdentityMenu_OnMessage;
|
||||
}
|
||||
|
||||
private void KeyPressed(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.Escape) {
|
||||
if (IdentityMenu.Visibility == Visibility.Visible) IdentityMenu.Visibility = Visibility.Collapsed;
|
||||
else if (MainMenu.Visibility == Visibility.Visible) MainMenu.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void MFASetup_OnLoad(bool isComplete, string title, string message) {
|
||||
if (isComplete) HideLoad();
|
||||
else ShowLoad(title, message);
|
||||
@@ -503,6 +516,7 @@ namespace ZitiDesktopEdge {
|
||||
Application.Current.Properties.Add("Identities", new List<ZitiIdentity>());
|
||||
MainMenu.OnAttachmentChange += AttachmentChanged;
|
||||
MainMenu.OnLogLevelChanged += LogLevelChanged;
|
||||
MainMenu.OnShowBlurb += MainMenu_OnShowBlurb;
|
||||
IdentityMenu.OnError += IdentityMenu_OnError;
|
||||
|
||||
try {
|
||||
@@ -524,7 +538,11 @@ namespace ZitiDesktopEdge {
|
||||
Placement();
|
||||
}
|
||||
|
||||
private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) {
|
||||
private void MainMenu_OnShowBlurb(string message) {
|
||||
_ = ShowBlurbAsync(message, "", "info");
|
||||
}
|
||||
|
||||
private void ServiceClient_OnBulkServiceEvent(object sender, BulkServiceEvent e) {
|
||||
var found = identities.Find(id => id.Fingerprint == e.Fingerprint);
|
||||
if (found == null) {
|
||||
logger.Warn($"{e.Action} service event for {e.Fingerprint} but the provided identity fingerprint was not found!");
|
||||
@@ -1287,7 +1305,14 @@ namespace ZitiDesktopEdge {
|
||||
/// </summary>
|
||||
/// <param name="message">The message to show</param>
|
||||
/// <param name="url">The url or action name to execute</param>
|
||||
public async Task ShowBlurbAsync(string message, string url) {
|
||||
public async Task ShowBlurbAsync(string message, string url, string level="error") {
|
||||
RedBlurb.Visibility = Visibility.Collapsed;
|
||||
InfoBlurb.Visibility = Visibility.Collapsed;
|
||||
if (level=="error") {
|
||||
RedBlurb.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
InfoBlurb.Visibility = Visibility.Visible;
|
||||
}
|
||||
Blurb.Content = message;
|
||||
_blurbUrl = url;
|
||||
BlurbArea.Visibility = Visibility.Visible;
|
||||
@@ -1377,6 +1402,11 @@ namespace ZitiDesktopEdge {
|
||||
someCommand = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void DoLoading(bool isComplete) {
|
||||
if (isComplete) HideLoad();
|
||||
else ShowLoad("Loading", "Please Wait.");
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionCommand : ICommand {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZitiDesktopEdge.Models {
|
||||
public class FilterData {
|
||||
|
||||
public FilterData():this("", "", "asc") { }
|
||||
|
||||
public FilterData(string searchFor, string sortBy, string sortHow) {
|
||||
SearchFor = searchFor;
|
||||
SortBy = sortBy;
|
||||
SortHow = sortHow;
|
||||
}
|
||||
|
||||
public string SearchFor { get; set; }
|
||||
public string SortBy { get; set; }
|
||||
public string SortHow { get; set; }
|
||||
}
|
||||
}
|
||||
+235
-127
@@ -1,133 +1,241 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ZitiDesktopEdge.DataStructures;
|
||||
|
||||
namespace ZitiDesktopEdge.Models {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
using ZitiDesktopEdge.DataStructures;
|
||||
|
||||
namespace ZitiDesktopEdge.Models {
|
||||
public class ZitiService {
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public string Name { get; set; }
|
||||
public string[] Protocols { get; set; }
|
||||
public Address[] Addresses { get; set; }
|
||||
public PortRange[] Ports { get; set; }
|
||||
public PostureCheck[] PostureChecks { get; set; }
|
||||
public bool OwnsIntercept { get; set; }
|
||||
public string AssignedIP { get; set; }
|
||||
|
||||
private bool failingPostureCheck;
|
||||
public bool HasFailingPostureCheck() {
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public string Name { get; set; }
|
||||
public string[] Protocols { get; set; }
|
||||
public Address[] Addresses { get; set; }
|
||||
public PortRange[] Ports { get; set; }
|
||||
public PostureCheck[] PostureChecks { get; set; }
|
||||
public bool OwnsIntercept { get; set; }
|
||||
public string AssignedIP { get; set; }
|
||||
|
||||
private bool failingPostureCheck;
|
||||
public bool HasFailingPostureCheck() {
|
||||
return failingPostureCheck;
|
||||
}
|
||||
public bool IsAccessable { get; set; }
|
||||
|
||||
public string Warning {
|
||||
get {
|
||||
if (this.OwnsIntercept) {
|
||||
return "";
|
||||
} else {
|
||||
return "this won't trigger right now"; //$"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ZitiService() {
|
||||
}
|
||||
|
||||
public ZitiService(Service svc) {
|
||||
this.Name = svc.Name;
|
||||
this.AssignedIP = svc.AssignedIP;
|
||||
this.Addresses = svc.Addresses;
|
||||
this.Protocols = svc.Protocols == null ? null : svc.Protocols.Select(p => p.ToUpper()).ToArray();
|
||||
this.Ports = svc.Ports;
|
||||
this.PostureChecks = svc.PostureChecks;
|
||||
}
|
||||
public bool IsAccessable { get; set; }
|
||||
|
||||
public string Warning {
|
||||
get {
|
||||
if (this.OwnsIntercept) {
|
||||
return "";
|
||||
} else {
|
||||
return "this won't trigger right now"; //$"Another identity already mapped the specified hostname: {Host}.\nThis service is only available via IP";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ZitiService() {
|
||||
}
|
||||
|
||||
public ZitiService(Service svc) {
|
||||
this.Name = svc.Name;
|
||||
this.AssignedIP = svc.AssignedIP;
|
||||
this.Addresses = svc.Addresses;
|
||||
this.Protocols = svc.Protocols == null ? null : svc.Protocols.Select(p => p.ToUpper()).ToArray();
|
||||
this.Ports = svc.Ports;
|
||||
this.PostureChecks = svc.PostureChecks;
|
||||
this.OwnsIntercept = svc.OwnsIntercept;
|
||||
if (this.PostureChecks != null) {
|
||||
this.failingPostureCheck = this.PostureChecks.Any(p => !p.IsPassing);
|
||||
}
|
||||
this.IsAccessable = svc.IsAccessable;
|
||||
//commented out for now logger.Warn("SERVICE: " + this.Name + " HAS FAILING POSTURE CHECK: " + failingPostureCheck);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ServiceMatrix builtMatrix = null;
|
||||
public ServiceMatrix Matrix {
|
||||
get {
|
||||
if (builtMatrix == null) {
|
||||
builtMatrix = new ServiceMatrix();
|
||||
List<ServiceMatrixElement> matrix = new List<ServiceMatrixElement>(this.Protocols.Length * this.Addresses.Length * this.Ports.Length);
|
||||
|
||||
foreach (var proto in this.Protocols) {
|
||||
foreach (var addy in this.Addresses) {
|
||||
foreach (var port in this.Ports) {
|
||||
ServiceMatrixElement m = new ServiceMatrixElement();
|
||||
m.Ports = port.ToString();
|
||||
m.Proto = proto.ToUpper();
|
||||
m.Address = addy.Hostname;
|
||||
|
||||
matrix.Add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
builtMatrix.Elements = matrix;
|
||||
}
|
||||
|
||||
return builtMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
string protos = "<none>";
|
||||
if (Protocols?.Length > 0) {
|
||||
if (Protocols.Length > 1) {
|
||||
protos = "[" + string.Join(",", Protocols.Select(p => p.ToString())) + "]";
|
||||
} else {
|
||||
protos = Protocols[0];
|
||||
}
|
||||
}
|
||||
string addys = "<none>";
|
||||
if (Addresses?.Length > 0) {
|
||||
if (Addresses.Length > 1) {
|
||||
addys = "[" + string.Join(",", Addresses.Select(a => a.ToString()).OrderBy(o => o)) + "]";
|
||||
} else {
|
||||
addys = Addresses[0].ToString();
|
||||
}
|
||||
}
|
||||
string ranges = "<none>";
|
||||
if (Ports?.Length > 0) {
|
||||
if (Ports.Length > 1) {
|
||||
ranges = "[" + string.Join(",", Ports.Select(a => a.ToString()).OrderBy(o => o)) + "]";
|
||||
} else {
|
||||
ranges = Ports[0].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return protos + ":" + addys + ":" + ranges;
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceMatrix {
|
||||
public List<ServiceMatrixElement> Elements { get; internal set; }
|
||||
}
|
||||
|
||||
public class ServiceMatrixElement {
|
||||
public ServiceMatrixElement() {
|
||||
Proto = "<none>";
|
||||
Address = "<none>";
|
||||
Ports = "<none>";
|
||||
}
|
||||
|
||||
public string Proto { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string Ports { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
return Proto + " " + Address + " " + Ports;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.IsAccessable = svc.IsAccessable;
|
||||
//commented out for now logger.Warn("SERVICE: " + this.Name + " HAS FAILING POSTURE CHECK: " + failingPostureCheck);
|
||||
}
|
||||
|
||||
public string WarningMessage {
|
||||
get {
|
||||
string message = Warning;
|
||||
if (this.PostureChecks != null && this.PostureChecks.Length > 0) {
|
||||
List<MessageCount> messages = new List<MessageCount>();
|
||||
for (int i = 0; i < this.PostureChecks.Length; i++) {
|
||||
if (!this.PostureChecks[i].IsPassing) {
|
||||
messages = AppendMessage(messages, this.PostureChecks[i].QueryType);
|
||||
}
|
||||
}
|
||||
if (messages.Count > 0) {
|
||||
string checks = "";
|
||||
for (int i = 0; i < messages.Count; i++) {
|
||||
checks += ((i > 0) ? ", " : "") + messages[i].Total + " " + messages[i].Message;
|
||||
}
|
||||
message = message + " Posture Check Failing: " + checks;
|
||||
return message.Trim();
|
||||
} else return message;
|
||||
} else return message;
|
||||
}
|
||||
}
|
||||
private List<MessageCount> AppendMessage(List<MessageCount> items, string message) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < items.Count; i++) {
|
||||
if (items[i].Message == message) {
|
||||
items[i].Total++;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
MessageCount count = new MessageCount();
|
||||
count.Total = 1;
|
||||
count.Message = message;
|
||||
items.Add(count);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public int WarnWidth {
|
||||
get {
|
||||
return (HasWarning) ? 30 : 0;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public Visibility WarningVisibility {
|
||||
get {
|
||||
return (HasWarning) ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public bool HasWarning {
|
||||
get {
|
||||
if (!this.OwnsIntercept) return true;
|
||||
else {
|
||||
if (this.IsAccessable) {
|
||||
return false;
|
||||
} else {
|
||||
if (this.PostureChecks==null) {
|
||||
return false;
|
||||
} else {
|
||||
for (int i = 0; i < this.PostureChecks.Length; i++) {
|
||||
if (!this.PostureChecks[i].IsPassing) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public string ProtocolString {
|
||||
get {
|
||||
string toReturn = "";
|
||||
for (int i = 0; i < this.Protocols.Length; i++) {
|
||||
toReturn += ((i > 0) ? "," : "") + this.Protocols[i];
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public string PortString {
|
||||
get {
|
||||
string toReturn = "";
|
||||
for (int i = 0; i < this.Ports.Length; i++) {
|
||||
toReturn += ((i > 0) ? "," : "") + this.Ports[i].ToString();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
public string AddressString {
|
||||
get {
|
||||
string toReturn = "";
|
||||
for (int i = 0; i < this.Addresses.Length; i++) {
|
||||
toReturn += ((i > 0) ? "," : "") + this.Addresses[i].ToString();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
private ServiceMatrix builtMatrix = null;
|
||||
public ServiceMatrix Matrix {
|
||||
get {
|
||||
if (builtMatrix == null) {
|
||||
builtMatrix = new ServiceMatrix();
|
||||
List<ServiceMatrixElement> matrix = new List<ServiceMatrixElement>(this.Protocols.Length * this.Addresses.Length * this.Ports.Length);
|
||||
|
||||
foreach (var proto in this.Protocols) {
|
||||
foreach (var addy in this.Addresses) {
|
||||
foreach (var port in this.Ports) {
|
||||
ServiceMatrixElement m = new ServiceMatrixElement();
|
||||
m.Ports = port.ToString();
|
||||
m.Proto = proto.ToUpper();
|
||||
m.Address = addy.Hostname;
|
||||
|
||||
matrix.Add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
builtMatrix.Elements = matrix;
|
||||
}
|
||||
|
||||
return builtMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
string protos = "<none>";
|
||||
if (Protocols?.Length > 0) {
|
||||
if (Protocols.Length > 1) {
|
||||
protos = "[" + string.Join(",", Protocols.Select(p => p.ToString())) + "]";
|
||||
} else {
|
||||
protos = Protocols[0];
|
||||
}
|
||||
}
|
||||
string addys = "<none>";
|
||||
if (Addresses?.Length > 0) {
|
||||
if (Addresses.Length > 1) {
|
||||
addys = "[" + string.Join(",", Addresses.Select(a => a.ToString()).OrderBy(o => o)) + "]";
|
||||
} else {
|
||||
addys = Addresses[0].ToString();
|
||||
}
|
||||
}
|
||||
string ranges = "<none>";
|
||||
if (Ports?.Length > 0) {
|
||||
if (Ports.Length > 1) {
|
||||
ranges = "[" + string.Join(",", Ports.Select(a => a.ToString()).OrderBy(o => o)) + "]";
|
||||
} else {
|
||||
ranges = Ports[0].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return protos + ":" + addys + ":" + ranges;
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceMatrix {
|
||||
public List<ServiceMatrixElement> Elements { get; internal set; }
|
||||
}
|
||||
|
||||
public class ServiceMatrixElement {
|
||||
public ServiceMatrixElement() {
|
||||
Proto = "<none>";
|
||||
Address = "<none>";
|
||||
Ports = "<none>";
|
||||
}
|
||||
|
||||
public string Proto { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string Ports { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
return Proto + " " + Address + " " + Ports;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,6 @@ using System.Windows;
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.9.3.0")]
|
||||
[assembly: AssemblyVersion("1.9.3.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.3.0")]
|
||||
// [assembly: AssemblyVersion("1.9.4.0")]
|
||||
[assembly: AssemblyVersion("1.9.4.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.4.0")]
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
<SolidColorBrush x:Name="ButtonBgColor" Color="#0069FF"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<Rectangle x:Name="ButtonBgDarken" Margin="40,0,40,0" Opacity="0.0" RadiusX="7" Grid.Row="8" RadiusY="7" ClipToBounds="True" Height="30" VerticalAlignment="Bottom" MouseUp="DoClick" Cursor="Hand" MouseEnter="Hover" MouseLeave="Leave" MouseDown="Down">
|
||||
<Rectangle.Fill>
|
||||
<SolidColorBrush Color="#000000"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<Label x:Name="ButtonLabel" HorizontalAlignment="Center" IsHitTestVisible="False" Foreground="#FFFFFF" Grid.Row="8"></Label>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -23,6 +23,15 @@ namespace ZitiDesktopEdge {
|
||||
public delegate void ClickAction();
|
||||
public event ClickAction OnClick;
|
||||
private string _label = "";
|
||||
private string bgColor = "#0069FF";
|
||||
|
||||
public string BgColor {
|
||||
get { return bgColor; }
|
||||
set {
|
||||
bgColor = value;
|
||||
ButtonBgColor.Color = (Color)ColorConverter.ConvertFromString(bgColor);
|
||||
}
|
||||
}
|
||||
|
||||
public string Label {
|
||||
get {
|
||||
@@ -44,8 +53,8 @@ namespace ZitiDesktopEdge {
|
||||
/// <param name="sender">The button object</param>
|
||||
/// <param name="e">The mouse event</param>
|
||||
private void Hover(object sender, MouseEventArgs e) {
|
||||
ButtonBg.Opacity = 0.8;
|
||||
ButtonBg.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(1.0, TimeSpan.FromSeconds(.3)));
|
||||
ButtonBgDarken.Opacity = 0.0;
|
||||
ButtonBgDarken.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(0.2, TimeSpan.FromSeconds(.3)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,9 +63,8 @@ namespace ZitiDesktopEdge {
|
||||
/// <param name="sender">The button object</param>
|
||||
/// <param name="e">The mouse event</param>
|
||||
private void Leave(object sender, MouseEventArgs e) {
|
||||
ButtonBgColor.Color = Color.FromRgb(0, 104, 249);
|
||||
ButtonBg.BeginAnimation(Grid.OpacityProperty, null);
|
||||
ButtonBg.Opacity = 0.8;
|
||||
ButtonBgDarken.Opacity = 0.2;
|
||||
ButtonBgDarken.BeginAnimation(Grid.OpacityProperty, new DoubleAnimation(0.0, TimeSpan.FromSeconds(.3)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,7 +73,7 @@ namespace ZitiDesktopEdge {
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void Down(object sender, MouseButtonEventArgs e) {
|
||||
ButtonBgColor.Color = Color.FromRgb(126, 180, 255);
|
||||
// ButtonBgColor.Color = Color.FromRgb(126, 180, 255);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<UserControl x:Class="ZitiDesktopEdge.Filter"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:ZitiDesktopEdge"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="36"
|
||||
Height="36"
|
||||
HorizontalAlignment="Stretch"
|
||||
d:DesignWidth="350" >
|
||||
<Grid Margin="0,0,0,0">
|
||||
<Rectangle Margin="0,0,0,0" Fill="#070826" Opacity="0.1" RadiusY="0" RadiusX="0"></Rectangle>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Label Content="Filter" Foreground="Black" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" FontWeight="Bold" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans"></Label>
|
||||
<TextBox x:Name="FilterFor" Text="any text" Width="80" Height="26" Padding="6,0,6,0" Grid.Row="0" VerticalContentAlignment="Center" BorderThickness="0" Cursor="Hand" Foreground="#070826" FontSize="12" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" GotFocus="FocusFilter" LostFocus="FocusLostFilter" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Keyboard.KeyUp="FilterChanged" Keyboard.KeyDown="FilterPressed">
|
||||
<TextBox.Resources>
|
||||
<Style TargetType="{x:Type Border}">
|
||||
<Setter Property="CornerRadius" Value="7"/>
|
||||
</Style>
|
||||
</TextBox.Resources>
|
||||
</TextBox>
|
||||
<Label Content=" and sort by " Foreground="Black" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans"></Label>
|
||||
<ComboBox Name="SortByField" SelectionChanged="SortByChanged" Width="80" VerticalContentAlignment="Center" Cursor="Hand" Height="26" VerticalAlignment="Center" TextBlock.TextAlignment="Center" HorizontalAlignment="Stretch" BorderThickness="0" Foreground="#070826" FontFamily="/ZitiDesktopEdge;component/Assets/Fonts/#Open Sans" FontSize="12" Style="{DynamicResource FilterComboStyle}">
|
||||
<ComboBoxItem IsSelected="True">Name</ComboBoxItem>
|
||||
<ComboBoxItem>Address</ComboBoxItem>
|
||||
<ComboBoxItem>Protocol</ComboBoxItem>
|
||||
<ComboBoxItem>Port</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<ComboBox Name="SortWayField" Margin="5,0,0,0" Width="60" VerticalContentAlignment="Center" SelectionChanged="SortWayChanged" Cursor="Hand" Height="26" VerticalAlignment="Center" TextBlock.TextAlignment="Center" HorizontalAlignment="Stretch" BorderThickness="0" Foreground="#070826" FontFamily="/ZitiDesktopEdge;component/Assets/Fonts/#Open Sans" FontSize="12" Style="{DynamicResource FilterComboStyle}">
|
||||
<ComboBoxItem IsSelected="True">Asc</ComboBoxItem>
|
||||
<ComboBoxItem>Desc</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Timers;
|
||||
using ZitiDesktopEdge.Models;
|
||||
|
||||
namespace ZitiDesktopEdge {
|
||||
/// <summary>
|
||||
/// Interaction logic for Filter.xaml
|
||||
/// </summary>
|
||||
public partial class Filter :UserControl {
|
||||
|
||||
public delegate void OnFilterEvent(FilterData filter);
|
||||
public event OnFilterEvent OnFilter;
|
||||
public string placeholder = "any text";
|
||||
private static Timer timeout;
|
||||
|
||||
private FilterData filter = new FilterData("", "Name", "Asc");
|
||||
public Filter() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
FilterFor.Text = "";
|
||||
filter.SearchFor = "";
|
||||
FilterFor.Text = placeholder;
|
||||
SortWayField.SelectedIndex = 0;
|
||||
SortByField.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void FilterPressed(object sender, KeyEventArgs e) {
|
||||
if (e.Key==Key.Enter) {
|
||||
OnFilter?.Invoke(filter);
|
||||
}
|
||||
}
|
||||
|
||||
private void FilterChanged(object sender, KeyEventArgs e) {
|
||||
string search = FilterFor.Text.Trim();
|
||||
if (filter.SearchFor!=search) {
|
||||
filter.SearchFor = search;
|
||||
if (filter.SearchFor == placeholder) filter.SearchFor = "";
|
||||
|
||||
if (e.Key==Key.Enter) {
|
||||
OnFilter?.Invoke(filter);
|
||||
} else {
|
||||
if (timeout != null && timeout.Enabled) {
|
||||
timeout.Close();
|
||||
}
|
||||
timeout = new Timer(1000);
|
||||
timeout.Elapsed += OnTimedEvent;
|
||||
timeout.AutoReset = false;
|
||||
timeout.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SortWayChanged(object sender, SelectionChangedEventArgs e) {
|
||||
ComboBoxItem selected = (ComboBoxItem)SortWayField.SelectedValue;
|
||||
if (selected != null && selected.Content != null) {
|
||||
if (selected.Content.ToString() != filter.SortHow) {
|
||||
filter.SortHow = selected.Content.ToString();
|
||||
this.OnFilter?.Invoke(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SortByChanged(object sender, SelectionChangedEventArgs e) {
|
||||
ComboBoxItem selected = (ComboBoxItem)SortByField.SelectedValue;
|
||||
if (selected != null && selected.Content != null) {
|
||||
if (selected.Content.ToString() != filter.SortBy) {
|
||||
filter.SortBy = selected.Content.ToString();
|
||||
this.OnFilter?.Invoke(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FocusFilter(object sender, RoutedEventArgs e) {
|
||||
if (FilterFor.Text==placeholder) {
|
||||
FilterFor.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void FocusLostFilter(object sender, RoutedEventArgs e) {
|
||||
if (FilterFor.Text.Trim() == "") {
|
||||
FilterFor.Text = placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTimedEvent(Object source, ElapsedEventArgs e) {
|
||||
this.Dispatcher.Invoke(() => {
|
||||
OnFilter?.Invoke(filter);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,8 +107,6 @@ namespace ZitiDesktopEdge {
|
||||
private void OpenDetails(object sender, MouseButtonEventArgs e) {
|
||||
IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu;
|
||||
deets.SelectedIdentity = this;
|
||||
deets.ServiceTitle.Clear();
|
||||
deets.IdDetailToggle.Enabled = this.Identity.IsEnabled;
|
||||
deets.Identity = this.Identity;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,5 @@
|
||||
<TextBox Name="MainLabel" Background="White" Height="30" FontWeight="Bold" IsReadOnly="True" HorizontalAlignment="Stretch" BorderThickness="0" ClipToBounds="True" Padding="0,6,3,0" Grid.Column="0" VerticalAlignment="Center" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></TextBox>
|
||||
<TextBox Name="MainEdit" Background="White" IsReadOnly="True" HorizontalAlignment="Stretch" Height="30" Grid.Column="1" BorderThickness="0" TextAlignment="Right" Padding="0,6,3,0" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" ></TextBox>
|
||||
</Grid>
|
||||
<Rectangle HorizontalAlignment="Stretch" Height="1" Fill="#7d8faf" Opacity="0.2"></Rectangle>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -21,7 +21,7 @@
|
||||
<TextBox Name="MainEdit" Background="White" HorizontalAlignment="Stretch" Height="30" Grid.Column="1" BorderThickness="1" TextAlignment="Left" Margin="30,0,0,0" Padding="5,3,3,5" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" VerticalContentAlignment="Center" SpellCheck.IsEnabled="True" MaxLength="100" KeyUp="MainEdit_KeyUp">
|
||||
<TextBox.Resources>
|
||||
<Style TargetType="{x:Type Border}">
|
||||
<Setter Property="CornerRadius" Value="10"/>
|
||||
<Setter Property="CornerRadius" Value="7"/>
|
||||
</Style>
|
||||
</TextBox.Resources>
|
||||
</TextBox>
|
||||
|
||||
@@ -64,7 +64,6 @@ namespace ZitiDesktopEdge {
|
||||
private void ShowIdentity(object sender, MouseButtonEventArgs e) {
|
||||
IdentityDetails deets = ((MainWindow)Application.Current.MainWindow).IdentityMenu;
|
||||
deets.SelectedIdentityMenu = this;
|
||||
deets.IdDetailToggle.Enabled = this.Identity.IsEnabled;
|
||||
deets.Identity = this.Identity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<StackPanel Orientation="Vertical" Height="33">
|
||||
<Grid Height="32">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="220"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition x:Name="WarningColumn" Width="0"/>
|
||||
<ColumnDefinition x:Name="DetailColumn" Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
@@ -17,8 +18,12 @@
|
||||
<TextBox Name="MainLabel" Padding="0,0,12,0" Height="15" IsReadOnly="True" BorderThickness="0" FontWeight="Bold" Background="Transparent" ClipToBounds="True" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" FontSize="11" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="White"></TextBox>
|
||||
<TextBox Name="MainEdit" IsReadOnly="True" Height="14" Padding="0,0,12,0" TextAlignment="Left" BorderThickness="0" Background="Transparent" ClipToBounds="True" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch" FontSize="10" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="LightGray"></TextBox>
|
||||
</StackPanel>
|
||||
<Image x:Name="DetailIcon" Source="/Assets/Images/detail.png" Grid.Column="2" Width="20" Height="20" Cursor="Hand" MouseUp="DetailIcon_MouseUp"/>
|
||||
<Image x:Name="WarnIcon" Visibility="Collapsed" Source="/Assets/Images/Warning.png" Grid.Column="1" Width="20" Height="20" Cursor="Hand" MouseUp="WarnIcon_MouseUp"/>
|
||||
<StackPanel Orientation="Vertical" Height="30" Grid.Column="1">
|
||||
<TextBox Name="Protocols" Padding="0,0,12,0" Height="15" IsReadOnly="True" BorderThickness="0" FontWeight="Bold" Background="Transparent" ClipToBounds="True" VerticalAlignment="Bottom" HorizontalAlignment="Right" FontSize="11" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="White" Opacity="0.9"></TextBox>
|
||||
<TextBox Name="Ports" IsReadOnly="True" Height="14" Padding="0,0,12,0" TextAlignment="Right" BorderThickness="0" Background="Transparent" ClipToBounds="True" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch" FontSize="10" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="LightGray"></TextBox>
|
||||
</StackPanel>
|
||||
<Image x:Name="DetailIcon" Source="/Assets/Images/detail.png" Grid.Column="3" Width="20" Height="20" Cursor="Hand" MouseUp="DetailIcon_MouseUp"/>
|
||||
<Image x:Name="WarnIcon" Visibility="Collapsed" Source="/Assets/Images/Warning.png" Grid.Column="2" Width="20" Height="20" Cursor="Hand" MouseUp="WarnIcon_MouseUp"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -36,10 +36,41 @@ namespace ZitiDesktopEdge {
|
||||
}
|
||||
set {
|
||||
this._info = value;
|
||||
MainEdit.ToolTip = this._info.ToString();
|
||||
MainEdit.Text = this._info.ToString();
|
||||
|
||||
string addresses = "";
|
||||
if (_info.Addresses!=null) {
|
||||
for (int i = 0; i < this._info.Addresses?.Length; i++) {
|
||||
addresses += ((i > 0) ? "," : "") + this._info.Addresses[i].Hostname;
|
||||
}
|
||||
}
|
||||
|
||||
MainEdit.ToolTip = addresses;
|
||||
MainEdit.Text = addresses;
|
||||
|
||||
MainLabel.ToolTip = this._info.Name;
|
||||
MainLabel.Text = this._info.Name;
|
||||
|
||||
string ports = "";
|
||||
if (_info.Ports != null) {
|
||||
for (int i = 0; i < this._info.Ports.Length; i++) {
|
||||
ports += ((i > 0) ? "," : "") + this._info.Ports[i].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
Ports.ToolTip = ports;
|
||||
Ports.Text = ports;
|
||||
|
||||
string protocols = "";
|
||||
|
||||
if (_info.Protocols != null) {
|
||||
for (int i = 0; i < this._info.Protocols.Length; i++) {
|
||||
protocols += ((i > 0) ? "," : "") + this._info.Protocols[i];
|
||||
}
|
||||
}
|
||||
|
||||
Protocols.ToolTip = protocols;
|
||||
Protocols.Text = protocols;
|
||||
|
||||
WarningColumn.Width = new GridLength(0);
|
||||
if (this._info.Warning.Length > 0) {
|
||||
WarnIcon.ToolTip = this._info.Warning;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
xmlns:local="clr-namespace:ZitiDesktopEdge"
|
||||
mc:Ignorable="d"
|
||||
x:Name="IdentityArea"
|
||||
d:DesignHeight="500" d:DesignWidth="350">
|
||||
d:DesignHeight="500" d:DesignWidth="350" IsVisibleChanged="VisibilityChanged">
|
||||
<Grid>
|
||||
<!-- Border Arrow pointing to TaskBar -->
|
||||
<Canvas>
|
||||
@@ -16,109 +16,91 @@
|
||||
</Rectangle.LayoutTransform>
|
||||
</Rectangle>
|
||||
</Canvas>
|
||||
|
||||
|
||||
<!-- Background Color for Pop Overs -->
|
||||
<Rectangle x:Name="MainCanvas" Margin="10,10,10,10" Fill="White" RadiusY="10" RadiusX="10"></Rectangle>
|
||||
|
||||
<Grid Margin="20,20,20,-20" MaxWidth="350">
|
||||
<Grid Margin="0,30,0,-20">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Stretch" Margin="10,10,10,10">
|
||||
|
||||
<StackPanel Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Stretch" Margin="0,0,0,30">
|
||||
|
||||
<!-- Header Controls -->
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40"/>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="40"/>
|
||||
<ColumnDefinition Width="60"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:Toggler x:Name="IdDetailToggle" Grid.Column="0" HorizontalAlignment="Left" OnToggled="IdToggle"></local:Toggler>
|
||||
<Image x:Name="IsConnected" Grid.Column="0" Visibility="Visible" Source="/Assets/Images/online.png" Height="25" HorizontalAlignment="Right" Cursor="Hand" MouseUp="DoDisconnect" />
|
||||
<Image x:Name="IsDisconnected" Grid.Column="0" Visibility="Collapsed" Source="/Assets/Images/offline.png" Height="25" HorizontalAlignment="Right" Cursor="Hand" MouseUp="DoConnect" />
|
||||
<TextBlock x:Name="IdDetailName" MouseDown="Window_MouseDown" MaxWidth="220" Grid.Column="1" TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" FontSize="14" FontWeight="Bold" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="#0F0F23" VerticalAlignment="Center" TextWrapping="NoWrap" />
|
||||
<Image Grid.Column="2" Cursor="Hand" Source="/Assets/Images/x.png" Width="20" Height="20" Margin="0,0,0,0" HorizontalAlignment="Right" MouseUp="HideMenu"></Image>
|
||||
<Image Grid.Column="2" Cursor="Hand" Source="/Assets/Images/x.png" Width="20" Height="20" Margin="0,0,0,0" HorizontalAlignment="Left" MouseUp="HideMenu"></Image>
|
||||
</Grid>
|
||||
<Rectangle HorizontalAlignment="Stretch" Height="1" Fill="#7d8faf" Opacity="0.2"></Rectangle>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition x:Name="ServiceRow" Height="140"></RowDefinition>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
<RowDefinition Height="40"></RowDefinition>
|
||||
<RowDefinition x:Name="IdImage" Height="0"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Identity Details Area -->
|
||||
<local:MenuEditItem x:Name="IdentityName" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Label="Name" IsLocked="True"></local:MenuEditItem>
|
||||
<local:MenuEditToggle x:Name="IdentityMFA" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" Label="Multi Factor Auth" Recovery="MFARecovery" Authenticate="MFAAuthenticate" Toggle="ToggleMFA"></local:MenuEditToggle>
|
||||
<local:MenuEditItem x:Name="IdentityNetwork" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Stretch" Label="Network" IsLocked="True"></local:MenuEditItem>
|
||||
<local:MenuEditItem x:Name="IdentityStatus" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Stretch" Label="Status" IsLocked="True"></local:MenuEditItem>
|
||||
<local:MenuEditItem x:Name="IdentityEnrollment" Grid.Column="0" Grid.Row="4" HorizontalAlignment="Stretch" Label="Enrollment Status" IsLocked="True"></local:MenuEditItem>
|
||||
<local:MenuEditSearch x:Name="ServiceTitle" Grid.Column="0" Grid.Row="5" HorizontalAlignment="Stretch" Filter="DoFilter"></local:MenuEditSearch>
|
||||
<TextBox Name="NoAuthServices" Height="30" FontWeight="Bold" TextAlignment="Center" Text="You must authenticate to access services" IsReadOnly="True" HorizontalAlignment="Stretch" BorderThickness="0" ClipToBounds="True" Grid.Column="0" Grid.Row="5" VerticalAlignment="Center" Padding="0,6,3,0" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></TextBox>
|
||||
<Rectangle Margin="40,0,40,10" Fill="#070826" Height="1" RadiusY="10" RadiusX="10" Opacity="0.1"></Rectangle>
|
||||
<local:MenuEditItem x:Name="IdName" Label="Name" IsLocked="True" />
|
||||
<Rectangle Margin="40,0,40,10" Fill="#070826" Height="1" RadiusY="10" RadiusX="10" Opacity="0.1"></Rectangle>
|
||||
<local:MenuEditItem x:Name="IdServer" Label="Network" IsLocked="True" />
|
||||
<Rectangle Margin="40,0,40,10" Fill="#070826" Height="1" RadiusY="10" RadiusX="10" Opacity="0.1"></Rectangle>
|
||||
<local:MenuEditToggle x:Name="IdentityMFA" HorizontalAlignment="Stretch" Label="Multi Factor Auth" Margin="0,10,0,0" Recovery="MFARecovery" Authenticate="MFAAuthenticate" Toggle="ToggleMFA"></local:MenuEditToggle>
|
||||
|
||||
<!-- Service List Area (Higher Contrast to differentiate) -->
|
||||
<Grid Name="MainDetailScroll" Grid.Column="0" MaxHeight="160" Grid.Row="6" Margin="-8,0,-8,0">
|
||||
<Rectangle Margin="10,10,10,10" Fill="#070826" RadiusY="10" RadiusX="10"></Rectangle>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible" CanContentScroll="True" Margin="16,16,8,16">
|
||||
<StackPanel Name="ServiceList" Orientation="Vertical"></StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<Rectangle x:Name="AuthMessageBg" Margin="40,0,40,0" Opacity="0.8" RadiusX="7" Grid.Row="6" RadiusY="7" ClipToBounds="True" Height="30" VerticalAlignment="Bottom" Cursor="Hand" MouseUp="AuthFromMessage">
|
||||
<local:Filter x:Name="FilterServices" OnFilter="DoFilter" VerticalAlignment="Top" Margin="10,16,10,0" />
|
||||
|
||||
<TextBox Name="NoAuthServices" Height="30" FontWeight="Bold" TextAlignment="Center" Text="You must authenticate to access services" IsReadOnly="True" HorizontalAlignment="Stretch" BorderThickness="0" ClipToBounds="True" Grid.Column="0" Grid.Row="5" VerticalAlignment="Center" Padding="0,6,3,0" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></TextBox>
|
||||
<Grid Name="MainDetailScroll" MaxHeight="160" Margin="10,0,10,-10">
|
||||
<Rectangle Margin="10,10,10,10" Fill="#070826" RadiusY="10" RadiusX="10"></Rectangle>
|
||||
<ListView x:Name="ServiceList" VirtualizingPanel.IsVirtualizing="True" ScrollViewer.IsDeferredScrollingEnabled="True" ScrollViewer.ScrollChanged="Scrolled" Focusable="False" IsManipulationEnabled="False" BorderThickness="0" Background="Transparent" Margin="20,20,10,20" Style="{DynamicResource ServiceListStyle}">
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<ContentPresenter />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Height="32">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="220"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition x:Name="WarningColumn" Width="20"/>
|
||||
<ColumnDefinition x:Name="DetailColumn" Width="20"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Vertical" Height="30" Grid.Column="0">
|
||||
<TextBlock Name="MainLabel" Text="{Binding Name}" Padding="0,0,12,0" Height="15" FontWeight="Bold" Background="Transparent" ClipToBounds="True" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" FontSize="11" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="White"></TextBlock>
|
||||
<TextBlock Name="MainEdit" Text="{Binding AddressString}" Height="14" Padding="0,0,12,0" Background="Transparent" ClipToBounds="True" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Stretch" FontSize="10" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="LightGray"></TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Vertical" Height="30" Grid.Column="1">
|
||||
<TextBlock Name="Protocols" Text="{Binding ProtocolString}" Padding="0,0,12,0" Height="15" FontWeight="Bold" Background="Transparent" ClipToBounds="True" VerticalAlignment="Bottom" HorizontalAlignment="Center" FontSize="11" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="White" Opacity="0.9"></TextBlock>
|
||||
<TextBlock Name="Ports" Text="{Binding PortString}" Height="14" Padding="0,0,12,0" HorizontalAlignment="Center" Background="Transparent" ClipToBounds="True" Grid.Column="0" VerticalAlignment="Top" FontSize="10" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="LightGray"></TextBlock>
|
||||
</StackPanel>
|
||||
<Image x:Name="WarnIcon" Visibility="{Binding WarningVisibility}" ToolTip="{Binding WarningMessage}" Source="/Assets/Images/Warning.png" Grid.Column="2" Width="20" Height="20" Cursor="Hand" MouseUp="WarnClicked"/>
|
||||
<Image x:Name="DetailIcon" Source="/Assets/Images/detail.png" Grid.Column="3" Width="20" Height="20" Cursor="Hand" MouseUp="DetailsClicked"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
<Label x:Name="ServiceCount" HorizontalAlignment="Center" Content="0 Services" Margin="0,0,0,0" Foreground="Gray" FontWeight="Bold" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans"></Label>
|
||||
<Grid>
|
||||
<Rectangle x:Name="AuthMessageBg" Margin="40,0,40,0" Opacity="0.8" RadiusX="7" RadiusY="7" ClipToBounds="True" Height="30" VerticalAlignment="Bottom" Cursor="Hand" MouseUp="AuthFromMessage">
|
||||
<Rectangle.Fill>
|
||||
<SolidColorBrush x:Name="AuthBgColor" Color="#0069FF"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<Label x:Name="AuthMessageLabel" HorizontalAlignment="Center" Content="Authenticate" IsHitTestVisible="False" Foreground="#FFFFFF" Grid.Row="6"></Label>
|
||||
|
||||
<!-- Sorting and Paging -->
|
||||
<Grid x:Name="PageSortArea" Grid.Column="0" Grid.Row="7">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="40"></ColumnDefinition>
|
||||
<ColumnDefinition Width="90"></ColumnDefinition>
|
||||
<ColumnDefinition Width="70"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Content="Page" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center"></Label>
|
||||
<ComboBox Name="Pages" Grid.Column="1" Grid.Row="0" SelectionChanged="Pages_SelectionChanged" Width="60" Height="28" VerticalAlignment="Top" HorizontalAlignment="Left" BorderThickness="0" Background="#FFD4CECE" Foreground="#FF292626" FontFamily="/ZitiDesktopEdge;component/Assets/Fonts/#Open Sans" FontSize="14"></ComboBox>
|
||||
|
||||
<Label Content="Sort" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center"></Label>
|
||||
<ComboBox Name="SortByField" Grid.Column="3" Grid.Row="0" SelectionChanged="SortByField_SelectionChanged" Height="28" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Background="#FFD4CECE" Foreground="#FF292626" FontFamily="/ZitiDesktopEdge;component/Assets/Fonts/#Open Sans" FontSize="14">
|
||||
<ComboBoxItem IsSelected="True">Name</ComboBoxItem>
|
||||
<ComboBoxItem>Address</ComboBoxItem>
|
||||
<ComboBoxItem>Protocol</ComboBoxItem>
|
||||
<ComboBoxItem>Port</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<ComboBox Name="SortWayField" Grid.Column="4" Grid.Row="0" Margin="5,0,0,0" SelectionChanged="SortWayField_SelectionChanged" Height="28" VerticalAlignment="Top" HorizontalAlignment="Stretch" BorderThickness="0" Foreground="#FF292626" FontFamily="/ZitiDesktopEdge;component/Assets/Fonts/#Open Sans" FontSize="14">
|
||||
<ComboBox.Resources>
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.WindowBrushKey}" Color="Yellow" />
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
|
||||
</ComboBox.Resources>
|
||||
<ComboBoxItem IsSelected="True">Asc</ComboBoxItem>
|
||||
<ComboBoxItem>Desc</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
|
||||
<!-- Forget Identity Button -->
|
||||
<Label Name="ForgetIdentityButton" Grid.Column="0" Grid.Row="8" Padding="0,10,0,10" Margin="0,0,0,0" Content="Forget This Identity" Cursor="Hand" Foreground="#F4044D" HorizontalAlignment="Center" Mouse.MouseUp="ForgetIdentity"></Label>
|
||||
<Label x:Name="AuthMessageLabel" HorizontalAlignment="Center" Content="Authenticate" IsHitTestVisible="False" Foreground="#FFFFFF"></Label>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
<local:StyledButton x:Name="ForgetIdentityButton" MinWidth="310" BgColor="#F4044D" Label="Forget This Identity" Margin="0,0,0,40" OnClick="ForgetIdentity" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
|
||||
<Rectangle x:Name="ModalBg" Margin="10,10,10,10" Fill="Black" RadiusY="10" RadiusX="10" Opacity="0" Visibility="Collapsed"></Rectangle>
|
||||
|
||||
|
||||
<!-- Expended Detail Modal for Details pop up on service list -->
|
||||
<Grid x:Name="DetailsArea" Visibility="Collapsed" Height="400" Margin="0,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -149,7 +131,7 @@
|
||||
|
||||
<Label Content="Protocols" Padding="10,0,0,0" FontWeight="Bold" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></Label>
|
||||
<TextBox x:Name="DetailProtocols" MaxWidth="300" Background="Transparent" IsReadOnly="True" HorizontalAlignment="Stretch" Height="20" BorderThickness="0" TextAlignment="Left" Padding="0,0,0,0" FontSize="12" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" ></TextBox>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
<Image Source="/Assets/Images/closeBlack.png" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,40,40,0" Width="10" Height="10" Cursor="Hand" MouseUp="CloseDetails"></Image>
|
||||
</Grid>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -10,6 +11,8 @@ using System.Windows.Media.Animation;
|
||||
|
||||
using NLog;
|
||||
using System.Web;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ZitiDesktopEdge {
|
||||
/// <summary>
|
||||
@@ -35,10 +38,21 @@ namespace ZitiDesktopEdge {
|
||||
public event OnAuthenticate Authenticate;
|
||||
public delegate void OnRecovery(ZitiIdentity identity);
|
||||
public event OnRecovery Recovery;
|
||||
public delegate void LoadingEvent(bool isComplete);
|
||||
public event LoadingEvent OnLoading;
|
||||
|
||||
public int Page = 1;
|
||||
public int PerPage = 50;
|
||||
public int TotalPages = 1;
|
||||
public string SortBy = "Name";
|
||||
public string SortWay = "Asc";
|
||||
private bool _loaded = false;
|
||||
private double scrolledTo = 0;
|
||||
public int totalServices = 0;
|
||||
private ScrollViewer _scroller;
|
||||
|
||||
public ObservableCollection<ZitiService> _services = new ObservableCollection<ZitiService>();
|
||||
public ObservableCollection<ZitiService> ZitiServices { get { return _services; } }
|
||||
|
||||
internal MainWindow MainWindow { get; set; }
|
||||
|
||||
@@ -55,13 +69,15 @@ namespace ZitiDesktopEdge {
|
||||
return _identity;
|
||||
}
|
||||
set {
|
||||
_loaded = false;
|
||||
FilterServices.Clear();
|
||||
scrolledTo = 0;
|
||||
_identity = value;
|
||||
this.IdDetailToggle.Enabled = _identity.IsEnabled;
|
||||
ServiceCount.Content = _identity.Services.Count + " service"+((_identity.Services.Count>1)?"s":"");
|
||||
Page = 1;
|
||||
SortBy = "Name";
|
||||
SortWay = "Asc";
|
||||
SortByField.SelectedIndex = 0;
|
||||
SortWayField.SelectedIndex = 0;
|
||||
filter = "";
|
||||
UpdateView();
|
||||
IdentityArea.Opacity = 1.0;
|
||||
IdentityArea.Visibility = Visibility.Visible;
|
||||
@@ -97,16 +113,31 @@ namespace ZitiDesktopEdge {
|
||||
}
|
||||
|
||||
public void UpdateView() {
|
||||
if (_scroller==null) {
|
||||
_scroller = GetScrollViewer(ServiceList) as ScrollViewer;
|
||||
}
|
||||
if (_scroller != null) {
|
||||
_scroller.InvalidateScrollInfo();
|
||||
_scroller.ScrollToVerticalOffset(0);
|
||||
_scroller.InvalidateScrollInfo();
|
||||
}
|
||||
scrolledTo = 0;
|
||||
IdDetailName.Text = _identity.Name;
|
||||
IdDetailName.ToolTip = _identity.Name;
|
||||
IdDetailToggle.Enabled = _identity.IsEnabled;
|
||||
IdentityName.Value = _identity.Name;
|
||||
IdentityNetwork.Value = _identity.ControllerUrl;
|
||||
IdentityEnrollment.Value = _identity.EnrollmentStatus;
|
||||
IdentityStatus.Value = _identity.IsEnabled ? "active" : "disabled";
|
||||
IdentityMFA.IsOn = _identity.IsMFAEnabled;
|
||||
IdentityMFA.ToggleField.IsEnabled = true;
|
||||
IdentityMFA.ToggleField.Opacity = 1;
|
||||
IsConnected.Visibility = Visibility.Collapsed;
|
||||
IsDisconnected.Visibility = Visibility.Collapsed;
|
||||
IsConnected.ToolTip = "Enabled - Click To Disable";
|
||||
IsDisconnected.ToolTip = "Disabled - Click to Enable";
|
||||
IdServer.Value = _identity.ControllerUrl;
|
||||
IdName.Value = _identity.Name;
|
||||
if (_identity.IsEnabled) {
|
||||
IsConnected.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
IsDisconnected.Visibility = Visibility.Visible;
|
||||
}
|
||||
if (_identity.IsMFAEnabled) {
|
||||
if (_identity.MFAInfo.IsAuthenticated) {
|
||||
IdentityMFA.ToggleField.IsEnabled = true;
|
||||
@@ -125,13 +156,16 @@ namespace ZitiDesktopEdge {
|
||||
IdentityMFA.AuthOff.Visibility = Visibility.Collapsed;
|
||||
IdentityMFA.RecoveryButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
ServiceList.Children.Clear();
|
||||
PageSortArea.Visibility = Visibility.Collapsed;
|
||||
//ServiceList.Children.Clear();
|
||||
|
||||
totalServices = _identity.Services.Count;
|
||||
|
||||
if (_identity.Services.Count>0) {
|
||||
PageSortArea.Visibility = Visibility.Visible;
|
||||
int index = 0;
|
||||
int total = 0;
|
||||
ZitiService[] services = new ZitiService[0];
|
||||
_services = null;
|
||||
_services = new ObservableCollection<ZitiService>();
|
||||
if (SortBy == "Name") services = _identity.Services.OrderBy(s => s.Name.ToLower()).ToArray();
|
||||
else if (SortBy == "Address") services = _identity.Services.OrderBy(s => s.Addresses.ToString()).ToArray();
|
||||
else if (SortBy == "Protocol") services = _identity.Services.OrderBy(s => s.Protocols.ToString()).ToArray();
|
||||
@@ -140,86 +174,49 @@ namespace ZitiDesktopEdge {
|
||||
int startIndex = (Page - 1) * PerPage;
|
||||
for (int i= startIndex; i<services.Length; i++) {
|
||||
ZitiService zitiSvc = services[i];
|
||||
total++;
|
||||
if (index<100) {
|
||||
total++;
|
||||
if (index<PerPage) {
|
||||
if (zitiSvc.Name.ToLower().IndexOf(filter.ToLower()) >= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) {
|
||||
Logger.Trace("painting: " + zitiSvc.Name);
|
||||
ServiceInfo info = new ServiceInfo();
|
||||
info.Info = zitiSvc;
|
||||
info.OnMessage += Info_OnMessage;
|
||||
info.OnDetails += ShowDetails;
|
||||
ServiceList.Children.Add(info);
|
||||
_services.Add(zitiSvc);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ServiceList.ItemsSource = ZitiServices;
|
||||
|
||||
if (Page==1) {
|
||||
Pages.Items.Clear();
|
||||
int totalPages = (total / PerPage) + 1;
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
ComboBoxItem item = new ComboBoxItem();
|
||||
if (i == Page) item.IsSelected = true;
|
||||
item.Content = i.ToString();
|
||||
Pages.Items.Add(item);
|
||||
}
|
||||
}
|
||||
TotalPages = (total / PerPage) + 1;
|
||||
|
||||
double newHeight = MainHeight - 330;
|
||||
ServiceRow.Height = new GridLength((double)newHeight);
|
||||
double newHeight = MainHeight - 330;
|
||||
MainDetailScroll.MaxHeight = newHeight;
|
||||
MainDetailScroll.Height = newHeight;
|
||||
MainDetailScroll.Visibility = Visibility.Visible;
|
||||
ServiceTitle.Label = _identity.Services.Count + " Services";
|
||||
ServiceTitle.MainEdit.Visibility = Visibility.Visible;
|
||||
ServiceTitle.Visibility = Visibility.Visible;
|
||||
|
||||
AuthMessageBg.Visibility = Visibility.Collapsed;
|
||||
AuthMessageLabel.Visibility = Visibility.Collapsed;
|
||||
NoAuthServices.Visibility = Visibility.Collapsed;
|
||||
} else {
|
||||
ServiceRow.Height = new GridLength((double)0.0);
|
||||
MainDetailScroll.Visibility = Visibility.Collapsed;
|
||||
ServiceTitle.Label = "No Services";
|
||||
ServiceTitle.MainEdit.Text = "";
|
||||
ServiceTitle.MainEdit.Visibility = Visibility.Collapsed;
|
||||
if (this._identity.IsMFAEnabled&&!this._identity.MFAInfo.IsAuthenticated) {
|
||||
ServiceTitle.Visibility = Visibility.Collapsed;
|
||||
AuthMessageBg.Visibility = Visibility.Visible;
|
||||
AuthMessageLabel.Visibility = Visibility.Visible;
|
||||
ServiceRow.Height = new GridLength((double)30);
|
||||
NoAuthServices.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
ServiceTitle.Visibility = Visibility.Visible;
|
||||
AuthMessageBg.Visibility = Visibility.Collapsed;
|
||||
AuthMessageLabel.Visibility = Visibility.Collapsed;
|
||||
NoAuthServices.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
ConfirmView.Visibility = Visibility.Collapsed;
|
||||
_loaded = true;
|
||||
}
|
||||
|
||||
private void ShowDetails(ZitiService info) {
|
||||
DetailName.Text = info.Name;
|
||||
DetailProtocols.Text = info.ProtocolString;
|
||||
DetailAddress.Text = info.AddressString;
|
||||
DetailPorts.Text = info.PortString;
|
||||
DetailUrl.Text = info.ToString();
|
||||
|
||||
string protocols = "";
|
||||
string addresses = "";
|
||||
string ports = "";
|
||||
|
||||
for (int i = 0; i < info.Protocols.Length; i++) {
|
||||
protocols += ((i > 0) ? "," : "") + info.Protocols[i];
|
||||
}
|
||||
for (int i = 0; i < info.Addresses.Length; i++) {
|
||||
addresses += ((i>0)?",":"")+info.Addresses[i];
|
||||
}
|
||||
for (int i = 0; i < info.Ports.Length; i++) {
|
||||
ports += ((i > 0) ? "," : "") + info.Ports[i];
|
||||
}
|
||||
|
||||
DetailProtocols.Text = protocols;
|
||||
DetailAddress.Text = addresses;
|
||||
DetailPorts.Text = ports;
|
||||
|
||||
DetailsArea.Visibility = Visibility.Visible;
|
||||
DetailsArea.Opacity = 0;
|
||||
DetailsArea.Margin = new Thickness(0, 0, 0, 0);
|
||||
@@ -257,15 +254,6 @@ namespace ZitiDesktopEdge {
|
||||
OnMessage?.Invoke(message);
|
||||
}
|
||||
|
||||
async private void IdToggle(bool on) {
|
||||
DataClient client = (DataClient)Application.Current.Properties["ServiceClient"];
|
||||
await client.IdentityOnOffAsync(_identity.Fingerprint, on);
|
||||
if (SelectedIdentity!=null) SelectedIdentity.ToggleSwitch.Enabled = on;
|
||||
if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = on;
|
||||
_identity.IsEnabled = on;
|
||||
IdentityStatus.Value = _identity.IsEnabled ? "active" : "disabled";
|
||||
}
|
||||
|
||||
public IdentityDetails() {
|
||||
InitializeComponent();
|
||||
}
|
||||
@@ -277,7 +265,7 @@ namespace ZitiDesktopEdge {
|
||||
MainDetailScroll.Height = height;
|
||||
}
|
||||
|
||||
private void ForgetIdentity(object sender, MouseButtonEventArgs e) {
|
||||
private void ForgetIdentity() {
|
||||
if (this.Visibility==Visibility.Visible&&ConfirmView.Visibility==Visibility.Collapsed) {
|
||||
ConfirmView.Visibility = Visibility.Visible;
|
||||
}
|
||||
@@ -313,12 +301,6 @@ namespace ZitiDesktopEdge {
|
||||
}
|
||||
}
|
||||
|
||||
private void DoFilter(string filter) {
|
||||
this.filter = filter;
|
||||
if (this._identity!=null) UpdateView();
|
||||
}
|
||||
|
||||
|
||||
private void ToggleMFA(bool isOn) {
|
||||
this.OnMFAToggled?.Invoke(isOn);
|
||||
}
|
||||
@@ -364,33 +346,112 @@ namespace ZitiDesktopEdge {
|
||||
this.Authenticate.Invoke(this.Identity);
|
||||
}
|
||||
|
||||
private void Pages_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
ComboBoxItem selected = (ComboBoxItem)Pages.SelectedValue;
|
||||
if (selected!=null) {
|
||||
int value = Int32.Parse(selected.Content.ToString());
|
||||
if (value!=Page) {
|
||||
Page = value;
|
||||
UpdateView();
|
||||
public static DependencyObject GetScrollViewer(DependencyObject o) {
|
||||
if (o is ScrollViewer) { return o; }
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) {
|
||||
var child = VisualTreeHelper.GetChild(o, i);
|
||||
var result = GetScrollViewer(child);
|
||||
if (result == null) {
|
||||
continue;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Scrolled(object sender, ScrollChangedEventArgs e) {
|
||||
if (_loaded) {
|
||||
if (_scroller == null) {
|
||||
_scroller = GetScrollViewer(ServiceList) as ScrollViewer;
|
||||
}
|
||||
var verticalOffset = _scroller.VerticalOffset;
|
||||
var maxVerticalOffset = _scroller.ScrollableHeight;
|
||||
|
||||
if ((maxVerticalOffset < 0 || verticalOffset == maxVerticalOffset) && verticalOffset>0 && scrolledTo<verticalOffset) {
|
||||
if (Page < TotalPages) {
|
||||
scrolledTo = verticalOffset;
|
||||
// scrollViewer.ScrollChanged -= Scrolled;
|
||||
Logger.Trace("Paging: " + Page);
|
||||
_loaded = false;
|
||||
Page += 1;
|
||||
int index = 0;
|
||||
ZitiService[] services = new ZitiService[0];
|
||||
if (SortBy == "Name") services = _identity.Services.OrderBy(s => s.Name.ToLower()).ToArray();
|
||||
else if (SortBy == "Address") services = _identity.Services.OrderBy(s => s.Addresses.ToString()).ToArray();
|
||||
else if (SortBy == "Protocol") services = _identity.Services.OrderBy(s => s.Protocols.ToString()).ToArray();
|
||||
else if (SortBy == "Port") services = _identity.Services.OrderBy(s => s.Ports.ToString()).ToArray();
|
||||
if (SortWay == "Desc") services = services.Reverse().ToArray();
|
||||
int startIndex = (Page - 1) * PerPage;
|
||||
for (int i = startIndex; i < services.Length; i++) {
|
||||
ZitiService zitiSvc = services[i];
|
||||
if (index < PerPage) {
|
||||
if (zitiSvc.Name.ToLower().IndexOf(filter.ToLower()) >= 0 || zitiSvc.ToString().ToLower().IndexOf(filter.ToLower()) >= 0) {
|
||||
ZitiServices.Add(zitiSvc);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
double totalOffset = _scroller.VerticalOffset;
|
||||
double toNegate = index * 33;
|
||||
double scrollTo = (totalOffset - toNegate);
|
||||
_scroller.InvalidateScrollInfo();
|
||||
_scroller.ScrollToVerticalOffset(verticalOffset);
|
||||
_scroller.InvalidateScrollInfo();
|
||||
_loaded = true;
|
||||
// scrollViewer.ScrollChanged += Scrolled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SortByField_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
ComboBoxItem selected = (ComboBoxItem)SortByField.SelectedValue;
|
||||
if (selected != null && selected.Content!=null) {
|
||||
if (selected.Content.ToString()!=SortBy) {
|
||||
SortBy = selected.Content.ToString();
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
private void DoFilter(FilterData filterData) {
|
||||
filter = filterData.SearchFor;
|
||||
SortBy = filterData.SortBy;
|
||||
SortWay = filterData.SortHow;
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private void SortWayField_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
ComboBoxItem selected = (ComboBoxItem)SortWayField.SelectedValue;
|
||||
if (selected != null && selected.Content != null) {
|
||||
if (selected.Content.ToString() != SortWay) {
|
||||
SortWay = selected.Content.ToString();
|
||||
UpdateView();
|
||||
async private void DoConnect(object sender, MouseButtonEventArgs e) {
|
||||
this.OnLoading?.Invoke(false);
|
||||
DataClient client = (DataClient)Application.Current.Properties["ServiceClient"];
|
||||
await client.IdentityOnOffAsync(_identity.Fingerprint, true);
|
||||
if (SelectedIdentity != null) SelectedIdentity.ToggleSwitch.Enabled = true;
|
||||
if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = true;
|
||||
_identity.IsEnabled = true;
|
||||
IsConnected.Visibility = Visibility.Visible;
|
||||
IsDisconnected.Visibility = Visibility.Collapsed;
|
||||
this.OnLoading?.Invoke(true);
|
||||
}
|
||||
|
||||
async private void DoDisconnect(object sender, MouseButtonEventArgs e) {
|
||||
this.OnLoading?.Invoke(false);
|
||||
DataClient client = (DataClient)Application.Current.Properties["ServiceClient"];
|
||||
await client.IdentityOnOffAsync(_identity.Fingerprint, false);
|
||||
if (SelectedIdentity != null) SelectedIdentity.ToggleSwitch.Enabled = false;
|
||||
if (SelectedIdentityMenu != null) SelectedIdentityMenu.ToggleSwitch.Enabled = false;
|
||||
_identity.IsEnabled = false;
|
||||
IsConnected.Visibility = Visibility.Collapsed;
|
||||
IsDisconnected.Visibility = Visibility.Visible;
|
||||
this.OnLoading?.Invoke(true);
|
||||
}
|
||||
|
||||
private void WarnClicked(object sender, MouseButtonEventArgs e) {
|
||||
ZitiService item = (ZitiService)(sender as FrameworkElement).DataContext;
|
||||
OnMessage?.Invoke(item.WarningMessage);
|
||||
}
|
||||
|
||||
private void DetailsClicked(object sender, MouseButtonEventArgs e) {
|
||||
ZitiService item = (ZitiService)(sender as FrameworkElement).DataContext;
|
||||
ShowDetails(item);
|
||||
}
|
||||
|
||||
private void VisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) {
|
||||
if (this.Visibility==Visibility.Collapsed) {
|
||||
ServiceList.DataContext = null;
|
||||
if (_services!=null) {
|
||||
_services.Clear();
|
||||
_services = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
mc:Ignorable="d"
|
||||
x:Name="MainMenuArea"
|
||||
d:DesignHeight="400" d:DesignWidth="400" Margin="1,1,1,1">
|
||||
|
||||
<Grid>
|
||||
<Canvas>
|
||||
<Rectangle Name="Arrow" HorizontalAlignment="Center" Height="20" Fill="White" VerticalAlignment="Bottom" Width="20" Canvas.Bottom="-10" Canvas.Left="185">
|
||||
@@ -93,6 +94,7 @@
|
||||
<local:MenuEditItem x:Name="ConfigSubnet" HorizontalAlignment="Stretch" Width="Auto" Label="Subnet Mask:"></local:MenuEditItem>
|
||||
<local:MenuEditItem x:Name="ConfigMtu" HorizontalAlignment="Stretch" Width="Auto" Label="MTU:"></local:MenuEditItem>
|
||||
<local:MenuEditItem x:Name="ConfigDns" HorizontalAlignment="Stretch" Width="Auto" Label="DNS Servers:"></local:MenuEditItem>
|
||||
<local:StyledButton x:Name="EditButton" OnClick="ShowEdit" Label="Edit Values" Grid.Row="8" Margin="0,20,0,0"></local:StyledButton>
|
||||
</StackPanel>
|
||||
<ScrollViewer Name="IdListScrollView" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" CanContentScroll="True" ClipToBounds="True" Visibility="Collapsed">
|
||||
<StackPanel Name="IdListView" Orientation="Vertical" IsItemsHost="False"></StackPanel>
|
||||
@@ -109,5 +111,77 @@
|
||||
<Label Name="MainItemsButton" Margin="0,10,0,0" Foreground="#F4044D" FontWeight="SemiBold" Content="Quit Ziti Desktop Edge" Cursor="Hand" MouseUp="CloseApp" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" HorizontalAlignment="Center"></Label>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Modal for Menu Items: Next revision make one global modal -->
|
||||
<Rectangle x:Name="ModalBg" Margin="10,10,10,10" Fill="Black" RadiusY="10" RadiusX="10" Opacity="0" Visibility="Collapsed"></Rectangle>
|
||||
|
||||
<!-- Modal For modifying the config data -->
|
||||
<Grid x:Name="EditArea" Visibility="Collapsed" Height="300" Margin="0,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Margin="10,10,10,10" BorderBrush="Black" BorderThickness="8" CornerRadius="10">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="20" Direction="1" RenderingBias="Quality" ShadowDepth="1" Opacity="1"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
<Rectangle Margin="10,10,10,10" RadiusX="10" RadiusY="10" ClipToBounds="True">
|
||||
<Rectangle.Fill>
|
||||
<SolidColorBrush Color="#FFFFFF" Opacity="0.97"/>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<StackPanel x:Name="DetailPanel" Grid.Column="0" Orientation="Vertical" Margin="20,20,20,20" VerticalAlignment="Center" FocusVisualStyle="{x:Null}">
|
||||
|
||||
<Label Content="IP Address" Padding="10,0,0,0" FontWeight="Bold" FontSize="14" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></Label>
|
||||
<TextBox x:Name="ConfigIpNew" Padding="10" Margin="10,10,10,10" Height="40" BorderThickness="1" TextAlignment="Left" FontSize="14" Foreground="Black" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans">
|
||||
<TextBox.Resources>
|
||||
<Style TargetType="{x:Type Border}">
|
||||
<Setter Property="CornerRadius" Value="7"/>
|
||||
</Style>
|
||||
</TextBox.Resources>
|
||||
</TextBox>
|
||||
|
||||
<Label Content="Subnet Mask" Padding="10,0,0,0" FontWeight="Bold" FontSize="14" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black"></Label>
|
||||
<ComboBox x:Name="ConfigMaskNew" Padding="10" Margin="10,10,10,10" FontSize="14" Height="40" FontFamily="pack://application:,,,/Assets/Fonts/#Open Sans" Foreground="Black" BorderBrush="#FFACACAC" Style="{DynamicResource ComboStyle}">
|
||||
<ComboBoxItem Content="/1 - 128.0.0.0" Tag="1" IsSelected="True"/>
|
||||
<ComboBoxItem Content="/2 - 192.0.0.0" Tag="2"/>
|
||||
<ComboBoxItem Content="/3 - 224.0.0.0" Tag="3"/>
|
||||
<ComboBoxItem Content="/4 - 240.0.0.0" Tag="4"/>
|
||||
<ComboBoxItem Content="/5 - 248.0.0.0" Tag="5"/>
|
||||
<ComboBoxItem Content="/6 - 252.0.0.0" Tag="6"/>
|
||||
<ComboBoxItem Content="/7 - 254.0.0.0" Tag="7"/>
|
||||
<ComboBoxItem Content="/8 - 255.0.0.0" Tag="8"/>
|
||||
<ComboBoxItem Content="/9 - 255.128.0.0" Tag="9"/>
|
||||
<ComboBoxItem Content="/10 - 255.192.0.0" Tag="10"/>
|
||||
<ComboBoxItem Content="/11 - 255.224.0.0" Tag="11"/>
|
||||
<ComboBoxItem Content="/12 - 255.240.0.0" Tag="12"/>
|
||||
<ComboBoxItem Content="/13 - 255.248.0.0" Tag="13"/>
|
||||
<ComboBoxItem Content="/14 - 255.252.0.0" Tag="14"/>
|
||||
<ComboBoxItem Content="/15 - 255.254.0.0" Tag="15"/>
|
||||
<ComboBoxItem Content="/16 - 255.255.0.0" Tag="16"/>
|
||||
<ComboBoxItem Content="/17 - 255.255.128.0" Tag="17"/>
|
||||
<ComboBoxItem Content="/18 - 255.255.192.0" Tag="18"/>
|
||||
<ComboBoxItem Content="/19 - 255.255.224.0" Tag="19"/>
|
||||
<ComboBoxItem Content="/20 - 255.255.240.0" Tag="20"/>
|
||||
<ComboBoxItem Content="/21 - 255.255.248.0" Tag="21"/>
|
||||
<ComboBoxItem Content="/22 - 255.255.252.0" Tag="22"/>
|
||||
<ComboBoxItem Content="/23 - 255.255.254.0" Tag="23"/>
|
||||
<ComboBoxItem Content="/24 - 255.255.255.0" Tag="24"/>
|
||||
<ComboBoxItem Content="/25 - 255.255.255.128" Tag="25"/>
|
||||
<ComboBoxItem Content="/26 - 255.255.255.192" Tag="26"/>
|
||||
<ComboBoxItem Content="/27 - 255.255.255.224" Tag="27"/>
|
||||
<ComboBoxItem Content="/28 - 255.255.255.240" Tag="28"/>
|
||||
<ComboBoxItem Content="/29 - 255.255.255.248" Tag="29"/>
|
||||
<ComboBoxItem Content="/30 - 255.255.255.252" Tag="30"/>
|
||||
<ComboBoxItem Content="/31 - 255.255.255.254" Tag="31"/>
|
||||
<ComboBoxItem Content="/32 - 255.255.255.255" Tag="32"/>
|
||||
</ComboBox>
|
||||
|
||||
<CheckBox x:Name="AddDnsNew" Content="Add DNS" IsChecked="True" Margin="10"/>
|
||||
|
||||
<local:StyledButton x:Name="SaveConfigButton" OnClick="SaveConfig" Label="Save" Grid.Row="8"></local:StyledButton>
|
||||
</StackPanel>
|
||||
<Image Source="/Assets/Images/closeBlack.png" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,40,40,0" Width="10" Height="10" Cursor="Hand" MouseUp="CloseEditConfig"></Image>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -143,11 +143,15 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Models\FilterData.cs" />
|
||||
<Compile Include="Models\MessageCount.cs" />
|
||||
<Compile Include="Models\MFA.cs" />
|
||||
<Compile Include="Views\Controls\StyledButton.xaml.cs">
|
||||
<DependentUpon>StyledButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ItemRenderers\Filter.xaml.cs">
|
||||
<DependentUpon>Filter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ItemRenderers\MenuEditSearch.xaml.cs">
|
||||
<DependentUpon>MenuEditSearch.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -197,6 +201,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ItemRenderers\Filter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ItemRenderers\MenuEditSearch.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -447,5 +455,10 @@
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\Images\recovery.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\Images\disconnected.png" />
|
||||
<Resource Include="Assets\Images\name.png" />
|
||||
<Resource Include="Assets\Images\statusconnected.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -23,10 +23,10 @@
|
||||
<ROW Property="CTRLS" Value="2"/>
|
||||
<ROW Property="Manufacturer" Value="NetFoundry, Inc."/>
|
||||
<ROW Property="MsiLogging" MultiBuildValue="AnyCPU_Release:vp"/>
|
||||
<ROW Property="ProductCode" Value="1033:{758AA10B-B1A9-45FB-97AB-20759FAB902D} " Type="16"/>
|
||||
<ROW Property="ProductCode" Value="1033:{426F09F2-D144-425D-BB84-593EAA8A6CE2} " Type="16"/>
|
||||
<ROW Property="ProductLanguage" Value="1033"/>
|
||||
<ROW Property="ProductName" Value="Ziti Desktop Edge"/>
|
||||
<ROW Property="ProductVersion" Value="1.9.3" Type="32"/>
|
||||
<ROW Property="ProductVersion" Value="1.9.4" Type="32"/>
|
||||
<ROW Property="REBOOT" MultiBuildValue="AnyCPU_Release:Suppress"/>
|
||||
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
|
||||
<ROW Property="UpgradeCode" Value="{CB7E173A-663D-4A23-BB22-D1E8D885C2F3}"/>
|
||||
|
||||
@@ -459,4 +459,27 @@ namespace ZitiDesktopEdge.DataStructures {
|
||||
public class MfaRecoveryCodesResponse : SvcResponse {
|
||||
public string[] Payload { get; set; }
|
||||
}
|
||||
|
||||
public class ConfigPayload
|
||||
{
|
||||
public string TunIPv4 { get; set; }
|
||||
public int TunIPv4Mask { get; set; }
|
||||
public bool AddDns { get; set; }
|
||||
}
|
||||
|
||||
public class ConfigUpdateFunction : ServiceFunction
|
||||
{
|
||||
public ConfigUpdateFunction(string tunIPv4, int tunIPv4Mask, bool addDns)
|
||||
{
|
||||
this.Function = "UpdateTunIpv4";
|
||||
this.Payload = new ConfigPayload()
|
||||
{
|
||||
TunIPv4 = tunIPv4,
|
||||
TunIPv4Mask = tunIPv4Mask,
|
||||
AddDns = addDns
|
||||
};
|
||||
}
|
||||
public ConfigPayload Payload { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -390,6 +390,30 @@ namespace ZitiDesktopEdge.ServiceClient {
|
||||
return;
|
||||
}
|
||||
|
||||
async public Task<SvcResponse> UpdateConfigAsync(string tunIPv4, int tunIPv4Mask, bool addDns) {
|
||||
SvcResponse resp = null;
|
||||
try {
|
||||
|
||||
ConfigUpdateFunction configPayload = new ConfigUpdateFunction(tunIPv4, tunIPv4Mask, addDns);
|
||||
|
||||
await sendAsync(configPayload);
|
||||
resp = await readAsync<SvcResponse>(ipcReader);
|
||||
Logger.Debug("config update payload is sent to the ziti tunnel");
|
||||
} catch (Exception ex) {
|
||||
//almost certainly a problem with the pipe - recreate the pipe...
|
||||
//setupPipe();
|
||||
//throw;
|
||||
Logger.Error(ex, "Unexpected error");
|
||||
CommunicationError(ex);
|
||||
throw ex;
|
||||
}
|
||||
if (resp?.Code != 0) {
|
||||
Logger.Warn("failed to update the config. {0} {1}", resp.Message, resp.Error);
|
||||
throw new ServiceException("Failed to update the config", resp.Code, "Un expected error.");
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
async public Task<ZitiTunnelStatus> debugAsync() {
|
||||
try {
|
||||
await sendAsync(new ServiceFunction() { Function = "Debug" });
|
||||
|
||||
@@ -30,6 +30,6 @@ using System.Runtime.InteropServices;
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.9.3.0")]
|
||||
[assembly: AssemblyVersion("1.9.3.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.3.0")]
|
||||
// [assembly: AssemblyVersion("1.9.4.0")]
|
||||
[assembly: AssemblyVersion("1.9.4.0")]
|
||||
[assembly: AssemblyFileVersion("1.9.4.0")]
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace ZitiUpdateService {
|
||||
}
|
||||
return zipName;
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Unexpected error {0}", ex.Message);
|
||||
Logger.Error(ex, "Unexpected error in generating system files {0}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +233,7 @@ namespace ZitiUpdateService {
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Unexpected error {0}", ex.Message);
|
||||
Logger.Error(ex, "Unexpected error in outputIpconfigInfo {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ namespace ZitiUpdateService {
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Unexpected error {0}", ex.Message);
|
||||
Logger.Error(ex, "Unexpected error in outputSystemInfo {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace ZitiUpdateService {
|
||||
process.Start();
|
||||
process.WaitForExit();
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Unexpected error {0}", ex.Message);
|
||||
Logger.Error(ex, "Unexpected error in outputDnsCache {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace ZitiUpdateService {
|
||||
string responseBody = resp.Content.ReadAsStringAsync().Result;
|
||||
File.WriteAllText(extIpFile, responseBody);
|
||||
} catch (Exception ex) {
|
||||
Logger.Error(ex, "Unexpected error {0}", ex.Message);
|
||||
Logger.Error(ex, "Unexpected error in outputExternalIP {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -1,16 +1,14 @@
|
||||
# Release 1.9.3
|
||||
# Release 1.9.4
|
||||
|
||||
## What's New
|
||||
* Page Service List
|
||||
* Sort Service on Identity Details Page
|
||||
* Consistent UX for MFA Screens
|
||||
* none
|
||||
|
||||
## Other changes:
|
||||
* Service to UI interaction is now with one bulk update of services instead of one event per service update
|
||||
* Added a configuration option to control if DNS is applied to the TUN. Some users are having issues with NRPT-only working. For now we'll add a boolean that allows the user to control if DNS should be added to the TUN
|
||||
* none
|
||||
|
||||
## Bugs fixed:
|
||||
* none
|
||||
* [#362](https://github.com/openziti/desktop-edge-win/issues/362) Update tun ip, mask and addDns flag
|
||||
* [#364](https://github.com/openziti/desktop-edge-win/issues/364) Add the test nrpt policy function in the startup method
|
||||
|
||||
## Dependency Updates
|
||||
* none
|
||||
@@ -24,6 +22,7 @@
|
||||
|
||||
## Other changes:
|
||||
* Service to UI interaction is now with one bulk update of services instead of one event per service update
|
||||
* Added a configuration option to control if DNS is applied to the TUN. Some users are having issues with NRPT-only working. For now we'll add a boolean that allows the user to control if DNS should be added to the TUN
|
||||
|
||||
## Bugs fixed:
|
||||
* none
|
||||
|
||||
@@ -238,3 +238,53 @@ ForEach ($ns in $toRemove){
|
||||
log.Errorf("ERROR removing nrpt rules: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func IsNrptPoliciesEffective(dnsserver string) bool {
|
||||
script := fmt.Sprintf(`Add-DnsClientNrptRule -Namespace ".ziti.test" -NameServers "%s" -Comment "Added by ziti-tunnel" -DisplayName "ziti-tunnel:.ziti.test"
|
||||
Get-DnsClientNrptPolicy -Effective | Select-Object Namespace -Unique | Where-Object Namespace -Eq ".ziti.test"`, dnsserver)
|
||||
log.Debugf("checking the nrpt policies with: %s", script)
|
||||
|
||||
cmd := exec.Command("powershell", "-Command", script)
|
||||
cmd.Stderr = os.Stdout
|
||||
output := new(bytes.Buffer)
|
||||
cmd.Stdout = output
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Errorf("ERROR adding the test nrpt rules: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
policyFound := false
|
||||
for {
|
||||
l, err := output.ReadString('\n')
|
||||
policyOut := strings.Trim(l, "\r\n")
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if strings.Compare(policyOut, ".ziti.test") == 0 {
|
||||
policyFound = true
|
||||
log.Debug("The nrpt policies are effective in this client")
|
||||
break
|
||||
}
|
||||
}
|
||||
removeSingleNrtpRule(".ziti.test")
|
||||
|
||||
return policyFound
|
||||
}
|
||||
|
||||
func removeSingleNrtpRule(nrptRule string) {
|
||||
script := fmt.Sprintf(`Get-DnsClientNrptRule | where Namespace -eq "%s" | Remove-DnsClientNrptRule -Force -ErrorAction SilentlyContinue`, nrptRule)
|
||||
log.Debugf("Removing the nrpt rule with: %s", script)
|
||||
|
||||
cmd := exec.Command("powershell", "-Command", script)
|
||||
cmd.Stderr = os.Stdout
|
||||
output := new(bytes.Buffer)
|
||||
cmd.Stdout = output
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Errorf("ERROR removing the nrpt rules: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ var NOTIFY_IDENTITY_UI = dto.CommandMsg{
|
||||
Function: "NotifyIdentityUI",
|
||||
}
|
||||
|
||||
var UPDATE_TUN_IPV4 = dto.CommandMsg{
|
||||
Function: "UpdateTunIpv4",
|
||||
}
|
||||
|
||||
var monitorIpcPipe = `\\.\pipe\OpenZiti\ziti-monitor\ipc`
|
||||
|
||||
var templateIdentity = `{{printf "%40s" "Name"}} | {{printf "%41s" "FingerPrint"}} | {{printf "%6s" "Active"}} | {{printf "%30s" "Config"}} | {{"Status"}}
|
||||
|
||||
@@ -57,11 +57,11 @@ func convertToServiceCli(svc dto.Service) dto.ServiceCli {
|
||||
}
|
||||
|
||||
return dto.ServiceCli{
|
||||
Name: svc.Name,
|
||||
Id: svc.Id,
|
||||
Protocols: strings.Join(svc.Protocols, ","),
|
||||
Ports: cliPorts,
|
||||
Addresses: cliAddresses,
|
||||
Name: svc.Name,
|
||||
Id: svc.Id,
|
||||
Protocols: strings.Join(svc.Protocols, ","),
|
||||
Ports: cliPorts,
|
||||
Addresses: cliAddresses,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
/*
|
||||
* Copyright NetFoundry, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
import (
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//GetIdentities is to fetch identities through cmdline
|
||||
@@ -53,3 +71,40 @@ func SetLogLevel(args []string, flags map[string]bool) {
|
||||
func GetFeedback(args []string, flags map[string]bool) {
|
||||
GetDataFromMonitorIpcPipe(&dto.FEEDBACK_REQUEST, args, flags)
|
||||
}
|
||||
|
||||
func UpdateConfigIPSubnet(args []string, flags map[string]interface{}) {
|
||||
CIDRstring := flags["CIDR"]
|
||||
AddDns := flags["AddDns"]
|
||||
log.Info("Updating the config file")
|
||||
|
||||
updateTunIpv4Payload := make(map[string]interface{})
|
||||
if CIDRstring != "" {
|
||||
ip, ipnet, err := net.ParseCIDR(CIDRstring.(string))
|
||||
if err != nil {
|
||||
log.Error("Incorrect cidr %s", CIDRstring.(string))
|
||||
}
|
||||
ipMask, _ := ipnet.Mask.Size()
|
||||
|
||||
updateTunIpv4Payload["TunIPv4"] = ip
|
||||
updateTunIpv4Payload["TunIPv4Mask"] = ipMask
|
||||
}
|
||||
if AddDns != "" {
|
||||
addDnsBool, err := strconv.ParseBool(AddDns.(string))
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Incorrect addDns %v", err)
|
||||
return
|
||||
}
|
||||
updateTunIpv4Payload["AddDns"] = addDnsBool
|
||||
}
|
||||
|
||||
UPDATE_TUN_IPV4.Payload = updateTunIpv4Payload
|
||||
log.Debugf("updateTunIpv4 Payload %v", UPDATE_TUN_IPV4)
|
||||
|
||||
status := GetDataFromIpcPipe(&UPDATE_TUN_IPV4, nil, GetResponseObjectFromRTS, args, nil)
|
||||
|
||||
if !status {
|
||||
log.Infof("Config can be updated only if the tunnel is started")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package cmd
|
||||
|
||||
/*
|
||||
* Copyright NetFoundry, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// configCmd represents the config command
|
||||
var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "A brief description of your command",
|
||||
Long: `A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
checkHelp()
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(configCmd)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cmd
|
||||
|
||||
/*
|
||||
* Copyright NetFoundry, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
import (
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/cli"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var CIDR string
|
||||
var AddDns string
|
||||
|
||||
// updateCmd represents the update command
|
||||
var updateCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Updates data into the ziti-tunnel",
|
||||
Long: `update command should be used as a sub command to the main command
|
||||
It helps to update the data into the ziti-tunnel.
|
||||
eg: ziti-tunnel config update --CIDR 100.64.0.1/10 --AddDns=true`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
flags := map[string]interface{}{}
|
||||
flags["CIDR"] = CIDR
|
||||
flags["AddDns"] = AddDns
|
||||
cli.UpdateConfigIPSubnet(args, flags)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
configCmd.AddCommand(updateCmd)
|
||||
|
||||
updateCmd.Flags().StringVar(&CIDR, "CIDR", "", "Updates the cidr property in the config file")
|
||||
updateCmd.Flags().StringVar(&AddDns, "AddDns", "", "Updates the Add Dns property in the config file")
|
||||
|
||||
}
|
||||
@@ -27,11 +27,11 @@ type IdentityCli struct {
|
||||
}
|
||||
|
||||
type ServiceCli struct {
|
||||
Name string
|
||||
Id string
|
||||
Protocols string
|
||||
Ports string
|
||||
Addresses string
|
||||
Name string
|
||||
Id string
|
||||
Protocols string
|
||||
Ports string
|
||||
Addresses string
|
||||
}
|
||||
|
||||
type IdentityOnOffPayload struct {
|
||||
|
||||
@@ -111,6 +111,8 @@ func main() {
|
||||
commandline.Execute()
|
||||
case "feedback":
|
||||
commandline.Execute()
|
||||
case "config":
|
||||
commandline.Execute()
|
||||
default:
|
||||
usage(fmt.Sprintf("invalid command %s", cmd))
|
||||
}
|
||||
@@ -126,7 +128,7 @@ func usage(errmsg string) {
|
||||
"%s\n\n"+
|
||||
"usage: %s <command>\n"+
|
||||
" where <command> is one of\n"+
|
||||
" install, remove, debug, start, stop, pause, continue, list, identity, loglevel, feedback or version.\n",
|
||||
" install, remove, debug, start, stop, pause, continue, list, identity, loglevel, feedback, config or version.\n",
|
||||
errmsg, os.Args[0])
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -498,6 +499,21 @@ func serveIpc(conn net.Conn) {
|
||||
|
||||
//save the state
|
||||
rts.SaveState()
|
||||
case "UpdateTunIpv4":
|
||||
var tunIPv4 string
|
||||
var tunIPv4Mask int
|
||||
var addDns string
|
||||
if cmd.Payload["TunIPv4"] != nil {
|
||||
tunIPv4 = cmd.Payload["TunIPv4"].(string)
|
||||
}
|
||||
if cmd.Payload["TunIPv4Mask"] != nil {
|
||||
var tunIpv4Mask = cmd.Payload["TunIPv4Mask"].(float64)
|
||||
tunIPv4Mask = int(tunIpv4Mask)
|
||||
}
|
||||
if cmd.Payload["AddDns"] != nil {
|
||||
addDns = strconv.FormatBool(cmd.Payload["AddDns"].(bool))
|
||||
}
|
||||
updateTunIpv4(enc, tunIPv4, tunIPv4Mask, addDns)
|
||||
case "NotifyLogLevelUIAndUpdateService":
|
||||
sendLogLevelAndNotify(enc, cmd.Payload["Level"].(string))
|
||||
case "NotifyIdentityUI":
|
||||
@@ -622,6 +638,17 @@ func setLogLevel(out *json.Encoder, level string) {
|
||||
respond(out, dto.Response{Message: "log level set", Code: SUCCESS, Error: "", Payload: nil})
|
||||
}
|
||||
|
||||
func updateTunIpv4(out *json.Encoder, ip string, ipMask int, addDns string) {
|
||||
|
||||
err := UpdateRuntimeStateIpv4(ip, ipMask, addDns)
|
||||
if err != nil {
|
||||
respondWithError(out, "Could not set Tun ip and mask", UNKNOWN_ERROR, err)
|
||||
return
|
||||
}
|
||||
|
||||
respond(out, dto.Response{Message: "TunIPv4 and mask is set, Manual Restart is required", Code: SUCCESS, Error: "", Payload: ""})
|
||||
}
|
||||
|
||||
func serveLogs(conn net.Conn) {
|
||||
log.Debug("accepted a logs connection, writing logs to pipe")
|
||||
w := bufio.NewWriter(conn)
|
||||
|
||||
@@ -20,24 +20,26 @@ package service
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/openziti/desktop-edge-win/service/cziti"
|
||||
"github.com/openziti/desktop-edge-win/service/windns"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
|
||||
idcfg "github.com/openziti/sdk-golang/ziti/config"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/openziti/desktop-edge-win/service/cziti"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/config"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/constants"
|
||||
"github.com/openziti/desktop-edge-win/service/ziti-tunnel/dto"
|
||||
idcfg "github.com/openziti/sdk-golang/ziti/config"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
)
|
||||
|
||||
type RuntimeState struct {
|
||||
@@ -221,7 +223,14 @@ func (t *RuntimeState) CreateTun(ipv4 string, ipv4mask int, applyDns bool) (net.
|
||||
}
|
||||
log.Info("routing applied")
|
||||
|
||||
if applyDns {
|
||||
zitiPoliciesEffective := windns.IsNrptPoliciesEffective(ipv4)
|
||||
if applyDns || !zitiPoliciesEffective {
|
||||
if applyDns {
|
||||
log.Infof("DNS is applied to the TUN interface, because apply Dns flag in the config file is %t ", applyDns)
|
||||
}
|
||||
if !applyDns && !zitiPoliciesEffective {
|
||||
log.Infof("DNS is applied to the TUN interface, because Ziti policies test result in this client is %t", zitiPoliciesEffective)
|
||||
}
|
||||
//for windows 10+, could 'domains' be able to replace NRPT? dunno - didn't test it
|
||||
luid.SetDNS(windows.AF_INET, []net.IP{ip}, nil)
|
||||
}
|
||||
@@ -401,6 +410,35 @@ func (t *RuntimeState) UpdateIpv4(ipv4 string) {
|
||||
rts.SaveState()
|
||||
}
|
||||
|
||||
func UpdateRuntimeStateIpv4(ip string, ipv4Mask int, addDns string) error {
|
||||
|
||||
log.Infof("updating configuration ip: %s, mask: %d, dns: %t", ip, ipv4Mask, addDns)
|
||||
|
||||
if ipv4Mask < constants.Ipv4MaxMask || ipv4Mask > constants.Ipv4MinMask {
|
||||
return errors.New(fmt.Sprintf("ipv4Mask should be between %d and %d", constants.Ipv4MaxMask, constants.Ipv4MinMask))
|
||||
}
|
||||
|
||||
if addDns != "" {
|
||||
addDnsBool, err := strconv.ParseBool(addDns)
|
||||
|
||||
if err != nil {
|
||||
return errors.New(fmt.Sprintf("Incorrect addDns %v", err))
|
||||
}
|
||||
|
||||
rts.state.AddDns = addDnsBool
|
||||
}
|
||||
|
||||
// if ip is not empty, then we set both ip and mask
|
||||
if ip != "" {
|
||||
rts.state.TunIpv4 = ip
|
||||
rts.state.TunIpv4Mask = ipv4Mask
|
||||
}
|
||||
|
||||
rts.SaveState()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// uses the registry to determine if IPv6 is enabled or disabled on this machine. If it is disabled an IPv6 DNS entry
|
||||
// will end up causing a fatal error on startup of the service. For this registry key and values see the MS documentation
|
||||
// at https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
package main
|
||||
|
||||
const (
|
||||
Version = "1.9.3"
|
||||
Revision = "a02a50cf6437"
|
||||
Branch = "main"
|
||||
Version = "1.9.4"
|
||||
Revision = "2db5f6a8362d"
|
||||
Branch = "release-next"
|
||||
BuildUser = ""
|
||||
BuildDate = "2021-04-12 17:35:14"
|
||||
BuildDate = "2021-04-21 18:46:25"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user