Updated site to use momentum for contacting, registration, gallery and calendar, as well as some other updates to the site content
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import {AfterViewInit, Component, Input, OnDestroy, OnInit} from '@angular/core';
|
||||
import {AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
|
||||
import {Photo} from '../models/photo';
|
||||
|
||||
@Component({
|
||||
@@ -18,6 +18,7 @@ export class CarouselComponent implements OnDestroy, OnInit, AfterViewInit {
|
||||
@Input() disableAutoplay = false;
|
||||
@Input() index = ~~(Math.random() * this.photos.length);
|
||||
@Input() height = '100%';
|
||||
@Output() indexChange = new EventEmitter<number>();
|
||||
|
||||
ngOnInit() {
|
||||
if(this.disableAutoplay) this.pause = true;
|
||||
@@ -41,11 +42,13 @@ export class CarouselComponent implements OnDestroy, OnInit, AfterViewInit {
|
||||
this.pause = pause;
|
||||
this.index++;
|
||||
if(this.index >= this.photos.length) this.index = 0;
|
||||
this.indexChange.emit(this.index);
|
||||
}
|
||||
|
||||
previous(pause = true) {
|
||||
this.loading = true;
|
||||
this.pause = pause;
|
||||
this.index = this.index > 0 ? this.index - 1 : this.photos.length - 1;
|
||||
this.indexChange.emit(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
<footer>
|
||||
<div class="social text-center py-3" style="background: #990000">
|
||||
<!-- <h2 class="mb-4">Follow us on social media</h2>-->
|
||||
<!-- <div class="d-flex justify-content-around mx-auto transparent-link" style="max-width: 300px">-->
|
||||
<!-- <a href="https://discord.gg/wW458KYR79" target="_blank">-->
|
||||
<!-- <i class="fa-brands fa-discord fa-2xl"></i>-->
|
||||
<!-- </a>-->
|
||||
<!-- <a href="https://facebook.com" target="_blank" aria-label="Facebook">-->
|
||||
<!-- <i class="fa-brands fa-facebook fa-2xl"></i>-->
|
||||
<!-- </a>-->
|
||||
<!-- <a href="https://instagram.com" target="_blank" aria-label="Instagram">-->
|
||||
<!-- <i class="fa-brands fa-instagram fa-2xl"></i>-->
|
||||
<!-- </a>-->
|
||||
<!-- <a href="https://tiktok.com" target="_blank" aria-label="TikTok">-->
|
||||
<!-- <i class="fa-brands fa-tiktok fa-2xl"></i>-->
|
||||
<!-- </a>-->
|
||||
<!-- <a href="https://youtube.com" target="_blank" aria-label="Youtube">-->
|
||||
<!-- <i class="fa-brands fa-youtube fa-2xl"></i>-->
|
||||
<!-- </a>-->
|
||||
<!-- </div>-->
|
||||
<!-- <h3 class="mt-4 mb-0">so we can invade your feed ⚔️</h3>-->
|
||||
<div class="text-center d-flex flex-row justify-content-center align-items-center gap-3">
|
||||
<hr class="flex-grow-1 m-0 opacity-75">
|
||||
<div class="d-flex flex-column align-items-end">
|
||||
<h2 class="mb-0">Ready to Enlist?</h2>
|
||||
<p class="mb-0">Take your place in our ranks...</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<a [routerLink]="['/register']" class="btn btn-light btn-lg">JOIN NOW</a>
|
||||
</div>
|
||||
<hr class="flex-grow-1 m-0 opacity-75">
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-dark text-center text-sm-start">
|
||||
<div class="d-flex flex-column flex-sm-row flex-wrap justify-content-center container p-3 pb-0">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {Component, Inject} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {MomentumService} from '../../services/momentum.service';
|
||||
import {Photo} from '../models/photo';
|
||||
|
||||
export interface ImageViewerOptions {
|
||||
@@ -10,12 +11,13 @@ export interface ImageViewerOptions {
|
||||
@Component({
|
||||
selector: 'xxx-viewer',
|
||||
styles: [`
|
||||
.close {
|
||||
.close, .delete {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 100000;
|
||||
}
|
||||
.close { right: 1rem; }
|
||||
.delete { right: 4rem; }
|
||||
::ng-deep .cdk-overlay-pane {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
@@ -24,18 +26,32 @@ export interface ImageViewerOptions {
|
||||
}
|
||||
`],
|
||||
template: `
|
||||
<button class="close" mat-icon-button aria-label="close dialog" mat-dialog-close>
|
||||
<button class="close" mat-icon-button mat-dialog-close>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<xxx-carousel [photos]="photos" [index]="index" [disableAutoplay]="true"></xxx-carousel>
|
||||
<button *ngIf="momentum.admin | async" class="delete me-3" mat-icon-button (click)="delete()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<xxx-carousel [photos]="photos" [index]="index" [disableAutoplay]="true" (indexChange)="index = $event"></xxx-carousel>
|
||||
`
|
||||
})
|
||||
export class ImageViewerComponent {
|
||||
index!: number;
|
||||
photos!: Photo[];
|
||||
|
||||
constructor(public ref: MatDialogRef<ImageViewerComponent>, @Inject(MAT_DIALOG_DATA) data: ImageViewerOptions) {
|
||||
constructor(
|
||||
public ref: MatDialogRef<ImageViewerComponent>,
|
||||
public momentum: MomentumService,
|
||||
@Inject(MAT_DIALOG_DATA) data: ImageViewerOptions
|
||||
) {
|
||||
this.index = data.index || 0;
|
||||
this.photos = data.photos || [];
|
||||
}
|
||||
|
||||
async delete() {
|
||||
if (!confirm('Delete this photo?')) return;
|
||||
const photo = this.photos[this.index];
|
||||
await this.momentum.api.storage.delete(photo.path);
|
||||
this.ref.close({deleted: photo});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export interface Photo {
|
||||
alt: string;
|
||||
src: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,21 @@
|
||||
<mat-menu #menu="matMenu">
|
||||
<ng-container *ngFor="let section of group.children; let first = first">
|
||||
<mat-divider *ngIf="!first"></mat-divider>
|
||||
<button *ngFor="let item of section" mat-menu-item [routerLink]="item.url" [fragment]="item.fragment">
|
||||
<button *ngFor="let item of section" mat-menu-item (click)="openItem(item)">
|
||||
{{item.label}}
|
||||
</button>
|
||||
</ng-container>
|
||||
<!-- Auth items, Members menu only -->
|
||||
<ng-container *ngIf="group.label === 'Members'">
|
||||
<mat-divider></mat-divider>
|
||||
<ng-container *ngIf="momentum.isLoggedIn | async; else guestItems">
|
||||
<button mat-menu-item (click)="momentum.api.auth.logout()">Logout</button>
|
||||
</ng-container>
|
||||
<ng-template #guestItems>
|
||||
<button mat-menu-item (click)="momentum.api.auth.handleLogin()">Login</button>
|
||||
<button mat-menu-item (click)="openItem({label:'Register', url:'/register'})">Register</button>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
</div>
|
||||
@@ -30,7 +41,7 @@
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let item of links.topLevel" [routerLink]="item.url" [fragment]="item.fragment">
|
||||
<button mat-menu-item *ngFor="let item of links.topLevel" (click)="openItem(item)">>
|
||||
{{item.label}}
|
||||
</button>
|
||||
<ng-container *ngFor="let group of links.other">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {AfterViewInit, Component, EventEmitter, Input, OnDestroy, Output} from '@angular/core';
|
||||
import {ActivatedRoute, NavigationEnd, NavigationStart, Router} from '@angular/router';
|
||||
import {ActivatedRoute, NavigationStart, Router} from '@angular/router';
|
||||
import {combineLatest, filter, Subscription} from 'rxjs';
|
||||
import {NAVIGATION} from '../../misc/navigation';
|
||||
import {BreakpointService} from '../../services/breakpoint.service';
|
||||
import {NAVIGATION, NavigationItem} from '../../misc/navigation';
|
||||
import {MomentumService} from '../../services/momentum.service';
|
||||
|
||||
@Component({
|
||||
selector: 'xxx-navbar',
|
||||
@@ -21,7 +21,7 @@ export class NavbarComponent implements AfterViewInit, OnDestroy {
|
||||
|
||||
@Output() hamburgerClick = new EventEmitter<void>();
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router, public breakpoint: BreakpointService) { }
|
||||
constructor(private route: ActivatedRoute, private router: Router, public momentum: MomentumService) { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.sub = combineLatest([this.router.events.pipe(filter((e: any) => e.navigationTrigger != 'popstate' || e instanceof NavigationStart)), this.route.fragment]).subscribe(([url, frag]) => {
|
||||
@@ -34,6 +34,15 @@ export class NavbarComponent implements AfterViewInit, OnDestroy {
|
||||
if(this.sub) this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
openItem(item: NavigationItem) {
|
||||
// Full url
|
||||
if(item.url.startsWith('http'))
|
||||
location.href = item.url;
|
||||
// Relative
|
||||
else
|
||||
this.router.navigate([item.url], {fragment: item.fragment});
|
||||
}
|
||||
|
||||
scroll(id: string) {
|
||||
const el = document.getElementById(id);
|
||||
if(el) el.scrollIntoView({behavior: 'smooth'});
|
||||
|
||||
16
src/app/components/uploader/uploader.component.html
Normal file
16
src/app/components/uploader/uploader.component.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<h2 mat-dialog-title>Upload Photos</h2>
|
||||
<mat-dialog-content>
|
||||
<p class="text-muted">Select the year these photos were taken then choose your files.</p>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Year</mat-label>
|
||||
<mat-select [(ngModel)]="year">
|
||||
<mat-option *ngFor="let y of years" [value]="y">{{y}}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close>Cancel</button>
|
||||
<button mat-raised-button color="primary" (click)="upload()" [disabled]="uploading">
|
||||
<mat-icon>upload</mat-icon> Choose Files
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
21
src/app/components/uploader/uploader.component.ts
Normal file
21
src/app/components/uploader/uploader.component.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
import {MomentumService} from '../../services/momentum.service';
|
||||
|
||||
@Component({
|
||||
selector: 'xxx-uploader',
|
||||
templateUrl: './uploader.component.html',
|
||||
})
|
||||
export class UploaderComponent {
|
||||
year: number = new Date().getFullYear();
|
||||
years: number[] = Array.from({length: this.year - 2006}, (_, i) => 2007 + i).reverse();
|
||||
uploading = false;
|
||||
|
||||
constructor(private momentum: MomentumService, private ref: MatDialogRef<UploaderComponent>) {}
|
||||
|
||||
async upload() {
|
||||
this.uploading = true;
|
||||
await this.momentum.api.storage.upload(`Photos/Submissions/${this.year}`, undefined, {multiple: true, accept: 'image/*'});
|
||||
this.ref.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user