diff --git a/.idea/.idea.HopFrame/.idea/workspace.xml b/.idea/.idea.HopFrame/.idea/workspace.xml index e3831a5..fd35196 100644 --- a/.idea/.idea.HopFrame/.idea/workspace.xml +++ b/.idea/.idea.HopFrame/.idea/workspace.xml @@ -12,9 +12,22 @@ - + + + + + - + + + + + + + + + + @@ -715,7 +729,6 @@ \ No newline at end of file diff --git a/src/HopFrame.Core/Config/HopFrameConfig.cs b/src/HopFrame.Core/Config/HopFrameConfig.cs index 57aabde..53b0ee9 100644 --- a/src/HopFrame.Core/Config/HopFrameConfig.cs +++ b/src/HopFrame.Core/Config/HopFrameConfig.cs @@ -24,6 +24,10 @@ public sealed class HopFrameConfigurator(HopFrameConfig config, IServiceCollecti /// public HopFrameConfig InnerConfig { get; } = config; + /// + /// The of the application. + /// WARNING: Only use this during application building phase + /// public IServiceCollection ServiceCollection { get; } = collection; /// diff --git a/src/HopFrame.Core/Config/PropertyConfig.cs b/src/HopFrame.Core/Config/PropertyConfig.cs index bb96fd6..563b1da 100644 --- a/src/HopFrame.Core/Config/PropertyConfig.cs +++ b/src/HopFrame.Core/Config/PropertyConfig.cs @@ -36,7 +36,9 @@ public class PropertyConfig(PropertyInfo info, TableConfig table, int nthPropert } } +/// public sealed class VirtualPropertyConfig(TableConfig table, int nthProperty) : PropertyConfig(GetDummyProperty(), table, nthProperty) { + public string? DummyProperty { get; set; } = null; public Func? VirtualParser { get; set; } @@ -69,6 +71,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Sets the title displayed in the table header and edit dialog /// + /// The new name of the property public PropertyConfigurator SetDisplayName(string displayName) { InnerConfig.Name = displayName; return this; @@ -77,6 +80,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the property should appear in the table, if not the property is also set to be not searchable /// + /// The toggle for the option /// public PropertyConfigurator List(bool list) { InnerConfig.List = list; @@ -87,6 +91,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the table can be sorted by the property /// + /// The toggle for the option public PropertyConfigurator IsSortable(bool sortable) { InnerConfig.Sortable = sortable; return this; @@ -95,6 +100,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the property get taken into account for search results /// + /// The toggle for the option public PropertyConfigurator IsSearchable(bool searchable) { InnerConfig.Searchable = searchable; return this; @@ -103,6 +109,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the value that should be displayed instead of the string representation of the type /// + /// The expression that points at the property that should be used public PropertyConfigurator SetDisplayedProperty(Expression> propertyExpression) { InnerConfig.DisplayedProperty = TableConfigurator.GetPropertyInfo(propertyExpression); return this; @@ -111,6 +118,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the value that's displayed in the admin ui /// + /// The function that formats the given entity /// public PropertyConfigurator Format(Func formatter) { InnerConfig.Formatter = (obj, provider) => Task.FromResult(formatter.Invoke((TProp)obj, provider)); @@ -126,6 +134,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the value that's displayed for each entry in the list /// + /// The function that formats each given element public PropertyConfigurator FormatEach(Func formatter) { InnerConfig.EnumerableFormatter = (obj, provider) => Task.FromResult(formatter.Invoke((TInnerProp)obj, provider)); return this; @@ -140,6 +149,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the function used for parsing the value provided in the editor dialog to the actual property value /// + /// The function that converts the user input to the desired type public PropertyConfigurator SetParser(Func parser) { InnerConfig.Parser = (str, provider) => Task.FromResult(parser.Invoke(str, provider)!); return this; @@ -154,6 +164,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the value can be edited in the admin ui. If true, the value can still be initially set, but not modified /// + /// The toggle for the option /// public PropertyConfigurator SetEditable(bool editable) { InnerConfig.Editable = editable; @@ -163,6 +174,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the initial value can be edited in the admin ui. If true the value will not be visible in the create dialog /// + /// The toggle for the option /// public PropertyConfigurator SetCreatable(bool creatable) { InnerConfig.Creatable = creatable; @@ -172,6 +184,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the value should be displayed in the admin ui (useful for secrets like passwords etc.) /// + /// The toggle for the option public PropertyConfigurator DisplayValue(bool display) { InnerConfig.DisplayValue = display; return this; @@ -180,6 +193,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines if the admin ui should use a text area for modifying the value /// + /// The toggle for the option /// public PropertyConfigurator IsTextArea(bool textField) { InnerConfig.TextArea = textField; @@ -189,6 +203,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the initial size of the text area field /// + /// The number of rows (height) the text area field should have /// public PropertyConfigurator SetTextAreaRows(int rows) { InnerConfig.TextAreaRows = rows; @@ -198,14 +213,18 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the validator used for the property value before saving /// + /// + /// The function that validates the given input. + /// + /// It takes in the parsed property and an + /// and returns an error list. If the list is empty, the property passes the check. + /// public PropertyConfigurator SetValidator(Func> validator) { InnerConfig.Validator = (obj, provider) => Task.FromResult(validator.Invoke((TProp?)obj, provider)); return this; } - /// - /// Determines the validator used for the property value before saving - /// + /// public PropertyConfigurator SetValidator(Func>> validator) { InnerConfig.Validator = (obj, provider) => validator.Invoke((TProp?)obj, provider); return this; @@ -214,6 +233,7 @@ public class PropertyConfigurator(PropertyConfig config) { /// /// Determines the order index for the property in the admin ui /// + /// The value for the option /// public PropertyConfigurator SetOrderIndex(int index) { InnerConfig.Order = index; @@ -242,10 +262,12 @@ public class PropertyConfigurator(PropertyConfig config) { } } +/// public sealed class VirtualPropertyConfigurator(VirtualPropertyConfig config) : PropertyConfigurator(config) { /// /// Determines the function used for parsing the value provided in the editor dialog to the actual model value /// + /// The function that takes in the parent object and the user input and applies all necessary changes public VirtualPropertyConfigurator SetVirtualParser(Action parser) { var cfg = InnerConfig as VirtualPropertyConfig; @@ -256,8 +278,8 @@ public sealed class VirtualPropertyConfigurator(VirtualPropertyConfig co return this; } - - /// + + /// public VirtualPropertyConfigurator SetVirtualParser(Func parser) { var cfg = InnerConfig as VirtualPropertyConfig; diff --git a/src/HopFrame.Core/Config/TableConfig.cs b/src/HopFrame.Core/Config/TableConfig.cs index 48e860b..eb6b9e4 100644 --- a/src/HopFrame.Core/Config/TableConfig.cs +++ b/src/HopFrame.Core/Config/TableConfig.cs @@ -63,6 +63,7 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines if the table should be ignored in the admin ui /// + /// The toggle for the option public TableConfigurator Ignore(bool ignore = true) { InnerConfig.Ignored = ignore; return this; @@ -70,6 +71,7 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines if search suggestions should be displayed in the ui (Advanced Search) /// + /// The toggle for the option public TableConfigurator ShowSearchSuggestions(bool show = true) { InnerConfig.ShowSearchSuggestions = show; return this; @@ -144,6 +146,7 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the name for the table used in the admin ui and url for the table page /// + /// The value for the option public TableConfigurator SetDisplayName(string name) { InnerConfig.DisplayName = name; return this; @@ -152,6 +155,7 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the description displayed in the admin ui /// + /// The value for the option public TableConfigurator SetDescription(string description) { InnerConfig.Description = description; return this; @@ -160,6 +164,7 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the order index for the table in the admin ui /// + /// The value for the option /// public TableConfigurator SetOrderIndex(int index) { InnerConfig.Order = index; @@ -169,6 +174,8 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the policy needed by a user in order to view the table /// + /// The value for the option + /// public TableConfigurator SetViewPolicy(string policy) { InnerConfig.ViewPolicy = policy; return this; @@ -177,6 +184,8 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the policy needed by a user in order to edit the entries /// + /// The value for the option + /// public TableConfigurator SetUpdatePolicy(string policy) { InnerConfig.UpdatePolicy = policy; return this; @@ -185,6 +194,8 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the policy needed by a user in order to create entries /// + /// The value for the option + /// public TableConfigurator SetCreatePolicy(string policy) { InnerConfig.CreatePolicy = policy; return this; @@ -193,11 +204,25 @@ public sealed class TableConfigurator(TableConfig config) { /// /// Determines the policy needed by a user in order to delete entries /// + /// The value for the option + /// public TableConfigurator SetDeletePolicy(string policy) { InnerConfig.DeletePolicy = policy; return this; } + /// + /// Sets the view, update, create and delete policies to the same value + /// + /// The value for the options + public TableConfigurator SetCombinedPolicy(string policy) { + InnerConfig.ViewPolicy = policy; + InnerConfig.UpdatePolicy = policy; + InnerConfig.CreatePolicy = policy; + InnerConfig.DeletePolicy = policy; + return this; + } + /// /// Adds a callback handler of the provided type /// diff --git a/src/HopFrame.Core/Repositories/IHopFrameRepository.cs b/src/HopFrame.Core/Repositories/IHopFrameRepository.cs index c4f09e2..6b0bcaf 100644 --- a/src/HopFrame.Core/Repositories/IHopFrameRepository.cs +++ b/src/HopFrame.Core/Repositories/IHopFrameRepository.cs @@ -1,24 +1,78 @@ namespace HopFrame.Core.Repositories; +/// +/// The middleware used to access data for custom repositories +/// +/// The type of the entity that is managed by this repository +/// The type of the primary key of the entity that is managed by this repository public interface IHopFrameRepository where TModel : class { + /// + /// Gets used to load all entities of the current page to display + /// + /// The page the user is currently on (starts at 0) + /// The maximum number of elements that should be returned + /// The entries for the requested page Task> LoadPage(int page, int perPage); + /// + /// Gets used to filter the entries by the entered search term + /// + /// The search text that was entered by the user + /// The page the user is currently on (starts at 0) + /// The maximum number of elements that should be returned + /// A list of the filtered entries on the current page with the total number of pages + /// Task> Search(string searchTerm, int page, int perPage); + /// + /// Gets used to determine the total number of pages + /// + /// The maximum number of elements per page + /// The total number of pages Task GetTotalPageCount(int perPage); + /// + /// Gets used when an entry is created through the UI + /// + /// The entry that needs to be saved Task CreateItem(TModel item); + /// + /// Gets used when an entry is modified through the UI + /// + /// The modified entry that needs to be saved Task EditItem(TModel item); + /// + /// Gets used when an entry is deleted through the UI + /// + /// The entry that should be deleted Task DeleteItem(TModel item); + /// + /// Gets used to receive information about a specific entry from the dataset + /// + /// The primary key of the desired entry + /// Either the entry if one is found or null Task GetOne(TKey key); } +/// +/// The object that is passed to the UI to display the search results +/// +/// The found entries on the current page +/// The total number of pages that the search contains +/// The type of the entity public readonly struct SearchResult(IEnumerable items, int pageCount) { + /// + /// The found entries on the current page + /// public IEnumerable Items { get; init; } = items; + + /// + /// The total number of pages that the search contains + /// public int PageCount { get; init; } = pageCount; } diff --git a/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor b/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor index e80bb4b..68585b8 100644 --- a/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor +++ b/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor @@ -98,7 +98,7 @@ Sortable="@property.Sortable"/> } - @if (DisplayActions && (_hasDeletePolicy || _hasUpdatePolicy)) { + @if (DisplayActions && (_hasDeletePolicy || _hasUpdatePolicy || _pluginButtons.Where(pb => pb.IsForTable(_config)).Any(pb => pb.Position == PluginButtonPosition.OnEntry))) { @foreach (var button in _pluginButtons.Where(pb => pb.IsForTable(_config)).Where(pb => pb.Position == PluginButtonPosition.OnEntry)) { diff --git a/src/HopFrame.Web/Plugins/Annotations/EventHandlerAttribute.cs b/src/HopFrame.Web/Plugins/Annotations/EventHandlerAttribute.cs index d6148ee..41e3641 100644 --- a/src/HopFrame.Web/Plugins/Annotations/EventHandlerAttribute.cs +++ b/src/HopFrame.Web/Plugins/Annotations/EventHandlerAttribute.cs @@ -1,4 +1,7 @@ namespace HopFrame.Web.Plugins.Annotations; +/// +/// Indicates, that the method is a handler for an event +/// [AttributeUsage(AttributeTargets.Method)] public class EventHandlerAttribute : Attribute; diff --git a/src/HopFrame.Web/Plugins/Events/EntryEvent.cs b/src/HopFrame.Web/Plugins/Events/EntryEvent.cs index 89ada2f..8a54903 100644 --- a/src/HopFrame.Web/Plugins/Events/EntryEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/EntryEvent.cs @@ -2,17 +2,42 @@ namespace HopFrame.Web.Plugins.Events; +/// +/// Raised before an entry should be deleted +/// public sealed class DeleteEntryEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// The entry that is about to be deleted + /// public required object Entity { get; init; } } +/// +/// Raised before a new entry gets saved to the dataset +/// public sealed class CreateEntryEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender); +/// +/// Raised before any changes are saved to the dataset +/// public sealed class UpdateEntryEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// The entry that is about to be updated + /// public required object Entity { get; init; } } +/// +/// Raised when an entity is selected or deselected in the relation picker dialog +/// public sealed class SelectEntryEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// The entry that is being selected + /// public required object Entity { get; init; } + + /// + /// Indicates whether the entry is selected (true) or deselected (false) + /// public required bool Selected { get; set; } } diff --git a/src/HopFrame.Web/Plugins/Events/HopFrameEventArgs.cs b/src/HopFrame.Web/Plugins/Events/HopFrameEventArgs.cs index d15d8d5..53f2e44 100644 --- a/src/HopFrame.Web/Plugins/Events/HopFrameEventArgs.cs +++ b/src/HopFrame.Web/Plugins/Events/HopFrameEventArgs.cs @@ -4,24 +4,47 @@ using HopFrame.Web.Components.Pages; namespace HopFrame.Web.Plugins.Events; +/// +/// The base event with parameters for every event +/// public abstract class HopFrameEventArgs(object internalSender) { internal object InternalSender { get; } = internalSender; + + /// + /// Indicates if the event got canceled by any event handler + /// public bool IsCanceled { get; protected set; } - + /// + /// Determines if the action that is about to be executed should be canceled + /// public void SetCancelled(bool canceled) => IsCanceled = canceled; } +/// public abstract class HopFrameEventArgs(TSender sender) : HopFrameEventArgs(sender) where TSender : class { + /// + /// The element that raised the event + /// public TSender Sender => (TSender)InternalSender; } -public abstract class HopFrameTablePageEventArgs(HopFrameTablePage sender) - : HopFrameEventArgs(sender) { +/// +/// The base event with parameters for every event raised by a +/// +public abstract class HopFrameTablePageEventArgs(HopFrameTablePage sender) : HopFrameEventArgs(sender) { + /// + /// The configuration of the table page that raised the event + /// public required TableConfig Table { get; init; } } -public abstract class HopFrameEditorEventArgs(HopFrameEditor sender) - : HopFrameEventArgs(sender) { +/// +/// The base event with parameters for every event raised by a +/// +public abstract class HopFrameEditorEventArgs(HopFrameEditor sender) : HopFrameEventArgs(sender) { + /// + /// The configuration of the parent table of the editor that raised the event + /// public required TableConfig Table { get; init; } } diff --git a/src/HopFrame.Web/Plugins/Events/PageChangeEvent.cs b/src/HopFrame.Web/Plugins/Events/PageChangeEvent.cs index 44570ed..0acd881 100644 --- a/src/HopFrame.Web/Plugins/Events/PageChangeEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/PageChangeEvent.cs @@ -2,8 +2,22 @@ namespace HopFrame.Web.Plugins.Events; +/// +/// Raised when the user is about to change the page he is currently on +/// public sealed class PageChangeEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// The page he is currently on + /// public required int CurrentPage { get; init; } + + /// + /// The total number of pages his table can currently display + /// public required int TotalPages { get; init; } + + /// + /// The new page he tries to access + /// public required int NewPage { get; set; } } \ No newline at end of file diff --git a/src/HopFrame.Web/Plugins/Events/ReloadEvent.cs b/src/HopFrame.Web/Plugins/Events/ReloadEvent.cs index 384197e..0e6cd5a 100644 --- a/src/HopFrame.Web/Plugins/Events/ReloadEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/ReloadEvent.cs @@ -2,6 +2,7 @@ namespace HopFrame.Web.Plugins.Events; -public sealed class ReloadEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { - -} \ No newline at end of file +/// +/// Raised before the table is about to reload its data +/// +public sealed class ReloadEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender); \ No newline at end of file diff --git a/src/HopFrame.Web/Plugins/Events/SearchEvent.cs b/src/HopFrame.Web/Plugins/Events/SearchEvent.cs index b012b10..dcb6f90 100644 --- a/src/HopFrame.Web/Plugins/Events/SearchEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/SearchEvent.cs @@ -3,9 +3,21 @@ using HopFrame.Web.Components.Pages; namespace HopFrame.Web.Plugins.Events; +/// +/// Raised before the search results are loaded +/// +/// public sealed class SearchEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// The search term the user entered + /// public required string SearchTerm { get; set; } + + /// + /// The page the user is currently on + /// public required int CurrentPage { get; init; } + internal IEnumerable? SearchResult { get; set; } internal int TotalPages { get; set; } diff --git a/src/HopFrame.Web/Plugins/Events/TableInitializedEvent.cs b/src/HopFrame.Web/Plugins/Events/TableInitializedEvent.cs index 2f3080b..3f7a417 100644 --- a/src/HopFrame.Web/Plugins/Events/TableInitializedEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/TableInitializedEvent.cs @@ -4,10 +4,28 @@ using Microsoft.FluentUI.AspNetCore.Components; namespace HopFrame.Web.Plugins.Events; +/// +/// Raised when a table is initialized +/// +/// public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePageEventArgs(sender) { + /// + /// List of all buttons added by the plugins + /// public List PluginButtons { get; } = new(); + + /// + /// Toggles for the native buttons on the page + /// public DefaultButtonToggles DefaultButtons { get; set; } = new(); + /// + /// Adds a custom button to the top bar of the page + /// + /// The text displayed on the button + /// The function that is invoked when the button is pressed + /// Determines if the button should be displayed on the right + /// Optional: The icon displayed next to the title public void AddPageButton(string title, Func callback, bool pushRight = false, IconInfo? icon = null) { PluginButtons.Add(new() { Title = title, @@ -16,7 +34,8 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage Handler = (_, _) => callback.Invoke() }); } - + + /// public void AddPageButton(string title, Action callback, bool pushRight = false, IconInfo? icon = null) { AddPageButton(title, () => { callback.Invoke(); @@ -24,6 +43,11 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }, pushRight, icon); } + /// + /// Adds a custom button to the Actions column next to every entry + /// + /// The icon displayed in the button + /// The function that is invoked when the button is pressed public void AddEntityButton(IconInfo icon, Func callback) { PluginButtons.Add(new() { Icon = icon, @@ -32,6 +56,7 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }); } + /// public void AddEntityButton(IconInfo icon, Action callback) { AddEntityButton(icon, (obj, cfg) => { callback.Invoke(obj, cfg); @@ -39,6 +64,8 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }); } + /// The entity type of the table that should display this button + /// public void AddEntityButton(IconInfo icon, Func callback) { PluginButtons.Add(new() { Icon = icon, @@ -48,6 +75,8 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }); } + /// The entity type of the table that should display this button + /// public void AddEntityButton(IconInfo icon, Action callback) { AddEntityButton(icon, (obj, cfg) => { callback.Invoke(obj, cfg); @@ -55,6 +84,8 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }); } + /// The entity type of the table that should display this button + /// public void AddPageButton(string title, Func callback, bool pushRight = false, IconInfo? icon = null) { PluginButtons.Add(new() { Title = title, @@ -65,6 +96,8 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage }); } + /// The entity type of the table that should display this button + /// public void AddPageButton(string title, Action callback, bool pushRight = false, IconInfo? icon = null) { AddPageButton(title, () => { callback.Invoke(); @@ -73,11 +106,33 @@ public class TableInitializedEvent(HopFrameTablePage sender) : HopFrameTablePage } } +/// +/// A wrapper object containing all information about a custom button +/// public struct PluginButton { + /// + /// The position of the button + /// public PluginButtonPosition Position { get; set; } + + /// + /// The function that is invoked when the button is pressed + /// public Func Handler { get; set; } + + /// + /// The text on the button if supported + /// public string? Title { get; set; } + + /// + /// The icon displayed on the button + /// public IconInfo? Icon { get; set; } + + /// + /// The entity type of the table that should display this button + /// public Type? TableFilter { get; set; } internal bool IsForTable(TableConfig? config) { @@ -87,12 +142,18 @@ public struct PluginButton { } } +/// +/// All available positions for a custom button +/// public enum PluginButtonPosition { TopLeft = 0, TopRight = 1, OnEntry = 2 } +/// +/// Toggles for the native buttons on the page +/// public struct DefaultButtonToggles() { public bool ShowRefreshButton { get; set; } = true; public bool ShowAddEntityButton { get; set; } = true; diff --git a/src/HopFrame.Web/Plugins/Events/ValidationEvent.cs b/src/HopFrame.Web/Plugins/Events/ValidationEvent.cs index 6c92f4d..fea40fc 100644 --- a/src/HopFrame.Web/Plugins/Events/ValidationEvent.cs +++ b/src/HopFrame.Web/Plugins/Events/ValidationEvent.cs @@ -3,7 +3,17 @@ using HopFrame.Web.Components.Dialogs; namespace HopFrame.Web.Plugins.Events; +/// +/// Raised when a property in the editor is validated +/// public sealed class ValidationEvent(HopFrameEditor sender) : HopFrameEditorEventArgs(sender) { + /// + /// All errors found by the validators. Can be modified to display more (or less) errors + /// public required IList Errors { get; init; } + + /// + /// The property that is validated + /// public required PropertyConfig Property { get; init; } } \ No newline at end of file diff --git a/src/HopFrame.Web/ServiceCollectionExtensions.cs b/src/HopFrame.Web/ServiceCollectionExtensions.cs index 5461b83..0549fc5 100644 --- a/src/HopFrame.Web/ServiceCollectionExtensions.cs +++ b/src/HopFrame.Web/ServiceCollectionExtensions.cs @@ -59,7 +59,7 @@ public static class ServiceCollectionExtensions { /// Adds the HopFrame admin ui endpoints /// /// - [Obsolete($"Use '{nameof(AddHopFramePages)}' instead")] + [Obsolete($"Use {nameof(AddHopFramePages)} instead")] public static RazorComponentsEndpointConventionBuilder MapHopFramePages(this RazorComponentsEndpointConventionBuilder builder) { return AddHopFramePages(builder); } @@ -74,6 +74,9 @@ public static class ServiceCollectionExtensions { return builder; } + /// + /// Adds the HopFrame admin ui endpoints + /// public static WebApplication MapHopFrame(this WebApplication app) { app.UseAntiforgery(); app.MapStaticAssets(); diff --git a/src/HopFrame.Web/Services/ISearchSuggestionProvider.cs b/src/HopFrame.Web/Services/ISearchSuggestionProvider.cs index c51e198..0e7eecf 100644 --- a/src/HopFrame.Web/Services/ISearchSuggestionProvider.cs +++ b/src/HopFrame.Web/Services/ISearchSuggestionProvider.cs @@ -2,10 +2,26 @@ namespace HopFrame.Web.Services; +/// +/// Accessor for the advanced search suggestion feature +/// public interface ISearchSuggestionProvider { + /// + /// Generates a list of search suggestions based on the current search term + /// + /// The current table for context + /// The partial input by the user + /// public IEnumerable GenerateSearchSuggestions(TableConfig table, string searchText); + /// + /// Generates the new search term by appending the generated text of the selected suggestion + /// + /// The current table for context + /// The partial input by the user + /// The suggestion that was selected + /// public string CompleteSearchSuggestion(TableConfig table, string searchText, string selectedSuggestion); } \ No newline at end of file