Skip to content

Commit

Permalink
feat: new @ng-web-apis/notification package (Notification API)
Browse files Browse the repository at this point in the history
  • Loading branch information
nsbarsukov committed Sep 29, 2023
1 parent 71739e1 commit aa56784
Show file tree
Hide file tree
Showing 32 changed files with 885 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ testem.log
Thumbs.db

apps/demo/routesFile.txt
.ssl
20 changes: 20 additions & 0 deletions apps/demo/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@
},
"defaultConfiguration": "development"
},
"serve-ssl": {
"executor": "nx:run-commands",
"options": {
"command": "nx mkcert demo && nx serve demo --ssl --open --host 0.0.0.0 --disable-host-check"
}
},
"generate-routes-file": {
"executor": "nx:run-commands",
"options": {
Expand Down Expand Up @@ -185,6 +191,20 @@
"params": "ignore"
}
]
},
"mkcert": {
"executor": "nx:run-commands",
"options": {
"parallel": false,
"commands": [
"echo \"mkcert is a simple tool for making locally-trusted development certificates\"",
"echo \"Read about installation and more: https://github.com/FiloSottile/mkcert\"",
"echo ------",
"mkcert -install",
"mkdir -p .ssl",
"mkcert -key-file .ssl/localhost-key.pem -cert-file .ssl/localhost.pem localhost 127.0.0.1 $(ifconfig | grep \"inet \" | grep -Fv 127.0.0.1 | awk '{print $2}' | tr '\\n' ' ') ::1"
]
}
}
}
}
6 changes: 6 additions & 0 deletions apps/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ export const appRoutes: Routes = [
(await import(`./pages/view-transition/view-transition-page.module`))
.ViewTransitionPageModule,
},
{
path: DemoPath.Notification,
loadChildren: async () =>
(await import(`./pages/notification/notification-page.module`))
.NotificationPageModule,
},
{
path: '',
redirectTo: DemoPath.HomePage,
Expand Down
1 change: 1 addition & 0 deletions apps/demo/src/app/constants/demo-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export enum DemoPath {
StoragePage = `storage`,
WorkersPage = `workers`,
ViewTransitionPage = `view-transition`,
Notification = `notification`,
}
16 changes: 16 additions & 0 deletions apps/demo/src/app/pages/home/home-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,19 @@ <h2>View Transition</h2>
class="icon"
/>
</a>

<a class="link" [routerLink]="['/', link.Notification]">
<div>
<h2>Notification</h2>
A library for declarative use of
<strong>Notification API</strong>
with Angular
</div>
<img
src="assets/images/notification.svg"
width="64"
height="64"
alt="Notification API logo"
class="icon"
/>
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button tuiButton (click)="askPermission()">Ask notification permission</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {NotificationService} from '@ng-web-apis/notification';

@Component({
selector: 'notification-page-example-1',
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotificationPageExample1 {
constructor(private readonly notificationAPIService: NotificationService) {}

askPermission(): void {
this.notificationAPIService.requestPermission().subscribe({
next: permission =>
console.info(
'Permission status:',
permission, // 'denied' | 'granted'
),
error: err =>
// e.g. 'Notification API is not supported in your browser'
console.error(err),
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button tuiButton (click)="sendNotification()">Send notification</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {NotificationService} from '@ng-web-apis/notification';
import {filter, switchMap} from 'rxjs/operators';

@Component({
selector: 'notification-page-example-2',
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotificationPageExample2 {
constructor(private readonly notificationAPIService: NotificationService) {}

sendNotification(): void {
this.notificationAPIService
.requestPermission()
.pipe(
filter(permission => permission === 'granted'),
switchMap(() =>
this.notificationAPIService.open('Hello world!', {
body: 'This is a notification',
requireInteraction: true,
}),
),
)
.subscribe();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button tuiButton (click)="sendNotification()">Send notification</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {NotificationService} from '@ng-web-apis/notification';
import {timer} from 'rxjs';
import {filter, switchMap, takeUntil} from 'rxjs/operators';

@Component({
selector: 'notification-page-example-3',
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotificationPageExample3 {
constructor(private readonly notificationAPIService: NotificationService) {}

sendNotification(): void {
this.notificationAPIService
.requestPermission()
.pipe(
filter(permission => permission === 'granted'),
switchMap(() => this.notificationAPIService.open('Hello world!')),
takeUntil(timer(2_000)), // close stream after 2 seconds
)
.subscribe({
complete: () => console.info('Notification closed!'),
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<button tuiButton (click)="sendNotification()">Send notification</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {NotificationService} from '@ng-web-apis/notification';
import {fromEvent} from 'rxjs';
import {filter, switchMap} from 'rxjs/operators';

@Component({
selector: 'notification-page-example-4',
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotificationPageExample4 {
constructor(private readonly notificationAPIService: NotificationService) {}

sendNotification(): void {
this.notificationAPIService
.requestPermission()
.pipe(
filter(permission => permission === 'granted'),
switchMap(() =>
this.notificationAPIService.open(`Hello world!`, {
body: Math.random().toString(),
requireInteraction: true,
}),
),
switchMap(notification => fromEvent(notification, 'click')),
)
.subscribe(console.info);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {TuiDocExample} from '@taiga-ui/addon-doc';

@Component({
selector: 'notification-page',
templateUrl: './notification-page.template.html',
styleUrls: ['./notification-page.style.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotificationPageComponent {
readonly gettingPermissionExample: TuiDocExample = {
'index.ts': import('./examples/01-getting-permission/index.ts?raw'),
'index.html': import('./examples/01-getting-permission/index.html?raw'),
};

readonly createNotificationExample: TuiDocExample = {
'index.ts': import('./examples/02-create-notification/index.ts?raw'),
'index.html': import('./examples/02-create-notification/index.html?raw'),
};

readonly closeNotificationExample: TuiDocExample = {
'index.ts': import('./examples/03-close-notification/index.ts?raw'),
'index.html': import('./examples/03-close-notification/index.html?raw'),
};

readonly listenNotificationEventsExample: TuiDocExample = {
'index.ts': import('./examples/04-listen-notification-events/index.ts?raw'),
'index.html': import('./examples/04-listen-notification-events/index.html?raw'),
};
}
26 changes: 26 additions & 0 deletions apps/demo/src/app/pages/notification/notification-page.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {TuiAddonDocModule} from '@taiga-ui/addon-doc';
import {TuiButtonModule, TuiNotificationModule} from '@taiga-ui/core';
import {NotificationPageExample1} from './examples/01-getting-permission';
import {NotificationPageExample2} from './examples/02-create-notification';
import {NotificationPageExample3} from './examples/03-close-notification';
import {NotificationPageExample4} from './examples/04-listen-notification-events';
import {NotificationPageComponent} from './notification-page.component';

@NgModule({
imports: [
TuiAddonDocModule,
TuiButtonModule,
TuiNotificationModule,
RouterModule.forChild([{path: '', component: NotificationPageComponent}]),
],
declarations: [
NotificationPageComponent,
NotificationPageExample1,
NotificationPageExample2,
NotificationPageExample3,
NotificationPageExample4,
],
})
export class NotificationPageModule {}
14 changes: 14 additions & 0 deletions apps/demo/src/app/pages/notification/notification-page.style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
:host {
display: block;
max-width: 900px;
margin: 0 auto;
font: var(--tui-font-text-m);
}

tui-notification {
margin-bottom: 1rem;
}

h2 {
font: var(--tui-font-heading-4);
}
126 changes: 126 additions & 0 deletions apps/demo/src/app/pages/notification/notification-page.template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<h2>Notification API</h2>
<p>
A library for declarative use of
<a
tuiLink
href="https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API"
target="_blank"
>
Notification API
</a>
with Angular.
</p>
<tui-doc-code
code="npm i @ng-web-apis/notification"
filename=" "
></tui-doc-code>

<tui-doc-example
heading="Getting Permissions"
[content]="gettingPermissionExample"
>
<tui-notification status="warning">
Notification prompting can only be done from a user gesture (e.g.
clicking a button)!
<br />
Otherwise, some browsers will silently disallow notification permission
requests.
</tui-notification>

<notification-page-example-1></notification-page-example-1>
</tui-doc-example>

<tui-doc-example
heading="Create notification"
[description]="createNotificationDescription"
[content]="createNotificationExample"
>
<ng-template #createNotificationDescription>
Use
<code>open</code>
method to create a notification.
<p>
The first argument is a
<strong>title</strong>
to display within the notification.
</p>
<p>
The second argument contains many experimental
<strong>options</strong>
to enhance the notification behavior and appearance.
<br />
See the full
<a
tuiLink
href="https://developer.mozilla.org/en-US/docs/Web/API/Notification/Notification"
target="_blank"
>
list of available options
</a>
.
</p>
</ng-template>
<notification-page-example-2></notification-page-example-2>
</tui-doc-example>

<tui-doc-example
heading="Close notification"
[content]="closeNotificationExample"
[description]="closeNotificationDescription"
>
<ng-template #closeNotificationDescription>
Most modern browsers dismiss notifications automatically after a few
moments (around four seconds).

<p>
The observable (returned by
<code>open</code>
method) automatically
<strong>completes</strong>
the stream when the notification is closed (e.g. user clicks the
close button).
</p>

<p>
You can also close the notification manually by closing the stream
by
<code>takeUntil</code>
operator.
</p>
</ng-template>
<notification-page-example-3></notification-page-example-3>
</tui-doc-example>

<tui-doc-example
heading="Listen to notification events"
[description]="listenEventDescription"
[content]="listenNotificationEventsExample"
>
<ng-template #listenEventDescription>
The observable (returned by
<code>open</code>
method) emits
<code>Notification</code>
instance after its successful creation.

<p>
Use rxjs function
<code>fromEvent</code>
to listen events that can be triggered on the
<code>Notification</code>
instance.
<br />
See the full
<a
tuiLink
href="https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API#notification_events"
target="_blank"
>
list of available events
</a>
.
</p>
</ng-template>

<notification-page-example-4></notification-page-example-4>
</tui-doc-example>
Empty file added libs/notification/CHANGELOG.md
Empty file.
Loading

0 comments on commit aa56784

Please sign in to comment.