Shipcalls now showing participant relevant info in correct columns

This commit is contained in:
Daniel Schick 2023-08-15 09:04:57 +02:00
parent 84462aead4
commit cf5498d049
10 changed files with 218 additions and 95 deletions

View File

@ -1,4 +1,5 @@
using System; using BreCalClient.misc.Model;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Configuration; using System.Configuration;
using System.Data; using System.Data;
@ -13,5 +14,6 @@ namespace BreCalClient
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
public static Participant Participant { get; set; } = new Participant();
} }
} }

View File

@ -0,0 +1,62 @@
// Copyright (c) 2023 schick Informatik
// Description: some helpers
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BreCalClient
{
internal static class Extensions
{
#region Enum
/// <summary>
/// Copied from models clunky I know
/// </summary>
[Flags]
public enum ParticipantType
{
[Description("not assigned")]
NONE = 0,
[Description("BSMD")]
BSMD = 1,
[Description("Terminal")]
TERMINAL = 2,
[Description("Lotsen")]
PILOT = 4,
[Description("Agentur")]
AGENCY = 8,
[Description("Festmacher")]
MOORING = 16,
[Description("Hafenamt")]
PORT_ADMINISTRATION = 32,
[Description("Schlepper")]
TUG = 64,
}
#endregion
#region public helper
public static bool IsFlagSet(this Participant participant, ParticipantType flag)
{
return (participant.Type & (uint)flag) != 0;
}
public static void SetFlag(this Participant participant, bool value, ParticipantType flag)
{
if (value) participant.Type |= (int)flag;
else participant.Type &= (int)~flag;
}
#endregion
}
}

View File

@ -57,6 +57,7 @@
<ColumnDefinition Width=".2*" /> <ColumnDefinition Width=".2*" />
<ColumnDefinition Width=".6*" /> <ColumnDefinition Width=".6*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Margin="2" Grid.Column="0" Content="{x:Static p:Resources.textNewDots}" x:Name="buttonNew" Visibility="Hidden" />
<Label Content="{x:Static p:Resources.textSortOrder}" Grid.Column="1" /> <Label Content="{x:Static p:Resources.textSortOrder}" Grid.Column="1" />
<ComboBox x:Name="comboBoxSortOrder" Margin="2" Grid.Column="2" /> <ComboBox x:Name="comboBoxSortOrder" Margin="2" Grid.Column="2" />
</Grid> </Grid>

View File

