Merge branch 'release/1.2.0'
This commit is contained in:
commit
35765b97b1
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@ -15,9 +15,9 @@
|
||||
"SECRET_KEY" : "zdiTz8P3jXOc7jztIQAoelK4zztyuCpJ" // https://randomkeygen.com/
|
||||
},
|
||||
"args": [
|
||||
"run" //,
|
||||
// "--no-debugger",
|
||||
//"--no-reload"
|
||||
"run",
|
||||
// "--no-debugger",
|
||||
"--no-reload"
|
||||
],
|
||||
"jinja": true,
|
||||
"justMyCode": true
|
||||
|
||||
5891
misc/BreCalApi.cs
5891
misc/BreCalApi.cs
File diff suppressed because it is too large
Load Diff
1824
misc/BreCalApi.yaml
1824
misc/BreCalApi.yaml
File diff suppressed because it is too large
Load Diff
31
misc/delete_data.sql
Normal file
31
misc/delete_data.sql
Normal file
@ -0,0 +1,31 @@
|
||||
CREATE DEFINER=`ds`@`localhost` PROCEDURE `delete_data`()
|
||||
BEGIN
|
||||
DECLARE shipcall_id_var int;
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
|
||||
DECLARE shipcall_iter CURSOR FOR
|
||||
SELECT shipcall.id FROM shipcall
|
||||
LEFT JOIN times ON
|
||||
times.shipcall_id = shipcall.id AND times.participant_type = 8
|
||||
WHERE
|
||||
-- ARRIVAL
|
||||
(type = 1 AND GREATEST(shipcall.eta, COALESCE(times.eta_berth, 0)) <= CURRENT_DATE() - INTERVAL 1 MONTH) OR
|
||||
-- DEPARTURE / SHIFTING
|
||||
(type != 1 AND GREATEST(shipcall.etd, COALESCE(times.etd_berth, 0)) <= CURRENT_DATE() - INTERVAL 1 MONTH);
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN shipcall_iter;
|
||||
|
||||
delete_loop: LOOP
|
||||
FETCH shipcall_iter INTO shipcall_id_var;
|
||||
IF done THEN
|
||||
LEAVE delete_loop;
|
||||
END IF;
|
||||
DELETE FROM shipcall_participant_map WHERE shipcall_id = shipcall_id_var;
|
||||
DELETE FROM shipcall_tug_map WHERE shipcall_id = shipcall_id_var;
|
||||
DELETE FROM times WHERE shipcall_id = shipcall_id_var;
|
||||
DELETE FROM shipcall WHERE id = shipcall_id_var;
|
||||
END LOOP;
|
||||
CLOSE shipcall_iter;
|
||||
END
|
||||
95
misc/update_1.1_to_1.2.sql
Normal file
95
misc/update_1.1_to_1.2.sql
Normal file
@ -0,0 +1,95 @@
|
||||
-- add notification handling columns to shipcall
|
||||
-- evaluation_time: Time when the "traffic light" was last changed
|
||||
-- evaluation_notifications_sent: Flag to indicate if notifications were sent for the current evaluation
|
||||
|
||||
ALTER TABLE `bremen_calling_test`.`shipcall`
|
||||
ADD COLUMN `evaluation_time` DATETIME NULL DEFAULT NULL AFTER `evaluation_message`,
|
||||
ADD COLUMN `evaluation_notifications_sent` BIT NULL AFTER `evaluation_time`,
|
||||
ADD COLUMN `time_ref_point` INT NULL DEFAULT 0 COMMENT 'Index of a location which is the reference point for all time value entries, e.g. berth or Geeste' AFTER `modified`;
|
||||
|
||||
|
||||
-- prepare notification table for historic notification data
|
||||
-- removed reference to participant and times and dropped unnecessary columns
|
||||
-- added reference to shipcall
|
||||
|
||||
ALTER TABLE `bremen_calling_test`.`notification`
|
||||
DROP FOREIGN KEY `FK_NOT_TIMES`,
|
||||
DROP FOREIGN KEY `FK_NOT_PART`;
|
||||
ALTER TABLE `bremen_calling_test`.`notification`
|
||||
DROP COLUMN `deleted`,
|
||||
DROP COLUMN `acknowledged`,
|
||||
DROP COLUMN `participant_id`,
|
||||
DROP COLUMN `times_id`,
|
||||
ADD COLUMN `shipcall_id` INT UNSIGNED NULL AFTER `id`,
|
||||
ADD INDEX `FK_NOTIFICATION_SHIPCALL_idx` (`shipcall_id` ASC) VISIBLE,
|
||||
DROP INDEX `FK_NOT_PART` ,
|
||||
DROP INDEX `FK_NOT_TIMES` ;
|
||||
;
|
||||
ALTER TABLE `bremen_calling_test`.`notification`
|
||||
ADD CONSTRAINT `FK_NOTIFICATION_SHIPCALL`
|
||||
FOREIGN KEY (`shipcall_id`)
|
||||
REFERENCES `bremen_calling_test`.`shipcall` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION;
|
||||
|
||||
|
||||
-- added notification flags
|
||||
-- participant reference is now mandatory
|
||||
|
||||
ALTER TABLE `bremen_calling_test`.`user`
|
||||
DROP FOREIGN KEY `FK_USER_PART`;
|
||||
ALTER TABLE `bremen_calling_test`.`user`
|
||||
ADD COLUMN `notify_email` BIT NULL DEFAULT NULL AFTER `api_key`,
|
||||
ADD COLUMN `notify_whatsapp` BIT NULL DEFAULT NULL AFTER `notify_email`,
|
||||
ADD COLUMN `notify_signal` BIT NULL DEFAULT NULL AFTER `notify_whatsapp`,
|
||||
ADD COLUMN `notify_popup` BIT NULL DEFAULT NULL AFTER `notify_signal`,
|
||||
CHANGE COLUMN `participant_id` `participant_id` INT UNSIGNED NOT NULL ;
|
||||
ALTER TABLE `bremen_calling_test`.`user`
|
||||
ADD CONSTRAINT `FK_USER_PART`
|
||||
FOREIGN KEY (`participant_id`)
|
||||
REFERENCES `bremen_calling_test`.`participant` (`id`);
|
||||
|
||||
-- History table for change tracking
|
||||
|
||||
CREATE TABLE `bremen_calling_test`.`history` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`participant_id` INT UNSIGNED NOT NULL,
|
||||
`user_id` INT UNSIGNED NOT NULL,
|
||||
`shipcall_id` INT UNSIGNED NOT NULL,
|
||||
`timestamp` DATETIME NOT NULL COMMENT 'Time of saving',
|
||||
`eta` DATETIME NULL COMMENT 'Current ETA / ETD value (depends if shipcall or times were saved)',
|
||||
`type` INT NOT NULL COMMENT 'shipcall or times',
|
||||
`operation` INT NOT NULL COMMENT 'insert, update or delete',
|
||||
PRIMARY KEY (`id`))
|
||||
COMMENT = 'This table stores a history of changes made to shipcalls so that everyone can see who changed what and when';
|
||||
|
||||
-- and foreign keys
|
||||
|
||||
ALTER TABLE `bremen_calling_test`.`history`
|
||||
ADD INDEX `FK_HISTORY_PARTICIPANT_idx` (`participant_id` ASC) VISIBLE,
|
||||
ADD INDEX `FK_HISTORY_SHIPCALL_idx` (`shipcall_id` ASC) VISIBLE;
|
||||
;
|
||||
ALTER TABLE `bremen_calling_test`.`history`
|
||||
ADD CONSTRAINT `FK_HISTORY_PARTICIPANT`
|
||||
FOREIGN KEY (`participant_id`)
|
||||
REFERENCES `bremen_calling_test`.`participant` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
ADD CONSTRAINT `FK_HISTORY_SHIPCALL`
|
||||
FOREIGN KEY (`shipcall_id`)
|
||||
REFERENCES `bremen_calling_test`.`shipcall` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
ADD CONSTRAINT `FK_HISTORY_USER`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `bremen_calling_test`.`user` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION;
|
||||
|
||||
-- add additional fields to times
|
||||
|
||||
ALTER TABLE `bremen_calling_test`.`times`
|
||||
ADD COLUMN `ata` DATETIME NULL DEFAULT NULL COMMENT 'Relevant only for mooring, this field can be used to record actual ATA' AFTER `participant_type`,
|
||||
ADD COLUMN `atd` DATETIME NULL DEFAULT NULL COMMENT 'Relevant only for mooring, this field can be used to record actual ATD' AFTER `ata`,
|
||||
ADD COLUMN `eta_interval_end` DATETIME NULL DEFAULT NULL COMMENT 'If this value is set the times are given as interval instead of a single point in time. The start time value depends on the participant type.' AFTER `atd`,
|
||||
ADD COLUMN `etd_interval_end` DATETIME NULL DEFAULT NULL COMMENT 'If this value is set the times are given as interval instead of a single point in time. The start time value depends on the participant type.' AFTER `eta_interval_end`;
|
||||
@ -1 +1 @@
|
||||
1.1.6.0
|
||||
1.2.0.0
|
||||
@ -25,7 +25,7 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
@ -47,6 +47,24 @@
|
||||
<setting name="W1Top" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W2Left" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W2Top" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W3Left" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W3Top" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W4Left" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
<setting name="W4Top" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
</BreCalClient.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
@ -2,16 +2,19 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
StartupUri="MainWindow.xaml" Exit="Application_Exit" Startup="Application_Startup" >
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
||||
|
||||
<ResourceDictionary Source="Resources\StringResources.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">10</sys:Double>
|
||||
<sys:Double x:Key="{x:Static SystemParameters.HorizontalScrollBarHeightKey}">10</sys:Double>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
<SignAssembly>True</SignAssembly>
|
||||
<StartupObject>BreCalClient.App</StartupObject>
|
||||
<AssemblyOriginatorKeyFile>..\..\misc\brecal.snk</AssemblyOriginatorKeyFile>
|
||||
<AssemblyVersion>1.1.6.0</AssemblyVersion>
|
||||
<FileVersion>1.1.6.0</FileVersion>
|
||||
<AssemblyVersion>1.2.0.10</AssemblyVersion>
|
||||
<FileVersion>1.2.0.0</FileVersion>
|
||||
<Title>Bremen calling client</Title>
|
||||
<Description>A Windows WPF client for the Bremen calling API.</Description>
|
||||
<ApplicationIcon>containership.ico</ApplicationIcon>
|
||||
@ -17,6 +17,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\add.png" />
|
||||
<None Remove="Resources\arrow_down_green.png" />
|
||||
<None Remove="Resources\arrow_down_red.png" />
|
||||
<None Remove="Resources\arrow_right_blue.png" />
|
||||
@ -31,8 +32,12 @@
|
||||
<None Remove="Resources\containership.png" />
|
||||
<None Remove="Resources\delete.png" />
|
||||
<None Remove="Resources\delete2.png" />
|
||||
<None Remove="Resources\edit.png" />
|
||||
<None Remove="Resources\emergency_stop_button.png" />
|
||||
<None Remove="Resources\lock.png" />
|
||||
<None Remove="Resources\lock_open.png" />
|
||||
<None Remove="Resources\logo_bremen_calling.png" />
|
||||
<None Remove="Resources\nav_refresh_green.png" />
|
||||
<None Remove="Resources\ship2.png" />
|
||||
<None Remove="Resources\sign_warning.png" />
|
||||
<None Remove="Resources\trafficlight_green.png" />
|
||||
@ -68,6 +73,7 @@
|
||||
<Generator>OpenApiCodeGenerator</Generator>
|
||||
<LastGenOutput>BreCalApi.cs</LastGenOutput>
|
||||
</None>
|
||||
<Resource Include="Resources\add.png" />
|
||||
<Resource Include="Resources\arrow_down_green.png" />
|
||||
<Resource Include="Resources\arrow_down_red.png" />
|
||||
<Resource Include="Resources\arrow_right_blue.png" />
|
||||
@ -82,8 +88,12 @@
|
||||
<Resource Include="Resources\containership.png" />
|
||||
<Resource Include="Resources\delete.png" />
|
||||
<Resource Include="Resources\delete2.png" />
|
||||
<Resource Include="Resources\edit.png" />
|
||||
<Resource Include="Resources\emergency_stop_button.png" />
|
||||
<Resource Include="Resources\lock.png" />
|
||||
<Resource Include="Resources\lock_open.png" />
|
||||
<Resource Include="Resources\logo_bremen_calling.png" />
|
||||
<Resource Include="Resources\nav_refresh_green.png" />
|
||||
<Resource Include="Resources\ship2.png" />
|
||||
<Resource Include="Resources\sign_warning.png" />
|
||||
<Resource Include="Resources\StringResources.de.xaml">
|
||||
@ -102,11 +112,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" />
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.6.0" />
|
||||
<PackageReference Include="JsonSubTypes" Version="2.0.1" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="log4net" Version="2.0.17" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Polly" Version="7.2.4" />
|
||||
<PackageReference Include="Polly" Version="8.3.1" />
|
||||
<PackageReference Include="RestSharp" Version="110.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
extensions: designer.cs generated.cs
|
||||
extensions: .cs .cpp .h
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Copyright (c) 2024- schick Informatik
|
||||
// Description:
|
||||
//
|
||||
|
||||
extensions: .aspx .ascx
|
||||
<%--
|
||||
Copyright (c) 2023 schick Informatik
|
||||
Copyright (c) 2024- schick Informatik
|
||||
--%>
|
||||
extensions: .vb
|
||||
'Sample license text.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Description: Static lists used everywhere
|
||||
//
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Model;
|
||||
using System.Collections.Concurrent;
|
||||
@ -30,6 +30,17 @@ namespace BreCalClient
|
||||
private readonly static ConcurrentDictionary<int, Berth> _berthLookupDict = new();
|
||||
private readonly static Dictionary<int, Participant> _participantLookupDict = new();
|
||||
|
||||
/// <summary>
|
||||
/// List of TimeRef points
|
||||
/// </summary>
|
||||
// TODO: To make this portable the list of texts should come from a configuration file
|
||||
private readonly static List<string> _timeRefs = new List<string>
|
||||
{
|
||||
"ETB",
|
||||
"Geeste",
|
||||
"TN-Weser"
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@ -90,6 +101,11 @@ namespace BreCalClient
|
||||
/// </summary>
|
||||
public static List<ShipModel> AllShips { get { return _allShips; } }
|
||||
|
||||
/// <summary>
|
||||
/// List of display values for TimeRef points
|
||||
/// </summary>
|
||||
public static List<string> TimeRefs { get { return _timeRefs; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region methods
|
||||
@ -101,7 +117,7 @@ namespace BreCalClient
|
||||
aList.Clear();
|
||||
mList.Clear();
|
||||
pList.Clear();
|
||||
tList.Clear();
|
||||
tList.Clear();
|
||||
terList.Clear();
|
||||
|
||||
foreach (Participant p in participants)
|
||||
@ -135,7 +151,7 @@ namespace BreCalClient
|
||||
if (!ship.Deleted)
|
||||
_ships.Add(sm);
|
||||
_allShips.Add(sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
257
src/BreCalClient/ENIDataGrid.cs
Normal file
257
src/BreCalClient/ENIDataGrid.cs
Normal file
@ -0,0 +1,257 @@
|
||||
// Copyright (c) 2017 schick Informatik
|
||||
// Description: DataGrid mit etwas "verbesserten" Funktionen
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
|
||||
///
|
||||
/// Step 1a) Using this custom control in a XAML file that exists in the current project.
|
||||
/// Add this XmlNamespace attribute to the root element of the markup file where it is
|
||||
/// to be used:
|
||||
///
|
||||
/// xmlns:enictrl="clr-namespace:ENI2.Controls"
|
||||
///
|
||||
///
|
||||
/// Step 1b) Using this custom control in a XAML file that exists in a different project.
|
||||
/// Add this XmlNamespace attribute to the root element of the markup file where it is
|
||||
/// to be used:
|
||||
///
|
||||
/// xmlns:enictrl="clr-namespace:ENI2.Controls;assembly=ENI2.Controls"
|
||||
///
|
||||
/// You will also need to add a project reference from the project where the XAML file lives
|
||||
/// to this project and Rebuild to avoid compilation errors:
|
||||
///
|
||||
/// Right click on the target project in the Solution Explorer and
|
||||
/// "Add Reference"->"Projects"->[Browse to and select this project]
|
||||
///
|
||||
///
|
||||
/// Step 2)
|
||||
/// Go ahead and use your control in the XAML file.
|
||||
///
|
||||
/// <MyNamespace:ENIDataGrid/>
|
||||
///
|
||||
/// </summary>
|
||||
public class ENIDataGrid : DataGrid
|
||||
{
|
||||
|
||||
public event Action<object>? EditRequested;
|
||||
public event Action<object>? DeleteRequested;
|
||||
public event Action? CreateRequested;
|
||||
public event Action? RefreshGrid;
|
||||
|
||||
public event Action<object>? PrintRequested;
|
||||
public event Action<object>? ExportRequested;
|
||||
public event Action<object>? ShowTextRequested;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
this.MouseDoubleClick += dataGrid_MouseDoubleClick;
|
||||
this.PreviewKeyDown += ENIDataGrid_PreviewKeyDown;
|
||||
|
||||
this.ContextMenu = new ContextMenu();
|
||||
this.CanUserAddRows = false;
|
||||
this.IsReadOnly = false;
|
||||
|
||||
MenuItem addItem = new MenuItem();
|
||||
|
||||
addItem.Header = BreCalClient.Resources.Resources.textAdd;
|
||||
addItem.Icon = new Image { Source = Util.LoadImage(BreCalClient.Resources.Resources.add) };
|
||||
addItem.Click += new RoutedEventHandler(this.addItem);
|
||||
this.ContextMenu.Items.Add(addItem);
|
||||
|
||||
MenuItem deleteItem = new MenuItem();
|
||||
deleteItem.Header = BreCalClient.Resources.Resources.textDelete;
|
||||
deleteItem.Icon = new Image { Source = Util.LoadImage(BreCalClient.Resources.Resources.delete) };
|
||||
deleteItem.Click += this.deleteItem;
|
||||
this.ContextMenu.Items.Add(deleteItem);
|
||||
|
||||
MenuItem editItem = new MenuItem();
|
||||
editItem.Header = BreCalClient.Resources.Resources.textEdit;
|
||||
editItem.Icon = new Image { Source = Util.LoadImage(BreCalClient.Resources.Resources.edit) };
|
||||
editItem.Click += this.editItem;
|
||||
this.ContextMenu.Items.Add(editItem);
|
||||
}
|
||||
|
||||
private void ENIDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if(sender is ENIDataGrid)
|
||||
{
|
||||
var grid = sender as ENIDataGrid;
|
||||
if (Key.Delete == e.Key)
|
||||
this.deleteItem(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
#region public
|
||||
|
||||
public DataGridRow GetRow(int index)
|
||||
{
|
||||
DataGridRow row = (DataGridRow)this.ItemContainerGenerator.ContainerFromIndex(index);
|
||||
if(row == null)
|
||||
{
|
||||
this.UpdateLayout();
|
||||
this.ScrollIntoView(this.Items[index]);
|
||||
row = (DataGridRow)this.ItemContainerGenerator.ContainerFromIndex(index);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public DataGridCell? GetCell(DataGridRow row, int column)
|
||||
{
|
||||
if (row != null)
|
||||
{
|
||||
DataGridCellsPresenter? presenter = GetVisualChild<DataGridCellsPresenter>(row);
|
||||
|
||||
if (presenter == null)
|
||||
{
|
||||
this.ScrollIntoView(row, this.Columns[column]);
|
||||
presenter = GetVisualChild<DataGridCellsPresenter>(row);
|
||||
}
|
||||
|
||||
DataGridCell? cell = (DataGridCell?)presenter?.ItemContainerGenerator.ContainerFromIndex(column);
|
||||
return cell;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public DataGridCell? GetCell(int rowIndex, int columnIndex)
|
||||
{
|
||||
DataGridRow row = this.GetRow(rowIndex);
|
||||
return this.GetCell(row, columnIndex);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region protected
|
||||
|
||||
protected void addItem(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!this.IsReadOnly)
|
||||
{
|
||||
this.CreateRequested?.Invoke();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
protected void deleteItem(object? sender, RoutedEventArgs? e)
|
||||
{
|
||||
if((this.SelectedItems != null) && (this.SelectedItems.Count > 0) && !this.IsReadOnly)
|
||||
{
|
||||
MessageBoxResult result = MessageBox.Show("Are your sure?", "Please confirm", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
List<object> deleteList = new List<object>();
|
||||
foreach (object deleteItem in this.SelectedItems)
|
||||
deleteList.Add(deleteItem);
|
||||
|
||||
foreach (object deleteItem in deleteList)
|
||||
{
|
||||
if (deleteItem != null)
|
||||
{
|
||||
this.DeleteRequested?.Invoke(deleteItem);
|
||||
}
|
||||
}
|
||||
|
||||
this.RefreshGrid?.Invoke();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void editItem(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if((this.SelectedItems != null) && (this.SelectedItems.Count == 1) && !this.IsReadOnly)
|
||||
{
|
||||
if (this.SelectedItems[0] is object selectedEntity)
|
||||
this.EditRequested?.Invoke(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
protected void printItem(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1) )
|
||||
{
|
||||
if (this.SelectedItems[0] is object selectedEntity)
|
||||
this.PrintRequested?.Invoke(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
protected void exportItem(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1))
|
||||
{
|
||||
if (this.SelectedItems[0] is object selectedEntity)
|
||||
this.ExportRequested?.Invoke(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
protected void showTextItem(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1))
|
||||
{
|
||||
if (this.SelectedItems[0] is object selectedEntity)
|
||||
this.ShowTextRequested?.Invoke(selectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private
|
||||
|
||||
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender != null)
|
||||
{
|
||||
if ((sender is DataGrid grid) && (grid.SelectedItems != null) && (grid.SelectedItems.Count == 1) && !this.IsReadOnly)
|
||||
{
|
||||
DataGridRow? dgr = grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem) as DataGridRow;
|
||||
if (grid.SelectedItem is object selectedEntity)
|
||||
this.EditRequested?.Invoke(selectedEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private static
|
||||
|
||||
private static T? GetVisualChild<T>(Visual parent) where T : Visual
|
||||
{
|
||||
T? child = default;
|
||||
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (int i = 0; i < numVisuals; i++)
|
||||
{
|
||||
Visual? v = (Visual)VisualTreeHelper.GetChild(parent, i);
|
||||
child = v as T;
|
||||
if (child == null)
|
||||
{
|
||||
child = GetVisualChild<T>(v);
|
||||
}
|
||||
if (child != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
54
src/BreCalClient/EditShipDialog.xaml
Normal file
54
src/BreCalClient/EditShipDialog.xaml
Normal file
@ -0,0 +1,54 @@
|
||||
<Window x:Class="BreCalClient.EditShipDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d"
|
||||
Left="{local:SettingBinding W3Left}" Top="{local:SettingBinding W3Top}"
|
||||
Title="{x:Static p:Resources.textEditShip}" Height="250" Width="500" Loaded="Window_Loaded" ResizeMode="NoResize">
|
||||
<Grid x:Name="shipGrid">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".3*" />
|
||||
<ColumnDefinition Width=".6*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Content="Name" HorizontalAlignment="Right" />
|
||||
<TextBox x:Name="textBoxName" Grid.Column="1" Margin="2" VerticalContentAlignment="Center" Text="{Binding Name, Mode=OneWay}" TextChanged="textBoxName_TextChanged" MaxLength="64"/>
|
||||
<Label Content="{x:Static p:Resources.textTugCompany}" HorizontalAlignment="Right" Grid.Row="1" />
|
||||
<Grid Grid.Row="1" Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="28" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ComboBox x:Name="comboBoxParticipants" Margin="2" DisplayMemberPath="Name" />
|
||||
<Button x:Name="buttonResetParticipant" Grid.Column="1" Margin="2" Click="buttonResetParticipant_Click">
|
||||
<Image Source="./Resources/delete2.png"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Label Content="IMO" HorizontalAlignment="Right" Grid.Row="2" />
|
||||
<xctk:IntegerUpDown Name="integerUpDownIMO" Grid.Column="1" Grid.Row="2" Value="{Binding Imo, Mode=OneWay}" Margin="2" Minimum="1000000" Maximum="9999999" ShowButtonSpinner="False" ValueChanged="integerUpDownIMO_ValueChanged"/>
|
||||
<Label Content="{x:Static p:Resources.textCallsign}" HorizontalAlignment="Right" Grid.Row="3" />
|
||||
<TextBox x:Name="textBoxCallsign" Grid.Column="1" Grid.Row="3" Margin="2" VerticalContentAlignment="Center" Text="{Binding Callsign, Mode=OneWay}" MaxLength="8"/>
|
||||
<Label Content="{x:Static p:Resources.textLength}" HorizontalAlignment="Right" Grid.Row="4" />
|
||||
<xctk:DoubleUpDown Name="doubleUpDownLength" Grid.Row="4" Grid.Column="1" Value="{Binding Length, Mode=OneWay}" Margin="2" Minimum="0" />
|
||||
<Label Content="{x:Static p:Resources.textWidth}" HorizontalAlignment="Right" Grid.Row="5" />
|
||||
<xctk:DoubleUpDown Name="doubleUpDownWidth" Grid.Row="5" Grid.Column="1" Value="{Binding Width, Mode=OneWay}" Margin="2" Minimum="0"/>
|
||||
<StackPanel Grid.Column="1" Grid.Row="7" Orientation="Horizontal" FlowDirection="RightToLeft">
|
||||
<Button x:Name="buttonCancel" Width="80" Content="{x:Static p:Resources.textCancel}" Margin="2" Click="buttonCancel_Click" />
|
||||
<Button x:Name="buttonOK" Width="80" Content="OK" Margin="2" Click="buttonOK_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
87
src/BreCalClient/EditShipDialog.xaml.cs
Normal file
87
src/BreCalClient/EditShipDialog.xaml.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using BreCalClient.misc.Model;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for EditShipDialog.xaml
|
||||
/// </summary>
|
||||
public partial class EditShipDialog : Window
|
||||
{
|
||||
public EditShipDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public Ship Ship { get; set; } = new();
|
||||
|
||||
public List<Participant> Participants { get; } = new List<Participant>();
|
||||
|
||||
private void buttonCancel_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.DialogResult = false;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void buttonOK_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
this.Ship.Name = this.textBoxName.Text.ToUpper().Trim();
|
||||
|
||||
if (this.comboBoxParticipants.SelectedItem != null)
|
||||
{
|
||||
this.Ship.ParticipantId = ((Participant)this.comboBoxParticipants.SelectedItem).Id;
|
||||
this.Ship.IsTug = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Ship.IsTug = false;
|
||||
}
|
||||
this.Ship.Imo = this.integerUpDownIMO.Value;
|
||||
this.Ship.Callsign = this.textBoxCallsign.Text.ToUpper().Trim();
|
||||
this.Ship.Length = (float?) this.doubleUpDownLength.Value;
|
||||
this.Ship.Width = (float?) this.doubleUpDownWidth.Value;
|
||||
this.DialogResult = true;
|
||||
this.Close();
|
||||
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.DataContext = this.Ship;
|
||||
this.comboBoxParticipants.ItemsSource = this.Participants;
|
||||
|
||||
if(this.Ship.ParticipantId != null)
|
||||
{
|
||||
foreach(Participant p in this.Participants)
|
||||
{
|
||||
if(this.Ship.ParticipantId == p.Id)
|
||||
this.comboBoxParticipants.SelectedItem = p;
|
||||
}
|
||||
}
|
||||
this.EnableOK();
|
||||
}
|
||||
|
||||
private void buttonResetParticipant_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxParticipants.SelectedItem = null;
|
||||
}
|
||||
|
||||
private void textBoxName_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
|
||||
{
|
||||
this.EnableOK();
|
||||
}
|
||||
|
||||
private void integerUpDownIMO_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.EnableOK();
|
||||
}
|
||||
|
||||
private void EnableOK()
|
||||
{
|
||||
this.buttonOK.IsEnabled = (this.textBoxName.Text.Length > 2) && (this.integerUpDownIMO.Value.HasValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,13 +4,14 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:api="clr-namespace:BreCalClient.misc.Model"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="242" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="270" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
<Window.Resources>
|
||||
<local:BoolToIndexConverter x:Key="boolToIndexConverter" />
|
||||
<local:EnumToStringConverter x:Key="enumToStringConverter" />
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -27,26 +28,26 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textShip}" Grid.Column="0" Grid.Row="0" HorizontalContentAlignment="Right"/>
|
||||
<ComboBox x:Name="comboBoxShip" Margin="2" Grid.Column="1" Grid.Row="0" SelectionChanged="comboBoxShip_SelectionChanged" SelectedValuePath="Ship.Id" IsEditable="True" IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" />
|
||||
<Label Content="IMO" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right"/>
|
||||
<xctk:IntegerUpDown x:Name="integerUpDownIMO" IsReadOnly="True" Margin="2" Grid.Column="1" Grid.Row="1" ShowButtonSpinner="False"/>
|
||||
<xctk:IntegerUpDown x:Name="integerUpDownIMO" IsReadOnly="True" Margin="2" Grid.Column="1" Grid.Row="1" ShowButtonSpinner="False" IsEnabled="False"/>
|
||||
<Label Content="{x:Static p:Resources.textCallsign}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right"/>
|
||||
<TextBox x:Name="textBoxCallsign" IsReadOnly="True" Grid.Column="1" Grid.Row="2" Margin="2" />
|
||||
<TextBox x:Name="textBoxCallsign" IsReadOnly="True" Grid.Column="1" Grid.Row="2" Margin="2" IsEnabled="False"/>
|
||||
<Label Content="{x:Static p:Resources.textLength}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right"/>
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownLength" Margin="2" Grid.Column="1" Grid.Row="3" FormatString="N2" IsReadOnly="True" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownLength" Margin="2" Grid.Column="1" Grid.Row="3" FormatString="N2" IsReadOnly="True" IsEnabled="False" ShowButtonSpinner="False"/>
|
||||
<Label Content="{x:Static p:Resources.textWidth}" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right"/>
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownWidth" Margin="2" Grid.Column="1" Grid.Row="4" FormatString="N2" IsReadOnly="True" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownWidth" Margin="2" Grid.Column="1" Grid.Row="4" FormatString="N2" IsReadOnly="True" IsEnabled="False" ShowButtonSpinner="False"/>
|
||||
<Label Content="{x:Static p:Resources.textCancelled}" Grid.Column="0" Grid.Row="5" HorizontalContentAlignment="Right" />
|
||||
<CheckBox x:Name="checkBoxCancelled" Grid.Column="1" Grid.Row="5" Margin="2" VerticalContentAlignment="Center" />
|
||||
<Button x:Name="buttonEditShips" Grid.Column="1" Grid.Row="6" Margin="2" Content="{x:Static p:Resources.textEditShips}" Click="buttonEditShips_Click" Visibility="Hidden" />
|
||||
|
||||
<Label Content="{x:Static p:Resources.textType}" Grid.Column="2" Grid.Row="0" HorizontalContentAlignment="Right" />
|
||||
<Label Content="ETA" Grid.Column="2" Grid.Row="2" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="ETD" Grid.Column="2" Grid.Row="3" HorizontalContentAlignment="Right"/>
|
||||
|
||||
<ComboBox x:Name="comboBoxCategories" Grid.Column="3" Margin="2" Grid.Row="0" SelectionChanged="comboBoxCategories_SelectionChanged"/>
|
||||
|
||||
<ComboBox ItemsSource="{local:Enumerate {x:Type api:ShipcallType}}" Grid.Column="3" Margin="2" Grid.Row="0" SelectionChanged="comboBoxCategories_SelectionChanged" x:Name="comboBoxCategories" />
|
||||
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Grid.Column="2" Grid.Row="1" HorizontalContentAlignment="Right"/>
|
||||
<Grid Grid.Row="1" Grid.Column="3">
|
||||
@ -60,12 +61,18 @@
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="3" Grid.Row="2" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerETA_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="3" Grid.Row="3" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textAgency}" Grid.Column="2" Grid.Row="4" HorizontalContentAlignment="Right"/>
|
||||
<ComboBox Name="comboBoxAgency" Grid.Column="3" Grid.Row="4" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxAgency_SelectionChanged">
|
||||
<Label Content="Zeit Ref." Grid.Column="2" Grid.Row="2" HorizontalContentAlignment="Right" />
|
||||
|
||||
<Label Content="ETA" Grid.Column="2" Grid.Row="3" HorizontalContentAlignment="Right" Margin="0,2,0,26" Grid.RowSpan="2"/>
|
||||
<Label Content="ETD" Grid.Column="2" Grid.Row="4" HorizontalContentAlignment="Right"/>
|
||||
|
||||
<ComboBox x:Name="comboBoxTimeRef" Grid.Column="3" Margin="2" Grid.Row="2" />
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="3" Grid.Row="3" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerETA_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="3" Grid.Row="4" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textAgency}" Grid.Column="2" Grid.Row="5" HorizontalContentAlignment="Right"/>
|
||||
<ComboBox Name="comboBoxAgency" Grid.Column="3" Grid.Row="5" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxAgency_SelectionChanged">
|
||||
<ComboBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearAssignment}" Name="contextMenuItemClearAgency" Click="contextMenuItemClearAgency_Click" />
|
||||
@ -73,8 +80,8 @@
|
||||
</ComboBox.ContextMenu>
|
||||
</ComboBox>
|
||||
|
||||
<Label x:Name="labelBSMDGranted" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBSMDGranted}" Visibility="Hidden" FontWeight="DemiBold" />
|
||||
<StackPanel Grid.Row="6" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Label x:Name="labelBSMDGranted" Grid.Row="6" Grid.Column="3" Grid.ColumnSpan="1" Content="{x:Static p:Resources.textBSMDGranted}" Visibility="Hidden" FontWeight="DemiBold" />
|
||||
<StackPanel Grid.Row="7" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False" />
|
||||
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
// Description: Windows dialog to create / edit ship calls
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Api;
|
||||
using BreCalClient.misc.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using static BreCalClient.Extensions;
|
||||
@ -31,6 +33,14 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShipEditingEnabled
|
||||
{
|
||||
get { return this.buttonEditShips.Visibility == Visibility.Visible; }
|
||||
set { this.buttonEditShips.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public ShipApi? ShipApi { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handler
|
||||
@ -40,10 +50,20 @@ namespace BreCalClient
|
||||
this.comboBoxAgency.ItemsSource = BreCalLists.Participants_Agent;
|
||||
|
||||
this.comboBoxShip.ItemsSource = BreCalLists.Ships;
|
||||
this.comboBoxCategories.ItemsSource = Enum.GetValues(typeof(TypeEnum));
|
||||
Array types = Enum.GetValues(typeof(ShipcallType));
|
||||
List<ShipcallType> shipcallTypes = new();
|
||||
bool first = true;
|
||||
foreach(ShipcallType shipcallType in types)
|
||||
{
|
||||
if (!first) shipcallTypes.Add(shipcallType);
|
||||
else first = false;
|
||||
}
|
||||
|
||||
this.comboBoxArrivalBerth.ItemsSource = BreCalLists.Berths;
|
||||
this.comboBoxDepartureBerth.ItemsSource = BreCalLists.Berths;
|
||||
|
||||
this.comboBoxTimeRef.ItemsSource = BreCalLists.TimeRefs;
|
||||
|
||||
if (this.ShipcallModel.Shipcall == null) this.ShipcallModel.Shipcall = new();
|
||||
this.CopyToControls();
|
||||
|
||||
@ -71,14 +91,14 @@ namespace BreCalClient
|
||||
this.integerUpDownIMO.Value = ship?.Ship.Imo;
|
||||
this.textBoxCallsign.Text = ship?.Ship.Callsign;
|
||||
this.doubleUpDownLength.Value = ship?.Ship.Length;
|
||||
this.doubleUpDownWidth.Value = ship?.Ship.Width;
|
||||
this.doubleUpDownWidth.Value = ship?.Ship.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.integerUpDownIMO.Value = null;
|
||||
this.textBoxCallsign.Text = string.Empty;
|
||||
this.doubleUpDownLength.Value = null;
|
||||
this.doubleUpDownWidth.Value = null;
|
||||
this.doubleUpDownWidth.Value = null;
|
||||
}
|
||||
this.CheckForCompletion();
|
||||
}
|
||||
@ -91,32 +111,37 @@ namespace BreCalClient
|
||||
|
||||
private void comboBoxCategories_SelectionChanged(object? sender, SelectionChangedEventArgs? e)
|
||||
{
|
||||
TypeEnum? type = this.comboBoxCategories.SelectedItem as TypeEnum?;
|
||||
ShipcallType? type = GetShipcallTypeFromCombobox();
|
||||
if (type != null)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TypeEnum.Incoming:
|
||||
case ShipcallType.Arrival:
|
||||
this.datePickerETA.IsEnabled = true;
|
||||
this.datePickerETD.IsEnabled = false;
|
||||
this.datePickerETD.Value = null;
|
||||
this.comboBoxDepartureBerth.SelectedIndex = -1;
|
||||
this.comboBoxDepartureBerth.IsEnabled = false;
|
||||
this.comboBoxArrivalBerth.IsEnabled = true;
|
||||
this.comboBoxTimeRef.IsEnabled = true;
|
||||
break;
|
||||
case TypeEnum.Outgoing:
|
||||
case ShipcallType.Departure:
|
||||
this.datePickerETA.IsEnabled = false;
|
||||
this.datePickerETD.IsEnabled = true;
|
||||
this.datePickerETA.Value = null;
|
||||
this.comboBoxArrivalBerth.SelectedIndex = -1;
|
||||
this.comboBoxArrivalBerth.IsEnabled = false;
|
||||
this.comboBoxDepartureBerth.IsEnabled = true;
|
||||
this.comboBoxTimeRef.IsEnabled = false;
|
||||
this.comboBoxTimeRef.SelectedIndex = 0;
|
||||
break;
|
||||
case TypeEnum.Shifting:
|
||||
case ShipcallType.Shifting:
|
||||
this.datePickerETA.IsEnabled = true;
|
||||
this.datePickerETD.IsEnabled = true;
|
||||
this.comboBoxArrivalBerth.IsEnabled = true;
|
||||
this.comboBoxDepartureBerth.IsEnabled = true;
|
||||
this.comboBoxTimeRef.IsEnabled = false;
|
||||
this.comboBoxTimeRef.SelectedIndex = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -137,6 +162,12 @@ namespace BreCalClient
|
||||
|
||||
#region private methods
|
||||
|
||||
ShipcallType? GetShipcallTypeFromCombobox()
|
||||
{
|
||||
EnumToStringConverter enumToStringConverter = new();
|
||||
return (ShipcallType?)enumToStringConverter.ConvertBack(this.comboBoxCategories.SelectedItem, typeof(ShipcallType), new object(), System.Globalization.CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
void CheckForCompletion()
|
||||
{
|
||||
bool isEnabled = true;
|
||||
@ -150,18 +181,18 @@ namespace BreCalClient
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeEnum callType = (TypeEnum)comboBoxCategories.SelectedItem;
|
||||
ShipcallType callType = GetShipcallTypeFromCombobox() ?? ShipcallType.Undefined;
|
||||
switch (callType)
|
||||
{
|
||||
case TypeEnum.Outgoing:
|
||||
case ShipcallType.Departure:
|
||||
isEnabled &= this.comboBoxDepartureBerth.SelectedItem != null;
|
||||
isEnabled &= this.datePickerETD.Value.HasValue;
|
||||
break;
|
||||
case TypeEnum.Incoming:
|
||||
case ShipcallType.Arrival:
|
||||
isEnabled &= this.comboBoxArrivalBerth.SelectedItem != null;
|
||||
isEnabled &= this.datePickerETA.Value.HasValue;
|
||||
break;
|
||||
case TypeEnum.Shifting:
|
||||
case ShipcallType.Shifting:
|
||||
isEnabled &= ((this.comboBoxDepartureBerth.SelectedItem != null) && (this.comboBoxArrivalBerth.SelectedItem != null));
|
||||
isEnabled &= this.datePickerETD.Value.HasValue;
|
||||
isEnabled &= this.datePickerETA.Value.HasValue;
|
||||
@ -178,7 +209,7 @@ namespace BreCalClient
|
||||
{
|
||||
if (this.ShipcallModel.Shipcall != null)
|
||||
{
|
||||
this.ShipcallModel.Shipcall.Type = (int)this.comboBoxCategories.SelectedItem;
|
||||
this.ShipcallModel.Shipcall.Type = GetShipcallTypeFromCombobox() ?? ShipcallType.Undefined;
|
||||
this.ShipcallModel.Shipcall.Eta = this.datePickerETA.Value;
|
||||
this.ShipcallModel.Shipcall.Etd = this.datePickerETD.Value;
|
||||
|
||||
@ -186,7 +217,7 @@ namespace BreCalClient
|
||||
this.ShipcallModel.Ship = ((ShipModel)this.comboBoxShip.SelectedItem).Ship;
|
||||
this.ShipcallModel.Shipcall.Canceled = this.checkBoxCancelled.IsChecked;
|
||||
|
||||
if (this.ShipcallModel.Shipcall.Type != 3) // incoming, outgoing
|
||||
if (this.ShipcallModel.Shipcall.Type != ShipcallType.Shifting) // incoming, outgoing
|
||||
{
|
||||
this.ShipcallModel.Shipcall.ArrivalBerthId = (this.comboBoxArrivalBerth.SelectedItem != null) ? ((Berth)this.comboBoxArrivalBerth.SelectedItem).Id : null;
|
||||
this.ShipcallModel.Shipcall.DepartureBerthId = (this.comboBoxDepartureBerth.SelectedItem != null) ? ((Berth)this.comboBoxDepartureBerth.SelectedItem).Id : null;
|
||||
@ -204,6 +235,7 @@ namespace BreCalClient
|
||||
ParticipantAssignment pa = new()
|
||||
{
|
||||
ParticipantId = participant.Id,
|
||||
|
||||
Type = (int)Extensions.ParticipantType.AGENCY
|
||||
};
|
||||
this.ShipcallModel.AssignedParticipants[Extensions.ParticipantType.AGENCY] = pa;
|
||||
@ -245,6 +277,10 @@ namespace BreCalClient
|
||||
};
|
||||
this.ShipcallModel.AssignedParticipants[ParticipantType.BSMD] = pa;
|
||||
}
|
||||
|
||||
// set the time reference value (which point do all times refer to?)
|
||||
this.ShipcallModel.Shipcall.TimeRefPoint = this.comboBoxTimeRef.SelectedIndex;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,15 +289,22 @@ namespace BreCalClient
|
||||
if (this.ShipcallModel == null) return;
|
||||
if (this.ShipcallModel.Shipcall != null)
|
||||
{
|
||||
this.comboBoxCategories.SelectedItem = (TypeEnum)this.ShipcallModel.Shipcall.Type;
|
||||
this.comboBoxTimeRef.SelectedIndex = this.ShipcallModel.Shipcall.TimeRefPoint ?? 0;
|
||||
this.comboBoxCategories.SelectedItem = new EnumToStringConverter().Convert(this.ShipcallModel.Shipcall.Type, typeof(ShipcallType), new object(), System.Globalization.CultureInfo.CurrentCulture);
|
||||
if (this.ShipcallModel.Shipcall.Eta != DateTime.MinValue)
|
||||
this.datePickerETA.Value = this.ShipcallModel.Shipcall.Eta;
|
||||
// this.textBoxVoyage.Text = this.ShipcallModel.Shipcall.Voyage;
|
||||
this.datePickerETD.Value = this.ShipcallModel.Shipcall.Etd;
|
||||
this.comboBoxShip.SelectedValue = this.ShipcallModel.Shipcall.ShipId;
|
||||
if (BreCalLists.Ships.Find(x => x.Ship.Id == this.ShipcallModel.Shipcall.ShipId) != null)
|
||||
{
|
||||
this.comboBoxShip.SelectedValue = this.ShipcallModel.Shipcall.ShipId;
|
||||
} else
|
||||
{
|
||||
this.comboBoxShip.IsEnabled = false;
|
||||
}
|
||||
this.checkBoxCancelled.IsChecked = this.ShipcallModel.Shipcall.Canceled ?? false;
|
||||
|
||||
if (this.ShipcallModel.Shipcall.Type != 3) // incoming, outgoing
|
||||
if (this.ShipcallModel.Shipcall.Type != ShipcallType.Shifting) // incoming, outgoing
|
||||
{
|
||||
this.comboBoxArrivalBerth.SelectedValue = this.ShipcallModel.Shipcall.ArrivalBerthId;
|
||||
this.comboBoxDepartureBerth.SelectedValue = this.ShipcallModel.Shipcall.DepartureBerthId;
|
||||
@ -340,6 +383,20 @@ namespace BreCalClient
|
||||
private void comboBoxDepartureBerth_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
this.CheckForCompletion();
|
||||
}
|
||||
|
||||
private void buttonEditShips_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShipListDialog shipListDialog = new()
|
||||
{
|
||||
ShipApi = this.ShipApi
|
||||
};
|
||||
|
||||
shipListDialog.ShowDialog();
|
||||
|
||||
// reload combobox
|
||||
this.comboBoxShip.ItemsSource = null;
|
||||
this.comboBoxShip.ItemsSource = BreCalLists.Ships;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -8,16 +8,16 @@
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="403" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="403" Width="900" Loaded="Window_Loaded" ResizeMode="CanResizeWithGrip" Icon="Resources/containership.ico">
|
||||
<Window.Resources>
|
||||
<local:BoolToIndexConverter x:Key="boolToIndexConverter" />
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.2*"/>
|
||||
<ColumnDefinition Width=".3*" />
|
||||
<ColumnDefinition Width="0.18*"/>
|
||||
<ColumnDefinition Width=".4*" />
|
||||
<ColumnDefinition Width="0.15*"/>
|
||||
<ColumnDefinition Width=".35*" />
|
||||
<ColumnDefinition Width=".3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
@ -31,7 +31,7 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Grid.Column="0">
|
||||
@ -43,10 +43,17 @@
|
||||
<Image Margin="2" Grid.Column="1" Source="Resources/arrow_down_red.png" />
|
||||
</Grid>
|
||||
|
||||
<Label Content="ETA" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="1" Grid.Row="1" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
<Label Content="ETA" x:Name="labelETA" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<Grid Grid.Column="1" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="0" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETA_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA_End" Grid.Column="1" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETA_End_ValueChanged"/>
|
||||
</Grid>
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<ComboBox Name="comboBoxArrivalBerth" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id">
|
||||
<ComboBox Name="comboBoxArrivalBerth" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxArrivalBerth_SelectionChanged">
|
||||
|
||||
</ComboBox>
|
||||
<Label Content="{x:Static p:Resources.textPierside}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right" />
|
||||
@ -60,9 +67,9 @@
|
||||
</ComboBox.ContextMenu>
|
||||
</ComboBox>
|
||||
<Label Content="{x:Static p:Resources.textBerthRemarks}" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right" />
|
||||
<TextBox x:Name="textBoxBerthRemarks" Grid.Column="1" Grid.Row="4" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="6" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5"/>
|
||||
<TextBox x:Name="textBoxBerthRemarks" Grid.Column="1" Grid.Row="4" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512" TextWrapping="Wrap" SpellCheck.IsEnabled="True" AcceptsTab="False" ScrollViewer.VerticalScrollBarVisibility="Auto" />
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right" FontWeight="Bold" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="6" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5" ValueChanged="doubleUpDownDraft_ValueChanged"/>
|
||||
<Label Content="{x:Static p:Resources.textTidalWindow}" FontWeight="DemiBold" Grid.Column="0" Grid.Row="7" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textFrom}" Grid.Column="0" Grid.Row="8" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textTo}" Grid.Column="0" Grid.Row="9" HorizontalContentAlignment="Right"/>
|
||||
@ -120,7 +127,7 @@
|
||||
<CheckBox x:Name="checkBoxReplenishingTerminal" Grid.Column="2" Grid.Row="8" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
|
||||
<CheckBox x:Name="checkBoxReplenishingLock" Grid.Column="2" Grid.Row="9" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
|
||||
<Label Content="{x:Static p:Resources.textRemarks}" Grid.Row="10" Grid.Column="2" HorizontalAlignment="Right"/>
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="10" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="10" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512" TextWrapping="Wrap" SpellCheck.IsEnabled="True" AcceptsTab="False" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
|
||||
<StackPanel Grid.Row="14" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False" />
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
|
||||
using BreCalClient.misc.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using static BreCalClient.Extensions;
|
||||
|
||||
@ -14,8 +12,14 @@ namespace BreCalClient
|
||||
/// <summary>
|
||||
/// Interaction logic for EditTimesAgencyIncomingControl.xaml
|
||||
/// </summary>
|
||||
public partial class EditTimesAgencyIncomingControl : Window, IEditShipcallTimesControl
|
||||
public partial class EditTimesAgencyIncomingControl : Window, IEditTimesControl
|
||||
{
|
||||
#region Fields
|
||||
|
||||
bool _editing = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
public EditTimesAgencyIncomingControl()
|
||||
@ -29,9 +33,7 @@ namespace BreCalClient
|
||||
|
||||
public ShipcallControlModel ShipcallModel { get; set; } = new();
|
||||
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
public Extensions.TypeEnum CallType { get; set; }
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -59,10 +61,10 @@ namespace BreCalClient
|
||||
allowBSMD = p.IsFlagSet(ParticipantFlag.ALLOW_BSMD);
|
||||
}
|
||||
|
||||
bool enableControls = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
_editing = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
(App.Participant.IsTypeFlagSet(ParticipantType.BSMD) && allowBSMD);
|
||||
|
||||
this.EnableControls(enableControls);
|
||||
this.EnableControls();
|
||||
|
||||
}
|
||||
|
||||
@ -88,6 +90,7 @@ namespace BreCalClient
|
||||
if (this.ShipcallModel.Shipcall != null)
|
||||
{
|
||||
this.Times.EtaBerth = this.datePickerETA.Value;
|
||||
this.Times.EtaIntervalEnd = this.datePickerETA_End.Value;
|
||||
|
||||
if (this.comboBoxPierside.SelectedIndex >= 0)
|
||||
{
|
||||
@ -176,6 +179,8 @@ namespace BreCalClient
|
||||
if (this.ShipcallModel.Shipcall.Eta != DateTime.MinValue)
|
||||
this.datePickerETA.Value = this.ShipcallModel.Shipcall.Eta;
|
||||
}
|
||||
|
||||
this.datePickerETA_End.Value = this.Times.EtaIntervalEnd;
|
||||
|
||||
if (Times.BerthId.HasValue)
|
||||
this.comboBoxArrivalBerth.SelectedValue = Times.BerthId;
|
||||
@ -204,6 +209,8 @@ namespace BreCalClient
|
||||
this.checkBoxReplenishingLock.IsChecked = this.ShipcallModel.Shipcall.ReplenishingLock ?? false;
|
||||
this.checkBoxReplenishingTerminal.IsChecked = this.ShipcallModel.Shipcall.ReplenishingTerminal ?? false;
|
||||
|
||||
this.labelETA.Content = string.Format("ETA {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall.TimeRefPoint ?? 0]);
|
||||
|
||||
if(!string.IsNullOrEmpty(this.Times.Remarks))
|
||||
this.textBoxRemarks.Text = this.Times.Remarks;
|
||||
|
||||
@ -242,37 +249,55 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableControls(bool isEnabled)
|
||||
private void EnableControls()
|
||||
{
|
||||
this.datePickerETA.IsEnabled = isEnabled;
|
||||
this.comboBoxArrivalBerth.IsEnabled = isEnabled;
|
||||
this.comboBoxPierside.IsEnabled = isEnabled;
|
||||
this.textBoxBerthRemarks.IsEnabled = isEnabled;
|
||||
this.doubleUpDownDraft.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowTo.IsEnabled = isEnabled;
|
||||
this.checkBoxCanceled.IsEnabled = isEnabled;
|
||||
this.datePickerETA.IsEnabled = _editing;
|
||||
this.datePickerETA_End.IsEnabled = _editing;
|
||||
this.comboBoxArrivalBerth.IsEnabled = _editing;
|
||||
this.comboBoxPierside.IsEnabled = _editing;
|
||||
this.textBoxBerthRemarks.IsReadOnly = !_editing;
|
||||
this.doubleUpDownDraft.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowTo.IsEnabled = _editing;
|
||||
this.checkBoxCanceled.IsEnabled = _editing;
|
||||
|
||||
this.checkBoxAnchored.IsEnabled = isEnabled;
|
||||
this.checkBoxAnchored.IsEnabled = _editing;
|
||||
|
||||
this.comboBoxTug.IsEnabled = isEnabled;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = isEnabled;
|
||||
this.comboBoxTug.IsEnabled = _editing;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = _editing;
|
||||
|
||||
this.comboBoxPilot.IsEnabled = isEnabled;
|
||||
this.comboBoxMooring.IsEnabled = isEnabled;
|
||||
this.checkBoxMooredLock.IsEnabled = isEnabled;
|
||||
this.comboBoxTerminal.IsEnabled = isEnabled;
|
||||
this.checkBoxBunkering.IsEnabled = isEnabled;
|
||||
this.checkBoxReplenishingTerminal.IsEnabled = isEnabled;
|
||||
this.checkBoxReplenishingLock.IsEnabled = isEnabled;
|
||||
this.textBoxRemarks.IsEnabled = isEnabled;
|
||||
this.comboBoxPilot.IsEnabled = _editing;
|
||||
this.comboBoxMooring.IsEnabled = _editing;
|
||||
this.checkBoxMooredLock.IsEnabled = _editing;
|
||||
this.comboBoxTerminal.IsEnabled = _editing;
|
||||
this.checkBoxBunkering.IsEnabled = _editing;
|
||||
this.checkBoxReplenishingTerminal.IsEnabled = _editing;
|
||||
this.checkBoxReplenishingLock.IsEnabled = _editing;
|
||||
this.textBoxRemarks.IsReadOnly = !_editing;
|
||||
|
||||
this.buttonOK.IsEnabled = isEnabled;
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private bool RequiredFieldsSet()
|
||||
{
|
||||
bool areSet = this.datePickerETA.Value.HasValue &&
|
||||
this.doubleUpDownDraft.Value.HasValue &&
|
||||
this.comboBoxArrivalBerth.SelectedIndex >= 0;
|
||||
|
||||
if (areSet && this.datePickerETA_End.Value.HasValue)
|
||||
areSet &= (this.datePickerETA.Value < this.datePickerETA_End.Value);
|
||||
|
||||
return areSet;
|
||||
}
|
||||
|
||||
private void CheckOKButton()
|
||||
{
|
||||
this.buttonOK.IsEnabled = _editing && RequiredFieldsSet();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region context menu handlers
|
||||
#region event handlers
|
||||
|
||||
private void contextMenuItemArrivalBerth_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@ -307,6 +332,26 @@ namespace BreCalClient
|
||||
private void contextMenuItemClearPierside_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxPierside.SelectedIndex = -1;
|
||||
}
|
||||
|
||||
private void doubleUpDownDraft_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
private void datePickerETA_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
private void comboBoxArrivalBerth_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
private void datePickerETA_End_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -8,13 +8,13 @@
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="375" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="375" Width="900" Loaded="Window_Loaded" ResizeMode="CanResizeWithGrip" Icon="Resources/containership.ico">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.2*"/>
|
||||
<ColumnDefinition Width=".3*" />
|
||||
<ColumnDefinition Width="0.18*"/>
|
||||
<ColumnDefinition Width=".4*" />
|
||||
<ColumnDefinition Width="0.15*"/>
|
||||
<ColumnDefinition Width=".35*" />
|
||||
<ColumnDefinition Width=".3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
@ -28,6 +28,7 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Grid.Column="0">
|
||||
@ -39,11 +40,17 @@
|
||||
<Image Margin="2" Grid.Column="1" Source="Resources/arrow_up_blue.png" />
|
||||
</Grid>
|
||||
|
||||
<Label Content="ETD" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="1" Grid.Row="1" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
<Label Content="ETD" x:Name="labelETD" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<Grid Grid.Row="1" Grid.Column="1" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="0" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD_End" Grid.Column="1" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
</Grid>
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<ComboBox Name="comboBoxDepartureBerth" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id">
|
||||
</ComboBox>
|
||||
<ComboBox Name="comboBoxDepartureBerth" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxDepartureBerth_SelectionChanged" />
|
||||
<Label Content="{x:Static p:Resources.textPierside}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right" />
|
||||
<ComboBox x:Name="comboBoxPierside" Grid.Column="1" Grid.Row="3" Margin="2" >
|
||||
<ComboBoxItem Content="{x:Static p:Resources.textPort}" />
|
||||
@ -55,15 +62,15 @@
|
||||
</ComboBox.ContextMenu>
|
||||
</ComboBox>
|
||||
<Label Content="{x:Static p:Resources.textBerthRemarks}" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right" />
|
||||
<TextBox x:Name="textBoxBerthRemarks" Grid.Column="1" Grid.Row="4" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="6" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5"/>
|
||||
<TextBox x:Name="textBoxBerthRemarks" Grid.Column="1" Grid.Row="4" Margin="2" Grid.RowSpan="2" VerticalContentAlignment="Top" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="6" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5" ValueChanged="doubleUpDownDraft_ValueChanged"/>
|
||||
<Label Content="{x:Static p:Resources.textTidalWindow}" FontWeight="DemiBold" Grid.Column="0" Grid.Row="7" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textFrom}" Grid.Column="0" Grid.Row="8" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textTo}" Grid.Column="0" Grid.Row="9" HorizontalContentAlignment="Right"/>
|
||||
<xctk:DateTimePicker Name="datePickerTidalWindowFrom" Grid.Column="1" Grid.Row="8" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
<xctk:DateTimePicker Name="datePickerTidalWindowTo" Grid.Column="1" Grid.Row="9" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
<Label Content="{x:Static p:Resources.textCancelled}" Grid.Column="0" Grid.Row="10" HorizontalContentAlignment="Right" />
|
||||
<Label Content="{x:Static p:Resources.textCancelled}" Grid.Column="0" Grid.Row="10" HorizontalContentAlignment="Right" VerticalAlignment="Center" />
|
||||
<CheckBox x:Name="checkBoxCanceled" Grid.Column="1" Grid.Row="10" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,4,0" />
|
||||
|
||||
<Label Content="{x:Static p:Resources.textTugRequired}" Grid.Column="2" Grid.Row="1" HorizontalContentAlignment="Right"/>
|
||||
@ -109,9 +116,9 @@
|
||||
<Label Content="{x:Static p:Resources.textRainSensitiveCargo}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="7" HorizontalAlignment="Right" />
|
||||
<CheckBox x:Name="checkBoxRainsensitiveCargo" Grid.Column="3" Grid.Row="7" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,4,0" />
|
||||
<Label Content="{x:Static p:Resources.textRemarks}" Grid.Column="2" Grid.Row="8" HorizontalContentAlignment="Right" />
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="8" Margin="2" Grid.RowSpan="3" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="8" Margin="2" Grid.RowSpan="4" VerticalContentAlignment="Top" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
|
||||
<StackPanel Grid.Row="11" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<StackPanel Grid.Row="12" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False" />
|
||||
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
@ -12,9 +12,15 @@ namespace BreCalClient
|
||||
/// <summary>
|
||||
/// Interaction logic for EditTimesAgencyOutgoingControl.xaml
|
||||
/// </summary>
|
||||
public partial class EditTimesAgencyOutgoingControl : Window, IEditShipcallTimesControl
|
||||
public partial class EditTimesAgencyOutgoingControl : Window, IEditTimesControl
|
||||
{
|
||||
|
||||
#region Fields
|
||||
|
||||
bool _editing = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
public EditTimesAgencyOutgoingControl()
|
||||
@ -28,9 +34,7 @@ namespace BreCalClient
|
||||
|
||||
public ShipcallControlModel ShipcallModel { get; set; } = new();
|
||||
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
public Extensions.TypeEnum CallType { get; set; }
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -58,10 +62,10 @@ namespace BreCalClient
|
||||
allowBSMD = p.IsFlagSet(ParticipantFlag.ALLOW_BSMD);
|
||||
}
|
||||
|
||||
bool enableControls = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
_editing = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
(App.Participant.IsTypeFlagSet(ParticipantType.BSMD) && allowBSMD);
|
||||
|
||||
this.EnableControls(enableControls);
|
||||
this.EnableControls();
|
||||
|
||||
}
|
||||
|
||||
@ -86,7 +90,9 @@ namespace BreCalClient
|
||||
{
|
||||
if (this.ShipcallModel.Shipcall != null)
|
||||
{
|
||||
this.Times.EtdBerth = this.datePickerETD.Value;
|
||||
this.Times.EtdBerth = this.datePickerETD.Value;
|
||||
this.Times.EtdIntervalEnd = this.datePickerETD_End.Value;
|
||||
|
||||
if (this.comboBoxPierside.SelectedIndex >= 0)
|
||||
{
|
||||
this.ShipcallModel.Shipcall.PierSide = (this.comboBoxPierside.SelectedIndex == 0) ? true : false;
|
||||
@ -170,6 +176,8 @@ namespace BreCalClient
|
||||
if (this.ShipcallModel.Shipcall.Etd != DateTime.MinValue)
|
||||
this.datePickerETD.Value = this.ShipcallModel.Shipcall.Etd;
|
||||
}
|
||||
|
||||
this.datePickerETD_End.Value = this.Times.EtdIntervalEnd;
|
||||
|
||||
if (this.Times.BerthId.HasValue)
|
||||
this.comboBoxDepartureBerth.SelectedValue = this.Times.BerthId;
|
||||
@ -193,7 +201,10 @@ namespace BreCalClient
|
||||
|
||||
this.checkBoxMooredLock.IsChecked = this.ShipcallModel.Shipcall.MooredLock ?? false;
|
||||
this.checkBoxRainsensitiveCargo.IsChecked = this.ShipcallModel.Shipcall.RainSensitiveCargo ?? false;
|
||||
if(!string.IsNullOrEmpty(this.Times.Remarks))
|
||||
|
||||
this.labelETD.Content = string.Format("ETD {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall.TimeRefPoint ?? 0]);
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Times.Remarks))
|
||||
this.textBoxRemarks.Text = this.Times.Remarks;
|
||||
|
||||
if (this.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.MOORING))
|
||||
@ -227,37 +238,54 @@ namespace BreCalClient
|
||||
this.comboBoxTug.SelectedValue = this.ShipcallModel.AssignedParticipants[ParticipantType.TUG].ParticipantId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableControls(bool isEnabled)
|
||||
private void EnableControls()
|
||||
{
|
||||
this.datePickerETD.IsEnabled = isEnabled;
|
||||
this.comboBoxDepartureBerth.IsEnabled = isEnabled;
|
||||
this.comboBoxPierside.IsEnabled = isEnabled;
|
||||
this.textBoxBerthRemarks.IsEnabled = isEnabled;
|
||||
this.doubleUpDownDraft.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowTo.IsEnabled = isEnabled;
|
||||
this.checkBoxCanceled.IsEnabled = isEnabled;
|
||||
this.datePickerETD.IsEnabled = _editing;
|
||||
this.datePickerETD_End.IsEnabled = _editing;
|
||||
this.comboBoxDepartureBerth.IsEnabled = _editing;
|
||||
this.comboBoxPierside.IsEnabled = _editing;
|
||||
this.textBoxBerthRemarks.IsReadOnly = !_editing;
|
||||
this.doubleUpDownDraft.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowTo.IsEnabled = _editing;
|
||||
this.checkBoxCanceled.IsEnabled = _editing;
|
||||
|
||||
|
||||
this.comboBoxTug.IsEnabled = isEnabled;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = isEnabled;
|
||||
this.comboBoxPilot.IsEnabled = isEnabled;
|
||||
this.comboBoxMooring.IsEnabled = isEnabled;
|
||||
this.checkBoxMooredLock.IsEnabled = isEnabled;
|
||||
this.comboBoxTerminal.IsEnabled = isEnabled;
|
||||
this.checkBoxRainsensitiveCargo.IsEnabled = isEnabled;
|
||||
this.textBoxRemarks.IsEnabled = isEnabled;
|
||||
this.comboBoxTug.IsEnabled = _editing;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = _editing;
|
||||
this.comboBoxPilot.IsEnabled = _editing;
|
||||
this.comboBoxMooring.IsEnabled = _editing;
|
||||
this.checkBoxMooredLock.IsEnabled = _editing;
|
||||
this.comboBoxTerminal.IsEnabled = _editing;
|
||||
this.checkBoxRainsensitiveCargo.IsEnabled = _editing;
|
||||
this.textBoxRemarks.IsReadOnly = !_editing;
|
||||
|
||||
this.buttonOK.IsEnabled = isEnabled;
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private bool RequiredFieldsSet()
|
||||
{
|
||||
bool areSet = this.datePickerETD.Value.HasValue &&
|
||||
this.doubleUpDownDraft.Value.HasValue &&
|
||||
this.comboBoxDepartureBerth.SelectedIndex >= 0;
|
||||
|
||||
if (areSet && this.datePickerETD_End.Value.HasValue)
|
||||
areSet &= (this.datePickerETD_End.Value > this.datePickerETD.Value);
|
||||
|
||||
return areSet;
|
||||
}
|
||||
|
||||
private void CheckOKButton()
|
||||
{
|
||||
this.buttonOK.IsEnabled = _editing && RequiredFieldsSet();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region context menu handlers
|
||||
#region event handlers
|
||||
|
||||
private void contextMenuItemClearTug_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@ -292,6 +320,21 @@ namespace BreCalClient
|
||||
private void contextMenuItemClearPierside_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxPierside.SelectedIndex = -1;
|
||||
}
|
||||
|
||||
private void datePickerETD_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void comboBoxDepartureBerth_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void doubleUpDownDraft_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -8,12 +8,12 @@
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="490" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
Title="{x:Static p:Resources.textEditShipcall}" Height="490" Width="900" Loaded="Window_Loaded" ResizeMode="CanResizeWithGrip" Icon="Resources/containership.ico">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.2*"/>
|
||||
<ColumnDefinition Width=".3*" />
|
||||
<ColumnDefinition Width="0.2*"/>
|
||||
<ColumnDefinition Width="0.18*"/>
|
||||
<ColumnDefinition Width=".4*" />
|
||||
<ColumnDefinition Width="0.15*"/>
|
||||
<ColumnDefinition Width=".3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
@ -30,7 +30,7 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
|
||||
@ -44,9 +44,16 @@
|
||||
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.textShiftingFrom}" FontWeight="DemiBold"/>
|
||||
<Image Margin="2" Grid.Column="1" Source="Resources/arrow_right_green.png" />
|
||||
</Grid>
|
||||
<Label Content="ETD" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="1" Grid.Row="1" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
|
||||
<Label Content="ETD" x:Name="labelETD" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<Grid Grid.Column="1" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="0" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETD_End" Grid.Column="1" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETD_ValueChanged"/>
|
||||
</Grid>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textTerminal}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right"/>
|
||||
<ComboBox Name="comboBoxTerminal" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id">
|
||||
<ComboBox.ContextMenu>
|
||||
@ -57,11 +64,11 @@
|
||||
</ComboBox>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<ComboBox Name="comboBoxDepartureBerth" Grid.Column="1" Grid.Row="3" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id">
|
||||
<ComboBox Name="comboBoxDepartureBerth" Grid.Column="1" Grid.Row="3" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxDepartureBerth_SelectionChanged">
|
||||
</ComboBox>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right" />
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="4" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5"/>
|
||||
|
||||
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="4" Margin="2" FormatString="N2" Minimum="0" Maximum="50" MaxLength="5" ValueChanged="doubleUpDownDraft_ValueChanged"/>
|
||||
<Label Content="{x:Static p:Resources.textTidalWindow}" FontWeight="DemiBold" Grid.Column="0" Grid.Row="5" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textFrom}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right"/>
|
||||
<Label Content="{x:Static p:Resources.textTo}" Grid.Column="0" Grid.Row="7" HorizontalContentAlignment="Right"/>
|
||||
@ -75,12 +82,19 @@
|
||||
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static p:Resources.textShiftingTo}" FontWeight="DemiBold"/>
|
||||
<Image Margin="2" Grid.Column="1" Source="Resources/arrow_right_green.png" />
|
||||
</Grid>
|
||||
<Label Content="ETA" Grid.Column="0" Grid.Row="9" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="1" Grid.Row="9" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm"/>
|
||||
<Label Content="ETA" x:Name="labelETA" Grid.Column="0" Grid.Row="9" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<Grid Grid.Column="1" Grid.Row="9">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="0" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETA_ValueChanged"/>
|
||||
<xctk:DateTimePicker x:Name="datePickerETA_End" Grid.Column="1" Grid.Row="0" Margin="2" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETA_ValueChanged"/>
|
||||
</Grid>
|
||||
|
||||
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Grid.Column="0" Grid.Row="10" HorizontalContentAlignment="Right" FontWeight="Bold"/>
|
||||
<ComboBox Name="comboBoxArrivalBerth" Grid.Column="1" Grid.Row="10" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id">
|
||||
</ComboBox>
|
||||
<ComboBox Name="comboBoxArrivalBerth" Grid.Column="1" Grid.Row="10" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" SelectionChanged="comboBoxArrivalBerth_SelectionChanged" />
|
||||
<Label Content="{x:Static p:Resources.textPierside}" Grid.Column="0" Grid.Row="11" HorizontalContentAlignment="Right" />
|
||||
<ComboBox x:Name="comboBoxPiersideArrival" Grid.Column="1" Grid.Row="11" Margin="2" >
|
||||
<ComboBoxItem Content="{x:Static p:Resources.textPort}" />
|
||||
@ -92,7 +106,7 @@
|
||||
</ComboBox.ContextMenu>
|
||||
</ComboBox>
|
||||
<Label Content="{x:Static p:Resources.textBerthRemarks}" Grid.Column="0" Grid.Row="12" HorizontalContentAlignment="Right" />
|
||||
<TextBox x:Name="textBoxBerthRemarksArrival" Grid.Column="1" Grid.Row="12" Margin="2,1,2,3" Grid.RowSpan="2" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<TextBox x:Name="textBoxBerthRemarksArrival" Grid.Column="1" Grid.Row="12" Margin="2,1,2,3" Grid.RowSpan="2" VerticalContentAlignment="Top" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
<Label Content="{x:Static p:Resources.textCancelled}" Grid.Column="0" Grid.Row="14" HorizontalContentAlignment="Right" />
|
||||
<CheckBox x:Name="checkBoxCanceled" Grid.Column="1" Grid.Row="14" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,4,0" />
|
||||
|
||||
@ -133,7 +147,7 @@
|
||||
<Label Content="{x:Static p:Resources.textRainSensitiveCargo}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="6" HorizontalAlignment="Right" />
|
||||
<CheckBox x:Name="checkBoxRainsensitiveCargo" Grid.Column="3" Grid.Row="6" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,0,4,0" />
|
||||
<Label Content="{x:Static p:Resources.textRemarks}" Grid.Column="2" Grid.Row="7" HorizontalContentAlignment="Right" />
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="7" Margin="2,1,2,3" Grid.RowSpan="7" VerticalContentAlignment="Top" AcceptsReturn="True" MaxLength="512"/>
|
||||
<TextBox x:Name="textBoxRemarks" Grid.Column="3" Grid.Row="7" Margin="2,1,2,3" Grid.RowSpan="7" VerticalContentAlignment="Top" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
|
||||
<StackPanel Grid.Row="15" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False"/>
|
||||
|
||||
@ -12,8 +12,13 @@ namespace BreCalClient
|
||||
/// <summary>
|
||||
/// Interaction logic for EditTimesAgencyShiftingControl.xaml
|
||||
/// </summary>
|
||||
public partial class EditTimesAgencyShiftingControl : Window, IEditShipcallTimesControl
|
||||
public partial class EditTimesAgencyShiftingControl : Window, IEditTimesControl
|
||||
{
|
||||
#region Fields
|
||||
|
||||
bool _editing = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
@ -28,9 +33,7 @@ namespace BreCalClient
|
||||
|
||||
public ShipcallControlModel ShipcallModel { get; set; } = new();
|
||||
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
public Extensions.TypeEnum CallType { get; set; }
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -59,10 +62,10 @@ namespace BreCalClient
|
||||
allowBSMD = p.IsFlagSet(ParticipantFlag.ALLOW_BSMD);
|
||||
}
|
||||
|
||||
bool enableControls = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
_editing = (this.Times.ParticipantId == App.Participant.Id) ||
|
||||
(App.Participant.IsTypeFlagSet(ParticipantType.BSMD) && allowBSMD);
|
||||
|
||||
this.EnableControls(enableControls);
|
||||
this.EnableControls();
|
||||
|
||||
}
|
||||
|
||||
@ -89,6 +92,9 @@ namespace BreCalClient
|
||||
{
|
||||
this.Times.EtdBerth = this.datePickerETD.Value;
|
||||
this.Times.EtaBerth = this.datePickerETA.Value;
|
||||
this.Times.EtaIntervalEnd = this.datePickerETA_End.Value;
|
||||
this.Times.EtdIntervalEnd = this.datePickerETD_End.Value;
|
||||
|
||||
this.ShipcallModel.Shipcall.DepartureBerthId = (int)this.comboBoxDepartureBerth.SelectedValue;
|
||||
if (this.comboBoxPiersideArrival.SelectedIndex >= 0)
|
||||
{
|
||||
@ -184,6 +190,9 @@ namespace BreCalClient
|
||||
this.datePickerETD.Value = this.ShipcallModel.Shipcall.Etd;
|
||||
}
|
||||
|
||||
this.datePickerETA_End.Value = this.Times.EtaIntervalEnd;
|
||||
this.datePickerETD_End.Value = this.Times.EtdIntervalEnd;
|
||||
|
||||
if (this.Times.BerthId.HasValue)
|
||||
this.comboBoxArrivalBerth.SelectedValue = this.Times.BerthId;
|
||||
else if (this.ShipcallModel.Shipcall.ArrivalBerthId.HasValue)
|
||||
@ -208,7 +217,11 @@ namespace BreCalClient
|
||||
|
||||
this.checkBoxMooredLock.IsChecked = this.ShipcallModel.Shipcall.MooredLock ?? false;
|
||||
this.checkBoxRainsensitiveCargo.IsChecked = this.ShipcallModel.Shipcall.RainSensitiveCargo ?? false;
|
||||
if(!string.IsNullOrEmpty(this.Times.Remarks))
|
||||
|
||||
this.labelETA.Content = string.Format("ETA {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall.TimeRefPoint ?? 0]);
|
||||
this.labelETD.Content = string.Format("ETD {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall.TimeRefPoint ?? 0]);
|
||||
|
||||
if (!string.IsNullOrEmpty(this.Times.Remarks))
|
||||
this.textBoxRemarks.Text = this.Times.Remarks;
|
||||
|
||||
if (this.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.MOORING))
|
||||
@ -245,35 +258,59 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableControls(bool isEnabled)
|
||||
private void EnableControls()
|
||||
{
|
||||
this.datePickerETD.IsEnabled = isEnabled;
|
||||
this.comboBoxArrivalBerth.IsEnabled = isEnabled;
|
||||
this.doubleUpDownDraft.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = isEnabled;
|
||||
this.datePickerTidalWindowTo.IsEnabled = isEnabled;
|
||||
this.datePickerETA.IsEnabled = isEnabled;
|
||||
this.comboBoxDepartureBerth.IsEnabled = isEnabled;
|
||||
this.comboBoxPiersideArrival.IsEnabled = isEnabled;
|
||||
this.textBoxBerthRemarksArrival.IsEnabled = isEnabled;
|
||||
this.checkBoxCanceled.IsEnabled = isEnabled;
|
||||
this.datePickerETD_End.IsEnabled = _editing;
|
||||
this.datePickerETA_End.IsEnabled = _editing;
|
||||
this.datePickerETD.IsEnabled = _editing;
|
||||
this.comboBoxArrivalBerth.IsEnabled = _editing;
|
||||
this.doubleUpDownDraft.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowFrom.IsEnabled = _editing;
|
||||
this.datePickerTidalWindowTo.IsEnabled = _editing;
|
||||
this.datePickerETA.IsEnabled = _editing;
|
||||
this.comboBoxDepartureBerth.IsEnabled = _editing;
|
||||
this.comboBoxPiersideArrival.IsEnabled = _editing;
|
||||
this.textBoxBerthRemarksArrival.IsReadOnly = !_editing;
|
||||
this.checkBoxCanceled.IsEnabled = _editing;
|
||||
|
||||
|
||||
this.comboBoxTug.IsEnabled = isEnabled;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = isEnabled;
|
||||
this.comboBoxPilot.IsEnabled = isEnabled;
|
||||
this.comboBoxMooring.IsEnabled = isEnabled;
|
||||
this.checkBoxMooredLock.IsEnabled = isEnabled;
|
||||
this.comboBoxTerminal.IsEnabled = isEnabled;
|
||||
this.checkBoxRainsensitiveCargo.IsEnabled = isEnabled;
|
||||
this.textBoxRemarks.IsEnabled = isEnabled;
|
||||
this.comboBoxTug.IsEnabled = _editing;
|
||||
this.integerUpDownRecommendedTugs.IsEnabled = _editing;
|
||||
this.comboBoxPilot.IsEnabled = _editing;
|
||||
this.comboBoxMooring.IsEnabled = _editing;
|
||||
this.checkBoxMooredLock.IsEnabled = _editing;
|
||||
this.comboBoxTerminal.IsEnabled = _editing;
|
||||
this.checkBoxRainsensitiveCargo.IsEnabled = _editing;
|
||||
this.textBoxRemarks.IsReadOnly = !_editing;
|
||||
|
||||
this.buttonOK.IsEnabled = isEnabled;
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private bool RequiredFieldsSet()
|
||||
{
|
||||
bool areSet = this.datePickerETA.Value.HasValue &&
|
||||
this.datePickerETD.Value.HasValue &&
|
||||
this.doubleUpDownDraft.Value.HasValue &&
|
||||
(this.comboBoxArrivalBerth.SelectedIndex >= 0) &&
|
||||
(this.comboBoxDepartureBerth.SelectedIndex >= 0);
|
||||
|
||||
if (this.datePickerETA_End.Value.HasValue)
|
||||
areSet &= (this.datePickerETA_End.Value > this.datePickerETA.Value);
|
||||
|
||||
if (this.datePickerETD_End.Value.HasValue)
|
||||
areSet &= (this.datePickerETD_End.Value > this.datePickerETD.Value);
|
||||
|
||||
return areSet;
|
||||
}
|
||||
|
||||
private void CheckOKButton()
|
||||
{
|
||||
this.buttonOK.IsEnabled = _editing && RequiredFieldsSet();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region context menu handlers
|
||||
#region event handlers
|
||||
|
||||
private void contextMenuItemDepartureBerth_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@ -314,6 +351,31 @@ namespace BreCalClient
|
||||
private void contextMenuItemClearPierside_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxPiersideArrival.SelectedIndex = -1;
|
||||
}
|
||||
|
||||
private void datePickerETD_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void comboBoxDepartureBerth_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void doubleUpDownDraft_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void datePickerETA_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void comboBoxArrivalBerth_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -8,11 +8,11 @@
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditTimes}" Height="265" Width="400" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
|
||||
Title="{x:Static p:Resources.textEditTimes}" Height="331" Width="500" Loaded="Window_Loaded" ResizeMode="CanResizeWithGrip" Icon="Resources/containership.ico">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".25*" />
|
||||
<ColumnDefinition Width=".75*" />
|
||||
<ColumnDefinition Width=".20*" />
|
||||
<ColumnDefinition Width=".80*" />
|
||||
<!--ColumnDefinition Width="40" /-->
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
@ -21,21 +21,92 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="56" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<Button x:Name="buttonFixedOrder" Grid.Row="0" Grid.Column="1" Margin="2" Click="buttonFixedOrder_Click" Width="28" HorizontalAlignment="Left">
|
||||
<Image x:Name="imageFixedOrder" Source="Resources\lock_open.png" />
|
||||
</Button>
|
||||
<!-- Label Grid.Row="0" Grid.Column="2" Content="{x:Static p:Resources.textFixed}" /-->
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textETABerth}" HorizontalContentAlignment="Right" x:Name="labelETA" />
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static p:Resources.textETDBerth}" HorizontalContentAlignment="Right" x:Name="labelETD" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static p:Resources.textLockTime}" HorizontalContentAlignment="Right" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static p:Resources.textZoneEntryTime}" HorizontalContentAlignment="Right" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="ATA" HorizontalContentAlignment="Right" x:Name="labelATA" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="ATD" HorizontalContentAlignment="Right" x:Name="labelATD" />
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static p:Resources.textLockTime}" HorizontalContentAlignment="Right" />
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static p:Resources.textZoneEntryTime}" HorizontalContentAlignment="Right" />
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" HorizontalContentAlignment="Right" />
|
||||
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" HorizontalContentAlignment="Right" />
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="1" Grid.Column="1" Margin="2" Name="datePickerETABerth" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<Grid Grid.Row="1" Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="0" Grid.Column="0" Margin="2" Name="datePickerETABerth" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETABerth_ValueChanged">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETA" Click="contextMenuItemClearETA_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="0" Grid.Column="1" Margin="2" Name="datePickerETABerth_End" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETA_End" Click="contextMenuItemClearETA_End_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="1" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="0" Grid.Column="0" Margin="2" Name="datePickerETDBerth" Format="Custom" FormatString="dd.MM. yyyy HH:mm" ValueChanged="datePickerETDBerth_ValueChanged">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETD" Click="contextMenuItemClearETD_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="0" Grid.Column="1" Margin="2" Name="datePickerETDBerth_End" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETD_End" Click="contextMenuItemClearETD_End_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
</Grid>
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="3" Grid.Column="1" Margin="2" Name="datePickerATA" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETA" Click="contextMenuItemClearETA_Click" >
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearATA" Click="contextMenuItemClearATA_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
@ -43,11 +114,11 @@
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<!--CheckBox IsEnabled="False" Grid.Row="1" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxEtaBerthFixed" VerticalAlignment="Center" /-->
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="2" Grid.Column="1" Margin="2" Name="datePickerETDBerth" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="4" Grid.Column="1" Margin="2" Name="datePickerATD" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearETD" Click="contextMenuItemClearETD_Click" >
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearATD" Click="contextMenuItemClearATD_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
@ -55,8 +126,8 @@
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<!--CheckBox IsEnabled="False" Grid.Row="2" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxEtDBerthFixed" VerticalAlignment="Center" /-->
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="3" Grid.Column="1" Margin="2" Name="datePickerLockTime" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="5" Grid.Column="1" Margin="2" Name="datePickerLockTime" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearLockTime" Click="contextMenuItemClearLockTime_Click" >
|
||||
@ -68,7 +139,7 @@
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<!--CheckBox IsEnabled="False" Grid.Row="3" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxLockTimeFixed" VerticalAlignment="Center" /-->
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="4" Grid.Column="1" Margin="2" Name="datePickerZoneEntry" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker IsEnabled="False" Grid.Row="6" Grid.Column="1" Margin="2" Name="datePickerZoneEntry" Format="Custom" FormatString="dd.MM. yyyy HH:mm">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearZoneEntry" Click="contextMenuItemClearZoneEntry_Click" >
|
||||
@ -81,8 +152,8 @@
|
||||
</xctk:DateTimePicker>
|
||||
<!--CheckBox IsEnabled="False" Grid.Row="4" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxZoneEntryFixed" VerticalAlignment="Center" /-->
|
||||
|
||||
<TextBox Grid.Row="5" Grid.Column="1" Margin="2" Name="textBoxRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsEnabled="False" MaxLength="512"/>
|
||||
<StackPanel Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<TextBox Grid.Row="7" Grid.Column="1" Margin="2" Name="textBoxRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsReadOnly="True" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
<StackPanel Grid.Row="8" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False" />
|
||||
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
@ -4,7 +4,9 @@
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Model;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
@ -25,9 +27,9 @@ namespace BreCalClient
|
||||
|
||||
#region Properties
|
||||
|
||||
public Times Times { get; set; } = new();
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
public Extensions.TypeEnum CallType { get; set; }
|
||||
public ShipcallControlModel ShipcallModel { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -52,6 +54,24 @@ namespace BreCalClient
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void buttonFixedOrder_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool newValue = true;
|
||||
if (this.Times.EtaBerthFixed ?? false)
|
||||
newValue = false;
|
||||
SetLockButton(newValue);
|
||||
}
|
||||
|
||||
private void datePickerETABerth_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
private void datePickerETDBerth_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
CheckOKButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
@ -61,8 +81,12 @@ namespace BreCalClient
|
||||
this.Times.Remarks = this.textBoxRemarks.Text.Trim().Truncate(512);
|
||||
this.Times.EtaBerth = this.datePickerETABerth.Value;
|
||||
this.Times.EtdBerth = this.datePickerETDBerth.Value;
|
||||
this.Times.EtaIntervalEnd = this.datePickerETABerth_End.Value;
|
||||
this.Times.EtdIntervalEnd = this.datePickerETDBerth_End.Value;
|
||||
this.Times.LockTime = this.datePickerLockTime.Value;
|
||||
this.Times.ZoneEntry = this.datePickerZoneEntry.Value;
|
||||
this.Times.Ata = this.datePickerATA.Value;
|
||||
this.Times.Atd = this.datePickerATD.Value;
|
||||
}
|
||||
|
||||
private void CopyToControls()
|
||||
@ -72,54 +96,114 @@ namespace BreCalClient
|
||||
this.datePickerETDBerth.Value = this.Times.EtdBerth;
|
||||
this.datePickerLockTime.Value = this.Times.LockTime;
|
||||
this.datePickerZoneEntry.Value = this.Times.ZoneEntry;
|
||||
this.datePickerATA.Value = this.Times.Ata;
|
||||
this.datePickerATD.Value = this.Times.Atd;
|
||||
this.datePickerETABerth_End.Value = this.Times.EtaIntervalEnd;
|
||||
this.datePickerETDBerth_End.Value = this.Times.EtdIntervalEnd;
|
||||
|
||||
switch (CallType)
|
||||
this.labelETA.Content = string.Format("ETA {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall?.TimeRefPoint ?? 0]);
|
||||
this.labelETD.Content = string.Format("ETD {0}", BreCalLists.TimeRefs[this.ShipcallModel.Shipcall?.TimeRefPoint ?? 0]);
|
||||
|
||||
switch (ShipcallModel.Shipcall?.Type)
|
||||
{
|
||||
case Extensions.TypeEnum.Incoming:
|
||||
case ShipcallType.Arrival:
|
||||
this.labelETA.FontWeight = FontWeights.Bold;
|
||||
this.datePickerETABerth.ContextMenu.IsEnabled = false;
|
||||
break;
|
||||
case Extensions.TypeEnum.Outgoing:
|
||||
case Extensions.TypeEnum.Shifting:
|
||||
case ShipcallType.Departure:
|
||||
case ShipcallType.Shifting:
|
||||
this.labelETD.FontWeight = FontWeights.Bold;
|
||||
this.datePickerETDBerth.ContextMenu.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.SetLockButton(this.Times.EtaBerthFixed ?? false);
|
||||
}
|
||||
|
||||
private void EnableControls()
|
||||
{
|
||||
Extensions.ParticipantType pType = (Extensions.ParticipantType) (this.Times.ParticipantType ?? 0);
|
||||
if (this.Times.ParticipantId != App.Participant.Id) return; // if this is not "my" entry, there is no editing!
|
||||
Extensions.ParticipantType pType = (Extensions.ParticipantType) this.Times.ParticipantType;
|
||||
|
||||
// setting visibility
|
||||
|
||||
if (pType != Extensions.ParticipantType.MOORING)
|
||||
{
|
||||
this.labelATA.Visibility = Visibility.Hidden;
|
||||
this.datePickerATA.Visibility = Visibility.Hidden;
|
||||
this.labelATD.Visibility = Visibility.Hidden;
|
||||
this.datePickerATD.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ShipcallModel.Shipcall?.Type == ShipcallType.Arrival)
|
||||
{
|
||||
this.labelATD.Visibility = Visibility.Hidden;
|
||||
this.datePickerATD.Visibility = Visibility.Hidden;
|
||||
}
|
||||
if (ShipcallModel.Shipcall?.Type == ShipcallType.Departure)
|
||||
{
|
||||
this.labelATA.Visibility = Visibility.Hidden;
|
||||
this.datePickerATA.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// setting en/dis-abled
|
||||
|
||||
if (this.Times.ParticipantId != App.Participant.Id)
|
||||
{
|
||||
this.buttonFixedOrder.IsEnabled = false;
|
||||
return; // if this is not "my" entry, there is no editing!
|
||||
}
|
||||
|
||||
this.datePickerETABerth.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.datePickerETABerth_End.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.datePickerETDBerth.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Departure || ShipcallModel.Shipcall?.Type == ShipcallType.Shifting);
|
||||
this.datePickerETDBerth_End.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Departure || ShipcallModel.Shipcall?.Type == ShipcallType.Shifting);
|
||||
this.textBoxRemarks.IsReadOnly = false;
|
||||
|
||||
switch (pType)
|
||||
{
|
||||
case Extensions.ParticipantType.MOORING:
|
||||
case Extensions.ParticipantType.PORT_ADMINISTRATION:
|
||||
case Extensions.ParticipantType.TUG:
|
||||
this.datePickerETABerth.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
//this.checkBoxEtaBerthFixed.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerETDBerth.IsEnabled = (CallType == Extensions.TypeEnum.Outgoing || CallType == Extensions.TypeEnum.Shifting);
|
||||
//this.checkBoxEtDBerthFixed.IsEnabled = (CallType == Extensions.TypeEnum.Outgoing || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerLockTime.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
//this.checkBoxLockTimeFixed.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerZoneEntry.IsEnabled = false;
|
||||
//this.checkBoxZoneEntryFixed.IsEnabled = false;
|
||||
this.textBoxRemarks.IsEnabled = true;
|
||||
this.datePickerATA.IsEnabled = true;
|
||||
this.datePickerATD.IsEnabled = true;
|
||||
break;
|
||||
case Extensions.ParticipantType.PILOT:
|
||||
this.datePickerETABerth.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
//this.checkBoxEtaBerthFixed.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerETDBerth.IsEnabled = (CallType == Extensions.TypeEnum.Outgoing || CallType == Extensions.TypeEnum.Shifting);
|
||||
//this.checkBoxEtDBerthFixed.IsEnabled = (CallType == Extensions.TypeEnum.Outgoing || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerLockTime.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
//this.checkBoxLockTimeFixed.IsEnabled = (CallType == Extensions.TypeEnum.Incoming || CallType == Extensions.TypeEnum.Shifting);
|
||||
this.datePickerZoneEntry.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
//this.checkBoxZoneEntryFixed.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
this.textBoxRemarks.IsEnabled = true;
|
||||
case Extensions.ParticipantType.PORT_ADMINISTRATION:
|
||||
this.datePickerLockTime.IsEnabled = true;
|
||||
break;
|
||||
case Extensions.ParticipantType.TUG:
|
||||
case Extensions.ParticipantType.PILOT:
|
||||
this.datePickerZoneEntry.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Arrival);
|
||||
break;
|
||||
}
|
||||
this.buttonOK.IsEnabled = true;
|
||||
|
||||
CheckOKButton();
|
||||
|
||||
}
|
||||
|
||||
private void SetLockButton(bool newValue)
|
||||
{
|
||||
if (newValue)
|
||||
{
|
||||
this.Times.EtaBerthFixed = true;
|
||||
this.imageFixedOrder.Source = new BitmapImage(new Uri(@"pack://application:,,,/Resources/lock.png", UriKind.RelativeOrAbsolute));
|
||||
this.buttonFixedOrder.ToolTip = BreCalClient.Resources.Resources.textTooltipUnSetFixedOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Times.EtaBerthFixed = false;
|
||||
this.imageFixedOrder.Source = new BitmapImage(new Uri(@"pack://application:,,,/Resources/lock_open.png", UriKind.RelativeOrAbsolute));
|
||||
this.buttonFixedOrder.ToolTip = BreCalClient.Resources.Resources.textTooltipSetFixedOrder;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckOKButton()
|
||||
{
|
||||
Extensions.ParticipantType pType = (Extensions.ParticipantType)this.Times.ParticipantType;
|
||||
if (pType != Extensions.ParticipantType.PORT_ADMINISTRATION)
|
||||
this.buttonOK.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Arrival) ?
|
||||
this.datePickerETABerth.Value.HasValue : this.datePickerETDBerth.Value.HasValue;
|
||||
else
|
||||
this.buttonOK.IsEnabled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -146,7 +230,27 @@ namespace BreCalClient
|
||||
this.datePickerZoneEntry.Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
private void contextMenuItemClearATA_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerATA.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemClearATD_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerATD.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemClearETA_End_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerETABerth_End.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemClearETD_End_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerETDBerth_End.Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W1Left}" Top="{local:SettingBinding W1Top}"
|
||||
Title="{x:Static p:Resources.textEditTimes}" Loaded="Window_Loaded" Height="295" Width="400" >
|
||||
Title="{x:Static p:Resources.textEditTimes}" Loaded="Window_Loaded" Height="295" Width="500" ResizeMode="CanResizeWithGrip" >
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".4*" />
|
||||
<ColumnDefinition Width=".6*" />
|
||||
<ColumnDefinition Width=".3*" />
|
||||
<ColumnDefinition Width=".7*" />
|
||||
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
@ -20,7 +20,7 @@
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="28" />
|
||||
<RowDefinition Height="56" />
|
||||
<RowDefinition Height="56" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
@ -32,28 +32,70 @@
|
||||
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" HorizontalContentAlignment="Right" />
|
||||
|
||||
<xctk:DateTimePicker Grid.Row="0" Grid.Column="1" Margin="2" Name="datePickerOperationStart" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationStart" Click="contextMenuItemClearOperationStart_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<xctk:DateTimePicker Grid.Row="1" Grid.Column="1" Margin="2" Name="datePickerOperationEnd" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationEnd" Click="contextMenuItemClearOperationEnd_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<Grid Grid.Row="0" Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<xctk:DateTimePicker Grid.Row="0" Grid.Column="0" Margin="2" Name="datePickerOperationStart" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerOperationStart_ValueChanged">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationStart" Click="contextMenuItemClearOperationStart_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
<xctk:DateTimePicker Grid.Row="0" Grid.Column="1" Margin="2" Name="datePickerOperationStart_End" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationStart_End" Click="contextMenuItemClearOperationStart_End_Click">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="1" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<xctk:DateTimePicker Grid.Row="0" Grid.Column="0" Margin="2" Name="datePickerOperationEnd" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False" ValueChanged="datePickerOperationEnd_ValueChanged">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationEnd" Click="contextMenuItemClearOperationEnd_Click" >
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
<xctk:DateTimePicker Grid.Row="0" Grid.Column="1" Margin="2" Name="datePickerOperationEnd_End" Format="Custom" FormatString="dd.MM. yyyy HH:mm" IsEnabled="False">
|
||||
<xctk:DateTimePicker.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.textClearValue}" Name="contextMenuItemClearOperationEnd_End" Click="contextMenuItemClearOperationEnd_End_Click">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources\delete.png" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</xctk:DateTimePicker.ContextMenu>
|
||||
</xctk:DateTimePicker>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<ComboBox Name="comboBoxBerth" Grid.Column="1" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" IsEnabled="False">
|
||||
<ComboBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
@ -70,8 +112,8 @@
|
||||
</ContextMenu>
|
||||
</ComboBox.ContextMenu>
|
||||
</ComboBox>
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Margin="2" Name="textBoxBerthRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsEnabled="False" MaxLength="512" />
|
||||
<TextBox Grid.Row="5" Grid.Column="1" Margin="2" Name="textBoxRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsEnabled="False" MaxLength="512" />
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Margin="2" Name="textBoxBerthRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsReadOnly="True" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
<TextBox Grid.Row="5" Grid.Column="1" Margin="2" Name="textBoxRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="False" IsReadOnly="True" MaxLength="512" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
|
||||
<StackPanel Grid.Row="6" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False"/>
|
||||
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
|
||||
|
||||
@ -21,7 +21,7 @@ namespace BreCalClient
|
||||
|
||||
public Times Times { get; set; } = new();
|
||||
|
||||
public Extensions.TypeEnum CallType { get; set; }
|
||||
public ShipcallControlModel ShipcallModel { get; set; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
@ -44,6 +44,16 @@ namespace BreCalClient
|
||||
this.datePickerOperationEnd.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemClearOperationStart_End_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerOperationStart_End.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemClearOperationEnd_End_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.datePickerOperationEnd_End.Value = null;
|
||||
}
|
||||
|
||||
private void contextMenuItemBerth_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxBerth.SelectedIndex -= 1;
|
||||
@ -66,20 +76,32 @@ namespace BreCalClient
|
||||
this.comboBoxPierside.SelectedIndex = -1;
|
||||
}
|
||||
|
||||
private void datePickerOperationStart_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
private void datePickerOperationEnd_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
|
||||
private void CopyToModel()
|
||||
{
|
||||
switch(this.comboBoxPierside.SelectedIndex)
|
||||
this.Times.PierSide = this.comboBoxPierside.SelectedIndex switch
|
||||
{
|
||||
case 0: this.Times.PierSide = true; break;
|
||||
case 1: this.Times.PierSide= false; break;
|
||||
default: this.Times.PierSide = null; break;
|
||||
}
|
||||
0 => true,
|
||||
1 => false,
|
||||
_ => null,
|
||||
};
|
||||
this.Times.OperationsStart = this.datePickerOperationStart.Value;
|
||||
this.Times.OperationsEnd = this.datePickerOperationEnd.Value;
|
||||
this.Times.EtaIntervalEnd = this.datePickerOperationStart_End.Value;
|
||||
this.Times.EtdIntervalEnd = this.datePickerOperationEnd_End.Value;
|
||||
this.Times.BerthId = (this.comboBoxBerth.SelectedItem != null) ? ((Berth)this.comboBoxBerth.SelectedItem).Id : null;
|
||||
this.Times.Remarks = this.textBoxRemarks.Text.Trim();
|
||||
this.Times.BerthInfo = this.textBoxBerthRemarks.Text.Trim();
|
||||
@ -89,20 +111,22 @@ namespace BreCalClient
|
||||
{
|
||||
this.datePickerOperationStart.Value = this.Times.OperationsStart;
|
||||
this.datePickerOperationEnd.Value = this.Times.OperationsEnd;
|
||||
this.datePickerOperationStart_End.Value = this.Times.EtaIntervalEnd;
|
||||
this.datePickerOperationEnd_End.Value = this.Times.EtdIntervalEnd;
|
||||
if(this.Times.PierSide == null) { this.comboBoxPierside.SelectedIndex = -1; }
|
||||
else this.comboBoxPierside.SelectedIndex = (this.Times.PierSide ?? false) ? 0 : 1;
|
||||
this.comboBoxBerth.SelectedValue = this.Times.BerthId;
|
||||
this.textBoxRemarks.Text = this.Times.Remarks;
|
||||
this.textBoxBerthRemarks.Text = this.Times.BerthInfo;
|
||||
|
||||
switch (CallType)
|
||||
switch (ShipcallModel.Shipcall?.Type)
|
||||
{
|
||||
case Extensions.TypeEnum.Incoming:
|
||||
case ShipcallType.Arrival:
|
||||
this.labelStart.FontWeight = FontWeights.Bold;
|
||||
this.datePickerOperationStart.ContextMenu.IsEnabled = false;
|
||||
break;
|
||||
case Extensions.TypeEnum.Outgoing:
|
||||
case Extensions.TypeEnum.Shifting:
|
||||
case ShipcallType.Departure:
|
||||
case ShipcallType.Shifting:
|
||||
this.labelEnd.FontWeight = FontWeights.Bold;
|
||||
this.datePickerOperationEnd.ContextMenu.IsEnabled = false;
|
||||
break;
|
||||
@ -114,13 +138,21 @@ namespace BreCalClient
|
||||
{
|
||||
if (this.Times.ParticipantId != App.Participant.Id) return;
|
||||
|
||||
this.datePickerOperationStart.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
this.datePickerOperationEnd.IsEnabled = (CallType == Extensions.TypeEnum.Outgoing) || (CallType == Extensions.TypeEnum.Shifting);
|
||||
this.comboBoxBerth.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
this.comboBoxPierside.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
this.textBoxBerthRemarks.IsEnabled = (CallType == Extensions.TypeEnum.Incoming);
|
||||
this.textBoxRemarks.IsEnabled = true;
|
||||
this.buttonOK.IsEnabled = true;
|
||||
this.datePickerOperationStart.IsEnabled = ShipcallModel.Shipcall?.Type == ShipcallType.Arrival;
|
||||
this.datePickerOperationStart_End.IsEnabled = ShipcallModel.Shipcall?.Type == ShipcallType.Arrival;
|
||||
this.datePickerOperationEnd.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Departure) || (ShipcallModel.Shipcall?.Type == ShipcallType.Shifting);
|
||||
this.datePickerOperationEnd_End.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Departure) || (ShipcallModel.Shipcall?.Type == ShipcallType.Shifting);
|
||||
this.comboBoxBerth.IsEnabled = ShipcallModel.Shipcall?.Type == ShipcallType.Arrival;
|
||||
this.comboBoxPierside.IsEnabled = ShipcallModel.Shipcall?.Type == ShipcallType.Arrival;
|
||||
this.textBoxBerthRemarks.IsReadOnly = ShipcallModel.Shipcall?.Type != ShipcallType.Arrival;
|
||||
this.textBoxRemarks.IsReadOnly = false;
|
||||
this.CheckOKButton();
|
||||
}
|
||||
|
||||
private void CheckOKButton()
|
||||
{
|
||||
this.buttonOK.IsEnabled = (ShipcallModel.Shipcall?.Type == ShipcallType.Arrival) ? this.datePickerOperationStart.Value.HasValue :
|
||||
this.datePickerOperationEnd.Value.HasValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
71
src/BreCalClient/EnumHelper.cs
Normal file
71
src/BreCalClient/EnumHelper.cs
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2024- schick Informatik
|
||||
// Description: Helpers to display localized Enum values in Comboboxes
|
||||
// https://stackoverflow.com/questions/29658721/enum-in-wpf-comboxbox-with-localized-names
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
|
||||
#region class EnumToStringConverter
|
||||
|
||||
public sealed class EnumToStringConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
{ return null; }
|
||||
|
||||
return Resources.Resources.ResourceManager.GetString(value.ToString() ?? "");
|
||||
}
|
||||
|
||||
public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
string str = (string)value;
|
||||
|
||||
foreach (object enumValue in Enum.GetValues(targetType))
|
||||
{
|
||||
if (str == Resources.Resources.ResourceManager.GetString(enumValue.ToString() ?? ""))
|
||||
{ return enumValue; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region class EnumerateExtension
|
||||
|
||||
public sealed class EnumerateExtension : MarkupExtension
|
||||
{
|
||||
public Type Type { get; set; }
|
||||
|
||||
public EnumerateExtension(Type type)
|
||||
{
|
||||
this.Type = type;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
string[] names = Enum.GetNames(Type);
|
||||
|
||||
// skip value "0" == "Unknown" (we dont want this selectable in the Combobox)
|
||||
// NOTE: This will only work in the future if the first element is always "undefined" aka unused
|
||||
|
||||
string[] values = new string[names.Length - 1];
|
||||
for (int i = 0; i < names.Length - 1; i++)
|
||||
{
|
||||
values[i] = Resources.Resources.ResourceManager.GetString(names[i + 1]) ?? names[i];
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
@ -1,17 +1,19 @@
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Description: some helpers
|
||||
//
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Model;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
|
||||
#region Enum
|
||||
#region Enum
|
||||
|
||||
/// <summary>
|
||||
/// Copied from models clunky I know
|
||||
@ -47,16 +49,6 @@ namespace BreCalClient
|
||||
ALLOW_BSMD = 1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should actually be defined in yaml
|
||||
/// </summary>
|
||||
public enum TypeEnum
|
||||
{
|
||||
Incoming = 1,
|
||||
Outgoing = 2,
|
||||
Shifting = 3
|
||||
}
|
||||
|
||||
public enum SortOrder
|
||||
{
|
||||
SHIP_NAME,
|
||||
@ -76,20 +68,87 @@ namespace BreCalClient
|
||||
public static bool IsFlagSet(this Participant participant, ParticipantFlag flag)
|
||||
{
|
||||
return (participant.Flags & (uint)flag) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Truncate(this string value, int maxLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return value;
|
||||
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
|
||||
return value.Length <= maxLength ? value : value[..maxLength];
|
||||
}
|
||||
|
||||
public static string TruncateDots(this string value, int maxLength)
|
||||
{
|
||||
if(string.IsNullOrEmpty(value)) return value;
|
||||
if (value.Length <= maxLength) return value;
|
||||
if (value.Length > (maxLength + 1)) return $"{value.Substring(0, maxLength)}..";
|
||||
return value.Substring(0, maxLength);
|
||||
if (value.Length > (maxLength + 1))
|
||||
{
|
||||
int i = maxLength - 2;
|
||||
for (; (i > 0) && !(char.IsWhiteSpace(value[i])); i--) ; // try to put the "..." at a word break
|
||||
return value.Substring(0, i) + " ...";
|
||||
}
|
||||
return value[..maxLength];
|
||||
}
|
||||
|
||||
public static string DisplayTime(this Times times, bool isArrival)
|
||||
{
|
||||
if (isArrival)
|
||||
{
|
||||
if(times.ParticipantType == (int) ParticipantType.TERMINAL)
|
||||
{
|
||||
if(times.OperationsStart.HasValue)
|
||||
{
|
||||
string result = times.OperationsStart.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
if (times.EtaIntervalEnd.HasValue) result += " - " + times.EtaIntervalEnd.Value.ToString("HH:mm");
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "- / -";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(times.EtaBerth.HasValue)
|
||||
{
|
||||
string result = times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
if (times.EtaIntervalEnd.HasValue) result += " - " + times.EtaIntervalEnd.Value.ToString("HH:mm");
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "- / -";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (times.ParticipantType == (int)ParticipantType.TERMINAL)
|
||||
{
|
||||
if(times.OperationsEnd.HasValue)
|
||||
{
|
||||
string result = times.OperationsEnd.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
if (times.EtdIntervalEnd.HasValue) result += " - " + times.EtdIntervalEnd.Value.ToString("HH:mm");
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "- / -";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(times.EtdBerth.HasValue)
|
||||
{
|
||||
string result = times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
if (times.EtdIntervalEnd.HasValue) result += " - " + times.EtdIntervalEnd.Value.ToString("HH:mm");
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "- / -";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
39
src/BreCalClient/HistoryControl.xaml
Normal file
39
src/BreCalClient/HistoryControl.xaml
Normal file
@ -0,0 +1,39 @@
|
||||
<UserControl x:Class="BreCalClient.HistoryControl"
|
||||
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:BreCalClient"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="46" d:DesignWidth="800">
|
||||
<Border BorderBrush="Black" BorderThickness="0 0 0 .5">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="14" />
|
||||
<RowDefinition Height="25" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".2*" />
|
||||
<ColumnDefinition Width=".2*" />
|
||||
<ColumnDefinition Width=".2*" />
|
||||
<ColumnDefinition Width=".2*" />
|
||||
<ColumnDefinition Width=".2*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" FontSize="10" FontWeight="DemiBold" Text="{x:Static p:Resources.textShip}" VerticalAlignment="Center" Foreground="Gray" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="10" FontWeight="DemiBold" VerticalAlignment="Center" x:Name="textBlockShipcallType" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="2" FontSize="10" FontWeight="DemiBold" Text="{x:Static p:Resources.textTimestamp}" VerticalAlignment="Center" Foreground="Gray"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="3" FontSize="10" FontWeight="DemiBold" Text="{x:Static p:Resources.textOperation}" VerticalAlignment="Center" Foreground="Gray"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="4" FontSize="10" FontWeight="DemiBold" Text="{x:Static p:Resources.textParticipant}" VerticalAlignment="Center" Foreground="Gray"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" x:Name="textBlockShip" FontWeight="DemiBold">
|
||||
<Hyperlink Click="textBlockShip_Click">
|
||||
<TextBlock x:Name="hyperLinkShip" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" x:Name="textBlockEta" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" x:Name="textBlockTimestamp" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="3" x:Name="textBlockOperation" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="4" x:Name="textBlockParticipant" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
38
src/BreCalClient/HistoryControl.xaml.cs
Normal file
38
src/BreCalClient/HistoryControl.xaml.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2024- schick Informatik
|
||||
// Description: display single history element (later shown in a list)
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Model;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HistoryControl.xaml
|
||||
/// </summary>
|
||||
public partial class HistoryControl : UserControl
|
||||
{
|
||||
private readonly History _history;
|
||||
public event Action<int>? HistorySelected;
|
||||
|
||||
public HistoryControl(string ship, History history, string callType, string etaetd)
|
||||
{
|
||||
InitializeComponent();
|
||||
_history = history;
|
||||
this.textBlockOperation.Text = $"{history.Operation} on {history.Type}";
|
||||
this.hyperLinkShip.Text = ship;
|
||||
|
||||
if(BreCalLists.ParticipantLookupDict.ContainsKey(history.ParticipantId))
|
||||
this.textBlockParticipant.Text = BreCalLists.ParticipantLookupDict[history.ParticipantId].Name;
|
||||
this.textBlockTimestamp.Text = history.Timestamp.ToString();
|
||||
this.textBlockEta.Text = etaetd;
|
||||
this.textBlockShipcallType.Text = callType;
|
||||
}
|
||||
|
||||
private void textBlockShip_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
this.HistorySelected?.Invoke(_history.ShipcallId);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/BreCalClient/HistoryDialog.xaml
Normal file
32
src/BreCalClient/HistoryDialog.xaml
Normal file
@ -0,0 +1,32 @@
|
||||
<Window x:Class="BreCalClient.HistoryDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W4Left}" Top="{local:SettingBinding W4Top}"
|
||||
Title="{x:Static p:Resources.textChangeHistory}" Height="450" Width="800" Loaded="Window_Loaded">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" Margin="2">
|
||||
<StackPanel x:Name="stackPanel"/>
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="1" Grid.Column="0" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="22" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width=".2*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox x:Name="checkboxMyOwnOnly" VerticalContentAlignment="Center" Grid.Column="0" Margin="2" Checked="checkboxMyOwnOnly_Checked" Unchecked="checkboxMyOwnOnly_Checked" />
|
||||
<Label Content="{x:Static p:Resources.textMineOnly}" Grid.Column="1" />
|
||||
<Button x:Name="buttonClose" Click="buttonClose_Click" Content="{x:Static p:Resources.textClose}" Width="80" Margin="2" Grid.Row="0" Grid.Column="3" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
150
src/BreCalClient/HistoryDialog.xaml.cs
Normal file
150
src/BreCalClient/HistoryDialog.xaml.cs
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2024- schick Informatik
|
||||
// Description: Window to show (complete) list of current shipcall histories
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Api;
|
||||
using BreCalClient.misc.Model;
|
||||
using log4net;
|
||||
using log4net.Core;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Printing;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for HistoryDialog.xaml
|
||||
/// </summary>
|
||||
public partial class HistoryDialog : Window
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private readonly ConcurrentDictionary<int, ShipcallControlModel> _shipcalls;
|
||||
private readonly StaticApi _staticApi;
|
||||
private readonly static ILog _log = LogManager.GetLogger(typeof(HistoryDialog));
|
||||
|
||||
#endregion
|
||||
|
||||
#region delegate/event to react to history item selection
|
||||
|
||||
public event Action<int>? HistoryItemSelected;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
|
||||
public HistoryDialog(ConcurrentDictionary<int, ShipcallControlModel> shipcalls, StaticApi staticApi)
|
||||
{
|
||||
InitializeComponent();
|
||||
_shipcalls = shipcalls;
|
||||
_staticApi = staticApi;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region event handler
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
RefreshHistory();
|
||||
}
|
||||
|
||||
private void buttonClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void checkboxMyOwnOnly_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
RefreshHistory();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
|
||||
private async void RefreshHistory()
|
||||
{
|
||||
List<History> allHistories = new();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (int shipcall_id in _shipcalls.Keys)
|
||||
{
|
||||
List<History> shipcallHistory = await _staticApi.HistoryGetAsync(shipcall_id);
|
||||
System.Diagnostics.Trace.WriteLine($"{shipcallHistory.Count} history elements loaded for shipcall {shipcall_id}");
|
||||
allHistories.AddRange(shipcallHistory);
|
||||
}
|
||||
|
||||
this.stackPanel.Children.Clear();
|
||||
|
||||
// sort all entries
|
||||
allHistories.Sort((x, y) => { return y.Timestamp.CompareTo(x.Timestamp); });
|
||||
|
||||
EnumToStringConverter enumToStringConverter = new();
|
||||
|
||||
// create controls for all entries
|
||||
foreach (History history in allHistories)
|
||||
{
|
||||
if (FilterShipcall(history.ShipcallId)) continue;
|
||||
string shipname = "";
|
||||
Ship? ship = this._shipcalls[history.ShipcallId].Ship;
|
||||
if (ship != null)
|
||||
shipname = ship.Name;
|
||||
string etaetd = "", calltype = "";
|
||||
if (_shipcalls.ContainsKey(history.ShipcallId))
|
||||
{
|
||||
etaetd = _shipcalls[history.ShipcallId].GetETAETD();
|
||||
if (_shipcalls[history.ShipcallId].Shipcall != null)
|
||||
{
|
||||
ShipcallType? type = _shipcalls[history.ShipcallId].Shipcall?.Type;
|
||||
if (type != null) calltype = (string)(enumToStringConverter.Convert(type ?? ShipcallType.Undefined, typeof(ShipcallType), new(), System.Globalization.CultureInfo.CurrentCulture) ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
HistoryControl hc = new(shipname, history, calltype, etaetd);
|
||||
hc.HistorySelected += (x) => { HistoryItemSelected?.Invoke(x); }; // bubble event
|
||||
this.stackPanel.Children.Add(hc);
|
||||
}
|
||||
|
||||
Mouse.OverrideCursor = null;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Here we rather not show a dialog box since it may confuse the user
|
||||
_log.Error(e.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool FilterShipcall(int shipcallId)
|
||||
{
|
||||
bool result = true;
|
||||
if (shipcallId < 0) return result;
|
||||
if(_shipcalls.TryGetValue(shipcallId, out ShipcallControlModel? scm))
|
||||
{
|
||||
if(this.checkboxMyOwnOnly.IsChecked ?? false)
|
||||
{
|
||||
foreach(ParticipantAssignment p in scm.AssignedParticipants.Values)
|
||||
{
|
||||
if (p.ParticipantId.Equals(App.Participant.Id)) return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@ -13,15 +13,10 @@ namespace BreCalClient
|
||||
|
||||
string Title { get; set; }
|
||||
|
||||
Extensions.TypeEnum CallType { get; set; }
|
||||
ShipcallControlModel ShipcallModel { get; set; }
|
||||
|
||||
bool? ShowDialog();
|
||||
|
||||
}
|
||||
|
||||
internal interface IEditShipcallTimesControl : IEditTimesControl
|
||||
{
|
||||
ShipcallControlModel ShipcallModel { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -106,14 +106,19 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="100" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="120" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="100" />
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
@ -132,15 +137,30 @@
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="5"/>
|
||||
<StatusBarItem Grid.Column="6">
|
||||
<Button x:Name="buttonInfo" Content="?" Click="buttonInfo_Click" Width="20" />
|
||||
<Button x:Name="buttonInfo" Content="?" Click="buttonInfo_Click" Width="20" ToolTip="{x:Static p:Resources.textInfoChangePW}"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="7"/>
|
||||
<StatusBarItem Grid.Column="8">
|
||||
<TextBlock Name="labelStatusBar"></TextBlock>
|
||||
<Button x:Name="buttonHistory" Click="buttonHistory_Click" Width="20" ToolTip="{x:Static p:Resources.textShowHistory}">
|
||||
<Image Source="./Resources/clock.png"/>
|
||||
</Button>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="9"/>
|
||||
<StatusBarItem Grid.Column="10">
|
||||
<ProgressBar Name="generalProgressStatus" Width="90" Height="16"/>
|
||||
<TextBlock Name="labelStatusBar"></TextBlock>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="11"/>
|
||||
<StatusBarItem Grid.Column="12">
|
||||
<Button x:Name="buttonManualRefresh" Width="20" Click="buttonManualRefresh_Click" ToolTip="{x:Static p:Resources.textTriggerManualRefresh}">
|
||||
<Image Source="./Resources/nav_refresh_green.png"/>
|
||||
</Button>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="13">
|
||||
<TextBlock x:Name="labelLatestUpdate" />
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="14"/>
|
||||
<StatusBarItem Grid.Column="15">
|
||||
<ProgressBar Name="generalProgressStatus" Width="90" Height="16" Foreground="LightGray"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Description: Bremen calling main window
|
||||
//
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -18,11 +18,12 @@ using BreCalClient.misc.Model;
|
||||
using static BreCalClient.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
using Newtonsoft.Json;
|
||||
using System.Security.Principal;
|
||||
|
||||
using Polly;
|
||||
using System.Net.Http;
|
||||
using System.Net;
|
||||
using Polly.Retry;
|
||||
using System.Windows.Input;
|
||||
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
@ -32,20 +33,25 @@ namespace BreCalClient
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly ILog _log = LogManager.GetLogger(typeof(MainWindow));
|
||||
|
||||
private const int SHIPCALL_UPDATE_INTERVAL_SECONDS = 30;
|
||||
private const int PROGRESS_STEPS = 50;
|
||||
|
||||
#region Fields
|
||||
|
||||
private static Int32 _uiUpdateRunning = 0;
|
||||
private static int _uiUpdateRunning = 0;
|
||||
|
||||
private Credentials? _credentials;
|
||||
|
||||
private readonly ConcurrentDictionary<int, ShipcallControlModel> _allShipcallsDict = new();
|
||||
private readonly ConcurrentDictionary<int, ShipcallControl> _allShipCallsControlDict = new();
|
||||
private readonly List<ShipcallControlModel> _visibleControlModels = new();
|
||||
private readonly List<ShipcallControlModel> _visibleControlModels = new();
|
||||
|
||||
private readonly ShipcallApi _shipcallApi;
|
||||
private readonly UserApi _userApi;
|
||||
private readonly TimesApi _timesApi;
|
||||
private readonly StaticApi _staticApi;
|
||||
private readonly ShipApi _shipApi;
|
||||
|
||||
private readonly DefaultApi _api;
|
||||
private CancellationTokenSource _tokenSource = new();
|
||||
private LoginResult? _loginResult;
|
||||
private bool _refreshImmediately = false;
|
||||
@ -56,6 +62,7 @@ namespace BreCalClient
|
||||
|
||||
// private bool _filterChanged = false;
|
||||
// private bool _sequenceChanged = false;
|
||||
private HistoryDialog? _historyDialog;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -75,8 +82,16 @@ namespace BreCalClient
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
_api = new DefaultApi(Properties.Settings.Default.API_URL);
|
||||
_api.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
_userApi = new UserApi(Properties.Settings.Default.API_URL);
|
||||
_userApi.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
_shipcallApi = new ShipcallApi(Properties.Settings.Default.API_URL);
|
||||
_shipcallApi.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
_timesApi = new TimesApi(Properties.Settings.Default.API_URL);
|
||||
_timesApi.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
_staticApi = new StaticApi(Properties.Settings.Default.API_URL);
|
||||
_staticApi.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
_shipApi = new ShipApi(Properties.Settings.Default.API_URL);
|
||||
_shipApi.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
|
||||
|
||||
const int maxDelayInMilliseconds = 32 * 1000;
|
||||
var jitterer = new Random();
|
||||
@ -95,10 +110,11 @@ namespace BreCalClient
|
||||
},
|
||||
onRetry: (resp, timespan, context) =>
|
||||
{
|
||||
this.RefreshToken(null);
|
||||
this.RefreshToken();
|
||||
Trace.WriteLine("token refreshed");
|
||||
});
|
||||
RetryConfiguration.AsyncRetryPolicy = retryPolicy;
|
||||
this.generalProgressStatus.Maximum = PROGRESS_STEPS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -111,14 +127,14 @@ namespace BreCalClient
|
||||
labelVersion.Text = "V. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
if (!string.IsNullOrEmpty(Properties.Settings.Default.APP_TITLE))
|
||||
this.Title = Properties.Settings.Default.APP_TITLE;
|
||||
searchFilterControl.SearchFilterChanged += SearchFilterControl_SearchFilterChanged;
|
||||
searchFilterControl.SearchFilterChanged += SearchFilterControl_SearchFilterChanged;
|
||||
searchFilterControl.LogoImageClicked += () =>
|
||||
{
|
||||
Process.Start("explorer", Properties.Settings.Default.LOGO_IMAGE_URL);
|
||||
Process.Start("explorer", Properties.Settings.Default.LOGO_IMAGE_URL);
|
||||
};
|
||||
this.comboBoxSortOrder.ItemsSource = Enum.GetValues(typeof(Extensions.SortOrder));
|
||||
this.comboBoxSortOrder.SelectedIndex = (int)_sortOrder;
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
@ -140,13 +156,18 @@ namespace BreCalClient
|
||||
|
||||
try
|
||||
{
|
||||
_loginResult = await _api.LoginPostAsync(_credentials);
|
||||
_loginResult = await _userApi.LoginAsync(_credentials);
|
||||
if (_loginResult != null)
|
||||
{
|
||||
if (_loginResult.Id > 0)
|
||||
{
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
this.busyIndicator.IsBusy = false;
|
||||
this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._userApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._shipcallApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._timesApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._staticApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._shipApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this.LoadStaticLists();
|
||||
this.labelUsername.Text = $"{_loginResult.FirstName} {_loginResult.LastName}";
|
||||
}
|
||||
@ -174,17 +195,21 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
private bool RefreshToken(object? state)
|
||||
private bool RefreshToken()
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
_loginResult = _api.LoginPost(_credentials);
|
||||
_loginResult = _userApi.Login(_credentials);
|
||||
if (_loginResult != null)
|
||||
{
|
||||
if (_loginResult.Id > 0)
|
||||
{
|
||||
this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
{
|
||||
this._userApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._timesApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._shipcallApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._staticApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
this._shipApi.Configuration.ApiKey["Authorization"] = _loginResult.Token;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@ -207,12 +232,16 @@ namespace BreCalClient
|
||||
|
||||
private void buttonNew_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
NewWithModel(null);
|
||||
NewWithModel(null);
|
||||
}
|
||||
|
||||
private void NewWithModel(ShipcallControlModel? model)
|
||||
{
|
||||
EditShipcallControl esc = new();
|
||||
EditShipcallControl esc = new()
|
||||
{
|
||||
ShipEditingEnabled = App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD),
|
||||
ShipApi = _shipApi
|
||||
};
|
||||
if (model != null)
|
||||
esc.ShipcallModel = model;
|
||||
|
||||
@ -228,7 +257,7 @@ namespace BreCalClient
|
||||
esc.ShipcallModel.Shipcall?.Participants.Add(pa);
|
||||
try
|
||||
{
|
||||
this._api.ShipcallsPost(esc.ShipcallModel.Shipcall); // save new ship call
|
||||
this._shipcallApi.ShipcallCreate(esc.ShipcallModel.Shipcall); // save new ship call
|
||||
this.AddShipcall(esc.ShipcallModel);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -240,11 +269,15 @@ namespace BreCalClient
|
||||
_tokenSource.Cancel(); // force timer loop end
|
||||
|
||||
// if this was an arrival, create the matching departure call and open it
|
||||
if (esc.ShipcallModel.Shipcall?.Type == (int)Extensions.TypeEnum.Incoming)
|
||||
if (esc.ShipcallModel.Shipcall?.Type == ShipcallType.Arrival)
|
||||
{
|
||||
ShipcallControlModel scmOut = new();
|
||||
scmOut.Shipcall = new();
|
||||
scmOut.Shipcall.Type = (int)Extensions.TypeEnum.Outgoing;
|
||||
ShipcallControlModel scmOut = new()
|
||||
{
|
||||
Shipcall = new()
|
||||
{
|
||||
Type = ShipcallType.Departure
|
||||
}
|
||||
};
|
||||
scmOut.Shipcall.ShipId = esc.ShipcallModel.Shipcall.ShipId;
|
||||
scmOut.Ship = esc.ShipcallModel.Ship;
|
||||
DateTime eta = esc.ShipcallModel.Shipcall?.Eta ?? DateTime.Now;
|
||||
@ -257,7 +290,11 @@ namespace BreCalClient
|
||||
foreach(ParticipantType pType in esc.ShipcallModel.AssignedParticipants.Keys)
|
||||
scmOut.AssignedParticipants[pType] = esc.ShipcallModel.AssignedParticipants[pType];
|
||||
}
|
||||
NewWithModel(scmOut);
|
||||
|
||||
this.Dispatcher.Invoke(() =>
|
||||
{
|
||||
NewWithModel(scmOut);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,8 +302,10 @@ namespace BreCalClient
|
||||
|
||||
private void buttonInfo_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AboutDialog ad = new();
|
||||
ad.LoginResult = this._loginResult;
|
||||
AboutDialog ad = new()
|
||||
{
|
||||
LoginResult = this._loginResult
|
||||
};
|
||||
ad.ChangePasswordRequested += async (oldPw, newPw) =>
|
||||
{
|
||||
if (_loginResult != null)
|
||||
@ -283,7 +322,7 @@ namespace BreCalClient
|
||||
};
|
||||
try
|
||||
{
|
||||
await _api.UserPutAsync(ud);
|
||||
await _userApi.UserUpdateAsync(ud);
|
||||
MessageBox.Show(BreCalClient.Resources.Resources.textPasswordChanged, BreCalClient.Resources.Resources.textConfirmation, MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -324,25 +363,51 @@ namespace BreCalClient
|
||||
this.UpdateUI();
|
||||
}
|
||||
|
||||
#endregion
|
||||
private void buttonHistory_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(_historyDialog == null)
|
||||
{
|
||||
_historyDialog = new HistoryDialog(_allShipcallsDict, _staticApi);
|
||||
_historyDialog.Closed += (sender, e) => { this._historyDialog = null; };
|
||||
_historyDialog.HistoryItemSelected += (x) =>
|
||||
{
|
||||
if(_allShipCallsControlDict.ContainsKey(x))
|
||||
_allShipCallsControlDict[x].BringIntoView();
|
||||
};
|
||||
_historyDialog.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
_historyDialog.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonManualRefresh_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_refreshImmediately = true; // set flag to avoid timer loop termination
|
||||
_tokenSource.Cancel(); // force timer loop end
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region network operations
|
||||
|
||||
private async void LoadStaticLists()
|
||||
{
|
||||
BreCalLists.InitializeBerths(await _api.BerthsGetAsync());
|
||||
BreCalLists.InitializeShips(await _api.ShipsGetAsync());
|
||||
BreCalLists.InitializeParticipants(await _api.ParticipantsGetAsync());
|
||||
BreCalLists.InitializeBerths(await _staticApi.BerthsGetAsync());
|
||||
BreCalLists.InitializeShips(await _shipApi.ShipsGetAsync());
|
||||
BreCalLists.InitializeParticipants(await _staticApi.ParticipantsGetAsync());
|
||||
|
||||
this.searchFilterControl.SetBerths(BreCalLists.Berths);
|
||||
|
||||
|
||||
foreach (Participant participant in BreCalLists.Participants)
|
||||
{
|
||||
{
|
||||
if (_loginResult?.ParticipantId == participant.Id)
|
||||
{
|
||||
App.Participant = participant;
|
||||
EnableControlsForParticipant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.searchFilterControl.SetAgencies(BreCalLists.Participants_Agent);
|
||||
@ -355,7 +420,7 @@ namespace BreCalClient
|
||||
}
|
||||
|
||||
_ = Task.Run(() => RefreshShipcalls());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshShipcalls()
|
||||
{
|
||||
@ -372,18 +437,19 @@ namespace BreCalClient
|
||||
try
|
||||
{
|
||||
if(this.searchPastDays != 0)
|
||||
shipcalls = await _api.ShipcallsGetAsync(this.searchPastDays);
|
||||
shipcalls = await _shipcallApi.ShipcallsGetAsync(this.searchPastDays);
|
||||
else
|
||||
shipcalls = await _api.ShipcallsGetAsync();
|
||||
shipcalls = await _shipcallApi.ShipcallsGetAsync();
|
||||
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
labelGeneralStatus.Text = $"Connection {ConnectionStatus.SUCCESSFUL}";
|
||||
labelGeneralStatus.Text = $"Ok";
|
||||
labelGeneralStatus.Text = $"Connection {ConnectionStatus.SUCCESSFUL}";
|
||||
labelLatestUpdate.Text = $"Last update: {DateTime.Now.ToLongTimeString()}";
|
||||
generalProgressStatus.Value = 0;
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
{
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
labelGeneralStatus.Text = $"Connection {ConnectionStatus.FAILED}";
|
||||
@ -392,7 +458,7 @@ namespace BreCalClient
|
||||
|
||||
if (ex.Message.Contains("access", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.RefreshToken(null);
|
||||
this.RefreshToken();
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +467,7 @@ namespace BreCalClient
|
||||
foreach (Shipcall shipcall in shipcalls)
|
||||
{
|
||||
// load times for each shipcall
|
||||
List<Times> currentTimes = await _api.TimesGetAsync(shipcall.Id);
|
||||
List<Times> currentTimes = await _timesApi.TimesGetAsync(shipcall.Id);
|
||||
|
||||
if(!_allShipcallsDict.ContainsKey(shipcall.Id))
|
||||
{
|
||||
@ -410,7 +476,7 @@ namespace BreCalClient
|
||||
{
|
||||
Shipcall = shipcall,
|
||||
Times = currentTimes
|
||||
};
|
||||
};
|
||||
this.AddShipcall(scm);
|
||||
}
|
||||
else
|
||||
@ -419,8 +485,8 @@ namespace BreCalClient
|
||||
_allShipcallsDict[shipcall.Id].Shipcall = shipcall;
|
||||
_allShipcallsDict[shipcall.Id].Times = currentTimes;
|
||||
UpdateShipcall(_allShipcallsDict[shipcall.Id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<int> existingIds = new(this._allShipcallsDict.Keys);
|
||||
|
||||
@ -433,12 +499,20 @@ namespace BreCalClient
|
||||
}
|
||||
|
||||
this.FilterShipcalls();
|
||||
this.UpdateUI();
|
||||
this.UpdateUI();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(SHIPCALL_UPDATE_INTERVAL_SECONDS), _tokenSource.Token);
|
||||
double interval = (double) SHIPCALL_UPDATE_INTERVAL_SECONDS / PROGRESS_STEPS;
|
||||
for (int i = 0; i < PROGRESS_STEPS; i++)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(interval), _tokenSource.Token);
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
this.generalProgressStatus.Value = i;
|
||||
}));
|
||||
}
|
||||
}
|
||||
catch(TaskCanceledException) { }
|
||||
}
|
||||
@ -456,7 +530,8 @@ namespace BreCalClient
|
||||
Shipcall shipcall = scm.Shipcall;
|
||||
if (BreCalLists.ShipLookupDict.ContainsKey(shipcall.ShipId))
|
||||
scm.Ship = BreCalLists.ShipLookupDict[shipcall.ShipId].Ship;
|
||||
if (shipcall.Type == 1)
|
||||
|
||||
if (shipcall.Type == ShipcallType.Arrival)
|
||||
{
|
||||
if (BreCalLists.BerthLookupDict.ContainsKey(shipcall.ArrivalBerthId ?? 0))
|
||||
scm.Berth = BreCalLists.BerthLookupDict[shipcall.ArrivalBerthId ?? 0].Name;
|
||||
@ -472,8 +547,8 @@ namespace BreCalClient
|
||||
{
|
||||
ShipcallControl sc = new()
|
||||
{
|
||||
Height = 120,
|
||||
ShipcallControlModel = scm
|
||||
Height = 135,
|
||||
ShipcallControlModel = scm
|
||||
};
|
||||
sc.EditTimesRequested += Sc_EditTimesRequested;
|
||||
sc.EditRequested += Sc_EditRequested;
|
||||
@ -481,7 +556,7 @@ namespace BreCalClient
|
||||
sc.RefreshData();
|
||||
this._allShipCallsControlDict[scm.Shipcall.Id] = sc;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateShipcall(ShipcallControlModel scm)
|
||||
{
|
||||
@ -489,7 +564,8 @@ namespace BreCalClient
|
||||
Shipcall shipcall = scm.Shipcall;
|
||||
if (BreCalLists.ShipLookupDict.ContainsKey(shipcall.ShipId))
|
||||
scm.Ship = BreCalLists.ShipLookupDict[shipcall.ShipId].Ship;
|
||||
if (shipcall.Type == 1)
|
||||
|
||||
if (shipcall.Type == ShipcallType.Arrival)
|
||||
{
|
||||
if (BreCalLists.BerthLookupDict.ContainsKey(shipcall.ArrivalBerthId ?? 0))
|
||||
scm.Berth = BreCalLists.BerthLookupDict[shipcall.ArrivalBerthId ?? 0].Name;
|
||||
@ -513,7 +589,7 @@ namespace BreCalClient
|
||||
_visibleControlModels.Remove(removeModel);
|
||||
|
||||
this._allShipCallsControlDict.Remove(shipcallId, out _);
|
||||
this._allShipcallsDict.Remove(shipcallId, out _);
|
||||
this._allShipcallsDict.Remove(shipcallId, out _);
|
||||
}
|
||||
|
||||
private void FilterShipcalls()
|
||||
@ -533,6 +609,8 @@ namespace BreCalClient
|
||||
else
|
||||
{
|
||||
searchPastDays = 0;
|
||||
if (sfm.EtaFrom == null)
|
||||
sfm.EtaFrom = DateTime.Now.AddDays(-2);
|
||||
}
|
||||
|
||||
this._visibleControlModels.Clear();
|
||||
@ -543,8 +621,8 @@ namespace BreCalClient
|
||||
|
||||
if(sfm.Berths.Count > 0 )
|
||||
{
|
||||
this._visibleControlModels.RemoveAll(x => (!sfm.Berths.Contains((x.Shipcall?.ArrivalBerthId) ?? -1) && (x.Shipcall?.Type == (int) Extensions.TypeEnum.Incoming)) ||
|
||||
(!sfm.Berths.Contains((x.Shipcall?.DepartureBerthId) ?? -1) && (x.Shipcall?.Type != (int) Extensions.TypeEnum.Incoming)));
|
||||
this._visibleControlModels.RemoveAll(x => (!sfm.Berths.Contains((x.Shipcall?.ArrivalBerthId) ?? -1) && (x.Shipcall?.Type == ShipcallType.Arrival)) ||
|
||||
(!sfm.Berths.Contains((x.Shipcall?.DepartureBerthId) ?? -1) && (x.Shipcall?.Type != ShipcallType.Arrival)));
|
||||
}
|
||||
|
||||
if(sfm.Agencies.Count > 0 )
|
||||
@ -557,12 +635,12 @@ namespace BreCalClient
|
||||
return !sfm.Agencies.Contains(agency.Id);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if(sfm.Categories.Count > 0 )
|
||||
{
|
||||
_ = this._visibleControlModels.RemoveAll(x => !sfm.Categories.Contains((x.Shipcall?.Type) ?? -1));
|
||||
_ = this._visibleControlModels.RemoveAll(x => { if (x.Shipcall == null) return false; else return !sfm.Categories.Contains(x.Shipcall.Type); });
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(sfm.SearchString))
|
||||
@ -582,40 +660,95 @@ namespace BreCalClient
|
||||
|
||||
if(sfm.EtaFrom != null)
|
||||
{
|
||||
_ = this._visibleControlModels.RemoveAll(x => x.Shipcall?.Eta < sfm.EtaFrom);
|
||||
_ = this._visibleControlModels.RemoveAll(x =>
|
||||
{
|
||||
Times? t = x.GetTimesForParticipantType(ParticipantType.AGENCY);
|
||||
switch (x.Shipcall?.Type)
|
||||
{
|
||||
case ShipcallType.Arrival:
|
||||
{
|
||||
if ((t != null) && t.EtaBerth.HasValue) return t.EtaBerth.Value < sfm.EtaFrom;
|
||||
return x.Shipcall?.Eta < sfm.EtaFrom;
|
||||
}
|
||||
default: // Shifting / Departing
|
||||
{
|
||||
if ((t != null) && t.EtdBerth.HasValue) return t.EtdBerth.Value < sfm.EtaFrom;
|
||||
return x.Shipcall?.Etd < sfm.EtaFrom;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(sfm.EtaTo != null)
|
||||
{
|
||||
_ = this._visibleControlModels.RemoveAll(x => x.Shipcall?.Eta > sfm.EtaTo);
|
||||
_ = this._visibleControlModels.RemoveAll(x =>
|
||||
{
|
||||
Times? t = x.GetTimesForParticipantType(ParticipantType.AGENCY);
|
||||
DateTime refValue = sfm.EtaTo.Value.AddMinutes(1439); // 23:59
|
||||
switch (x.Shipcall?.Type)
|
||||
{
|
||||
case ShipcallType.Arrival:
|
||||
{
|
||||
if ((t != null) && t.EtaBerth.HasValue) return t.EtaBerth.Value > refValue;
|
||||
return x.Shipcall?.Eta > refValue;
|
||||
}
|
||||
default: // Shifting / Departing
|
||||
{
|
||||
if ((t != null) && t.EtdBerth.HasValue) return t.EtdBerth.Value > refValue;
|
||||
return x.Shipcall?.Etd > refValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(sfm.MineOnly ?? false)
|
||||
{
|
||||
_ = _visibleControlModels.RemoveAll(x =>
|
||||
{
|
||||
bool contained = false;
|
||||
foreach(ParticipantAssignment p in x.AssignedParticipants.Values)
|
||||
{
|
||||
if(p.ParticipantId.Equals(App.Participant.Id))
|
||||
{
|
||||
contained = true; break;
|
||||
}
|
||||
}
|
||||
return !contained;
|
||||
});
|
||||
}
|
||||
|
||||
if(!_showCanceled ?? true) // canceled calls are filtered by default
|
||||
{
|
||||
_ = this._visibleControlModels.RemoveAll(x => x.Shipcall?.Canceled ?? false);
|
||||
}
|
||||
|
||||
|
||||
switch(this._sortOrder)
|
||||
{
|
||||
case Extensions.SortOrder.SHIP_NAME:
|
||||
this._visibleControlModels.Sort((x, y) => { if (x.Ship == null) return 0; if (y.Ship == null) return 0; return x.Ship.Name.CompareTo(y.Ship.Name); });
|
||||
this._visibleControlModels.Sort((x, y) => { if (x.Ship == null) return 0; if (y.Ship == null) return 0; return x.Ship.Name.CompareTo(y.Ship.Name); });
|
||||
break;
|
||||
case Extensions.SortOrder.MODIFIED:
|
||||
this._visibleControlModels.Sort((x, y) => { if (x.Shipcall == null) return 0; if (y.Shipcall == null) return 0; return DateTime.Compare(x.Shipcall.Modified ?? x.Shipcall.Created, y.Shipcall.Modified ?? x.Shipcall.Created); });
|
||||
break;
|
||||
case Extensions.SortOrder.ETA_ETD:
|
||||
this._visibleControlModels.Sort((x, y) =>
|
||||
{
|
||||
{
|
||||
if (x.Shipcall == null) return 0;
|
||||
if (y.Shipcall == null) return 0;
|
||||
DateTime xDate = (x.Shipcall.Type == (int) Extensions.TypeEnum.Incoming) ? x.Eta ?? DateTime.Now : x.Etd ?? DateTime.Now;
|
||||
DateTime yDate = (y.Shipcall.Type == (int) Extensions.TypeEnum.Incoming) ? y.Eta ?? DateTime.Now : y.Etd ?? DateTime.Now;
|
||||
DateTime xDate = (x.Shipcall.Type == ShipcallType.Arrival) ? x.Eta ?? DateTime.Now : x.Etd ?? DateTime.Now;
|
||||
Times? xTimes = x.GetTimesForParticipantType(ParticipantType.AGENCY);
|
||||
if(xTimes != null)
|
||||
xDate = (x.Shipcall.Type == ShipcallType.Arrival) ? xTimes.EtaBerth ?? DateTime.Now : xTimes.EtdBerth ?? DateTime.Now;
|
||||
DateTime yDate = (y.Shipcall.Type == ShipcallType.Arrival) ? y.Eta ?? DateTime.Now : y.Etd ?? DateTime.Now;
|
||||
Times? yTimes = y.GetTimesForParticipantType(ParticipantType.AGENCY);
|
||||
if (yTimes != null)
|
||||
yDate = (y.Shipcall.Type == ShipcallType.Arrival) ? yTimes.EtaBerth ?? DateTime.Now : yTimes.EtdBerth ?? DateTime.Now;
|
||||
return DateTime.Compare(xDate, yDate);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -652,6 +785,7 @@ namespace BreCalClient
|
||||
_uiUpdateRunning = 0;
|
||||
}
|
||||
|
||||
Mouse.OverrideCursor = null;
|
||||
}));
|
||||
}
|
||||
|
||||
@ -660,12 +794,14 @@ namespace BreCalClient
|
||||
#region control event handler
|
||||
|
||||
private async void Sc_EditRequested(ShipcallControl obj)
|
||||
{
|
||||
{
|
||||
if (obj.ShipcallControlModel != null)
|
||||
{
|
||||
EditShipcallControl esc = new()
|
||||
{
|
||||
ShipcallModel = obj.ShipcallControlModel
|
||||
ShipcallModel = obj.ShipcallControlModel,
|
||||
ShipApi = _shipApi,
|
||||
ShipEditingEnabled = App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD)
|
||||
};
|
||||
|
||||
if(esc.ShowDialog() ?? false)
|
||||
@ -673,10 +809,10 @@ namespace BreCalClient
|
||||
try
|
||||
{
|
||||
obj.ShipcallControlModel.Shipcall?.Participants.Clear();
|
||||
obj.ShipcallControlModel.UpdateTimesAssignments(this._api);
|
||||
obj.ShipcallControlModel.UpdateTimesAssignments(this._timesApi);
|
||||
foreach(ParticipantAssignment pa in obj.ShipcallControlModel.AssignedParticipants.Values)
|
||||
obj.ShipcallControlModel.Shipcall?.Participants.Add(pa);
|
||||
await _api.ShipcallsPutAsync(obj.ShipcallControlModel.Shipcall);
|
||||
await _shipcallApi.ShipcallUpdateAsync(obj.ShipcallControlModel.Shipcall);
|
||||
obj.RefreshData();
|
||||
_refreshImmediately = true;
|
||||
_tokenSource.Cancel();
|
||||
@ -689,7 +825,7 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
private async void Sc_EditTimesRequested(ShipcallControl obj, Times? times, Extensions.ParticipantType participantType)
|
||||
private async void Sc_EditTimesRequested(ShipcallControl obj, Times? times, ParticipantType participantType)
|
||||
{
|
||||
|
||||
if( obj.ShipcallControlModel == null) { return; }
|
||||
@ -698,15 +834,13 @@ namespace BreCalClient
|
||||
// show a dialog that lets the user create / update times for the given shipcall
|
||||
IEditTimesControl etc = (participantType == ParticipantType.TERMINAL) ? new EditTimesTerminalControl() : new EditTimesControl();
|
||||
etc.Title = obj.ShipcallControlModel.Title;
|
||||
|
||||
if(obj.ShipcallControlModel.Shipcall != null)
|
||||
etc.CallType = (TypeEnum) obj.ShipcallControlModel.Shipcall.Type;
|
||||
etc.ShipcallModel = obj.ShipcallControlModel;
|
||||
|
||||
bool wasEdit = false;
|
||||
if (times != null)
|
||||
{
|
||||
etc.Times = times;
|
||||
wasEdit = true;
|
||||
wasEdit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -725,7 +859,7 @@ namespace BreCalClient
|
||||
{
|
||||
if (wasEdit)
|
||||
{
|
||||
await _api.TimesPutAsync(etc.Times);
|
||||
await _timesApi.TimesUpdateAsync(etc.Times);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -734,7 +868,7 @@ namespace BreCalClient
|
||||
{
|
||||
etc.Times.ShipcallId = obj.ShipcallControlModel.Shipcall.Id;
|
||||
}
|
||||
Id apiResultId = await _api.TimesPostAsync(etc.Times);
|
||||
Id apiResultId = await _timesApi.TimesCreateAsync(etc.Times);
|
||||
etc.Times.Id = apiResultId.VarId;
|
||||
obj.ShipcallControlModel?.Times.Add(etc.Times);
|
||||
}
|
||||
@ -750,16 +884,16 @@ namespace BreCalClient
|
||||
|
||||
private async void Sc_EditAgencyRequested(ShipcallControl sc, Times? times)
|
||||
{
|
||||
IEditShipcallTimesControl? editControl = null;
|
||||
IEditTimesControl? editControl = null;
|
||||
switch(sc.ShipcallControlModel?.Shipcall?.Type)
|
||||
{
|
||||
case (int)TypeEnum.Incoming:
|
||||
case ShipcallType.Arrival:
|
||||
editControl = new EditTimesAgencyIncomingControl();
|
||||
break;
|
||||
case (int)TypeEnum.Outgoing:
|
||||
case ShipcallType.Departure:
|
||||
editControl = new EditTimesAgencyOutgoingControl();
|
||||
break;
|
||||
case (int)TypeEnum.Shifting:
|
||||
case ShipcallType.Shifting:
|
||||
editControl = new EditTimesAgencyShiftingControl();
|
||||
break;
|
||||
}
|
||||
@ -772,7 +906,7 @@ namespace BreCalClient
|
||||
{
|
||||
editControl.Times = times;
|
||||
wasEdit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(editControl.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.AGENCY))
|
||||
@ -783,7 +917,7 @@ namespace BreCalClient
|
||||
{
|
||||
try
|
||||
{
|
||||
sc.ShipcallControlModel?.UpdateTimesAssignments(_api); // if the agent changed the assignment of the participant to another
|
||||
sc.ShipcallControlModel?.UpdateTimesAssignments(_timesApi); // if the agent changed the assignment of the participant to another
|
||||
|
||||
// always try to be the agent, even if we are BSMD
|
||||
if (editControl.ShipcallModel.AssignedParticipants.ContainsKey(ParticipantType.AGENCY))
|
||||
@ -797,15 +931,15 @@ namespace BreCalClient
|
||||
|
||||
if (wasEdit)
|
||||
{
|
||||
await _api.TimesPutAsync(editControl.Times);
|
||||
await _timesApi.TimesUpdateAsync(editControl.Times);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
if ((sc.ShipcallControlModel != null) && (sc.ShipcallControlModel.Shipcall != null))
|
||||
{
|
||||
editControl.Times.ShipcallId = sc.ShipcallControlModel.Shipcall.Id;
|
||||
}
|
||||
Id resultAPI_Id = await _api.TimesPostAsync(editControl.Times);
|
||||
Id resultAPI_Id = await _timesApi.TimesCreateAsync(editControl.Times);
|
||||
editControl.Times.Id = resultAPI_Id.VarId;
|
||||
|
||||
sc.ShipcallControlModel?.Times.Add(editControl.Times);
|
||||
@ -813,7 +947,7 @@ namespace BreCalClient
|
||||
editControl.ShipcallModel.Shipcall?.Participants.Clear();
|
||||
foreach (ParticipantAssignment pa in editControl.ShipcallModel.AssignedParticipants.Values)
|
||||
editControl.ShipcallModel.Shipcall?.Participants.Add(pa);
|
||||
await _api.ShipcallsPutAsync(editControl.ShipcallModel.Shipcall);
|
||||
await _shipcallApi.ShipcallUpdateAsync(editControl.ShipcallModel.Shipcall);
|
||||
_refreshImmediately = true;
|
||||
_tokenSource.Cancel();
|
||||
}
|
||||
@ -846,7 +980,7 @@ namespace BreCalClient
|
||||
if (App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD))
|
||||
this.buttonNew.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
|
||||
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
|
||||
@ -854,6 +988,6 @@ namespace BreCalClient
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.1.3.0</ApplicationVersion>
|
||||
<ApplicationRevision>1</ApplicationRevision>
|
||||
<ApplicationVersion>1.2.0.2</ApplicationVersion>
|
||||
<BootstrapperEnabled>True</BootstrapperEnabled>
|
||||
<Configuration>Debug</Configuration>
|
||||
<CreateDesktopShortcut>True</CreateDesktopShortcut>
|
||||
|
||||
@ -4,8 +4,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.1.6.0</ApplicationVersion>
|
||||
<ApplicationRevision>10</ApplicationRevision>
|
||||
<ApplicationVersion>1.2.0.10</ApplicationVersion>
|
||||
<BootstrapperEnabled>False</BootstrapperEnabled>
|
||||
<Configuration>Release</Configuration>
|
||||
<CreateWebPageOnPublish>True</CreateWebPageOnPublish>
|
||||
|
||||
@ -4,8 +4,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.1.6.*</ApplicationVersion>
|
||||
<ApplicationRevision>2</ApplicationRevision>
|
||||
<ApplicationVersion>1.2.0.10</ApplicationVersion>
|
||||
<BootstrapperEnabled>True</BootstrapperEnabled>
|
||||
<Configuration>Debug</Configuration>
|
||||
<CreateDesktopShortcut>True</CreateDesktopShortcut>
|
||||
|
||||
72
src/BreCalClient/Properties/Settings.Designer.cs
generated
72
src/BreCalClient/Properties/Settings.Designer.cs
generated
@ -142,5 +142,77 @@ namespace BreCalClient.Properties {
|
||||
this["W1Top"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W2Left {
|
||||
get {
|
||||
return ((double)(this["W2Left"]));
|
||||
}
|
||||
set {
|
||||
this["W2Left"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W2Top {
|
||||
get {
|
||||
return ((double)(this["W2Top"]));
|
||||
}
|
||||
set {
|
||||
this["W2Top"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W3Left {
|
||||
get {
|
||||
return ((double)(this["W3Left"]));
|
||||
}
|
||||
set {
|
||||
this["W3Left"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W3Top {
|
||||
get {
|
||||
return ((double)(this["W3Top"]));
|
||||
}
|
||||
set {
|
||||
this["W3Top"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W4Left {
|
||||
get {
|
||||
return ((double)(this["W4Left"]));
|
||||
}
|
||||
set {
|
||||
this["W4Left"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public double W4Top {
|
||||
get {
|
||||
return ((double)(this["W4Top"]));
|
||||
}
|
||||
set {
|
||||
this["W4Top"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,5 +35,23 @@
|
||||
<Setting Name="W1Top" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W2Left" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W2Top" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W3Left" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W3Top" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W4Left" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
<Setting Name="W4Top" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
257
src/BreCalClient/Resources/Resources.Designer.cs
generated
257
src/BreCalClient/Resources/Resources.Designer.cs
generated
@ -60,6 +60,35 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] _lock {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("_lock", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] add {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("add", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Incoming.
|
||||
/// </summary>
|
||||
public static string Arrival {
|
||||
get {
|
||||
return ResourceManager.GetString("Arrival", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
@ -180,6 +209,25 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Outgoing.
|
||||
/// </summary>
|
||||
public static string Departure {
|
||||
get {
|
||||
return ResourceManager.GetString("Departure", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] edit {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("edit", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
@ -190,6 +238,16 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] lock_open {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("lock_open", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
@ -200,6 +258,25 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] nav_refresh_green {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("nav_refresh_green", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shifting.
|
||||
/// </summary>
|
||||
public static string Shifting {
|
||||
get {
|
||||
return ResourceManager.GetString("Shifting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
@ -220,6 +297,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Add.
|
||||
/// </summary>
|
||||
public static string textAdd {
|
||||
get {
|
||||
return ResourceManager.GetString("textAdd", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Agencies.
|
||||
/// </summary>
|
||||
@ -355,6 +441,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Change history.
|
||||
/// </summary>
|
||||
public static string textChangeHistory {
|
||||
get {
|
||||
return ResourceManager.GetString("textChangeHistory", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Change password.
|
||||
/// </summary>
|
||||
@ -409,6 +504,24 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Delete.
|
||||
/// </summary>
|
||||
public static string textDelete {
|
||||
get {
|
||||
return ResourceManager.GetString("textDelete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deleted.
|
||||
/// </summary>
|
||||
public static string textDeleted {
|
||||
get {
|
||||
return ResourceManager.GetString("textDeleted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Departure terminal.
|
||||
/// </summary>
|
||||
@ -427,6 +540,24 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit.
|
||||
/// </summary>
|
||||
public static string textEdit {
|
||||
get {
|
||||
return ResourceManager.GetString("textEdit", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit ship.
|
||||
/// </summary>
|
||||
public static string textEditShip {
|
||||
get {
|
||||
return ResourceManager.GetString("textEditShip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit ship call.
|
||||
/// </summary>
|
||||
@ -436,6 +567,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit ships.
|
||||
/// </summary>
|
||||
public static string textEditShips {
|
||||
get {
|
||||
return ResourceManager.GetString("textEditShips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit times.
|
||||
/// </summary>
|
||||
@ -499,6 +639,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Marked as a fixed order.
|
||||
/// </summary>
|
||||
public static string textFixedOrder {
|
||||
get {
|
||||
return ResourceManager.GetString("textFixedOrder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to from.
|
||||
/// </summary>
|
||||
@ -517,6 +666,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show app info and change user password.
|
||||
/// </summary>
|
||||
public static string textInfoChangePW {
|
||||
get {
|
||||
return ResourceManager.GetString("textInfoChangePW", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Interval.
|
||||
/// </summary>
|
||||
@ -562,6 +720,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to mine only.
|
||||
/// </summary>
|
||||
public static string textMineOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("textMineOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Moored in lock.
|
||||
/// </summary>
|
||||
@ -625,6 +792,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Operation.
|
||||
/// </summary>
|
||||
public static string textOperation {
|
||||
get {
|
||||
return ResourceManager.GetString("textOperation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Operations end.
|
||||
/// </summary>
|
||||
@ -652,6 +828,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Participant.
|
||||
/// </summary>
|
||||
public static string textParticipant {
|
||||
get {
|
||||
return ResourceManager.GetString("textParticipant", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Participants.
|
||||
/// </summary>
|
||||
@ -841,6 +1026,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Ships.
|
||||
/// </summary>
|
||||
public static string textShips {
|
||||
get {
|
||||
return ResourceManager.GetString("textShips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show cancelled calls.
|
||||
/// </summary>
|
||||
@ -850,6 +1044,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show shipcall change history.
|
||||
/// </summary>
|
||||
public static string textShowHistory {
|
||||
get {
|
||||
return ResourceManager.GetString("textShowHistory", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sort order.
|
||||
/// </summary>
|
||||
@ -886,6 +1089,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Timestamp.
|
||||
/// </summary>
|
||||
public static string textTimestamp {
|
||||
get {
|
||||
return ResourceManager.GetString("textTimestamp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to to.
|
||||
/// </summary>
|
||||
@ -895,6 +1107,33 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Set as a fixed order.
|
||||
/// </summary>
|
||||
public static string textTooltipSetFixedOrder {
|
||||
get {
|
||||
return ResourceManager.GetString("textTooltipSetFixedOrder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unset as a a fixed order.
|
||||
/// </summary>
|
||||
public static string textTooltipUnSetFixedOrder {
|
||||
get {
|
||||
return ResourceManager.GetString("textTooltipUnSetFixedOrder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Trigger a manual refresh of all shipcalls.
|
||||
/// </summary>
|
||||
public static string textTriggerManualRefresh {
|
||||
get {
|
||||
return ResourceManager.GetString("textTriggerManualRefresh", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tug.
|
||||
/// </summary>
|
||||
@ -904,6 +1143,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tug company.
|
||||
/// </summary>
|
||||
public static string textTugCompany {
|
||||
get {
|
||||
return ResourceManager.GetString("textTugCompany", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tug required.
|
||||
/// </summary>
|
||||
@ -1065,6 +1313,15 @@ namespace BreCalClient.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Undefined.
|
||||
/// </summary>
|
||||
public static string Undefined {
|
||||
get {
|
||||
return ResourceManager.GetString("Undefined", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
@ -26,36 +26,36 @@
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
@ -218,7 +218,7 @@
|
||||
<value>Zeitraum</value>
|
||||
</data>
|
||||
<data name="textLengthWidth" xml:space="preserve">
|
||||
<value>L/B</value>
|
||||
<value>L/B (m)</value>
|
||||
</data>
|
||||
<data name="textLogin" xml:space="preserve">
|
||||
<value>Anmelden</value>
|
||||
@ -427,4 +427,73 @@
|
||||
<data name="textStarboard" xml:space="preserve">
|
||||
<value>Steuerbord</value>
|
||||
</data>
|
||||
<data name="textAdd" xml:space="preserve">
|
||||
<value>Hinzufügen</value>
|
||||
</data>
|
||||
<data name="textDelete" xml:space="preserve">
|
||||
<value>Löschen</value>
|
||||
</data>
|
||||
<data name="textEdit" xml:space="preserve">
|
||||
<value>Bearbeiten</value>
|
||||
</data>
|
||||
<data name="textEditShips" xml:space="preserve">
|
||||
<value>Schiffe anlegen / bearbeiten</value>
|
||||
</data>
|
||||
<data name="textDeleted" xml:space="preserve">
|
||||
<value>Gelöscht</value>
|
||||
</data>
|
||||
<data name="textEditShip" xml:space="preserve">
|
||||
<value>Schiff bearbeiten</value>
|
||||
</data>
|
||||
<data name="textTugCompany" xml:space="preserve">
|
||||
<value>Schlepper-Reederei</value>
|
||||
</data>
|
||||
<data name="textChangeHistory" xml:space="preserve">
|
||||
<value>Verlauf</value>
|
||||
</data>
|
||||
<data name="textInfoChangePW" xml:space="preserve">
|
||||
<value>App Info anzeigen und Passwort ändern</value>
|
||||
</data>
|
||||
<data name="textShowHistory" xml:space="preserve">
|
||||
<value>Änderungshistorie der Anläufe anzeigen</value>
|
||||
</data>
|
||||
<data name="textMineOnly" xml:space="preserve">
|
||||
<value>nur eigene</value>
|
||||
</data>
|
||||
<data name="textOperation" xml:space="preserve">
|
||||
<value>Vorgang</value>
|
||||
</data>
|
||||
<data name="textParticipant" xml:space="preserve">
|
||||
<value>Teilnehmer</value>
|
||||
</data>
|
||||
<data name="textTimestamp" xml:space="preserve">
|
||||
<value>Zeitpunkt</value>
|
||||
</data>
|
||||
<data name="textFixedOrder" xml:space="preserve">
|
||||
<value>Als feste Bestellung vermerkt</value>
|
||||
</data>
|
||||
<data name="textTooltipSetFixedOrder" xml:space="preserve">
|
||||
<value>Als feste Bestellung vermerken</value>
|
||||
</data>
|
||||
<data name="textTooltipUnSetFixedOrder" xml:space="preserve">
|
||||
<value>Feste Bestellung zurücknehmen</value>
|
||||
</data>
|
||||
<data name="textTriggerManualRefresh" xml:space="preserve">
|
||||
<value>Manuelle Aktualisierung der Anläufe auslösen</value>
|
||||
</data>
|
||||
<data name="Arrival" xml:space="preserve">
|
||||
<value>Einkommend</value>
|
||||
</data>
|
||||
<data name="Departure" xml:space="preserve">
|
||||
<value>Ausgehend</value>
|
||||
</data>
|
||||
<data name="Shifting" xml:space="preserve">
|
||||
<value>Verholung</value>
|
||||
</data>
|
||||
<data name="Undefined" xml:space="preserve">
|
||||
<value>Unbekannt</value>
|
||||
</data>
|
||||
<data name="textShips" xml:space="preserve">
|
||||
<value>Schiffe</value>
|
||||
</data>
|
||||
</root>
|
||||
@ -118,6 +118,12 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="add" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>add.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Arrival" xml:space="preserve">
|
||||
<value>Incoming</value>
|
||||
</data>
|
||||
<data name="arrow_down_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>arrow_down_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
@ -154,18 +160,36 @@
|
||||
<data name="delete2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>delete2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Departure" xml:space="preserve">
|
||||
<value>Outgoing</value>
|
||||
</data>
|
||||
<data name="edit" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>edit.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="emergency_stop_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>emergency_stop_button.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="lock_open" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>lock_open.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="logo_bremen_calling" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>logo_bremen_calling.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="nav_refresh_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>nav_refresh_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Shifting" xml:space="preserve">
|
||||
<value>Shifting</value>
|
||||
</data>
|
||||
<data name="ship2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>ship2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="sign_warning" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>sign_warning.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="textAdd" xml:space="preserve">
|
||||
<value>Add</value>
|
||||
</data>
|
||||
<data name="textAgencies" xml:space="preserve">
|
||||
<value>Agencies</value>
|
||||
</data>
|
||||
@ -211,6 +235,9 @@
|
||||
<data name="textChangeContactInfo" xml:space="preserve">
|
||||
<value>Update contact info</value>
|
||||
</data>
|
||||
<data name="textChangeHistory" xml:space="preserve">
|
||||
<value>Change history</value>
|
||||
</data>
|
||||
<data name="textChangePassword" xml:space="preserve">
|
||||
<value>Change password</value>
|
||||
</data>
|
||||
@ -229,15 +256,30 @@
|
||||
<data name="textConfirmation" xml:space="preserve">
|
||||
<value>Confirmation</value>
|
||||
</data>
|
||||
<data name="textDelete" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="textDeleted" xml:space="preserve">
|
||||
<value>Deleted</value>
|
||||
</data>
|
||||
<data name="textDepartureTerminal" xml:space="preserve">
|
||||
<value>Departure terminal</value>
|
||||
</data>
|
||||
<data name="textDraft" xml:space="preserve">
|
||||
<value>Draft (m)</value>
|
||||
</data>
|
||||
<data name="textEdit" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="textEditShip" xml:space="preserve">
|
||||
<value>Edit ship</value>
|
||||
</data>
|
||||
<data name="textEditShipcall" xml:space="preserve">
|
||||
<value>Edit ship call</value>
|
||||
</data>
|
||||
<data name="textEditShips" xml:space="preserve">
|
||||
<value>Edit ships</value>
|
||||
</data>
|
||||
<data name="textEditTimes" xml:space="preserve">
|
||||
<value>Edit times</value>
|
||||
</data>
|
||||
@ -259,12 +301,18 @@
|
||||
<data name="textFixed" xml:space="preserve">
|
||||
<value>Fixed</value>
|
||||
</data>
|
||||
<data name="textFixedOrder" xml:space="preserve">
|
||||
<value>Marked as a fixed order</value>
|
||||
</data>
|
||||
<data name="textFrom" xml:space="preserve">
|
||||
<value>from</value>
|
||||
</data>
|
||||
<data name="textIncoming" xml:space="preserve">
|
||||
<value>Incoming</value>
|
||||
</data>
|
||||
<data name="textInfoChangePW" xml:space="preserve">
|
||||
<value>Show app info and change user password</value>
|
||||
</data>
|
||||
<data name="textInterval" xml:space="preserve">
|
||||
<value>Interval</value>
|
||||
</data>
|
||||
@ -280,6 +328,9 @@
|
||||
<data name="textLogin" xml:space="preserve">
|
||||
<value>Login</value>
|
||||
</data>
|
||||
<data name="textMineOnly" xml:space="preserve">
|
||||
<value>mine only</value>
|
||||
</data>
|
||||
<data name="textMooredLock" xml:space="preserve">
|
||||
<value>Moored in lock</value>
|
||||
</data>
|
||||
@ -301,6 +352,9 @@
|
||||
<data name="textOldPassword" xml:space="preserve">
|
||||
<value>Old password</value>
|
||||
</data>
|
||||
<data name="textOperation" xml:space="preserve">
|
||||
<value>Operation</value>
|
||||
</data>
|
||||
<data name="textOperationsEnd" xml:space="preserve">
|
||||
<value>Operations end</value>
|
||||
</data>
|
||||
@ -310,6 +364,9 @@
|
||||
<data name="textOutgoing" xml:space="preserve">
|
||||
<value>Outgoing</value>
|
||||
</data>
|
||||
<data name="textParticipant" xml:space="preserve">
|
||||
<value>Participant</value>
|
||||
</data>
|
||||
<data name="textParticipants" xml:space="preserve">
|
||||
<value>Participants</value>
|
||||
</data>
|
||||
@ -373,9 +430,15 @@
|
||||
<data name="textShipLength" xml:space="preserve">
|
||||
<value>Ship length</value>
|
||||
</data>
|
||||
<data name="textShips" xml:space="preserve">
|
||||
<value>Ships</value>
|
||||
</data>
|
||||
<data name="textShowCancelledShipcalls" xml:space="preserve">
|
||||
<value>Show cancelled calls</value>
|
||||
</data>
|
||||
<data name="textShowHistory" xml:space="preserve">
|
||||
<value>Show shipcall change history</value>
|
||||
</data>
|
||||
<data name="textSortOrder" xml:space="preserve">
|
||||
<value>Sort order</value>
|
||||
</data>
|
||||
@ -388,12 +451,27 @@
|
||||
<data name="textTidalWindow" xml:space="preserve">
|
||||
<value>Tidal window</value>
|
||||
</data>
|
||||
<data name="textTimestamp" xml:space="preserve">
|
||||
<value>Timestamp</value>
|
||||
</data>
|
||||
<data name="textTo" xml:space="preserve">
|
||||
<value>to</value>
|
||||
</data>
|
||||
<data name="textTooltipSetFixedOrder" xml:space="preserve">
|
||||
<value>Set as a fixed order</value>
|
||||
</data>
|
||||
<data name="textTooltipUnSetFixedOrder" xml:space="preserve">
|
||||
<value>Unset as a a fixed order</value>
|
||||
</data>
|
||||
<data name="textTriggerManualRefresh" xml:space="preserve">
|
||||
<value>Trigger a manual refresh of all shipcalls</value>
|
||||
</data>
|
||||
<data name="textTug" xml:space="preserve">
|
||||
<value>Tug</value>
|
||||
</data>
|
||||
<data name="textTugCompany" xml:space="preserve">
|
||||
<value>Tug company</value>
|
||||
</data>
|
||||
<data name="textTugRequired" xml:space="preserve">
|
||||
<value>Tug required</value>
|
||||
</data>
|
||||
@ -445,7 +523,13 @@
|
||||
<data name="umbrella_open" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>umbrella_open.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="Undefined" xml:space="preserve">
|
||||
<value>Undefined</value>
|
||||
</data>
|
||||
<data name="worker2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>worker2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="_lock" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>lock.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
src/BreCalClient/Resources/add.png
Normal file
BIN
src/BreCalClient/Resources/add.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/BreCalClient/Resources/edit.png
Normal file
BIN
src/BreCalClient/Resources/edit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/BreCalClient/Resources/lock.png
Normal file
BIN
src/BreCalClient/Resources/lock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/BreCalClient/Resources/lock_open.png
Normal file
BIN
src/BreCalClient/Resources/lock_open.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/BreCalClient/Resources/nav_refresh_green.png
Normal file
BIN
src/BreCalClient/Resources/nav_refresh_green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@ -5,9 +5,13 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
xmlns:api="clr-namespace:BreCalClient.misc.Model"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="56" d:DesignWidth="800" Loaded="UserControl_Loaded">
|
||||
<UserControl.Resources>
|
||||
<local:EnumToStringConverter x:Key="enumToStringConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="28" />
|
||||
@ -63,7 +67,7 @@
|
||||
<Label Grid.Column="1" Content="{x:Static p:Resources.textTo}" />
|
||||
<DatePicker x:Name="datePickerETATo" Grid.Column="2" Margin="2" SelectedDateChanged="datePickerETATo_SelectedDateChanged" SelectedDate="{Binding Path=EtaTo}"/>
|
||||
</Grid>
|
||||
<xctk:CheckComboBox x:Name="comboBoxCategories" Grid.Column="4" Margin="2" ItemSelectionChanged="comboBoxCategories_ItemSelectionChanged" />
|
||||
<xctk:CheckComboBox x:Name="comboBoxCategories" Grid.Column="4" Margin="2" ItemSelectionChanged="comboBoxCategories_ItemSelectionChanged" ItemsSource="{local:Enumerate {x:Type api:ShipcallType}}" />
|
||||
<Grid Grid.Column="6" Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
@ -74,8 +78,17 @@
|
||||
<Label Grid.Column="1" Content="{x:Static p:Resources.textTo}" />
|
||||
<xctk:DoubleUpDown x:Name="upDownShiplengthTo" Grid.Column="2" Margin="2" Minimum="0" Maximum="1000" ValueChanged="upDownShiplengthTo_ValueChanged" Value="{Binding Path=ShipLengthTo}"/>
|
||||
</Grid>
|
||||
<xctk:WatermarkTextBox x:Name="textBoxSearch" Grid.Column="2" Grid.Row="1" Margin="2" Watermark="{x:Static p:Resources.textEnterKeyword}" PreviewTextInput="textBoxSearch_PreviewTextInput"
|
||||
<Grid Grid.Column="2" Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width=".5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<xctk:WatermarkTextBox x:Name="textBoxSearch" Grid.Column="0" Margin="2" Watermark="{x:Static p:Resources.textEnterKeyword}" PreviewTextInput="textBoxSearch_PreviewTextInput"
|
||||
DataObject.Pasting="textBoxSearch_Pasting" TextChanged="textBoxSearch_TextChanged" />
|
||||
<CheckBox x:Name="checkBoxOwn" VerticalAlignment="Center" Grid.Column="1" HorizontalAlignment="Right" Margin="2" Checked="checkBoxOwn_Checked" Unchecked="checkBoxOwn_Checked" />
|
||||
<Label Content="{x:Static p:Resources.textMineOnly}" Grid.Column="2" />
|
||||
</Grid>
|
||||
<xctk:CheckComboBox x:Name="comboBoxBerths" DisplayMemberPath="Name" Grid.Column="4" Grid.Row="1" Margin="2" ItemSelectionChanged="comboBoxBerths_ItemSelectionChanged" />
|
||||
<xctk:CheckComboBox x:Name="comboBoxAgencies" DisplayMemberPath="Name" Grid.Column="6" Grid.Row="1" Margin="2" ItemSelectionChanged="comboBoxAgencies_ItemSelectionChanged" />
|
||||
</Grid>
|
||||
|
||||
@ -72,11 +72,12 @@ namespace BreCalClient
|
||||
this.comboBoxAgencies.UnSelectAll();
|
||||
this.comboBoxBerths.UnSelectAll();
|
||||
this.comboBoxCategories.UnSelectAll();
|
||||
this.datePickerETAFrom.SelectedDate = null;
|
||||
this.datePickerETAFrom.SelectedDate = DateTime.Now.AddDays(-2);
|
||||
this.datePickerETATo.SelectedDate = null;
|
||||
this.textBoxSearch.Clear();
|
||||
this.upDownShiplengthFrom.Value = null;
|
||||
this.upDownShiplengthTo.Value = null;
|
||||
this.upDownShiplengthTo.Value = null;
|
||||
this.checkBoxOwn.IsChecked = false;
|
||||
}
|
||||
|
||||
|
||||
@ -100,14 +101,21 @@ namespace BreCalClient
|
||||
}
|
||||
if(sfm.Categories != null)
|
||||
{
|
||||
foreach(int category in sfm.Categories)
|
||||
this.comboBoxCategories.SelectedItems.Add((Extensions.TypeEnum)category);
|
||||
EnumToStringConverter enumToStringConverter = new();
|
||||
foreach (ShipcallType category in sfm.Categories)
|
||||
{
|
||||
this.comboBoxCategories.SelectedItems.Add(enumToStringConverter.Convert(category, typeof(ShipcallControl), new object(), System.Globalization.CultureInfo.CurrentCulture));
|
||||
}
|
||||
}
|
||||
if (sfm.SearchString != null) this.textBoxSearch.Text = sfm.SearchString;
|
||||
this.upDownShiplengthFrom.Value = sfm.ShipLengthFrom;
|
||||
this.upDownShiplengthTo.Value = sfm.ShipLengthTo;
|
||||
this.datePickerETAFrom.SelectedDate = sfm.EtaFrom;
|
||||
if (sfm.EtaFrom != null)
|
||||
this.datePickerETAFrom.SelectedDate = sfm.EtaFrom;
|
||||
else
|
||||
this.datePickerETAFrom.SelectedDate = DateTime.Now.AddDays(-2);
|
||||
this.datePickerETATo.SelectedDate = sfm.EtaTo;
|
||||
this.checkBoxOwn.IsChecked = sfm.MineOnly;
|
||||
|
||||
this._model = sfm;
|
||||
SearchFilterChanged?.Invoke();
|
||||
@ -124,7 +132,7 @@ namespace BreCalClient
|
||||
|
||||
private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
this.comboBoxCategories.ItemsSource = Enum.GetValues(typeof(Extensions.TypeEnum));
|
||||
|
||||
}
|
||||
|
||||
private void datePickerETAFrom_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
|
||||
@ -141,9 +149,15 @@ namespace BreCalClient
|
||||
|
||||
private void comboBoxCategories_ItemSelectionChanged(object sender, Xceed.Wpf.Toolkit.Primitives.ItemSelectionChangedEventArgs e)
|
||||
{
|
||||
EnumToStringConverter enumToStringConverter = new();
|
||||
|
||||
_model.Categories.Clear();
|
||||
foreach(int category in comboBoxCategories.SelectedItems)
|
||||
_model.Categories.Add(category);
|
||||
foreach (string categoryString in comboBoxCategories.SelectedItems)
|
||||
{
|
||||
ShipcallType? type = (ShipcallType?)enumToStringConverter.ConvertBack(categoryString, typeof(ShipcallType), new object(), System.Globalization.CultureInfo.CurrentCulture);
|
||||
if(type != null)
|
||||
_model.Categories.Add(type.Value);
|
||||
}
|
||||
|
||||
SearchFilterChanged?.Invoke();
|
||||
}
|
||||
@ -192,6 +206,12 @@ namespace BreCalClient
|
||||
{
|
||||
this.SearchFilter.SearchString = this.textBoxSearch.Text;
|
||||
SearchFilterChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void checkBoxOwn_Checked(object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
this._model.MineOnly = this.checkBoxOwn.IsChecked;
|
||||
SearchFilterChanged?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -19,7 +19,7 @@ namespace BreCalClient
|
||||
|
||||
public DateTime? EtaTo { get; set; }
|
||||
|
||||
public List<int> Categories { get; set; } = new();
|
||||
public List<ShipcallType> Categories { get; set; } = new();
|
||||
|
||||
public List<int> Agencies { get; set; } = new();
|
||||
|
||||
@ -31,8 +31,12 @@ namespace BreCalClient
|
||||
|
||||
public double? ShipLengthTo { get; set; }
|
||||
|
||||
public bool? MineOnly { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialisation
|
||||
|
||||
public static SearchFilterModel? Deserialize(string json)
|
||||
{
|
||||
return (SearchFilterModel?) JsonConvert.DeserializeObject(json, typeof(SearchFilterModel));
|
||||
@ -43,5 +47,7 @@ namespace BreCalClient
|
||||
return JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
41
src/BreCalClient/ShipListDialog.xaml
Normal file
41
src/BreCalClient/ShipListDialog.xaml
Normal file
@ -0,0 +1,41 @@
|
||||
<Window x:Class="BreCalClient.ShipListDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:local="clr-namespace:BreCalClient"
|
||||
mc:Ignorable="d" Left="{local:SettingBinding W2Left}" Top="{local:SettingBinding W2Top}" Title="{x:Static p:Resources.textShips}"
|
||||
Height="490" Width="800" ResizeMode="CanResize" Icon="Resources/containership.ico" Loaded="Window_Loaded">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="28" />
|
||||
</Grid.RowDefinitions>
|
||||
<local:ENIDataGrid x:Name="dataGridShips" Grid.Row="0" SelectionMode="Single" IsReadOnly="True" AlternatingRowBackground="LightBlue" AutoGenerateColumns="False"
|
||||
CanUserAddRows="False" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
|
||||
<local:ENIDataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Ship.Deleted}" Value="True">
|
||||
<Setter Property="Foreground" Value="DarkGray"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</local:ENIDataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Id" Binding="{Binding Path=Ship.Id}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="Name" Binding="{Binding Path=Ship.Name}" IsReadOnly="True"/>
|
||||
<DataGridCheckBoxColumn Header="{x:Static p:Resources.textTug}" Binding="{Binding Path=Ship.IsTug, Mode=OneWay}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="{x:Static p:Resources.textTugCompany}" Binding="{Binding Path=TugCompany, Mode=OneWay}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="IMO" Binding="{Binding Path=Ship.Imo}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="{x:Static p:Resources.textCallsign}" Binding="{Binding Path=Ship.Callsign}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="{x:Static p:Resources.textLength}" Binding="{Binding Path=Ship.Length}" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="{x:Static p:Resources.textWidth}" Binding="{Binding Path=Ship.Width}" IsReadOnly="True"/>
|
||||
<DataGridCheckBoxColumn Header="{x:Static p:Resources.textDeleted}" Binding="{Binding Path=Ship.Deleted, Mode=OneWay}" IsReadOnly="True" />
|
||||
</DataGrid.Columns>
|
||||
</local:ENIDataGrid>
|
||||
<Button Grid.Row="1" x:Name="buttonClose" Content="{x:Static p:Resources.textClose}" HorizontalAlignment="Right" Margin="2" Click="buttonClose_Click"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
127
src/BreCalClient/ShipListDialog.xaml.cs
Normal file
127
src/BreCalClient/ShipListDialog.xaml.cs
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Description: Administration screen for ships
|
||||
//
|
||||
|
||||
|
||||
using BreCalClient.misc.Api;
|
||||
using BreCalClient.misc.Model;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ShipListDialog.xaml
|
||||
/// </summary>
|
||||
public partial class ShipListDialog : Window
|
||||
{
|
||||
public ShipListDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
public ShipApi? ShipApi { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handler
|
||||
|
||||
private void buttonClose_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.dataGridShips.Initialize();
|
||||
this.dataGridShips.ItemsSource = BreCalLists.AllShips;
|
||||
|
||||
this.dataGridShips.CreateRequested += DataGridShips_CreateRequested;
|
||||
this.dataGridShips.EditRequested += DataGridShips_EditRequested;
|
||||
this.dataGridShips.DeleteRequested += DataGridShips_DeleteRequested;
|
||||
}
|
||||
|
||||
private async void DataGridShips_DeleteRequested(object obj)
|
||||
{
|
||||
if (obj is ShipModel shipmodel)
|
||||
{
|
||||
if (!shipmodel.Ship.Deleted)
|
||||
{
|
||||
if (this.ShipApi != null)
|
||||
await this.ShipApi.ShipDeleteAsync(shipmodel.Ship.Id);
|
||||
BreCalLists.Ships.Remove(shipmodel); // remove from "selectable" ships
|
||||
shipmodel.Ship.Deleted = true; // set deleted marker on working instance
|
||||
this.dataGridShips.ItemsSource = null;
|
||||
this.dataGridShips.ItemsSource = BreCalLists.AllShips;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void DataGridShips_EditRequested(object obj)
|
||||
{
|
||||
if (obj is ShipModel shipmodel)
|
||||
{
|
||||
EditShipDialog esd = new()
|
||||
{
|
||||
Ship = shipmodel.Ship
|
||||
};
|
||||
esd.Participants.AddRange(BreCalLists.Participants_Tug);
|
||||
|
||||
if (esd.ShowDialog() ?? false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.ShipApi != null)
|
||||
{
|
||||
Id tmpId = await this.ShipApi.ShipUpdateAsync(shipmodel.Ship);
|
||||
}
|
||||
this.dataGridShips.ItemsSource = null;
|
||||
this.dataGridShips.ItemsSource = BreCalLists.AllShips;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void DataGridShips_CreateRequested()
|
||||
{
|
||||
ShipModel shipModel = new(new Ship());
|
||||
EditShipDialog esd = new()
|
||||
{
|
||||
Ship = shipModel.Ship
|
||||
};
|
||||
esd.Participants.AddRange(BreCalLists.Participants_Tug);
|
||||
|
||||
if(esd.ShowDialog() ?? false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.ShipApi != null)
|
||||
{
|
||||
Id id = await this.ShipApi.ShipsCreateAsync(shipModel.Ship);
|
||||
shipModel.Ship.Id = id.VarId;
|
||||
this.dataGridShips.ItemsSource = null;
|
||||
BreCalLists.AllShips.Add(shipModel);
|
||||
BreCalLists.Ships.Add(shipModel);
|
||||
if(!BreCalLists.ShipLookupDict.TryAdd(id.VarId, shipModel))
|
||||
BreCalLists.ShipLookupDict[id.VarId] = shipModel;
|
||||
this.dataGridShips.ItemsSource = BreCalLists.AllShips;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,16 @@ namespace BreCalClient
|
||||
|
||||
public Ship Ship { get; private set; }
|
||||
|
||||
public string TugCompany
|
||||
{
|
||||
get { if(this.Ship.ParticipantId.HasValue)
|
||||
{
|
||||
return BreCalLists.ParticipantLookupDict[this.Ship.ParticipantId.Value].Name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0} ({1})", this.Ship.Name, this.Ship.Imo);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
xmlns:sets="clr-namespace:BreCalClient.Properties"
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="120" d:DesignWidth="800" Loaded="UserControl_Loaded">
|
||||
d:DesignHeight="135" d:DesignWidth="800">
|
||||
<Border BorderBrush="LightGray" Margin="1" BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -30,7 +30,7 @@
|
||||
<RowDefinition Height=".125*"/>
|
||||
<RowDefinition Height=".125*"/>
|
||||
|
||||
<RowDefinition Height=".05*"/>
|
||||
<RowDefinition Height=".125*"/>
|
||||
<RowDefinition Height=".125*"/>
|
||||
<RowDefinition Height=".125*"/>
|
||||
</Grid.RowDefinitions>
|
||||
@ -71,6 +71,12 @@
|
||||
<Viewbox Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left">
|
||||
<TextBlock x:Name="textBlockLengthWidth" Padding="0"/>
|
||||
</Viewbox>
|
||||
<Viewbox Grid.Row="4" Grid.Column="0" HorizontalAlignment="Left">
|
||||
<TextBlock Text="{x:Static p:Resources.textDraft}" Padding="0" />
|
||||
</Viewbox>
|
||||
<Viewbox Grid.Row="4" Grid.Column="1" HorizontalAlignment="Left">
|
||||
<TextBlock x:Name="textBlockDraft" Padding="0"/>
|
||||
</Viewbox>
|
||||
<Viewbox Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left">
|
||||
<TextBlock Text="ETA" x:Name="labelETA"/>
|
||||
</Viewbox>
|
||||
@ -116,52 +122,67 @@
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" Content = "ETA" x:Name="labelETAETDAgent" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
|
||||
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
|
||||
<Border Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" BorderThickness="0,1,0,0" BorderBrush="Gray" >
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
|
||||
</Border>
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelAgencyETAETDValue" FontWeight="DemiBold"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Grid.RowSpan="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockAgencyRemarks" FontSize="10"/>
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="1" HorizontalContentAlignment="Left" x:Name="labelAgencyBerth" Padding="0" VerticalContentAlignment="Center" FontSize="11" FontWeight="SemiBold" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{x:Static p:Resources.textBerthRemarks}" Padding="0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="9"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{x:Static p:Resources.textRemarks}" Padding="0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="9"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockAgencyBerthRemarks" FontSize="10"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- MOORING -->
|
||||
<Border Grid.Row="2" Grid.Column="2" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0">
|
||||
<Grid>
|
||||
<Grid x:Name="gridMooring">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.3*" />
|
||||
<ColumnDefinition Width="0.7*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="0" x:Name="ataRowDefinition" />
|
||||
<RowDefinition Height="0" x:Name="atdRowDefinition" />
|
||||
<RowDefinition Height="*" x:Name="infoRowDefinition"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" x:Name="labelETAETDMooring" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelMooringETAETDValue" FontWeight="DemiBold"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockMooringRemarks"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="ATA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="1" x:Name="labelTimesMooringATA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="ATD" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="2" Grid.Column="1" x:Name="labelTimesMooringATD" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Image Grid.Row="3" Grid.Column="0" x:Name="imageMooringLocked" VerticalAlignment="Top" Margin="0 20 0 0" HorizontalAlignment="Left" Source="./Resources/lock.png" Width="16" Height="16" ToolTip="{x:Static p:Resources.textFixedOrder}"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockMooringRemarks"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- PORT AUTHORITY -->
|
||||
<Border Grid.Row="2" Grid.Column="3" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0">
|
||||
<Grid >
|
||||
<Grid x:Name="gridPortAuthority">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.3*" />
|
||||
<ColumnDefinition Width="0.7*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="20" />
|
||||
<RowDefinition Height="0" x:Name="lockTimeRowDefinition" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" x:Name="labelETAETDPortAuthority" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textLockTime}" VerticalContentAlignment="Center" Padding="0"/>
|
||||
<Label Grid.Row="1" Grid.Column="1" x:Name="labelPortAuthorityLockTime" VerticalContentAlignment="Center" Padding="0" />
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPortAuthorityETAETDValue" FontWeight="DemiBold"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockPortAuthorityRemarks"/>
|
||||
<Image Grid.Row="2" Grid.Column="0" x:Name="imagePortAuthorityLocked" VerticalAlignment="Top" Margin="0 20 0 0" HorizontalAlignment="Left" Source="./Resources/lock.png" Width="16" Height="16" ToolTip="{x:Static p:Resources.textFixedOrder}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockPortAuthorityRemarks"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- PILOT -->
|
||||
<Border Grid.Row="2" Grid.Column="4" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0">
|
||||
<Grid >
|
||||
<Grid x:Name="gridPilot">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.3*" />
|
||||
<ColumnDefinition Width="0.7*" />
|
||||
@ -173,12 +194,13 @@
|
||||
<Label Grid.Row="0" Grid.Column="0" x:Name="labelETAETDPilot" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPilotETAETDValue" FontWeight="DemiBold"/>
|
||||
<Image Grid.Row="1" Grid.Column="0" x:Name="imagePilotLocked" VerticalAlignment="Top" Margin="0 20 0 0" HorizontalAlignment="Left" Source="./Resources/lock.png" Width="16" Height="16" ToolTip="{x:Static p:Resources.textFixedOrder}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockPilotRemarks"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<!-- TUG -->
|
||||
<Border Grid.Row="2" Grid.Column="5" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0">
|
||||
<Grid>
|
||||
<Grid x:Name="gridTug">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0.3*" />
|
||||
<ColumnDefinition Width="0.7*" />
|
||||
@ -190,6 +212,7 @@
|
||||
<Label Grid.Row="0" Grid.Column="0" x:Name="labelETAETDTug" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelTugETAETDValue" FontWeight="DemiBold"/>
|
||||
<Image Grid.Row="1" Grid.Column="0" x:Name="imageTugLocked" VerticalAlignment="Top" Margin="0 20 0 0" HorizontalAlignment="Left" Source="./Resources/lock.png" Width="16" Height="16" ToolTip="{x:Static p:Resources.textFixedOrder}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockTugRemarks"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
@ -210,9 +233,11 @@
|
||||
<Label Grid.Row="0" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelOperationsStart" FontWeight="DemiBold"/>
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Top" FontSize="9"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockTerminalRemarks" FontSize="10"/>
|
||||
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
|
||||
<Border BorderThickness="0,1,0,0" BorderBrush="Gray" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
|
||||
</Border>
|
||||
<Label Grid.Row="2" Grid.Column="1" HorizontalContentAlignment="Left" x:Name="labelTerminalBerth" Padding="0" VerticalContentAlignment="Center" FontSize="11" FontWeight="SemiBold" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{x:Static p:Resources.textBerthRemarks}" TextWrapping="Wrap" Padding="0" VerticalAlignment="Top" FontSize="9"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{x:Static p:Resources.textRemarks}" TextWrapping="Wrap" Padding="0" VerticalAlignment="Top" FontSize="9"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockTerminalBerthRemarks" FontSize="10"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@ -26,6 +26,9 @@ namespace BreCalClient
|
||||
Participant? _tug;
|
||||
Participant? _port_administration;
|
||||
private static readonly ILog _log = LogManager.GetLogger(typeof(ShipcallControl));
|
||||
bool ataAdded = false;
|
||||
bool atdAdded = false;
|
||||
bool lockTimeAdded = false;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -78,6 +81,7 @@ namespace BreCalClient
|
||||
this.labelAgencyETAETDValue.Content = "";
|
||||
this.textBlockAgencyRemarks.Text = "";
|
||||
this.textBlockAgencyBerthRemarks.Text = "";
|
||||
this.textBlockDraft.Text = "";
|
||||
}
|
||||
|
||||
_mooring = this.ShipcallControlModel.GetParticipantForType(Extensions.ParticipantType.MOORING);
|
||||
@ -209,13 +213,13 @@ namespace BreCalClient
|
||||
// this.labelShipName.Content = this.ShipcallControlModel?.Ship?.Name;
|
||||
switch (this.ShipcallControlModel?.Shipcall?.Type)
|
||||
{
|
||||
case 1: // incoming
|
||||
case ShipcallType.Arrival: // incoming
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_down_red.png"));
|
||||
break;
|
||||
case 2: // outgoing
|
||||
case ShipcallType.Departure: // outgoing
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_up_blue.png"));
|
||||
break;
|
||||
case 3: // shifting
|
||||
case ShipcallType.Shifting: // shifting
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_right_green.png"));
|
||||
break;
|
||||
default:
|
||||
@ -224,13 +228,13 @@ namespace BreCalClient
|
||||
|
||||
switch(this.ShipcallControlModel?.LightMode)
|
||||
{
|
||||
case ShipcallControlModel.TrafficLightMode.GREEN:
|
||||
case EvaluationType.Green:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/check.png"));
|
||||
break;
|
||||
case ShipcallControlModel.TrafficLightMode.YELLOW:
|
||||
case EvaluationType.Yellow:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/sign_warning.png"));
|
||||
break;
|
||||
case ShipcallControlModel.TrafficLightMode.RED:
|
||||
case EvaluationType.Red:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/delete2.png"));
|
||||
break;
|
||||
default:
|
||||
@ -248,22 +252,13 @@ namespace BreCalClient
|
||||
{
|
||||
if (this.ShipcallControlModel?.Shipcall?.Evaluation != null)
|
||||
{
|
||||
ShipcallControlModel.TrafficLightMode resultColor = (ShipcallControlModel.TrafficLightMode)(this.ShipcallControlModel?.Shipcall?.Evaluation ?? 0); // der nullable Operator hier ist so doof, die VS validation blickts einfach nicht
|
||||
switch (resultColor)
|
||||
this.Background = this.ShipcallControlModel.LightMode switch
|
||||
{
|
||||
//case ShipcallControlModel.TrafficLightMode.GREEN:
|
||||
// this.Background = Brushes.LightGreen;
|
||||
// break;
|
||||
case ShipcallControlModel.TrafficLightMode.YELLOW:
|
||||
this.Background = Brushes.LightYellow;
|
||||
break;
|
||||
case ShipcallControlModel.TrafficLightMode.RED:
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(200, 255, 100, 100));
|
||||
break;
|
||||
default:
|
||||
this.Background = Brushes.Transparent;
|
||||
break;
|
||||
}
|
||||
// ShipcallControlModel.TrafficLightMode.GREEN => this.Background = Brushes.LightGreen,
|
||||
EvaluationType.Yellow => Brushes.LightYellow,
|
||||
EvaluationType.Red => new SolidColorBrush(Color.FromArgb(200, 255, 100, 100)),
|
||||
_ => Brushes.Transparent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,11 +269,11 @@ namespace BreCalClient
|
||||
|
||||
this.textBlockBerth.Text = this.ShipcallControlModel?.Berth;
|
||||
this.textBlockCallsign.Text = this.ShipcallControlModel?.Ship?.Callsign;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type == 1)
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival)
|
||||
{
|
||||
this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Eta?.ToString("dd.MM. HH:mm");
|
||||
}
|
||||
if ((this.ShipcallControlModel?.Shipcall?.Type == 2) || (this.ShipcallControlModel?.Shipcall?.Type == 3))
|
||||
if ((this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Departure) || (this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Shifting))
|
||||
{
|
||||
this.labelETA.Text = "ETD";
|
||||
this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Etd?.ToString("dd.MM. HH:mm");
|
||||
@ -290,7 +285,7 @@ namespace BreCalClient
|
||||
// rename labels if this is not an incoming
|
||||
// must be here because there may not be a times record for each participant (yet)
|
||||
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != ShipcallType.Arrival)
|
||||
{
|
||||
this.labelETAETDAgent.Content = "ETD";
|
||||
this.labelETAETDMooring.Content = "ETD";
|
||||
@ -300,6 +295,17 @@ namespace BreCalClient
|
||||
this.labelETAETDTerminal.Content = BreCalClient.Resources.Resources.textOperationsEnd;
|
||||
}
|
||||
|
||||
if((this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival) && (this.ShipcallControlModel?.Shipcall.TimeRefPoint != null))
|
||||
{
|
||||
int timeRefPointIndex = this.ShipcallControlModel?.Shipcall?.TimeRefPoint ?? 0;
|
||||
|
||||
this.labelETAETDAgent.Content = BreCalLists.TimeRefs[timeRefPointIndex];
|
||||
this.labelETAETDMooring.Content = BreCalLists.TimeRefs[timeRefPointIndex];
|
||||
this.labelETAETDPilot.Content = BreCalLists.TimeRefs[timeRefPointIndex];
|
||||
this.labelETAETDPortAuthority.Content = BreCalLists.TimeRefs[timeRefPointIndex];
|
||||
this.labelETAETDTug.Content = BreCalLists.TimeRefs[timeRefPointIndex];
|
||||
}
|
||||
|
||||
if (this.ShipcallControlModel != null)
|
||||
{
|
||||
|
||||
@ -307,13 +313,10 @@ namespace BreCalClient
|
||||
if (agencyTimes != null)
|
||||
{
|
||||
this.labelAgencyBerth.Content = this.ShipcallControlModel?.GetBerthText(agencyTimes);
|
||||
this.labelAgencyETAETDValue.Content = agencyTimes.EtaBerth.HasValue ? agencyTimes.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockAgencyRemarks.Text = agencyTimes.Remarks;
|
||||
this.textBlockAgencyBerthRemarks.Text = agencyTimes.BerthInfo;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
{
|
||||
this.labelAgencyETAETDValue.Content = agencyTimes.EtdBerth.HasValue ? agencyTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
}
|
||||
this.labelAgencyETAETDValue.Content = agencyTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockAgencyRemarks.Text = agencyTimes.Remarks.TruncateDots(50);
|
||||
this.textBlockAgencyBerthRemarks.Text = agencyTimes.BerthInfo.TruncateDots(50);
|
||||
this.textBlockDraft.Text = ShipcallControlModel?.Shipcall?.Draft?.ToString("N2");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -322,84 +325,105 @@ namespace BreCalClient
|
||||
this.labelAgencyETAETDValue.Content = "- / -";
|
||||
this.textBlockAgencyRemarks.Text = "";
|
||||
this.textBlockAgencyBerthRemarks.Text = "";
|
||||
this.textBlockDraft.Text = "";
|
||||
}
|
||||
|
||||
Times? mooringTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.MOORING);
|
||||
|
||||
if (mooringTimes != null)
|
||||
{
|
||||
|
||||
this.labelMooringETAETDValue.Content = mooringTimes.EtaBerth.HasValue ? mooringTimes.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockMooringRemarks.Text = mooringTimes.Remarks;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
this.labelMooringETAETDValue.Content = mooringTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockMooringRemarks.Text = mooringTimes.Remarks.TruncateDots(50);
|
||||
this.imageMooringLocked.Visibility = (mooringTimes.EtaBerthFixed ?? false) ? Visibility.Visible : Visibility.Hidden;
|
||||
|
||||
if(mooringTimes.Ata.HasValue)
|
||||
{
|
||||
this.labelMooringETAETDValue.Content = mooringTimes.EtdBerth.HasValue ? mooringTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
if(!ataAdded)
|
||||
{
|
||||
|
||||
ataRowDefinition.Height = new GridLength(15);
|
||||
labelTimesMooringATA.Content = mooringTimes.Ata.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
ataAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mooringTimes.Atd.HasValue)
|
||||
{
|
||||
if (!atdAdded)
|
||||
{
|
||||
atdRowDefinition.Height = new GridLength(15);
|
||||
labelTimesMooringATD.Content = mooringTimes.Atd.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
atdAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.labelMooringETAETDValue.Content = "- / ";
|
||||
this.textBlockMooringRemarks.Text = "";
|
||||
this.imageMooringLocked.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
Times? portAuthorityTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PORT_ADMINISTRATION);
|
||||
if (portAuthorityTimes != null)
|
||||
{
|
||||
this.labelPortAuthorityETAETDValue.Content = portAuthorityTimes.EtaBerth.HasValue ? portAuthorityTimes.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockPortAuthorityRemarks.Text = portAuthorityTimes.Remarks;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
this.labelPortAuthorityETAETDValue.Content = portAuthorityTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockPortAuthorityRemarks.Text = portAuthorityTimes.Remarks.TruncateDots(50);
|
||||
this.imagePortAuthorityLocked.Visibility = (portAuthorityTimes.EtaBerthFixed ?? false) ? Visibility.Visible : Visibility.Hidden;
|
||||
if(portAuthorityTimes.LockTime.HasValue)
|
||||
{
|
||||
this.labelPortAuthorityETAETDValue.Content = portAuthorityTimes.EtdBerth.HasValue ? portAuthorityTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
if(!lockTimeAdded)
|
||||
{
|
||||
lockTimeRowDefinition.Height = new GridLength(15);
|
||||
labelPortAuthorityLockTime.Content = portAuthorityTimes.LockTime.Value.ToString("dd.MM.yyyy HH:mm");
|
||||
lockTimeAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.labelPortAuthorityETAETDValue.Content = "- / -";
|
||||
this.textBlockPortAuthorityRemarks.Text = "";
|
||||
this.imagePortAuthorityLocked.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
Times? pilotTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PILOT);
|
||||
if (pilotTimes != null)
|
||||
{
|
||||
this.labelPilotETAETDValue.Content = pilotTimes.EtaBerth.HasValue ? pilotTimes.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockPilotRemarks.Text = pilotTimes.Remarks;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
{
|
||||
this.labelPilotETAETDValue.Content = pilotTimes.EtdBerth.HasValue ? pilotTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
}
|
||||
this.labelPilotETAETDValue.Content = pilotTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockPilotRemarks.Text = pilotTimes.Remarks.TruncateDots(50);
|
||||
this.imagePilotLocked.Visibility = (pilotTimes.EtaBerthFixed ?? false) ? Visibility.Visible : Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.labelPilotETAETDValue.Content = "- / -";
|
||||
this.textBlockPilotRemarks.Text = "";
|
||||
this.imagePilotLocked.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
Times? tugTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.TUG);
|
||||
if (tugTimes != null)
|
||||
{
|
||||
this.labelTugETAETDValue.Content = tugTimes.EtaBerth.HasValue ? tugTimes.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockTugRemarks.Text = tugTimes.Remarks;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
{
|
||||
this.labelTugETAETDValue.Content = tugTimes.EtdBerth.HasValue ? tugTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
}
|
||||
this.labelTugETAETDValue.Content = tugTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockTugRemarks.Text = tugTimes.Remarks.TruncateDots(50);
|
||||
this.imageTugLocked.Visibility = (tugTimes.EtaBerthFixed ?? false) ? Visibility.Visible : Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.labelTugETAETDValue.Content = "- / -";
|
||||
this.textBlockTugRemarks.Text = "";
|
||||
this.imageTugLocked.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
Times? terminalTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.TERMINAL);
|
||||
if (terminalTimes != null)
|
||||
{
|
||||
this.labelTerminalBerth.Content = this.ShipcallControlModel?.GetBerthText(terminalTimes);
|
||||
this.labelOperationsStart.Content = terminalTimes.OperationsStart.HasValue ? terminalTimes.OperationsStart.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
this.textBlockTerminalRemarks.Text = terminalTimes.Remarks;
|
||||
if (this.ShipcallControlModel?.Shipcall?.Type != 1)
|
||||
{
|
||||
this.labelOperationsStart.Content = terminalTimes.OperationsEnd.HasValue ? terminalTimes.OperationsEnd.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
|
||||
}
|
||||
this.textBlockTerminalBerthRemarks.Text = terminalTimes.BerthInfo;
|
||||
this.labelOperationsStart.Content = terminalTimes.DisplayTime(this.ShipcallControlModel?.Shipcall?.Type == ShipcallType.Arrival);
|
||||
this.textBlockTerminalRemarks.Text = terminalTimes.Remarks.TruncateDots(40);
|
||||
this.textBlockTerminalBerthRemarks.Text = terminalTimes.BerthInfo.TruncateDots(40);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -423,11 +447,6 @@ namespace BreCalClient
|
||||
|
||||
#region event handler
|
||||
|
||||
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
private void buttonEditShipcall_Click(object? sender, RoutedEventArgs? e)
|
||||
{
|
||||
if(App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2023 schick Informatik
|
||||
// Description: Container model for shipcall related info
|
||||
//
|
||||
//
|
||||
|
||||
using BreCalClient.misc.Api;
|
||||
using BreCalClient.misc.Model;
|
||||
@ -16,17 +16,7 @@ namespace BreCalClient
|
||||
public class ShipcallControlModel
|
||||
{
|
||||
|
||||
#region Enumerations
|
||||
|
||||
public enum TrafficLightMode
|
||||
{
|
||||
OFF,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
RED,
|
||||
RED_YELLOW,
|
||||
ALL
|
||||
};
|
||||
#region Enumerations
|
||||
|
||||
[Flags]
|
||||
public enum StatusFlags
|
||||
@ -44,7 +34,7 @@ namespace BreCalClient
|
||||
|
||||
public Shipcall? Shipcall { get; set; }
|
||||
|
||||
public Ship? Ship { get; set; }
|
||||
public Ship? Ship { get; set; }
|
||||
|
||||
public string? Berth { get; set; }
|
||||
|
||||
@ -74,21 +64,21 @@ namespace BreCalClient
|
||||
}
|
||||
}
|
||||
|
||||
public TrafficLightMode LightMode
|
||||
public EvaluationType LightMode
|
||||
{
|
||||
get
|
||||
{
|
||||
TrafficLightMode tlm = TrafficLightMode.OFF;
|
||||
EvaluationType elm = EvaluationType.Undefined;
|
||||
|
||||
if (this.Shipcall != null)
|
||||
{
|
||||
if(this.Shipcall.Evaluation.HasValue)
|
||||
{
|
||||
tlm = (TrafficLightMode)this.Shipcall.Evaluation;
|
||||
elm = this.Shipcall.Evaluation.Value;
|
||||
}
|
||||
}
|
||||
return tlm;
|
||||
}
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
|
||||
public string Title
|
||||
@ -96,8 +86,7 @@ namespace BreCalClient
|
||||
get
|
||||
{
|
||||
if (this.Shipcall == null) return "";
|
||||
Extensions.TypeEnum callType = (Extensions.TypeEnum) this.Shipcall.Type;
|
||||
return string.Format("{0} {1}", callType, this.Ship?.Name);
|
||||
return string.Format("{0} {1}", this.Shipcall.Type, this.Ship?.Name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +101,7 @@ namespace BreCalClient
|
||||
{
|
||||
foreach (ParticipantAssignment participantAssignment in Shipcall.Participants)
|
||||
{
|
||||
AssignedParticipants[(Extensions.ParticipantType)participantAssignment.Type] = participantAssignment;
|
||||
AssignedParticipants[(Extensions.ParticipantType)participantAssignment.Type] = participantAssignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,15 +149,15 @@ namespace BreCalClient
|
||||
public string? GetBerthText(Times times)
|
||||
{
|
||||
string? berthText = null;
|
||||
if ((BreCalLists.AllBerths != null) && times.BerthId.HasValue && (this.Shipcall?.Type != (int)Extensions.TypeEnum.Shifting))
|
||||
if ((BreCalLists.Berths != null) && times.BerthId.HasValue && (this.Shipcall?.Type != ShipcallType.Shifting))
|
||||
{
|
||||
Berth? berth = BreCalLists.AllBerths.Find((x) => x.Id == times.BerthId);
|
||||
berthText = berth?.Name;
|
||||
}
|
||||
|
||||
if ((berthText == null) && (times.ParticipantType != (int)Extensions.ParticipantType.TERMINAL))
|
||||
if ((berthText == null) && (times.ParticipantType != (int) Extensions.ParticipantType.TERMINAL))
|
||||
{
|
||||
if (this.Shipcall?.Type == (int)Extensions.TypeEnum.Incoming)
|
||||
if (this.Shipcall?.Type == ShipcallType.Arrival)
|
||||
{
|
||||
Berth? berth = BreCalLists.AllBerths?.Find((x) => x.Id == this.Shipcall?.ArrivalBerthId);
|
||||
berthText = berth?.Name;
|
||||
@ -183,13 +172,40 @@ namespace BreCalClient
|
||||
return berthText;
|
||||
}
|
||||
|
||||
public string GetETAETD()
|
||||
{
|
||||
DateTime theDate = DateTime.Now;
|
||||
if(this.Shipcall != null)
|
||||
{
|
||||
if (this.Shipcall.Type == ShipcallType.Arrival)
|
||||
theDate = this.Shipcall.Eta ?? DateTime.Now;
|
||||
else
|
||||
theDate = this.Shipcall.Etd ?? DateTime.Now;
|
||||
}
|
||||
Times? agentTimes = this.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
|
||||
if(agentTimes != null)
|
||||
{
|
||||
if(this.Shipcall?.Type == ShipcallType.Arrival)
|
||||
{
|
||||
if (agentTimes.EtaBerth != null)
|
||||
theDate = agentTimes.EtaBerth.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (agentTimes.EtdBerth != null)
|
||||
theDate = agentTimes.EtdBerth.Value;
|
||||
}
|
||||
}
|
||||
return theDate.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// After closing the edit shipcall or edit agency dialogs, the times assignments may have changed.
|
||||
/// This function updates the assignments for existing times records accordingly and saves them.
|
||||
/// </summary>
|
||||
/// <param name="_api">API reference to PUT eidted times</param>
|
||||
internal async void UpdateTimesAssignments(DefaultApi _api)
|
||||
internal async void UpdateTimesAssignments(TimesApi api)
|
||||
{
|
||||
foreach (Extensions.ParticipantType participantType in this.AssignedParticipants.Keys)
|
||||
{
|
||||
@ -198,7 +214,7 @@ namespace BreCalClient
|
||||
if(times.ParticipantId != this.AssignedParticipants[participantType].ParticipantId)
|
||||
{
|
||||
times.ParticipantId = this.AssignedParticipants[participantType].ParticipantId;
|
||||
await _api.TimesPutAsync(times);
|
||||
await api.TimesUpdateAsync(times);
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +241,7 @@ namespace BreCalClient
|
||||
|
||||
foreach(Times times in deleteTimes)
|
||||
{
|
||||
_api.TimesDelete(times.Id);
|
||||
api.TimesDelete(times.Id);
|
||||
this.Times.Remove(times);
|
||||
}
|
||||
}
|
||||
@ -236,11 +252,11 @@ namespace BreCalClient
|
||||
|
||||
internal Participant? GetParticipantForType(Extensions.ParticipantType participantType)
|
||||
{
|
||||
if(AssignedParticipants.ContainsKey(participantType) && BreCalLists.ParticipantLookupDict.ContainsKey(AssignedParticipants[participantType].ParticipantId))
|
||||
if(AssignedParticipants.ContainsKey(participantType) && BreCalLists.ParticipantLookupDict.ContainsKey(AssignedParticipants[participantType].ParticipantId))
|
||||
return BreCalLists.ParticipantLookupDict[AssignedParticipants[participantType].ParticipantId];
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsFlagSet(StatusFlags flag)
|
||||
{
|
||||
@ -248,7 +264,7 @@ namespace BreCalClient
|
||||
return (this.Shipcall.Flags & (int) flag) != 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
31
src/BreCalClient/Util.cs
Normal file
31
src/BreCalClient/Util.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace BreCalClient
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
public static BitmapImage? LoadImage (byte[] imageData)
|
||||
{
|
||||
if (imageData == null || imageData.Length == 0) return null;
|
||||
var image = new BitmapImage();
|
||||
using (var mem = new MemoryStream(imageData))
|
||||
{
|
||||
mem.Position = 0;
|
||||
image.BeginInit();
|
||||
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
|
||||
image.CacheOption = BitmapCacheOption.OnLoad;
|
||||
image.UriSource = null;
|
||||
image.StreamSource = mem;
|
||||
image.EndInit();
|
||||
}
|
||||
image.Freeze();
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ from .api import berths
|
||||
from .api import ships
|
||||
from .api import login
|
||||
from .api import user
|
||||
from .api import history
|
||||
|
||||
from BreCal.brecal_utils.file_handling import get_project_root, ensure_path
|
||||
from BreCal.brecal_utils.test_handling import execute_test_with_pytest, execute_coverage_test
|
||||
@ -59,7 +60,7 @@ def create_app(test_config=None):
|
||||
app.register_blueprint(ships.bp)
|
||||
app.register_blueprint(login.bp)
|
||||
app.register_blueprint(user.bp)
|
||||
|
||||
app.register_blueprint(history.bp)
|
||||
|
||||
logging.basicConfig(filename='brecal.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')
|
||||
local_db.initPool(os.path.dirname(app.instance_path))
|
||||
|
||||
21
src/server/BreCal/api/history.py
Normal file
21
src/server/BreCal/api/history.py
Normal file
@ -0,0 +1,21 @@
|
||||
from flask import Blueprint, request
|
||||
from .. import impl
|
||||
from ..services.auth_guard import auth_guard
|
||||
import json
|
||||
|
||||
bp = Blueprint('history', __name__)
|
||||
|
||||
@bp.route('/history', methods=['get'])
|
||||
@auth_guard() # no restriction by role
|
||||
def GetParticipant():
|
||||
|
||||
if 'Authorization' in request.headers:
|
||||
token = request.headers.get('Authorization')
|
||||
options = {}
|
||||
if not 'shipcall_id' in request.args:
|
||||
return json.dumps("missing parameter"), 400
|
||||
options["shipcall_id"] = request.args.get("shipcall_id")
|
||||
return impl.history.GetHistory(options)
|
||||
else:
|
||||
return json.dumps("not authenticated"), 403
|
||||
|
||||
@ -10,12 +10,10 @@ bp = Blueprint('notifications', __name__)
|
||||
@bp.route('/notifications', methods=['get'])
|
||||
@auth_guard() # no restriction by role
|
||||
def GetNotifications():
|
||||
|
||||
if 'participant_id' in request.args:
|
||||
if 'shipcall_id' in request.args:
|
||||
options = {}
|
||||
options["participant_id"] = request.args.get("participant_id")
|
||||
options["shipcall_id"] = request.args.get("shipcall_id")
|
||||
return impl.notifications.GetNotifications(options)
|
||||
else:
|
||||
logging.warning("attempt to load notifications without participant id")
|
||||
logging.warning("attempt to load notifications without shipcall id")
|
||||
return json.dumps("missing argument"), 400
|
||||
@ -30,6 +30,7 @@ def PostShipcalls():
|
||||
|
||||
try:
|
||||
content = request.get_json(force=True)
|
||||
logging.info(content)
|
||||
loadedModel = model.ShipcallSchema().load(data=content, many=False, partial=True)
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
@ -45,6 +46,7 @@ def PutShipcalls():
|
||||
|
||||
try:
|
||||
content = request.get_json(force=True)
|
||||
logging.info(content)
|
||||
loadedModel = model.ShipcallSchema().load(data=content, many=False, partial=True)
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
from flask import Blueprint, request
|
||||
from .. import impl
|
||||
from ..services.auth_guard import auth_guard
|
||||
from marshmallow import EXCLUDE
|
||||
from ..schemas import model
|
||||
import json
|
||||
import logging
|
||||
|
||||
bp = Blueprint('ships', __name__)
|
||||
|
||||
@ -14,3 +17,52 @@ def GetShips():
|
||||
return impl.ships.GetShips(token)
|
||||
else:
|
||||
return json.dumps("not authenticated"), 403
|
||||
|
||||
|
||||
@bp.route('/ships', methods=['post'])
|
||||
@auth_guard() # no restriction by role
|
||||
def PostShip():
|
||||
|
||||
try:
|
||||
content = request.get_json(force=True)
|
||||
loadedModel = model.ShipSchema().load(data=content, many=False, partial=True)
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
return json.dumps("bad format"), 400
|
||||
|
||||
return impl.ships.PostShip(loadedModel)
|
||||
|
||||
|
||||
@bp.route('/ships', methods=['put'])
|
||||
@auth_guard() # no restriction by role
|
||||
def PutShip():
|
||||
|
||||
try:
|
||||
content = request.get_json(force=True)
|
||||
loadedModel = model.ShipSchema().load(data=content, many=False, partial=True, unknown=EXCLUDE)
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
return json.dumps("bad format"), 400
|
||||
|
||||
return impl.ships.PutShip(loadedModel)
|
||||
|
||||
|
||||
@bp.route('/ships', methods=['delete'])
|
||||
@auth_guard() # no restriction by role
|
||||
def DeleteShip():
|
||||
|
||||
# TODO check if I am allowed to delete this thing by deriving the participant from the bearer token
|
||||
try:
|
||||
if 'id' in request.args:
|
||||
options = {}
|
||||
options["id"] = request.args.get("id")
|
||||
else:
|
||||
return json.dumps("no id provided"), 400
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
return json.dumps("bad format"), 400
|
||||
|
||||
return impl.ships.DeleteShip(options)
|
||||
|
||||
@ -5,4 +5,5 @@ from . import shipcalls
|
||||
from . import times
|
||||
from . import ships
|
||||
from . import login
|
||||
from . import user
|
||||
from . import user
|
||||
from . import history
|
||||
@ -10,8 +10,6 @@ def GetBerths(token):
|
||||
No parameters, gets all entries
|
||||
"""
|
||||
|
||||
# TODO: validate token
|
||||
|
||||
try:
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
|
||||
39
src/server/BreCal/impl/history.py
Normal file
39
src/server/BreCal/impl/history.py
Normal file
@ -0,0 +1,39 @@
|
||||
import json
|
||||
import logging
|
||||
import pydapper
|
||||
import pdb
|
||||
|
||||
from ..schemas import model
|
||||
from ..schemas.model import History
|
||||
|
||||
from .. import local_db
|
||||
|
||||
def GetHistory(options):
|
||||
|
||||
"""
|
||||
:param options: A dictionary containing all the paramters for the Operations
|
||||
options["shipcall_id"]: **Id of shipcall**.
|
||||
"""
|
||||
|
||||
try:
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
|
||||
if "shipcall_id" in options and options["shipcall_id"]:
|
||||
data = commands.query("SELECT id, participant_id, shipcall_id, timestamp, eta, type, operation FROM history WHERE shipcall_id = ?shipcallid?",
|
||||
model=History.from_query_row,
|
||||
param={"shipcallid" : options["shipcall_id"]})
|
||||
|
||||
|
||||
pooledConnection.close()
|
||||
|
||||
except Exception as ex:
|
||||
pdb.pm()
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps("call failed"), 500
|
||||
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -14,7 +14,9 @@ def GetUser(options):
|
||||
hash = bcrypt.hashpw(options["password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8')
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
data = commands.query("SELECT id, participant_id, first_name, last_name, user_name, user_email, user_phone, password_hash, api_key, created, modified FROM user WHERE user_name = ?username? OR user_email = ?username?",
|
||||
data = commands.query("SELECT id, participant_id, first_name, last_name, user_name, user_email, user_phone, password_hash, " +
|
||||
"api_key, notify_email, notify_whatsapp, notify_signal, notify_popup, created, modified FROM user " +
|
||||
"WHERE user_name = ?username? OR user_email = ?username?",
|
||||
model=model.User, param={"username" : options["username"]})
|
||||
# print(data)
|
||||
if len(data) == 1:
|
||||
|
||||
@ -8,22 +8,25 @@ from .. import local_db
|
||||
def GetNotifications(options):
|
||||
"""
|
||||
:param options: A dictionary containing all the paramters for the Operations
|
||||
options["participant_id"]: **Id of participant**. *Example: 2*. Id returned through loading of participant
|
||||
options["shipcall_id"]: **Id of ship call**. *Example: 52*. Id given in ship call list
|
||||
options["shipcall_id"]: **Id**. *Example: 42*. Id of referenced ship call.
|
||||
|
||||
"""
|
||||
|
||||
# Implement your business logic here
|
||||
# All the parameters are present in the options argument
|
||||
|
||||
return json.dumps({
|
||||
"acknowledged": "<boolean>",
|
||||
"id": "<integer>",
|
||||
"notification_type": "<string>",
|
||||
"participant_id": "<integer>",
|
||||
"times_id": "<integer>",
|
||||
"timestamp": "<date-time>",
|
||||
}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
data = commands.query("SELECT id, shipcall_id, level, type, message, created, modified FROM notification " +
|
||||
"WHERE shipcall_id = ?scid?", model=model.Notification.from_query_row, param={"scid" : options["shipcall_id"]})
|
||||
pooledConnection.close()
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import pydapper
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from ..services.auth_guard import check_jwt
|
||||
|
||||
from BreCal.database.update_database import evaluate_shipcall_state
|
||||
|
||||
@ -20,19 +21,15 @@ def GetShipcalls(options):
|
||||
query = ("SELECT s.id as id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, " +
|
||||
"flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, " +
|
||||
"tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, " +
|
||||
"evaluation_message, s.created as created, s.modified as modified " +
|
||||
"evaluation_message, evaluation_time, evaluation_notifications_sent, s.created as created, s.modified as modified, time_ref_point " +
|
||||
"FROM shipcall s " +
|
||||
"LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 " +
|
||||
"WHERE " +
|
||||
"(type = 1 AND " +
|
||||
"((t.id IS NOT NULL AND t.eta_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
|
||||
"(eta >= DATE(NOW() - INTERVAL %d DAY)))) OR " +
|
||||
"((type = 2 OR type = 3) AND " +
|
||||
"((t.id IS NOT NULL AND t.etd_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
|
||||
"(etd >= DATE(NOW() - INTERVAL %d DAY)))) " +
|
||||
"ORDER BY eta") % (options["past_days"], options["past_days"], options["past_days"], options["past_days"])
|
||||
"(type = 1 AND (COALESCE(t.eta_berth, eta) >= DATE(NOW() - INTERVAL %d DAY))) OR " +
|
||||
"((type = 2 OR type = 3) AND (COALESCE(t.etd_berth, etd) >= DATE(NOW() - INTERVAL %d DAY)))" +
|
||||
"ORDER BY s.id") % (options["past_days"], options["past_days"])
|
||||
|
||||
data = commands.query(query, model=model.Shipcall)
|
||||
data = commands.query(query, model=model.Shipcall.from_query_row, buffered=True)
|
||||
for shipcall in data:
|
||||
participant_query = "SELECT participant_id, type FROM shipcall_participant_map WHERE shipcall_id=?shipcall_id?";
|
||||
for record in commands.query(participant_query, model=dict, param={"shipcall_id" : shipcall.id}, buffered=False):
|
||||
@ -84,6 +81,10 @@ def PostShipcalls(schemaModel):
|
||||
continue
|
||||
if key == "evaluation_message":
|
||||
continue
|
||||
if key == "type_value":
|
||||
continue
|
||||
if key == "evaluation_value":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ","
|
||||
isNotFirst = True
|
||||
@ -91,6 +92,7 @@ def PostShipcalls(schemaModel):
|
||||
query += ") VALUES ("
|
||||
isNotFirst = False
|
||||
for key in schemaModel.keys():
|
||||
param_key = key
|
||||
if key == "id":
|
||||
continue
|
||||
if key == "participants":
|
||||
@ -103,22 +105,38 @@ def PostShipcalls(schemaModel):
|
||||
continue
|
||||
if key == "evaluation_message":
|
||||
continue
|
||||
if key == "type":
|
||||
param_key = "type_value"
|
||||
if key == "type_value":
|
||||
continue
|
||||
if key == "evaluation":
|
||||
param_key = "evaluation_value"
|
||||
if key == "evaluation_value":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ","
|
||||
isNotFirst = True
|
||||
query += "?" + key + "?"
|
||||
query += "?" + param_key + "?"
|
||||
query += ")"
|
||||
|
||||
logging.info(query)
|
||||
commands.execute(query, schemaModel)
|
||||
new_id = commands.execute_scalar("select last_insert_id()")
|
||||
|
||||
# add participant assignments
|
||||
pquery = "INSERT INTO shipcall_participant_map (shipcall_id, participant_id, type) VALUES (?shipcall_id?, ?participant_id?, ?type?)"
|
||||
for participant_assignment in schemaModel["participants"]:
|
||||
commands.execute(pquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"], "type" : participant_assignment["type"]})
|
||||
# add participant assignments if we have a list of participants
|
||||
if 'participants' in schemaModel:
|
||||
pquery = "INSERT INTO shipcall_participant_map (shipcall_id, participant_id, type) VALUES (?shipcall_id?, ?participant_id?, ?type?)"
|
||||
for participant_assignment in schemaModel["participants"]:
|
||||
commands.execute(pquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"], "type" : participant_assignment["type"]})
|
||||
|
||||
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database
|
||||
evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=new_id) # new_id (last insert id) refers to the shipcall id
|
||||
# evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=new_id) # new_id (last insert id) refers to the shipcall id
|
||||
|
||||
# save history data
|
||||
# TODO: set ETA properly
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1, 1)"
|
||||
commands.execute(query, {"scid" : new_id, "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -158,6 +176,7 @@ def PutShipcalls(schemaModel):
|
||||
query = "UPDATE shipcall SET "
|
||||
isNotFirst = False
|
||||
for key in schemaModel.keys():
|
||||
param_key = key
|
||||
if key == "id":
|
||||
continue
|
||||
if key == "participants":
|
||||
@ -170,10 +189,18 @@ def PutShipcalls(schemaModel):
|
||||
continue
|
||||
if key == "evaluation_message":
|
||||
continue
|
||||
if key == "type":
|
||||
param_key = "type_value"
|
||||
if key == "type_value":
|
||||
continue
|
||||
if key == "evaluation":
|
||||
param_key = "evaluation_value"
|
||||
if key == "evaluation_value":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ", "
|
||||
isNotFirst = True
|
||||
query += key + " = ?" + key + "? "
|
||||
query += key + " = ?" + param_key + "? "
|
||||
|
||||
query += "WHERE id = ?id?"
|
||||
affected_rows = commands.execute(query, param=schemaModel)
|
||||
@ -205,6 +232,13 @@ def PutShipcalls(schemaModel):
|
||||
commands.execute(dquery, param={"existing_id" : elem["id"]})
|
||||
|
||||
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database
|
||||
# evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=schemaModel["id"]) # schemaModel["id"] refers to the shipcall id
|
||||
|
||||
# save history data
|
||||
# TODO: set ETA properly
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1, 2)"
|
||||
commands.execute(query, {"scid" : schemaModel["id"], "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
return json.dumps({"id" : schemaModel["id"]}), 200
|
||||
|
||||
|
||||
@ -10,8 +10,6 @@ def GetShips(token):
|
||||
No parameters, gets all entries
|
||||
"""
|
||||
|
||||
# TODO: validate token
|
||||
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
@ -35,3 +33,127 @@ def GetShips(token):
|
||||
|
||||
|
||||
|
||||
def PostShip(schemaModel):
|
||||
"""
|
||||
:param schemaModel: The deserialized model of the record to be inserted
|
||||
"""
|
||||
|
||||
# TODO: Validate the incoming data
|
||||
|
||||
# This creates a *new* entry
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
|
||||
query = "INSERT INTO ship ("
|
||||
isNotFirst = False
|
||||
for key in schemaModel.keys():
|
||||
if key == "id":
|
||||
continue
|
||||
if key == "created":
|
||||
continue
|
||||
if key == "modified":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ","
|
||||
isNotFirst = True
|
||||
query += key
|
||||
query += ") VALUES ("
|
||||
isNotFirst = False
|
||||
for key in schemaModel.keys():
|
||||
if key == "id":
|
||||
continue
|
||||
if key == "created":
|
||||
continue
|
||||
if key == "modified":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ","
|
||||
isNotFirst = True
|
||||
query += "?" + key + "?"
|
||||
query += ")"
|
||||
|
||||
commands.execute(query, schemaModel)
|
||||
new_id = commands.execute_scalar("select last_insert_id()")
|
||||
|
||||
pooledConnection.close()
|
||||
|
||||
return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
def PutShip(schemaModel):
|
||||
"""
|
||||
:param schemaModel: The deserialized model of the record to be inserted
|
||||
"""
|
||||
|
||||
# This updates an *existing* entry
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
|
||||
query = "UPDATE ship SET "
|
||||
isNotFirst = False
|
||||
for key in schemaModel.keys():
|
||||
if key == "id":
|
||||
continue
|
||||
if key == "created":
|
||||
continue
|
||||
if key == "modified":
|
||||
continue
|
||||
if isNotFirst:
|
||||
query += ", "
|
||||
isNotFirst = True
|
||||
query += key + " = ?" + key + "? "
|
||||
|
||||
query += "WHERE id = ?id?"
|
||||
|
||||
affected_rows = commands.execute(query, param=schemaModel)
|
||||
|
||||
pooledConnection.close()
|
||||
|
||||
return json.dumps({"id" : schemaModel["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
def DeleteShip(options):
|
||||
"""
|
||||
:param options: A dictionary containing all the paramters for the Operations
|
||||
options["id"]
|
||||
|
||||
"""
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
affected_rows = commands.execute("UPDATE ship SET deleted = 1 WHERE id = ?id?", param={"id" : options["id"]})
|
||||
|
||||
pooledConnection.close()
|
||||
|
||||
if affected_rows == 1:
|
||||
return json.dumps({"id" : options["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
result = {}
|
||||
result["message"] = "no such record"
|
||||
return json.dumps(result), 404, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
@ -1,9 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
import traceback
|
||||
import pydapper
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from ..services.auth_guard import check_jwt
|
||||
|
||||
from BreCal.database.update_database import evaluate_shipcall_state
|
||||
|
||||
@ -14,19 +16,18 @@ def GetTimes(options):
|
||||
|
||||
"""
|
||||
|
||||
# TODO: validate token
|
||||
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
data = commands.query("SELECT id, eta_berth, eta_berth_fixed, etd_berth, etd_berth_fixed, lock_time, lock_time_fixed, " +
|
||||
"zone_entry, zone_entry_fixed, operations_start, operations_end, remarks, shipcall_id, participant_id, " +
|
||||
"berth_id, berth_info, pier_side, participant_type, created, modified FROM times " +
|
||||
"berth_id, berth_info, pier_side, participant_type, created, modified, ata, atd, eta_interval_end, etd_interval_end FROM times " +
|
||||
"WHERE times.shipcall_id = ?scid?", model=model.Times, param={"scid" : options["shipcall_id"]})
|
||||
pooledConnection.close()
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(traceback.format_exc())
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
@ -85,9 +86,16 @@ def PostTimes(schemaModel):
|
||||
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database 'shipcall'
|
||||
evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=schemaModel["shipcall_id"]) # every times data object refers to the 'shipcall_id'
|
||||
|
||||
# save history data
|
||||
# TODO: set ETA properly
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 2, 1)"
|
||||
commands.execute(query, {"scid" : schemaModel["shipcall_id"], "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(traceback.format_exc())
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
@ -132,13 +140,21 @@ def PutTimes(schemaModel):
|
||||
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database 'shipcall'
|
||||
evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=schemaModel["shipcall_id"]) # every times data object refers to the 'shipcall_id'
|
||||
|
||||
# save history data
|
||||
# TODO: set ETA properly
|
||||
user_data = check_jwt()
|
||||
if "participant_id" in user_data and "id" in user_data:
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 2, 2)"
|
||||
commands.execute(query, {"pid" : user_data["participant_id"], "scid" : schemaModel["shipcall_id"], "uid" : user_data["id"]})
|
||||
else:
|
||||
logging.error("user_data does not contain participant_id or id")
|
||||
|
||||
# if affected_rows == 1: # this doesn't work as expected
|
||||
|
||||
return json.dumps({"id" : schemaModel["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
# return json.dumps("no such record"), 404, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(traceback.format_exc())
|
||||
logging.error(ex)
|
||||
print(ex)
|
||||
result = {}
|
||||
@ -159,8 +175,16 @@ def DeleteTimes(options):
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
shipcall_id = commands.execute_scalar("SELECT shipcall_id FROM times WHERE id = ?id?", param={"id" : options["id"]})
|
||||
affected_rows = commands.execute("DELETE FROM times WHERE id = ?id?", param={"id" : options["id"]})
|
||||
|
||||
# TODO: set ETA properly?
|
||||
|
||||
# save history data
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?shipcall_id?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 2, 3)"
|
||||
commands.execute(query, {"pid" : user_data["participant_id"], "shipcall_id" : shipcall_id, "uid" : user_data["id"]})
|
||||
|
||||
if affected_rows == 1:
|
||||
return json.dumps({"id" : options["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
@ -39,4 +39,4 @@ def getPoolConnection():
|
||||
global config_path
|
||||
f = open(config_path);
|
||||
connection_data = json.load(f)
|
||||
return mysql.connector.connect(**connection_data)
|
||||
return mysql.connector.connect(**connection_data)
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
from dataclasses import field
|
||||
from marshmallow import Schema, fields, INCLUDE, ValidationError
|
||||
from dataclasses import field, dataclass
|
||||
from marshmallow import Schema, fields, post_load, INCLUDE, ValidationError
|
||||
from marshmallow.fields import Field
|
||||
from marshmallow_enum import EnumField
|
||||
from enum import IntEnum
|
||||
|
||||
from marshmallow_dataclass import dataclass
|
||||
from typing import List
|
||||
@ -10,6 +13,8 @@ import datetime
|
||||
def obj_dict(obj):
|
||||
if isinstance(obj, datetime.datetime):
|
||||
return obj.isoformat()
|
||||
if hasattr(obj, 'to_json'):
|
||||
return obj.to_json()
|
||||
return obj.__dict__
|
||||
|
||||
@dataclass
|
||||
@ -23,6 +28,81 @@ class Berth(Schema):
|
||||
modified: datetime
|
||||
deleted: bool
|
||||
|
||||
class OperationType(IntEnum):
|
||||
undefined = 0
|
||||
insert = 1
|
||||
update = 2
|
||||
delete = 3
|
||||
|
||||
class ObjectType(IntEnum):
|
||||
undefined = 0
|
||||
shipcall = 1
|
||||
times = 2
|
||||
|
||||
class EvaluationType(IntEnum):
|
||||
undefined = 0
|
||||
green = 1
|
||||
yellow = 2
|
||||
red = 3
|
||||
|
||||
@classmethod
|
||||
def _missing_(cls, value):
|
||||
return cls.undefined
|
||||
|
||||
class NotificationType(IntEnum):
|
||||
undefined = 0
|
||||
email = 1
|
||||
push = 2
|
||||
@classmethod
|
||||
def _missing_(cls, value):
|
||||
return cls.undefined
|
||||
|
||||
class ShipcallType(IntEnum):
|
||||
undefined = 0
|
||||
arrival = 1
|
||||
departure = 2
|
||||
shifting = 3
|
||||
|
||||
@classmethod
|
||||
def _missing_(cls, value):
|
||||
return cls.undefined
|
||||
|
||||
|
||||
@dataclass
|
||||
class History:
|
||||
def __init__(self, id, participant_id, shipcall_id, timestamp, eta, type, operation):
|
||||
self.id = id
|
||||
self.participant_id = participant_id
|
||||
self.shipcall_id = shipcall_id
|
||||
self.timestamp = timestamp
|
||||
self.eta = eta
|
||||
self.type = type
|
||||
self.operation = operation
|
||||
pass
|
||||
|
||||
id: int
|
||||
participant_id: int
|
||||
shipcall_id: int
|
||||
timestamp: datetime
|
||||
eta: datetime
|
||||
type: ObjectType
|
||||
operation: OperationType
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"participant_id": self.participant_id,
|
||||
"shipcall_id": self.shipcall_id,
|
||||
"timestamp": self.timestamp.isoformat() if self.timestamp else "",
|
||||
"eta": self.eta.isoformat() if self.eta else "",
|
||||
"type": self.type.name,
|
||||
"operation": self.operation.name
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_query_row(self, id, participant_id, shipcall_id, timestamp, eta, type, operation):
|
||||
return self(id, participant_id, shipcall_id, timestamp, eta, ObjectType(type), OperationType(operation))
|
||||
|
||||
class Error(Schema):
|
||||
message = fields.String(required=True)
|
||||
|
||||
@ -31,17 +111,30 @@ class GetVerifyInlineResp(Schema):
|
||||
pass
|
||||
|
||||
@dataclass
|
||||
class Notification(Schema):
|
||||
|
||||
class Notification:
|
||||
id: int
|
||||
times_id: int
|
||||
acknowledged: bool
|
||||
shipcall_id: int
|
||||
level: int
|
||||
type: int
|
||||
type: NotificationType
|
||||
message: str
|
||||
created: datetime
|
||||
modified: datetime
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"shipcall_id": self.shipcall_id,
|
||||
"level": self.level,
|
||||
"type": self.type.name,
|
||||
"message": self.message,
|
||||
"created": self.created.isoformat() if self.created else "",
|
||||
"modified": self.modified.isoformat() if self.modified else ""
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_query_row(self, id, shipcall_id, level, type, message, created, modified):
|
||||
return self(id, shipcall_id, level, NotificationType(type), message, created, modified)
|
||||
|
||||
@dataclass
|
||||
class Participant(Schema):
|
||||
id: int
|
||||
@ -69,7 +162,7 @@ class ShipcallSchema(Schema):
|
||||
|
||||
id = fields.Int()
|
||||
ship_id = fields.Int()
|
||||
type = fields.Int()
|
||||
type = fields.Enum(ShipcallType, required=True)
|
||||
eta = fields.DateTime(Required = False, allow_none=True)
|
||||
voyage = fields.Str(allow_none=True, metadata={'Required':False}) # Solving: RemovedInMarshmallow4Warning: Passing field metadata as keyword arguments is deprecated. Use the explicit `metadata=...` argument instead. Additional metadata: {'Required': False}
|
||||
etd = fields.DateTime(Required = False, allow_none=True)
|
||||
@ -90,12 +183,28 @@ class ShipcallSchema(Schema):
|
||||
anchored = fields.Bool(Required = False, allow_none=True)
|
||||
moored_lock = fields.Bool(Required = False, allow_none=True)
|
||||
canceled = fields.Bool(Required = False, allow_none=True)
|
||||
evaluation = fields.Int(Required = False, allow_none=True)
|
||||
evaluation = fields.Enum(EvaluationType, required=False, allow_none=True, default=EvaluationType.undefined)
|
||||
evaluation_message = fields.Str(allow_none=True, metadata={'Required':False}) # Solving: RemovedInMarshmallow4Warning: Passing field metadata as keyword arguments is deprecated. Use the explicit `metadata=...` argument instead. Additional metadata: {'Required': False}
|
||||
evaluation_time = fields.DateTime(Required = False, allow_none=True)
|
||||
evaluation_notifications_sent = fields.Bool(Required = False, allow_none=True)
|
||||
time_ref_point = fields.Int(Required = False, allow_none=True)
|
||||
participants = fields.List(fields.Nested(ParticipantAssignmentSchema))
|
||||
created = fields.DateTime(Required = False, allow_none=True)
|
||||
modified = fields.DateTime(Required = False, allow_none=True)
|
||||
|
||||
@post_load
|
||||
def make_shipcall(self, data, **kwargs):
|
||||
if 'type' in data:
|
||||
data['type_value'] = data['type'].value
|
||||
else:
|
||||
data['type_value'] = ShipcallType.undefined
|
||||
if 'evaluation' in data:
|
||||
if data['evaluation']:
|
||||
data['evaluation_value'] = data['evaluation'].value
|
||||
else:
|
||||
data['evaluation_value'] = EvaluationType.undefined
|
||||
return data
|
||||
|
||||
@dataclass
|
||||
class Participant_Assignment:
|
||||
def __init__(self, participant_id, type):
|
||||
@ -104,14 +213,15 @@ class Participant_Assignment:
|
||||
pass
|
||||
|
||||
participant_id: int
|
||||
type: int
|
||||
type: int # a variant would be to use the IntFlag type (with appropriate serialization)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Shipcall:
|
||||
|
||||
id: int
|
||||
ship_id: int
|
||||
type: str
|
||||
type: ShipcallType
|
||||
eta: datetime
|
||||
voyage: str
|
||||
etd: datetime
|
||||
@ -132,12 +242,56 @@ class Shipcall:
|
||||
anchored: bool
|
||||
moored_lock: bool
|
||||
canceled: bool
|
||||
evaluation: int
|
||||
evaluation: EvaluationType
|
||||
evaluation_message: str
|
||||
evaluation_time: datetime
|
||||
evaluation_notifications_sent: bool
|
||||
time_ref_point: int
|
||||
created: datetime
|
||||
modified: datetime
|
||||
participants: List[Participant_Assignment] = field(default_factory=list)
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"ship_id": self.ship_id,
|
||||
"type": self.type.name,
|
||||
"eta": self.eta.isoformat() if self.eta else "",
|
||||
"voyage": self.voyage,
|
||||
"etd": self.etd.isoformat() if self.etd else "",
|
||||
"arrival_berth_id": self.arrival_berth_id,
|
||||
"departure_berth_id": self.departure_berth_id,
|
||||
"tug_required": self.tug_required,
|
||||
"pilot_required": self.pilot_required,
|
||||
"flags": self.flags,
|
||||
"pier_side": self.pier_side,
|
||||
"bunkering": self.bunkering,
|
||||
"replenishing_terminal": self.replenishing_terminal,
|
||||
"replenishing_lock": self.replenishing_lock,
|
||||
"draft": self.draft,
|
||||
"tidal_window_from": self.tidal_window_from.isoformat() if self.tidal_window_from else "",
|
||||
"tidal_window_to": self.tidal_window_to.isoformat() if self.tidal_window_to else "",
|
||||
"rain_sensitive_cargo": self.rain_sensitive_cargo,
|
||||
"recommended_tugs": self.recommended_tugs,
|
||||
"anchored": self.anchored,
|
||||
"moored_lock": self.moored_lock,
|
||||
"canceled": self.canceled,
|
||||
"evaluation": self.evaluation.name,
|
||||
"evaluation_message": self.evaluation_message,
|
||||
"evaluation_time": self.evaluation_time.isoformat() if self.evaluation_time else "",
|
||||
"evaluation_notifications_sent": self.evaluation_notifications_sent,
|
||||
"time_ref_point": self.time_ref_point,
|
||||
"created": self.created.isoformat() if self.created else "",
|
||||
"modified": self.modified.isoformat() if self.modified else "",
|
||||
"participants": [participant.__dict__ for participant in self.participants]
|
||||
|
||||
}
|
||||
|
||||
|
||||
@classmethod
|
||||
def from_query_row(self, id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, flags, pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, created, modified):
|
||||
return self(id, ship_id, ShipcallType(type), eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, flags, pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, EvaluationType(evaluation), evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, created, modified)
|
||||
|
||||
class ShipcallId(Schema):
|
||||
pass
|
||||
|
||||
@ -166,6 +320,10 @@ class TimesSchema(Schema):
|
||||
pier_side = fields.Bool(Required = False, allow_none = True)
|
||||
shipcall_id = fields.Int(Required = True)
|
||||
participant_type = fields.Int(Required = False, allow_none=True)
|
||||
ata = fields.DateTime(Required = False, allow_none=True)
|
||||
atd = fields.DateTime(Required = False, allow_none=True)
|
||||
eta_interval_end = fields.DateTime(Required = False, allow_none=True)
|
||||
etd_interval_end = fields.DateTime(Required = False, allow_none=True)
|
||||
created = fields.DateTime(Required = False, allow_none=True)
|
||||
modified = fields.DateTime(Required = False, allow_none=True)
|
||||
|
||||
@ -185,7 +343,6 @@ class UserSchema(Schema):
|
||||
|
||||
@dataclass
|
||||
class Times:
|
||||
|
||||
id: int
|
||||
eta_berth: datetime
|
||||
eta_berth_fixed: bool
|
||||
@ -204,6 +361,10 @@ class Times:
|
||||
pier_side: bool
|
||||
participant_type: int
|
||||
shipcall_id: int
|
||||
ata: datetime
|
||||
atd: datetime
|
||||
eta_interval_end: datetime
|
||||
etd_interval_end: datetime
|
||||
created: datetime
|
||||
modified: datetime
|
||||
|
||||
@ -219,11 +380,15 @@ class User:
|
||||
user_phone: str
|
||||
password_hash: str
|
||||
api_key: str
|
||||
notify_email: bool
|
||||
notify_whatsapp: bool
|
||||
notify_signal: bool
|
||||
notify_popup: bool
|
||||
created: datetime
|
||||
modified: datetime
|
||||
|
||||
@dataclass
|
||||
class Ship(Schema):
|
||||
class Ship:
|
||||
id: int
|
||||
name: str
|
||||
imo: int
|
||||
@ -233,11 +398,32 @@ class Ship(Schema):
|
||||
width: float
|
||||
is_tug: bool
|
||||
bollard_pull: int
|
||||
eni: str
|
||||
eni: int
|
||||
created: datetime
|
||||
modified: datetime
|
||||
deleted: bool
|
||||
|
||||
|
||||
class ShipSchema(Schema):
|
||||
def __init__(self):
|
||||
super().__init__(unknown=None)
|
||||
pass
|
||||
|
||||
id = fields.Int(Required=False)
|
||||
name = fields.String(allow_none=False, metadata={'Required':True})
|
||||
imo = fields.Int(allow_none=False, metadata={'Required':True})
|
||||
callsign = fields.String(allow_none=True, metadata={'Required':False})
|
||||
participant_id = fields.Int(allow_none=True, metadata={'Required':False})
|
||||
length = fields.Float(allow_none=True, metadata={'Required':False})
|
||||
width = fields.Float(allow_none=True, metadata={'Required':False})
|
||||
is_tug = fields.Bool(allow_none=True, metadata={'Required':False}, default=False)
|
||||
bollard_pull = fields.Int(allow_none=True, metadata={'Required':False})
|
||||
eni = fields.Int(allow_none=True, metadata={'Required':False})
|
||||
created = fields.DateTime(allow_none=True, metadata={'Required':False})
|
||||
modified = fields.DateTime(allow_none=True, metadata={'Required':False})
|
||||
deleted = fields.Bool(allow_none=True, metadata={'Required':False}, default=False)
|
||||
|
||||
|
||||
class TimesId(Schema):
|
||||
pass
|
||||
|
||||
|
||||
@ -25,11 +25,15 @@ def UpdateShipcalls(options:dict = {'past_days':2}):
|
||||
try:
|
||||
pooledConnection = getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
query = ("SELECT id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, "
|
||||
"flags, pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, tidal_window_to, rain_sensitive_cargo, recommended_tugs, "
|
||||
"anchored, moored_lock, canceled, evaluation, evaluation_message, created, modified FROM shipcall WHERE ((type = 1 OR type = 3) AND eta >= DATE(NOW() - INTERVAL %d DAY)"
|
||||
"OR (type = 2 AND etd >= DATE(NOW() - INTERVAL %d DAY))) "
|
||||
"ORDER BY eta") % (options["past_days"], options["past_days"])
|
||||
|
||||
query = ("SELECT s.id as id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, "
|
||||
"flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, tidal_window_to, rain_sensitive_cargo, recommended_tugs, "
|
||||
"anchored, moored_lock, canceled, evaluation, evaluation_message, evaluation_notifications_sent, evaluation_time, s.created as created, s.modified as modified, time_ref_point FROM shipcall s " +
|
||||
"LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 "
|
||||
"WHERE "
|
||||
"(type = 1 AND (COALESCE(t.eta_berth, eta) >= DATE(NOW() - INTERVAL %d DAY))) OR "
|
||||
"((type = 2 OR type = 3) AND (COALESCE(t.etd_berth, etd) >= DATE(NOW() - INTERVAL %d DAY)))"
|
||||
"ORDER BY s.id") % (options["past_days"], options["past_days"])
|
||||
|
||||
# obtain data from the MYSQL database
|
||||
data = commands.query(query, model=model.Shipcall)
|
||||
@ -54,6 +58,9 @@ def add_function_to_schedule__update_shipcalls(interval_in_minutes:int, options:
|
||||
return
|
||||
|
||||
def setup_schedule(update_shipcalls_interval_in_minutes:int=60):
|
||||
|
||||
logging.getLogger('schedule').setLevel(logging.INFO); # set the logging level of the schedule module to INFO
|
||||
|
||||
schedule.clear() # clear all routine jobs. This prevents jobs from being created multiple times
|
||||
|
||||
# update the evaluation state in every recent shipcall
|
||||
|
||||
@ -41,40 +41,44 @@ def get_shipcall_simple():
|
||||
canceled = False
|
||||
evaluation = None
|
||||
evaluation_message = ""
|
||||
evaluation_time = None
|
||||
evaluation_notifications_sent = False
|
||||
created = datetime.datetime.now()
|
||||
modified = created+datetime.timedelta(seconds=10)
|
||||
|
||||
participants = [generate_uuid1_int(), generate_uuid1_int(), generate_uuid1_int(), generate_uuid1_int()] # field(default_factory=[generate_uuid1_int(), generate_uuid1_int(), generate_uuid1_int(), generate_uuid1_int()]) # list
|
||||
|
||||
shipcall = Shipcall(
|
||||
shipcall_id,
|
||||
ship_id,
|
||||
shipcall_id,
|
||||
ship_id,
|
||||
role_type,
|
||||
eta,
|
||||
voyage,
|
||||
etd,
|
||||
arrival_berth_id,
|
||||
departure_berth_id,
|
||||
tug_required,
|
||||
pilot_required,
|
||||
flags,
|
||||
pier_side,
|
||||
bunkering,
|
||||
replenishing_terminal,
|
||||
replenishing_lock,
|
||||
draft,
|
||||
tidal_window_from,
|
||||
tidal_window_to,
|
||||
rain_sensitive_cargo,
|
||||
recommended_tugs,
|
||||
anchored,
|
||||
moored_lock,
|
||||
canceled,
|
||||
eta,
|
||||
voyage,
|
||||
etd,
|
||||
arrival_berth_id,
|
||||
departure_berth_id,
|
||||
tug_required,
|
||||
pilot_required,
|
||||
flags,
|
||||
pier_side,
|
||||
bunkering,
|
||||
replenishing_terminal,
|
||||
replenishing_lock,
|
||||
draft,
|
||||
tidal_window_from,
|
||||
tidal_window_to,
|
||||
rain_sensitive_cargo,
|
||||
recommended_tugs,
|
||||
anchored,
|
||||
moored_lock,
|
||||
canceled,
|
||||
evaluation,
|
||||
evaluation_message,
|
||||
created,
|
||||
modified,
|
||||
participants,
|
||||
evaluation_message,
|
||||
evaluation_time,
|
||||
evaluation_notifications_sent,
|
||||
created,
|
||||
modified,
|
||||
participants,
|
||||
)
|
||||
return shipcall
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ class ValidationRuleBaseFunctions():
|
||||
self.error_message_dict = error_message_dict
|
||||
# as of 23 dec. 2023 port authority validation is temporarily disabled
|
||||
self.ignore_port_administration_flag = True # flag to disable all port administration validation rules
|
||||
self.ignore_terminal_flag = True # flag to disable Terminal validation rules 0001-L & 0001-M
|
||||
|
||||
def describe_error_message(self, key)->str:
|
||||
"""
|
||||
@ -106,7 +107,7 @@ class ValidationRuleBaseFunctions():
|
||||
violation_state = (delta<=threshold)
|
||||
return violation_state
|
||||
|
||||
def check_participants_agree_on_estimated_time(self, shipcall, query, df_times, applicable_shipcall_type)->bool:
|
||||
def check_participants_agree_on_estimated_time(self, shipcall, query, df_times, applicable_shipcall_type, threshold:int=3660)->bool:
|
||||
"""
|
||||
# base function for all validation rules in the group {0002} A-C
|
||||
|
||||
@ -117,10 +118,12 @@ class ValidationRuleBaseFunctions():
|
||||
- the shipcall belongs to a different type than the rule expects
|
||||
- there are no matching times for the provided {query} (e.g., "eta_berth")
|
||||
|
||||
Instead of comparing each individual result, this function counts the amount of unique instances.
|
||||
When there is not only one unique value, there are deviating time estimates, and a violation occurs
|
||||
This method computes the absolute time difference between all time entries. A threshold (in seconds) is used
|
||||
to identify, when the time differences are so large, that participants essentially disagree on the times.
|
||||
This circumvents previous instabilities, which stem from rounding the pd.Timestamp elements.
|
||||
|
||||
To reduce the potential of false violations, the agreement is rounded (e.g., by minute).
|
||||
options:
|
||||
threshold: integer. Determines the threshold in seconds, when two Timestamps differ 'too much'
|
||||
|
||||
returns: violation_state (bool)
|
||||
"""
|
||||
@ -136,14 +139,14 @@ class ValidationRuleBaseFunctions():
|
||||
participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PILOT.value, ParticipantType.TUG.value]
|
||||
|
||||
agency_times = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value,:]
|
||||
df_times = df_times.loc[df_times["participant_type"].isin(participant_types),:]
|
||||
|
||||
|
||||
agency_time = [time_ for time_ in agency_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)]
|
||||
if not len(agency_time):
|
||||
if len(agency_times)==0:
|
||||
violation_state = False
|
||||
return violation_state
|
||||
|
||||
df_times = df_times.loc[df_times["participant_type"].isin(participant_types),:]
|
||||
agency_time = [time_ for time_ in agency_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)]
|
||||
|
||||
# for the given query, e.g., 'eta_berth', sample all times from the pandas DataFrame
|
||||
# exclude missing entries and consider only pd.Timestamp entries (which ignores pd.NaT/null entries)
|
||||
estimated_times = [time_ for time_ in df_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)] # df_times = df_times.loc[~df_times[query].isnull(),:]
|
||||
|
||||
@ -151,9 +154,25 @@ class ValidationRuleBaseFunctions():
|
||||
if len(estimated_times)==0:
|
||||
violation_state = False
|
||||
return violation_state
|
||||
|
||||
# this (current) solution compares times to the reference (agency) time and checks if the difference is greater than 15 minutes
|
||||
violation_state = ((np.max(estimated_times) - agency_time[0]) > pd.Timedelta("15min")) or ((agency_time[0] - np.min(estimated_times)) > pd.Timedelta("15min"))
|
||||
|
||||
# for the given query, e.g., 'eta_berth', sample all times from the pandas DataFrame
|
||||
estimated_times = [time_ for time_ in df_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)] # consider only pandas Timestamp objects
|
||||
|
||||
# measure the time difference between all pairs.
|
||||
# for each pair of times, the absolute timedifference in seconds (float) is measured
|
||||
time_absolute_differences = [[abs(time_.to_pydatetime()-time__.to_pydatetime()).total_seconds() for j_, time__ in enumerate(estimated_times) if j_ != i_] for i_, time_ in enumerate(estimated_times)]
|
||||
|
||||
# list of lists: for each element in the list, create a boolean that indicates, whether the threshold is exceeded
|
||||
time_difference_exceeds_threshold = [[time__ > threshold for time__ in time_] for time_ in time_absolute_differences]
|
||||
|
||||
# list of booleans for each time entry separately
|
||||
time_difference_exceeds_threshold = [any(time_) for time_ in time_difference_exceeds_threshold]
|
||||
|
||||
# if *any* of these entries exceeds the threshold, the times are too distinct. In those case, a rule violation occurs
|
||||
violation_state = any(time_difference_exceeds_threshold)
|
||||
|
||||
# this (previous) solution compares times to the reference (agency) time and checks if the difference is greater than 15 minutes
|
||||
# violation_state = ((np.max(estimated_times) - agency_time[0]) > pd.Timedelta("15min")) or ((agency_time[0] - np.min(estimated_times)) > pd.Timedelta("15min"))
|
||||
|
||||
# this solution to the rule compares all times to each other. When there is a total difference of more than 15 minutes, a violation occurs
|
||||
# Consequently, it treats all times as equally important
|
||||
@ -161,7 +180,7 @@ class ValidationRuleBaseFunctions():
|
||||
# violation_state = difference > pd.Timedelta("15min")
|
||||
|
||||
# this solution clamps the times to 15 minute intervals and compares these values. When there is a single time difference, a violation occurs
|
||||
# the drawback is that in some cases if there is a minimal difference say of 1 minute (:22 and :23 minutes after the hour) the violation is
|
||||
# the drawback is that in some cases if there is a minimal difference say of 1 minute (:22 and :23 minutes after the hour) the violation is
|
||||
# triggered even though the times are very close to each other
|
||||
|
||||
# apply rounding. For example, the agreement of different participants may be required to match minute-wise
|
||||
@ -581,6 +600,9 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Checks, if times_terminal.operations_start is filled in.
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
if self.ignore_terminal_flag: # this feature flag may disable the validation rule for Terminals
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
@ -615,6 +637,9 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Checks, if times_terminal.operations_end is filled in.
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
if self.ignore_terminal_flag: # this feature flag may disable the validation rule for Terminals
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
@ -730,6 +755,9 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
query time: eta_berth (times_agency)
|
||||
start_time & end_time: operations_start & operations_end (times_terminal)
|
||||
"""
|
||||
if self.ignore_terminal_flag: # this feature flag may disable the validation rule for Terminals
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
@ -770,6 +798,9 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
query time: eta_berth (times_agency)
|
||||
start_time & end_time: operations_start & operations_end (times_terminal)
|
||||
"""
|
||||
if self.ignore_terminal_flag: # this feature flag may disable the validation rule for Terminals
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import copy
|
||||
import logging
|
||||
import re
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@ -21,7 +22,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
# currently flagged: notification_state initially was based on using one ValidationRules object for each query. This is deprecated.
|
||||
# self.notification_state = self.determine_notification_state() # (state:str, should_notify:bool)
|
||||
return
|
||||
|
||||
|
||||
def evaluate(self, shipcall):
|
||||
"""
|
||||
1.) prepare df_times, which every validation rule tends to use
|
||||
@ -34,7 +35,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
|
||||
if len(df_times)==0:
|
||||
return (StatusFlags.GREEN.value, [])
|
||||
|
||||
|
||||
spm = self.sql_handler.df_dict["shipcall_participant_map"]
|
||||
if len(spm.loc[spm["shipcall_id"]==shipcall.id])==0:
|
||||
return (StatusFlags.GREEN.value, [])
|
||||
@ -51,12 +52,14 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
|
||||
# 'translate' all error codes into readable, human-understandable format.
|
||||
evaluation_results = [(state, self.describe_error_message(msg)) for (state, msg) in evaluation_results]
|
||||
|
||||
|
||||
logging.info(f"Validation results for shipcall {shipcall.id}: {evaluation_results}")
|
||||
|
||||
# check, what the maximum state flag is and return it
|
||||
evaluation_state = np.max(np.array([result[0].value for result in evaluation_results])) if len(evaluation_results)>0 else StatusFlags.GREEN.value
|
||||
evaluation_verbosity = [result[1] for result in evaluation_results]
|
||||
return (evaluation_state, evaluation_verbosity)
|
||||
|
||||
|
||||
def evaluation_verbosity(self, evaluation_state, evaluation_results):
|
||||
"""This function suggestions verbosity for the evaluation results. Based on 'True'/'False' evaluation outcome, the returned string is different."""
|
||||
if evaluation_state:
|
||||
@ -64,17 +67,17 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
else:
|
||||
verbose_string = "These are:" + "\n\t".join(evaluation_results) # every element of the list will be displayed in a new line with a tab
|
||||
return f"FAILED VALIDATION. There have been {len(evaluation_results)} violations. {verbose_string}"
|
||||
|
||||
|
||||
def evaluate_shipcall_from_df(self, x):
|
||||
shipcall = Shipcall(**{**{'id':x.name}, **x.to_dict()})
|
||||
evaluation_state, violations = self.evaluate(shipcall)
|
||||
return evaluation_state, violations
|
||||
|
||||
|
||||
def evaluate_shipcalls(self, shipcall_df:pd.DataFrame)->pd.DataFrame:
|
||||
"""apply 'evaluate_shipcall_from_df' to each individual shipcall in {shipcall_df}. Returns shipcall_df ('evaluation' and 'evaluation_message' are updated)"""
|
||||
results = shipcall_df.apply(lambda x: self.evaluate_shipcall_from_df(x), axis=1).values
|
||||
|
||||
# unbundle individual results. evaluation_state becomes an integer, violation
|
||||
# unbundle individual results. evaluation_state becomes an integer, violation
|
||||
evaluation_state = [StatusFlags(res[0]).value for res in results]
|
||||
violations = [",\r\n".join(res[1]) if len(res[1])>0 else None for res in results]
|
||||
violations = [self.concise_evaluation_message_if_too_long(violation) for violation in violations]
|
||||
@ -90,31 +93,31 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
"""
|
||||
if violation is None:
|
||||
return violation
|
||||
|
||||
|
||||
if len(violation)>=512:
|
||||
concise = re.findall(r'{(.*?)\}', violation)
|
||||
|
||||
# e.g.: Evaluation message too long. Violated Rules: ['Rule #0001C', 'Rule #0001H', 'Rule #0001F', 'Rule #0001G', 'Rule #0001L', 'Rule #0001M', 'Rule #0001J', 'Rule #0001K']
|
||||
violation = f"Evaluation message too long. Violated Rules: {concise}"
|
||||
return violation
|
||||
|
||||
|
||||
def determine_validation_state(self) -> str:
|
||||
"""
|
||||
this method determines the validation state of a shipcall. The state is either ['green', 'yellow', 'red'] and signals,
|
||||
whether an entry causes issues within the workflow of users.
|
||||
|
||||
whether an entry causes issues within the workflow of users.
|
||||
|
||||
returns: validation_state_new (str)
|
||||
"""
|
||||
(validation_state_new, description) = self.undefined_method()
|
||||
# should there also be notifications for critical validation states? In principle, the traffic light itself provides that notification.
|
||||
# should there also be notifications for critical validation states? In principle, the traffic light itself provides that notification.
|
||||
self.validation_state = validation_state_new
|
||||
return validation_state_new
|
||||
|
||||
|
||||
def determine_notification_state(self) -> (str, bool):
|
||||
"""
|
||||
this method determines state changes in the notification state. When the state is changed to yellow or red,
|
||||
a user is notified about it. The only exception for this rule is when the state was yellow or red before,
|
||||
as the user has then already been notified.
|
||||
as the user has then already been notified.
|
||||
|
||||
returns: notification_state_new (str), should_notify (bool)
|
||||
"""
|
||||
@ -122,10 +125,10 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
should_notify = self.identify_notification_state_change(state_new)
|
||||
self.notification_state = state_new # overwrite the predecessor
|
||||
return state_new, should_notify
|
||||
|
||||
|
||||
def identify_notification_state_change(self, state_new) -> bool:
|
||||
"""
|
||||
determines, whether the observed state change should trigger a notification.
|
||||
determines, whether the observed state change should trigger a notification.
|
||||
internally, this function maps a color string to an integer and determines, if the successor state is more severe than the predecessor.
|
||||
|
||||
state changes trigger a notification in the following cases:
|
||||
@ -135,14 +138,14 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
|
||||
(none -> yellow) or (none -> red)
|
||||
due to the values in the enumeration objects, the states are mapped to provide this function.
|
||||
green=1, yellow=2, red=3, none=1. Hence, critical changes can be observed by simply checking with "greater than".
|
||||
green=1, yellow=2, red=3, none=1. Hence, critical changes can be observed by simply checking with "greater than".
|
||||
|
||||
returns bool, whether a notification should be triggered
|
||||
"""
|
||||
# state_old is always considered at least 'Green' (1)
|
||||
state_old = max(copy.copy(self.notification_state) if "notification_state" in list(self.__dict__.keys()) else StatusFlags.NONE, StatusFlags.GREEN.value)
|
||||
return state_new.value > state_old.value
|
||||
|
||||
|
||||
def undefined_method(self) -> str:
|
||||
"""this function should apply the ValidationRules to the respective .shipcall, in regards to .times"""
|
||||
# #TODO_traffic_state
|
||||
|
||||
@ -2,7 +2,7 @@ from setuptools import find_packages, setup
|
||||
|
||||
setup(
|
||||
name='BreCal',
|
||||
version='1.1.6',
|
||||
version='1.2.0',
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
|
||||
Reference in New Issue
Block a user