Skip to content

Commit

Permalink
feat(components/pages): add sky-modal-link-list component (#3131) (#…
Browse files Browse the repository at this point in the history
…3132)

🍒 Cherry picked from #3131 [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)

Co-authored-by: John White <[email protected]>
  • Loading branch information
blackbaud-sky-build-user and johnhwhite authored Feb 10, 2025
1 parent f658639 commit 306f929
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 32 deletions.
1 change: 1 addition & 0 deletions libs/components/pages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<sky-link-list-recently-accessed [recentLinks]="recentLinks" />
<sky-modal-link-list
[links]="settingsLinks"
[title]="'sky_action_hub_settings_links' | skyLibResources"
[headingText]="'sky_action_hub_settings_links' | skyLibResources"
/>
</sky-page-links>
</sky-page>
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<sky-wait [isWaiting]="links === 'loading'" />
@if (links === 'loading') {
<sky-wait [isWaiting]="links() === 'loading'" />
@if (links() === 'loading') {
<ng-container [ngTemplateOutlet]="headingTemplateRef" />
} @else {
@if (linksArray.length > 0) {
@if (linksArray().length > 0) {
<ng-container [ngTemplateOutlet]="headingTemplateRef" />
<ul class="sky-link-list">
@for (link of linksArray; track link) {
@for (link of linksArray(); track link) {
<li>
@if (link | linkAs: 'skyHref') {
<a class="sky-link-list-item" [skyHref]="link.permalink?.url">
Expand Down Expand Up @@ -50,6 +50,6 @@

<ng-template #headingTemplateRef>
<h2 class="sky-font-heading-4">
{{ title }}
{{ headingText() }}
</h2>
</ng-template>
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -44,28 +45,46 @@ 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<HTMLButtonElement>(
fixture.nativeElement.querySelectorAll('button.sky-link-list-item'),
);
expect(link.length).toBe(1);
SkyAppTestUtility.fireDomEvent(link[0], 'click');
expect(openModalSpy).toHaveBeenCalledWith(MockStandaloneComponent, {});
});

it('should log when modal is not standalone', () => {
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<HTMLButtonElement>(
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();
});
});
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
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 `<sky-page-links>` component.
*/
@Component({
selector: 'sky-modal-link-list',
templateUrl: './modal-link-list.component.html',
styleUrls: ['./modal-link-list.component.scss'],
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<SkyPageModalLinksInput>();

@Input()
public title: string | undefined;
/**
* The text to display as the list's heading.
*/
public readonly headingText = input<string>();

public linksArray: SkyPageModalLink[] = [];

#_links: SkyPageModalLinksInput | undefined;
protected readonly linksArray = computed<SkyPageModalLink[]>(() => {
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) {
Expand Down
6 changes: 6 additions & 0 deletions libs/components/pages/src/lib/modules/page/page.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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,
Expand Down

0 comments on commit 306f929

Please sign in to comment.