From 0f04e7ee68c0cb5927f3e4e2810806be8eb28223 Mon Sep 17 00:00:00 2001
From: John White <750350+johnhwhite@users.noreply.github.com>
Date: Mon, 10 Feb 2025 15:33:28 -0500
Subject: [PATCH] feat(components/pages): add `sky-modal-link-list` component
(#3131)
[AB#3252968](https://dev.azure.com/blackbaud/f565481a-7bc9-4083-95d5-4f953da6d499/_workitems/edit/3252968)
Related to #2784, #2800, and #2962
---
libs/components/pages/src/index.ts | 1 +
.../action-hub/action-hub.component.html | 2 +-
.../modal-link-list.component.html | 10 ++---
.../modal-link-list.component.spec.ts | 39 ++++++++++++-----
.../modal-link-list.component.ts | 43 ++++++++++++-------
.../pages/src/lib/modules/page/page.module.ts | 6 +++
6 files changed, 69 insertions(+), 32 deletions(-)
diff --git a/libs/components/pages/src/index.ts b/libs/components/pages/src/index.ts
index 96b13a8143..07d9a56525 100644
--- a/libs/components/pages/src/index.ts
+++ b/libs/components/pages/src/index.ts
@@ -5,6 +5,7 @@ export {
SkyActionHubNeedsAttentionClickHandlerArgs,
} from './lib/modules/action-hub/types/action-hub-needs-attention-click-handler';
export { SkyLinkListModule } from './lib/modules/link-list/link-list.module';
+export { SkyModalLinkListModule } from './lib/modules/modal-link-list/modal-link-list.module';
export { SkyNeedsAttentionModule } from './lib/modules/needs-attention/needs-attention.module';
export { SkyActionHubNeedsAttentionInput } from './lib/modules/action-hub/types/action-hub-needs-attention-input';
export { SkyPageLink } from './lib/modules/action-hub/types/page-link';
diff --git a/libs/components/pages/src/lib/modules/action-hub/action-hub.component.html b/libs/components/pages/src/lib/modules/action-hub/action-hub.component.html
index 9d864b7b27..271b06865e 100644
--- a/libs/components/pages/src/lib/modules/action-hub/action-hub.component.html
+++ b/libs/components/pages/src/lib/modules/action-hub/action-hub.component.html
@@ -26,7 +26,7 @@
diff --git a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.html b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.html
index 2b5ff769fa..f58dcc6561 100644
--- a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.html
+++ b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.html
@@ -1,11 +1,11 @@
-
-@if (links === 'loading') {
+
+@if (links() === 'loading') {
} @else {
- @if (linksArray.length > 0) {
+ @if (linksArray().length > 0) {
- @for (link of linksArray; track link) {
+ @for (link of linksArray(); track link) {
-
@if (link | linkAs: 'skyHref') {
@@ -50,6 +50,6 @@
- {{ title }}
+ {{ headingText() }}
diff --git a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.spec.ts b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.spec.ts
index 717ae9b452..49053987e5 100644
--- a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.spec.ts
+++ b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.spec.ts
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { SkyAppTestUtility } from '@skyux-sdk/testing';
import { SkyLogService } from '@skyux/core';
import { SkyModalService } from '@skyux/modals';
@@ -44,10 +45,18 @@ describe('SkyModalLinkListComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
- component.openModal({
- label: 'Link 1',
- modal: { component: MockStandaloneComponent, config: {} },
- });
+ fixture.componentRef.setInput('links', [
+ {
+ label: 'Link 1',
+ modal: { component: MockStandaloneComponent, config: {} },
+ },
+ ]);
+ fixture.detectChanges();
+ const link = Array.from(
+ fixture.nativeElement.querySelectorAll('button.sky-link-list-item'),
+ );
+ expect(link.length).toBe(1);
+ SkyAppTestUtility.fireDomEvent(link[0], 'click');
expect(openModalSpy).toHaveBeenCalledWith(MockStandaloneComponent, {});
});
@@ -55,17 +64,27 @@ describe('SkyModalLinkListComponent', () => {
const logger = TestBed.inject(SkyLogService);
spyOn(logger, 'deprecated');
expect(component).toBeTruthy();
- component.openModal({
- label: 'Link 1',
- modal: { component: MockComponent, config: {} },
- });
+ fixture.componentRef.setInput('links', [
+ {
+ label: 'Link 1',
+ modal: { component: MockComponent, config: {} },
+ },
+ ]);
+ fixture.detectChanges();
+ const link = Array.from(
+ fixture.nativeElement.querySelectorAll('button.sky-link-list-item'),
+ );
+ expect(link.length).toBe(1);
+ SkyAppTestUtility.fireDomEvent(link[0], 'click');
expect(logger.deprecated).toHaveBeenCalled();
expect(openModalSpy).toHaveBeenCalledWith(MockComponent, {});
});
it('should handle empty input', () => {
expect(component).toBeTruthy();
- component.links = undefined;
- expect(component.links).toBeUndefined();
+ fixture.componentRef.setInput('links', undefined);
+ fixture.detectChanges();
+ expect(component.links()).toBeUndefined();
+ expect(fixture.nativeElement.querySelector('ul.sky-link-list')).toBeFalsy();
});
});
diff --git a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.ts b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.ts
index 882ebd4128..fc10e64206 100644
--- a/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.ts
+++ b/libs/components/pages/src/lib/modules/modal-link-list/modal-link-list.component.ts
@@ -1,10 +1,19 @@
-import { Component, Input, inject, isStandalone } from '@angular/core';
+import {
+ Component,
+ computed,
+ inject,
+ input,
+ isStandalone,
+} from '@angular/core';
import { SkyLogService } from '@skyux/core';
import { SkyModalLegacyService, SkyModalService } from '@skyux/modals';
import { SkyPageModalLink } from '../action-hub/types/page-modal-link';
import { SkyPageModalLinksInput } from '../action-hub/types/page-modal-links-input';
+/**
+ * A component that displays a list of links such as within a `` component.
+ */
@Component({
selector: 'sky-modal-link-list',
templateUrl: './modal-link-list.component.html',
@@ -12,27 +21,29 @@ import { SkyPageModalLinksInput } from '../action-hub/types/page-modal-links-inp
standalone: false,
})
export class SkyModalLinkListComponent {
- @Input()
- public set links(value: SkyPageModalLinksInput | undefined) {
- this.#_links = value;
- this.linksArray = Array.isArray(value) ? value : [];
- }
-
- public get links(): SkyPageModalLinksInput | undefined {
- return this.#_links;
- }
+ /**
+ * Option to pass links as an array of `SkyPageModalLink` objects or `'loading'` to display a loading indicator.
+ */
+ public readonly links = input();
- @Input()
- public title: string | undefined;
+ /**
+ * The text to display as the list's heading.
+ */
+ public readonly headingText = input();
- public linksArray: SkyPageModalLink[] = [];
-
- #_links: SkyPageModalLinksInput | undefined;
+ protected readonly linksArray = computed(() => {
+ const links = this.links();
+ if (Array.isArray(links)) {
+ return links;
+ } else {
+ return [];
+ }
+ });
readonly #logger = inject(SkyLogService, { optional: true });
readonly #modalSvc = inject(SkyModalService);
- public openModal(link: SkyPageModalLink): void {
+ protected openModal(link: SkyPageModalLink): void {
const modal = link.modal;
if (modal) {
diff --git a/libs/components/pages/src/lib/modules/page/page.module.ts b/libs/components/pages/src/lib/modules/page/page.module.ts
index 4c57d7dc17..36af50b3b3 100644
--- a/libs/components/pages/src/lib/modules/page/page.module.ts
+++ b/libs/components/pages/src/lib/modules/page/page.module.ts
@@ -3,6 +3,8 @@ import { NgModule } from '@angular/core';
import { SkyLinkListRecentlyAccessedComponent } from '../link-list-recently-accessed/link-list-recently-accessed.component';
import { SkyLinkListItemComponent } from '../link-list/link-list-item.component';
import { SkyLinkListComponent } from '../link-list/link-list.component';
+import { SkyLinkListModule } from '../link-list/link-list.module';
+import { SkyModalLinkListModule } from '../modal-link-list/modal-link-list.module';
import { SkyPageHeaderModule } from '../page-header/page-header.module';
import { SkyPageContentComponent } from './page-content.component';
@@ -12,15 +14,19 @@ import { SkyPageComponent } from './page.component';
@NgModule({
declarations: [SkyPageComponent, SkyPageContentComponent],
imports: [
+ SkyLinkListModule,
SkyPageLinksComponent,
SkyLinkListComponent,
SkyLinkListItemComponent,
SkyLinkListRecentlyAccessedComponent,
+ SkyModalLinkListModule,
],
exports: [
SkyLinkListComponent,
SkyLinkListItemComponent,
SkyLinkListRecentlyAccessedComponent,
+ SkyLinkListModule,
+ SkyModalLinkListModule,
SkyPageComponent,
SkyPageHeaderModule,
SkyPageContentComponent,