@ -22,15 +22,17 @@ namespace BreCalClient
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private const int SHIPCALL_UPDATE_INTERVAL_SECONDS = 30; private const int SHIPCALL_UPDATE_INTERVAL_SECONDS = 30;
private DefaultApi _api; private readonly DefaultApi _api;
private ObservableCollection<ShipcallControlModel> _controlModels = new(); private readonly ObservableCollection<ShipcallControlModel> _controlModels = new();
private List<Ship> _ships = new(); private List<Ship> _ships = new();
private ConcurrentDictionary<int, Ship> _shipLookupDict = new(); private readonly ConcurrentDictionary<int, Ship> _shipLookupDict = new();
private List<Berth> _berths = new(); private List<Berth> _berths = new();
private ConcurrentDictionary<int, Berth> _berthLookupDict = new(); private readonly ConcurrentDictionary<int, Berth> _berthLookupDict = new();
private List<Participant> _participants = new(); private List<Participant> _participants = new();
private Dictionary<int, Participant> _participantLookupDict = new(); private readonly Dictionary<int, Participant> _participantLookupDict = new();
private CancellationTokenSource _tokenSource = new CancellationTokenSource(); private readonly Dictionary<int, ShipcallControl> _shipCallControlDict = new();
private readonly CancellationTokenSource _tokenSource = new();
private LoginResult? _loginResult;
public MainWindow() public MainWindow()
{ {
@ -64,13 +66,13 @@ namespace BreCalClient
try try
{ {
LoginResult loginResult = await _api.LoginPostAsync(credentials); _loginResult = await _api.LoginPostAsync(credentials);
if(loginResult != null) if(_loginResult != null)
{ {
if(loginResult.Id > 0) if(_loginResult.Id > 0)
{ {
this.busyIndicator.IsBusy = false; this.busyIndicator.IsBusy = false;
this._api.Configuration.ApiKey["Authorization"] = loginResult.Token; this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token;
this.LoadStaticLists(); this.LoadStaticLists();
} }
} }
@ -104,35 +106,46 @@ namespace BreCalClient
foreach(var ship in this._ships) foreach(var ship in this._ships)
_shipLookupDict[ship.Id] = ship; _shipLookupDict[ship.Id] = ship;
this._participants = await _api.ParticipantsGetAsync(); this._participants = await _api.ParticipantsGetAsync();
List<Participant> agencies = new List<Participant>();
foreach (Participant participant in this._participants) foreach (Participant participant in this._participants)
{ {
this._participantLookupDict[participant.Id] = participant; this._participantLookupDict[participant.Id] = participant;
if (_loginResult?.ParticipantId == participant.Id)
{
App.Participant = participant;
EnableControlsForParticipant();
}
} }
_ = Task.Run(() => RefreshShipcalls()); _ = Task.Run(() => RefreshShipcalls());
} }
private void EnableControlsForParticipant()
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.BSMD))
this.buttonNew.Visibility = Visibility.Visible;
}
public async Task RefreshShipcalls() public async Task RefreshShipcalls()
{ {
while (!_tokenSource.Token.IsCancellationRequested) while (!_tokenSource.Token.IsCancellationRequested)
{ {
List<Shipcall> shipcalls = await _api.ShipcallsGetAsync(); List<Shipcall> shipcalls = await _api.ShipcallsGetAsync();
if (shipcalls != null)
{
foreach (Shipcall shipcall in shipcalls) foreach (Shipcall shipcall in shipcalls)
{ {
ShipcallControlModel? selectedSCMModel = null; ShipcallControlModel? selectedSCMModel = null;
foreach(ShipcallControlModel scm in this._controlModels) foreach (ShipcallControlModel scm in this._controlModels)
{ {
if(scm.Shipcall?.Id == shipcall.Id) if (scm.Shipcall?.Id == shipcall.Id)
{ {
selectedSCMModel = scm; selectedSCMModel = scm;
break; break;
} }
} }
if(selectedSCMModel != null) if (selectedSCMModel != null)
{ {
selectedSCMModel.Shipcall = shipcall; selectedSCMModel.Shipcall = shipcall;
} }
@ -155,28 +168,33 @@ namespace BreCalClient
sc.TimesRequested += Sc_TimesRequested; sc.TimesRequested += Sc_TimesRequested;
sc.EditRequested += Sc_EditRequested; sc.EditRequested += Sc_EditRequested;
this.stackPanel.Children.Add(sc); this.stackPanel.Children.Add(sc);
this._shipCallControlDict[shipcall.Id] = sc;
})); }));
} }
selectedSCMModel.AssignParticipants(this._participants); selectedSCMModel.AssignParticipants(this._participants);
this.Dispatcher.Invoke((Action)(() =>
{
this._shipCallControlDict[shipcall.Id].RefreshData();
}));
} }
List<ShipcallControl> removeList = new(); List<ShipcallControl> removeList = new();
foreach (ShipcallControlModel scm in this._controlModels) foreach (ShipcallControlModel scm in this._controlModels)
{ {
if(shipcalls.Find(s => s.Id == scm.Shipcall?.Id) == null) if (shipcalls.Find(s => s.Id == scm.Shipcall?.Id) == null) // the model is no longer in the search result
{ {
foreach (ShipcallControl sc in this.stackPanel.Children) if((scm.Shipcall != null) && this._shipCallControlDict.ContainsKey(scm.Shipcall.Id))
if (sc.ShipcallControlModel?.Shipcall?.Id == scm.Shipcall?.Id)
removeList.Add(sc);
}
}
foreach(ShipcallControl sc in removeList)
{ {
this.Dispatcher.Invoke(new Action(() => this.Dispatcher.Invoke((Action)(() =>
{ {
this.stackPanel.Children.Remove(sc); this.stackPanel.Children.Remove(this._shipCallControlDict[scm.Shipcall.Id]);
})); }));
this._shipCallControlDict.Remove(scm.Shipcall.Id);
}
}
}
} }
await Task.Delay(TimeSpan.FromSeconds(SHIPCALL_UPDATE_INTERVAL_SECONDS), _tokenSource.Token); await Task.Delay(TimeSpan.FromSeconds(SHIPCALL_UPDATE_INTERVAL_SECONDS), _tokenSource.Token);

View File

