Skip to content

Commit

Permalink
Port banner system from old site (ft. deferring)
Browse files Browse the repository at this point in the history
I tried to fix the closing animation but just couldn't.
  • Loading branch information
jvyden committed Aug 26, 2024
1 parent ac5dde2 commit aa5479b
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<app-header class="z-40"></app-header>
@defer (when bannerService.banners.length > 0) {
<app-popup-banner-container class="container"></app-popup-banner-container>
}
<div class="container mx-auto bg-backdrop p-5 border-divider">
<router-outlet />
</div>
5 changes: 4 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import {EmbedService} from "./services/embed.service";
import {FaIconLibrary} from "@fortawesome/angular-fontawesome";
import {fas} from "@fortawesome/free-solid-svg-icons";
import {AuthenticationService} from "./api/authentication.service";
import {PopupBannerContainerComponent} from "./banners/popup-banner-container.component";
import {BannerService} from "./banners/banner.service";

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, HeaderComponent],
imports: [RouterOutlet, HeaderComponent, PopupBannerContainerComponent],
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private title: TitleService,
private embed: EmbedService,
private auth: AuthenticationService,
protected bannerService: BannerService,
library: FaIconLibrary) {
library.addIconPacks(fas)
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import {APIv3Interceptor} from "./api/interceptors/apiv3.interceptor";
import {IMAGE_LOADER} from "@angular/common";
import {loadImage} from "./helpers/data-fetching";
import {ApiTokenInterceptor} from "./api/interceptors/api-token.interceptor";
import {provideAnimations} from "@angular/platform-browser/animations";
import {provideAnimationsAsync} from "@angular/platform-browser/animations/async";

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideClientHydration(),
provideHttpClient(withInterceptorsFromDi()),
provideAnimationsAsync(),
useInterceptor(ApiBaseInterceptor),
useInterceptor(APIv3Interceptor),
useInterceptor(ApiTokenInterceptor),
Expand Down
11 changes: 11 additions & 0 deletions src/app/banners/banner-info.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {IconProp} from "@fortawesome/fontawesome-svg-core";

export interface BannerInfo {
// Styling
color: string
icon: IconProp

// Text
title: string
text: string
}
42 changes: 42 additions & 0 deletions src/app/banners/banner.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {Injectable} from "@angular/core";
import {BannerInfo} from "./banner-info.interface";

@Injectable({providedIn: 'root'})
export class BannerService {
banners: BannerInfo[] = []

add(banner: BannerInfo) {
this.banners.push(banner);
}

dismiss(id: number): void {
this.banners.splice(id, 1);
}

success(title: string, text: string) {
this.add({
color: 'bg-success',
icon: 'check-circle',
text: text,
title: title,
})
}

warn(title: string, text: string) {
this.add({
color: 'bg-warning',
icon: 'warning',
text: text,
title: title,
})
}

error(title: string, text: string) {
this.add({
color: 'dangerous',
icon: 'exclamation-circle',
text: text,
title: title,
})
}
}
22 changes: 22 additions & 0 deletions src/app/banners/popup-banner-container.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component } from '@angular/core';
import {BannerService} from "./banner.service";
import {PopupBannerComponent} from "./popup-banner.component";
import {NgForOf} from "@angular/common";

@Component({
selector: 'app-popup-banner-container',
standalone: true,
imports: [
PopupBannerComponent,
NgForOf
],
template: `
<ng-container *ngFor="let info of bannerService.banners; let i = index">
<app-popup-banner [info]="info" [id]="i"></app-popup-banner>
</ng-container>
`
})
export class PopupBannerContainerComponent {
constructor(protected bannerService: BannerService) {
}
}
65 changes: 65 additions & 0 deletions src/app/banners/popup-banner.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {Component, HostBinding, Input} from '@angular/core';
import {BannerInfo} from "./banner-info.interface";
import {FaIconComponent} from "@fortawesome/angular-fontawesome";
import {NgIf} from "@angular/common";
import {BannerService} from "./banner.service";
import {animate, animateChild, query, style, transition, trigger} from "@angular/animations";

