Various small adjustments

This commit is contained in:
Mateus Meyer Jiacomelli 2023-03-01 03:19:16 +00:00
parent 6b75b00319
commit 1ac5016974
13 changed files with 152 additions and 29 deletions

7
.browserslistrc Normal file
View File

@ -0,0 +1,7 @@
last 10 Chrome version
last 10 Firefox version
last 10 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
not IE >= 0 # IE is dead

View File

@ -19,17 +19,29 @@
<mat-sidenav-container> <mat-sidenav-container>
<mat-sidenav #menu mode="over"> <mat-sidenav #menu mode="over">
<mat-nav-list> <mat-nav-list>
<a mat-list-item (click)="menu.close()" routerLink="/service"><mat-icon>list</mat-icon> Service</a> <a mat-list-item (click)="menu.close()" routerLink="/service" routerLinkActive #serviceRoute="routerLinkActive" [activated]="serviceRoute.isActive">
<a mat-list-item (click)="menu.close()" routerLink="/slides"><mat-icon>collections</mat-icon> Slides</a> <mat-icon>list</mat-icon> Service
<a mat-list-item (click)="menu.close()" routerLink="/alerts"><mat-icon>error</mat-icon> Alerts</a> </a>
<a mat-list-item (click)="menu.close()" routerLink="/search"><mat-icon>search</mat-icon> Search</a> <a mat-list-item (click)="menu.close()" routerLink="/slides" routerLinkActive #slidesRoute="routerLinkActive" [activated]="slidesRoute.isActive">
<a mat-list-item (click)="menu.close()" routerLink="/themes"><mat-icon>image</mat-icon> Themes</a> <mat-icon>collections</mat-icon> Slides
</a>
<a mat-list-item (click)="menu.close()" routerLink="/alerts" routerLinkActive #alertsRoute="routerLinkActive" [activated]="alertsRoute.isActive">
<mat-icon>error</mat-icon> Alerts
</a>
<a mat-list-item (click)="menu.close()" routerLink="/search" routerLinkActive #searchRoute="routerLinkActive" [activated]="searchRoute.isActive">
<mat-icon>search</mat-icon> Search
</a>
<a mat-list-item (click)="menu.close()" routerLink="/themes" routerLinkActive #themesRoute="routerLinkActive" [activated]="themesRoute.isActive">
<mat-icon>image</mat-icon> Themes
</a>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<a mat-list-item (click)="menu.close()" routerLink="/main">Main View</a> <a mat-list-item (click)="menu.close()" routerLink="/main">Main View</a>
<a mat-list-item (click)="menu.close()" routerLink="/stage">Stage View</a> <a mat-list-item (click)="menu.close()" routerLink="/stage">Stage View</a>
<a mat-list-item (click)="menu.close()" routerLink="/chords">Chord View</a> <a mat-list-item (click)="menu.close()" routerLink="/chords">Chord View</a>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<a mat-list-item (click)="menu.close()" routerLink="/settings"><mat-icon>settings</mat-icon> Settings</a> <a mat-list-item (click)="menu.close()" routerLink="/settings" routerLinkActive #settingsRoute="routerLinkActive" [activated]="settingsRoute.isActive">
<mat-icon>settings</mat-icon> Settings
</a>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content> <mat-sidenav-content>

View File

@ -17,7 +17,7 @@
<app-stage-view-item [slide]="currentSlides[activeSlide]" [active]="true"></app-stage-view-item> <app-stage-view-item [slide]="currentSlides[activeSlide]" [active]="true"></app-stage-view-item>
</ng-template> </ng-template>
<div class="nextSlides"> <div class="nextSlides">
<ng-container *ngFor="let slide of nextSlides"> <ng-container *ngFor="let slide of nextSlides; trackBy: trackByIndex">
<app-chord-view-item [slide]="slide" *ngIf="slide?.chords; else elseNextSlideNoChords"></app-chord-view-item> <app-chord-view-item [slide]="slide" *ngIf="slide?.chords; else elseNextSlideNoChords"></app-chord-view-item>
<ng-template #elseNextSlideNoChords> <ng-template #elseNextSlideNoChords>
<app-stage-view-item [slide]="slide"></app-stage-view-item> <app-stage-view-item [slide]="slide"></app-stage-view-item>

View File

