mirror of
https://gitlab.com/openlp/web-remote.git
synced 2024-12-22 11:32:47 +00:00
Merge branch 'update-ui' into 'master'
Update the UI See merge request openlp/web-remote!4
This commit is contained in:
commit
1e4be02530
@ -1,4 +1,10 @@
|
||||
<mat-sidenav-container class="all-wrap" fullscreen>
|
||||
<mat-toolbar color="primary">
|
||||
<mat-toolbar-row>
|
||||
<button mat-icon-button (click)="menu.toggle()"><mat-icon>menu</mat-icon></button>
|
||||
<span class="page-title">{{pageTitle}}</span>
|
||||
</mat-toolbar-row>
|
||||
</mat-toolbar>
|
||||
<mat-sidenav-container>
|
||||
<mat-sidenav #menu mode="over">
|
||||
<mat-nav-list>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/service">Service</a>
|
||||
@ -13,19 +19,11 @@
|
||||
<mat-slide-toggle color="primary" [checked]="fastSwitching" (change)="sliderChanged($event)">Fast switching</mat-slide-toggle>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
<div class="page-wrap">
|
||||
<header>
|
||||
<mat-toolbar style="background-color: #64aef3;">
|
||||
<button mat-icon-button (click)="menu.toggle()"><mat-icon>menu</mat-icon></button>
|
||||
<span>OpenLP Remote</span>
|
||||
<span class="filler"></span>
|
||||
<button *ngIf="showLogin" mat-button (click)="login()">Login</button>
|
||||
</mat-toolbar>
|
||||
</header>
|
||||
<main class="content">
|
||||
<mat-sidenav-content>
|
||||
<main class="content">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
<footer>
|
||||
</main>
|
||||
<footer>
|
||||
<mat-toolbar class="footer">
|
||||
<button mat-icon-button (click)="previousItem()" matTooltip="Previous item">
|
||||
<mat-icon>first_page</mat-icon>
|
||||
@ -59,5 +57,5 @@
|
||||
<button mat-icon-button routerLink="/search"><mat-icon>search</mat-icon></button>
|
||||
</mat-toolbar>
|
||||
</footer>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
|
@ -1,26 +1,15 @@
|
||||
mat-sidenav {
|
||||
background: white;
|
||||
}
|
||||
.all-wrap {
|
||||
|
||||
mat-sidenav-container {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.page-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.filler {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
mat-slide-toggle {
|
||||
margin-top: 0.8rem;
|
||||
margin-left: 1rem;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.fast-access {
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatSlideToggleChange, MatDialog } from '@angular/material';
|
||||
|
||||
import { State } from './responses';
|
||||
import { OpenLPService } from './openlp.service';
|
||||
import { MatSlideToggleChange, MatDialog } from '@angular/material';
|
||||
import { PageTitleService } from './page-title.service';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
|
||||
@Component({
|
||||
@ -13,8 +15,11 @@ export class AppComponent implements OnInit {
|
||||
fastSwitching = false;
|
||||
state = new State();
|
||||
showLogin = false;
|
||||
pageTitle = 'OpenLP Remote';
|
||||
|
||||
constructor(private openlpService: OpenLPService, private dialog: MatDialog) {
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService,
|
||||
private dialog: MatDialog) {
|
||||
pageTitleService.pageTitleChanged$.subscribe(pageTitle => this.pageTitle = pageTitle);
|
||||
openlpService.stateChanged$.subscribe(item => this.state = item);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@ -18,6 +18,7 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { PageTitleService } from './page-title.service';
|
||||
import { OpenLPService } from './openlp.service';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppRoutingModule } from './app.routing';
|
||||
@ -68,7 +69,9 @@ import { LoginComponent } from './components/login/login.component';
|
||||
MatSnackBarModule
|
||||
],
|
||||
providers: [
|
||||
OpenLPService
|
||||
PageTitleService,
|
||||
OpenLPService,
|
||||
Title
|
||||
],
|
||||
entryComponents: [
|
||||
LoginComponent
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
|
||||
import { OpenLPService } from '../../openlp.service';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
|
||||
import { PageTitleService } from '../../page-title.service';
|
||||
import { OpenLPService } from '../../openlp.service';
|
||||
|
||||
@Component({
|
||||
selector: 'openlp-alert',
|
||||
templateUrl: './alert.component.html',
|
||||
@ -15,7 +15,10 @@ export class AlertComponent {
|
||||
|
||||
public alert: string;
|
||||
|
||||
constructor(private openlpService: OpenLPService, private snackBar: MatSnackBar) { }
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService,
|
||||
private snackBar: MatSnackBar) {
|
||||
pageTitleService.changePageTitle('Alerts');
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.openlpService.showAlert(this.alert).subscribe(res => this.snackBar.open('Alert submitted', '', {duration: 2000}));
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { OpenLPService } from '../../openlp.service';
|
||||
import { PageTitleService } from '../../page-title.service';
|
||||
import { PluginDescription } from '../../responses';
|
||||
|
||||
@Component({
|
||||
@ -8,17 +10,16 @@ import { PluginDescription } from '../../responses';
|
||||
styleUrls: ['./search.component.scss'],
|
||||
providers: [OpenLPService]
|
||||
})
|
||||
|
||||
|
||||
export class SearchComponent implements OnInit {
|
||||
|
||||
public searchPlugins: PluginDescription[] = [];
|
||||
public searchText = null;
|
||||
public searchResults = null;
|
||||
public selectedPlugin = 'songs';
|
||||
public currentPlugin: string;
|
||||
|
||||
constructor(private openlpService: OpenLPService) {}
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService) {
|
||||
pageTitleService.changePageTitle('Search');
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.currentPlugin = this.selectedPlugin;
|
||||
|
@ -1,9 +1,3 @@
|
||||
<h3>Service items:</h3>
|
||||
<div>
|
||||
<mat-nav-list>
|
||||
<a mat-list-item *ngFor="let item of items;let counter = index;" (click)="onItemSelected(counter)" [class.selected]="item.selected">
|
||||
<mat-icon mat-list-icon>{{ getIcon(item) }}</mat-icon>
|
||||
<p mat-line>{{item.title}}<p>
|
||||
</a>
|
||||
</mat-nav-list>
|
||||
</div>
|
||||
<mat-card *ngFor="let item of items; let counter = index;" (click)="onItemSelected(counter)" [tabindex]="counter" class="service-item">
|
||||
<mat-icon>{{ getIcon(item) }}</mat-icon> {{ item.title }}
|
||||
</mat-card>
|
||||
|
@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { OpenLPService } from '../../openlp.service';
|
||||
import { PageTitleService } from '../../page-title.service';
|
||||
import { ServiceItem } from '../../responses';
|
||||
|
||||
@Component({
|
||||
@ -13,6 +14,7 @@ import { ServiceItem } from '../../responses';
|
||||
|
||||
export class ServiceComponent implements OnInit {
|
||||
items: ServiceItem[] = [];
|
||||
|
||||
ngOnInit() {
|
||||
this.getServiceItems();
|
||||
}
|
||||
@ -26,7 +28,9 @@ export class ServiceComponent implements OnInit {
|
||||
this.openlpService.getServiceItems().subscribe(items => this.items = items);
|
||||
}
|
||||
|
||||
constructor(private openlpService: OpenLPService, private router: Router) {
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService,
|
||||
private router: Router) {
|
||||
pageTitleService.changePageTitle('Service');
|
||||
openlpService.stateChanged$.subscribe(item => this.getServiceItems());
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
<h3>Slides:</h3>
|
||||
<div>
|
||||
<mat-nav-list>
|
||||
<mat-list-item *ngFor="let slide of slides; let counter = index;" (click)="onSlideSelected(counter)" [class.selected]="slide.selected">
|
||||
<span MatListAvatar>{{ slide.tag }}</span>
|
||||
<span MatLine style="margin-left: 2rem;">{{ slide.text }}</span>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</div>
|
||||
<mat-card mat-list-item *ngFor="let slide of slides; let counter = index;" (click)="onSlideSelected(counter)" [class.selected]="slide.selected">
|
||||
<div class="verse-tag">{{ slide.tag }}</div>
|
||||
<div class="verse-text">{{ slide.text }}</div>
|
||||
</mat-card>
|
||||
|
@ -1,3 +1,16 @@
|
||||
mat-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selected {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.verse-tag {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.verse-text {
|
||||
margin-left: 2.5rem;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
|
||||
import { OpenLPService } from '../../openlp.service';
|
||||
import { PageTitleService } from '../../page-title.service';
|
||||
|
||||
@Component({
|
||||
selector: 'openlp-slides',
|
||||
@ -12,6 +12,12 @@ import { OpenLPService } from '../../openlp.service';
|
||||
|
||||
export class SlidesComponent implements OnInit {
|
||||
slides = null;
|
||||
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService) {
|
||||
pageTitleService.changePageTitle('Slides');
|
||||
openlpService.stateChanged$.subscribe(item => this.getSlides());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.getSlides();
|
||||
}
|
||||
@ -23,8 +29,4 @@ export class SlidesComponent implements OnInit {
|
||||
getSlides() {
|
||||
this.openlpService.getItemSlides().subscribe(slides => this.slides = slides);
|
||||
}
|
||||
|
||||
constructor(private openlpService: OpenLPService) {
|
||||
openlpService.stateChanged$.subscribe(item => this.getSlides());
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,20 @@
|
||||
import { Injectable, EventEmitter } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { PluginDescription, State, Slide, ServiceItem, MainView, SystemInformation, Credentials, AuthToken } from './responses';
|
||||
import {
|
||||
PluginDescription,
|
||||
State,
|
||||
Slide,
|
||||
ServiceItem,
|
||||
MainView,
|
||||
SystemInformation,
|
||||
Credentials,
|
||||
AuthToken
|
||||
} from './responses';
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
|
||||
const deserialize = (json, cls) => {
|
||||
const inst = new cls();
|
||||
for (const p in json) {
|
||||
@ -21,12 +30,14 @@ const httpOptions = {
|
||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||
};
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OpenLPService {
|
||||
private apiURL: string;
|
||||
public stateChanged$: EventEmitter<State>;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
const host = window.location.hostname;
|
||||
let port: string;
|
||||
if (environment.production) {
|
||||
port = window.location.port;
|
||||
@ -34,12 +45,11 @@ export class OpenLPService {
|
||||
else {
|
||||
port = '4316';
|
||||
}
|
||||
this.apiURL = `http://localhost:${port}/api/v1`;
|
||||
|
||||
this.apiURL = `http://${host}:${port}/api/v1`;
|
||||
|
||||
this.stateChanged$ = new EventEmitter<State>();
|
||||
this.retrieveSystemInformation().subscribe(info => {
|
||||
const ws = new WebSocket(`ws://localhost:${info.websocket_port}/state`);
|
||||
const ws = new WebSocket(`ws://${host}:${info.websocket_port}/state`);
|
||||
ws.onmessage = (event) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
|
16
src/app/page-title.service.ts
Normal file
16
src/app/page-title.service.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class PageTitleService {
|
||||
private pageTitleSource = new Subject<string>();
|
||||
public pageTitleChanged$ = this.pageTitleSource.asObservable();
|
||||
|
||||
constructor(private titleService: Title) {}
|
||||
|
||||
changePageTitle(pageTitle: string) {
|
||||
this.pageTitleSource.next(pageTitle);
|
||||
this.titleService.setTitle(pageTitle + ' | OpenLP Remote');
|
||||
}
|
||||
}
|
@ -2,12 +2,11 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>OpenLP • Remote</title>
|
||||
<title>OpenLP Remote</title>
|
||||
<base href="/">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<app-root>
|
||||
|
@ -1,25 +1,60 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
|
||||
@import '~@angular/material/theming';
|
||||
|
||||
@include mat-core();
|
||||
$primary: mat-palette($mat-indigo);
|
||||
$accent: mat-palette($mat-light-blue, A200, A100, A400);
|
||||
$theme: mat-light-theme($primary, $accent);
|
||||
@include angular-material-theme($theme);
|
||||
|
||||
* {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 500 20px/32px Roboto, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
mat-sidenav-layout {
|
||||
background: rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
mat-sidenav {
|
||||
width: 200px;
|
||||
width: 12rem;
|
||||
}
|
||||
|
||||
mat-card {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
mat-card.service-item,
|
||||
mat-card.slide {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.displayButton .active {
|
||||
background: 'teal';
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 20px;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.chordline {
|
||||
|
@ -72,7 +72,6 @@
|
||||
"no-trailing-whitespace": true,
|
||||
"no-unnecessary-initializer": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"object-literal-sort-keys": false,
|
||||
"one-line": [
|
||||
@ -115,12 +114,12 @@
|
||||
"check-type"
|
||||
],
|
||||
"no-output-on-prefix": true,
|
||||
"use-input-property-decorator": true,
|
||||
"use-output-property-decorator": true,
|
||||
"use-host-property-decorator": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-output-rename": true,
|
||||
"use-life-cycle-interface": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"component-class-suffix": true,
|
||||
"directive-class-suffix": true
|
||||
|
Loading…
Reference in New Issue
Block a user