@Component({
selector: 'app-popup-banner',
standalone: true,
imports: [
FaIconComponent,
NgIf
],
animations: [
trigger('expand', [
transition(':leave', [
query('@*', animateChild(), {optional: true}),
animate('300ms ease-in-out', style({
opacity: 0,
height: 0,
'padding-top': 0,
'padding-bottom': 0,
'border-bottom': 0
})),
]),
transition(':enter', [
style({opacity: 0, height: 0, 'padding-top': 0, 'padding-bottom': 0}),
animate('500ms ease-in-out', style({
opacity: 1,
height: '*',
'padding-top': '*',
'padding-bottom': '*'
})),
]),
]),
],
template: `
<!-- defer to give the async animation system a reasonable amount of time to pull down js-->
@defer (on timer(50ms)) {
<div @expand class="mx-auto {{info.color}} p-5 py-3 border-b-2 text-lg overflow-hidden">
<fa-icon *ngIf="id != -1" class="float-right cursor-pointer transition-colors hover:text-dangerous"
title="Dismiss" (click)="dismiss()" [icon]="'xmark'"></fa-icon>
<fa-icon [icon]="info.icon" class="pr-2"></fa-icon>
<span class="font-bold">{{ info.title }}</span>
<p class="text-sm">{{ info.text }}</p>
</div>
}
`,
})
export class PopupBannerComponent {
@HostBinding("@expand") parentAnimation = true;

@Input() id: number = -1;
@Input({required: true}) info: BannerInfo = null!;

constructor(private bannerService: BannerService) {}

dismiss() {
if(this.id == -1) return;
this.bannerService.dismiss(this.id);
}
}
5 changes: 5 additions & 0 deletions src/app/debug/debug.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const debugRoutes: Routes = [
path: 'form',
loadComponent: () => import('./pages/form-debug/form-debug.component').then(x => x.FormDebugComponent),
data: {title: "Example Form"},
},
{
path: 'notifications',
loadComponent: () => import('./pages/notifications/notifications.component').then(x => x.NotificationsComponent),
data: {title: "Notifications Debug"},
}
]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<app-page-title></app-page-title>

<app-button-group>
<app-button text="Success" color="bg-success" [icon]="faCheckCircle" (click)="bannerSuccess()"></app-button>
</app-button-group>
27 changes: 27 additions & 0 deletions src/app/debug/pages/notifications/notifications.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Component } from '@angular/core';
import {PageTitleComponent} from "../../../components/ui/text/page-title.component";
import {ButtonGroupComponent} from "../../../components/ui/form/button-group.component";
import {ButtonComponent} from "../../../components/ui/form/button.component";
import {faCheckCircle} from "@fortawesome/free-solid-svg-icons";
import {BannerService} from "../../../banners/banner.service";

@Component({
selector: 'app-notifications',
standalone: true,
imports: [
PageTitleComponent,
ButtonGroupComponent,
ButtonComponent
],
templateUrl: './notifications.component.html'
})
export class NotificationsComponent {
protected readonly faCheckCircle = faCheckCircle;

constructor(private bannerService: BannerService) {
}

bannerSuccess() {
this.bannerService.success("You Did It", "Congration On Doing The Thing");
}
}
2 changes: 1 addition & 1 deletion src/app/pages/auth/login/login.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<app-form [form]="form" (submit)="submit()">
<app-textbox [icon]="faEnvelope" [form]="form" placeholder="[email protected]" ctrlName="emailAddress" label="Email Address" type="email"></app-textbox>
<app-textbox [icon]="faKey" [form]="form" placeholder="Your very secure password" ctrlName="password" label="Password" type="password"></app-textbox>
<app-textbox [icon]="faKey" [form]="form" placeholder="•••••••••" ctrlName="password" label="Password" type="password"></app-textbox>

<ng-container buttons>
<app-button-submit-form [form]="form" action="Log In"></app-button-submit-form>
Expand Down

0 comments on commit aa5479b

Please sign in to comment.