Asymmetrik/ngx-starter

View on GitHub
src/app/core/admin/feedback/list-feedback/admin-list-feedback.component.html

Summary

Maintainability
Test Coverage
<section class="page-header mb-3">
    <div>
        <h1 skipTo>System Feedback</h1>
        View and manage system feedback.
    </div>
    <system-alert />
</section>

<section class="page-body anchored-page-body">
    <div class="table-header d-flex align-items-center">
        <div class="table-actions d-flex flex-wrap flex-grow-1">
            <div class="mb-3 me-5">
                <asy-search-input
                    placeholder="Search..."
                    [search]="dataSource.searchEvent$.value"
                    (applySearch)="dataSource.search($event)"
                />
            </div>

            <div class="mb-3 ms-auto">
                <button
                    class="btn btn-outline-primary ms-auto"
                    type="button"
                    (click)="exportCurrentView()"
                >
                    <span class="fa-solid fa-download"></span> Export
                </button>

                <button
                    class="btn btn-outline-primary font-weight-bold ms-3"
                    type="button"
                    ngbTooltip="Set Columns"
                    (click)="sidebar.toggle()"
                >
                    <span class="fa-solid fa-columns"></span>
                </button>
            </div>
        </div>
    </div>

    <div class="d-flex overflow-hidden">
        <div class="table-content">
            <table
                class="table table-striped"
                asyFilter
                asySort
                cdk-table
                [dataSource]="dataSource"
            >
                <ng-container cdkColumnDef="creator.name">
                    <th cdk-header-cell *cdkHeaderCellDef>Submitted By</th>
                    <td class="hide-overflow" cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.creator.name }}
                    </td>
                </ng-container>
                <ng-container cdkColumnDef="creator.username">
                    <th cdk-header-cell *cdkHeaderCellDef>Username</th>
                    <td class="hide-overflow" cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.creator.username }}
                    </td>
                </ng-container>
                <ng-container cdkColumnDef="creator.email">
                    <th cdk-header-cell *cdkHeaderCellDef>Email</th>
                    <td class="hide-overflow" cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.creator.email }}
                    </td>
                </ng-container>
                <ng-container cdkColumnDef="creator.organization">
                    <th cdk-header-cell *cdkHeaderCellDef>Organization</th>
                    <td class="hide-overflow" cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.creator.organization }}
                    </td>
                </ng-container>
                <asy-ago-date-column name="created" header="Submitted Date" sortable />
                <asy-ago-date-column name="updated" sortable />
                <ng-container cdkColumnDef="type">
                    <th cdk-header-cell *cdkHeaderCellDef>
                        <asy-header-sort>Type</asy-header-sort>
                    </th>
                    <td class="text-nowrap" cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.type | titlecase }}
                    </td>
                </ng-container>
                <ng-container cdkColumnDef="body">
                    <th cdk-header-cell *cdkHeaderCellDef>
                        Feedback
                        <asy-header-filter text-filter />
                    </th>
                    <td cdk-cell *cdkCellDef="let feedback">
                        {{ feedback.body }}
                    </td>
                </ng-container>
                <asy-text-column name="browser" sortable />
                <asy-text-column name="os" sortable />
                <asy-text-column name="url" header="Submitted From" sortable />
                <ng-container cdkColumnDef="status">
                    <th cdk-header-cell *cdkHeaderCellDef>
                        <asy-header-sort> Status </asy-header-sort>
                        <asy-header-filter list-filter [options]="['New', 'Open', 'Closed']" />
                    </th>
                    <td cdk-cell *cdkCellDef="let feedback">
                        <button
                            class="btn btn-text dropdown-toggle p-0"
                            id="feedback-{{ feedback._id }}-status-menu-btn"
                            type="button"
                            attr.aria-controls="feedback-{{ feedback._id }}-status-menu"
                            [cdkMenuTriggerFor]="statusMenu"
                        >
                            {{ feedback.status }}
                        </button>
                        <ng-template #statusMenu>
                            <div
                                class="dropdown-menu"
                                id="feedback-{{ feedback._id }}-status-menu"
                                attr.aria-labelledby="feedback-{{ feedback._id }}-status-menu-btn"
                                cdkMenu
                            >
                                @if (feedback.status !== feedbackStatusOptions.OPEN) {
                                    <button
                                        class="dropdown-item"
                                        type="button"
                                        cdkMenuItem
                                        (cdkMenuItemTriggered)="
                                            updateFeedbackStatus(
                                                feedback,
                                                feedbackStatusOptions.OPEN
                                            )
                                        "
                                    >
                                        Open
                                    </button>
                                }
                                @if (feedback.status !== feedbackStatusOptions.CLOSED) {
                                    <button
                                        class="dropdown-item"
                                        type="button"
                                        cdkMenuItem
                                        (cdkMenuItemTriggered)="
                                            updateFeedbackStatus(
                                                feedback,
                                                feedbackStatusOptions.CLOSED
                                            )
                                        "
                                    >
                                        Close
                                    </button>
                                }
                            </div>
                        </ng-template>
                    </td>
                </ng-container>
                <ng-container cdkColumnDef="assignee">
                    <th cdk-header-cell *cdkHeaderCellDef>
                        <asy-header-sort>Assignee</asy-header-sort>
                    </th>
                    <td cdk-cell *cdkCellDef="let feedback">
                        <button
                            class="btn btn-text dropdown-toggle p-0"
                            id="feedback-{{ feedback._id }}-assignee-menu-btn"
                            type="button"
                            attr.aria-controls="feedback-{{ feedback._id }}-assignee-menu"
                            [cdkMenuTriggerFor]="assigneeMenu"
                        >
                            {{ feedback.assignee ?? 'None' }}
                        </button>
                        <ng-template #assigneeMenu>
                            <div
                                class="dropdown-menu"
                                id="feedback-{{ feedback._id }}-assignee-menu"
                                attr.aria-labelledby="feedback-{{ feedback._id }}-assignee-menu-btn"
                                cdkMenu
                            >
                                <button
                                    class="dropdown-item"
                                    type="button"
                                    cdkMenuItem
                                    (cdkMenuItemTriggered)="updateFeedbackAssignee(feedback)"
                                >
                                    None
                                </button>
                                @for (username of assigneeUsernames(); track username) {
                                    <button
                                        class="dropdown-item"
                                        type="button"
                                        cdkMenuItem
                                        (cdkMenuItemTriggered)="
                                            updateFeedbackAssignee(feedback, username)
                                        "
                                    >
                                        {{ username }}
                                    </button>
                                }
                            </div>
                        </ng-template>
                    </td>
                </ng-container>
                <tr cdk-header-row *cdkHeaderRowDef="displayedColumns(); sticky: true"></tr>
                <tr cdk-row *cdkRowDef="let team; columns: displayedColumns()"></tr>
            </table>

            <asy-table-empty-state
                emptyText="No feedback is available."
                filteredText="No feedback matched your search."
                [dataSource]="dataSource"
                (clearFilters)="clearFilters()"
            />
        </div>

        <asy-sidebar headerText="Columns" #sidebar>
            <asy-column-chooser
                [columns]="columns"
                [storageKey]="dataSource.storageKey"
                (columnsChange)="columnsChanged($event)"
            />
        </asy-sidebar>
    </div>

    <div class="table-footer d-flex align-items-center">
        <div class="table-footer-pager ms-auto">
            <asy-paginator [dataSource]="dataSource" />
        </div>
    </div>
</section>