Fingerprints filter for records station computer (#15017)

* add new labels and buttons for records stantion console

* add fingerprint fields for server

* set buttons and updates for fingerPrints filters

* set fingerprints filters

* final set for finger prints filters

* add new trhaslates for station records computer

* some fix for the PR

* refactor server side station record console system

* add message for filters

* add tranlates

* add new ui with several filters

* updetes prints with server side logic

* resolve conflicts with DNA

* resolve conflicts with DNA

* deleted unused variable and rename some fields

* added description for new state

* added select for filter

* set multiplay filters for the console

* added new translates

* add class filters &  fixed issue with reset line edit

* fix dublicate with set the  selectId for option button

* fixed review notes

* fixed review notes forget changet fix name

* add event TextEntered for better usability

* fixed review notes 3

* fixed formating in xaml

* fixed array with _filterTypes

* fixed ui and made it in minimalistic style

* fixed generalstationRecordFilter class, move method

* delete margin after line edit

* fix placeholder for lineEdit

* fix placeholder for lineEdit, the review note

* Revert "fixed generalstationRecordFilter class, move method"

This reverts commit 1b35c6ac44e7dafe9a1f0560eb177152b822f20b.

* impliment short swith in method IsSkippedRecord

* fixed review notes, remaked method IsSkipped and fix casing

* fixed the review note about check null record name
This commit is contained in:
Artjom
2023-04-12 17:27:13 +03:00
committed by GitHub
parent c4fd54eefb
commit d3936b24fe
8 changed files with 223 additions and 24 deletions

View File

@@ -16,6 +16,7 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt
_window = new(); _window = new();
_window.OnKeySelected += OnKeySelected; _window.OnKeySelected += OnKeySelected;
_window.OnFiltersChanged += OnFiltersChanged;
_window.OnClose += Close; _window.OnClose += Close;
_window.OpenCentered(); _window.OpenCentered();
@@ -26,6 +27,13 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt
SendMessage(new SelectGeneralStationRecord(key)); SendMessage(new SelectGeneralStationRecord(key));
} }
private void OnFiltersChanged(
GeneralStationRecordFilterType type, string filterValue)
{
GeneralStationRecordsFilterMsg msg = new(type, filterValue);
SendMessage(msg);
}
protected override void UpdateState(BoundUserInterfaceState state) protected override void UpdateState(BoundUserInterfaceState state)
{ {
base.UpdateState(state); base.UpdateState(state);

View File

@@ -1,17 +1,26 @@
<DefaultWindow xmlns="https://spacestation14.io" <DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'general-station-record-console-window-title'}" Title="{Loc 'general-station-record-console-window-title'}"
MinSize="750 500"> MinSize="750 500">
<BoxContainer> <BoxContainer Orientation="Vertical">
<!-- Record listing --> <BoxContainer Margin="5 5 5 10" HorizontalExpand="true" VerticalAlignment="Center">
<BoxContainer Orientation="Vertical" Margin="5 5 5 5" MinWidth="250" VerticalExpand="True"> <OptionButton Name="StationRecordsFilterType" MinWidth="200" Margin="0 0 10 0"/>
<Label Name="RecordListingStatus" Visible="False" /> <LineEdit Name="StationRecordsFiltersValue"
<ScrollContainer VerticalExpand="True"> PlaceHolder="{Loc 'general-station-record-for-filter-line-placeholder'}" HorizontalExpand="True"/>
<ItemList Name="RecordListing" /> <Button Name="StationRecordsFilters" Text="{Loc 'general-station-record-console-search-records'}"/>
</ScrollContainer> <Button Name="StationRecordsFiltersReset" Text="{Loc 'general-station-record-console-reset-filters'}"/>
</BoxContainer> </BoxContainer>
<BoxContainer Orientation="Vertical" Margin="5 5 5 5"> <BoxContainer VerticalExpand="True">
<Label Name="RecordContainerStatus" Visible="False" Text="{Loc 'general-station-record-console-select-record-info'}"/> <!-- Record listing -->
<BoxContainer Name="RecordContainer" Orientation="Vertical" /> <BoxContainer Orientation="Vertical" Margin="5" MinWidth="250" MaxWidth="250">
<Label Name="RecordListingStatus" Visible="False" />
<ScrollContainer VerticalExpand="True">
<ItemList Name="RecordListing" />
</ScrollContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" Margin="5">
<Label Name="RecordContainerStatus" Visible="False" Text="{Loc 'general-station-record-console-select-record-info'}"/>
<BoxContainer Name="RecordContainer" Orientation="Vertical" />
</BoxContainer>
</BoxContainer> </BoxContainer>
</BoxContainer> </BoxContainer>
</DefaultWindow> </DefaultWindow>

View File

@@ -12,12 +12,24 @@ namespace Content.Client.StationRecords;
public sealed partial class GeneralStationRecordConsoleWindow : DefaultWindow public sealed partial class GeneralStationRecordConsoleWindow : DefaultWindow
{ {
public Action<StationRecordKey?>? OnKeySelected; public Action<StationRecordKey?>? OnKeySelected;
public Action<GeneralStationRecordFilterType, string>? OnFiltersChanged;
private bool _isPopulating; private bool _isPopulating;
private GeneralStationRecordFilterType _currentFilterType;
public GeneralStationRecordConsoleWindow() public GeneralStationRecordConsoleWindow()
{ {
RobustXamlLoader.Load(this); RobustXamlLoader.Load(this);
_currentFilterType = GeneralStationRecordFilterType.Name;
foreach (var item in Enum.GetValues<GeneralStationRecordFilterType>())
{
StationRecordsFilterType.AddItem(GetTypeFilterLocals(item), (int)item);
}
RecordListing.OnItemSelected += args => RecordListing.OnItemSelected += args =>
{ {
if (_isPopulating || RecordListing[args.ItemIndex].Metadata is not StationRecordKey cast) if (_isPopulating || RecordListing[args.ItemIndex].Metadata is not StationRecordKey cast)
@@ -33,20 +45,66 @@ public sealed partial class GeneralStationRecordConsoleWindow : DefaultWindow
if (!_isPopulating) if (!_isPopulating)
OnKeySelected?.Invoke(null); OnKeySelected?.Invoke(null);
}; };
StationRecordsFilterType.OnItemSelected += eventArgs =>
{
var type = (GeneralStationRecordFilterType)eventArgs.Id;
if (_currentFilterType != type)
{
_currentFilterType = type;
FilterListingOfRecords();
}
};
StationRecordsFiltersValue.OnTextEntered += args =>
{
FilterListingOfRecords(args.Text);
};
StationRecordsFilters.OnPressed += _ =>
{
FilterListingOfRecords(StationRecordsFiltersValue.Text);
};
StationRecordsFiltersReset.OnPressed += _ =>
{
StationRecordsFiltersValue.Text = "";
FilterListingOfRecords();
};
} }
public void UpdateState(GeneralStationRecordConsoleState state) public void UpdateState(GeneralStationRecordConsoleState state)
{ {
if (state.Filter != null)
{
if (state.Filter.Type != _currentFilterType)
{
_currentFilterType = state.Filter.Type;
}
if (state.Filter.Value != StationRecordsFiltersValue.Text)
{
StationRecordsFiltersValue.Text = state.Filter.Value;
}
}
StationRecordsFilterType.SelectId((int)_currentFilterType);
if (state.RecordListing == null) if (state.RecordListing == null)
{ {
RecordListingStatus.Visible = true; RecordListingStatus.Visible = true;
RecordListing.Visible = false; RecordListing.Visible = false;
RecordListingStatus.Text = Loc.GetString("general-station-record-console-empty-state"); RecordListingStatus.Text = Loc.GetString("general-station-record-console-empty-state");
RecordContainer.Visible = false;
RecordContainerStatus.Visible = false;
return; return;
} }
RecordListingStatus.Visible = false; RecordListingStatus.Visible = false;
RecordListing.Visible = true; RecordListing.Visible = true;
RecordContainer.Visible = true;
PopulateRecordListing(state.RecordListing!, state.SelectedKey); PopulateRecordListing(state.RecordListing!, state.SelectedKey);
RecordContainerStatus.Visible = state.Record == null; RecordContainerStatus.Visible = state.Record == null;
@@ -65,18 +123,17 @@ public sealed partial class GeneralStationRecordConsoleWindow : DefaultWindow
RecordContainer.RemoveAllChildren(); RecordContainer.RemoveAllChildren();
} }
} }
private void PopulateRecordListing(Dictionary<StationRecordKey, string> listing, StationRecordKey? selected) private void PopulateRecordListing(Dictionary<StationRecordKey, string> listing, StationRecordKey? selected)
{ {
RecordListing.Clear(); RecordListing.Clear();
RecordListing.ClearSelected(); RecordListing.ClearSelected();
_isPopulating = true; _isPopulating = true;
foreach (var (key, name) in listing) foreach (var (key, name) in listing)
{ {
var item = RecordListing.AddItem(name); var item = RecordListing.AddItem(name);
item.Metadata = key; item.Metadata = key;
if (selected != null && key.ID == selected.Value.ID) if (selected != null && key.ID == selected.Value.ID)
{ {
item.Selected = true; item.Selected = true;
@@ -131,4 +188,17 @@ public sealed partial class GeneralStationRecordConsoleWindow : DefaultWindow
RecordContainer.AddChild(control); RecordContainer.AddChild(control);
} }
} }
private void FilterListingOfRecords(string text = "")
{
if (!_isPopulating)
{
OnFiltersChanged?.Invoke(_currentFilterType, text);
}
}
private string GetTypeFilterLocals(GeneralStationRecordFilterType type)
{
return Loc.GetString($"general-station-record-{type.ToString().ToLower()}-filter");
}
} }

View File

@@ -6,4 +6,5 @@ namespace Content.Server.StationRecords;
public sealed class GeneralStationRecordConsoleComponent : Component public sealed class GeneralStationRecordConsoleComponent : Component
{ {
public StationRecordKey? ActiveKey { get; set; } public StationRecordKey? ActiveKey { get; set; }
public GeneralStationRecordsFilter? Filter { get; set; }
} }

View File

@@ -1,6 +1,7 @@
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.StationRecords; using Content.Shared.StationRecords;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using System.Linq;
namespace Content.Server.StationRecords.Systems; namespace Content.Server.StationRecords.Systems;
@@ -14,6 +15,7 @@ public sealed class GeneralStationRecordConsoleSystem : EntitySystem
{ {
SubscribeLocalEvent<GeneralStationRecordConsoleComponent, BoundUIOpenedEvent>(UpdateUserInterface); SubscribeLocalEvent<GeneralStationRecordConsoleComponent, BoundUIOpenedEvent>(UpdateUserInterface);
SubscribeLocalEvent<GeneralStationRecordConsoleComponent, SelectGeneralStationRecord>(OnKeySelected); SubscribeLocalEvent<GeneralStationRecordConsoleComponent, SelectGeneralStationRecord>(OnKeySelected);
SubscribeLocalEvent<GeneralStationRecordConsoleComponent, GeneralStationRecordsFilterMsg>(OnFiltersChanged);
SubscribeLocalEvent<GeneralStationRecordConsoleComponent, RecordModifiedEvent>(UpdateUserInterface); SubscribeLocalEvent<GeneralStationRecordConsoleComponent, RecordModifiedEvent>(UpdateUserInterface);
SubscribeLocalEvent<GeneralStationRecordConsoleComponent, AfterGeneralRecordCreatedEvent>(UpdateUserInterface); SubscribeLocalEvent<GeneralStationRecordConsoleComponent, AfterGeneralRecordCreatedEvent>(UpdateUserInterface);
} }
@@ -30,7 +32,19 @@ public sealed class GeneralStationRecordConsoleSystem : EntitySystem
UpdateUserInterface(uid, component); UpdateUserInterface(uid, component);
} }
private void UpdateUserInterface(EntityUid uid, GeneralStationRecordConsoleComponent? console = null) private void OnFiltersChanged(EntityUid uid,
GeneralStationRecordConsoleComponent component, GeneralStationRecordsFilterMsg msg)
{
if (component.Filter == null ||
component.Filter.Type != msg.Type || component.Filter.Value != msg.Value)
{
component.Filter = new GeneralStationRecordsFilter(msg.Type, msg.Value);
UpdateUserInterface(uid, component);
}
}
private void UpdateUserInterface(EntityUid uid,
GeneralStationRecordConsoleComponent? console = null)
{ {
if (!Resolve(uid, ref console)) if (!Resolve(uid, ref console))
{ {
@@ -39,27 +53,39 @@ public sealed class GeneralStationRecordConsoleSystem : EntitySystem
var owningStation = _stationSystem.GetOwningStation(uid); var owningStation = _stationSystem.GetOwningStation(uid);
if (!TryComp<StationRecordsComponent>(owningStation, out var stationRecordsComponent)) if (!TryComp<StationRecordsComponent>(owningStation, out var stationRecordsComponent))
{ {
_userInterface.GetUiOrNull(uid, GeneralStationRecordConsoleKey.Key)?.SetState(new GeneralStationRecordConsoleState(null, null, null)); GeneralStationRecordConsoleState state = new(null, null, null, null);
SetStateForInterface(uid, state);
return; return;
} }
var enumerator = _stationRecordsSystem.GetRecordsOfType<GeneralStationRecord>(owningStation.Value, stationRecordsComponent); var consoleRecords =
_stationRecordsSystem.GetRecordsOfType<GeneralStationRecord>(owningStation.Value, stationRecordsComponent);
var listing = new Dictionary<StationRecordKey, string>(); var listing = new Dictionary<StationRecordKey, string>();
foreach (var pair in enumerator)
foreach (var pair in consoleRecords)
{ {
if (console != null && console.Filter != null
&& IsSkippedRecord(console.Filter, pair.Item2))
{
continue;
}
listing.Add(pair.Item1, pair.Item2.Name); listing.Add(pair.Item1, pair.Item2.Name);
} }
if (listing.Count == 0) if (listing.Count == 0)
{ {
_userInterface.GetUiOrNull(uid, GeneralStationRecordConsoleKey.Key)?.SetState(new GeneralStationRecordConsoleState(null, null, null)); GeneralStationRecordConsoleState state = new(null, null, null, console.Filter);
SetStateForInterface(uid, state);
return; return;
} }
else if (listing.Count == 1)
{
console.ActiveKey = listing.Keys.First();
}
GeneralStationRecord? record = null; GeneralStationRecord? record = null;
if (console.ActiveKey != null) if (console.ActiveKey != null)
@@ -68,8 +94,41 @@ public sealed class GeneralStationRecordConsoleSystem : EntitySystem
stationRecordsComponent); stationRecordsComponent);
} }
GeneralStationRecordConsoleState newState = new(console.ActiveKey, record, listing, console.Filter);
SetStateForInterface(uid, newState);
}
private void SetStateForInterface(EntityUid uid, GeneralStationRecordConsoleState newState)
{
_userInterface _userInterface
.GetUiOrNull(uid, GeneralStationRecordConsoleKey.Key)? .GetUiOrNull(uid, GeneralStationRecordConsoleKey.Key)
.SetState(new GeneralStationRecordConsoleState(console.ActiveKey, record, listing)); ?.SetState(newState);
}
private bool IsSkippedRecord(GeneralStationRecordsFilter filter,
GeneralStationRecord someRecord)
{
bool isFilter = filter.Value.Length > 0;
string filterLowerCaseValue = "";
if (!isFilter)
return false;
filterLowerCaseValue = filter.Value.ToLower();
return filter.Type switch
{
GeneralStationRecordFilterType.Name =>
!someRecord.Name.ToLower().Contains(filterLowerCaseValue),
GeneralStationRecordFilterType.Prints => someRecord.Fingerprint != null
&& IsFilterWithSomeCodeValue(someRecord.Fingerprint, filterLowerCaseValue),
GeneralStationRecordFilterType.DNA => someRecord.DNA != null
&& IsFilterWithSomeCodeValue(someRecord.DNA, filterLowerCaseValue),
};
}
private bool IsFilterWithSomeCodeValue(string value, string filter)
{
return !value.ToLower().StartsWith(filter);
} }
} }

