left-icon

Blazor Succinctly®
by Michael Washington

Previous
Chapter

of
A
A
A

CHAPTER 8

Help Desk Ticket Administration

Help Desk Ticket Administration


In this chapter, we will detail the steps to create the screens to allow administrators to manage the help desk tickets.

In the ticket administration we will construct, help desk tickets can be updated and deleted, but ticket details that are part of a help desk ticket can only be added and deleted.

Create the Administration page

New Item

Figure 56: New Item

Add the Administration page to the project by right-clicking on the Pages folder and selecting Add, then New Item.

Add New Item

Figure 57: Add New Item

Select the Razor Component template, name the control Administration.razor, and click Add.

Use the following code for the Razor control.

Code Listing 33: Administration.razor

@page "/administration"

@using SyncfusionHelpDesk.Data;

@inherits OwningComponentBase<SyncfusionHelpDeskService>

@*AuthorizeView control ensures that *@

@*Only users in the Administrators role can view this content*@

<AuthorizeView Roles="Administrators">

</AuthorizeView>

@code {

    [CascadingParameter]

    private Task<AuthenticationState> authenticationStateTask { get; set; }

}

Add link in NavMenu.razor

We will now add a link to the Administration control in the navigation menu.

Open the NavMenu.razor control in the Shared folder and remove the following code (for the links to the counter and fetchdata pages).

Code Listing 34: Remove NavMenu Code

        <li class="nav-item px-3">

            <NavLink class="nav-link" href="counter">

                <span class="oi oi-plus" aria-hidden="true"></span> Counter

            </NavLink>

        </li>

        <li class="nav-item px-3">

            <NavLink class="nav-link" href="fetchdata">

                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data

            </NavLink>

        </li>

Add the following code in its place.

Code Listing 35: Add NavMenu Code

        <AuthorizeView Roles="Administrators">

            <li class="nav-item px-3">

                <NavLink class="nav-link" href="administration">

                    <span class="oi oi-plus" aria-hidden="true"></span> Administration

                </NavLink>

            </li>

        </AuthorizeView>

This will display a link to the Administration.razor page, but this link will only display for administrators because it is wrapped in an AuthorizeView control with the Roles property set to Administrators.

Administration Link

Figure 58: Administration Link

When we run the application and log in as the administrator, we see the Administration link. When we click on the link, we are navigated to the Administration page (that is currently blank).

Using Syncfusion Data Grid

The Syncfusion Data Grid (programmatically called SfGrid) is a control that allows you to display tabular data. We will use it to display the help desk tickets. This control will allow us to page, sort, and trigger editing of the records.

It has a DataSource property that we will bind to a collection of the help desk tickets. It also has properties to allow for paging and sorting.

The control also allows us to define the columns that will contain the tabular data as well as Edit and Delete buttons.

Enter the following inside the AuthorizeView control tag.

Code Listing 36: Data Grid

<div>

    <div id="target" style="height: 500px;">

        <SfGrid ID="Grid"

                    DataSource="@colHelpDeskTickets"

                    AllowPaging="true"

                    AllowSorting="true"

                    AllowResizing="true"

                    AllowReordering="true">

            <GridPageSettings PageSize="5"></GridPageSettings>

            <GridEvents CommandClicked="OnCommandClicked"

                        TValue="HelpDeskTickets">

            </GridEvents>

            <GridColumns>

                <GridColumn HeaderText="" TextAlign="TextAlign.Left" Width="150">

                    <GridCommandColumns>

                        <GridCommandColumn Type=CommandButtonType.Edit

                                            ButtonOption="@(new CommandButtonOptions()

                                                        { Content = "Edit" })">

                        </GridCommandColumn>

                        <GridCommandColumn Type=CommandButtonType.Delete

                                            ButtonOption="@(new CommandButtonOptions()

                                                        { Content = "Delete" })">

                        </GridCommandColumn>

                    </GridCommandColumns>

                </GridColumn>

                <GridColumn IsPrimaryKey="true" Field=@nameof(HelpDeskTickets.Id)

                            HeaderText="ID #" TextAlign="@TextAlign.Left"

                            Width="70">

                </GridColumn>

                <GridColumn Field=@nameof(HelpDeskTickets.TicketStatus)

                            HeaderText="Status" TextAlign="@TextAlign.Left"

                            Width="80">

                </GridColumn>

                <GridColumn Field=@nameof(HelpDeskTickets.TicketDate)

                            HeaderText="Date" TextAlign="@TextAlign.Left"

                            Width="80">

                </GridColumn>

                <GridColumn Field=@nameof(HelpDeskTickets.TicketDescription)

                            HeaderText="Description" TextAlign="@TextAlign.Left"

                            Width="150">

                </GridColumn>

                <GridColumn Field=@nameof(HelpDeskTickets.TicketRequesterEmail)

                            HeaderText="Requester" TextAlign="@TextAlign.Left"

                            Width="150">

                </GridColumn>

            </GridColumns>

        </SfGrid>

    </div>

