Compare commits

...
8 changed files with 95 additions and 26 deletions

No files matched your search

@@ -37,6 +37,7 @@ namespace bts.shell.manual_fills {
public ManualFillRow(ManualFillData data) {
_data = data;
persisted_data = data;
key = data.key;
_security = data.value.security;
_account = data.value.account;
@@ -93,6 +94,8 @@ namespace bts.shell.manual_fills {
public ManualFillData data => _data ??
(_data = new ManualFillData(key, new ManualFillTuple(new ManualFillImmutable(to_man_fill()), security, account, user))).Value;
public ManualFillData? persisted_data { get; }
public void revert() =>
_committed_snapshot.Dispose();
@@ -59,7 +59,7 @@
VerticalAlignment="Stretch"
CloseOnCancel="True"
CloseOnOK="True"
Header="{Binding security}"
Header="{Binding security, Converter={StaticResource EditableSecurityTextConverter}}"
IsEditMode="False"
IsLazy="True"
SecurityMap="{DynamicResource ResourceKey={x:Static u:ResourceKeys.Securities}}"
@@ -95,9 +95,13 @@ namespace bts.shell.manual_fills {
if (selection_mon.filtered_items.Count < _max_unconfirmed_removes || BTSMessageBox.Confirm($"Are you sure you want to delete {selection_mon.filtered_items.Count} fills?", "Delete Fills")) {
var persisted_fills = new List<ManualFill>();
foreach (var r in selection_mon.filtered_items.ToList()) {
if (r.placeholder_key.HasValue)
if (r.placeholder_key.HasValue) {
_placeholder_rows.RemoveSorted(r, _row_key_comparer);
else persisted_fills.Add(r.to_man_fill());
} else if (r.persisted_data.HasValue) {
// this should always be true if placeholder_key doesn't have a value,
// but it's [almost always] good practice to verify that a nullable has a value before accessing it.
persisted_fills.Add(r.persisted_data.Value.value.manual_fill.CloneToMutable());
}
}
await _model.delete_fills(persisted_fills);
}
@@ -129,7 +129,7 @@
<DataGridTemplateColumn c:DataGridEx.CellKey="{x:Static Security, MemberType={u:Nested usp:ManualFillsView.Columns}}" Header="Security" SortMemberPath="security">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding security}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding security, Converter={StaticResource EditableSecurityTextConverter}}" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
@@ -139,7 +139,7 @@
VerticalAlignment="Stretch"
CloseOnCancel="True"
CloseOnOK="True"
Header="{Binding security}"
Header="{Binding security, Converter={StaticResource EditableSecurityTextConverter}}"
IsEditMode="False"
IsLazy="True"
SecurityMap="{Binding DataContext.security_map, RelativeSource={RelativeSource AncestorType=DataGrid}, Mode=OneWay}"
+20 -21
View File
@@ -380,29 +380,17 @@ namespace mbts.spark {
_error.handle_error(result, template, r => r.ErrorCode, e => e == OrderError.Ok, r => new uint?(r.OrderKey));
#region Manual Fillls
public async Task<bool> create_manual_fills(IEnumerable<ManualFill> fills) {
return await create_manual_fills(_create_fill_batch(fills));
}
public async Task<bool> create_manual_fills(ManualFillBatchImmutable fills) {
var result = await _position_service.create_manual_fill_async(fills);
return _handle_error(result);
}
public async Task<bool> create_manual_fills(IEnumerable<ManualFill> fills) =>
(await _execute_manual_fill_op(fills, _position_service.create_manual_fill_async, "create manual fills"))
.success;
public async Task<bool> update_manual_fills(IEnumerable<ManualFill> fills) {
return await update_manual_fills(_create_fill_batch(fills));
}
public async Task<bool> update_manual_fills(ManualFillBatchImmutable fills) {
var result = await _position_service.update_manual_fill_async(fills);
return _handle_error(result);
}
public async Task<bool> update_manual_fills(IEnumerable<ManualFill> fills) =>
(await _execute_manual_fill_op(fills, _position_service.update_manual_fill_async, "update manual fills"))
.success;
public async Task<bool> delete_manual_fills(IEnumerable<ManualFill> fills) {
return await delete_manual_fills(_create_fill_batch(fills));
}
public async Task<bool> delete_manual_fills(ManualFillBatchImmutable fills) {
var result = await _position_service.remove_manual_fill_async(fills);
return _handle_error(result);
}
public async Task<bool> delete_manual_fills(IEnumerable<ManualFill> fills) =>
(await _execute_manual_fill_op(fills, _position_service.remove_manual_fill_async, "delete manual fills"))
.success;
ManualFillBatchImmutable _create_fill_batch(IEnumerable<ManualFill> fills) {
var batch = new ManualFillBatch();
@@ -415,6 +403,17 @@ namespace mbts.spark {
_error.report_error(result.error_message);
return result.value.Response.All(r => r.Ok);
}
Task<(PositionServiceResponse value, bool success)> _execute_manual_fill_op(
IEnumerable<ManualFill> fills,
Func<ManualFillBatchImmutable, Task<Result<PositionServiceResponse>>> execute_async,
string desc) =>
//
_error.safe_execute(
() => execute_async(_create_fill_batch(fills)),
r => r.Response.All(op => op.Ok),
r => string.Join("\n", r.Response.Where(op => op.Ok).Select(op => op.Msg)),
desc);
#endregion
#endregion
@@ -0,0 +1,15 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace mbts.ui.converters {
class StaticValueConverterWrapper : IValueConverter {
public object Value { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
Value;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
}
}
@@ -0,0 +1,43 @@
using bts.collections;
using System;
using System.Collections;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace mbts.ui.converters {
[ContentProperty(nameof(Map))]
class ConverterMap : IValueConverter {
readonly KeyedCollection<KeyConverter, object> _map = new KeyedCollection<KeyConverter, object>(kv => kv.Key);
public IList Map => _map;
public IValueConverter Default { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (_map.TryGetValue(value ?? KeyConverter.NullPlaceholder, out var kc)) {
return kc.Converter.Convert(value, targetType, parameter, culture);
} else if (Default != null) {
return Default.Convert(value, targetType, parameter, culture);
} else {
return value;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
}
[ContentProperty(nameof(Converter))]
class KeyConverter {
object _key;
// dictionaries/lookup classes typically prohibit null keys
public static object NullPlaceholder => new _NullPlaceholder();
public object Key { get => _key ?? NullPlaceholder; set => _key = value; }
public IValueConverter Converter { get; set; }
struct _NullPlaceholder {
public override bool Equals(object obj) => obj is _NullPlaceholder;
public override int GetHashCode() => -1;
}
}
}
@@ -28,6 +28,11 @@
<cv:CellPathConverter x:Key="CellPathConverter" />
<cv:CellKeyConverter x:Key="CellKeyConverter" />
<cv:SecurityDisplayTextConverter x:Key="SecurityTextConverter"/>
<cv:ConverterMap x:Key="EditableSecurityTextConverter" Default="{x:Static cv:ValueConverters.SimpleString}">
<cv:KeyConverter Key="{x:Null}">
<cv:StaticValueConverterWrapper Value="(None)"/>
</cv:KeyConverter>
</cv:ConverterMap>
<cv:NumericSignBrushConverter x:Key="NumericSignBrushConverter" />
<cv:TickDisplayTextConverter x:Key="TickTextConverter" />
<cv:DoubleTextConverter x:Key="DoubleTextConverter" />