using System;
using System.Collections.Generic;
using System.Linq;
using InABox.Clients;
using InABox.Core;
namespace InABox.DynamicGrid;
public interface IDynamicEditorHost
{
///
/// A list of columns which are defined for this editor; from this are loaded the additional columns for lookups. A useful default is just
/// to call , if a singular type for the editor is well-defined.
///
///
/// I'm still not sure whether this one is actually a good idea, but it seems to be how the editors have functioned for a while. My reasoning is that
/// if the lookup defines a column to be loaded, but it doesn't get loaded because it is not in this list, then we would have broken functionality.
///
IEnumerable Columns { get; }
///
/// Loads into all columns that start with the same prefix as ; e.g, when taking a
/// lookup defined for column EntityLink.ID, will contain all EntityLink.* except EntityLink.ID.
///
/// This essentially gives us the other columns we need to load from the database for lookups.
/// See for the canonical implementation.
///
///
/// This is dumb; we don't want it, because the presence of kinda makes it redundant.
///
/// The column to use the prefix of.
/// The dictionary into which the columns will be loaded, in the form "FieldName": "EntityLink.FieldName"
void LoadColumns(string column, Dictionary columns);
///
/// Trigger the loading of the lookup values; the canonical implementation calls ,
/// and calls (either sync/async) when the values are loaded.
///
/// The editor to load the lookups for.
void LoadLookups(ILookupEditorControl editor);
///
/// Get a document for a given filename.
///
///
/// The usual implementation will go through the interface.
///
/// The filename of the document.
/// The document with the right filename, or if not found.
Document? FindDocument(string filename)
{
return new Client().Load(new Filter(x => x.FileName).IsEqualTo(filename)).FirstOrDefault();
}
///
/// Get a document for a given ID.
///
///
/// The usual implementation will go through the interface.
///
/// The ID of the document.
/// The document, or if not found.
Document? GetDocument(Guid id)
{
return new Client().Load(new Filter(x => x.ID).IsEqualTo(id)).FirstOrDefault();
}
///
/// Saves a document.
///
///
/// The usual implementation will go through the interface.
///
/// The document to save.
void SaveDocument(Document document)
{
new Client().Save(document, "Updated by Editor");
}
///
/// Returns a list of the currently edited items; may be an empty array.
///
/// This should probably always be a [].
///
/// The items being edited.
BaseObject[] GetItems();
///
/// Return the type of the edited object.
///
///
Type GetEditorType();
///
/// Um... I'm really not sure; achieves the same function as - if you know what that does, good job.
///
///
/// I think you should be fine to just return .Editor, as defined by .
///
/// The column to get the editor of.
/// The editor, or if it doesn't exist.
BaseEditor? GetEditor(DynamicGridColumn column);
}
public class DefaultDynamicEditorHost : IDynamicEditorHost
where T : BaseObject
{
public virtual T[]? Items { get; set; }
public IEnumerable Columns => new DynamicGridColumns().ExtractColumns(typeof(T));
public BaseEditor? GetEditor(DynamicGridColumn column) => column.Editor.CloneEditor();
public BaseObject[] GetItems() => Items ?? Array.Empty();
public Type GetEditorType() => typeof(T);
public void LoadColumns(string column, Dictionary columns)
{
columns.Clear();
var comps = column.Split('.').ToList();
comps.RemoveAt(comps.Count - 1);
var prefix = string.Format("{0}.", string.Join(".", comps));
var cols = Columns.Where(x => !x.ColumnName.Equals(column) && x.ColumnName.StartsWith(prefix));
foreach (var col in cols)
columns[col.ColumnName.Replace(prefix, "")] = col.ColumnName;
}
public void LoadLookups(ILookupEditorControl sender)
{
var editor = sender.EditorDefinition as ILookupEditor;
var colname = sender.ColumnName;
var values = editor.Values(typeof(T), colname, Items);
sender.LoadLookups(values);
}
}