diff --git a/angular.json b/angular.json
index 103db74..fde59d5 100644
--- a/angular.json
+++ b/angular.json
@@ -8,7 +8,11 @@
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
- "schematics": {},
+ "schematics": {
+ "@schematics/angular:component": {
+ "styleext": "scss"
+ }
+ },
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
@@ -119,4 +123,4 @@
}
},
"defaultProject": "openlp-remote"
-}
\ No newline at end of file
+}
diff --git a/package.json b/package.json
index b730a36..e9cfb6d 100644
--- a/package.json
+++ b/package.json
@@ -12,11 +12,13 @@
"private": true,
"dependencies": {
"@angular/animations": "^6.0.0",
+ "@angular/cdk": "^6.4.2",
"@angular/common": "^6.0.0",
"@angular/compiler": "^6.0.0",
"@angular/core": "^6.0.0",
"@angular/forms": "^6.0.0",
"@angular/http": "^6.0.0",
+ "@angular/material": "^6.4.2",
"@angular/platform-browser": "^6.0.0",
"@angular/platform-browser-dynamic": "^6.0.0",
"@angular/router": "^6.0.0",
@@ -25,10 +27,9 @@
"zone.js": "^0.8.26"
},
"devDependencies": {
- "@angular/compiler-cli": "^6.0.0",
"@angular-devkit/build-angular": "~0.6.0",
- "typescript": "~2.7.2",
"@angular/cli": "~6.0.0",
+ "@angular/compiler-cli": "^6.0.0",
"@angular/language-service": "^6.0.0",
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
@@ -43,6 +44,7 @@
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.3.0",
"ts-node": "~5.0.1",
- "tslint": "~5.9.1"
+ "tslint": "~5.9.1",
+ "typescript": "~2.7.2"
}
-}
\ No newline at end of file
+}
diff --git a/src/app/alert.component.ts b/src/app/alert.component.ts
new file mode 100644
index 0000000..2e0e684
--- /dev/null
+++ b/src/app/alert.component.ts
@@ -0,0 +1,30 @@
+import { Component } from '@angular/core';
+
+
+import { OpenLPService } from './openlp.service';
+
+@Component({
+selector: 'openlp-remote-alert',
+template: `
+
Send an Alert
+
+
+
+
+
+`,
+providers: [OpenLPService]
+})
+
+export class OpenLPAlertComponent {
+
+ public alert: string;
+
+ constructor(private openlpService: OpenLPService) { }
+
+ onSubmit() {
+ console.log('submitted: ', this.alert);
+ this.openlpService.showAlert(this.alert);
+ this.alert = '';
+ }
+}
diff --git a/src/app/app.component.css b/src/app/app.component.css
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/app.component.html b/src/app/app.component.html
index fa2706a..b9cddfc 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,20 +1,49 @@
-
-
-
- Welcome to {{ title }}!
-
-
+
+
+
+ Service
+ Slides
+ Alerts
+ Search
+
+
+
+
+
+
+ OpenLP Remote
+
+
+
+
+
+
-Here are some links to help you start:
-
-
+
diff --git a/src/app/app.component.scss b/src/app/app.component.scss
new file mode 100644
index 0000000..5df9b8e
--- /dev/null
+++ b/src/app/app.component.scss
@@ -0,0 +1,34 @@
+mat-sidenav {
+ background: white;
+}
+.all-wrap {
+ min-height: 100vh;
+ }
+
+.page-wrap {
+display: flex;
+flex-direction: column;
+min-height: 100vh;
+}
+
+.content {
+flex: 1;
+}
+
+.footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+}
+
+/*
+* Make the Component injected by Router Outlet full height:
+*/
+main {
+ display: flex;
+ flex-direction: column;
+ > *:not(router-outlet) {
+ flex: 1;
+ display: block;
+ }
+}
\ No newline at end of file
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 7b0f672..8acfef8 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,55 @@
import { Component } from '@angular/core';
+import { State } from './state';
+import { OpenLPService } from './openlp.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
+ styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
+
+ state: State = new State();
+
+ constructor(private openlpService: OpenLPService) {
+ openlpService.stateChanged$.subscribe(item => this.state = item);
+ openlpService.getServiceItems().subscribe(result => {
+ console.log(result);
+ });
+ }
+ /*
+ nextItem() {
+ this.openlpService.nextItem();
+ }
+
+ previousItem() {
+ this.openlpService.previousItem();
+ }
+
+ nextSlide() {
+ this.openlpService.nextSlide();
+ }
+
+ previousSlide() {
+ this.openlpService.previousSlide();
+ }
+
+ blankDisplay() {
+ this.openlpService.blankDisplay();
+ }
+
+ themeDisplay() {
+ this.openlpService.themeDisplay();
+ }
+
+ desktopDisplay() {
+ this.openlpService.desktopDisplay();
+ }
+
+ showDisplay() {
+ this.openlpService.showDisplay();
+ }
+ */
+
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f657163..524e318 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,16 +1,53 @@
import { BrowserModule } from '@angular/platform-browser';
+import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+
import { NgModule } from '@angular/core';
+import {MatListModule} from '@angular/material/list';
+import {MatSidenavModule} from '@angular/material/sidenav';
+import {MatIconModule} from '@angular/material/icon';
+import {MatToolbarModule} from '@angular/material/toolbar';
+import {MatGridListModule} from '@angular/material/grid-list';
+import {MatFormFieldModule} from '@angular/material/form-field';
+import {MatSelectModule} from '@angular/material/select';
+import {MatButtonModule} from '@angular/material/button';
+
import { AppComponent } from './app.component';
+import { OpenLPService } from './openlp.service';
+import { HttpClientModule } from '@angular/common/http';
+import { AppRoutingModule } from './app.routing';
+import { OpenLPServiceComponent } from './service.component';
+import { OpenLPAlertComponent } from './alert.component';
+import { OpenLPSearchComponent } from './search.component';
+import { OpenLPSlidesComponent } from './slides.component';
+import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
- AppComponent
+ AppComponent,
+ OpenLPServiceComponent,
+ OpenLPAlertComponent,
+ OpenLPSearchComponent,
+ OpenLPSlidesComponent
],
imports: [
- BrowserModule
+ BrowserModule,
+ BrowserAnimationsModule,
+ HttpClientModule,
+ AppRoutingModule,
+ MatListModule,
+ MatSidenavModule,
+ MatIconModule,
+ MatToolbarModule,
+ MatGridListModule,
+ FormsModule,
+ MatFormFieldModule,
+ MatSelectModule,
+ MatButtonModule
+ ],
+ providers: [
+ OpenLPService
],
- providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts
new file mode 100644
index 0000000..4a714d6
--- /dev/null
+++ b/src/app/app.routing.ts
@@ -0,0 +1,38 @@
+import { ModuleWithProviders, NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { AppComponent } from './app.component';
+import { OpenLPSearchComponent } from './search.component';
+import { OpenLPAlertComponent } from './alert.component';
+import { OpenLPSlidesComponent } from './slides.component';
+import { OpenLPServiceComponent } from './service.component';
+
+const routes: Routes = [
+{
+path: '',
+redirectTo: '/service',
+pathMatch: 'full'
+},
+{
+path: 'service',
+component: OpenLPServiceComponent
+},
+{
+path: 'slides',
+component: OpenLPSlidesComponent
+},
+// {
+// path: 'alerts',
+// component: OpenLPAlertComponent
+// },
+// {
+// path: 'search',
+// component: OpenLPSearchComponent
+// }
+];
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule]
+})
+
+export class AppRoutingModule {}
\ No newline at end of file
diff --git a/src/app/openlp.service.ts b/src/app/openlp.service.ts
new file mode 100644
index 0000000..c0986af
--- /dev/null
+++ b/src/app/openlp.service.ts
@@ -0,0 +1,221 @@
+import { Injectable, EventEmitter } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { URLSearchParams, Http } from '@angular/http';
+
+import { State } from './state';
+import { Slide } from './slide';
+import { ServiceItem } from './service_item';
+import { Observable } from 'rxjs';
+import { map, take } from 'rxjs/operators';
+import { SlideOuterResponse } from './responses';
+
+let deserialize = (json, cls) => {
+ var inst = new cls();
+ for(var p in json) {
+ if(!json.hasOwnProperty(p)) {
+ continue;
+ }
+ inst[p] = json[p];
+ }
+ return inst;
+ }
+
+let buildTextParams = id => {
+ let params: URLSearchParams = new URLSearchParams();
+ params.set('data', '{"request": {"text": "' + id + '"}}');
+ return {search: params}
+}
+
+let buildNumberParams = id => {
+ let params: URLSearchParams = new URLSearchParams();
+ params.set('data', '{"request": {"id": ' + id + '}}');
+ return {search: params}
+}
+
+@Injectable()
+export class OpenLPService {
+ private apiURL: string = 'http://localhost:4316';
+
+ public stateChanged$: EventEmitter
;
+
+ constructor(private http: HttpClient) {
+ this.stateChanged$ = new EventEmitter();
+ let state:State = null;
+ let ws:WebSocket = new WebSocket('ws://localhost:4317/poll')
+ ws.onmessage = (event) => {
+ let reader = new FileReader()
+ reader.onload = () => {
+ state = deserialize(JSON.parse(reader.result).results, State);
+ this.stateChanged$.emit(state);
+ }
+ reader.readAsText(event.data);
+ }
+ }
+
+ getItemSlides(): Observable {
+ return this.http.get('http://localhost:4316/controller/live/text')
+ .pipe(
+ take(1),
+ map(result => result.results.slides));
+ }
+
+ // getItemSlides() {
+ // return this.http.get('http://localhost:4316/api/controller/live/text')
+ // .toPromise()
+ // .then(response => {
+ // let slides:Slide[] = [];
+ // response.json().results.slides.forEach(item => {
+ // let slide = deserialize(item, Slide);
+ // slide.lines = slide.text.split('\n');
+ // slides.push(slide);
+ // });
+ // return slides;
+ // })
+ // .catch(this.handleError);
+ // }
+
+ getServiceItems(): Observable {
+ return this.http.get('http://localhost:4316/service/list');
+ }
+
+
+ // getServiceItems() {
+ // return this.http.get('http://localhost:4316/api/service/list')
+ // .toPromise()
+ // .then(response => {
+ // let serviceItems:ServiceItem[] = [];
+ // response.json().results.items.forEach(item => serviceItems.push(deserialize(item, ServiceItem)));
+ // return serviceItems;
+ // })
+ // .catch(this.handleError);
+ // }
+
+ sendItemLive(plugin, id) {}
+ showAlert(text) {}
+ search(plugin, text) {}
+ addItemToService(plugin, id) {}
+
+ getSearchablePlugins() {
+ return this.http.get(`${this.apiURL}/plugin/search`);
+ }
+
+ // getSearchablePlugins() {
+ // return this.http.get('http://localhost:4316/plugin/search')
+ // .toPromise()
+ // .then(response => response.json().results.items)
+ // .catch(this.handleError);
+ // }
+
+ setServiceItem(id:number) {
+ }
+
+
+ // setServiceItem(id:number) {
+ // this.http.get('http://localhost:4316/service/set', buildNumberParams(id))
+ // .toPromise()
+ // .then(response => console.log(response.json().results))
+ // .catch(this.dropError);
+ // }
+
+ /*
+ setSlide(id) {
+ this.http.get('http://localhost:4316/controller/live/set', buildNumberParams(id))
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ nextItem() {
+ this.http.get('http://localhost:4316/service/next')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ previousItem() {
+ this.http.get('http://localhost:4316/service/previous')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ nextSlide() {
+ this.http.get('http://localhost:4316/controller/live/next')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ previousSlide() {
+ this.http.get('http://localhost:4316/controller/live/previous')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ blankDisplay() {
+ this.http.get('http://localhost:4316/display/blank')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ themeDisplay() {
+ this.http.get('http://localhost:4316/display/theme')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ desktopDisplay() {
+ this.http.get('http://localhost:4316/display/desktop')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ showDisplay() {
+ this.http.get('http://localhost:4316/display/show')
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ showAlert(text) {
+ this.http.get('http://localhost:4316/alert', buildTextParams(text))
+ .toPromise()
+ .then(response => console.log(response.json().results))
+ .catch(this.dropError);
+ }
+
+ search(plugin, text) {
+ return this.http.get('http://localhost:4316/' + plugin + '/search', buildTextParams(text))
+ .toPromise()
+ .then(response => response.json().results.items)
+ .catch(this.handleError);
+ }
+
+ sendItemLive(plugin, id) {
+ this.http.get('http://localhost:4316/' + plugin + '/live', buildNumberParams(id))
+ .toPromise()
+ .then(response => console.log(response))
+ .catch(this.dropError);
+ }
+
+ addItemToService(plugin, id) {
+ this.http.get('http://localhost:4316/' + plugin + '/add', buildNumberParams(id))
+ .toPromise()
+ .then(response => console.log(response))
+ .catch(this.dropError);
+ }
+
+ private dropError(error: any) {
+ console.error('An error occurred', error);
+ }
+
+ private handleError(error: any) {
+ console.error('An error occurred', error);
+ return Promise.reject(error.message || error);
+ }
+ */
+}
diff --git a/src/app/responses.ts b/src/app/responses.ts
new file mode 100644
index 0000000..582010e
--- /dev/null
+++ b/src/app/responses.ts
@@ -0,0 +1,10 @@
+import { Slide } from "./slide";
+
+interface SlideResponse {
+ item: string;
+ slides: Slide[];
+}
+
+export interface SlideOuterResponse {
+ results: SlideResponse;
+}
\ No newline at end of file
diff --git a/src/app/search.component.ts b/src/app/search.component.ts
new file mode 100644
index 0000000..c7049c0
--- /dev/null
+++ b/src/app/search.component.ts
@@ -0,0 +1,76 @@
+import { Component, OnInit } from '@angular/core';
+import { OpenLPService } from './openlp.service';
+
+@Component({
+selector: 'openlp-remote-search',
+template: `
+Search
+
+
+
Search Results:
+
+
+ {{item[1]}} |
+ |
+ |
+
+
+
+`,
+providers: [OpenLPService]
+})
+
+
+export class OpenLPSearchComponent implements OnInit {
+
+ public searchPlugins: OpenLPPlugin[] = null;
+ public searchText = null;
+ public searchResults = null;
+ public selectedPlugin: string;
+ public currentPlugin: string;
+
+ constructor(private openlpService: OpenLPService) {}
+
+ onSubmit() {
+ this.currentPlugin = this.selectedPlugin;
+ // this.openlpService.search(this.currentPlugin, this.searchText).then(items => this.searchResults = items);
+ }
+
+ sendLive(id) {
+ this.openlpService.sendItemLive(this.currentPlugin, id);
+ }
+
+ addToService(id) {
+ this.openlpService.addItemToService(this.currentPlugin, id);
+ }
+
+ ngOnInit() {
+ this.getSearchablePlugins();
+ }
+
+ getSearchablePlugins() {
+ // this.openlpService.getSearchablePlugins().then(items => {
+ // this.searchPlugins = [];
+ // for (var i = items.length - 1; i >= 0; i--) {
+ // this.searchPlugins.push({id: items[i][0], name: items[i][1]})
+ // }
+ // });
+ }
+}
+
+interface OpenLPPlugin {
+ id: string;
+ name: string;
+}
diff --git a/src/app/service.component.ts b/src/app/service.component.ts
new file mode 100644
index 0000000..dce2f68
--- /dev/null
+++ b/src/app/service.component.ts
@@ -0,0 +1,40 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router'
+
+import { OpenLPService } from './openlp.service';
+
+@Component({
+selector: 'openlp-remote-service',
+template: `
+Service items:
+
+`,
+providers: [OpenLPService]
+})
+
+export class OpenLPServiceComponent implements OnInit {
+ items = null;
+ ngOnInit() {
+ this.getServiceItems();
+ }
+
+ onItemSelected(item) {
+ this.openlpService.setServiceItem(item);
+ this.router.navigate(['slides']);
+ }
+
+ getServiceItems() {
+ // this.openlpService.getServiceItems().then(items => this.items = items);
+ }
+
+ constructor(private openlpService: OpenLPService, private router: Router) {
+ openlpService.stateChanged$.subscribe(item => this.getServiceItems());
+ }
+
+}
diff --git a/src/app/service_item.ts b/src/app/service_item.ts
new file mode 100644
index 0000000..b3ea666
--- /dev/null
+++ b/src/app/service_item.ts
@@ -0,0 +1,7 @@
+export class ServiceItem {
+ id: string;
+ notes: string;
+ plugin: string;
+ selected: boolean;
+ title: string;
+}
diff --git a/src/app/slide.ts b/src/app/slide.ts
new file mode 100644
index 0000000..25abe9f
--- /dev/null
+++ b/src/app/slide.ts
@@ -0,0 +1,7 @@
+export class Slide {
+ selected: boolean;
+ html: string;
+ tag: string;
+ text: string;
+ lines: string[];
+}
\ No newline at end of file
diff --git a/src/app/slides.component.ts b/src/app/slides.component.ts
new file mode 100644
index 0000000..02e311c
--- /dev/null
+++ b/src/app/slides.component.ts
@@ -0,0 +1,41 @@
+import { Component, OnInit } from '@angular/core';
+
+
+import { OpenLPService } from './openlp.service';
+
+@Component({
+selector: 'openlp-remote-slides',
+template: `
+Slides:
+
+
+
+ {{ slide.tag }}
+
+ {{line}}
+
+
+
+
+`,
+providers: [OpenLPService]
+})
+
+export class OpenLPSlidesComponent implements OnInit {
+ slides = null;
+ ngOnInit() {
+ this.getSlides();
+ }
+
+ onSlideSelected(item) {
+ // this.openlpService.setSlide(item);
+ }
+
+ getSlides() {
+ // this.openlpService.getItemSlides().then(slides=> {this.slides = slides;console.log(slides);});
+ }
+
+ constructor(private openlpService: OpenLPService) {
+ openlpService.stateChanged$.subscribe(item => this.getSlides());
+ }
+}
diff --git a/src/app/state.ts b/src/app/state.ts
new file mode 100644
index 0000000..2251b30
--- /dev/null
+++ b/src/app/state.ts
@@ -0,0 +1,12 @@
+export class State {
+ isAuthorized: boolean;
+ version: number;
+ slide: number;
+ display: boolean;
+ isSecure: boolean;
+ blank: boolean;
+ twelve: boolean;
+ theme: boolean;
+
+ live = () => {return !(this.blank || this.display || this.theme);}
+}
\ No newline at end of file
diff --git a/src/assets/images/loading.png b/src/assets/images/loading.png
new file mode 100644
index 0000000..0adfeea
Binary files /dev/null and b/src/assets/images/loading.png differ
diff --git a/src/index.html b/src/index.html
index 722017b..4a2d2fa 100644
--- a/src/index.html
+++ b/src/index.html
@@ -7,8 +7,16 @@
+
-
+
+
+
+
+
Loading...
+
+
+