Skip to content

Commit

Permalink
Complete the aircraft lookup UI
Browse files Browse the repository at this point in the history
  • Loading branch information
davewalker5 committed Sep 27, 2023
1 parent eb1cdfb commit 743d3ac
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 29 deletions.
10 changes: 5 additions & 5 deletions src/BaseStationReader.Logic/Api/AirLabs/AirLabsAircraftApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ public AirLabsAircraftApi(string url, string key)
// Extract the values into a dictionary
properties = new()
{
{ ApiProperty.AirlineIATA, apiResponse!["airline_iata"]!.GetValue<string>() },
{ ApiProperty.AirlineICAO, apiResponse!["airline_icao"]!.GetValue<string>() },
{ ApiProperty.ManufacturerName, apiResponse!["manufacturer"]!.GetValue<string>() },
{ ApiProperty.ModelIATA, apiResponse!["iata"]!.GetValue<string>() },
{ ApiProperty.ModelICAO, apiResponse!["icao"]!.GetValue<string>() }
{ ApiProperty.AirlineIATA, apiResponse!["airline_iata"]?.GetValue<string?>() ?? "" },
{ ApiProperty.AirlineICAO, apiResponse!["airline_icao"]?.GetValue<string?>() ?? "" },
{ ApiProperty.ManufacturerName, apiResponse!["manufacturer"]?.GetValue<string>() ?? "" },
{ ApiProperty.ModelIATA, apiResponse!["iata"]?.GetValue<string>() ?? "" },
{ ApiProperty.ModelICAO, apiResponse!["icao"]?.GetValue<string>() ?? "" }
};
}
catch
Expand Down
20 changes: 11 additions & 9 deletions src/BaseStationReader.Logic/Tracking/AircraftLookupManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,19 @@ public class AircraftLookupManager
{
// Look for a match for both the IATA and ICAO codes
Model? model = await _modelManager!.GetAsync(x => (x.IATA == iata) && (x.ICAO == icao));
if (model == null)

// See if there's a match? If not, use the IATA code alone. This provides more granularity
// than the ICAO code alone. For example, there are multiple aircraft models with ICAO
// designation B738, but each has a different IATA code
if ((model == null) && !string.IsNullOrEmpty(iata))
{
// No match, so use the IATA code alone. This provides more granularity than the ICAO
// code alone. For example, there are multiple aircraft models with ICAO designation B738,
// but each has a different IATA code
model = await _modelManager!.GetAsync(x => x.IATA == iata);
if (model == null)
{
// No match, so fallback to using the ICAO code alone
model = await _modelManager!.GetAsync(x => x.ICAO == icao);
}
}

// See if there's a match? If not, fallback to using the ICAO code alone
if ((model == null) && !string.IsNullOrEmpty(icao))
{
model = await _modelManager!.GetAsync(x => x.ICAO == icao);
}

return model;
Expand Down
40 changes: 33 additions & 7 deletions src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.ReactiveUI;
using BaseStationReader.UI.ViewModels;
Expand All @@ -8,6 +9,8 @@ namespace BaseStationReader.UI;

public partial class AircraftLookupWindow : ReactiveWindow<AircraftLookupWindowViewModel>
{
private const string DetailsNotAvailableText = "Not available";

public AircraftLookupWindow()
{
InitializeComponent();
Expand All @@ -24,6 +27,10 @@ public AircraftLookupWindow()
private void OnLoaded(object? source, RoutedEventArgs e)
{
Address.Text = ViewModel?.Address ?? "";
if (!string.IsNullOrEmpty(Address.Text))
{
LookupAircraftDetails();
}
}

/// <summary>
Expand All @@ -33,19 +40,38 @@ private void OnLoaded(object? source, RoutedEventArgs e)
/// <param name="e"></param>
private void OnLookup(object source, RoutedEventArgs e)
{
// Store the current ICAO address
ViewModel!.Address = Address.Text;
LookupAircraftDetails();
}

/// <summary>
/// Look up the aircraft details and populate the dialog with the results
/// </summary>
private void LookupAircraftDetails()
{
// Search for the current ICAO address
var originalCursor = Cursor;
Cursor = new Cursor(StandardCursorType.Wait);
var details = ViewModel!.Search(Address.Text);
Cursor = originalCursor;

// Check we have some valid details
if (details != null)
{
// Result is valid, so populate the text blocks with the aircraft details
AirlineName.Text = details?.Airline?.Name ?? "";
ManufacturerName.Text = details?.Model?.Manufacturer.Name ?? "";
ModelName.Text = details?.Model?.Name ?? "";
ModelIATA.Text = details?.Model?.IATA ?? "";
ModelICAO.Text = details?.Model?.ICAO ?? "";
AirlineName.Text = details?.Airline?.Name ?? DetailsNotAvailableText;

Check warning on line 61 in src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs

View workflow job for this annotation

GitHub Actions / build

Change this expression which always evaluates to the same result.
ManufacturerName.Text = details?.Model?.Manufacturer.Name ?? DetailsNotAvailableText;

Check warning on line 62 in src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs

View workflow job for this annotation

GitHub Actions / build

Change this expression which always evaluates to the same result.
ModelName.Text = details?.Model?.Name ?? DetailsNotAvailableText;

Check warning on line 63 in src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs

View workflow job for this annotation

GitHub Actions / build

Change this expression which always evaluates to the same result.
ModelIATA.Text = details?.Model?.IATA ?? DetailsNotAvailableText;

Check warning on line 64 in src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs

View workflow job for this annotation

GitHub Actions / build

Change this expression which always evaluates to the same result.
ModelICAO.Text = details?.Model?.ICAO ?? DetailsNotAvailableText;

Check warning on line 65 in src/BaseStationReader.UI/Views/AircraftLookupWindow.axaml.cs

View workflow job for this annotation

GitHub Actions / build

Change this expression which always evaluates to the same result.
}
else
{
// No details availables, so set the default "not available" text
AirlineName.Text = DetailsNotAvailableText;
ManufacturerName.Text = DetailsNotAvailableText;
ModelName.Text = DetailsNotAvailableText;
ModelIATA.Text = DetailsNotAvailableText;
ModelICAO.Text = DetailsNotAvailableText;
}
}
}
48 changes: 41 additions & 7 deletions src/BaseStationReader.UI/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
private DispatcherTimer _timer = new DispatcherTimer();
private ITrackerLogger? _logger = null;
private bool _aircraftLookupIsEnabled = false;

public MainWindow()
{
Expand Down Expand Up @@ -63,6 +64,13 @@ private void OnLoaded(object? source, RoutedEventArgs e)
// Configure the column titles and visibility
ConfigureColumns(TrackedAircraftGrid);
ConfigureColumns(DatabaseGrid);

// The aircraft lookup option should only be available if there's a potentially valid API
// key in the settings. The enabled state is stored for future use enabling/disabling the
// row double-click handler
var key = ViewModel!.Settings.ApiServiceKeys.FirstOrDefault()?.Key;
_aircraftLookupIsEnabled = !string.IsNullOrEmpty(key);
AircraftLookupMenuItem.IsEnabled = _aircraftLookupIsEnabled;
}

/// <summary>
Expand Down Expand Up @@ -108,12 +116,13 @@ private void ConfigureColumns(DataGrid grid)
}

/// <summary>
/// Handler to set the background colour of a row based on aircraft staleness
/// Handler to configure row appearance and behaviour
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private void OnLoadingRow(object? source, DataGridRowEventArgs e)
{
// Set the row colour based on the aircraft staleness
var aircraft = e.Row.DataContext as Aircraft;
if (aircraft != null)
{
Expand All @@ -130,6 +139,34 @@ private void OnLoadingRow(object? source, DataGridRowEventArgs e)
break;
}
}

// Hook up the row tap handler
e.Row.Tapped += OnRowTapped;
}

