From e232ab2e3aefa6b400c40260980dfe307eaf98d3 Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Fri, 8 Mar 2024 21:37:17 -0600 Subject: [PATCH] Fix: Dark theme details and auto detection --- .../clients-view/clients-view.component.scss | 1 - src/app/clients/clients.component.scss | 4 - .../view-bulk-import.component.scss | 5 - .../view-scheduler-job.component.html | 2 +- .../view-scheduler-job.component.scss | 6 +- .../theme-toggle/theme-toggle.component.html | 4 +- .../theme-toggle/theme-toggle.component.ts | 24 ++- src/app/theme-toggle/theming.service.ts | 51 +++++ src/app/theme.service.spec.ts | 16 -- src/app/theme.service.ts | 21 -- src/app/web-app.component.ts | 10 +- src/theme/_content.scss | 16 ++ src/theme/_dark_content.scss | 183 ++++++++++++++++++ src/theme/mifosx-theme.scss | 41 +--- 14 files changed, 287 insertions(+), 97 deletions(-) create mode 100644 src/app/theme-toggle/theming.service.ts delete mode 100644 src/app/theme.service.spec.ts delete mode 100644 src/app/theme.service.ts create mode 100644 src/theme/_dark_content.scss diff --git a/src/app/clients/clients-view/clients-view.component.scss b/src/app/clients/clients-view/clients-view.component.scss index c248d019a..12b402f91 100644 --- a/src/app/clients/clients-view/clients-view.component.scss +++ b/src/app/clients/clients-view/clients-view.component.scss @@ -8,7 +8,6 @@ line-height: 25px; } .signature { - background-color: #0a6aac; color: white; text-align: center; margin: 0; diff --git a/src/app/clients/clients.component.scss b/src/app/clients/clients.component.scss index 76043013c..fddd262cb 100644 --- a/src/app/clients/clients.component.scss +++ b/src/app/clients/clients.component.scss @@ -22,7 +22,3 @@ table { color : black; } } - -.status { - color: black; -} diff --git a/src/app/organization/bulk-import/view-bulk-import/view-bulk-import.component.scss b/src/app/organization/bulk-import/view-bulk-import/view-bulk-import.component.scss index 268a0c346..b47a2ac2a 100644 --- a/src/app/organization/bulk-import/view-bulk-import/view-bulk-import.component.scss +++ b/src/app/organization/bulk-import/view-bulk-import/view-bulk-import.component.scss @@ -6,11 +6,6 @@ margin: 0; } -.cover { - background-color: #f2f2f2; - margin-top: 1%; -} - h4 { font-weight: 400; margin: 1% 0; diff --git a/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.html b/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.html index c1ea174fc..be956b8dd 100644 --- a/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.html +++ b/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.html @@ -37,7 +37,7 @@
- {{ jobData.active }} + {{ jobData.active | yesNo }}
diff --git a/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.scss b/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.scss index 1274158b6..ca6975790 100644 --- a/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.scss +++ b/src/app/system/manage-jobs/scheduler-jobs/view-scheduler-job/view-scheduler-job.component.scss @@ -1,7 +1,3 @@ -a{ - color: blue; -} - .container { max-width: 37rem; @@ -11,4 +7,4 @@ a{ word-wrap: break-word; } } -} +} \ No newline at end of file diff --git a/src/app/theme-toggle/theme-toggle.component.html b/src/app/theme-toggle/theme-toggle.component.html index badec94b5..b9d2ab195 100644 --- a/src/app/theme-toggle/theme-toggle.component.html +++ b/src/app/theme-toggle/theme-toggle.component.html @@ -1,3 +1,3 @@ - diff --git a/src/app/theme-toggle/theme-toggle.component.ts b/src/app/theme-toggle/theme-toggle.component.ts index 13b0a5002..8055e06b1 100644 --- a/src/app/theme-toggle/theme-toggle.component.ts +++ b/src/app/theme-toggle/theme-toggle.component.ts @@ -1,20 +1,28 @@ -import { Component } from '@angular/core'; -import { ThemeService } from '../theme.service'; +import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { ThemingService } from './theming.service'; @Component({ selector: 'theme-toggle-component', templateUrl: './theme-toggle.component.html', styleUrls: ['./theme-toggle.component.scss'], }) -export class ThemeToggleComponent { - isDarkMode: boolean; +export class ThemeToggleComponent implements OnInit, OnChanges { + darkModeOn: boolean; - constructor(private themeService: ThemeService) { - this.isDarkMode = this.themeService.isDarkMode(); + constructor(private themingService: ThemingService) { + this.darkModeOn = this.themingService.isDarkMode(); + } + + ngOnInit(): void { + this.darkModeOn = this.themingService.isDarkMode(); + } + + ngOnChanges(changes: SimpleChanges): void { + this.darkModeOn = this.themingService.isDarkMode(); } toggleTheme() { - this.isDarkMode = !this.isDarkMode; - this.themeService.setDarkMode(this.isDarkMode); + this.darkModeOn = !this.darkModeOn; + this.themingService.setDarkMode(this.darkModeOn); } } diff --git a/src/app/theme-toggle/theming.service.ts b/src/app/theme-toggle/theming.service.ts new file mode 100644 index 000000000..61104ff29 --- /dev/null +++ b/src/app/theme-toggle/theming.service.ts @@ -0,0 +1,51 @@ +import { ApplicationRef, Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class ThemingService { + private darkModeOn = false; + + themes = ["dark-theme", "light-theme"]; // <- list all themes in this array + theme = new BehaviorSubject("light-theme"); // <- initial theme + + constructor(private ref: ApplicationRef) { + // Initially check if dark mode is enabled on system + this.darkModeOn = + window.matchMedia && + window.matchMedia("(prefers-color-scheme: dark)").matches; + + // If dark mode is enabled then directly switch to the dark-theme + if(this.darkModeOn){ + this.theme.next("dark-theme"); + } + + // Watch for changes of the preference + window.matchMedia("(prefers-color-scheme: dark)").addListener(e => { + const turnOn = e.matches; + this.theme.next(turnOn ? "dark-theme" : "light-theme"); + + // Trigger refresh of UI + this.ref.tick(); + }); + } + + isDarkMode(): boolean { + this.darkModeOn = + window.matchMedia && + window.matchMedia("(prefers-color-scheme: dark)").matches; + return this.darkModeOn; + } + + setDarkMode(isDarkMode: boolean) { + this.darkModeOn = isDarkMode; + if (isDarkMode) { + document.body.classList.add('dark-theme'); + this.theme.next("dark-theme"); + } else { + document.body.classList.remove('dark-theme'); + this.theme.next("light-theme"); + } + } +} diff --git a/src/app/theme.service.spec.ts b/src/app/theme.service.spec.ts deleted file mode 100644 index 1c2957ba8..000000000 --- a/src/app/theme.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { ThemeService } from './theme.service'; - -describe('ThemeService', () => { - let service: ThemeService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ThemeService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/theme.service.ts b/src/app/theme.service.ts deleted file mode 100644 index 1189e722c..000000000 --- a/src/app/theme.service.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable({ - providedIn: 'root', -}) -export class ThemeService { - private darkMode = false; - - isDarkMode() { - return this.darkMode; - } - - setDarkMode(isDarkMode: boolean) { - this.darkMode = isDarkMode; - if (isDarkMode) { - document.body.classList.add('dark-theme'); - } else { - document.body.classList.remove('dark-theme'); - } - } -} diff --git a/src/app/web-app.component.ts b/src/app/web-app.component.ts index 48b3c28b9..5fb5005c7 100644 --- a/src/app/web-app.component.ts +++ b/src/app/web-app.component.ts @@ -1,5 +1,5 @@ /** Angular Imports */ -import { Component, OnInit, HostListener } from '@angular/core'; +import { Component, OnInit, HostListener, HostBinding } from '@angular/core'; import { Router, NavigationEnd, ActivatedRoute } from '@angular/router'; import { Title } from '@angular/platform-browser'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -27,6 +27,7 @@ import { KeyboardShortcutsConfiguration } from './keyboards-shortcut-config'; import { Dates } from './core/utils/dates'; import { animate, style, transition, trigger } from '@angular/animations'; import { I18nService } from './core/i18n/i18n.service'; +import { ThemingService } from './theme-toggle/theming.service'; /** Initialize Logger */ const log = new Logger('MifosX'); @@ -104,8 +105,11 @@ export class WebAppComponent implements OnInit { private alertService: AlertService, private settingsService: SettingsService, private authenticationService: AuthenticationService, + private themingService: ThemingService, private dateUtils: Dates) { } + @HostBinding('class') public cssClass: string; + /** * Initial Setup: * @@ -120,6 +124,10 @@ export class WebAppComponent implements OnInit { * 5) Alerts */ ngOnInit() { + this.themingService.theme.subscribe((theme: string) => { + this.cssClass = theme; + }); + // Setup logger if (environment.production) { Logger.enableProductionMode(); diff --git a/src/theme/_content.scss b/src/theme/_content.scss index dbf00b609..97c741018 100644 --- a/src/theme/_content.scss +++ b/src/theme/_content.scss @@ -3,6 +3,19 @@ @mixin account-view-component-theme($theme) { $primary: map-get($theme, primary); + mifosx-view-bulk-import { + .cover { + background-color: white; + margin-top: 1%; + } + } + + mifosx-clients { + .status { + color: black; + } + } + mifosx-clients-view, mifosx-fixed-deposit-account-view, mifosx-loans-view, @@ -42,6 +55,9 @@ object-fit: cover; border-radius: 20px; } + .signature { + background-color: mat.get-color-from-palette($primary, 500); + } } .account-actions { align-self: flex-end; diff --git a/src/theme/_dark_content.scss b/src/theme/_dark_content.scss new file mode 100644 index 000000000..6bb85ae22 --- /dev/null +++ b/src/theme/_dark_content.scss @@ -0,0 +1,183 @@ +@use "@angular/material" as mat; + + +@mixin account-view-component-dark-theme($theme) { + $primary: map-get($theme, primary); + + mifosx-view-bulk-import { + .cover { + background-color: #424242; + margin-top: 1%; + } + } + + mifosx-clients { + .status { + color: white; + } + } + + mifosx-clients-view, + mifosx-fixed-deposit-account-view, + mifosx-loans-view, + mifosx-recurring-deposits-account-view, + mifosx-savings-account-view { + .account-card { + margin: 0 auto; + max-width: 80rem; + width: 90%; + padding: 0; + + .header { + background-color: mat.get-color-from-palette($primary, 500); + + padding: 1%; + + .header-title-group { + .account-card-title { + color: white; + width: 90%; + + p { + color: white; + } + + .account-overview { + border: none; + max-width: 240px; + font-size: 14px; + + tr:nth-child(even) { + background-color: transparent; + } + } + } + } + + .profile-image-container { + margin: 1%; + + .profile-image { + object-fit: cover; + border-radius: 20px; + } + + .signature { + background-color: mat.get-color-from-palette($primary, 500); + } + } + + .account-actions { + align-self: flex-end; + margin: 0 1%; + + i { + margin-bottom: 2px; + margin-right: 4px; + } + } + } + + .navigation-tabs { + background-color: #303135; + color: white; + overflow: auto; + } + + .content { + .savings-account-tables { + padding: 1%; + margin: 1%; + + .table-headers { + margin: 0; + padding: 6px; + } + + td { + padding: 3px; + } + } + } + + i, + img:hover { + cursor: pointer; + } + } + } +} + +.dark-theme { + + // Override the background color of the label text for dark theme + .mat-option-text, + .mat-input-element, + .mat-form-field-label { + color: white !important; + } + + mifosx-popover, + .mat-menu-content, + .mat-dialog-container { + background-color: #303135; + color: white; + } + + // Override the background color of the calendar for dark theme + .mat-calendar, + .mat-calendar-body-cell, + .mat-calendar-body-label, + .mat-calendar-table, + .mat-list-item.active { + background-color: #303135; + border: none; + } + + .mat-tab-label-active { + border-bottom: lightgray; + } + + // Changing the logo color for dark mode + .img-button, + .app-user-photo, + .profile-image { + filter: invert(100%); + } + + span.breadcrumb-link { + a { + color: #0098ff !important; + } + } + + a:-webkit-any-link { + color: #0098ff !important; + } + + div.alert { + color: #303135; + } + + a.tab-link { + color: white !important; + } + + .cdk-drag-preview { + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); + display: table; + background-color: white; + color: #303135; + } + + #footer { + .business-date { + color: #0098ff; + } + } + +} diff --git a/src/theme/mifosx-theme.scss b/src/theme/mifosx-theme.scss index 563d79f3e..2e7ec9cef 100644 --- a/src/theme/mifosx-theme.scss +++ b/src/theme/mifosx-theme.scss @@ -9,6 +9,7 @@ @import '../app/home/dashboard/dashboard.component-theme.scss'; @import '../app/shares/shares-account-view/shares-account-view.component-theme.scss'; @import 'content'; +@import 'dark_content'; // Include the common styles for Angular Material. We include this here so that you only // have to load a single css file for Angular Material in your app. @@ -23,10 +24,10 @@ // (imported above). For each palette, you can optionally specify a default, lighter, and darker // hue. Available color palettes: https://material.io/design/color/ $mifosx-app-primary: mat.define-palette($primary-palette); -$mifosx-app-accent: mat.define-palette($accent-palette); +$mifosx-app-accent: mat.define-palette($accent-palette); // The warn palette is optional (defaults to red). -$mifosx-app-warn: mat.define-palette(mat.$red-palette); +$mifosx-app-warn: mat.define-palette(mat.$red-palette); // Create the theme object (a Sass map containing all of the palettes). $mifosx-app-theme: mat.define-light-theme($mifosx-app-primary, $mifosx-app-accent, $mifosx-app-warn); @@ -46,45 +47,19 @@ $mifosx-app-theme: mat.define-light-theme($mifosx-app-primary, $mifosx-app-accen // Define the palettes for your theme using the Material Design palettes available in palette.scss -$mifosx-app-dark-primary: mat.define-palette($dark-primary-palette); -$mifosx-app-dark-accent: mat.define-palette($dark-accent-palette); -$mifosx-app-dark-warn: mat.define-palette(mat.$red-palette); +$mifosx-app-dark-primary: mat.define-palette($dark-primary-palette); +$mifosx-app-dark-accent: mat.define-palette($dark-accent-palette); +$mifosx-app-dark-warn: mat.define-palette(mat.$red-palette); // Create the theme object (a Sass map containing all of the palettes). $mifosx-app-dark-theme: mat.define-dark-theme($mifosx-app-dark-primary, $mifosx-app-dark-accent, $mifosx-app-dark-warn); // Include theme styles for core and each component used in your app. .dark-theme { - - // Override the background color of the label text for dark theme - .mat-option-text,.mat-input-element,.mat-form-field-label{ - color: white !important; - } - mifosx-popover,.mat-menu-content{ - background-color: #303135; - color : white; - } - - // Override the background color of the calendar for dark theme - .mat-calendar, - .mat-calendar-body-cell, - .mat-calendar-body-label, - .mat-calendar-table{ - background-color: #303135; - border: none; - } - - // Changing the logo color for dark mode - .img-button, - .app-user-photo, - .profile-image{ - filter: invert(100%); - } - @include mat.all-component-themes($mifosx-app-dark-theme); @include groups-view-component-theme($mifosx-app-dark-theme); @include centers-view-component-theme($mifosx-app-dark-theme); @include dashboard-component-theme($mifosx-app-dark-theme); @include shares-account-view-component-theme($mifosx-app-dark-theme); - @include account-view-component-theme($mifosx-app-dark-theme); -} \ No newline at end of file + @include account-view-component-dark-theme($mifosx-app-dark-theme); +}