Base solution for your next web application

Activities of "BigCDogCrew"

Question

Now that I have completed the first release version of my AspNetZero project, I want to go back and put all of my user guides into an online website. I have looked at the Abp Docs Module and I believe it will serve my need very well, but I am a little bit fuzzy on how to integrate the Docs module with AspNetZero.

Here are may goals:

  1. add a Docs module to my AspNetZero project
  2. my project consists of mutliple products which are identified by name (a product), version (software release version) , and edition (abp edition).
  3. user login accounts on the main product must drive that user's access to appropriate documentation.
  4. I use Mercurial for revision control and would prefer not to have to move to GIT.

My questions:

  1. Is there a guide somewhere that explains how to add the Docs module to an AspNetZero project?
  2. Looking at Abp Docs Module,
    1. Step 1 - Download
      1. it seemed like maybe this step has already been satisfied by using the AspNetZero project; that this step 1 should be skipped.
    2. Step 2 - Referencing Docs Module Packages
      1. The choice to manually install the nuget packages felt like the most likely path to success. However, the AspNetZero project does not contain a project that I could identify as equivalent to "Acme.MyProject.Domain". The others (EntityFrameworkCore, Application, and Web) are all obvious...but the Domain appears to be missing. Do I need to add it? And what is the best way to do that to assure the projects are properly linked?
    3. Step 3 - Adding Module Dependencies
      1. Adding the DependsOn statements seems pretty straightforward. However, none of the AspNetZero module extension classes match the example "MyProject...." classes in the Abp Docs examples. Some clarification might be helpful.
    4. Step 4 - Database Integration
      1. Again, this seems fairly straight forward, but the Abp examples differ slightly from the AspNetZero code. Clarification would be helpful.
      2. In the Abp example code, it seemslike the addition of "builder.ConfigureDocs();" is the only required additional code....and I assume that can be added just after the "base.OnModelCreating(modelBuilder);" that appears in theOnModelCreating function of the AspNetZero ProjectNameDbContext class.
      3. adding of the migration and updating the database are straight forward and are expected to work as described.
    5. Step 5 - Linking Docs Module
      1. The "ConfigureMainMenuAsync" function does not exist in the AspNetZero project.
      2. It appears as though perhaps the new menu item should be added in the SetNavigation function of AppNavigationProvider.cs
        1. after the code shown below in Code Sample 1, add something like the code shown below in Code Sample 2.
    6. Step 6 - Adding New Docs Project
      1. No questions about this particular step.
    7. Step 7 - Creating a New Document
      1. No questions about this particular step.
    8. Step 8 - Creating the Navigation Document
      1. No questions about this particular step.
  3. What is the mechanism for integrating user-authentication to assure that some documents are only visible to users who have sufficient feature/permission credentials?

Code Sample 1

public override void SetNavigation(INavigationProviderContext context)
        {
            var menu = context.Manager.Menus[MenuName] = new MenuDefinition(MenuName, new FixedLocalizableString("Main Menu"));

Code Sample 2

                menu.AddItem(new MenuItemDefinition(
                        AppPageNames.Host.Documents,
                        L("Documents"),
                        url: "Documents",
                        icon: "flaticon-more",
                        permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Administration_Host_Documents)
                    )
                );

Fantastic! Worked like a charm. Excellent documentation. Keep up the great work.

I'm using AspNetZero v8.6 MVC/jQuery and I'm trying to get a datatable to sort using multiple, user-selected columns.

The image below shows a table where the Name column was clicked (generating an ascending ordered list by name). Subsequently, the Code column was clicked twice while the shift key was depressed (causing the sort arrows to cycle from ascending to descending on that column).