@ -278,6 +278,15 @@ namespace BreCalClient.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to New...
/// </summary>
public static string textNewDots {
get {
return ResourceManager.GetString("textNewDots", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Password. /// Looks up a localized string similar to Password.
/// </summary> /// </summary>

View File

@ -181,6 +181,9 @@
<data name="textLogin" xml:space="preserve"> <data name="textLogin" xml:space="preserve">
<value>Anmelden</value> <value>Anmelden</value>
</data> </data>
<data name="textNewDots" xml:space="preserve">
<value>Neu..</value>
</data>
<data name="textPassword" xml:space="preserve"> <data name="textPassword" xml:space="preserve">
<value>Passwort</value> <value>Passwort</value>
</data> </data>

View File

@ -187,6 +187,9 @@
<data name="textLogin" xml:space="preserve"> <data name="textLogin" xml:space="preserve">
<value>Login</value> <value>Login</value>
</data> </data>
<data name="textNewDots" xml:space="preserve">
<value>New..</value>
</data>
<data name="textPassword" xml:space="preserve"> <data name="textPassword" xml:space="preserve">
<value>Password</value> <value>Password</value>
</data> </data>

View File

@ -89,17 +89,17 @@
</Grid> </Grid>
<Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="1" FontSize="10" Content="Agent" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelAgent"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelAgent"/>
<Label Grid.Row="0" Grid.Column="2" Grid.RowSpan="1" FontSize="10" Content="Mooring" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="2" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelMooring"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelMooring"/>
<Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="1" FontSize="10" Content="Port authority" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPortAuthority"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPortAuthority"/>
<Label Grid.Row="0" Grid.Column="4" Grid.RowSpan="1" FontSize="10" Content="Pilot" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="4" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPilot"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPilot"/>
<Label Grid.Row="0" Grid.Column="5" Grid.RowSpan="1" FontSize="10" Content="Tug" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="5" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTug"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTug"/>
<Label Grid.Row="0" Grid.Column="6" Grid.RowSpan="1" FontSize="10" Content="Terminal" Foreground="White" Background="#203864" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="6" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTerminal"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTerminal"/>

View File

@ -42,14 +42,39 @@ namespace BreCalClient
#endregion #endregion
#region public methods
public void RefreshData()
{
if (this.ShipcallControlModel == null) return;
string? name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.AGENCY);
if (name != null)
this.labelAgent.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.MOORING);
if (name != null)
this.labelMooring.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.PILOT);
if (name != null)
this.labelPilot.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.TUG);
if (name != null)
this.labelTug.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.PORT_ADMINISTRATION);
if (name != null)
this.labelPortAuthority.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.TERMINAL);
if (name != null)
this.labelTerminal.Content = name;
}
#endregion
#region event handler #region event handler
private void UserControl_Loaded(object sender, RoutedEventArgs e) private void UserControl_Loaded(object sender, RoutedEventArgs e)
{ {
this.DataContext = this.ShipcallControlModel; this.DataContext = this.ShipcallControlModel;
if (this.ShipcallControlModel == null) return;
this.labelAgent.Content = this.ShipcallControlModel.AssignedParticipants.ContainsKey(8) ? this.ShipcallControlModel.AssignedParticipants[8].Name : string.Empty;
this.labelMooring.Content = this.ShipcallControlModel.AssignedParticipants.ContainsKey(16) ? this.ShipcallControlModel.AssignedParticipants[16].Name : string.Empty;
} }
private void buttonListTimes_Click(object sender, RoutedEventArgs e) private void buttonListTimes_Click(object sender, RoutedEventArgs e)
@ -80,20 +105,3 @@ namespace BreCalClient
} }
} }
/*
* Description("not assigned")]
NONE = 0,
[Description("BSMD")]
BSMD = 1,
[Description("Terminal")]
TERMINAL = 2,
[Description("Lotsen")]
PILOT = 4,
[Description("Agentur")]
AGENCY = 8,
[Description("Festmacher")]
MOORING = 16,
[Description("Hafenamt")]
PORT_ADMINISTRATION = 32,
[Description("Schlepper")]
TUG = 64,*/

View File

@ -2,9 +2,12 @@
// Description: Container model for shipcall related info // Description: Container model for shipcall related info
// //
using BreCalClient.misc.Client;
using BreCalClient.misc.Model; using BreCalClient.misc.Model;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace BreCalClient namespace BreCalClient
{ {
@ -15,6 +18,8 @@ namespace BreCalClient
public class ShipcallControlModel public class ShipcallControlModel
{ {
#region Enumerations
public enum TrafficLightMode public enum TrafficLightMode
{ {
OFF, OFF,
@ -35,6 +40,8 @@ namespace BreCalClient
BLINK_2 BLINK_2
}; };
#endregion
public Shipcall? Shipcall { get; set; } public Shipcall? Shipcall { get; set; }
public Ship? Ship { get; set; } public Ship? Ship { get; set; }
@ -84,6 +91,16 @@ namespace BreCalClient
} }
} }
internal string? GetParticipantNameForType(Extensions.ParticipantType participantType)
{
foreach(Participant p in AssignedParticipants.Values)
{
if (p.IsFlagSet(participantType))
return p.Name;
}
return null;
}
#region private helper #region private helper
private bool IsFlagSet(StatusFlags flag) private bool IsFlagSet(StatusFlags flag)