diff --git a/package.json b/package.json
index a692792..fcfa2d0 100644
--- a/package.json
+++ b/package.json
@@ -25,23 +25,23 @@
"tx": "node scripts/tx.js"
},
"dependencies": {
- "@angular/animations": "^17.3.6",
- "@angular/cdk": "^17.3.6",
- "@angular/common": "^17.3.6",
- "@angular/compiler": "^17.3.6",
- "@angular/core": "^17.3.6",
- "@angular/forms": "^17.3.6",
- "@angular/material": "^17.3.6",
- "@angular/platform-browser": "^17.3.6",
- "@angular/platform-browser-dynamic": "^17.3.6",
- "@angular/router": "^17.3.6",
+ "@angular/animations": "^17.3.7",
+ "@angular/cdk": "^17.3.7",
+ "@angular/common": "^17.3.7",
+ "@angular/compiler": "^17.3.7",
+ "@angular/core": "^17.3.7",
+ "@angular/forms": "^17.3.7",
+ "@angular/material": "^17.3.7",
+ "@angular/platform-browser": "^17.3.7",
+ "@angular/platform-browser-dynamic": "^17.3.7",
+ "@angular/router": "^17.3.7",
"@fontsource/roboto": "^5.0.13",
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"core-js": "^3.37.0",
"material-icons": "^1.13.12",
"rxjs": "^7.8.1",
- "zone.js": "^0.14.4"
+ "zone.js": "^0.14.5"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.3.6",
@@ -51,16 +51,16 @@
"@angular-eslint/schematics": "^17.3.0",
"@angular-eslint/template-parser": "^17.3.0",
"@angular/cli": "~17.3.6",
- "@angular/compiler-cli": "^17.3.6",
- "@angular/language-service": "^17.3.6",
+ "@angular/compiler-cli": "^17.3.7",
+ "@angular/language-service": "^17.3.7",
"@chiragrupani/karma-chromium-edge-launcher": "^2.3.1",
"@transifex/api": "^7.1.0",
"@types/jasmine": "~5.1.4",
"@types/jasminewd2": "~2.0.13",
"@types/jest": "^29.5.12",
- "@types/node": "~20.12.7",
- "@typescript-eslint/eslint-plugin": "7.7.1",
- "@typescript-eslint/parser": "7.7.1",
+ "@types/node": "~20.12.8",
+ "@typescript-eslint/eslint-plugin": "7.8.0",
+ "@typescript-eslint/parser": "7.8.0",
"axios": "^1.6.8",
"browserslist": "^4.23.0",
"browserslist-useragent-regexp": "^4.1.3",
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 8ecd9c9..5e54725 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -3,13 +3,13 @@
- {{ pageTitle | translate }}
+ {{ pageTitle | translate | titlecase }}
@if (showLogin) {
}
@if (webSocketOpen) {
@@ -17,7 +17,7 @@
mat-icon-button
(click)="forceWebSocketReconnection()"
class="connection-status"
- matTooltip="{{ 'CONNECTED_TO_OPENLP' | translate }}">
+ matTooltip="{{ 'CONNECTED_TO_OPENLP' | translate | titlecase }}">
link
}
@@ -26,7 +26,7 @@
mat-icon-button
(click)="forceWebSocketReconnection()"
class="connection-status"
- matTooltip="{{ 'DISCONNECTED' | translate }}">
+ matTooltip="{{ 'DISCONNECTED' | translate | titlecase }}">
link_off
}
@@ -41,58 +41,58 @@
routerLink="/service"
routerLinkActive #serviceRoute="routerLinkActive"
[activated]="serviceRoute.isActive">
- list {{ 'SERVICE' | translate }}
+ list {{ 'SERVICE' | translate | titlecase }}
- collections {{ 'SLIDES' | translate }}
+ collections {{ 'SLIDES' | translate | titlecase }}
- error {{ 'ALERTS' | translate }}
+ error {{ 'ALERTS' | translate | titlecase }}
- search {{ 'SEARCH' | translate }}
+ search {{ 'SEARCH' | translate | titlecase }}
- image {{ 'THEMES' | translate }}
+ image {{ 'THEMES' | translate | titlecase }}
- {{ 'MAIN_VIEW' | translate }}
+ {{ 'MAIN_VIEW' | translate | titlecase }}
- {{ 'STAGE_VIEW' | translate }}
+ {{ 'STAGE_VIEW' | translate | titlecase }}
- {{ 'CHORD_VIEW' | translate }}
+ {{ 'CHORD_VIEW' | translate | titlecase }}
- settings {{ 'SETTINGS' | translate }}
+ settings {{ 'SETTINGS' | translate | titlecase }}
@@ -113,28 +113,28 @@
@@ -143,7 +143,7 @@
#squashedDisplayButton
(click)="openDisplayModeSelector()"
class="squashed-display-button"
- matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate }}"
+ matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate | titlecase }}"
matTooltipPosition="above">
@if (state.blank) {
videocam_off
@@ -164,7 +164,7 @@
class="displayButton"
[class.active]="state.blank"
[disabled]="state.blank"
- matTooltip="{{ 'SHOW_BLACK' | translate }}"
+ matTooltip="{{ 'SHOW_BLACK' | translate | titlecase }}"
matTooltipPosition="above">
videocam_off
@@ -174,7 +174,7 @@
class="displayButton"
[class.active]="state.theme"
[disabled]="state.theme"
- matTooltip="{{ 'SHOW_BACKGROUND' | translate }}"
+ matTooltip="{{ 'SHOW_BACKGROUND' | translate | titlecase }}"
matTooltipPosition="above">
wallpaper
@@ -184,7 +184,7 @@
class="displayButton"
[class.active]="state.display"
[disabled]="state.display"
- matTooltip="{{ 'SHOW_DESKTOP' | translate }}"
+ matTooltip="{{ 'SHOW_DESKTOP' | translate | titlecase }}"
matTooltipPosition="above">
desktop_windows
@@ -194,7 +194,7 @@
class="displayButton"
[class.active]="state.display"
[disabled]="state.live()"
- matTooltip="{{ 'SHOW_PRESENTATION' | translate }}"
+ matTooltip="{{ 'SHOW_PRESENTATION' | translate | titlecase }}"
matTooltipPosition="above">
videocam
@@ -203,26 +203,26 @@
@@ -231,7 +231,7 @@
#squashedDisplayButton
(click)="openDisplayModeSelector()"
class="squashed-display-button"
- matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate }}"
+ matTooltip="{{ 'CHANGE_DISPLAY_MODE' | translate | titlecase }}"
matTooltipPosition="above">
@if (state.blank) {
videocam_off
@@ -251,7 +251,7 @@
class="displayButton"
[class.active]="state.blank"
[disabled]="state.blank"
- matTooltip="{{ 'SHOW_BLACK' | translate }}"
+ matTooltip="{{ 'SHOW_BLACK' | translate | titlecase }}"
matTooltipPosition="above">
videocam_off
@@ -261,7 +261,7 @@
class="displayButton"
[class.active]="state.theme"
[disabled]="state.theme"
- matTooltip="{{ 'SHOW_BACKGROUND' | translate }}"
+ matTooltip="{{ 'SHOW_BACKGROUND' | translate | titlecase }}"
matTooltipPosition="above">
wallpaper
@@ -270,7 +270,7 @@
class="displayButton"
[class.active]="state.display"
[disabled]="state.display"
- matTooltip="{{ 'SHOW_DESKTOP' | translate }}"
+ matTooltip="{{ 'SHOW_DESKTOP' | translate | titlecase }}"
matTooltipPosition="above">
desktop_windows
@@ -279,7 +279,7 @@
class="displayButton"
[class.active]="state.display"
[disabled]="state.live()"
- matTooltip="{{ 'SHOW_PRESENTATION' | translate }}"
+ matTooltip="{{ 'SHOW_PRESENTATION' | translate | titlecase }}"
matTooltipPosition="above">
videocam
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 98890b3..a9d1191 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -13,7 +13,7 @@ import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { DisplayModeSelectorComponent } from './components/display-mode-selector/display-mode-selector.component';
import { Shortcuts, ShortcutsService } from './shortcuts.service';
-import { ShortcutPipe } from './components/shortcuts/shortcut.pipe';
+import { ShortcutPipe } from './components/pipes/shortcut.pipe';
import { SettingsService } from './settings.service';
import * as supportedBrowsers from '../assets/supportedBrowsers';
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f6f9613..79a8bce 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,6 +3,7 @@ import { BrowserModule, Title } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
+import { TitleCasePipe } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
@@ -38,9 +39,9 @@ import { SearchOptionsComponent } from './components/search/search-options/searc
import { SlidesComponent } from './components/slides/slides.component';
import { ChordViewComponent } from './components/chord-view/chord-view.component';
import { StageViewComponent } from './components/stage-view/stage-view.component';
-import { Nl2BrPipe } from './components/stage-view/nl2br.pipe';
+import { Nl2BrPipe } from './components/pipes/nl2br.pipe';
import { MainViewComponent } from './components/main-view/main-view.component';
-import { ChordProPipe } from './components/chord-view/chordpro.pipe';
+import { ChordProPipe } from './components/pipes/chordpro.pipe';
import { LoginComponent } from './components/login/login.component';
import { ThemesComponent } from './components/themes/themes.component';
import { SlideListComponent } from './components/slides/slide-list/slide-list.component';
@@ -50,6 +51,7 @@ import { ServiceListComponent } from './components/service/service-list/service-
import { ChordViewItemComponent } from './components/chord-view/chord-view-item/chord-view-item.component';
import { StageViewItemComponent } from './components/stage-view/stage-view-item/stage-view-item.component';
import { DisplayModeSelectorComponent } from './components/display-mode-selector/display-mode-selector.component';
+import { SentenceCasePipe } from './components/pipes/sentence-case.pipe';
import { SettingsComponent } from './components/settings/settings.component';
import { StageChordPreviewComponent } from './components/settings/stage-chord-preview/stage-chord-preview.component';
@@ -70,6 +72,7 @@ import { StageChordPreviewComponent } from './components/settings/stage-chord-pr
AlertComponent,
SearchComponent,
SearchOptionsComponent,
+ SentenceCasePipe,
SlidesComponent,
SlideListComponent,
SlideItemComponent,
@@ -113,7 +116,9 @@ import { StageChordPreviewComponent } from './components/settings/stage-chord-pr
PageTitleService,
OpenLPService,
TranslationService,
+ SentenceCasePipe,
Title,
+ TitleCasePipe,
WindowRef
],
bootstrap: [AppComponent]
diff --git a/src/app/components/alert/alert.component.html b/src/app/components/alert/alert.component.html
index 7600af9..04f7b80 100644
--- a/src/app/components/alert/alert.component.html
+++ b/src/app/components/alert/alert.component.html
@@ -1,4 +1,4 @@
-
{{ 'SEND_AN_ALERT' | translate }}
+{{ 'SEND_AN_ALERT' | translate | sentencecase }}
diff --git a/src/app/components/alert/alert.component.ts b/src/app/components/alert/alert.component.ts
index 714c76f..0652a95 100644
--- a/src/app/components/alert/alert.component.ts
+++ b/src/app/components/alert/alert.component.ts
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
+import { TitleCasePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core';
import { PageTitleService } from '../../page-title.service';
@@ -21,12 +22,13 @@ export class AlertComponent {
private pageTitleService: PageTitleService,
private openlpService: OpenLPService,
private snackBar: MatSnackBar,
+ private titleCasePipe: TitleCasePipe,
private translateService: TranslateService) {
this.translateService.stream('ALERTS').subscribe(res => {
this.pageTitleService.changePageTitle(res);
});
this.translateService.stream('ALERT_SUBMITTED').subscribe(res => {
- this.alertMessage = res;
+ this.alertMessage = this.titleCasePipe.transform(res);
});
}
diff --git a/src/app/components/chord-view/chord-view.component.html b/src/app/components/chord-view/chord-view.component.html
index c4328e2..898349d 100644
--- a/src/app/components/chord-view/chord-view.component.html
+++ b/src/app/components/chord-view/chord-view.component.html
@@ -45,7 +45,7 @@
mat-mini-fab color=""
class="back-button"
routerLink="/"
- matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate }}">
+ matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate | titlecase }}">
arrow_back
}
@@ -65,7 +65,7 @@
@if (!embedded && activeSlide+1 === currentSlides.length) {
+ matTooltip="{{ 'NEXT_ITEM' | translate | titlecase }}">
{{ nextServiceItemTitle }}
}
diff --git a/src/app/components/display-mode-selector/display-mode-selector.component.html b/src/app/components/display-mode-selector/display-mode-selector.component.html
index ccf1a63..bebf5e6 100644
--- a/src/app/components/display-mode-selector/display-mode-selector.component.html
+++ b/src/app/components/display-mode-selector/display-mode-selector.component.html
@@ -13,7 +13,7 @@
- {{ 'SHOW_BLACK' | translate }}
+ {{ 'SHOW_BLACK' | translate | titlecase }}
- {{ 'SHOW_BACKGROUND' | translate }}
+ {{ 'SHOW_BACKGROUND' | translate | titlecase }}
- {{ 'SHOW_DESKTOP' | translate }}
+ {{ 'SHOW_DESKTOP' | translate | titlecase }}
- {{ 'SHOW_PRESENTATION' | translate }}
+ {{ 'SHOW_PRESENTATION' | translate | titlecase }}
}
@@ -65,7 +65,7 @@
(click)="setMode(displayMode.Blank)"
[disabled]="display.displayMode === displayMode.Blank">
videocam_off
- {{ 'SHOW_BLACK' | translate }}
+ {{ 'SHOW_BLACK' | translate | titlecase }}
}
diff --git a/src/app/components/login/login.component.html b/src/app/components/login/login.component.html
index 01a094b..3e8df68 100644
--- a/src/app/components/login/login.component.html
+++ b/src/app/components/login/login.component.html
@@ -1,11 +1,11 @@
-{{ 'LOGIN' | translate }}
+{{ 'LOGIN' | translate | titlecase }}
diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts
index d4369cc..e6f890b 100644
--- a/src/app/components/login/login.component.ts
+++ b/src/app/components/login/login.component.ts
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
+import { TitleCasePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core';
import { OpenLPService } from '../../openlp.service';
@@ -20,12 +21,13 @@ export class LoginComponent {
private dialogRef: MatDialogRef,
private openlpService: OpenLPService,
private snackBar: MatSnackBar,
+ private titleCasePipe: TitleCasePipe,
private translateService: TranslateService) {
this.translateService.stream('LOGIN_SUCCEEDED').subscribe(res => {
- this.loginSucceededMessage = res;
+ this.loginSucceededMessage = this.titleCasePipe.transform(res);
});
this.translateService.stream('LOGIN_FAILED').subscribe(res => {
- this.loginFailedMessage = res;
+ this.loginFailedMessage = this.titleCasePipe.transform(res);
});
}
diff --git a/src/app/components/chord-view/chordpro.pipe.ts b/src/app/components/pipes/chordpro.pipe.ts
similarity index 100%
rename from src/app/components/chord-view/chordpro.pipe.ts
rename to src/app/components/pipes/chordpro.pipe.ts
diff --git a/src/app/components/stage-view/nl2br.pipe.ts b/src/app/components/pipes/nl2br.pipe.ts
similarity index 91%
rename from src/app/components/stage-view/nl2br.pipe.ts
rename to src/app/components/pipes/nl2br.pipe.ts
index 908a199..900ce3c 100644
--- a/src/app/components/stage-view/nl2br.pipe.ts
+++ b/src/app/components/pipes/nl2br.pipe.ts
@@ -5,7 +5,7 @@ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
export class Nl2BrPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
- transform(value: string): string|SafeHtml {
+ transform(value: string): string | SafeHtml {
if (!value) {
return value;
}
diff --git a/src/app/components/pipes/sentence-case.pipe.ts b/src/app/components/pipes/sentence-case.pipe.ts
new file mode 100644
index 0000000..5f8e539
--- /dev/null
+++ b/src/app/components/pipes/sentence-case.pipe.ts
@@ -0,0 +1,17 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({name: 'sentencecase'})
+export class SentenceCasePipe implements PipeTransform {
+ transform(value: string): string {
+ if (!value) {
+ return value;
+ }
+ if (typeof value !== 'string') {
+ throw Error(`Invalid pipe argument: '${value}' for pipe 'SentenceCasePipe'`);
+ }
+ const sentenceEndMarker: string = '. '
+ return value.split(sentenceEndMarker).map(
+ (sentence) => sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1).toLowerCase()
+ ).join(sentenceEndMarker);
+ }
+}
diff --git a/src/app/components/shortcuts/shortcut.pipe.ts b/src/app/components/pipes/shortcut.pipe.ts
similarity index 100%
rename from src/app/components/shortcuts/shortcut.pipe.ts
rename to src/app/components/pipes/shortcut.pipe.ts
diff --git a/src/app/components/search/search-options/search-options.component.ts b/src/app/components/search/search-options/search-options.component.ts
index dfb1ce5..c6a65f1 100644
--- a/src/app/components/search/search-options/search-options.component.ts
+++ b/src/app/components/search/search-options/search-options.component.ts
@@ -1,4 +1,5 @@
import { Component } from '@angular/core';
+import { TitleCasePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core';
import { OpenLPService } from '../../../openlp.service';
@@ -17,6 +18,7 @@ export class SearchOptionsComponent {
constructor(
private openlpService: OpenLPService,
+ private titleCasePipe: TitleCasePipe,
private translateService: TranslateService) { }
// Used to display search-options for certain plugins
@@ -24,7 +26,7 @@ export class SearchOptionsComponent {
this.selectedPlugin = plugin;
if (this.selectedPlugin === 'bibles') {
this.translateService.stream('BIBLE_VERSION').subscribe(res => {
- this.searchOptionsTitle = res + ':';
+ this.searchOptionsTitle = this.titleCasePipe.transform(res) + ':';
});
this.getSearchOptions();
}
diff --git a/src/app/components/search/search.component.html b/src/app/components/search/search.component.html
index 946b6d5..1d43671 100644
--- a/src/app/components/search/search.component.html
+++ b/src/app/components/search/search.component.html
@@ -1,4 +1,4 @@
-{{ 'SEARCH' | translate }}
+{{ 'SEARCH' | translate | titlecase }}
@if (searchResults) {
-
{{ 'SEARCH_RESULTS' | translate }}:
+
{{ 'SEARCH_RESULTS' | translate | titlecase }}:
@if (searchResults.length) {
@for (item of searchResults; track item) {
@@ -49,14 +49,14 @@
|
@@ -65,7 +65,7 @@
}
@else {
- {{ 'NO_SEARCH_RESULTS' | translate }}...
+ {{ 'NO_SEARCH_RESULTS' | translate | sentencecase }}...
}
diff --git a/src/app/components/service/service-list/service-list.component.html b/src/app/components/service/service-list/service-list.component.html
index d92f8f5..fa4323c 100644
--- a/src/app/components/service/service-list/service-list.component.html
+++ b/src/app/components/service/service-list/service-list.component.html
@@ -14,7 +14,7 @@
info
- {{ 'NO_SERVICE_ITEMS' | translate }}.
+ {{ 'NO_SERVICE_ITEMS' | translate | sentencecase }}.
diff --git a/src/app/components/service/service-list/service-list.component.ts b/src/app/components/service/service-list/service-list.component.ts
index 58b9c7d..8b0c1a1 100644
--- a/src/app/components/service/service-list/service-list.component.ts
+++ b/src/app/components/service/service-list/service-list.component.ts
@@ -7,7 +7,7 @@ import { ServiceItem } from '../../../responses';
@Component({
selector: 'openlp-service-list',
templateUrl: './service-list.component.html',
- styleUrls: ['./service-list.component.scss', '../../no-items.scss'],
+ styleUrls: ['./service-list.component.scss', '../../no-items.scss']
})
export class ServiceListComponent implements OnInit, OnDestroy {
diff --git a/src/app/components/settings/settings.component.html b/src/app/components/settings/settings.component.html
index 7fcb8ee..7aff63f 100644
--- a/src/app/components/settings/settings.component.html
+++ b/src/app/components/settings/settings.component.html
@@ -1,7 +1,7 @@
- {{ 'USER_INTERFACE' | translate }}
+ {{ 'USER_INTERFACE' | translate | titlecase }}
@@ -9,7 +9,7 @@
color="primary"
[checked]="settings.fastSwitching"
(change)="setSetting('fastSwitching', $event.checked)">
- {{ 'ENABLE_FAST_SWITCHING_PANEL' | translate }}
+ {{ 'ENABLE_FAST_SWITCHING_PANEL' | translate | sentencecase }}
@@ -17,18 +17,18 @@
color="primary"
[checked]="settings.bigDisplayButtons"
(change)="setSetting('bigDisplayButtons', $event.checked)">
- {{ 'ENABLE_BIG_DISPLAY_BUTTONS' | translate }}
+ {{ 'ENABLE_BIG_DISPLAY_BUTTONS' | translate | sentencecase }}
- {{ 'STAGE_AND_CHORDS_APPEARANCE' | translate }}
+ {{ 'STAGE_AND_CHORDS_APPEARANCE' | translate | sentencecase }}
-
+
@@ -38,7 +38,7 @@
-
+
@@ -55,7 +55,7 @@
let-prefix="prefix">
-
+
info
- {{ 'NO_SLIDE_ITEMS' | translate }}.
+ {{ 'NO_SLIDE_ITEMS' | translate | sentencecase }}.
diff --git a/src/app/components/stage-view/stage-view.component.html b/src/app/components/stage-view/stage-view.component.html
index 9a16951..23e71ab 100644
--- a/src/app/components/stage-view/stage-view.component.html
+++ b/src/app/components/stage-view/stage-view.component.html
@@ -27,7 +27,7 @@
class="back-button"
mat-mini-fab color=""
routerLink="/"
- matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate }}">
+ matTooltip="{{ 'GO_BACK_TO_CONTROLLER' | translate | titlecase }}">
arrow_back
}
@@ -35,7 +35,7 @@