Here is the javascript that feeds the datatable. I have collapsed the columnDef code a little to preserve length...

        var dataTable = _$addressEMailTypesTable.DataTable({
            scrollX: true,
            responsive: false,
            paging: true,
            serverSide: true,
            processing: true,
            listAction: {
                ajaxFunction: _addressEMailTypesService.getAll,
                inputFilter: function () {
                    return {
					    filter: $('#AddressEMailTypesTableFilter').val(),
					    nameFilter: $('#NameFilterId').val(),
					    codeFilter: $('#CodeFilterId').val()
                    };
                }
            },
            columnDefs: [
                {
                    width: 120,
                    targets: 0,
                    data: null,
                    orderable: false,
                    autoWidth: false,
                    defaultContent: '',
                    rowAction: {
                        cssClass: 'btn btn-brand dropdown-toggle',
                        text: '<i class="fa fa-cog"></i> ' + app.localize('Actions') + ' <span class="caret"></span>',
                        items: [
						    { text: app.localize('View'), action: function (data) { _viewAddressEMailTypeModal.open({ id: data.record.addressEMailType.id }); } },
						    { text: app.localize('Edit'), visible: function () { return _permissions.edit; }, action: function (data) { _createOrEditModal.open({ id: data.record.addressEMailType.id }); } }, 
						    { text: app.localize('Delete'), visible: function () { return _permissions.delete; }, action: function (data) { deleteAddressEMailType(data.record.addressEMailType); } }
                        ]
                    }
                },
					{ targets: 1, data: "addressEMailType.uid", name: "uid", visible: false }, 
                    { targets: 2, data: "addressEMailType.name", name: "name" },
					{ targets: 3, data: "addressEMailType.code", name: "code" },
					{ targets: 4, data: "addressEMailType.order", name: "order" },
					{ targets: 5, data: "addressEMailType.status", name: "status" }
            ]
        });

In the following code (part of the GetAll function), the input.Sorting variable contains "name asc" with no mention of the Code field. I had expected to see "name asc, code desc" in that variable.

                var pagedAndFilteredAddressEMailTypes = filteredAddressEMailTypes
                    .OrderBy(input.Sorting ?? "id asc")
                    .PageBy(input);

Because the sort arrow indicators are behaving correctly, I assume that multiple column sorting is already turned on and supported. What am I missing? Do I need to manually capture the sort information from the table and then override the "sorting" member on the listAction.inputFilter?

Excellent. Thanks.

Yes. In v8.6, I still see the pagination controls without DOM being added to DataTable options.

Answer

This is an issue for me as well. I opened an issue on github. https://github.com/aspnetzero/aspnet-zero-core/issues/3257

After playing around with this issue a little more, it appears as though setting only two options are sufficient to make the scroll work properly.

scrollX: true,
responsive: false

However, it's very possible that I did not catch or reproduce the scenario where the "dom" option becomes necessary. Will you please provide some clarity as to why and when the dom option should be used?

Thanks.

First, thank you to the whole AspNetTeam for being so responsive. I've submitted at least half a dozen emails and a few more support forum posts. The AspNetZero team has always answered within 24-48 hours. You're doing fantastic and the product is great.

Your solution works great too. I was able to find the CSS by searching for "dataTables_paginate" class. It was then a simple matter of removing the "div.bottom" descendant requirement. My resulting custom style script (as I left the original intact), follows below.

I'll do a little more work to make sure that the style update is bundled and that the appropriate theme styles are updated. Thanks, again.

P.S. - there may be a simple update that the AspNetZero team can do to fix this styling holistically for future users...and maybe autoset those DOM and RESPONSIVE options when scrollX is true and those options have not been specified yet.

