Skip to content

Commit

Permalink
feat(markdown-nav): add children url property
Browse files Browse the repository at this point in the history
  • Loading branch information
christianmemije committed Apr 3, 2020
1 parent 9d770f1 commit bba9ac9
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<td-markdown-navigator [items]="items"></td-markdown-navigator>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component } from '@angular/core';
import { IMarkdownNavigatorItem } from '@covalent/markdown-navigator';

@Component({
selector: 'markdown-navigator-demo-children-url',
styleUrls: ['./markdown-navigator-demo-children-url.component.scss'],
templateUrl: './markdown-navigator-demo-children-url.component.html',
})
export class MarkdownNavigatorDemoChildrenUrlComponent {
items: IMarkdownNavigatorItem[] = [
{
title: '🔥',
childrenUrl: 'https://api.myjson.com/bins/aqnfk',
},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
<demo-component [demoId]="'markdown-navigator-demo-events'">
<markdown-navigator-demo-events></markdown-navigator-demo-events>
</demo-component>

<demo-component [demoId]="'markdown-navigator-demo-children-url'">
<markdown-navigator-demo-children-url></markdown-navigator-demo-children-url>
</demo-component>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from './markdown-navigator-demo-footer/markdown-navigator-demo-footer.component';
import { MatListModule } from '@angular/material/list';
import { MarkdownNavigatorDemoEventsComponent } from './markdown-navigator-demo-events/markdown-navigator-demo-events.component';
import { MarkdownNavigatorDemoChildrenUrlComponent } from './markdown-navigator-demo-children-url/markdown-navigator-demo-children-url.component';

@NgModule({
declarations: [
Expand All @@ -22,6 +23,7 @@ import { MarkdownNavigatorDemoEventsComponent } from './markdown-navigator-demo-
MarkdownNavigatorDemoFooterExampleAComponent,
MarkdownNavigatorDemoFooterExampleBComponent,
MarkdownNavigatorDemoEventsComponent,
MarkdownNavigatorDemoChildrenUrlComponent,
],
imports: [
DemoModule,
Expand Down
1 change: 1 addition & 0 deletions src/platform/markdown-navigator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface IMarkdownNavigatorItem {
markdownString?: string; // raw markdown
anchor?: string;
children?: IMarkdownNavigatorItem[];
childrenUrl?: string;
description?: string;
icon?: string;
footer?: Type<any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { By } from '@angular/platform-browser';
import { Component, DebugElement, Type } from '@angular/core';
import { CovalentMarkdownNavigatorModule } from './markdown-navigator.module';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';

const RAW_MARKDOWN_HEADING: string = 'Heading';
const RAW_MARKDOWN: string = `# ${RAW_MARKDOWN_HEADING}`;
Expand Down Expand Up @@ -79,6 +81,15 @@ const ITEMS_WITH_FOOTERS: IMarkdownNavigatorItem[] = [
},
];

const CHILDREN_URL: string = 'https://samplechildrenurl.com';

const ITEMS_WITH_CHILDREN_URL: IMarkdownNavigatorItem[] = [
{
title: 'Children url',
childrenUrl: CHILDREN_URL,
},
];

export const DEEPLY_NESTED_TREE: IMarkdownNavigatorItem[] = [
{
title: 'A',
Expand Down Expand Up @@ -288,11 +299,17 @@ class TdMarkdownNavigatorTestComponent {
}

describe('MarkdownNavigatorComponent', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TdMarkdownNavigatorTestComponent],
imports: [NoopAnimationsModule, CovalentMarkdownNavigatorModule],
imports: [NoopAnimationsModule, CovalentMarkdownNavigatorModule, HttpClientTestingModule],
}).compileComponents();

httpClient = TestBed.inject(HttpClient);
httpTestingController = TestBed.inject(HttpTestingController);
}));

it('should render empty state when an empty array is passed into items', async(
Expand Down Expand Up @@ -361,6 +378,42 @@ describe('MarkdownNavigatorComponent', () => {
}),
));

it('should fetch childrenUrl and render', async(
inject([], async () => {
const itemATitle: string = 'fetched item A';
const itemBTitle: string = 'fetched item B';

const testData: IMarkdownNavigatorItem[] = [{ title: itemATitle }, { title: itemBTitle }];
const fixture: ComponentFixture<TdMarkdownNavigatorTestComponent> = TestBed.createComponent(
TdMarkdownNavigatorTestComponent,
);

fixture.componentInstance.items = ITEMS_WITH_CHILDREN_URL;
await wait(fixture);

const markdownNavigator: TdMarkdownNavigatorComponent = fixture.debugElement.query(
By.directive(TdMarkdownNavigatorComponent),
).componentInstance;

expect(markdownNavigator.showMenu).toBeTruthy();
expect(markdownNavigator.showTdMarkdown).toBeFalsy();

getItem(fixture, 0).click();
const req: TestRequest = httpTestingController.expectOne(CHILDREN_URL);
req.flush(testData);

await wait(fixture);
await wait(fixture);

expect(markdownNavigator.showMenu).toBeTruthy();
expect(markdownNavigator.showTdMarkdown).toBeFalsy();
expect(getItem(fixture, 0).textContent).toContain(itemATitle);
expect(getItem(fixture, 1).textContent).toContain(itemBTitle);

httpTestingController.verify();
}),
));

it('should render one url item from GitHub', async(
inject([], async () => {
const fixture: ComponentFixture<TdMarkdownNavigatorTestComponent> = TestBed.createComponent(
Expand Down
49 changes: 46 additions & 3 deletions src/platform/markdown-navigator/markdown-navigator.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import {
Type,
Output,
EventEmitter,
SecurityContext,
} from '@angular/core';
import { removeLeadingHash, isAnchorLink, TdMarkdownLoaderService } from '@covalent/markdown';
import { ITdFlavoredMarkdownButtonClickEvent } from '@covalent/flavored-markdown';
import { DomSanitizer } from '@angular/platform-browser';
import { HttpClient } from '@angular/common/http';

export interface IMarkdownNavigatorItem {
title?: string;
Expand All @@ -22,6 +25,7 @@ export interface IMarkdownNavigatorItem {
markdownString?: string; // raw markdown
anchor?: string;
children?: IMarkdownNavigatorItem[];
childrenUrl?: string;
description?: string;
icon?: string;
footer?: Type<any>;
Expand Down Expand Up @@ -145,6 +149,8 @@ export class TdMarkdownNavigatorComponent implements OnChanges {
constructor(
private _markdownUrlLoaderService: TdMarkdownLoaderService,
private _changeDetectorRef: ChangeDetectorRef,
private _sanitizer: DomSanitizer,
private _http: HttpClient,
) {}

@HostListener('click', ['$event'])
Expand Down Expand Up @@ -245,9 +251,14 @@ export class TdMarkdownNavigatorComponent implements OnChanges {
}
}

hasChildrenOrChildrenUrl(item: IMarkdownNavigatorItem): boolean {
return (item.children && item.children.length > 0) || !!item.childrenUrl;
}

reset(): void {
this.loading = false;
// if single item and no children
if (this.items && this.items.length === 1 && (!this.items[0].children || this.items[0].children.length === 0)) {
if (this.items && this.items.length === 1 && !this.hasChildrenOrChildrenUrl(this.items[0])) {
this.currentMenuItems = [];
this.currentMarkdownItem = this.items[0];
} else {
Expand All @@ -259,10 +270,11 @@ export class TdMarkdownNavigatorComponent implements OnChanges {
}

goBack(): void {
this.loading = false;
if (this.historyStack.length > 1) {
const parent: IMarkdownNavigatorItem = this.historyStack[this.historyStack.length - 2];
this.currentMarkdownItem = parent;
this.currentMenuItems = parent.children;
this.setChildrenAsCurrentMenuItems(parent);
this.historyStack = this.historyStack.slice(0, -1);
} else {
// one level down just go to root
Expand All @@ -273,11 +285,42 @@ export class TdMarkdownNavigatorComponent implements OnChanges {

handleItemSelected(item: IMarkdownNavigatorItem): void {
this.historyStack = [...this.historyStack, item];
this.currentMenuItems = item.children;
this.setChildrenAsCurrentMenuItems(item);
this.currentMarkdownItem = item;
this._changeDetectorRef.markForCheck();
}

async setChildrenAsCurrentMenuItems(item: IMarkdownNavigatorItem): Promise<void> {
this.currentMenuItems = [];
this.loading = true;
this._changeDetectorRef.markForCheck();

const itemToVerifyWith: IMarkdownNavigatorItem = this.historyStack[0];
let children: IMarkdownNavigatorItem[] = [];
if (item.children) {
children = item.children;
} else if (item.childrenUrl) {
children = await this.loadChildrenUrl(item);
}
if (this.historyStack[0] === itemToVerifyWith) {
this.currentMenuItems = children;
}

this.loading = false;
this._changeDetectorRef.markForCheck();
}

async loadChildrenUrl(item: IMarkdownNavigatorItem): Promise<IMarkdownNavigatorItem[]> {
const sanitizedUrl: string = this._sanitizer.sanitize(SecurityContext.URL, item.childrenUrl);
try {
return await this._http
.get<IMarkdownNavigatorItem[]>(sanitizedUrl, { ...item.httpOptions })
.toPromise();
} catch {
return [];
}
}

getTitle(item: IMarkdownNavigatorItem): string {
if (item) {
return (
Expand Down

0 comments on commit bba9ac9

Please sign in to comment.