Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor UI extensions #6647

Merged
merged 85 commits into from Mar 24, 2021
Merged

Blazor UI extensions #6647

merged 85 commits into from Mar 24, 2021

Conversation

ilkayilknur
Copy link
Contributor

This PR contains blazor UI extensibility features except the module extensibility feature.
I implemented the usage in the Identity module. I will start implementing the other modules once I get initial feedback. It takes time to change all modules when you get feedback on usage :)

Entity Actions and Table Columns

Developers can easily define table columns and actions by using UIExtensions.Instance.EntityActions and UIExtensions.Instance.TableColumns properties. This PR also introduces the ABPDataGrid component. This component creates table columns and actions automatically using the UI extensibility system.

Developers can also extend the modules and add their actions/columns like below.

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(RoleManagement))]
    public class MyRoleManagement : RoleManagement
    {
        protected override async ValueTask SetTableColumnsAsync()
        {
            await base.SetTableColumnsAsync();
            UIExtensions.Instance.TableColumns.Get<RoleManagement>().AddIfNotContains(new Volo.Abp.AspNetCore.Components.Extensibility.TableColumns.TableColumn()
            {
                Title = "MyCustomColumn",
                Data = nameof(IdentityRoleDto.Name)
            });
        }


        protected override async ValueTask SetEntityActionsAsync()
        {
            await base.SetEntityActionsAsync();
            UIExtensions.Instance.EntityActions.Get<RoleManagement>().AddIfNotContains
                (new Volo.Abp.AspNetCore.Components.Extensibility.EntityActions.EntityAction
                {
                    Text = "My Custom Action",
                    Clicked = (data) =>
                    {
                        Console.WriteLine("Clicked!");
                        return Task.CompletedTask;
                    }
                });
        }
    }

Page Toolbars

In the final implementation, I will move the PageHeader component and related types from Abp.Volo.BlazoriseUI to Volo.Abp.AspNetCore.Components.WebAssembly.Theming. There two PageHeader components in this branch right now. I didn't want to break the all modules.

In our modules, we can simply inject IOptions<AbpPageToolbarOptions> and add the toolbar items inside SetToolbarItemsAsync method.

Developers can also define their own contributors and add them inside configure method.

public class ToolbarContributor : IPageToolbarContributor
    {
        public Task ContributeAsync(PageToolbarContributionContext context)
        {
            context.Items.Add(new PageToolbarItem(typeof(Component)));
            return Task.CompletedTask;
        }
    }
Configure<AbpPageToolbarOptions>(options =>
{
    options.Configure<RoleManagement>(configure =>
    {
        configure.Contributors.Add(new ToolbarContributor());
    });
});

Bundling and Minification

I made related changes and abp bundle command reads the appsettings.json to get the bundling settings right now. I also added a parameter named parameters. Developers can define extra key/value pair parameters and send them to the contributors.

I didn't make any changes on the extensibility side. The current design supports extensibility. Developers can define a contributor and update any dependency by using context.BundleDefinitions property.

<DataGridColumns>
@foreach (var column in UIExtensions.Instance.TableColumns.Get(Page))
{
if (column.Actions.Any())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, one datagrid will have a single column with "actions". So, instead of adding Actions to column, it might be better to add it to a containing object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably. There is also UIExtensions.Instance.EntityActions property. Devs can get entity action collection for a specific page and update actions. Putting an Actions property inside the table column provides flexibility and devs can change the order of the Actions column etc.. We provide the same flexibility on the MVC side and, I want to provide that on the Blazor side.

framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj Outdated Show resolved Hide resolved
UIExtensions.Instance
.EntityActions
.Get<RoleManagement>()
.AddIfNotContains(new EntityAction[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AddIfNotContains prevents duplicate adding. However, wouldn't it better to make this into the module's ConfigureServices method (with OneTimeRunner wrapper) to not execute it every time component is rendered.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment below.

UIExtensions.Instance
.TableColumns
.Get<RoleManagement>()
.AddIfNotContains(new TableColumn[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment like SetEntityActionsAsync

@274188A
Copy link
Contributor

274188A commented Dec 16, 2020

A sample project would be ideal

@hikalkan hikalkan modified the milestones: 4.1-preview, 4.2-preview Dec 16, 2020
@ilkayilknur
Copy link
Contributor Author

I've made some improvements to the design. Instead of storing the actions and columns in a singleton type, I moved the definitions to the AbpCrudPageBase. Devs can access the page context in a correct way and add or customize the actions, table columns, and toolbar items.
Sample Usage

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(RoleManagement))]
public class MyRoleManagement : RoleManagement
{
    protected override async ValueTask SetTableColumnsAsync()
    {
        await base.SetTableColumnsAsync();
        TableColumns.Get<RoleManagement>().Add(new Volo.Abp.AspNetCore.Components.Extensibility.TableColumns.TableColumn()
        {
            Title = "MyCustomColumn",
            Data = nameof(IdentityRoleDto.Name)
        });
    }


    protected override async ValueTask SetEntityActionsAsync()
    {
        await base.SetEntityActionsAsync();
        EntityActions.Get<RoleManagement>().Add(new Volo.Abp.AspNetCore.Components.Extensibility.EntityActions.EntityAction
        {
            Text = "My Custom Action",
            Clicked = (data) =>
            {
                Console.WriteLine("Clicked!");
                return Task.CompletedTask;
            }
        });
    }

    protected override async ValueTask SetToolbarItemsAsync()
    {
        await base.SetToolbarItemsAsync();
        Toolbar.AddButton("Toolbar item", () =>
        {
            Console.WriteLine("Toolbar item Clicked");
            return Task.CompletedTask;
        }, IconName.Baby);
    }
}

@ilkayilknur ilkayilknur marked this pull request as ready for review March 11, 2021 14:13
@ilkayilknur
Copy link
Contributor Author

The PR is ready for review.

await base.OnParametersSetAsync();
if (Toolbar!=null)
{
Console.WriteLine("Toolbar is not null");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove Console.WriteLine

{
Console.WriteLine("Toolbar is not null");
var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar);
Console.WriteLine($"Toolbar item count:{toolbarItems.Length}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove Console.WriteLine. If you want, you can write debug logs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants