diff --git a/frontend/package.json b/frontend/package.json index aa63237bb..ce17df68d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,11 +18,12 @@ "@angular/compiler": "^18.0.2", "@angular/core": "^18.0.2", "@angular/forms": "^18.0.2", - "@angular/material-moment-adapter": "^18.0.2", + "@angular/material-moment-adapter": "^18.2.7", "@angular/platform-browser": "^18.0.2", "@kolkov/angular-editor": "^2.1.0", "@mat-datetimepicker/core": "^13.0.2", "@mat-datetimepicker/moment": "^13.0.2", + "@material/material-color-utilities": "^0.3.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", "@swimlane/ngx-datatable": "^20.1.0", @@ -53,11 +54,11 @@ }, "devDependencies": { "@angular-devkit/build-angular": "^18.0.3", - "@angular/cdk": "^18.0.2", + "@angular/cdk": "^18.2.7", "@angular/cli": "18.0.3", "@angular/compiler-cli": "^18.0.2", "@angular/language-service": "^18.0.2", - "@angular/material": "^18.0.2", + "@angular/material": "^18.2.7", "@angular/platform-browser-dynamic": "^18.0.2", "@angular/router": "^18.0.2", "@types/dragula": "^3.7.5", diff --git a/frontend/src/app/core/model/tenant-configuaration/tenant-configuration.ts b/frontend/src/app/core/model/tenant-configuaration/tenant-configuration.ts index 3c3f2b745..0e9630a5b 100644 --- a/frontend/src/app/core/model/tenant-configuaration/tenant-configuration.ts +++ b/frontend/src/app/core/model/tenant-configuaration/tenant-configuration.ts @@ -14,9 +14,7 @@ export interface TenantConfiguration extends BaseEntity{ export interface CssColorsTenantConfiguration{ primaryColor: string; - primaryColor2: string; - primaryColor3: string; - secondaryColor: string; + cssOverride: string; } export interface DefaultUserLocaleTenantConfiguration{ @@ -70,13 +68,7 @@ export interface TenantConfigurationPersist extends BaseEntityPersist{ export interface CssColorsTenantConfigurationPersist{ primaryColor: string; - primaryColor2: string; - primaryColor3: string; - secondaryColor: string; - primaryText?: string; - secondaryText?: string; - invertedBtnColor?: string; - warningColor?: string; + cssOverride: string; } export interface DefaultUserLocaleTenantConfigurationPersist{ diff --git a/frontend/src/app/core/services/configuration/configuration.service.ts b/frontend/src/app/core/services/configuration/configuration.service.ts index 8aadf0737..009708683 100644 --- a/frontend/src/app/core/services/configuration/configuration.service.ts +++ b/frontend/src/app/core/services/configuration/configuration.service.ts @@ -294,9 +294,7 @@ export class ConfigurationService extends BaseComponent { if (config.defaultCssColors) { this._cssColorsTenantConfiguration = { primaryColor: config.defaultCssColors.primaryColor, - primaryColor2: config.defaultCssColors.primaryColor2, - primaryColor3: config.defaultCssColors.primaryColor3, - secondaryColor: config.defaultCssColors.secondaryColor, + cssOverride: config.defaultCssColors.cssOverride } } } diff --git a/frontend/src/app/core/services/tenant/tenant-handling.service.ts b/frontend/src/app/core/services/tenant/tenant-handling.service.ts index c47cb718c..9f7635748 100644 --- a/frontend/src/app/core/services/tenant/tenant-handling.service.ts +++ b/frontend/src/app/core/services/tenant/tenant-handling.service.ts @@ -7,6 +7,7 @@ import { BaseService } from '@common/base/base.service'; import { Observable, takeUntil } from 'rxjs'; import { nameof } from 'ts-simple-nameof'; import { TenantConfigurationService } from '../tenant-configuration/tenant-configuration.service'; +import { generateDynamicTheme, overrideCss } from '@app/ui/misc/theme-helper'; @Injectable() export class TenantHandlingService extends BaseService { @@ -74,24 +75,19 @@ export class TenantHandlingService extends BaseService { return this.tenantConfigurationService.getCurrentTenantType(TenantConfigurationType.CssColors, [ nameof(x => x.type), [nameof(x => x.cssColors), nameof(x => x.primaryColor)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.primaryColor2)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.primaryColor3)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.secondaryColor)].join('.'), + [nameof(x => x.cssColors), nameof(x => x.cssOverride)].join('.') ]); } public applyTenantCssColors(cssColors: CssColorsTenantConfiguration) { if (cssColors) { - if (cssColors.primaryColor) document.documentElement.style.setProperty(`--primary-color`, cssColors.primaryColor); - if (cssColors.primaryColor2) document.documentElement.style.setProperty(`--link-color`, cssColors.primaryColor2); - if (cssColors.primaryColor3) document.documentElement.style.setProperty(`--draft-color`, cssColors.primaryColor3); - if (cssColors.secondaryColor) document.documentElement.style.setProperty(`--secondary-color`, cssColors.secondaryColor); - if (localStorage.getItem('primaryText')) document.documentElement.style.setProperty(`--primary-text`, localStorage.getItem('primaryText')); - if (localStorage.getItem('secondaryText')) document.documentElement.style.setProperty(`--secondary-text`, localStorage.getItem('secondaryText')); - if (localStorage.getItem('invertedBtnColor')) document.documentElement.style.setProperty(`--inverted-btn-color`, localStorage.getItem('invertedBtnColor')); - - if (localStorage.getItem('warningColor')) document.documentElement.style.setProperty(`--warning-color`, localStorage.getItem('warningColor')); + if (cssColors.primaryColor){ + generateDynamicTheme(cssColors.primaryColor); + } + if (cssColors.cssOverride){ + overrideCss(cssColors.cssOverride); + } } } } \ No newline at end of file diff --git a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.html b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.html index ad3b12826..f4fec2ae7 100644 --- a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.html +++ b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.html @@ -4,137 +4,41 @@
- {{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR' | translate}} - + + {{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR' | translate}} + + - {{formGroup.get('cssColors')?.get('primaryColor')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} + {{cssColorForm?.get('primaryColor')?.getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.SECONDARY-COLOR' | translate}} - - - {{formGroup.get('cssColors')?.get('secondaryColor')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.PRIMARY-COLOR-TEXT' | translate}} - - - {{formGroup.get('cssColors')?.get('primaryText')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.SECONDARY-COLOR-TEXT' | translate}} - - - {{formGroup.get('cssColors')?.get('secondaryText')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.WARNING-COLOR' | translate}} + + + {{'TENANT-CONFIGURATION-EDITOR.FIELDS.CSS-OVERRIDE' | translate}} - - - {{formGroup.get('cssColors')?.get('invertedBtnColor')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - - - info - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.LINK-COLOR' | translate}} - - - - {{formGroup.get('cssColors')?.get('primaryColor2')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - - - info - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.DRAFT-STATUS-COLOR' | translate}} - - - - {{formGroup.get('cssColors')?.get('primaryColor3')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - - - - - - info - - {{'TENANT-CONFIGURATION-EDITOR.FIELDS.INVERTED-BUTTON-COLOR' | translate}} - - - - {{formGroup.get('cssColors')?.get('invertedBtnColor')?.getError('backendError').message}} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - {{'GENERAL.VALIDATION.INVALID-COLOR' | translate}} - + + {{cssColorForm?.get('cssOverride')?.getError('backendError').message}} +
-
-
diff --git a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.scss b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.scss index e6b81ab51..57ed58056 100644 --- a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.scss +++ b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.scss @@ -1,7 +1,8 @@ -.css-colors { - -} ::ng-deep .mat-mdc-form-field-icon-suffix { margin-right: 0.2em; } + +.css-override { + min-height: 5rem; +} \ No newline at end of file diff --git a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.ts b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.ts index 8bb0e0ecc..b32261b34 100644 --- a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.ts +++ b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { UntypedFormGroup } from '@angular/forms'; +import { FormGroup, UntypedFormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { AppPermission } from '@app/core/common/enum/permission.enum'; @@ -10,7 +10,7 @@ import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; -import { TenantConfigurationEditorModel } from './css-colors-editor.model'; +import { CssColorForm, TenantConfigurationEditorModel } from './css-colors-editor.model'; import { TenantConfiguration, TenantConfigurationPersist } from '@app/core/model/tenant-configuaration/tenant-configuration'; import { TenantConfigurationService } from '@app/core/services/tenant-configuration/tenant-configuration.service'; import { CssColorsEditorService } from './css-colors-editor.service'; @@ -21,6 +21,7 @@ import { TenantConfigurationType } from '@app/core/common/enum/tenant-configurat import { HttpErrorResponse } from '@angular/common/http'; import { LoggingService } from '@app/core/services/logging/logging-service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; +import { TenantHandlingService } from '@app/core/services/tenant/tenant-handling.service'; @Component({ @@ -60,7 +61,8 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem private logger: LoggingService, private tenantConfigurationService: TenantConfigurationService, private cssColorsEditorService: CssColorsEditorService, - private analyticsService: AnalyticsService + private analyticsService: AnalyticsService, + private tenantHandlingService: TenantHandlingService ) { super(); } @@ -80,90 +82,21 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem } + get cssColorForm(): FormGroup { + return this.formGroup.get('cssColors') as FormGroup; + } + private bindColorInputs() { - this.formGroup.get('cssColors')?.get('primaryColorInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('primaryColor').setValue(color, { + this.cssColorForm?.get('primaryColorInput').valueChanges.subscribe((color) => { + this.cssColorForm?.get('primaryColor').setValue(color, { emitEvent: false, }); }); - this.formGroup.get('cssColors')?.get('primaryColor').valueChanges.subscribe((color) => - this.formGroup.get('cssColors')?.get('primaryColorInput').setValue(color, { + this.cssColorForm?.get('primaryColor').valueChanges.subscribe((color) => + this.cssColorForm?.get('primaryColorInput').setValue(color, { emitEvent: false, }) ); - this.formGroup.get('cssColors')?.get('primaryColor2Input').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('primaryColor2').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('primaryColor2').valueChanges.subscribe((color) => - this.formGroup.get('cssColors')?.get('primaryColor2Input').setValue(color, { - emitEvent: false, - }) - ); - this.formGroup.get('cssColors')?.get('primaryColor3Input').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('primaryColor3').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('primaryColor3').valueChanges.subscribe((color) => - this.formGroup.get('cssColors')?.get('primaryColor3Input').setValue(color, { - emitEvent: false, - }) - ); - this.formGroup.get('cssColors')?.get('secondaryColorInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('secondaryColor').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('secondaryColor').valueChanges.subscribe((color) => - this.formGroup.get('cssColors')?.get('secondaryColorInput').setValue(color, { - emitEvent: false, - }) - ); - - this.formGroup.get('cssColors')?.get('primaryTextInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('primaryText').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('secondaryTextInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('secondaryText').setValue(color, { - emitEvent: false, - }); - }); - - this.formGroup.get('cssColors')?.get('primaryText').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('primaryTextInput').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('secondaryText').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('secondaryTextInput').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('invertedBtnColor').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('invertedBtnColorInput').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('invertedBtnColorInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('invertedBtnColor').setValue(color, { - emitEvent: false, - }); - }); - - this.formGroup.get('cssColors')?.get('warningColor').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('warningColorInput').setValue(color, { - emitEvent: false, - }); - }); - this.formGroup.get('cssColors')?.get('warningColorInput').valueChanges.subscribe((color) => { - this.formGroup.get('cssColors')?.get('warningColor').setValue(color, { - emitEvent: false, - }); - }); } getItem(successFunction: (item: TenantConfiguration) => void) { @@ -186,10 +119,10 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem } } - onCallbackSuccess(data?: any): void { - + onCallbackSuccess(cssColors?: any): void { this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - this.refreshData(); + this.tenantHandlingService.applyTenantCssColors(cssColors); + this.refreshData(); } @@ -221,16 +154,11 @@ export class CssColorsEditorComponent extends BasePendingChangesComponent implem persistEntity(onSuccess?: (response) => void): void { const formData = this.formService.getValue(this.formGroup.value) as TenantConfigurationPersist; - localStorage.setItem('primaryText', formData?.cssColors?.primaryText); - localStorage.setItem('secondaryText', formData?.cssColors?.secondaryText); - localStorage.setItem('invertedBtnColor', formData?.cssColors?.invertedBtnColor); - localStorage.setItem('warningColor', formData?.cssColors?.warningColor); - - this.tenantConfigurationService.persist(formData) - .pipe(takeUntil(this._destroyed)).subscribe( - complete => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete), - error => this.onCallbackError(error) - ); + this.tenantConfigurationService.persist(formData) + .pipe(takeUntil(this._destroyed)).subscribe({ + next: (complete) => onSuccess ? onSuccess(complete) : this.onCallbackSuccess(formData?.cssColors), + error: (error) => this.onCallbackError(error) + }); } formSubmit(): void { diff --git a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.model.ts b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.model.ts index ccdefee1e..4209e9c6f 100644 --- a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.model.ts +++ b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.model.ts @@ -1,4 +1,4 @@ -import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { FormControl, FormGroup, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { TenantConfigurationType } from "@app/core/common/enum/tenant-configuration-type"; import { CssColorsTenantConfiguration, CssColorsTenantConfigurationPersist, TenantConfiguration, TenantConfigurationPersist } from "@app/core/model/tenant-configuaration/tenant-configuration"; import { BaseEditorModel } from "@common/base/base-form-editor-model"; @@ -54,13 +54,7 @@ export class TenantConfigurationEditorModel extends BaseEditorModel implements T export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantConfigurationPersist { primaryColor: string; - primaryColor2: string; - primaryColor3: string; - secondaryColor: string; - primaryText: string; - secondaryText: string; - invertedBtnColor: string; - warningColor: string; + cssOverride: string; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -71,13 +65,7 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC public fromModel(item: CssColorsTenantConfiguration): CssColorsTenantConfigurationEditorModel { if (item) { this.primaryColor = item.primaryColor; - this.primaryColor2 = item.primaryColor2; - this.primaryColor3 = item.primaryColor3; - this.secondaryColor = item.secondaryColor; - this.primaryText = localStorage.getItem('primaryText') ?? '#ffffff'; - this.secondaryText = localStorage.getItem('secondaryText') ?? '#000000'; - this.invertedBtnColor = localStorage.getItem('invertedBtnColor') ?? '#ffffff'; - this.warningColor = localStorage.getItem('warningColor') ?? '#ff4081'; + this.cssOverride = item.cssOverride } return this; } @@ -86,7 +74,7 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC context?: ValidationContext, disabled?: boolean, rootPath?: string - }): UntypedFormGroup { + }): FormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { context = CssColorsTenantConfigurationEditorModel.createValidationContext({ @@ -97,22 +85,8 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC const form: UntypedFormGroup = this.formBuilder.group({ primaryColor: [{ value: this.primaryColor, disabled: disabled }, context.getValidation('primaryColor').validators], - primaryText: [{ value: this.primaryText, disabled: disabled }, context.getValidation('primaryText').validators], - primaryColor2: [{ value: this.primaryColor2, disabled: disabled }, context.getValidation('primaryColor2').validators], - primaryColor3: [{ value: this.primaryColor3, disabled: disabled }, context.getValidation('primaryColor3').validators], - secondaryColor: [{ value: this.secondaryColor, disabled: disabled }, context.getValidation('secondaryColor').validators], - secondaryText: [{ value: this.secondaryText, disabled: disabled }, context.getValidation('secondaryText').validators], - invertedBtnColor: [{ value: this.invertedBtnColor, disabled: disabled }, context.getValidation('invertedBtnColor').validators], primaryColorInput: [{ value: this.primaryColor, disabled: disabled}, context.getValidation('primaryColorInput').validators ], - primaryColor2Input: [{ value: this.primaryColor2, disabled: disabled}, context.getValidation('primaryColor2Input').validators ], - primaryColor3Input: [{ value: this.primaryColor3, disabled: disabled}, context.getValidation('primaryColor3Input').validators ], - secondaryColorInput: [{ value: this.secondaryColor, disabled: disabled}, context.getValidation('secondaryColorInput').validators ], - secondaryTextInput: [{ value: this.secondaryText, disabled: disabled}, context.getValidation('secondaryTextInput').validators ], - primaryTextInput: [{ value: this.primaryText, disabled: disabled}, context.getValidation('primaryTextInput').validators ], - invertedBtnColorInput: [{ value: this.invertedBtnColor, disabled: disabled}, context.getValidation('invertedBtnColorInput').validators ], - - warningColor: [{ value: this.warningColor, disabled: disabled }, context.getValidation('secondaryText').validators], - warningColorInput: [{ value: this.warningColor, disabled: disabled }, context.getValidation('invertedBtnColor').validators], + cssOverride: [{value: this.cssOverride, disabled: disabled}, context.getValidation('cssOverride').validators] }, { updateOn: "change" }); @@ -129,23 +103,16 @@ export class CssColorsTenantConfigurationEditorModel implements CssColorsTenantC const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'primaryColor', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor`)] }); - baseValidationArray.push({ key: 'primaryColor2', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor2`)] }); - baseValidationArray.push({ key: 'primaryColor3', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColor3`)] }); - baseValidationArray.push({ key: 'secondaryColor', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}secondaryColor`)] }); - baseValidationArray.push({ key: 'primaryText', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}primaryColorText`)] }); - baseValidationArray.push({ key: 'secondaryText', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}secondaryColorText`)] }); - baseValidationArray.push({ key: 'invertedBtnColor', validators: [validColorValidator(), Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}invertedBtnColor`)] }); baseValidationArray.push({ key: 'primaryColorInput', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'primaryColor2Input', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'primaryColor3Input', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'secondaryColorInput', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'primaryTextInput', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'secondaryTextInput', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'invertedBtnColorInput', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'warningColor', validators: [validColorValidator()] }); - baseValidationArray.push({ key: 'warningColorInput', validators: [validColorValidator()] }); + baseValidationArray.push({ key: 'cssOverride', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}cssOverride`)] }); baseContext.validation = baseValidationArray; return baseContext; } } + +export interface CssColorForm { + primaryColor: FormControl; + primaryColorInput: FormControl; + cssOverride: FormControl; +} \ No newline at end of file diff --git a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.resolver.ts b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.resolver.ts index 60da3eb84..b376d1bc5 100644 --- a/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.resolver.ts +++ b/frontend/src/app/ui/admin/tenant-configuration/editor/css-colors/css-colors-editor.resolver.ts @@ -23,9 +23,7 @@ export class CssColorsEditorResolver extends BaseEditorResolver { nameof(x => x.cssColors), [nameof(x => x.cssColors), nameof(x => x.primaryColor)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.primaryColor2)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.primaryColor3)].join('.'), - [nameof(x => x.cssColors), nameof(x => x.secondaryColor)].join('.'), + [nameof(x => x.cssColors), nameof(x => x.cssOverride)].join('.'), nameof(x => x.createdAt), diff --git a/frontend/src/app/ui/dashboard/dashboard.component.html b/frontend/src/app/ui/dashboard/dashboard.component.html index b9bd19de1..17c52f220 100644 --- a/frontend/src/app/ui/dashboard/dashboard.component.html +++ b/frontend/src/app/ui/dashboard/dashboard.component.html @@ -45,12 +45,12 @@
- +
- +
diff --git a/frontend/src/app/ui/misc/theme-helper.ts b/frontend/src/app/ui/misc/theme-helper.ts new file mode 100644 index 000000000..730608e4f --- /dev/null +++ b/frontend/src/app/ui/misc/theme-helper.ts @@ -0,0 +1,127 @@ +import { argbFromHex, hexFromArgb, themeFromSourceColor, TonalPalette, applyTheme } from "@material/material-color-utilities"; + + +export function generateDynamicTheme(primaryColor: string) { + const fallbackPrimary = '#18488F'; + + let argbPrimary; + try { + argbPrimary = argbFromHex(primaryColor); + } catch (error) { + // falling to default color if it's invalid color + argbPrimary = argbFromHex(fallbackPrimary); + } + + const targetElement = document.documentElement; + + // Get the theme from a hex color + const theme = themeFromSourceColor(argbPrimary); + + // Apply theme to root element + applyTheme(theme, { + target: targetElement, + dark: false, + brightnessSuffix: true, + }); + + const styles = targetElement.style; + + for (const key in styles) { + if (Object.prototype.hasOwnProperty.call(styles, key)) { + const propName = styles[key]; + if (propName.indexOf('--md-sys') === 0) { + const sysPropName = '--sys' + propName.replace('--md-sys-color', ''); + targetElement.style.setProperty( + sysPropName, + targetElement.style.getPropertyValue(propName) + ); + } + } + } + } + +// export function applyThemeFromSelectedColors(primary: string, secondary: string, error: string): void { + +// const primaryPalette = getColorPalette(primary ?? '#18488F'); +// const secondaryPalette = getColorPalette(secondary ?? '#36900B'); +// const errorPalette = getColorPalette(error ?? '#cf1407'); + +// primaryPalette.error = errorPalette?.primary; + +// document.documentElement.style.setProperty(`--primary-color`, primary); +// createCustomProperties(primaryPalette, 'p'); + +// createCustomProperties(secondaryPalette, 't'); +// document.documentElement.style.setProperty(`--secondary-color`, secondary); +// // errorPalette?.forEach((color) => { +// // document.documentElement.style.setProperty(`--error-${color.tone}`, color.hex); +// // }) +// } + +// function getColorPalette(color: string): Record{ +// const tones = [0, 10, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 95, 99, 100]; +// const theme = themeFromSourceColor( +// argbFromHex(color) +// ); + +// const colors = Object.entries(theme.palettes).reduce( +// (acc: any, curr: [string, TonalPalette]) => { +// const hexColors = tones.map((tone) => ({ +// tone, +// hex: hexFromArgb(curr[1].tone(tone))// tone < 30 || tone > 60 ? hexFromArgb(curr[1].tone(tone)) : color, +// })); + +// return { ...acc, [curr[0]]: hexColors }; +// }, +// {} +// ); + +// return colors; +// } + +// function createCustomProperties( +// colorsFromPaletteConfig: Record, +// paletteKey: 'p' | 't', +// ) { +// let styleString = ''; + +// for (const [key, palette] of Object.entries(colorsFromPaletteConfig)) { +// palette.forEach(({ hex, tone }) => { +// if (key === 'primary') { +// styleString = `--${paletteKey === 'p' ? key : 'tertiary'}-${tone}`; +// } else { +// styleString = `--${paletteKey}-${key}-${tone}`; +// } +// document.documentElement.style.setProperty(styleString, hex) +// }); +// } +// } + +export function overrideCss(input: string){ + let json; + const targetElement = document.documentElement; + try { + input = input.replace(/(\r\n|\n|\r)/gm, ""); + json = JSON.parse(input); + } catch(error) { + return; + } + for (const [key, rgba] of Object.entries(json)) { + if (key.indexOf('--md-sys') === 0) { + const sysPropName = '--sys' + key.replace('--md-sys-color', ''); + targetElement.style.setProperty( + sysPropName, + rgba.toString() + ); + } + targetElement.style.setProperty( + key, + rgba.toString() + ); + } +} + +interface ColorData { + tone: number; + hex: string; +} \ No newline at end of file diff --git a/frontend/src/app/ui/navbar/navbar.component.html b/frontend/src/app/ui/navbar/navbar.component.html index 38e68ffc6..65eb8d659 100644 --- a/frontend/src/app/ui/navbar/navbar.component.html +++ b/frontend/src/app/ui/navbar/navbar.component.html @@ -25,7 +25,7 @@ @@ -103,13 +103,13 @@ tenancy arrow_drop_down - +
  • - +
  • diff --git a/frontend/src/app/ui/navbar/navbar.component.scss b/frontend/src/app/ui/navbar/navbar.component.scss index 7a5a89d53..41dbe9d50 100644 --- a/frontend/src/app/ui/navbar/navbar.component.scss +++ b/frontend/src/app/ui/navbar/navbar.component.scss @@ -73,13 +73,18 @@ $mat-card-header-size: 40px !default; .faq-title { text-align: left; font-weight: bold; - color: #000000; opacity: 1; } +.faq-title, .lang { + color: #000000 !important; + &:hover { + color: var(--sys-primary) + } +} .faq-title:hover, .lang:hover { - color: var(--primary-color) !important; + color: var(--sys-primary) !important; } .lang { @@ -184,8 +189,9 @@ $mat-card-header-size: 40px !default; height: auto !important; } -::ng-deep .nav-mat-menu { - .mat-mdc-menu-content { +::ng-deep .mat-mdc-menu-content { padding: 0 !important; - } + .mat-button-toggle-group { + border: none !important; + } } diff --git a/frontend/src/app/ui/plan/overview/plan-overview.component.html b/frontend/src/app/ui/plan/overview/plan-overview.component.html index 4a95d432b..0328d3160 100644 --- a/frontend/src/app/ui/plan/overview/plan-overview.component.html +++ b/frontend/src/app/ui/plan/overview/plan-overview.component.html @@ -60,7 +60,7 @@
    @if(isActive && canEditPlan(plan) && !lockStatus){ - } @else { @@ -184,7 +184,7 @@
    -
    diff --git a/frontend/src/app/ui/plan/overview/plan-overview.component.ts b/frontend/src/app/ui/plan/overview/plan-overview.component.ts index 9d7cb8fab..c1f8fb3b1 100644 --- a/frontend/src/app/ui/plan/overview/plan-overview.component.ts +++ b/frontend/src/app/ui/plan/overview/plan-overview.component.ts @@ -489,7 +489,8 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit { planId: rowId, planName: rowName, blueprint: this.selectedBlueprint - } + }, + minWidth: '80vw' }); } diff --git a/frontend/src/assets/i18n/baq.json b/frontend/src/assets/i18n/baq.json index ec6d399a9..6011418f5 100644 --- a/frontend/src/assets/i18n/baq.json +++ b/frontend/src/assets/i18n/baq.json @@ -469,18 +469,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json index e9b590cee..2577bf502 100644 --- a/frontend/src/assets/i18n/de.json +++ b/frontend/src/assets/i18n/de.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index 1e260364d..f72e6d00b 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -478,18 +478,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/es.json b/frontend/src/assets/i18n/es.json index beae1438c..7a9001a83 100644 --- a/frontend/src/assets/i18n/es.json +++ b/frontend/src/assets/i18n/es.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/gr.json b/frontend/src/assets/i18n/gr.json index b9082cd72..aa0511aa2 100644 --- a/frontend/src/assets/i18n/gr.json +++ b/frontend/src/assets/i18n/gr.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/hr.json b/frontend/src/assets/i18n/hr.json index 0817e53cf..6c0c57cfe 100644 --- a/frontend/src/assets/i18n/hr.json +++ b/frontend/src/assets/i18n/hr.json @@ -472,17 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/pl.json b/frontend/src/assets/i18n/pl.json index 27aeabfed..d7b62a739 100644 --- a/frontend/src/assets/i18n/pl.json +++ b/frontend/src/assets/i18n/pl.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/pt.json b/frontend/src/assets/i18n/pt.json index 25d9de005..0dcfc6f54 100644 --- a/frontend/src/assets/i18n/pt.json +++ b/frontend/src/assets/i18n/pt.json @@ -471,18 +471,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/sk.json b/frontend/src/assets/i18n/sk.json index e77dda979..a81845a65 100644 --- a/frontend/src/assets/i18n/sk.json +++ b/frontend/src/assets/i18n/sk.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/sr.json b/frontend/src/assets/i18n/sr.json index aad383f92..33755e221 100644 --- a/frontend/src/assets/i18n/sr.json +++ b/frontend/src/assets/i18n/sr.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/assets/i18n/tr.json b/frontend/src/assets/i18n/tr.json index 9874ef547..8633e67f6 100644 --- a/frontend/src/assets/i18n/tr.json +++ b/frontend/src/assets/i18n/tr.json @@ -472,18 +472,8 @@ "CULTURE": "Format", "LANGUAGE": "Language", "PRIMARY-COLOR": "Primary Color", - "PRIMARY-COLOR-2": "Primary Color 2", - "PRIMARY-COLOR-3": "Primary Color 3", - "DRAFT-STATUS-COLOR": "Draft Status Color", - "DRAFT-STATUS-COLOR-HINT": "Font color for plans and descriptions that are in drafted status", - "LINK-COLOR": "Link Color", - "LINK-COLOR-HINT": "Font color for the links in the application", - "SECONDARY-COLOR": "Secondary Color", - "PRIMARY-COLOR-TEXT": "Primary Color Text", - "SECONDARY-COLOR-TEXT": "Secondary Color Text", - "INVERTED-BUTTON-COLOR": "Inverted Button Color", - "INVERTED-BUTTON-HINT": "Background color for buttons whose text color is the selected Primary color", - "WARNING-COLOR": "Warning Color", + "PRIMARY-COLOR-HINT": "This color generates a theme based on it. Any changes to the theme can be made using the CSS override", + "CSS-OVERRIDE": "CSS Override", "DISABLE-SYSTEM-SOURCES": "Disable System Sources", "DEPOSIT-PLUGINS": "Plugin", "FILE-TRANSFORMER-PLUGINS": "Plugin", diff --git a/frontend/src/material-theme.scss b/frontend/src/material-theme.scss new file mode 100644 index 000000000..2db9ba4ad --- /dev/null +++ b/frontend/src/material-theme.scss @@ -0,0 +1,126 @@ +@use 'sass:map'; +@use '@angular/material' as mat; + +// Be sure that you only ever include this mixin once! +@include mat.core(); + + +:root { + --primary-color: #18488F; + --link-color: #1E59B1; + --draft-color: #f16868; + --secondary-color: #36900B; + --primary-text: #ffffff; + --secondary-text: #000000; + --inverted-btn-color: #ffffff; + + --warning-color: var(--mat-form-field-error-text-color); // #cf1407 or #f44336 for better contrast + --gray: #707070; //previously #848484 + --light-gray: #aaaaaa; + --dark-gray: #212121; +} + +$angular-material-3-theme: mat.define-theme(( + color: ( + theme-type: light, + primary: mat.$cyan-palette, + tertiary: mat.$yellow-palette, + use-system-variables: true + ), + typography: ( + plain-family: 'Roboto, sans-serif', + brand-family: 'Roboto, sans-serif', + regular-weight: 400, + medium-weight: 400, + bold-weight: 700, + use-system-variables: true + ), + density: ( + scale: 0 + ) +)); + +:root { + @include mat.all-component-themes($angular-material-3-theme); + @include mat.color-variants-backwards-compatibility($angular-material-3-theme); + @include mat.system-level-colors($angular-material-3-theme); + @include mat.system-level-typography($angular-material-3-theme); + // --sys-body-large: 400 1rem / 1.5rem Roboto, sans-serif; + --sys-body-large-line-height: 1.125rem; + --sys-body-large-size: 1rem; + // --sys-body-large-tracking: 0.031rem; + // --sys-body-large-weight: 400; + // --sys-body-medium: 400 0.875rem / 1.25rem Roboto, sans-serif; + --sys-body-medium-line-height: 1.25rem; + --sys-body-medium-size: 0.875rem; + // --sys-body-medium-tracking: 0.016rem; + // --sys-body-medium-weight: 400; + // --sys-body-small: 400 0.75rem / 1rem Roboto, sans-serif; + --sys-body-small-line-height: 1rem; + --sys-body-small-size: 0.75rem; + // --sys-body-small-tracking: 0.025rem; + // --sys-body-small-weight: 400; + // --sys-display-large: 400 3.562rem / 4rem Roboto, sans-serif; + --sys-display-large-line-height: 4rem; + --sys-display-large-size: 3.562rem; + // --sys-display-large-tracking: -0.016rem; + // --sys-display-large-weight: 400; + // --sys-display-medium: 400 2.812rem / 3.25rem Roboto, sans-serif; + --sys-display-medium-line-height: 3.25rem; + --sys-display-medium-size: 2.812rem; + // --sys-display-medium-tracking: 0rem; + // --sys-display-medium-weight: 400; + // --sys-display-small: 400 2.25rem / 2.75rem Roboto, sans-serif; + --sys-display-small-line-height: 2.75rem; + --sys-display-small-size: 2.25rem; + // --sys-display-small-tracking: 0rem; + // --sys-display-small-weight: 400; + // --sys-headline-large: 400 2rem / 2.5rem Roboto, sans-serif; + --sys-headline-large-line-height: 2.5rem; + --sys-headline-large-size: 2rem; + // --sys-headline-large-tracking: 0rem; + // --sys-headline-large-weight: 400; + // --sys-headline-medium: 400 1.75rem / 2.25rem Roboto, sans-serif; + --sys-headline-medium-line-height: 2.25rem; + --sys-headline-medium-size: 1.75rem; + // --sys-headline-medium-tracking: 0rem; + // --sys-headline-medium-weight: 400; + // --sys-headline-small: 400 1.5rem / 2rem Roboto, sans-serif; + --sys-headline-small-line-height: 2rem; + --sys-headline-small-size: 1.5rem; + // --sys-headline-small-tracking: 0rem; + // --sys-headline-small-weight: 400; + // --sys-label-large: 500 0.875rem / 1.25rem Roboto, sans-serif; + --sys-label-large-line-height: 1.25rem; + --sys-label-large-size: 0.87rem; + // --sys-label-large-tracking: 0.006rem; + // --sys-label-large-weight: 500; + --sys-label-large-weight-prominent: 700; + // --sys-label-medium: 500 0.75rem / 1rem Roboto, sans-serif; + --sys-label-medium-line-height: 1rem; + --sys-label-medium-size: 0.75rem; + // --sys-label-medium-tracking: 0.031rem; + // --sys-label-medium-weight: 500; + --sys-label-medium-weight-prominent: 700; + // --sys-label-small: 500 0.688rem / 1rem Roboto, sans-serif; + --sys-label-small-line-height: 1rem; + --sys-label-small-size: 0.688rem; + // --sys-label-small-tracking: 0.031rem; + // --sys-label-small-weight: 500; + // --sys-title-large: 400 1.375rem / 1.75rem Roboto, sans-serif; + --sys-title-large-line-height: 1.75rem; + --sys-title-large-size: 1.375rem; + // --sys-title-large-tracking: 0rem; + --sys-title-large-weight: 500; + // --sys-title-medium: 500 1rem / 1.5rem Roboto, sans-serif; + --sys-title-medium-line-height: 1.125rem; + --sys-title-medium-size: 1rem; + // --sys-title-medium-tracking: 0.009rem; + // --sys-title-medium-weight: 500; + // --sys-title-small: 500 0.875rem / 1.25rem Roboto, sans-serif; + --sys-title-small-line-height: 1.25rem; + --sys-title-small-size: 0.875rem; + // --sys-title-small-tracking: 0.006rem; + // --sys-title-small-weight: 500; +} + diff --git a/frontend/src/styles.scss b/frontend/src/styles.scss index e6cac883c..95b293799 100644 --- a/frontend/src/styles.scss +++ b/frontend/src/styles.scss @@ -18,136 +18,122 @@ // Guided Tour style @import '../node_modules/ngx-guided-tour/scss/guided-tour-base-theme.scss'; - // Be sure that you only ever include this mixin once! -@include mat.core(); +//@include mat.core(); // styles moved from material-dashboard.scss -> overwrite bootstrap default styles // @import "assets/scss/core/type"; -:root { - --primary-color: #18488F; - --link-color: #1E59B1; - --draft-color: #f16868; - --secondary-color: #36900B; - --primary-text: #ffffff; - --secondary-text: #000000; - --inverted-btn-color: #ffffff; +// :root { +// --primary-color: #18488F; +// --link-color: #1E59B1; +// --draft-color: #f16868; +// --secondary-color: #36900B; +// --primary-text: #ffffff; +// --secondary-text: #000000; +// --inverted-btn-color: #ffffff; - --warning-color: var(--mat-form-field-error-text-color); // #cf1407 or #f44336 for better contrast - --gray: #707070; //previously #848484 - --light-gray: #aaaaaa; - --dark-gray: #212121; -} +// --warning-color: var(--mat-form-field-error-text-color); // #cf1407 or #f44336 for better contrast +// --gray: #707070; //previously #848484 +// --light-gray: #aaaaaa; +// --dark-gray: #212121; +// } // Define your theme with color palettes, typography and density -$mat-theme-primary-palette: map-merge(mat.$m2-cyan-palette, (501: var(--primary-color), contrast: (100: black, ))); -$mat-theme-primary: mat.m2-define-palette($mat-theme-primary-palette, - $default: 501, - $lighter: 100, - $darker: 700, - $text: 500); +// $mat-theme-primary-palette: map-merge(mat.$m2-cyan-palette, (501: var(--primary-color), contrast: (100: black, ))); +// $mat-theme-primary: mat.m2-define-palette($mat-theme-primary-palette, +// $default: 501, +// $lighter: 100, +// $darker: 700, +// $text: 500); -$mat-theme-accent-palette: map-merge(mat.$m2-teal-palette, (501: var(--secondary-color), contrast: (A100: white, A200: white, ))); -$mat-theme-accent: mat.m2-define-palette($mat-theme-accent-palette, - $default: 501, - $lighter: A100, - $darker: A200, - $text: 600); +// $mat-theme-accent-palette: map-merge(mat.$m2-teal-palette, (501: var(--secondary-color), contrast: (A100: white, A200: white, ))); +// $mat-theme-accent: mat.m2-define-palette($mat-theme-accent-palette, +// $default: 501, +// $lighter: A100, +// $darker: A200, +// $text: 600); -$mat-theme-warn-palette: map-merge(mat.$m2-pink-palette, ()); -$mat-theme-warn: mat.m2-define-palette($mat-theme-warn-palette, - $default: A200, - $lighter: 500, - $darker: 500, - $text: A700); - -$mat-dark-theme-primary-palette: map-merge(mat.$m2-lime-palette, (contrast: (200: #030844, A100: rgba(0, 0, 0, 0.87), A700: rgba(0, 0, 0, 0.87), ))); -$mat-dark-theme-primary: mat.m2-define-palette($mat-dark-theme-primary-palette, - $default: 200, - $lighter: A100, - $darker: A700, - $text: 700); - -$mat-dark-theme-accent-palette: map-merge(mat.$m2-green-palette, (contrast: (A200: black, 50: black, A400: black, ))); -$mat-dark-theme-accent: mat.m2-define-palette($mat-dark-theme-accent-palette, - $default: A200, - $lighter: 50, - $darker: A400, - $text: A100); - -$mat-dark-theme-warn-palette: map-merge(mat.$m2-pink-palette, (contrast: (A100: black, 100: white, ))); -$mat-dark-theme-warn: mat.m2-define-palette($mat-dark-theme-warn-palette, - $default: A100, - $lighter: 100, - $darker: A700, - $text: 100); +// $mat-theme-warn-palette: map-merge(mat.$m2-pink-palette, ()); +// $mat-theme-warn: mat.m2-define-palette($mat-theme-warn-palette, +// $default: A200, +// $lighter: 500, +// $darker: 500, +// $text: A700); //including the typography rules from _type.scss here -$mat-typography: mat.m2-define-typography-config($font-family: 'Roboto, sans-serif;', - // $headline-1: mat.m2-define-typography-level($font-size: 2.5rem), - // $headline-2: mat.m2-define-typography-level($font-size: 2.25rem), - // $headline-3: mat.m2-define-typography-level($font-size: 1.5625rem), - // $headline-4: mat.m2-define-typography-level($font-size: 1.125rem), - // $headline-5: mat.m2-define-typography-level($font-size: 1.0625rem), - // $headline-6: mat.m2-define-typography-level($font-size: 1rem ), - $body-1: mat.m2-define-typography-level($font-size: 1.125rem), - $body-2: mat.m2-define-typography-level($font-size: 0.9rem), - $button: mat.m2-define-typography-level($font-size: 0.87rem), - $caption: mat.m2-define-typography-level($font-size: 0.77rem), - // Line-height must be unit-less fraction of the font-size. - // $input: mat.m2-define-typography-level($font-size: inherit, $line-height: 1.125), -); +// $mat-typography: mat.m2-define-typography-config($font-family: 'Roboto, sans-serif;', +// // $headline-1: mat.m2-define-typography-level($font-size: 2.5rem), +// // $headline-2: mat.m2-define-typography-level($font-size: 2.25rem), +// // $headline-3: mat.m2-define-typography-level($font-size: 1.5625rem), +// // $headline-4: mat.m2-define-typography-level($font-size: 1.125rem), +// // $headline-5: mat.m2-define-typography-level($font-size: 1.0625rem), +// // $headline-6: mat.m2-define-typography-level($font-size: 1rem ), +// $body-1: mat.m2-define-typography-level($font-size: 1.125rem), +// $body-2: mat.m2-define-typography-level($font-size: 0.9rem), +// $button: mat.m2-define-typography-level($font-size: 0.87rem), +// $caption: mat.m2-define-typography-level($font-size: 0.77rem), +// // Line-height must be unit-less fraction of the font-size. +// // $input: mat.m2-define-typography-level($font-size: inherit, $line-height: 1.125), +// ); -$mat-accessibility-typography: mat.m2-define-typography-config($font-family: 'Roboto, sans-serif;', - // $headline-1: mat.m2-define-typography-level($font-size: 2.5rem), - // $headline-2: mat.m2-define-typography-level($font-size: 2.38rem), - // $headline-3: mat.m2-define-typography-level($font-size: 1.6925rem), - // $headline-4: mat.m2-define-typography-level($font-size: 1.255rem), - // $headline-5: mat.m2-define-typography-level($font-size: 1.1925rem), - // $headline-6: mat.m2-define-typography-level($font-size: 1.13rem ), - $body-1: mat.m2-define-typography-level($font-size: 1.255rem), - $body-2: mat.m2-define-typography-level($font-size: 1.15rem), - $button: mat.m2-define-typography-level($font-size: 1rem), -); +// $mat-accessibility-typography: mat.m2-define-typography-config($font-family: 'Roboto, sans-serif;', +// // $headline-1: mat.m2-define-typography-level($font-size: 2.5rem), +// // $headline-2: mat.m2-define-typography-level($font-size: 2.38rem), +// // $headline-3: mat.m2-define-typography-level($font-size: 1.6925rem), +// // $headline-4: mat.m2-define-typography-level($font-size: 1.255rem), +// // $headline-5: mat.m2-define-typography-level($font-size: 1.1925rem), +// // $headline-6: mat.m2-define-typography-level($font-size: 1.13rem ), +// $body-1: mat.m2-define-typography-level($font-size: 1.255rem), +// $body-2: mat.m2-define-typography-level($font-size: 1.15rem), +// $button: mat.m2-define-typography-level($font-size: 1rem), +// ); -$mat-density: 0; +// $mat-density: 0; // @include mat.elevation( // $zValue: 12, // $color: #000, // $opacity: 0.5 // ); -$mat-core-theme: mat.m2-define-light-theme((color: (primary: $mat-theme-primary, - accent: $mat-theme-accent, - warn: $mat-theme-warn), - typography: $mat-typography, - density: $mat-density)); +// $mat-core-theme: mat.m2-define-light-theme((color: (primary: $mat-theme-primary, +// accent: $mat-theme-accent, +// warn: $mat-theme-warn), +// typography: $mat-typography, +// density: $mat-density)); -$mat-dark-theme: mat.m2-define-dark-theme((color: (primary: $mat-dark-theme-primary, - accent: $mat-dark-theme-accent, - warn: $mat-dark-theme-warn, - ))); -$mat-accessibility-theme: mat.m2-define-light-theme((color: (primary: $mat-theme-primary, - accent: $mat-theme-accent, - warn: $mat-theme-warn), - typography: $mat-accessibility-typography, - density: $mat-density)); +@import './material-theme.scss'; -@include mat.all-component-themes($mat-core-theme); - -.dark-theme { - @include mat.all-component-colors($mat-dark-theme); +//m3 styles overwrites +.mat-mdc-mini-fab { + border-radius: 50% !important; } +.mat-mdc-dialog-surface { + border-radius: 8px !important; +} +.mat-button-toggle-group.mat-button-toggle-group-appearance-standard{ + border-radius: 4px; + border-color: var(--mat-standard-button-toggle-selected-state-background-color); + .mat-button-toggle.mat-button-toggle-appearance-standard { + border-left-color: var(--mat-standard-button-toggle-selected-state-background-color); + } +} +// $mat-accessibility-theme: mat.m2-define-light-theme((color: (primary: $mat-theme-primary, +// accent: $mat-theme-accent, +// warn: $mat-theme-warn), +// typography: $mat-accessibility-typography, +// density: $mat-density)); + +// @include mat.all-component-themes($mat-core-theme); .accessibility-theme { - @include mat.all-component-themes($mat-accessibility-theme); + // @include mat.all-component-themes($mat-accessibility-theme); // change individual classes set in components' scss .frame-txt, .action-list-text, .stepper-back, .nav-row, .nav-subrow, .center-content, .form-check, @@ -172,9 +158,6 @@ $mat-accessibility-theme: mat.m2-define-light-theme((color: (primary: $mat-theme } - - - a { color: var(--link-color); &:hover { @@ -502,11 +485,6 @@ button, .mdc-button, .mat-mdc-button, .mdc-button:has(.material-icons,mat-icon,[ &.rounded-btn{ padding: 0.62rem 1.87rem; min-height: 40px; - - border-radius: 30px; - opacity: 1; - // padding-left: 2em; - // padding-right: 2em; box-shadow: 0px 3px 6px #1E202029; } &.primary {