<style>
    /*Pagination*/
    .dataTables_wrapper div.dataTables_paginate ul li {
      padding: 0;
      margin-right: 5px;
      display: inline-block;
    }
    .dataTables_wrapper div.dataTables_paginate ul li a {
      cursor: pointer;
      display: inline-block;
      height: 2.25rem;
      width: 2.25rem;
      padding: 0;
      -webkit-border-radius: 50%;
      -moz-border-radius: 50%;
      -ms-border-radius: 50%;
      -o-border-radius: 50%;
      border-radius: 50%;
      position: relative;
      display: -webkit-box;
      display: -moz-box;
      display: -ms-flexbox;
      display: -webkit-flex;
      display: flex;
      -webkit-justify-content: center;
      -moz-justify-content: center;
      -ms-justify-content: center;
      justify-content: center;
      -webkit-align-items: center;
      -moz-align-items: center;
      -ms-align-items: center;
      align-items: center;
      text-align: center;
      vertical-align: middle;
      font-size: 1rem;
      line-height: 1rem;
      font-weight: 400;
    }
    .dataTables_wrapper div.dataTables_paginate ul li a {
      text-decoration: none;
    }

    .dataTables_wrapper div.dataTables_paginate ul li.active a,
    .dataTables_wrapper div.dataTables_paginate ul li.active a:hover {
        background: #5867dd;
        color: #fff;
    }

    .dataTables_wrapper div.dataTables_paginate ul li a:hover {
        background-color: #deddf3;
    }

    .dataTables_wrapper div.dataTables_paginate ul li a {
        background-color: #edecf8;
    }

</style>

I found and applied the Metronic CSS class "table-scrollable". But that did not work.

I found an article on the DataTables Forum regarding ScrollX not working (actually reviewed that before posting this issue). That article led me to try a few style adjustments...but these did not work either.

<style>
.dataTables_scrollBody table {
    margin-left:0px;
}
.dataTables_blockRequired {
    display:inline-block; 
}
</style>

For good measure...here is the cshtml for the sample. Advanced Filtering has been removed and the project name has been changed (to protect the innocent).

@using ProjectX.Authorization
@using ProjectX.Web.Areas.App.Models.Peripherals
@using ProjectX.Web.Areas.App.Startup
@model PeripheralsViewModel
@{
    ViewBag.CurrentPageName = AppPageNames.Common.Peripherals;
}
@section Scripts
{
    <script abp-src="/view-resources/Areas/App/Views/Peripherals/Index.js" asp-append-version="true"></script>
}
<div class="kt-content  kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor">
    <div class="kt-subheader kt-grid__item">
        <div class="@(await GetContainerClass())">
            <div class="kt-subheader__main">
                <h3 class="kt-subheader__title">
                    <span>@L("Peripherals")</span>
                </h3>
                <span class="kt-subheader__separator kt-subheader__separator--v"></span>
                <span class="kt-subheader__desc">
                    @L("PeripheralsHeaderInfo")
                </span>
            </div>
            <div class="kt-subheader__toolbar">
                <div class="kt-subheader__wrapper">
                    <button id="ExportToExcelButton" class="btn btn-outline-success"><i class="fa fa-file-excel"></i> @L("ExportToExcel")</button>
                    @if (IsGranted(AppPermissions.Pages_Peripherals_Create))
                    {
                        <button id="CreateNewPeripheralButton" class="btn btn-primary blue"><i class="fa fa-plus"></i> @L("Peripheral_CreateNew")</button>
                    }
                </div>
            </div>
        </div>
    </div>
    <div class="@(await GetContainerClass()) kt-grid__item kt-grid__item--fluid">
        <div class="kt-portlet kt-portlet--mobile">
            <div class="kt-portlet__body">
                <div class="kt-form">
                    <div class="row align-items-center mb-4">
                        <div class="col-xl-12">
                            <div class="form-group align-items-center">
                                <div class="input-group">
                                    <input type="text" id="PeripheralsTableFilter" class="form-control m-input" placeholder="@L("SearchWithThreeDot")" value="@Model.FilterText">
                                    <span class="input-group-btn">
                                        <button id="GetPeripheralsButton" class="btn btn-primary" type="submit"><i class="flaticon-search-1"></i></button>
                                    </span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="row align-items-center">
                    <table id="PeripheralsTable" class="display table table-striped table-bordered table-hover dt-responsive">
                        <thead>
                            <tr>
                                <th>@L("Actions")</th>
                                <th>@L("UID")</th>
                                <th>@L("SerialNumber")</th>
                                <th>@L("AssetTag")</th>
                                <th>@L("FirmwareVersion")</th>
                                <th>@L("PeripheralModelCode")</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
Showing 31 to 40 of 46 entries