/// <summary>
/// Handler for double-click events on a row
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private void OnRowTapped(object? source, TappedEventArgs e)
{
// Get the source as a grid row and check it's valid
var row = source as DataGridRow;
if (row != null)
{
// Valid row, so get the data context as an aircraft and check it's vali
var aircraft = row.DataContext as Aircraft;
if (aircraft != null)
{
// Valid, so set the ICAO address to search for to the aircraft address and trigger
// an aircraft lookup
ViewModel!.AircraftLookupCriteria = new AircraftLookupCriteria { Address = aircraft.Address };
ViewModel!.ShowAircraftLookupCommand?.Execute(null);
}
}

e.Handled = true;
}

/// <summary>
Expand Down Expand Up @@ -332,12 +369,9 @@ private async Task DoShowAircraftLookupAsync(InteractionContext<AircraftLookupWi
interaction.SetOutput(result);
#pragma warning restore CS8604

// Check we have a dialog result i.e. user didn't cancel
if (result != null)
{
// Capture the lookup criteria so they're retained next time the dialog is shown
ViewModel!.AircraftLookupCriteria = result;
}
// Clear the view model's aircraft lookup criteria - this stops it from automatically
// repeating the previous search when it's next opened
ViewModel!.AircraftLookupCriteria = null;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/BaseStationReader.UI/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,4 @@
"ConnectionStrings": {
"BaseStationReaderDB": "Data Source=C:\\MyApps\\aircrafttracker.db"
}
}
}

0 comments on commit 743d3ac

Please sign in to comment.