View File

@@ -0,0 +1,38 @@
using Robust.Shared.Serialization;
namespace Content.Shared.StationRecords;
[Serializable, NetSerializable]
public sealed class GeneralStationRecordsFilter
{
public GeneralStationRecordFilterType Type { get; set; }
= GeneralStationRecordFilterType.Name;
public string Value { get; set; } = "";
public GeneralStationRecordsFilter(GeneralStationRecordFilterType filterType, string newValue = "")
{
Type = filterType;
Value = newValue;
}
}
[Serializable, NetSerializable]
public sealed class GeneralStationRecordsFilterMsg : BoundUserInterfaceMessage
{
public string Value { get; }
public GeneralStationRecordFilterType Type { get; }
public GeneralStationRecordsFilterMsg(GeneralStationRecordFilterType filterType,
string filterValue)
{
Type = filterType;
Value = filterValue;
}
}
[Serializable, NetSerializable]
public enum GeneralStationRecordFilterType : byte
{
Name,
Prints,
DNA,
}

View File

@@ -20,6 +20,10 @@ public enum GeneralStationRecordConsoleKey : byte
/// - SelectedKey non-null, Record non-null, RecordListing non-null /// - SelectedKey non-null, Record non-null, RecordListing non-null
/// - The selected key has a record tied to it, and the record has been sent. /// - The selected key has a record tied to it, and the record has been sent.
/// ///
/// - there is added new filters and so added new states
/// -SelectedKey null, Record null, RecordListing null, filters non-null
/// the station may have data, but they all did not pass through the filters
///
/// Other states are erroneous. /// Other states are erroneous.
/// </summary> /// </summary>
[Serializable, NetSerializable] [Serializable, NetSerializable]
@@ -31,15 +35,18 @@ public sealed class GeneralStationRecordConsoleState : BoundUserInterfaceState
public StationRecordKey? SelectedKey { get; } public StationRecordKey? SelectedKey { get; }
public GeneralStationRecord? Record { get; } public GeneralStationRecord? Record { get; }
public Dictionary<StationRecordKey, string>? RecordListing { get; } public Dictionary<StationRecordKey, string>? RecordListing { get; }
public GeneralStationRecordsFilter? Filter { get; }
public GeneralStationRecordConsoleState(StationRecordKey? key, GeneralStationRecord? record, Dictionary<StationRecordKey, string>? recordListing) public GeneralStationRecordConsoleState(StationRecordKey? key, GeneralStationRecord? record,
Dictionary<StationRecordKey, string>? recordListing, GeneralStationRecordsFilter? newFilter)
{ {
SelectedKey = key; SelectedKey = key;
Record = record; Record = record;
RecordListing = recordListing; RecordListing = recordListing;
Filter = newFilter;
} }
public bool IsEmpty() => SelectedKey == null && Record == null && RecordListing == null; public bool IsEmpty() => SelectedKey == null
&& Record == null && RecordListing == null;
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]

View File

@@ -9,3 +9,10 @@ general-station-record-console-record-species = Species: {$species}
general-station-record-console-record-gender = Gender: {$gender} general-station-record-console-record-gender = Gender: {$gender}
general-station-record-console-record-fingerprint = Fingerprint: {$fingerprint} general-station-record-console-record-fingerprint = Fingerprint: {$fingerprint}
general-station-record-console-record-dna = DNA: {$dna} general-station-record-console-record-dna = DNA: {$dna}
general-station-record-for-filter-line-placeholder = Input text and press "Enter"
general-station-record-name-filter = Name of person
general-station-record-prints-filter = Fingerprints
general-station-record-dna-filter = DNA
general-station-record-console-search-records = Search
general-station-record-console-reset-filters = Reset