@ -0,0 +1,29 @@
.no-items {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
&-title {
display: flex;
align-items: center;
color: gray;
.icon {
margin-right: 0.25em;
}
}
&-actions {
display: flex;
justify-content: center;
gap: 1em;
margin-top: 0.25em;
button, a {
text-decoration: none;
font-size: 0.813rem;
height: 28px;
}
}
}

View File

@ -138,6 +138,7 @@
.back-button { .back-button {
background: #fff; background: #fff;
color: #000;
} }
@media screen and (max-width: ($mobile-breakpoint - 0.125px)){ @media screen and (max-width: ($mobile-breakpoint - 0.125px)){

View File

@ -1,7 +1,23 @@
<openlp-service-item <ng-container *ngIf="items?.length; else noServiceItems">
*ngFor="let item of items" <openlp-service-item
[item]="item" *ngFor="let item of items"
[selected]="item.selected" [item]="item"
(selectItem)="onItemSelected($event)" [selected]="item.selected"
[tabindex]="item.id" (selectItem)="onItemSelected($event)"
></openlp-service-item> [tabindex]="item.id"
></openlp-service-item>
</ng-container>
<ng-template #noServiceItems>
<div class="no-items" *ngIf="!loading">
<div class="no-items-title">
<span class="material-icons icon">info</span>
No service items.
</div>
<div class="no-items-actions">
<a routerLink="/search" mat-stroked-button color="primary" size="small">
<span class="material-icons">add</span>
Add Item
</a>
</div>
</div>
</ng-template>

View File

@ -7,12 +7,13 @@ import { ServiceItem } from '../../../responses';
@Component({ @Component({
selector: 'openlp-service-list', selector: 'openlp-service-list',
templateUrl: './service-list.component.html', templateUrl: './service-list.component.html',
styleUrls: ['./service-list.component.scss'], styleUrls: ['./service-list.component.scss', '../../no-items.scss'],
}) })
export class ServiceListComponent implements OnInit, OnDestroy { export class ServiceListComponent implements OnInit, OnDestroy {
items: ServiceItem[] = []; items: ServiceItem[] = [];
_subscription: Subscription; _subscription: Subscription;
loading = false;
@Output() itemSelected = new EventEmitter<ServiceItem>(); @Output() itemSelected = new EventEmitter<ServiceItem>();
@ -25,7 +26,11 @@ export class ServiceListComponent implements OnInit, OnDestroy {
} }
fetchServiceItems() { fetchServiceItems() {
this.openlpService.getServiceItems().subscribe(items => this.items = items); this.loading = true;
this.openlpService.getServiceItems().subscribe(items => {
this.items = items;
this.loading = false;
});
} }
constructor(private openlpService: OpenLPService) { constructor(private openlpService: OpenLPService) {

View File

@ -1 +1,23 @@
<openlp-slide-item *ngFor="let slide of slides; let index = index" [slide]="slide" [tabindex]="counter" [selected]="slide.selected" (selectSlide)="onSlideSelected($event, index)"></openlp-slide-item> <ng-container *ngIf="slides?.length; else noSlideItems">
<openlp-slide-item
*ngFor="let slide of slides; let index = index"
[slide]="slide"
[tabindex]="counter"
[selected]="slide.selected"
(selectSlide)="onSlideSelected($event, index)"
></openlp-slide-item>
</ng-container>
<ng-template #noSlideItems>
<div class="no-items" *ngIf="!loading">
<div class="no-items-title">
<span class="material-icons icon">info</span>
No slide items.
</div>
<div class="no-items-actions">
<a routerLink="/search" mat-stroked-button color="primary" size="small">
<span class="material-icons">add</span>
Add Item to Service
</a>
</div>
</div>
</ng-template>

View File

@ -7,13 +7,14 @@ import { OpenLPService } from '../../../openlp.service';
@Component({ @Component({
selector: 'openlp-slide-list', selector: 'openlp-slide-list',
templateUrl: './slide-list.component.html', templateUrl: './slide-list.component.html',
styleUrls: ['./slide-list.component.scss'], styleUrls: ['./slide-list.component.scss', '../../no-items.scss'],
}) })
export class SlideListComponent implements OnInit, OnDestroy { export class SlideListComponent implements OnInit, OnDestroy {
slides: Slide[] = null; slides: Slide[] = null;
@Output() slideSelected = new EventEmitter<SlideListItem>(); @Output() slideSelected = new EventEmitter<SlideListItem>();
_subscription: Subscription; _subscription: Subscription;
loading = false;
constructor(private openlpService: OpenLPService) { constructor(private openlpService: OpenLPService) {
this._subscription = openlpService.stateChanged$.subscribe(item => this.fetchSlides()); this._subscription = openlpService.stateChanged$.subscribe(item => this.fetchSlides());
@ -32,7 +33,9 @@ export class SlideListComponent implements OnInit, OnDestroy {
} }
fetchSlides() { fetchSlides() {
this.loading = true;
this.openlpService.getServiceItem().subscribe(serviceItem => { this.openlpService.getServiceItem().subscribe(serviceItem => {
this.loading = false;
if (serviceItem instanceof Array) { if (serviceItem instanceof Array) {
this.slides = serviceItem; this.slides = serviceItem;
} }

View File

@ -10,7 +10,7 @@
<div class="container"> <div class="container">
<app-stage-view-item [slide]="currentSlides[activeSlide]" [active]="true"></app-stage-view-item> <app-stage-view-item [slide]="currentSlides[activeSlide]" [active]="true"></app-stage-view-item>
<div class="nextSlides"> <div class="nextSlides">
<app-stage-view-item [slide]="slide" *ngFor="let slide of nextSlides"></app-stage-view-item> <app-stage-view-item [slide]="slide" *ngFor="let slide of nextSlides; trackBy: trackByIndex"></app-stage-view-item>
</div> </div>
</div> </div>
</div> </div>

View File

@ -41,6 +41,8 @@ export class StageViewComponent implements OnInit, OnDestroy {
setInterval(() => this.time = new Date(), 1000); setInterval(() => this.time = new Date(), 1000);
} }
nextSlides: Slide[] = [];
ngOnInit() { ngOnInit() {
this.updateCurrentSlides(null, null); this.updateCurrentSlides(null, null);
this.openlpService.stateChanged$.subscribe(item => this.updateCurrentSlides(item.item, item.slide)); this.openlpService.stateChanged$.subscribe(item => this.updateCurrentSlides(item.item, item.slide));
@ -74,16 +76,13 @@ export class StageViewComponent implements OnInit, OnDestroy {
}); });
} }
get nextSlides(): Slide[] {
return this.currentSlides.slice(this.activeSlide + 1);
}
setNewSlides(slides: Slide[], currentSlide: number): void { setNewSlides(slides: Slide[], currentSlide: number): void {
if (slides.length === 0) { if (slides.length === 0) {
return; return;
} }
this.currentSlides = slides; this.currentSlides = slides;
this.activeSlide = slides.findIndex(s => s.selected); this.activeSlide = slides.findIndex(s => s.selected);
this.nextSlides = this.currentSlides.slice(this.activeSlide + 1);
this.updateTags(); this.updateTags();
} }
@ -129,4 +128,8 @@ export class StageViewComponent implements OnInit, OnDestroy {
lastIndex = index; lastIndex = index;
} }
} }
trackByIndex(index: number, el: any) {
return index;
}
} }

View File

@ -1,11 +1,25 @@
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
@use '@angular/material' as mat;
@import '@angular/material/theming'; @import '@angular/material/theming';
@include mat-core(); @include mat.core();
$primary: mat-palette($mat-indigo); $olp-primary: mat.define-palette(mat.$indigo-palette, 500);
$accent: mat-palette($mat-light-blue, A200, A100, A400); $olp-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$theme: mat-light-theme($primary, $accent);
@include angular-material-theme($theme); // The "warn" palette is optional and defaults to red if not specified.
$olp-warn: mat.define-palette(mat.$red-palette);
$olp-theme: mat.define-light-theme((
color: (
primary: $olp-primary,
accent: $olp-accent,
warn: $olp-warn,
),
density: 0,
));
// Including only used components
@include mat.all-component-themes($olp-theme);
* { * {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
@ -111,3 +125,13 @@ footer {
footer { footer {
z-index: 1; z-index: 1;
} }
// This rule is to avoid the left menu scrolling with the page itself.
.mat-drawer.mat-sidenav {
position: fixed;
padding-top: $mat-toolbar-height-desktop;
@media ($mat-xsmall) {
padding-top: $mat-toolbar-height-mobile;
}
}

View File

@ -9,7 +9,8 @@
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"target": "es5", "target": "es2022",
"useDefineForClassFields": false,
"typeRoots": [ "typeRoots": [
"node_modules/@types" "node_modules/@types"
], ],