|
@@ -77,6 +77,17 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
var dataComponent = new DynamicGridClientDataComponent<TEntity>(this);
|
|
|
dataComponent.OnReload += DataComponent_OnReload;
|
|
|
DataComponent = dataComponent;
|
|
|
+
|
|
|
+ MergeBtn = AddButton("Merge", Wpf.Resources.merge.AsBitmapImage(Color.White), DoMerge);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void SelectItems(CoreRow[]? rows)
|
|
|
+ {
|
|
|
+ base.SelectItems(rows);
|
|
|
+ MergeBtn.Visibility = Options.MultiSelect && typeof(T).IsAssignableTo(typeof(IMergeable)) && Security.CanMerge<TEntity>()
|
|
|
+ && rows != null && rows.Length > 1
|
|
|
+ ? Visibility.Visible
|
|
|
+ : Visibility.Collapsed;
|
|
|
}
|
|
|
|
|
|
private void DataComponent_OnReload(object sender, Filters<TEntity> criteria, Columns<TEntity> columns, ref SortOrder<TEntity>? sortby)
|
|
@@ -89,6 +100,9 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
base.OptionsChanged();
|
|
|
|
|
|
FilterComponent.ShowFilterList = Options.FilterRows && !Options.HideDatabaseFilters;
|
|
|
+
|
|
|
+ if (MergeBtn != null)
|
|
|
+ MergeBtn.Visibility = Visibility.Collapsed;
|
|
|
}
|
|
|
|
|
|
protected override void DoReconfigure(DynamicGridOptions options)
|
|
@@ -125,83 +139,6 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- protected override string FormatRecordCount(int count)
|
|
|
- {
|
|
|
- return IsPaging
|
|
|
- ? $"{base.FormatRecordCount(count)} (loading..)"
|
|
|
- : base.FormatRecordCount(count);
|
|
|
- }
|
|
|
-
|
|
|
- private CoreRow[]? SelectedBeforeRefresh;
|
|
|
- protected override void OnAfterRefresh()
|
|
|
- {
|
|
|
- base.OnAfterRefresh();
|
|
|
-
|
|
|
- if (SelectedBeforeRefresh is not null)
|
|
|
- {
|
|
|
- var selectedValues = SelectedBeforeRefresh
|
|
|
- .Select(x => FilterColumns.Select(c => x[c.Property]).ToList())
|
|
|
- .ToList();
|
|
|
-
|
|
|
- SelectedBeforeRefresh = null;
|
|
|
-
|
|
|
- var selectedRows = Data.Rows.Where(r =>
|
|
|
- {
|
|
|
- return selectedValues.Any(v =>
|
|
|
- {
|
|
|
- for (int i = 0; i < v.Count; ++i)
|
|
|
- {
|
|
|
- if (v[i]?.Equals(r[FilterColumns[i].Property]) != true)
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
- });
|
|
|
- }).ToArray();
|
|
|
-
|
|
|
- SelectedRows = selectedRows;
|
|
|
- SelectItems(selectedRows);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public override void Refresh(bool reloadcolumns, bool reloaddata)
|
|
|
- {
|
|
|
- SelectedBeforeRefresh = SelectedRows;
|
|
|
- base.Refresh(reloadcolumns, reloaddata);
|
|
|
- }
|
|
|
-
|
|
|
- private object GetPropertyValue(Expression member, object obj)
|
|
|
- {
|
|
|
- var objectMember = Expression.Convert(member, typeof(object));
|
|
|
-
|
|
|
- var getterLambda = Expression.Lambda<Func<object>>(objectMember);
|
|
|
-
|
|
|
- var getter = getterLambda.Compile();
|
|
|
-
|
|
|
- return getter();
|
|
|
- }
|
|
|
-
|
|
|
- protected override void ObjectToRow(TEntity obj, CoreRow row)
|
|
|
- {
|
|
|
- foreach (var column in Data.Columns)
|
|
|
- {
|
|
|
- var prop = DatabaseSchema.Property(obj.GetType(), column.ColumnName);
|
|
|
- if (prop is StandardProperty)
|
|
|
- row.Set(column.ColumnName, CoreUtils.GetPropertyValue(obj, prop.Name));
|
|
|
- else if (prop is CustomProperty)
|
|
|
- row.Set(column.ColumnName, obj.UserProperties[column.ColumnName]);
|
|
|
- }
|
|
|
-
|
|
|
- //base.ObjectToRow(obj, row);
|
|
|
- }
|
|
|
-
|
|
|
- //private void Auditgrid_OnReload(object sender, Dictionary<string, object> criteria, ref String sort)
|
|
|
- //{
|
|
|
- // criteria["DocumentType"] = typeof(TEntity).EntityName();
|
|
|
- // criteria["DocumentID"] = (sender as FrameworkElement).Tag;
|
|
|
-
|
|
|
- // sort = "TimeStamp";
|
|
|
- //}
|
|
|
-
|
|
|
public override void LoadEditorButtons(TEntity item, DynamicEditorButtons buttons)
|
|
|
{
|
|
|
base.LoadEditorButtons(item, buttons);
|
|
@@ -209,9 +146,9 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
buttons.Add("Audit Trail", Wpf.Resources.view.AsBitmapImage(), item, AuditTrailClick);
|
|
|
}
|
|
|
|
|
|
- private void AuditTrailClick(object sender, object item)
|
|
|
+ private void AuditTrailClick(object sender, object? item)
|
|
|
{
|
|
|
- var entity = (TEntity)item;
|
|
|
+ var entity = (item as TEntity)!;
|
|
|
var window = new AuditWindow(entity.ID);
|
|
|
window.ShowDialog();
|
|
|
}
|
|
@@ -260,42 +197,7 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
new UserConfiguration<DynamicGridSettings>(tag).Save(settings);
|
|
|
}
|
|
|
|
|
|
- protected override BaseEditor? GetEditor(object item, DynamicGridColumn column)
|
|
|
- {
|
|
|
- var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == column.ColumnName);
|
|
|
- if (prop != null)
|
|
|
- return prop.Editor;
|
|
|
- return base.GetEditor(item, column);
|
|
|
- }
|
|
|
-
|
|
|
- protected override object? GetEditorValue(object item, string name)
|
|
|
- {
|
|
|
- if (item is TEntity entity)
|
|
|
- {
|
|
|
- var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == name);
|
|
|
- if (prop is CustomProperty)
|
|
|
- {
|
|
|
- if (entity.UserProperties.ContainsKey(name))
|
|
|
- return entity.UserProperties[name];
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return base.GetEditorValue(item, name);
|
|
|
- }
|
|
|
-
|
|
|
- protected override void SetEditorValue(object item, string name, object value)
|
|
|
- {
|
|
|
- var prop = DatabaseSchema.Properties(typeof(TEntity)).FirstOrDefault(x => x.Name == name);
|
|
|
- if (prop is CustomProperty && item is TEntity entity)
|
|
|
- {
|
|
|
- entity.UserProperties[name] = value;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- base.SetEditorValue(item, name, value);
|
|
|
- }
|
|
|
- }
|
|
|
+ #region Duplicate
|
|
|
|
|
|
protected bool Duplicate(
|
|
|
CoreRow row,
|
|
@@ -417,6 +319,8 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
return rows.Select(x => x.ToObject<TEntity>());
|
|
|
}
|
|
|
|
|
|
+ #endregion
|
|
|
+
|
|
|
protected override bool BeforePaste(IEnumerable<TEntity> items, ClipAction action)
|
|
|
{
|
|
|
if (action == ClipAction.Copy)
|
|
@@ -429,38 +333,6 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
return base.BeforePaste(items, action);
|
|
|
}
|
|
|
|
|
|
- protected override void CustomiseExportFilters(Filters<TEntity> filters, CoreRow[] visiblerows)
|
|
|
- {
|
|
|
- base.CustomiseExportFilters(filters, visiblerows);
|
|
|
-
|
|
|
- /*if (IsEntity)
|
|
|
- {
|
|
|
- var ids = visiblerows.Select(r => r.Get<TEntity, Guid>(c => c.ID)).ToArray();
|
|
|
- filters.Add(new Filter<TEntity>(x => x.ID).InList(ids));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Filter<TEntity>? filter = null;
|
|
|
-
|
|
|
- foreach (var row in visiblerows)
|
|
|
- {
|
|
|
- var rowFilter = GetRowFilter(row);
|
|
|
- if(rowFilter is not null)
|
|
|
- {
|
|
|
- if (filter is null)
|
|
|
- {
|
|
|
- filter = rowFilter;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- filter.Or(rowFilter);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- filters.Add(filter);
|
|
|
- }*/
|
|
|
- }
|
|
|
-
|
|
|
protected override IEnumerable<Tuple<Type?, CoreTable>> LoadExportTables(Filters<TEntity> filter, IEnumerable<Tuple<Type, IColumns>> tableColumns)
|
|
|
{
|
|
|
var queries = new Dictionary<string, IQueryDef>();
|
|
@@ -515,4 +387,97 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
|
|
|
return Client.Query(null, Columns.None<TEntity>().Add(fields));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ #region Merge
|
|
|
+
|
|
|
+ private bool DoMerge(Button arg1, CoreRow[] arg2)
|
|
|
+ {
|
|
|
+ if (arg2 == null || arg2.Length <= 1)
|
|
|
+ return false;
|
|
|
+ var targetid = arg2.Last().Get<T, Guid>(x => x.ID);
|
|
|
+ var target = arg2.Last().ToObject<T>().ToString();
|
|
|
+ var otherids = arg2.Select(r => r.Get<T, Guid>(x => x.ID)).Where(x => x != targetid).ToArray();
|
|
|
+ string[] others = arg2.Where(r => otherids.Contains(r.Get<Guid>("ID"))).Select(x => x.ToObject<T>().ToString()!).ToArray();
|
|
|
+ var rows = arg2.Length;
|
|
|
+ if (MessageBox.Show(
|
|
|
+ string.Format(
|
|
|
+ "This will merge the following items:\n\n- {0}\n\n into:\n\n- {1}\n\nAfter this, the items will be permanently removed.\nAre you sure you wish to do this?",
|
|
|
+ string.Join("\n- ", others),
|
|
|
+ target
|
|
|
+ ),
|
|
|
+ "Merge Items Warning",
|
|
|
+ MessageBoxButton.YesNo,
|
|
|
+ MessageBoxImage.Stop) != MessageBoxResult.Yes
|
|
|
+ )
|
|
|
+ return false;
|
|
|
+
|
|
|
+ using (new WaitCursor())
|
|
|
+ {
|
|
|
+ var types = CoreUtils.Entities.Where(
|
|
|
+ x =>
|
|
|
+ x.IsClass
|
|
|
+ && !x.IsGenericType
|
|
|
+ && x.IsSubclassOf(typeof(Entity))
|
|
|
+ && !x.Equals(typeof(AuditTrail))
|
|
|
+ && !x.Equals(typeof(T))
|
|
|
+ && x.GetCustomAttribute<AutoEntity>() == null
|
|
|
+ && x.HasInterface<IRemotable>()
|
|
|
+ && x.HasInterface<IPersistent>()
|
|
|
+ ).ToArray();
|
|
|
+
|
|
|
+ foreach (var type in types)
|
|
|
+ {
|
|
|
+ var props = CoreUtils.PropertyList(
|
|
|
+ type,
|
|
|
+ x =>
|
|
|
+ x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
|
|
|
+ && x.PropertyType.GetInheritedGenericTypeArguments().Contains(typeof(T))
|
|
|
+ );
|
|
|
+ foreach (var prop in props)
|
|
|
+ {
|
|
|
+ var propname = string.Format(prop.Name + ".ID");
|
|
|
+ var filter = Core.Filter.Create(type);
|
|
|
+ filter.Expression = CoreUtils.CreateMemberExpression(type, propname);
|
|
|
+ filter.Operator = Operator.InList;
|
|
|
+ filter.Value = otherids;
|
|
|
+ var columns = Columns.None(type)
|
|
|
+ .Add("ID")
|
|
|
+ .Add(propname);
|
|
|
+ var updates = ClientFactory.CreateClient(type).Query(filter, columns).Rows.Select(r => r.ToObject(type)).ToArray();
|
|
|
+ if (updates.Any())
|
|
|
+ {
|
|
|
+ foreach (var update in updates)
|
|
|
+ CoreUtils.SetPropertyValue(update, propname, targetid);
|
|
|
+ ClientFactory.CreateClient(type).Save(updates,
|
|
|
+ string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var histories = new Client<AuditTrail>()
|
|
|
+ .Query(
|
|
|
+ new Filter<AuditTrail>(x => x.EntityID).InList(otherids),
|
|
|
+ Columns.None<AuditTrail>()
|
|
|
+ .Add(x => x.ID).Add(x => x.EntityID))
|
|
|
+ .ToArray<AuditTrail>();
|
|
|
+ foreach (var history in histories)
|
|
|
+ history.EntityID = targetid;
|
|
|
+ if (histories.Length != 0)
|
|
|
+ new Client<AuditTrail>().Save(histories, "");
|
|
|
+
|
|
|
+ var deletes = new List<object>();
|
|
|
+ foreach (var otherid in otherids)
|
|
|
+ {
|
|
|
+ var delete = new T();
|
|
|
+ CoreUtils.SetPropertyValue(delete, "ID", otherid);
|
|
|
+ deletes.Add(delete);
|
|
|
+ }
|
|
|
+
|
|
|
+ ClientFactory.CreateClient(typeof(T))
|
|
|
+ .Delete(deletes, string.Format("Merged {0} Records", typeof(T).EntityName().Split('.').Last()));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
}
|