mirror of
https://gitlab.com/openlp/web-remote.git
synced 2024-12-22 11:32:47 +00:00
Merge branch 'use-translation-for-configured-language' into 'master'
Make use of the configured language in OpenLP in order to use translations in Web Remote See merge request openlp/web-remote!86
This commit is contained in:
commit
bf0e14caee
@ -24,14 +24,42 @@ To run the web remote, run the following command:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn run
|
||||
yarn start
|
||||
|
||||
|
||||
To build the web remote manually for deployment:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn build --prod --aot
|
||||
yarn build --aot
|
||||
|
||||
|
||||
To lint the web remote:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn lint
|
||||
|
||||
|
||||
To audit the web remote:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn audit
|
||||
|
||||
|
||||
To run unit tests on the web remote using the Chrome browser:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn test --browsers Chrome
|
||||
|
||||
|
||||
To run unit tests on the web remote using the Microsoft Edge browser:
|
||||
|
||||
.. code::
|
||||
|
||||
yarn test --browsers Edge
|
||||
|
||||
|
||||
Deployment
|
||||
|
40
package.json
40
package.json
@ -24,17 +24,19 @@
|
||||
"supportedBrowsers": "(echo module.exports = && browserslist-useragent-regexp --allowHigherVersions) > src/assets/supportedBrowsers.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^17.3.3",
|
||||
"@angular/cdk": "^17.3.3",
|
||||
"@angular/common": "^17.3.3",
|
||||
"@angular/compiler": "^17.3.3",
|
||||
"@angular/core": "^17.3.3",
|
||||
"@angular/forms": "^17.3.3",
|
||||
"@angular/material": "^17.3.3",
|
||||
"@angular/platform-browser": "^17.3.3",
|
||||
"@angular/platform-browser-dynamic": "^17.3.3",
|
||||
"@angular/router": "^17.3.3",
|
||||
"@angular/animations": "^17.3.4",
|
||||
"@angular/cdk": "^17.3.4",
|
||||
"@angular/common": "^17.3.4",
|
||||
"@angular/compiler": "^17.3.4",
|
||||
"@angular/core": "^17.3.4",
|
||||
"@angular/forms": "^17.3.4",
|
||||
"@angular/material": "^17.3.4",
|
||||
"@angular/platform-browser": "^17.3.4",
|
||||
"@angular/platform-browser-dynamic": "^17.3.4",
|
||||
"@angular/router": "^17.3.4",
|
||||
"@fontsource/roboto": "^5.0.12",
|
||||
"@ngx-translate/core": "^15.0.0",
|
||||
"@ngx-translate/http-loader": "^8.0.0",
|
||||
"core-js": "^3.36.1",
|
||||
"hammerjs": "^2.0.8",
|
||||
"material-icons": "^1.13.12",
|
||||
@ -42,23 +44,23 @@
|
||||
"zone.js": "^0.14.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.3.3",
|
||||
"@angular-devkit/build-angular": "^17.3.4",
|
||||
"@angular-eslint/builder": "^17.3.0",
|
||||
"@angular-eslint/eslint-plugin": "^17.3.0",
|
||||
"@angular-eslint/eslint-plugin-template": "^17.3.0",
|
||||
"@angular-eslint/schematics": "^17.3.0",
|
||||
"@angular-eslint/template-parser": "^17.3.0",
|
||||
"@angular/cli": "~17.3.3",
|
||||
"@angular/compiler-cli": "^17.3.3",
|
||||
"@angular/language-service": "^17.3.3",
|
||||
"@angular/cli": "~17.3.4",
|
||||
"@angular/compiler-cli": "^17.3.4",
|
||||
"@angular/language-service": "^17.3.4",
|
||||
"@chiragrupani/karma-chromium-edge-launcher": "^2.3.1",
|
||||
"@types/jasmine": "~5.1.4",
|
||||
"@types/jasminewd2": "~2.0.13",
|
||||
"@types/node": "~20.12.5",
|
||||
"@typescript-eslint/eslint-plugin": "7.5.0",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@types/node": "~20.12.7",
|
||||
"@typescript-eslint/eslint-plugin": "7.6.0",
|
||||
"@typescript-eslint/parser": "7.6.0",
|
||||
"browserslist": "^4.23.0",
|
||||
"browserslist-useragent-regexp": "^4.1.2",
|
||||
"browserslist-useragent-regexp": "^4.1.3",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import": "~2.29.1",
|
||||
"eslint-plugin-jsdoc": "~48.2.3",
|
||||
@ -71,7 +73,7 @@
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "^2.1.0",
|
||||
"ts-node": "~10.9.2",
|
||||
"typescript": "~5.4.4"
|
||||
"typescript": "~5.4.5"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
@ -1,16 +1,21 @@
|
||||
<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>
|
||||
<span class="page-title">{{ pageTitle | translate }}</span>
|
||||
<span class="spacer"></span>
|
||||
<button *ngIf="showLogin" mat-button (click)="login()">Login</button>
|
||||
<button
|
||||
<button *ngIf="showLogin" mat-button (click)="login()">{{ 'LOGIN' | translate }}</button>
|
||||
<button *ngIf="webSocketOpen"
|
||||
mat-icon-button
|
||||
(click)="forceWebSocketReconnection()"
|
||||
class="connection-status"
|
||||
[matTooltip]="webSocketOpen ? 'Connected to OpenLP' : 'Disconnected'"
|
||||
>
|
||||
matTooltip="{{ 'CONNECTED_TO_OPENLP' | translate }}">
|
||||
<mat-icon *ngIf="webSocketOpen">link</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!webSocketOpen"
|
||||
mat-icon-button
|
||||
(click)="forceWebSocketReconnection()"
|
||||
class="connection-status"
|
||||
matTooltip="{{ 'DISCONNECTED' | translate }}">
|
||||
<mat-icon *ngIf="!webSocketOpen">link_off</mat-icon>
|
||||
</button>
|
||||
<span class="app-version">v{{appVersion}}</span>
|
||||
@ -19,28 +24,63 @@
|
||||
<mat-sidenav-container>
|
||||
<mat-sidenav #menu mode="over">
|
||||
<mat-nav-list>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/service" routerLinkActive #serviceRoute="routerLinkActive" [activated]="serviceRoute.isActive">
|
||||
<mat-icon>list</mat-icon> Service
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/service"
|
||||
routerLinkActive #serviceRoute="routerLinkActive"
|
||||
[activated]="serviceRoute.isActive">
|
||||
<mat-icon>list</mat-icon> {{ 'SERVICE' | translate }}
|
||||
</a>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/slides" routerLinkActive #slidesRoute="routerLinkActive" [activated]="slidesRoute.isActive">
|
||||
<mat-icon>collections</mat-icon> Slides
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/slides"
|
||||
routerLinkActive #slidesRoute="routerLinkActive"
|
||||
[activated]="slidesRoute.isActive">
|
||||
<mat-icon>collections</mat-icon> {{ 'SLIDES' | translate }}
|
||||
</a>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/alerts" routerLinkActive #alertsRoute="routerLinkActive" [activated]="alertsRoute.isActive">
|
||||
<mat-icon>error</mat-icon> Alerts
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/alerts"
|
||||
routerLinkActive #alertsRoute="routerLinkActive"
|
||||
[activated]="alertsRoute.isActive">
|
||||
<mat-icon>error</mat-icon> {{ 'ALERTS' | translate }}
|
||||
</a>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/search" routerLinkActive #searchRoute="routerLinkActive" [activated]="searchRoute.isActive">
|
||||
<mat-icon>search</mat-icon> Search
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/search"
|
||||
routerLinkActive #searchRoute="routerLinkActive"
|
||||
[activated]="searchRoute.isActive">
|
||||
<mat-icon>search</mat-icon> {{ 'SEARCH' | translate }}
|
||||
</a>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/themes" routerLinkActive #themesRoute="routerLinkActive" [activated]="themesRoute.isActive">
|
||||
<mat-icon>image</mat-icon> Themes
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/themes"
|
||||
routerLinkActive #themesRoute="routerLinkActive"
|
||||
[activated]="themesRoute.isActive">
|
||||
<mat-icon>image</mat-icon> {{ 'THEMES' | translate }}
|
||||
</a>
|
||||
<mat-divider></mat-divider>
|
||||
<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="/chords">Chord View</a>
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/main">
|
||||
{{ 'MAIN_VIEW' | translate }}
|
||||
</a>
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/stage">
|
||||
{{ 'STAGE_VIEW' | translate }}
|
||||
</a>
|
||||
<a mat-list-item
|
||||
(click)="menu.close()"
|
||||
routerLink="/chords">
|
||||
{{ 'CHORD_VIEW' | translate }}
|
||||
</a>
|
||||
<mat-divider></mat-divider>
|
||||
<a mat-list-item (click)="menu.close()" routerLink="/settings" routerLinkActive #settingsRoute="routerLinkActive" [activated]="settingsRoute.isActive">
|
||||
<mat-icon>settings</mat-icon> Settings
|
||||
<a mat-list-item (click)="menu.close()"
|
||||
routerLink="/settings"
|
||||
routerLinkActive #settingsRoute="routerLinkActive"
|
||||
[activated]="settingsRoute.isActive">
|
||||
<mat-icon>settings</mat-icon> {{ 'SETTINGS' | translate }}
|
||||
</a>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
@ -55,68 +95,164 @@
|
||||
<mat-toolbar *ngIf="fastSwitching" class="toolbar-padding"></mat-toolbar>
|
||||
<footer>
|
||||
<mat-toolbar class="footer">
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="previousItem()" matTooltip="Previous item" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="previousItem()"
|
||||
matTooltip="{{ 'PREVIOUS_ITEM' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>first_page</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="previousItem()" matTooltip="Previous item" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="previousItem()"
|
||||
matTooltip="{{ 'PREVIOUS_ITEM' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>first_page</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="nextItem()" matTooltip="Next item" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="nextItem()"
|
||||
matTooltip="{{ 'NEXT_ITEM' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>last_page</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="nextItem()" matTooltip="Next item" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="nextItem()"
|
||||
matTooltip="{{ 'NEXT_ITEM' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>last_page</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="previousSlide()" matTooltip="Previous slide" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="previousSlide()"
|
||||
matTooltip="{{ 'PREVIOUS_SLIDE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>navigate_before</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="previousSlide()" matTooltip="Previous slide" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="previousSlide()"
|
||||
matTooltip="{{ 'PREVIOUS_SLIDE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>navigate_before</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="nextSlide()" matTooltip="Next slide" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="nextSlide()"
|
||||
matTooltip="{{ 'NEXT_SLIDE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>navigate_next</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="nextSlide()" matTooltip="Next slide" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="nextSlide()"
|
||||
matTooltip="{{ 'NEXT_SLIDE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>navigate_next</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" #squashedDisplayButton (click)="openDisplayModeSelector()" class="squashed-display-button" matTooltip="Change Display Mode" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
#squashedDisplayButton
|
||||
(click)="openDisplayModeSelector()"
|
||||
class="squashed-display-button"
|
||||
matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon *ngIf="state.blank">videocam_off</mat-icon>
|
||||
<mat-icon *ngIf="state.theme">wallpaper</mat-icon>
|
||||
<mat-icon *ngIf="state.display">desktop_windows</mat-icon>
|
||||
<mat-icon *ngIf="state.live()">videocam</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button #squashedDisplayButton (click)="openDisplayModeSelector()" class="squashed-display-button" matTooltip="Change Display Mode" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button
|
||||
#squashedDisplayButton
|
||||
(click)="openDisplayModeSelector()"
|
||||
class="squashed-display-button"
|
||||
matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon *ngIf="state.blank">videocam_off</mat-icon>
|
||||
<mat-icon *ngIf="state.theme">wallpaper</mat-icon>
|
||||
<mat-icon *ngIf="state.display">desktop_windows</mat-icon>
|
||||
<mat-icon *ngIf="state.live()">videocam</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="blankDisplay()" class="displayButton" [class.active]="state.blank" [disabled]="state.blank" matTooltip="Show black" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="blankDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.blank"
|
||||
[disabled]="state.blank"
|
||||
matTooltip="{{ 'SHOW_BLACK' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>videocam_off</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="blankDisplay()" class="displayButton" [class.active]="state.blank" [disabled]="state.blank" matTooltip="Show black" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="blankDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.blank"
|
||||
[disabled]="state.blank"
|
||||
matTooltip="{{ 'SHOW_BLACK' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>videocam_off</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="themeDisplay()" class="displayButton" [class.active]="state.theme" [disabled]="state.theme" matTooltip="Show background" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="themeDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.theme"
|
||||
[disabled]="state.theme"
|
||||
matTooltip="{{ 'SHOW_BACKGROUND' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>wallpaper</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="themeDisplay()" class="displayButton" [class.active]="state.theme" [disabled]="state.theme" matTooltip="Show background" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button
|
||||
(click)="themeDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.theme"
|
||||
[disabled]="state.theme"
|
||||
matTooltip="{{ 'SHOW_BACKGROUND' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>wallpaper</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="desktopDisplay()" class="displayButton" [class.active]="state.display" [disabled]="state.display" matTooltip="Show Desktop" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="desktopDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.display"
|
||||
[disabled]="state.display"
|
||||
matTooltip="{{ 'SHOW_DESKTOP' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>desktop_windows</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="desktopDisplay()" class="displayButton" [class.active]="state.display" [disabled]="state.display" matTooltip="Show Desktop" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="desktopDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.display"
|
||||
[disabled]="state.display"
|
||||
matTooltip="{{ 'SHOW_DESKTOP' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>desktop_windows</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="bigDisplayButtons" mat-fab color="primary" (click)="showDisplay()" class="displayButton" [class.active]="state.display" [disabled]="state.live()" matTooltip="Show Presentation" matTooltipPosition="above">
|
||||
<button *ngIf="bigDisplayButtons"
|
||||
mat-fab color="primary"
|
||||
(click)="showDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.display"
|
||||
[disabled]="state.live()"
|
||||
matTooltip="{{ 'SHOW_PRESENTATION' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>videocam</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="!bigDisplayButtons" mat-icon-button (click)="showDisplay()" class="displayButton" [class.active]="state.display" [disabled]="state.live()" matTooltip="Show Presentation" matTooltipPosition="above">
|
||||
<button *ngIf="!bigDisplayButtons"
|
||||
mat-icon-button (click)="showDisplay()"
|
||||
class="displayButton"
|
||||
[class.active]="state.display"
|
||||
[disabled]="state.live()"
|
||||
matTooltip="{{ 'SHOW_PRESENTATION' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>videocam</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
<nav mat-tab-nav-bar mat-stretch-tabs class="fast-switcher" [tabPanel]="tabPanel" *ngIf="fastSwitching">
|
||||
<nav *ngIf="fastSwitching"
|
||||
mat-tab-nav-bar mat-stretch-tabs
|
||||
class="fast-switcher"
|
||||
[tabPanel]="tabPanel">
|
||||
<a mat-tab-link
|
||||
routerLink="/service"
|
||||
routerLinkActive #serviceRoute="routerLinkActive"
|
||||
|
@ -2,6 +2,8 @@ import { Component, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatBottomSheet } from '@angular/material/bottom-sheet';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { State, Display, DisplayMode } from './responses';
|
||||
import { OpenLPService, WebSocketStatus } from './openlp.service';
|
||||
import { WindowRef } from './window-ref.service';
|
||||
@ -32,15 +34,20 @@ export class AppComponent implements OnInit {
|
||||
fastSwitching = false;
|
||||
bigDisplayButtons = false;
|
||||
useShortcutsFromOpenlp = false;
|
||||
useLanguageFromOpenlp = false;
|
||||
|
||||
constructor(private pageTitleService: PageTitleService, private openlpService: OpenLPService,
|
||||
private dialog: MatDialog, private bottomSheet: MatBottomSheet, private windowRef: WindowRef,
|
||||
private shortcutsService: ShortcutsService, private settingsService: SettingsService) {
|
||||
this.pageTitleService.pageTitleChanged$.subscribe(pageTitle => this.pageTitle = pageTitle);
|
||||
constructor(private translateService: TranslateService, private pageTitleService: PageTitleService,
|
||||
private openlpService: OpenLPService, private dialog: MatDialog, private bottomSheet: MatBottomSheet,
|
||||
private windowRef: WindowRef, private shortcutsService: ShortcutsService, private settingsService: SettingsService) {
|
||||
this.pageTitleService.pageTitleChanged$.subscribe(pageTitle => this.pageTitle = pageTitle.toUpperCase());
|
||||
this.openlpService.stateChanged$.subscribe(item => this.state = item);
|
||||
this.openlpService.webSocketStateChanged$.subscribe(status => this.webSocketOpen = status === WebSocketStatus.Open);
|
||||
this.shortcutsService.shortcutsChanged$.subscribe(shortcuts => this.addShortcuts(shortcuts));
|
||||
this.appVersion = this.windowRef.nativeWindow.appVersion || '0.0';
|
||||
|
||||
// This language will be used as a fallback when a translation isn't found in the current language
|
||||
this.translateService.setDefaultLang('en');
|
||||
|
||||
this.webSocketOpen = openlpService.webSocketStatus === WebSocketStatus.Open;
|
||||
// Try to force websocket reconnection as user is now focused on window and will try to interact soon
|
||||
// Adding a debounce to avoid event flooding
|
||||
@ -55,6 +62,12 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
this.openlpService.retrieveSystemInformation().subscribe(res => {
|
||||
this.showLogin = res.login_required
|
||||
this.useLanguageFromOpenlp = this.openlpService.assertApiVersionMinimum(2, 5)
|
||||
if (this.useLanguageFromOpenlp) {
|
||||
this.openlpService.getLanguage().subscribe(res => {
|
||||
this.translateService.use(res.language);
|
||||
});
|
||||
}
|
||||
this.useShortcutsFromOpenlp = this.openlpService.assertApiVersionMinimum(2, 5)
|
||||
this.shortcutsService.getShortcuts(this.useShortcutsFromOpenlp);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
@ -23,6 +23,9 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { PageTitleService } from './page-title.service';
|
||||
import { OpenLPService } from './openlp.service';
|
||||
@ -50,6 +53,10 @@ import { DisplayModeSelectorComponent } from './components/display-mode-selector
|
||||
import { SettingsComponent } from './components/settings/settings.component';
|
||||
import { StageChordPreviewComponent } from './components/settings/stage-chord-preview/stage-chord-preview.component';
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
export function createTranslateLoader(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -99,7 +106,15 @@ import { StageChordPreviewComponent } from './components/settings/stage-chord-pr
|
||||
MatToolbarModule,
|
||||
MatTooltipModule,
|
||||
MatBottomSheetModule,
|
||||
MatSliderModule
|
||||
MatSliderModule,
|
||||
TranslateModule.forRoot({
|
||||
defaultLanguage: 'en',
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: (createTranslateLoader),
|
||||
deps: [HttpClient]
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
PageTitleService,
|
||||
|
@ -1,7 +1,17 @@
|
||||
<h3>Send an Alert</h3>
|
||||
<h3>{{ 'SEND_AN_ALERT' | translate }}</h3>
|
||||
<form #alertForm="ngForm">
|
||||
<mat-form-field>
|
||||
<input matInput [(ngModel)]="alert" type="text" name="alert" placeholder="Alert" required>
|
||||
<input matInput
|
||||
[(ngModel)]="alert"
|
||||
type="text"
|
||||
name="alert"
|
||||
placeholder="{{ 'ALERT' | translate }}"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<button mat-raised-button color="primary" id="sendButton" [disabled]="!alertForm.form.valid" (click)="onSubmit(); alertForm.reset()">Send</button>
|
||||
</form>
|
||||
<button mat-raised-button color="primary"
|
||||
id="sendButton"
|
||||
[disabled]="!alertForm.form.valid"
|
||||
(click)="onSubmit(); alertForm.reset()">
|
||||
{{ 'SEND' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
|
@ -27,7 +27,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<a class="back-button" mat-mini-fab color="" routerLink="/" [matTooltip]="'Go back to controller'" *ngIf="!embedded">
|
||||
<a *ngIf="!embedded"
|
||||
mat-mini-fab color=""
|
||||
class="back-button"
|
||||
routerLink="/"
|
||||
matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate }}">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</a>
|
||||
<div class="transpose">
|
||||
@ -39,7 +43,9 @@
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="next-service-item" [matTooltip]="'Next item'" *ngIf="!embedded && activeSlide+1 === currentSlides.length">
|
||||
<div *ngIf="!embedded && activeSlide+1 === currentSlides.length"
|
||||
class="next-service-item"
|
||||
matTooltip="{{ 'NEXT_ITEM' | translate }}">
|
||||
{{ nextServiceItemTitle }}
|
||||
</div>
|
||||
<div class="time">{{ (openlpService.getIsTwelveHourTime()) ? (time|date:'h:mm a') : (time|date:'HH:mm') }}</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
(click)="setMode(DisplayMode.Blank)"
|
||||
[disabled]="displayMode === DisplayMode.Blank">
|
||||
<mat-icon class="small-icon">videocam_off</mat-icon>
|
||||
<span id="caption-blank" class="caption">Show Black</span>
|
||||
<span id="caption-blank" class="caption">{{ 'SHOW_BLACK' | translate }}</span>
|
||||
</button>
|
||||
<button mat-list-item
|
||||
aria-labelledby="caption-theme"
|
||||
@ -13,7 +13,7 @@
|
||||
(click)="setMode(DisplayMode.Theme)"
|
||||
[disabled]="displayMode === DisplayMode.Theme">
|
||||
<mat-icon class="small-icon">wallpaper</mat-icon>
|
||||
<span id="caption-theme" class="caption">Show Background</span>
|
||||
<span id="caption-theme" class="caption">{{ 'SHOW_BACKGROUND' | translate }}</span>
|
||||
</button>
|
||||
<button mat-list-item
|
||||
aria-labelledby="caption-desktop"
|
||||
@ -21,7 +21,7 @@
|
||||
(click)="setMode(DisplayMode.Desktop)"
|
||||
[disabled]="displayMode === DisplayMode.Desktop">
|
||||
<mat-icon class="small-icon">desktop_windows</mat-icon>
|
||||
<span id="caption-desktop" class="caption">Show Desktop</span>
|
||||
<span id="caption-desktop" class="caption">{{ 'SHOW_DESKTOP' | translate }}</span>
|
||||
</button>
|
||||
<button mat-list-item
|
||||
aria-labelledby="caption-presentation"
|
||||
@ -29,7 +29,7 @@
|
||||
(click)="setMode(DisplayMode.Presentation)"
|
||||
[disabled]="displayMode === DisplayMode.Presentation">
|
||||
<mat-icon class="small-icon">videocam</mat-icon>
|
||||
<span id="caption-presentation" class="caption">Show Presentation</span>
|
||||
<span id="caption-presentation" class="caption">{{ 'SHOW_PRESENTATION' | translate }}</span>
|
||||
</button>
|
||||
</mat-action-list>
|
||||
<mat-grid-list *ngIf="display.bigDisplayButtons" cols="2" rowHeight="2:1">
|
||||
@ -43,7 +43,7 @@
|
||||
</button>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<div id="caption-blank" class="caption">Show Black</div>
|
||||
<div id="caption-blank" class="caption">{{ 'SHOW_BLACK' | translate }}</div>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<button mat-fab color="primary"
|
||||
@ -55,7 +55,7 @@
|
||||
</button>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<div id="caption-theme" class="caption">Show Background</div>
|
||||
<div id="caption-theme" class="caption">{{ 'SHOW_BACKGROUND' | translate }}</div>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<button mat-fab color="primary"
|
||||
@ -67,7 +67,7 @@
|
||||
</button>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<div id="caption-desktop" class="caption">Show Desktop</div>
|
||||
<div id="caption-desktop" class="caption">{{ 'SHOW_DESKTOP' | translate }}</div>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<button mat-fab color="primary"
|
||||
@ -79,6 +79,6 @@
|
||||
</button>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<div id="caption-presentation" class="caption">Show Presentation</div>
|
||||
<div id="caption-presentation" class="caption">{{ 'SHOW_PRESENTATION' | translate }}</div>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
|
@ -1,15 +1,29 @@
|
||||
<h1 mat-dialog-title>Login</h1>
|
||||
<h1 mat-dialog-title>{{ 'LOGIN' | translate }}</h1>
|
||||
|
||||
<form #loginForm="ngForm">
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="Username" [(ngModel)]="username" name="username" required>
|
||||
<input matInput
|
||||
placeholder="{{ 'USER_NAME' | translate }}"
|
||||
[(ngModel)]="username"
|
||||
name="username"
|
||||
required>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input matInput placeholder="password" type="password" [(ngModel)]="password" name="password" required>
|
||||
<input matInput
|
||||
placeholder="{{ 'PASSWORD' | translate }}"
|
||||
type="password"
|
||||
[(ngModel)]="password"
|
||||
name="password"
|
||||
required>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-raised-button id="loginButton" color="primary" [disabled]="!loginForm.form.valid" (click)="performLogin()">Login</button>
|
||||
<button mat-raised-button id="loginButton"
|
||||
color="primary"
|
||||
[disabled]="!loginForm.form.valid"
|
||||
(click)="performLogin()">
|
||||
{{ 'LOGIN' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
@ -1,3 +1,3 @@
|
||||
<div class="overlay">
|
||||
<img src="{{ img }}">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5,4 +5,4 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<br>
|
||||
<br>
|
||||
|
@ -12,21 +12,36 @@
|
||||
<openlp-search-options></openlp-search-options>
|
||||
</div>
|
||||
<mat-form-field>
|
||||
<input matInput [(ngModel)]="searchText" name="searchText" placeholder="Search Text" required>
|
||||
<input matInput [(ngModel)]="searchText" name="searchText" placeholder="{{ 'SEARCH_TEXT' | translate }}" required>
|
||||
</mat-form-field>
|
||||
<br>
|
||||
<button mat-raised-button id="searchButton" color="primary" [disabled]="!searchForm.form.valid" (click)="onSubmit()">Search</button>
|
||||
<button mat-raised-button id="searchButton"
|
||||
color="primary"
|
||||
[disabled]="!searchForm.form.valid"
|
||||
(click)="onSubmit()">
|
||||
{{ 'SEARCH' | translate }}
|
||||
</button>
|
||||
</form>
|
||||
<div *ngIf="searchResults">
|
||||
<h3>Search Results:</h3>
|
||||
<h3>{{ 'SEARCH_RESULTS' | translate }}:</h3>
|
||||
<div *ngIf="!searchResults.length">
|
||||
No Results matching your search were found...
|
||||
{{ 'NO_SEARCH_RESULTS' | translate }}...
|
||||
</div>
|
||||
<table *ngIf="searchResults.length">
|
||||
<tr *ngFor="let item of searchResults">
|
||||
<td>{{item[1]}}</td>
|
||||
<td><button mat-button color="primary" (click)="addToService(item[0])">Add to Service</button></td>
|
||||
<td><button mat-button color="accent" (click)="sendLive(item[0])">Send Live</button></td>
|
||||
<td>
|
||||
<button mat-button color="primary"
|
||||
(click)="addToService(item[0])">
|
||||
{{ 'ADD_TO_SERVICE' | translate }}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<button mat-button color="accent"
|
||||
(click)="sendLive(item[0])">
|
||||
{{ 'SEND_LIVE' | translate }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -4,19 +4,18 @@
|
||||
[item]="item"
|
||||
[selected]="item.selected"
|
||||
(selectItem)="onItemSelected($event)"
|
||||
[tabindex]="item.id"
|
||||
></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.
|
||||
{{ 'NO_SERVICE_ITEMS' | translate }}.
|
||||
</div>
|
||||
<div class="no-items-actions">
|
||||
<a routerLink="/search" mat-stroked-button color="primary" size="small">
|
||||
<span class="material-icons">add</span>
|
||||
Add Item
|
||||
{{ 'ADD_ITEM' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1 +1 @@
|
||||
<openlp-service-list (itemSelected)="this.onItemSelected($event)"></openlp-service-list>
|
||||
<openlp-service-list (itemSelected)="this.onItemSelected($event)"></openlp-service-list>
|
||||
|
@ -1,36 +1,34 @@
|
||||
<div class="settings-panel">
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
User Interface
|
||||
{{ 'USER_INTERFACE' | translate }}
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="settings-item">
|
||||
<mat-slide-toggle
|
||||
color="primary"
|
||||
[checked]="settings.fastSwitching"
|
||||
(change)="setSetting('fastSwitching', $event.checked)"
|
||||
>
|
||||
Enable Fast Switching Panel
|
||||
(change)="setSetting('fastSwitching', $event.checked)">
|
||||
{{ 'ENABLE_FAST_SWITCHING_PANEL' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<div class="settings-item">
|
||||
<mat-slide-toggle
|
||||
color="primary"
|
||||
[checked]="settings.bigDisplayButtons"
|
||||
(change)="setSetting('bigDisplayButtons', $event.checked)"
|
||||
>
|
||||
Enable Big Display Buttons
|
||||
(change)="setSetting('bigDisplayButtons', $event.checked)">
|
||||
{{ 'ENABLE_BIG_DISPLAY_BUTTONS' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
Stage and Chords Appearance
|
||||
{{ 'STAGE_AND_CHORDS_APPEARANCE' | translate }}
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Stage">
|
||||
<mat-tab label="{{ 'STAGE' | translate }}">
|
||||
<ng-template matTabContent>
|
||||
<ng-container>
|
||||
<openlp-stage-chord-preview stageType="stage"></openlp-stage-chord-preview>
|
||||
@ -38,10 +36,10 @@
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab label="Chords">
|
||||
<mat-tab label="{{ 'CHORDS' | translate }}">
|
||||
<ng-template matTabContent>
|
||||
<openlp-stage-chord-preview stageType="chords"></openlp-stage-chord-preview>
|
||||
<ng-container *ngTemplateOutlet="stageSettings; context: {prefix: 'chords'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="stageSettings; context: {prefix: 'chords'}"></ng-container>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
@ -51,18 +49,16 @@
|
||||
<ng-template #stageSettings let-prefix="prefix">
|
||||
<div class="stage-settings">
|
||||
<div class="settings-item">
|
||||
<label>Font Scale: {{settings[prefix + 'FontScale'] ?? 100}}%</label>
|
||||
<label>{{ 'FONT_SCALE' | translate }}: {{settings[prefix + 'FontScale'] ?? 100}}%</label>
|
||||
<mat-slider
|
||||
min="25"
|
||||
max="200"
|
||||
step="6.25"
|
||||
>
|
||||
step="6.25">
|
||||
<input
|
||||
matSliderThumb
|
||||
[value]="settings[prefix + 'FontScale']"
|
||||
(valueChange)="setSetting(prefix + 'FontScale', $event)"
|
||||
>
|
||||
(valueChange)="setSetting(prefix + 'FontScale', $event)">
|
||||
</mat-slider>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
@ -11,4 +11,4 @@
|
||||
[embedded]="true"
|
||||
[style.--openlp-stage-font-scale]="fontScale"
|
||||
></app-chord-view>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,4 +12,3 @@
|
||||
</ng-template>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
|
@ -11,13 +11,13 @@
|
||||
<div class="no-items" *ngIf="!loading">
|
||||
<div class="no-items-title">
|
||||
<span class="material-icons icon">info</span>
|
||||
No slide items.
|
||||
{{ 'NO_SLIDE_ITEMS' | translate }}.
|
||||
</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
|
||||
{{ 'ADD_ITEM_TO_SERVICE' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
@ -1 +1 @@
|
||||
<openlp-slide-list (slideSelected)="onSlideSelected($event)"></openlp-slide-list>
|
||||
<openlp-slide-list (slideSelected)="onSlideSelected($event)"></openlp-slide-list>
|
||||
|
@ -3,8 +3,7 @@
|
||||
[class.mat-headline-2]="active"
|
||||
[class.currentSlide]="active"
|
||||
[class.mat-headline-4]="!active"
|
||||
[class.first]="!active && slide.first_slide_of_tag"
|
||||
>
|
||||
[class.first]="!active && slide.first_slide_of_tag">
|
||||
<ng-container *ngIf="!(slide?.img); else elseImage">
|
||||
{{slide?.text}}
|
||||
</ng-container>
|
||||
|
@ -1,8 +1,7 @@
|
||||
<div
|
||||
class="overlay"
|
||||
[class.embedded]="embedded"
|
||||
[style.--openlp-stage-font-scale]="fontScale"
|
||||
>
|
||||
[style.--openlp-stage-font-scale]="fontScale">
|
||||
<div class="overlay-content">
|
||||
<div class="tags">
|
||||
<span *ngFor="let tag of tags" [class.active]="tag.active">{{ tag.text }}</span>
|
||||
@ -15,20 +14,34 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<a class="back-button" mat-mini-fab color="" routerLink="/" [matTooltip]="'Go back to controller'" *ngIf="!embedded">
|
||||
<a *ngIf="!embedded"
|
||||
class="back-button"
|
||||
mat-mini-fab color=""
|
||||
routerLink="/"
|
||||
matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate }}">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</a>
|
||||
<button
|
||||
<button *ngIf="showNotes"
|
||||
mat-mini-fab
|
||||
class="show-notes"
|
||||
[matTooltip]="'Show/hide notes'"
|
||||
[color]="showNotes ? 'primary' : ''"
|
||||
[class.show-notes-disabled]="!showNotes"
|
||||
(click)="showNotes = !showNotes"
|
||||
>
|
||||
matTooltip="{{ 'HIDE_NOTES' | translate }}"
|
||||
[color]="primary"
|
||||
[class.show-notes-disabled]="false"
|
||||
(click)="showNotes = false">
|
||||
<mat-icon>sticky_note_2</mat-icon>
|
||||
</button>
|
||||
<div class="next-service-item" [matTooltip]="'Next item'" *ngIf="!embedded && activeSlide+1 === currentSlides.length">
|
||||
<button *ngIf="!showNotes"
|
||||
mat-mini-fab
|
||||
class="show-notes"
|
||||
matTooltip="{{ 'SHOW_NOTES' | translate }}"
|
||||
[color]=""
|
||||
[class.show-notes-disabled]="true"
|
||||
(click)="showNotes = true">
|
||||
<mat-icon>sticky_note_2</mat-icon>
|
||||
</button>
|
||||
<div *ngIf="!embedded && activeSlide+1 === currentSlides.length"
|
||||
class="next-service-item"
|
||||
matTooltip="{{ 'NEXT_ITEM' | translate }}">
|
||||
{{ nextServiceItemTitle }}
|
||||
</div>
|
||||
<div class="time">{{ (openlpService.getIsTwelveHourTime()) ? (time|date:'h:mm a') : (time|date:'HH:mm') }}</div>
|
||||
|
@ -1,17 +1,15 @@
|
||||
<form #themeForm="ngForm">
|
||||
<h4>Theme Options</h4>
|
||||
<h4>{{ 'THEME_OPTIONS' | translate }}</h4>
|
||||
<div>
|
||||
<!-- Theme level menu -->
|
||||
<mat-form-field>
|
||||
<mat-label>Theme level</mat-label>
|
||||
<mat-label>{{ 'THEME_LEVEL' | translate }}</mat-label>
|
||||
<mat-select [(value)]="themeLevel">
|
||||
<mat-option value="global">Global</mat-option>
|
||||
<mat-option value="service">Service</mat-option>
|
||||
<mat-option value="song">Song</mat-option>
|
||||
<mat-option value="global">{{ 'GLOBAL' | translate }}</mat-option>
|
||||
<mat-option value="service">{{ 'SERVICE' | translate }}</mat-option>
|
||||
<mat-option value="song">{{ 'SONG' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- Themes display -->
|
||||
<div class="theme-container content" *ngIf="isThemeLevelSupported()">
|
||||
<div *ngFor="let theme of themeList;">
|
||||
<mat-card class="theme-card" (click)='setTheme(theme.name)' [class.selected]="theme.selected">
|
||||
@ -22,5 +20,7 @@
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<mat-error *ngIf="!isThemeLevelSupported()">Song level theme changing not supported. Change your theme level to Global or Service</mat-error>
|
||||
</form>
|
||||
<mat-error *ngIf="!isThemeLevelSupported()">
|
||||
{{ 'SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED' | translate }}
|
||||
</mat-error>
|
||||
</form>
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
Slide,
|
||||
ServiceItem,
|
||||
Theme,
|
||||
Language,
|
||||
MainView,
|
||||
Shortcut,
|
||||
SystemInformation,
|
||||
@ -93,6 +94,10 @@ export class OpenLPService {
|
||||
}));
|
||||
}
|
||||
|
||||
getLanguage(): Observable<Language> {
|
||||
return this.doGet(`${this.apiURL}/core/language`);
|
||||
}
|
||||
|
||||
getMainImage(): Observable<MainView> {
|
||||
return this.doGet<MainView>(`${this.apiURL}/core/live-image`);
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ export interface Theme {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Language {
|
||||
language: string;
|
||||
}
|
||||
|
||||
export interface MainView {
|
||||
binary_image: string;
|
||||
}
|
||||
|
52
src/assets/i18n/de.json
Normal file
52
src/assets/i18n/de.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"ADD_ITEM": "Element Hinzufügen",
|
||||
"ADD_ITEM_TO_SERVICE": "Element zum Ablauf Hinzufügen",
|
||||
"ADD_TO_SERVICE": "Zum Ablauf Hinzufügen",
|
||||
"ALERT": "Hinweise",
|
||||
"ALERTS": "Hinweisen",
|
||||
"CHANGE_DISPLAY_MODE": "Anzeigemodus Ändern",
|
||||
"CHORD_VIEW": "Akkordansicht",
|
||||
"CHORDS": "Akkorde",
|
||||
"CONNECTED_TO_OPENLP": "Mit OpenLP Verbunden",
|
||||
"DISCONNECTED": "Getrennt",
|
||||
"ENABLE_BIG_DISPLAY_BUTTONS": "Große Anzeige-Schaltflächen Aktivieren",
|
||||
"ENABLE_FAST_SWITCHING_PANEL": "Schnelles Umschalten Aktivieren",
|
||||
"FONT_SCALE": "Schriftgrad",
|
||||
"GLOBAL": "Global",
|
||||
"GO_BACK_TO_CONTROLLER": "Zurück zum Controller",
|
||||
"HIDE_NOTES": "Notizen Ausblenden",
|
||||
"LOGIN": "Anmelden",
|
||||
"MAIN_VIEW": "Hauptansicht",
|
||||
"NEXT_ITEM": "Nächstes Element",
|
||||
"NEXT_SLIDE": "Nächste Folie",
|
||||
"NO_SEARCH_RESULTS": "Keine Suchergebnisse Gefunden",
|
||||
"NO_SERVICE_ITEMS": "Keine Ablauf Elemente",
|
||||
"NO_SLIDE_ITEMS": "Keine Folien-Elemente",
|
||||
"PASSWORD": "Passwort",
|
||||
"PREVIOUS_ITEM": "Vorheriges Element",
|
||||
"PREVIOUS_SLIDE": "Vorherige Folie",
|
||||
"SEARCH": "Suche",
|
||||
"SEARCH_RESULTS": "Suchergebnisse",
|
||||
"SEARCH_TEXT": "Suchtext",
|
||||
"SEND": "Senden",
|
||||
"SEND_AN_ALERT": "Hinweise Senden",
|
||||
"SEND_LIVE": "Live Senden",
|
||||
"SERVICE": "Ablauf",
|
||||
"SETTINGS": "Einstellungen",
|
||||
"SHOW_BACKGROUND": "Hintergrund Anzeigen",
|
||||
"SHOW_BLACK": "Schwarz Anzeigen",
|
||||
"SHOW_DESKTOP": "Desktop Anzeigen",
|
||||
"SHOW_NOTES": "Notizen Anzeigen",
|
||||
"SHOW_PRESENTATION": "Präsentation Anzeigen",
|
||||
"SLIDES": "Folien",
|
||||
"SONG": "Lied",
|
||||
"SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED": "Das Ändern des Themas auf Liedebene wird nicht unterstützt. Ändern Sie Ihr Themenlevel auf Global oder Ablauf",
|
||||
"STAGE": "Bühne",
|
||||
"STAGE_AND_CHORDS_APPEARANCE": "Bühnen- und Akkorddarstellung",
|
||||
"STAGE_VIEW": "Bühnenansicht",
|
||||
"THEMES": "Themen",
|
||||
"THEME_LEVEL": "Themenlevel",
|
||||
"THEME_OPTIONS": "Themenoptionen",
|
||||
"USER_NAME": "Benutzername",
|
||||
"USER_INTERFACE": "Benutzeroberfläche"
|
||||
}
|
52
src/assets/i18n/en.json
Normal file
52
src/assets/i18n/en.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"ADD_ITEM": "Add Item",
|
||||
"ADD_ITEM_TO_SERVICE": "Add Item to Service",
|
||||
"ADD_TO_SERVICE": "Add to Service",
|
||||
"ALERT": "Alert",
|
||||
"ALERTS": "Alerts",
|
||||
"CHANGE_DISPLAY_MODE": "Change Display Mode",
|
||||
"CHORD_VIEW": "Chord View",
|
||||
"CHORDS": "Chords",
|
||||
"CONNECTED_TO_OPENLP": "Connected to OpenLP",
|
||||
"DISCONNECTED": "Disconnected",
|
||||
"ENABLE_BIG_DISPLAY_BUTTONS": "Enable Big Display Buttons",
|
||||
"ENABLE_FAST_SWITCHING_PANEL": "Enable Fast Switching Panel",
|
||||
"FONT_SCALE": "Font Scale",
|
||||
"GLOBAL": "Global",
|
||||
"GO_BACK_TO_CONTROLLER": "Go Back to Controller",
|
||||
"HIDE_NOTES": "Hide Notes",
|
||||
"LOGIN": "Login",
|
||||
"MAIN_VIEW": "Main View",
|
||||
"NEXT_ITEM": "Next Item",
|
||||
"NEXT_SLIDE": "Next Slide",
|
||||
"NO_SEARCH_RESULTS": "No results matching your search were found",
|
||||
"NO_SERVICE_ITEMS": "No Service Items",
|
||||
"NO_SLIDE_ITEMS": "No Slide Items",
|
||||
"PASSWORD": "Password",
|
||||
"PREVIOUS_ITEM": "Previous Item",
|
||||
"PREVIOUS_SLIDE": "Previous Slide",
|
||||
"SEARCH": "Search",
|
||||
"SEARCH_RESULTS": "Search Results",
|
||||
"SEARCH_TEXT": "Search Text",
|
||||
"SEND": "Send",
|
||||
"SEND_AN_ALERT": "Send an Alert",
|
||||
"SEND_LIVE": "Send Live",
|
||||
"SERVICE": "Service",
|
||||
"SETTINGS": "Settings",
|
||||
"SHOW_BACKGROUND": "Show Background",
|
||||
"SHOW_BLACK": "Show Black",
|
||||
"SHOW_DESKTOP": "Show Desktop",
|
||||
"SHOW_NOTES": "Show Notes",
|
||||
"SHOW_PRESENTATION": "Show Presentation",
|
||||
"SLIDES": "Slides",
|
||||
"SONG": "Song",
|
||||
"SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED": "Song level theme changing not supported. Change your theme level to Global or Service",
|
||||
"STAGE": "Stage",
|
||||
"STAGE_AND_CHORDS_APPEARANCE": "Stage and Chords Appearance",
|
||||
"STAGE_VIEW": "Stage View",
|
||||
"THEMES": "Themes",
|
||||
"THEME_LEVEL": "Theme Level",
|
||||
"THEME_OPTIONS": "Theme Options",
|
||||
"USER_NAME": "User Name",
|
||||
"USER_INTERFACE": "User Interface"
|
||||
}
|
52
src/assets/i18n/fr.json
Normal file
52
src/assets/i18n/fr.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"ADD_ITEM": "Ajouter un Élément",
|
||||
"ADD_ITEM_TO_SERVICE": "Ajouter un Élément au Service",
|
||||
"ADD_TO_SERVICE": "Ajouter au Service",
|
||||
"ALERT": "Alerte",
|
||||
"ALERTS": "Alertes",
|
||||
"CHANGE_DISPLAY_MODE": "Changer le Mode d’Affichage",
|
||||
"CHORD_VIEW": "Vue des Accords",
|
||||
"CHORDS": "Accords",
|
||||
"CONNECTED_TO_OPENLP": "Connecté à OpenLP",
|
||||
"DISCONNECTED": "Déconnecté",
|
||||
"ENABLE_BIG_DISPLAY_BUTTONS": "Activer les Gros Boutons d’Afichage",
|
||||
"ENABLE_FAST_SWITCHING_PANEL": "Activer le Panneau de Commutation Rapide",
|
||||
"FONT_SCALE": "Échelle de Police",
|
||||
"GLOBAL": "Global",
|
||||
"GO_BACK_TO_CONTROLLER": "Retour au Contrôleur",
|
||||
"HIDE_NOTES": "Masquer les Notes",
|
||||
"LOGIN": "Connexion",
|
||||
"MAIN_VIEW": "Vue Principale",
|
||||
"NEXT_ITEM": "Élément Suivant",
|
||||
"NEXT_SLIDE": "Diapositive Suivante",
|
||||
"NO_SEARCH_RESULTS": "Aucun résultat correspondant à votre recherche n’a été trouvé",
|
||||
"NO_SERVICE_ITEMS": "Aucun Élément de Service",
|
||||
"NO_SLIDE_ITEMS": "Aucun Élément de Diapositive",
|
||||
"PASSWORD": "Mot de Passe",
|
||||
"PREVIOUS_ITEM": "Élément Précédent",
|
||||
"PREVIOUS_SLIDE": "Diapositive Précédente",
|
||||
"SEARCH": "Recherche",
|
||||
"SEARCH_RESULTS": "Résultats de la Recherche",
|
||||
"SEARCH_TEXT": "Texte de Recherche",
|
||||
"SEND": "Envoyer",
|
||||
"SEND_AN_ALERT": "Envoyer une Alerte",
|
||||
"SEND_LIVE": "Envoyer en Direct",
|
||||
"SERVICE": "Service",
|
||||
"SETTINGS": "Paramètres",
|
||||
"SHOW_BACKGROUND": "Afficher l’Arrière-plan",
|
||||
"SHOW_BLACK": "Afficher écran Noir",
|
||||
"SHOW_DESKTOP": "Afficher le Bureau",
|
||||
"SHOW_NOTES": "Afficher les Notes",
|
||||
"SHOW_PRESENTATION": "Afficher la Présentation",
|
||||
"SLIDES": "Diapositives",
|
||||
"SONG": "Chanson",
|
||||
"SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED": "Le changement de thème au niveau de la chanson n’est pas pris en charge. Changez votre niveau de thème en Global ou Service",
|
||||
"STAGE": "Scène",
|
||||
"STAGE_AND_CHORDS_APPEARANCE": "Apparence de la Scène et des Accords",
|
||||
"STAGE_VIEW": "Vue de la Scène",
|
||||
"THEMES": "Thèmes",
|
||||
"THEME_LEVEL": "Niveau de Thème",
|
||||
"THEME_OPTIONS": "Options de Thème",
|
||||
"USER_NAME": "Nom d’Utilisateur",
|
||||
"USER_INTERFACE": "Interface Utilisateur"
|
||||
}
|
52
src/assets/i18n/nl.json
Normal file
52
src/assets/i18n/nl.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"ADD_ITEM": "Voeg Item Toe",
|
||||
"ADD_ITEM_TO_SERVICE": "Voeg Item Toe aan Liturgie",
|
||||
"ADD_TO_SERVICE": "Voeg Toe aan Liturgie",
|
||||
"ALERT": "Waarschuwing",
|
||||
"ALERTS": "Waarschuwingen",
|
||||
"CHANGE_DISPLAY_MODE": "Wijzig Weergave",
|
||||
"CHORD_VIEW": "Akkoordenscherm",
|
||||
"CHORDS": "Akkoorden",
|
||||
"CONNECTED_TO_OPENLP": "Verbonden met OpenLP",
|
||||
"DISCONNECTED": "Niet Verbonden",
|
||||
"ENABLE_BIG_DISPLAY_BUTTONS": "Activeer Grote Beeldschermknoppen",
|
||||
"ENABLE_FAST_SWITCHING_PANEL": "Activeer Snel Wisselpaneel",
|
||||
"FONT_SCALE": "Schaal Lettertype",
|
||||
"GLOBAL": "Globaal",
|
||||
"GO_BACK_TO_CONTROLLER": "Ga Terug naar Controller",
|
||||
"HIDE_NOTES": "Verberg Notities",
|
||||
"LOGIN": "Log In",
|
||||
"MAIN_VIEW": "Hoofdscherm",
|
||||
"NEXT_ITEM": "Volgend Item",
|
||||
"NEXT_SLIDE": "Volgende Slide",
|
||||
"NO_SEARCH_RESULTS": "Jouw zoekopdracht heeft geen resultaten opgeleverd",
|
||||
"NO_SERVICE_ITEMS": "Geen Liturgie Items",
|
||||
"NO_SLIDE_ITEMS": "Geen Slide Items",
|
||||
"PASSWORD": "Wachtwoord",
|
||||
"PREVIOUS_ITEM": "Vorig Item",
|
||||
"PREVIOUS_SLIDE": "Vorige Slide",
|
||||
"SEARCH": "Zoek",
|
||||
"SEARCH_RESULTS": "Zoekresultaten",
|
||||
"SEARCH_TEXT": "Zoektekst",
|
||||
"SEND": "Versturen",
|
||||
"SEND_AN_ALERT": "Stuur een Waarschuwing",
|
||||
"SEND_LIVE": "Ga Live",
|
||||
"SERVICE": "Liturgie",
|
||||
"SETTINGS": "Instellingen",
|
||||
"SHOW_BACKGROUND": "Toon Achtergrond",
|
||||
"SHOW_BLACK": "Toon Zwart",
|
||||
"SHOW_DESKTOP": "Toon Bureaublad",
|
||||
"SHOW_NOTES": "Toon Notities",
|
||||
"SHOW_PRESENTATION": "Toon Presentatie",
|
||||
"SLIDES": "Slides",
|
||||
"SONG": "Lied",
|
||||
"SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED": "Themawijziging op liedniveau wordt niet ondersteund. Wijzig uw themaniveau naar Globaal of Service",
|
||||
"STAGE": "Podium",
|
||||
"STAGE_AND_CHORDS_APPEARANCE": "Podium- en Akkoordenscherm",
|
||||
"STAGE_VIEW": "Podiumscherm",
|
||||
"THEMES": "Thema's",
|
||||
"THEME_LEVEL": "Thema Niveau",
|
||||
"THEME_OPTIONS": "Theme Opties",
|
||||
"USER_NAME": "Gebruikersnaam",
|
||||
"USER_INTERFACE": "Gebruikersinterface"
|
||||
}
|
52
src/assets/i18n/sl.json
Normal file
52
src/assets/i18n/sl.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"ADD_ITEM": "Dodaj Element",
|
||||
"ADD_ITEM_TO_SERVICE": "Dodaj Element Spored",
|
||||
"ADD_TO_SERVICE": "Dodaj Spored",
|
||||
"ALERT": "Opozorilo",
|
||||
"ALERTS": "Opozorila",
|
||||
"CHANGE_DISPLAY_MODE": "Spremeni način Prikaza",
|
||||
"CHORD_VIEW": "Pogled Akordov",
|
||||
"CHORDS": "Akordi",
|
||||
"CONNECTED_TO_OPENLP": "Povezano z OpenLP",
|
||||
"DISCONNECTED": "Prekinjeno",
|
||||
"ENABLE_BIG_DISPLAY_BUTTONS": "Omogoči Velike Gumbe za Prikaz",
|
||||
"ENABLE_FAST_SWITCHING_PANEL": "Omogoči Hitro Preklapljanje Plošče",
|
||||
"FONT_SCALE": "Velikost Pisave",
|
||||
"GLOBAL": "Globalno",
|
||||
"GO_BACK_TO_CONTROLLER": "Vrni se na Krmilnikr",
|
||||
"HIDE_NOTES": "Skrij Opombe",
|
||||
"LOGIN": "Prijava",
|
||||
"MAIN_VIEW": "Glavni Pogled",
|
||||
"NEXT_ITEM": "Naslednji Element",
|
||||
"NEXT_SLIDE": "Naslednji Diapozitiv",
|
||||
"NO_SEARCH_RESULTS": "Ni rezultatov, ki bi se ujemali z vašim iskanjem",
|
||||
"NO_SERVICE_ITEMS": "Ni Elementov Spored",
|
||||
"NO_SLIDE_ITEMS": "Ni Diapozitivnih Elementov",
|
||||
"PASSWORD": "Geslo",
|
||||
"PREVIOUS_ITEM": "Prejšnji Element",
|
||||
"PREVIOUS_SLIDE": "Prejšnji Diapozitiv",
|
||||
"SEARCH": "Iskanje",
|
||||
"SEARCH_RESULTS": "Rezultati Iskanja",
|
||||
"SEARCH_TEXT": "Besedilo Iskanja",
|
||||
"SEND": "Pošlji",
|
||||
"SEND_AN_ALERT": "Pošlji Opozorilo",
|
||||
"SEND_LIVE": "Pošlji v Živo",
|
||||
"SERVICE": "Spored",
|
||||
"SETTINGS": "Nastavitve",
|
||||
"SHOW_BACKGROUND": "Prikaži Ozadje",
|
||||
"SHOW_BLACK": "Prikaži Črno",
|
||||
"SHOW_DESKTOP": "Prikaži Namizje",
|
||||
"SHOW_NOTES": "Prikaži Opomb",
|
||||
"SHOW_PRESENTATION": "Prikaži Predstavitve",
|
||||
"SLIDES": "Diapozitivi",
|
||||
"SONG": "Pesem",
|
||||
"SONG_LEVEL_THEME_CHANGING_NOT_SUPPORTED": "Spreminjanje teme na ravni pesmi ni podprto. Spremenite raven teme na Globalno ali Spored",
|
||||
"STAGE": "Odrom",
|
||||
"STAGE_AND_CHORDS_APPEARANCE": "Videz Odra in Akordov",
|
||||
"STAGE_VIEW": "Pogled Odra",
|
||||
"THEMES": "Teme",
|
||||
"THEME_LEVEL": "Raven Teme",
|
||||
"THEME_OPTIONS": "Možnosti Teme",
|
||||
"USER_NAME": "Uporabniško Ime",
|
||||
"USER_INTERFACE": "Uporabniški Vmesnik"
|
||||
}
|
Loading…
Reference in New Issue
Block a user