</div>

Enter the following in the @code section.

Code Listing 37: Data Grid Code

    public IQueryable<HelpDeskTickets> colHelpDeskTickets { get; set; }

    private HelpDeskTickets SelectedTicket = new HelpDeskTickets();

    protected override void OnInitialized()

    {

        // GetHelpDeskTickets returns IQueryable that the

        // SfGrid will use to only pull records for the

        // page that is currently selected.

        colHelpDeskTickets = @Service.GetHelpDeskTickets();

    }

    public async void OnCommandClicked(

        CommandClickEventArgs<HelpDeskTickets> args)

    {

        // Code to be added later.

    }

The OnInitialized method is the first method to run when the page loads. This method populates the colHelpDeskTickets collection that is bound to the DataSource property of the Data Grid.

Data Grid Control

Figure 59: Data Grid Control

When we run the application, log in as an administrator, and navigate to the Administration page, we will see the help desk ticket records displayed in the Data Grid.

Sorting

Figure 60: Sorting

Sorting is achieved by clicking on the column headers.

Paging

Figure 61: Paging

The grid also enables paging.

Deleting a record

We will implement the functionality to delete a help desk ticket record.

To enable this, the Data Grid allows us to create custom command buttons using the CommandClicked property that we currently have wired up to the OnCommandClicked method.

We will use the OnCommandClicked method to display a pop-up, using the Syncfusion Dialog control, that will require the user to confirm that they want to delete the record.

Syncfusion Dialog

The Dialog control is used to display information and accept user input. It can display as a modal control that requires the user to interact with it before continuing to use any other part of the application.

Enter the following inside the AuthorizeView control tag.

Code Listing 38: Confirm Delete Dialog

<SfDialog Target="#target"

            Width="100px"

            Height="130px"

            IsModal="true"

            ShowCloseIcon="false"

            @bind-Visible="DeleteRecordConfirmVisibility">

    <DialogTemplates>

        <Header> DELETE RECORD ? </Header>

        <Content>

            <div class="button-container">

                <button type="submit"

                        class="e-btn e-normal e-primary"

                        @onclick="ConfirmDeleteYes">

                    Yes

                </button>

                <button type="submit"

                        class="e-btn e-normal"

                        @onclick="ConfirmDeleteNo">

                    No

                </button>

            </div>

        </Content>

    </DialogTemplates>

</SfDialog>

Enter the following in the @code section.

Code Listing 39: Help Desk Ticket Property

    // Global property for the help desk ticket.

    HelpDeskTicket objHelpDeskTicket =

    new HelpDeskTicket() { TicketDate = DateTime.Now };

Change the OnCommandClicked method to the following to respond to the DELETE button being clicked for a help desk record.

This method will open the confirmation dialog.

Code Listing 40: Open Confirmation Dialog

    public async void OnCommandClicked(

        CommandClickEventArgs<HelpDeskTickets> args)

    {

        // Get the selected help desk ticket.

        SelectedTicket =

            await @Service.GetHelpDeskTicketAsync(args.RowData.TicketGuid);

        if (args.CommandColumn.ButtonOption.Content == "Delete")

        {

            // Open Delete confirmation dialog.

            this.DeleteRecordConfirmVisibility = true;

            StateHasChanged();

        }

    }

Note: StateHasChanged, used in the preceding code, notifies a component (in this case the Administration page) that its state has changed and causes that component to rerender. This is usually only required when that state was changed by a JavaScript interop call. The Syncfusion Dialog control uses JavaScript interop in the underlying code to open the dialog, so StateHasChanged is required in this case.

