Skip to content

Commit 475591b

Browse files
committed
feat: initial release notes component
1 parent d7e0be1 commit 475591b

14 files changed

+364
-2
lines changed

angular.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
"styles": [
2424
"src/styles.scss"
2525
],
26-
"scripts": []
26+
"scripts": [
27+
"node_modules/marked/lib/marked.js"
28+
]
2729
},
2830
"configurations": {
2931
"production": {

package-lock.json

Lines changed: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"hammerjs": "^2.0.8",
3939
"highlight.js": "^9.13.1",
4040
"markdown-to-html": "0.0.13",
41+
"ngx-markdown": "^8.1.0",
4142
"rxjs": "^6.5.2",
4243
"tslib": "^1.10.0",
4344
"web-animations-js": "^2.3.2",

src/app/app.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ export class AppComponent implements OnInit, OnDestroy {
9090
name: 'Settings',
9191
url: 'settings',
9292
icon: 'settings'
93+
},
94+
{
95+
name: 'Release notes',
96+
url: 'release-notes',
97+
icon: 'new_releases'
9398
}
9499
];
95100
constructor(

src/app/app.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import { AngularFirestoreModule } from '@angular/fire/firestore';
4444
import { AngularFireAuthModule } from '@angular/fire/auth';
4545
import { HeadlinesComponent } from './headlines/headlines.component';
4646
import { HotkeysModule } from './hotkeys/hotkeys.module';
47+
import { ComponentsModule } from './components/components.module';
48+
import { MarkdownModule } from 'ngx-markdown';
4749

4850
const OVERLAYS = [
4951
FilterOverlayComponent,
@@ -82,6 +84,7 @@ const PIPES = [
8284
FormsModule,
8385
FlexLayoutModule,
8486
HttpClientModule,
87+
MarkdownModule.forRoot(),
8588
MaterialModule,
8689
SharedModule,
8790
AppRouting,
@@ -91,7 +94,8 @@ const PIPES = [
9194
// AngularFirestoreModule.enablePersistence(),
9295
// AngularFireAuthModule,
9396
ActionItemsModule,
94-
HotkeysModule
97+
HotkeysModule,
98+
ComponentsModule
9599
],
96100
bootstrap: [AppComponent],
97101
providers: [

src/app/app.routing.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { AndroidComponent } from './devices/android/android.component';
1111
import { IOSComponent } from './devices/ios/ios.component';
1212
import { ExploreComponent } from './explore/explore.component';
1313
import { HeadlinesComponent } from './headlines/headlines.component';
14+
import { ReleaseNotesComponent } from './components/release-notes/release-notes.component';
1415

1516
const APP_ROUTES: Routes = [
1617
{
@@ -27,6 +28,7 @@ const APP_ROUTES: Routes = [
2728
{ path: 'feed', component: FeedComponent },
2829
{ path: 'headlines', component: HeadlinesComponent },
2930
{ path: 'home', redirectTo: '/feed' },
31+
{ path: 'release-notes', component: ReleaseNotesComponent },
3032
{ path: 'settings', component: SettingsComponent },
3133
{ path: 'test', component: TestpageComponent },
3234
{ path: '', pathMatch: 'full', redirectTo: '/feed' },
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { ReleaseNotesModule } from './release-notes/release-notes.module';
4+
5+
@NgModule({
6+
declarations: [],
7+
imports: [
8+
CommonModule
9+
],
10+
exports: [
11+
ReleaseNotesModule
12+
]
13+
})
14+
export class ComponentsModule { }
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<div class="app-content">
2+
<h1 id="current-version">Current version: {{ releaseNotes.latestVersion }}</h1>
3+
4+
<p><em><a routerLink="." fragment="version-{{ releaseNotes.latestVersion }}">Jump to release notes</a></em></p>
5+
<hr>
6+
7+
<h1 id="release-notes" *ngIf="versions?.length > 0">Release notes</h1>
8+
<ng-container *ngIf="versions; else: noReleaseNotes">
9+
<ng-container *ngFor="let version of versions">
10+
<h2 id="version-{{ version }}">Version {{ version }}</h2>
11+
<ng-container *ngIf="getReleaseNote(version) as releaseNote">
12+
<ng-container *ngIf="isArray(releaseNote.summary)">
13+
<p [innerHTML]="joinReleaseNotes(releaseNote.summary) | markdown"></p>
14+
</ng-container>
15+
<ng-container *ngIf="!isArray(releaseNote.summary) && isUrl(releaseNote.summary)">
16+
<p>See this <a [href]="releaseNote.summary">link</a> for more info.</p>
17+
</ng-container>
18+
</ng-container>
19+
</ng-container>
20+
</ng-container>
21+
22+
</div>
23+
<ng-template #noReleaseNotes>
24+
<div class="center">
25+
<h1 id="no-release-notes-available">No release notes available!</h1>
26+
<p>Are you connected to the internet?</p>
27+
</div>
28+
</ng-template>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { HttpClient } from '@angular/common/http';
3+
import { ReleaseNotesJSON, ReleaseNotes } from './release-notes';
4+
import releaseNotes from '../../../assets/release-notes.json';
5+
6+
@Component({
7+
selector: 'app-release-notes',
8+
templateUrl: './release-notes.component.html',
9+
styles: []
10+
})
11+
export class ReleaseNotesComponent implements OnInit {
12+
13+
constructor(private http: HttpClient) { }
14+
15+
/** Retrieves the release notes JSON file. */
16+
get releaseNotes(): ReleaseNotesJSON {
17+
return releaseNotes;
18+
}
19+
20+
/** Retrieves the list of versions. */
21+
get versions(): string[] {
22+
return Object.keys(this.releaseNotes.releases);
23+
}
24+
25+
/**
26+
* Retrieves the release notes for the specified `version`.
27+
* @param version The version
28+
*/
29+
getReleaseNote(version: string): ReleaseNotes {
30+
return this.releaseNotes.releases[version].releaseNotes;
31+
}
32+
33+
/**
34+
* Joins a list of release notes to a string.
35+
* @param notes The notes to join
36+
*/
37+
joinReleaseNotes(notes: string[]): string {
38+
return notes.join('\n');
39+
}
40+
41+
/**
42+
* Checks if the specified `val` parameter is an array.
43+
* @param val The value to check.
44+
*/
45+
isArray(val: any): boolean {
46+
return Array.isArray(val);
47+
}
48+
49+
/**
50+
* Checks whether the specified `val` parameter is a URL.
51+
* @param val The value to check.
52+
*
53+
* _See https://stackoverflow.com/a/46296668/6782707 for more info._
54+
*/
55+
isUrl(val: string): boolean {
56+
return /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/.test(val);
57+
}
58+
ngOnInit() {
59+
}
60+
61+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { HttpClientModule } from '@angular/common/http';
4+
import { RouterModule } from '@angular/router';
5+
import { MarkdownModule } from 'ngx-markdown';
6+
import { ReleaseNotesComponent } from './release-notes.component';
7+
8+
@NgModule({
9+
declarations: [ReleaseNotesComponent],
10+
exports: [ReleaseNotesComponent],
11+
imports: [
12+
CommonModule,
13+
HttpClientModule,
14+
RouterModule,
15+
MarkdownModule.forChild()
16+
]
17+
})
18+
export class ReleaseNotesModule { }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export interface Release {
2+
/** Release notes for the version. */
3+
releaseNotes: ReleaseNotes;
4+
/** Release date for the version. */
5+
releaseDate?: string | number;
6+
/** The person who released the version. */
7+
releaseAuthor?: string;
8+
}
9+
10+
export interface ReleaseNotes {
11+
/** A summary of the release notes. */
12+
summary: string[] | string;
13+
/** A detailed version of the release notes. */
14+
details?: string[] | string;
15+
}
16+
17+
export interface Releases {
18+
[key: string]: Release;
19+
}
20+
export interface ReleaseNotesJSON {
21+
/** The schema of the JSON file. */
22+
$schema: string;
23+
/** The latest version of the app. */
24+
latestVersion: string;
25+
/** The list of releases. */
26+
releases: Releases;
27+
}

0 commit comments

Comments
 (0)