diff --git a/ZKuP/MainWindow.xaml b/ZKuP/MainWindow.xaml index 3159133..8e8ee41 100644 --- a/ZKuP/MainWindow.xaml +++ b/ZKuP/MainWindow.xaml @@ -173,7 +173,7 @@ - + @@ -554,8 +554,19 @@ + + + + + - + + + + + + + @@ -786,13 +797,13 @@ - + - + diff --git a/ZKuP/MainWindow.xaml.cs b/ZKuP/MainWindow.xaml.cs index 302e506..ddc9b7f 100644 --- a/ZKuP/MainWindow.xaml.cs +++ b/ZKuP/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using ControlzEx.Standard; using FuzzySharp; using MahApps.Metro.Controls; using Microsoft.Toolkit.Uwp.Notifications; +using Microsoft.Win32; using MySql.Data.MySqlClient; using MySql.Data.Types; using System; @@ -28,6 +29,8 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Threading; +using Windows.Storage.Pickers; +using Windows.Storage.Streams; using Windows.UI.Composition; using Process = System.Diagnostics.Process; @@ -46,7 +49,7 @@ namespace ZKuP PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - public static string Version { get; } = "5.2.5.2"; + public static string Version { get; } = "5.2.6.1"; //public static Roles LoggedInRole { get; private set; } = Roles.None; internal static MainWindow main; ThemeManager TM; @@ -369,6 +372,7 @@ namespace ZKuP private void OnWindowMoveFinished() { + CheckArrivalsSpacing(gridSplitter, null); Helper.CheckScale(this); } @@ -537,23 +541,36 @@ namespace ZKuP RoleManager.LoggedInRole != Roles.None) { var id = SQL.ReadSingleValue($"SELECT idusers FROM {MainWindow.table}.users WHERE `Username` = '{Environment.UserName}'"); - var aspId = SQL.ReadSingleValue($"SELECT EXISTS (SELECT 1 FROM ansprechpartner WHERE CreatorID = '{id}')"); + var aspId = SQL.ReadSingleValue($"SELECT EXISTS (SELECT 1 FROM {MainWindow.table}.ansprechpartner WHERE CreatorID = '{id}')"); if (aspId != "0") { var res = SQL.ReadSQL($"SELECT * FROM {MainWindow.table}.ansprechpartner WHERE CreatorID = '{id}'").Result; var firstRow = res.Rows[0]; - bool hasEmptyOrNull = firstRow.ItemArray.Any(field => - field == DBNull.Value || - (field is string str && string.IsNullOrWhiteSpace(str)) - ); + var emptyFields = firstRow.Table.Columns + .Cast() + .Where(col => + { + var value = firstRow[col]; + return value == DBNull.Value || + (value is string s && string.IsNullOrWhiteSpace(s)); + }) + .Select(col => col.ColumnName) + .ToList(); - if (hasEmptyOrNull) + //bool hasEmptyOrNull = firstRow.ItemArray.Any(field => + // field == DBNull.Value || + // (field is string str && string.IsNullOrWhiteSpace(str)) + // ); + + if (emptyFields.Count > 0) { if (MessageBoxResult.OK == MessageBox.Show("Ihr Eintrag als Ansprechpartner ist nicht vorhanden oder unvollständig!\n\nBitte erstellen oder vervollständigen", "Fehlende Asp Informationen", MessageBoxButton.OK, MessageBoxImage.Warning)) { - ManageAsp map = new ManageAsp(); + ManageAsp map = new ManageAsp(emptyFields); map.ShowDialog(); + + } } } @@ -1135,7 +1152,12 @@ namespace ZKuP private async Task getToday() { bool isVisible = false; - Dispatcher.Invoke(() => isVisible = gridToday.Visibility == Visibility.Visible); + Dispatcher.Invoke(() => + { + isVisible = gridToday.Visibility == Visibility.Visible; + Cursor = Cursors.Wait; + }); + if (isVisible) { //bool changeTable = false; @@ -1250,6 +1272,8 @@ namespace ZKuP q.Click += BtnInfo_Click; })); } + + Dispatcher.Invoke(() => Cursor = Cursors.Arrow); } @@ -2740,6 +2764,11 @@ namespace ZKuP private void gridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) + { + CheckArrivalsSpacing(sender, e); + } + + private void CheckArrivalsSpacing(object sender, DragCompletedEventArgs e) { GridSplitter splitter = sender as GridSplitter; Window window = Window.GetWindow(splitter); @@ -2748,16 +2777,29 @@ namespace ZKuP Point splitterPosition = splitter.TransformToAncestor(window).Transform(new Point(0, 0)); - if (splitterPosition.Y > ((this.ActualHeight - 190) / Helper.scale)) - { - e.Handled = true; // Bewegung stoppen - gridRowTop.Height = new GridLength((this.ActualHeight - 160 - 190) / (Helper.scale == 0 ? 1 : Helper.scale)); + var arrivalsHeight = this.ActualHeight - splitterPosition.Y; + + var x = gridRowArrivals.ActualHeight; + + + if(arrivalsHeight < 100) + { + //if (arrivalsHeight < ((this.ActualHeight * .05))) + //{ + if(e != null) e.Handled = true; // Bewegung stoppen 160: MenuRow Height + //gridRowTop.Height = new GridLength((this.ActualHeight - Main.ActualHeight - (this.ActualHeight * .05)) / (Helper.scale == 0 ? 1 : Helper.scale)); + //gridRowTop.Height = new GridLength(this.ActualHeight - Main.ActualHeight - (this.ActualHeight * .05));// / (Helper.scale == 0 ? 1 : Helper.scale)); + gridRowTop.Height = new GridLength(this.ActualHeight - Main.ActualHeight - 100); } + //if (splitterPosition.Y > ((this.ActualHeight - 160) / Helper.scale)) + //{ + // e.Handled = true; // Bewegung stoppen 160: MenuRow Height + // gridRowTop.Height = new GridLength((this.ActualHeight - 160 - 160) / (Helper.scale == 0 ? 1 : Helper.scale)); + //} Settings.WriteSetting("SplitterPos", gridRowTop.Height.Value); } - private void Window_SizeChanged(object sender, SizeChangedEventArgs e) { @@ -3053,6 +3095,24 @@ namespace ZKuP lAb.WindowStartupLocation = WindowStartupLocation.CenterScreen; lAb.ShowDialog(); } + + + + private void btnTableExport_Click(object sender, RoutedEventArgs e) + { + FileDialog file = new SaveFileDialog(); + file.DefaultExt = "*.csv"; + file.Filter = "CSV Datei | *.csv"; + file.ShowDialog(); + + if (!string.IsNullOrWhiteSpace(file.FileName)) + TableExporter.ExportToCsv(file.FileName, new DataGrid[] { dgToday, dgTodayBesucher }); + } + + private void btnRefresh_Click(object sender, RoutedEventArgs e) + { + getToday(); + } } diff --git a/ZKuP/ManageAsp.xaml b/ZKuP/ManageAsp.xaml index 6a9db77..e532d5d 100644 --- a/ZKuP/ManageAsp.xaml +++ b/ZKuP/ManageAsp.xaml @@ -7,8 +7,72 @@ xmlns:local="clr-namespace:ZKuP" mc:Ignorable="d" Title="Ansprechpartner verwalten" Height="450" Width="1180" - WindowStartupLocation="CenterScreen" MinHeight="450" MinWidth="1180"> - + WindowStartupLocation="CenterScreen" MinHeight="450" MinWidth="1180" ClipToBounds="False"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -42,13 +106,56 @@ - + - + + + + + + + + + + + + + + + + + diff --git a/ZKuP/ManageAsp.xaml.cs b/ZKuP/ManageAsp.xaml.cs index 06790c3..62e2e00 100644 --- a/ZKuP/ManageAsp.xaml.cs +++ b/ZKuP/ManageAsp.xaml.cs @@ -13,6 +13,7 @@ using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Shapes; @@ -35,7 +36,7 @@ namespace ZKuP DataTable asp = new DataTable("Asp"); string UserID = "-1"; - public ManageAsp() + public ManageAsp(List Columns = null) { this.DataContext = this; @@ -46,8 +47,17 @@ namespace ZKuP if (UserID == "1" && Environment.UserName.ToLower() != "marcusbachler") Log.WriteLog("UserID Fail"); Query(); + + if (Columns != null) + { + foreach (var col in Columns) + { + CreateBlinkStoryboard(col).Begin(); + } + } } + private void Query() { if (RoleManager.LoggedInRole == Roles.Admin) @@ -240,6 +250,46 @@ namespace ZKuP { Helper.CheckWindowIsInScreenSpace(this); } - } + + + private Storyboard CreateBlinkStoryboard(string target) + { + var storyboard = new Storyboard + { + RepeatBehavior = RepeatBehavior.Forever + }; + + var animation = new DoubleAnimationUsingKeyFrames(); + + var element = (FrameworkElement)this.FindName("arrow" + target); + + if (element == null) return null; + + element.Visibility = Visibility.Visible; + Storyboard.SetTarget(animation, element); + Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty)); + + animation.KeyFrames.Add(new EasingDoubleKeyFrame + { + KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0)), + Value = 1 + }); + + animation.KeyFrames.Add(new EasingDoubleKeyFrame + { + KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5)), + Value = 0 + }); + + animation.KeyFrames.Add(new EasingDoubleKeyFrame + { + KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)), + Value = 1 + }); + + storyboard.Children.Add(animation); + return storyboard; + } + } } diff --git a/ZKuP/Resources/Refresh.png b/ZKuP/Resources/Refresh.png new file mode 100644 index 0000000..7115a5d Binary files /dev/null and b/ZKuP/Resources/Refresh.png differ diff --git a/ZKuP/Resources/TableExport.png b/ZKuP/Resources/TableExport.png new file mode 100644 index 0000000..705671c Binary files /dev/null and b/ZKuP/Resources/TableExport.png differ diff --git a/ZKuP/Resources/arrow.png b/ZKuP/Resources/arrow.png new file mode 100644 index 0000000..151a2d6 Binary files /dev/null and b/ZKuP/Resources/arrow.png differ diff --git a/ZKuP/RoleManager.cs b/ZKuP/RoleManager.cs index a2dc42a..aad77f9 100644 --- a/ZKuP/RoleManager.cs +++ b/ZKuP/RoleManager.cs @@ -392,6 +392,11 @@ namespace ZKuP main.BE.Visibility = Visibility.Visible; main.BesuchP.Visibility = Visibility.Visible; + + main.btnRefresh.Visibility = Visibility.Visible; + main.btnTableExport.Visibility = Visibility.Visible; + + main.tcMainMenu.SelectedIndex = 2; } diff --git a/ZKuP/TableExporter.cs b/ZKuP/TableExporter.cs new file mode 100644 index 0000000..18a98f0 --- /dev/null +++ b/ZKuP/TableExporter.cs @@ -0,0 +1,146 @@ +using Microsoft.Win32; +using System; +using System.Collections; +using System.Data; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Media; + +namespace ZKuP +{ + public static class TableExporter + { + public static void ExportToCsv(string filePath, params DataGrid[] grids) + { + var sb = new StringBuilder(); + + foreach (var dg in grids) + { + var table = TryGetDataTable(dg); + + // sichtbare Spalten + var cols = dg.Columns + .Where(c => c.Visibility == Visibility.Visible) + .ToList(); + + // Header + sb.AppendLine(string.Join(";", cols.Select(c => Escape(GetHeader(c))))); + + if (table != null) + { + // --- CSV aus DataTable (immer vollständig, unabhängig von Virtualisierung) --- + foreach (DataRow row in table.Rows) + { + var vals = cols.Select(col => + { + var name = GetBindingPath(col); + if (name != null && table.Columns.Contains(name)) + return Escape(Convert.ToString(row[name])); + return ""; + }); + + sb.AppendLine(string.Join(";", vals)); + } + } + else + { + // --- Fallback: Items → Reflection über BindingPath --- + foreach (var item in GetAllItems(dg)) + { + var vals = cols.Select(col => + { + var path = GetBindingPath(col); + if (path == null) return ""; + var val = GetPropertyValue(item, path); + return Escape(val?.ToString() ?? ""); + }); + + sb.AppendLine(string.Join(";", vals)); + } + } + + sb.AppendLine(); + } + + File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8); + } + + // ---------------- Hilfsfunktionen ---------------- + + private static DataTable TryGetDataTable(DataGrid dg) + { + if (dg.ItemsSource is DataView dv) return dv.Table; + if (dg.ItemsSource is DataTable dt) return dt; + + if (dg.ItemsSource is IEnumerable ie) + { + var first = ie.Cast().FirstOrDefault(); + if (first is DataRowView drv) return drv.DataView.Table; + } + + return null; + } + + private static IEnumerable GetAllItems(DataGrid dg) + { + if (dg.ItemsSource == null) + return dg.Items.Cast().Where(x => x != CollectionView.NewItemPlaceholder); + + if (dg.ItemsSource is System.ComponentModel.ICollectionView cv) + return cv.SourceCollection; + + return dg.ItemsSource as IEnumerable; + } + + private static string GetHeader(DataGridColumn col) + { + if (col.Header is string s) return s; + return col.Header?.ToString() ?? ""; + } + + private static string GetBindingPath(DataGridColumn col) + { + if (col is DataGridBoundColumn bc && bc.Binding is Binding b && b.Path != null) + return b.Path.Path; + + if (col is DataGridCheckBoxColumn cb && cb.Binding is Binding b2 && b2.Path != null) + return b2.Path.Path; + + return null; + } + + private static object GetPropertyValue(object obj, string path) + { + var parts = path.Split('.'); + object current = obj; + + foreach (var part in parts) + { + if (current == null) return null; + + var type = current.GetType(); + var prop = type.GetProperty(part, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); + if (prop == null) return null; + + current = prop.GetValue(current); + } + + return current; + } + + private static string Escape(string s) + { + if (s == null) return ""; + if (s.Contains(";") || s.Contains("\"")) + return "\"" + s.Replace("\"", "\"\"") + "\""; + return s; + } + } +} \ No newline at end of file diff --git a/ZKuP/ZKuP.csproj b/ZKuP/ZKuP.csproj index cb0c6b5..59c5bf1 100644 --- a/ZKuP/ZKuP.csproj +++ b/ZKuP/ZKuP.csproj @@ -336,6 +336,7 @@ + ucSpinnerPiston.xaml @@ -898,5 +899,14 @@ + + + + + + + + + \ No newline at end of file