Add the following method that will simply close the dialog if the user clicks the NO button in the dialog.

Code Listing 41: Close Dialog

    public void ConfirmDeleteNo()

    {

        // Open the dialog

        // to give the user a chance

        // to confirm they want to delete the record.

        this.DeleteRecordConfirmVisibility = false;

    }

Using @ref (capture references to components)

Adding an @ref attribute to a component allows you to programmatically access and manipulate a control or component.

To implement it, you add the @ref attribute to a component, then define a field with the same type as the component.

Add the following property to the SfGrid control.

Code Listing 42: Data Grid @ref

@ref="gridObj"

Now, add the following corresponding field to the @code section.

Code Listing 43: Data Grid Property

    SfGrid<HelpDeskTickets> gridObj;

Now that we have done this, we can add the following method to delete the record if the user clicks the YES button in the dialog.

This method will refresh the Data Grid by calling gridObj.Refresh(), which uses the gridObj object defined with the @ref attribute.

Code Listing 44: Delete Record

    public async void ConfirmDeleteYes()

    {

        // The user selected Yes to delete the

        // selected help desk ticket.

        // Delete the record.

        var result =

            await @Service.DeleteHelpDeskTicketsAsync(

                SelectedTicket);

        // Close the dialog.

        this.DeleteRecordConfirmVisibility = false;

        // Refresh the SfGrid

        // so the deleted record will not show.

        gridObj.Refresh();

    }

When we run the application, we can click the DELETE button to open the dialog.

Figure 62: Delete Confirmation

Clicking the NO button will simply close the dialog. Clicking the YES button will delete the selected record and refresh the Data Grid.

EditTicket control

We will construct an EditTicket control that will be placed inside a dialog in the Administration page and displayed when an administrator wants to edit a help desk ticket.

We do this to allow this control to be reused in the EmailTicketEdit.razor page covered in the following chapter.

In the Pages folder, create a new control called EditTicket.razor using the following code.

Code Listing 45: EditTicket.razor

@using System.Security.Claims;

@using SyncfusionHelpDesk.Data;

@using Syncfusion.Blazor.DropDowns

@inherits OwningComponentBase<SyncfusionHelpDeskService>

<div>

    <SfDropDownList TItem="HelpDeskStatus" Enabled="!isReadOnly"

                     TValue="string" PopupHeight="230px" Index=0

                     Placeholder="Ticket Status"

                     DataSource="@HelpDeskStatus.Statuses"

                     FloatLabelType="@FloatLabelType.Always"

                     @bind-Value="@SelectedTicket.TicketStatus">

        <DropDownListFieldSettings Text="Text"

                                   Value="ID">

        </DropDownListFieldSettings>

    </SfDropDownList>

</div>

<div>

    <SfDatePicker ID="TicketDate" Enabled="!isReadOnly"

                   Placeholder="Ticket Date"

                   FloatLabelType="@FloatLabelType.Always"

                   @bind-Value="@SelectedTicket.TicketDate"

                   Max="DateTime.Now"

                   ShowClearButton="false">

    </SfDatePicker>

</div>

<div>

    <SfTextBox Enabled="!isReadOnly" Placeholder="Ticket Description"

                FloatLabelType="@FloatLabelType.Always"

                @bind-Value="@SelectedTicket.TicketDescription">

    </SfTextBox>

</div>

<div>

    <SfTextBox Enabled="!isReadOnly" Placeholder="Requester Email"

                FloatLabelType="@FloatLabelType.Always"

                @bind-Value="@SelectedTicket.TicketRequesterEmail">

    </SfTextBox>

</div>

@if (SelectedTicket.HelpDeskTicketDetails != null)

{

    @if (SelectedTicket.HelpDeskTicketDetails.Count() > 0)

    {

        <table class="table">

            <thead>

                <tr>

                    <th>Date</th>

                    <th>Description</th>

                </tr>

            </thead>

            <tbody>

                @foreach (var TicketDetail in

                SelectedTicket.HelpDeskTicketDetails)

                {

                    <tr>

                        <td>

                            @TicketDetail.TicketDetailDate.ToShortDateString()

                        </td>

                        <td>

                            @TicketDetail.TicketDescription

                        </td>

                    </tr>

                }

            </tbody>

        </table>

    }

    <SfTextBox Placeholder="NewHelp Desk Ticket Detail"

                @bind-Value="@NewHelpDeskTicketDetail">

    </SfTextBox>

    <SfButton CssClass="e-small e-success"

               @onclick="AddHelpDeskTicketDetail">

        Add

    </SfButton>

}

