Asymmetrik/ngx-starter

View on GitHub
src/app/core/site-navbar/site-navbar.component.html

Summary

Maintainability
Test Coverage
<nav
    class="navbar d-flex flex-column align-items-stretch py-0 bg-body-tertiary border-end"
    [ngClass]="{ 'navbar-open': navbarOpen(), 'navbar-close': !navbarOpen() }"
>
    <nav class="nav flex-column border-bottom">
        <a class="nav-link navbar-logo p-1 border-bottom" href="#">
            <img ngSrc="/assets/images/nav-logo.png" height="184" width="184" alt="Logo" />
            <span class="nav-label">{{ appTitle() }}</span>
        </a>
    </nav>

    <div class="nav-inner-scroll" cdkScrollable>
        <nav class="nav nav-pills nav-main flex-column">
            @for (navbarItem of navbarItems; track navbarItem) {
                @if (session().hasSomeRoles(navbarItem.hasSomeRoles)) {
                    <a
                        class="nav-link"
                        container="body"
                        placement="end"
                        routerLinkActive="active"
                        [disableTooltip]="navbarOpen()"
                        [ngbTooltip]="navbarItem.title"
                        [routerLink]="navbarItem.path"
                    >
                        <span class="nav-icon fa-solid fa-fw {{ navbarItem.iconClass }}"></span>
                        <span class="nav-label">{{ navbarItem.title }}</span>
                    </a>
                }
            }
        </nav>

        <!-- Bottom Aux Nav -->
        <nav class="nav nav-pills nav-aux flex-column">
            <!-- Auditor Nav    -->
            @if (auditEnabled && session().hasRole('auditor')) {
                <a
                    class="nav-link"
                    container="body"
                    ngbTooltip="Audit Logs"
                    placement="end"
                    routerLink="/audit"
                    routerLinkActive="active"
                    [disableTooltip]="navbarOpen()"
                >
                    <span class="nav-icon fa-solid fa-fw fa-file-text"></span>
                    <span class="nav-label">Audit Logs</span>
                </a>
            }

            <!-- Team Nav   -->
            @if (teamsEnabled && session().isUser()) {
                <a
                    class="nav-link"
                    container="body"
                    ngbTooltip="Teams"
                    placement="end"
                    routerLink="/team"
                    routerLinkActive="active"
                    [disableTooltip]="navbarOpen()"
                >
                    <span class="nav-icon fa-solid fa-fw fa-users"></span>
                    <span class="nav-label">Teams</span>
                </a>
            }

            <!-- User Nav    -->
            @if (session().isAuthenticated()) {
                <a
                    class="nav-link"
                    [class.highlight-link]="userNavOpen()"
                    id="user-nav-menu-btn"
                    aria-controls="user-nav-menu"
                    container="body"
                    linkAccessibility
                    ngbTooltip="User Profile"
                    placement="end"
                    [cdkMenuPosition]="menuPositions"
                    [cdkMenuTriggerFor]="userNav"
                    [disableTooltip]="navbarOpen()"
                    (cdkMenuClosed)="userNavOpen.set(false)"
                    (cdkMenuOpened)="userNavOpen.set(true)"
                >
                    @if (!isMasquerade()) {
                        <span class="nav-icon fa-solid fa-fw fa-user-circle"></span>
                    } @else {
                        <span class="nav-icon fa-solid fa-fw fa-user-secret"></span>
                    }
                    <span class="nav-label">{{ session().user?.name }}</span>
                </a>

                <ng-template #userNav>
                    <div
                        class="nav-menu dropdown-menu"
                        id="user-nav-menu"
                        aria-labelledby="user-nav-menu-btn"
                        cdkMenu
                    >
                        <!-- User Signout -->
                        <a class="dropdown-item" href="/api/auth/signout" cdkMenuItem> Sign out </a>
                        @if (session().user?.eua) {
                            <button
                                class="dropdown-item"
                                type="button"
                                cdkMenuItem
                                routerLink="/eua"
                            >
                                View EUA
                            </button>
                        }

                        <!-- User Preferences -->
                        @if (showUserPreferencesLink()) {
                            <button
                                class="dropdown-item"
                                type="button"
                                cdkMenuItem
                                [routerLink]="userPreferencesLink()"
                            >
                                User Preferences
                            </button>
                        }
                        @if (masqueradeEnabled() && (canMasquerade() || isMasquerade())) {
                            <button
                                class="dropdown-item"
                                type="button"
                                cdkMenuItem
                                routerLink="/masquerade"
                            >
                                @if (isMasquerade()) {
                                    Clear
                                }
                                Masquerade
                            </button>
                        }
                        <app-theme-toggle class="dropdown-item" cdkMenuItem />
                    </div>
                </ng-template>
            }

            @if (masqueradeEnabled() && isMasquerade() && !this.session().isAuthenticated()) {
                <a
                    class="nav-link"
                    container="body"
                    ngbTooltip="Clear Masquerade"
                    placement="end"
                    routerLink="masquerade"
                    routerLinkActive="active"
                    [disableTooltip]="navbarOpen()"
                >
                    <span class="class nav-icon fa-stack">
                        <span class="fa-solid fa-lg fa-user-secret fa-stack-1x"></span>
                        <span class="fa-solid fa-ban fa-stack-2x text-danger"></span>
                    </span>
                    <span class="nav-label">Clear Masquerade</span>
                </a>
            }

            <!-- Admin Nav    -->
            @if (adminEnabled && session().isAdmin()) {
                <a
                    class="nav-link"
                    [class.highlight-link]="adminNavOpen()"
                    id="admin-nav-menu-btn"
                    aria-controls="admin-nav-menu"
                    container="body"
                    linkAccessibility
                    ngbTooltip="Admin"
                    placement="end"
                    [cdkMenuPosition]="menuPositions"
                    [cdkMenuTriggerFor]="adminNav"
                    [disableTooltip]="navbarOpen()"
                    (cdkMenuClosed)="adminNavOpen.set(false)"
                    (cdkMenuOpened)="adminNavOpen.set(true)"
                >
                    <span class="nav-icon fa-solid fa-fw fa-cog"></span>
                    <span class="nav-label">Admin</span>
                </a>

                <ng-template #adminNav>
                    <div
                        class="nav-menu dropdown-menu"
                        id="admin-nav-menu"
                        aria-labelledby="admin-nav-menu-btn"
                        cdkMenu
                    >
                        @for (adminItem of adminTopics; track adminItem) {
                            <button
                                class="dropdown-item"
                                type="button"
                                cdkMenuItem
                                [routerLink]="['admin/' + adminItem.path]"
                            >
                                {{ adminItem.title }}
                            </button>
                        }
                    </div>
                </ng-template>
            }

            <!-- Messages Nav   -->
            @if (session().isUser()) {
                <button
                    class="nav-link"
                    [class.highlight-link]="messagesNavOpen()"
                    type="button"
                    container="body"
                    ngbTooltip="Notifications"
                    placement="end"
                    #trigger
                    [disableTooltip]="navbarOpen()"
                    (click)="messagesNavOpen.set(!messagesNavOpen())"
                >
                    <span
                        class="nav-icon fa-solid fa-fw fa-bell position-relative"
                        [class.messages-icon]="numNewMessages() > 0"
                        [attr.data-new-messages-count]="numNewMessages()"
                    ></span>
                    <span class="nav-label">Notifications</span>
                </button>
                <ng-template
                    cdkConnectedOverlay
                    cdkConnectedOverlayPanelClass="messages-nav"
                    [cdkConnectedOverlayOpen]="messagesNavOpen()"
                    [cdkConnectedOverlayOrigin]="trigger"
                    [cdkConnectedOverlayPositions]="menuPositions"
                    [cdkConnectedOverlayPush]="true"
                    [cdkConnectedOverlayViewportMargin]="24"
                    (overlayOutsideClick)="messagesNavOpen.set(false)"
                >
                    <div class="dropdown-menu messages-menu">
                        <app-recent-messages (viewAllClicked)="messagesNavOpen.set(false)" />
                    </div>
                </ng-template>
            }

            <!-- Help Nav -->
            <a
                class="nav-link"
                [class.highlight-link]="helpNavOpen()"
                id="help-nav-menu-btn"
                aria-controls="help-nav-menu"
                container="body"
                linkAccessibility
                ngbTooltip="Help"
                placement="end"
                [cdkMenuPosition]="menuPositions"
                [cdkMenuTriggerFor]="helpNav"
                [disableTooltip]="navbarOpen()"
                (cdkMenuClosed)="helpNavOpen.set(false)"
                (cdkMenuOpened)="helpNavOpen.set(true)"
            >
                <span class="nav-icon fa-solid fa-fw fa-question-circle"></span>
                <span class="nav-label">Help</span>
            </a>

            <ng-template #helpNav>
                <div
                    class="nav-menu dropdown-menu"
                    id="help-nav-menu"
                    aria-labelledby="help-nav-menu-btn"
                    cdkMenu
                >
                    <!-- Help -->
                    @if (helpEnabled) {
                        <button class="dropdown-item" type="button" cdkMenuItem routerLink="/help">
                            Help Docs
                        </button>
                    }
                    <!-- Feedback -->
                    @if (isAuthenticated() && showFeedbackOption()) {
                        <button
                            class="dropdown-item"
                            type="button"
                            cdkMenuItem
                            (cdkMenuItemTriggered)="showFeedbackModal()"
                        >
                            Give Feedback
                        </button>
                    }
                    <!-- API Docs -->
                    @if (showApiDocsLink()) {
                        <a class="dropdown-item" [href]="apiDocsLink()" cdkMenuItem target="_blank">
                            API Docs
                        </a>
                    }
                    <!-- About -->
                    <button class="dropdown-item" type="button" cdkMenuItem routerLink="/about">
                        About
                    </button>
                </div>
            </ng-template>
        </nav>
    </div>

    <nav class="nav nav-collapse flex-column border-top">
        <!-- Divider -->
        <li class="element element-divider element-divider-collapse"></li>

        <!-- Collapse/Expand -->
        <button class="nav-link text-start" type="button" (click)="toggleNavbar()">
            <span
                class="nav-icon fa-solid fa-fw fa-angle-double-right"
                [class.fa-flip-horizontal]="navbarOpen()"
            ></span>
            <span class="nav-label">Collapse</span>
        </button>
    </nav>
</nav>

<div
    class="navbar-content"
    [ngClass]="{ 'navbar-open': navbarOpen(), 'navbar-close': !navbarOpen() }"
>
    <ng-content />
</div>