From aa5479bd47328bdedeb28b57b10a5745dac87a8c Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 26 Aug 2024 18:28:16 -0400 Subject: [PATCH] Port banner system from old site (ft. deferring) I tried to fix the closing animation but just couldn't. --- src/app/app.component.html | 3 + src/app/app.component.ts | 5 +- src/app/app.config.ts | 3 + src/app/banners/banner-info.interface.ts | 11 ++++ src/app/banners/banner.service.ts | 42 ++++++++++++ .../popup-banner-container.component.ts | 22 +++++++ src/app/banners/popup-banner.component.ts | 65 +++++++++++++++++++ src/app/debug/debug.routes.ts | 5 ++ .../notifications.component.html | 5 ++ .../notifications/notifications.component.ts | 27 ++++++++ src/app/pages/auth/login/login.component.html | 2 +- 11 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/app/banners/banner-info.interface.ts create mode 100644 src/app/banners/banner.service.ts create mode 100644 src/app/banners/popup-banner-container.component.ts create mode 100644 src/app/banners/popup-banner.component.ts create mode 100644 src/app/debug/pages/notifications/notifications.component.html create mode 100644 src/app/debug/pages/notifications/notifications.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index aa0c257..91cca96 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,4 +1,7 @@ +@defer (when bannerService.banners.length > 0) { + +}
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0968b09..1a54425 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -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) } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index d038aa5..904cda3 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -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), diff --git a/src/app/banners/banner-info.interface.ts b/src/app/banners/banner-info.interface.ts new file mode 100644 index 0000000..d08855f --- /dev/null +++ b/src/app/banners/banner-info.interface.ts @@ -0,0 +1,11 @@ +import {IconProp} from "@fortawesome/fontawesome-svg-core"; + +export interface BannerInfo { + // Styling + color: string + icon: IconProp + + // Text + title: string + text: string +} \ No newline at end of file diff --git a/src/app/banners/banner.service.ts b/src/app/banners/banner.service.ts new file mode 100644 index 0000000..eca1d52 --- /dev/null +++ b/src/app/banners/banner.service.ts @@ -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, + }) + } +} \ No newline at end of file diff --git a/src/app/banners/popup-banner-container.component.ts b/src/app/banners/popup-banner-container.component.ts new file mode 100644 index 0000000..8d9670b --- /dev/null +++ b/src/app/banners/popup-banner-container.component.ts @@ -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: ` + + + + ` +}) +export class PopupBannerContainerComponent { + constructor(protected bannerService: BannerService) { + } +} diff --git a/src/app/banners/popup-banner.component.ts b/src/app/banners/popup-banner.component.ts new file mode 100644 index 0000000..f866a03 --- /dev/null +++ b/src/app/banners/popup-banner.component.ts @@ -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 (on timer(50ms)) { +
+ + + + {{ info.title }} + +

{{ info.text }}

+
+ } + `, +}) +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); + } +} diff --git a/src/app/debug/debug.routes.ts b/src/app/debug/debug.routes.ts index 8c75caa..dbceb71 100644 --- a/src/app/debug/debug.routes.ts +++ b/src/app/debug/debug.routes.ts @@ -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"}, } ] diff --git a/src/app/debug/pages/notifications/notifications.component.html b/src/app/debug/pages/notifications/notifications.component.html new file mode 100644 index 0000000..5001ce3 --- /dev/null +++ b/src/app/debug/pages/notifications/notifications.component.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/app/debug/pages/notifications/notifications.component.ts b/src/app/debug/pages/notifications/notifications.component.ts new file mode 100644 index 0000000..7fa3112 --- /dev/null +++ b/src/app/debug/pages/notifications/notifications.component.ts @@ -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"); + } +} diff --git a/src/app/pages/auth/login/login.component.html b/src/app/pages/auth/login/login.component.html index cd46989..b503425 100644 --- a/src/app/pages/auth/login/login.component.html +++ b/src/app/pages/auth/login/login.component.html @@ -2,7 +2,7 @@ - +