<br />

@code {

    [CascadingParameter]

    private Task<AuthenticationState> authenticationStateTask { get; set; }

    [Parameter]

    public HelpDeskTickets SelectedTicket { get; set; }

    public bool isReadOnly = true;

    ClaimsPrincipal CurrentUser = new ClaimsPrincipal();

    string NewHelpDeskTicketDetail = "";

    protected override async Task OnInitializedAsync()

    {

        // Get the current user.

        CurrentUser = (await authenticationStateTask).User;

        // If there is a logged in user

        // they are an administrator.

        // Enable editing.

        isReadOnly = !CurrentUser.Identity.IsAuthenticated;

    }

    private void AddHelpDeskTicketDetail()

    {

        // Create new HelpDeskTicketDetails record.

        HelpDeskTicketDetails NewHelpDeskTicketDetails =

            new HelpDeskTicketDetails();

        NewHelpDeskTicketDetails.HelpDeskTicketId =

            SelectedTicket.Id;

        NewHelpDeskTicketDetails.TicketDetailDate =

            DateTime.Now;

        NewHelpDeskTicketDetails.TicketDescription =

            NewHelpDeskTicketDetail;

        // Add to collection.

        SelectedTicket.HelpDeskTicketDetails

            .Add(NewHelpDeskTicketDetails);

        // Clear the Text Box.

        NewHelpDeskTicketDetail = "";

    }

}

Notice that this exposes a SelectedTicket parameter (of type HelpDeskTickets) that will accept a reference of a help desk ticket record.

In the Administration.razor control, add the following markup to display the EditTicket.razor page in a Dialog control.

Code Listing 46: EditTicket Dialog

<SfDialog Target="#target"

            Width="500px"

            Height="500px"

            IsModal="true"

            ShowCloseIcon="true"

            @bind-Visible="EditDialogVisibility">

    <DialogTemplates>

        <Header> EDIT TICKET # @SelectedTicket.Id</Header>

        <Content>

            <EditTicket SelectedTicket="@SelectedTicket" />

        </Content>

        <FooterTemplate>

            <div class="button-container">

                <button type="submit"

                        class="e-btn e-normal e-primary"

                        @onclick="SaveTicket">

                    Save

                </button>

            </div>

        </FooterTemplate>

    </DialogTemplates>

</SfDialog>

Note that this instantiates the EditTicket control (the EditTicket.razor code page) and passes a reference to the currently selected help desk ticket record (@SelectedTicket) through the SelectedTicket property.

Also, add the following to the @code section to implement the functionality for the Save button on the dialog.

Code Listing 47: SaveTicket Method

    public async Task SaveTicket()

    {

        // Update the selected help desk ticket.

        var result =

            await @Service.UpdateTicketAsync(SelectedTicket);

        // Close the Edit dialog.

        this.EditDialogVisibility = false;

        // Refresh the SfGrid

        // so the changes to the selected

        // help desk ticket are reflected.

        gridObj.Refresh();

    }

Finally, add the following code to the OnCommandClicked method (under the SelectedTicket line) to open the dialog when the EDIT button is clicked in a row in the Data Grid.

Code Listing 48: Open Dialog

        if (args.CommandColumn.ButtonOption.Content == "Edit")

        {

            // Open the Edit dialog.

            this.EditDialogVisibility = true;

            StateHasChanged();

        }

Edit Ticket Dialog

Figure 63: Edit Ticket Dialog

When we run the application, we can click the EDIT button next to a record to open it up in the dialog.

Any of the help desk ticket values at the top of the form can be edited and saved by clicking SAVE at the bottom of the dialog.

Near the bottom of the form, help desk ticket detail records can be added by entering text in the text box and clicking ADD.

Edit Ticket

Figure 64: Edit Ticket

The help desk detail record will be added, but it will not be saved until SAVE is clicked.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.