diff --git a/ENI2/Controls/ClosableTabItem.cs b/ENI2/Controls/ClosableTabItem.cs index 07a332ca..93a6cd34 100644 --- a/ENI2/Controls/ClosableTabItem.cs +++ b/ENI2/Controls/ClosableTabItem.cs @@ -8,6 +8,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; +using System.Windows.Threading; namespace ENI2.Controls { @@ -161,8 +162,9 @@ namespace ENI2.Controls } if (!abort) { - var tabControl = Parent as ItemsControl; - tabControl.Items.Remove(this); + var tabControl = Parent as TabControl; + tabControl.SelectedItem = null; + _ = Dispatcher.BeginInvoke(new Action(() => tabControl.Items.Remove(this)), DispatcherPriority.Background); } }; dockPanel.Children.Add(closeButton); diff --git a/ENI2/DetailBaseControl.cs b/ENI2/DetailBaseControl.cs index 88b5c7dc..c3641a15 100644 --- a/ENI2/DetailBaseControl.cs +++ b/ENI2/DetailBaseControl.cs @@ -70,7 +70,7 @@ namespace ENI2 /// /// Damit kann ein Listenelement eine Validierung der gesamten Anmeldung auslösen (inkl. Highlighting) (auf Knopfdruck) /// - public event Action RequestValidate; + public event Action RequestValidate; /// /// Alle Meldeklassen die auf "zu versenden" stehen werden validiert und falls die Validierung scheitert auf "SUSPEND" gestellt @@ -160,9 +160,9 @@ namespace ENI2 this.RequestReload?.Invoke(coreId); } - protected virtual void OnRequestValidate() + protected virtual void OnRequestValidate(bool showDialog) { - this.RequestValidate?.Invoke(); + this.RequestValidate?.Invoke(showDialog); } protected virtual void OnRequestSendValidation() diff --git a/ENI2/DetailRootControl.xaml b/ENI2/DetailRootControl.xaml index d5e5dffe..8de72598 100644 --- a/ENI2/DetailRootControl.xaml +++ b/ENI2/DetailRootControl.xaml @@ -15,7 +15,7 @@ - + diff --git a/ENI2/DetailRootControl.xaml.cs b/ENI2/DetailRootControl.xaml.cs index 93c28cde..a108449e 100644 --- a/ENI2/DetailRootControl.xaml.cs +++ b/ENI2/DetailRootControl.xaml.cs @@ -189,6 +189,7 @@ namespace ENI2 this._listBoxList.Add(new MessageGroup() { MessageGroupName = Properties.Resources.text11DangerousCargoDeparture, MessageGroupControlType = typeof(DangerousCargoControl), ImagePath = "Resources/sign_warning_radiation.png" }); this._listBoxList.Add(new MessageGroup() { MessageGroupName = Properties.Resources.text12ATAATD, MessageGroupControlType = typeof(ATAControl), ImagePath = "Resources/clock.png" }); this._listBoxList.Add(new MessageGroup() { MessageGroupName = Properties.Resources.text13WasteReceipts, MessageGroupControlType = typeof(WasteReceiptsControl), ImagePath = "Resources/garbage.png" }); + this.leftColumnDefinition.Width = new GridLength(260); } this.listBoxMessages.ItemsSource = this._listBoxList; @@ -657,7 +658,7 @@ namespace ENI2 private void ShortCutValidate(object sender, ExecutedRoutedEventArgs e) { - this.DetailControl_RequestValidate(); + this.DetailControl_RequestValidate(true); } private void DetailControl_RequestReload(Guid id) @@ -770,9 +771,9 @@ namespace ENI2 } } - private void DetailControl_RequestValidate() + private void DetailControl_RequestValidate(bool showDialog) { - this.Validate(true, out _, out _); + this.Validate(showDialog, out _, out _); } private void Validate(bool showMessages, out List vViolations, out List vErrors) @@ -793,6 +794,15 @@ namespace ENI2 List violations = new List(); ruleEngine.ValidateMessage(aMessage, out errors, out violations); + if (errors.Count > 0) + aMessage.ErrorCount = errors.Count; + else + aMessage.ErrorCount = null; + if (violations.Count > 0) + aMessage.ViolationCount = violations.Count; + else + aMessage.ViolationCount = null; + string messageGroup = this.MessageGroupForMessage(aMessage); if (messageGroup != null) @@ -1266,7 +1276,7 @@ namespace ENI2 this._violationListDialog.BringUp(); } _violationListDialog.Violations = vViolations; - } + } if((vErrors.Count == 0) && (vViolations.Count == 0)) { @@ -1278,7 +1288,7 @@ namespace ENI2 private void _errorListDialog_RefreshClicked() { - DetailControl_RequestValidate(); + DetailControl_RequestValidate(true); } private void _errorListDialog_ErrorSelected(DatabaseEntity obj) diff --git a/ENI2/DetailViewControls/OverViewDetailControl.xaml b/ENI2/DetailViewControls/OverViewDetailControl.xaml index 931a9414..9df80aea 100644 --- a/ENI2/DetailViewControls/OverViewDetailControl.xaml +++ b/ENI2/DetailViewControls/OverViewDetailControl.xaml @@ -11,7 +11,7 @@ xmlns:data="clr-namespace:bsmd.database;assembly=bsmd.database" xmlns:local="clr-namespace:ENI2.DetailViewControls" mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="800"> + d:DesignHeight="768" d:DesignWidth="1024"> + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -222,29 +381,29 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -257,6 +416,7 @@ + @@ -269,41 +429,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + diff --git a/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs b/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs index e1d4ca77..25ddadc5 100644 --- a/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs +++ b/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs @@ -22,6 +22,7 @@ using System.Diagnostics; using System.ComponentModel; using static bsmd.database.Message; using PdfSharp.Fonts; +using System.Linq; namespace ENI2.DetailViewControls { @@ -30,6 +31,9 @@ namespace ENI2.DetailViewControls /// public partial class OverViewDetailControl : DetailBaseControl { + + #region Fields + private Message _message = null; private Message _ataMessage; private Message _atdMessage; @@ -39,12 +43,20 @@ namespace ENI2.DetailViewControls private readonly object _collectionLock = new object(); // private MessageSendStatusDialog mssd = null; + #endregion + + #region Construction + public OverViewDetailControl() { InitializeComponent(); this.Loaded += OverViewDetailControl_Loaded; } + #endregion + + #region Initialize + private void OverViewDetailControl_Loaded(object sender, RoutedEventArgs e) { // die Controls nach Änderungen monitoren @@ -53,7 +65,7 @@ namespace ENI2.DetailViewControls this.textBoxDisplayId.TextChanged += CoreTextBox_TextChanged; this.textBoxIMO.TextChanged += CoreTextBox_TextChanged; this.textBoxENI.TextChanged += CoreTextBox_TextChanged; - this.locodePoC.PropertyChanged += CoreLocode_LocodeChanged; + this.locodePoC.PropertyChanged += CoreLocode_LocodeChanged; this.RegisterDateTimePickerChange(this.dateTimePickerATA, Message.NotificationClass.ATA); this.RegisterDateTimePickerChange(this.dateTimePickerATD, Message.NotificationClass.ATD); @@ -61,18 +73,6 @@ namespace ENI2.DetailViewControls this.RegisterDateTimePickerChange(this.dateTimePickerETD, Message.NotificationClass.NOA_NOD); } - private void CoreLocode_LocodeChanged(object sender, PropertyChangedEventArgs e) - { - this.OnNotificationClassChanged(null); - } - - private void CoreTextBox_TextChanged(object sender, TextChangedEventArgs e) - { - this.OnNotificationClassChanged(null); - } - - #region Initialize - public override void Initialize() { bool iAmAdmin = DBManager.Instance.GetReportingPartyDict()[App.UserId.Value].IsAdmin; @@ -317,7 +317,9 @@ namespace ENI2.DetailViewControls BindingOperations.EnableCollectionSynchronization(this.Messages, _collectionLock); this.dataGridMessages.ItemsSource = this.Messages; - + + this.OnRequestValidate(false); + base.Initialize(); // wenn Meldeklassen erst bei der Init. erzeugt werden, fehlen die Handler, die hier erneut festgelegt werden this._initialized = true; } @@ -432,44 +434,50 @@ namespace ENI2.DetailViewControls MessageBoxResult result = MessageBox.Show(Properties.Resources.textConfirmSend, Properties.Resources.textConfirm, MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { - bool somethingsNotSaved = false; - foreach (Message selectedMessage in this.dataGridMessages.SelectedItems) + this.SendMessages(this.dataGridMessages.SelectedItems.Cast()); + } + } + + private void SendMessages(IEnumerable messages) + { + bool somethingsNotSaved = false; + + foreach (Message selectedMessage in messages) + { + if (selectedMessage.IsDirty) somethingsNotSaved = true; + } + + if (somethingsNotSaved) + { + if (MessageBox.Show(Properties.Resources.textUnsavedChangesSendAnyWay, Properties.Resources.textConfirmation, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No) + return; + } + + List watchList = new List(); + foreach (Message selectedMessage in messages) + { + if (selectedMessage.Reset) selectedMessage.Reset = false; // "nochmal" Versenden ist möglich + selectedMessage.InternalStatus = Message.BSMDStatus.TOSEND; + string userName = "?"; + if (App.UserId.HasValue && DBManager.Instance.GetReportingPartyDict().ContainsKey(App.UserId.Value)) { - if (selectedMessage.IsDirty) somethingsNotSaved = true; + userName = DBManager.Instance.GetReportingPartyDict()[App.UserId.Value].Logon; } + selectedMessage.ChangedBy = string.Format("{0} at {1} (Send)", userName, DateTime.Now); + selectedMessage.StatusInfo = string.Format(Properties.Resources.textMessageSentAt, DateTime.Now); + DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(selectedMessage); + watchList.Add(selectedMessage); + } - if(somethingsNotSaved) - { - if (MessageBox.Show(Properties.Resources.textUnsavedChangesSendAnyWay, Properties.Resources.textConfirmation, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No) - return; - } + // komplette Anmeldung auf "zu versenden" stellen + this.Core.BSMDStatusInternal = MessageCore.BSMDStatus.TOSEND; + this.Core.DefaultReportingPartyId = App.UserId; - List watchList = new List(); - foreach (Message selectedMessage in this.dataGridMessages.SelectedItems) - { - if (selectedMessage.Reset) selectedMessage.Reset = false; // "nochmal" Versenden ist möglich - selectedMessage.InternalStatus = Message.BSMDStatus.TOSEND; - string userName = "?"; - if (App.UserId.HasValue && DBManager.Instance.GetReportingPartyDict().ContainsKey(App.UserId.Value)) - { - userName = DBManager.Instance.GetReportingPartyDict()[App.UserId.Value].Logon; - } - selectedMessage.ChangedBy = string.Format("{0} at {1} (Send)", userName, DateTime.Now); - selectedMessage.StatusInfo = string.Format(Properties.Resources.textMessageSentAt, DateTime.Now); - DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(selectedMessage); - watchList.Add(selectedMessage); - } + DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(this.Core); // löst auch den Watchdog aus + this.OnRequestSendValidation(); + this.dataGridMessages.Items.Refresh(); - // komplette Anmeldung auf "zu versenden" stellen - this.Core.BSMDStatusInternal = MessageCore.BSMDStatus.TOSEND; - this.Core.DefaultReportingPartyId = App.UserId; - - DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(this.Core); // löst auch den Watchdog aus - this.OnRequestSendValidation(); - this.dataGridMessages.Items.Refresh(); - - - /* + /* if (this.mssd == null) { this.mssd = new MessageSendStatusDialog(this.Core); @@ -489,7 +497,6 @@ namespace ENI2.DetailViewControls this.mssd.Activate(); // bring to foreground this.mssd.AddMessages(watchList); */ - } } private void contextResetMessage(object sender, RoutedEventArgs e) @@ -623,6 +630,16 @@ namespace ENI2.DetailViewControls #region event handler + private void CoreLocode_LocodeChanged(object sender, PropertyChangedEventArgs e) + { + this.OnNotificationClassChanged(null); + } + + private void CoreTextBox_TextChanged(object sender, TextChangedEventArgs e) + { + this.OnNotificationClassChanged(null); + } + private void _checkStatusTimer_Elapsed(object sender, ElapsedEventArgs e) { bool? statusFlag = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoreQueryStatusFlag(this.Core.Id.Value); @@ -731,7 +748,7 @@ namespace ENI2.DetailViewControls private void buttonValidate_Click(object sender, RoutedEventArgs e) { - this.OnRequestValidate(); + this.OnRequestValidate(true); } /// @@ -761,7 +778,7 @@ namespace ENI2.DetailViewControls this.OnRequestReload(this.Core.Id.Value); // validate all selected import classes (Finger with "selection") - this.OnRequestValidate(); + this.OnRequestValidate(true); } else @@ -815,7 +832,56 @@ namespace ENI2.DetailViewControls } } - #endregion - + private void buttonSendAll_Click(object sender, RoutedEventArgs e) + { + SelectImportClassesDialog sicd = new SelectImportClassesDialog(); + List readyToSendMessages = new List(); + + foreach (Message message in this.Messages) + { + // Evaluate a number of criteria for messages that should not be preselected for sending + if (((message.ViolationCount ?? 0) > 0) || ((message.ErrorCount ?? 0) > 0)) continue; // these need more work + if (Message.IsListClass(message.MessageNotificationClass) && (message.Elements.Count == 0)) continue; // avoid suspend on empty list classes + if ((message.MessageNotificationClass == Message.NotificationClass.HAZA) && !XtraSendLogic.ShouldSendMessage(message)) continue; + if ((message.MessageNotificationClass == Message.NotificationClass.HAZD) && !XtraSendLogic.ShouldSendMessage(message)) continue; + if (message.MessageNotificationClass == Message.NotificationClass.BPOL) + { + if (message.Elements.Count > 0) + { + if (message.Elements[0] is BPOL bpol) + { + if (bpol.PortOfItineraries.Count == 0) continue; + } + } + } + readyToSendMessages.Add(message.MessageNotificationClass); + } + + sicd.Messages = this.Messages; + sicd.PreselectedClasses.AddRange(readyToSendMessages); + sicd.IsTransit = this.Core.IsTransit; + sicd.IsImportMode = false; + + if ((sicd.ShowDialog() ?? false) && (sicd.SelectedClasses.Count > 0)) + { + // now send all selected messages + List toSendMessages = new List(); + foreach(NotificationClass notificationClass in sicd.SelectedClasses) + { + Message selectedMessage = this.Messages.Find(x => x.MessageNotificationClass == notificationClass); + if (selectedMessage != null) + { + toSendMessages.Add(selectedMessage); + } + } + if (toSendMessages.Count > 0) + { + this.SendMessages(toSendMessages); + } + } + } + + #endregion + } } diff --git a/ENI2/DetailViewControls/PortCallDetailControl.xaml b/ENI2/DetailViewControls/PortCallDetailControl.xaml index 75e598c0..4758f600 100644 --- a/ENI2/DetailViewControls/PortCallDetailControl.xaml +++ b/ENI2/DetailViewControls/PortCallDetailControl.xaml @@ -12,7 +12,7 @@ mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="800"> - + @@ -92,8 +92,9 @@ - + + @@ -148,18 +147,23 @@ - - + + - - - + @@ -312,7 +317,7 @@ - + @@ -338,7 +343,7 @@ -