diff --git a/.gitignore b/.gitignore index 81d5aae..0d1053a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ out/ /.idea/ /uploads/ +/META-INF/ diff --git a/jambotron-ui/package-lock.json b/jambotron-ui/package-lock.json index c7527e4..97bcf01 100644 --- a/jambotron-ui/package-lock.json +++ b/jambotron-ui/package-lock.json @@ -9,20 +9,23 @@ "version": "0.0.0", "dependencies": { "@angular/animations": "^20.0.4", - "@angular/cdk": "^20.0.3", + "@angular/cdk": "^20.1.6", "@angular/common": "^20.0.0", "@angular/compiler": "^20.0.0", "@angular/core": "^20.0.0", "@angular/forms": "^20.0.0", - "@angular/material": "^20.0.3", + "@angular/material": "^20.1.6", "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/router": "^20.0.0", "@angular/ssr": "^20.0.2", + "@material/material-color-utilities": "^0.3.0", "@ng-bootstrap/ng-bootstrap": "19.0.0", "@popperjs/core": "2.11.8", "angular-markdown-editor": "^3.1.1", "bootstrap": "5.3.6", + "ngx-color-picker": "^20.1.0", + "ngx-colors": "^3.6.0", "ngx-image-cropper": "^9.1.5", "ngx-markdown": "^20.0.0", "prismjs": "^1.30.0", @@ -582,12 +585,12 @@ } }, "node_modules/@angular/cdk": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.3.tgz", - "integrity": "sha512-70KG8GpK4aV9j5hUkpDZJQ6oMgCuaCRY6JX1axPxkNtQaiK6PAmTfQLiGqF2cYhbQneeq3uGvTorAjRfvp8NPQ==", + "version": "20.1.6", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.1.6.tgz", + "integrity": "sha512-GKxCS/GOAOQCNTnrvYia9wR4Z9rRWjzNRE0989LXwWLYcmiG7+ku30PolGV7zhmlgUu/qx8P6BbxZgUvK34X/A==", "license": "MIT", "dependencies": { - "parse5": "^7.1.2", + "parse5": "^8.0.0", "tslib": "^2.3.0" }, "peerDependencies": { @@ -596,6 +599,30 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@angular/cdk/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@angular/cdk/node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/@angular/cli": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.0.3.tgz", @@ -843,15 +870,15 @@ } }, "node_modules/@angular/material": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.0.3.tgz", - "integrity": "sha512-kd5Mi6gVxcjDs1nfm8GG2rId59SXWQjkiBMqrYuhy2Trpb+zG0vrLClrpoe3JdWqoX4GJagxGwl3VRDBIoP/cw==", + "version": "20.1.6", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.1.6.tgz", + "integrity": "sha512-k2rjN6ABd5ahE4LWAJ5rv7Z3WAO6tgmjOrFZG7ED0xavhcGWyHroALFqdmlIkb2QFAAF186ifLIH+xgln9edqw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "20.0.3", + "@angular/cdk": "20.1.6", "@angular/common": "^20.0.0 || ^21.0.0", "@angular/core": "^20.0.0 || ^21.0.0", "@angular/forms": "^20.0.0 || ^21.0.0", @@ -3746,6 +3773,12 @@ "win32" ] }, + "node_modules/@material/material-color-utilities": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.3.0.tgz", + "integrity": "sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==", + "license": "Apache-2.0" + }, "node_modules/@mermaid-js/parser": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.0.tgz", @@ -11781,6 +11814,35 @@ "dev": true, "license": "MIT" }, + "node_modules/ngx-color-picker": { + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-20.1.0.tgz", + "integrity": "sha512-669JqpvSroMt9AZjcyks0zzV0Indqjch0lAGTOvo6AR8RiSH9GPGeFT5Lk0sNFvNIa1cywS1emL4S3Jj+hMLZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=18.0.0", + "@angular/core": ">=18.0.0", + "@angular/forms": ">=18.0.0" + } + }, + "node_modules/ngx-colors": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/ngx-colors/-/ngx-colors-3.6.0.tgz", + "integrity": "sha512-jPFzosd7t7YHKqKTBbOxdAF67aevBTiv0UdS0i7umWQMdMfi0lwcNTrL8XLhW2YbIpy98r54zWgc0iZH5FpiZA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/animations": ">=15.0.0", + "@angular/common": ">=15.0.0", + "@angular/core": ">=15.0.0", + "@angular/forms": ">=15.0.0" + } + }, "node_modules/ngx-image-cropper": { "version": "9.1.5", "resolved": "https://registry.npmjs.org/ngx-image-cropper/-/ngx-image-cropper-9.1.5.tgz", @@ -12426,6 +12488,7 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -12479,6 +12542,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" diff --git a/jambotron-ui/package.json b/jambotron-ui/package.json index cccd6af..898a60e 100644 --- a/jambotron-ui/package.json +++ b/jambotron-ui/package.json @@ -14,20 +14,23 @@ "private": true, "dependencies": { "@angular/animations": "^20.0.4", - "@angular/cdk": "^20.0.3", + "@angular/cdk": "^20.1.6", "@angular/common": "^20.0.0", "@angular/compiler": "^20.0.0", "@angular/core": "^20.0.0", "@angular/forms": "^20.0.0", - "@angular/material": "^20.0.3", + "@angular/material": "^20.1.6", "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/router": "^20.0.0", "@angular/ssr": "^20.0.2", + "@material/material-color-utilities": "^0.3.0", "@ng-bootstrap/ng-bootstrap": "19.0.0", "@popperjs/core": "2.11.8", "angular-markdown-editor": "^3.1.1", "bootstrap": "5.3.6", + "ngx-color-picker": "^20.1.0", + "ngx-colors": "^3.6.0", "ngx-image-cropper": "^9.1.5", "ngx-markdown": "^20.0.0", "prismjs": "^1.30.0", diff --git a/jambotron-ui/src/app/app.module.ts b/jambotron-ui/src/app/app.module.ts index fb4aa21..ef4f85a 100644 --- a/jambotron-ui/src/app/app.module.ts +++ b/jambotron-ui/src/app/app.module.ts @@ -18,7 +18,7 @@ import {App} from './app'; import {CustomHttpInterceptor} from './helpers/custom-http-interceptor'; import {AngularMarkdownEditorModule} from 'angular-markdown-editor'; import {MatFormFieldModule} from '@angular/material/form-field'; - +import {NgxColorsModule} from 'ngx-colors'; @NgModule({ declarations: [ @@ -35,7 +35,8 @@ import {MatFormFieldModule} from '@angular/material/form-field'; SettingsComponent, SystemComponent, AngularMarkdownEditorModule.forRoot({ iconlibrary: 'fa' }), - MatFormFieldModule + MatFormFieldModule, + NgxColorsModule ], providers: [ authInterceptorProviders,provideHttpClient(withInterceptorsFromDi()),{ diff --git a/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.html b/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.html index 4c5a4ff..f01d83a 100644 --- a/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.html +++ b/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.html @@ -5,11 +5,7 @@
admin-welcome.component works!
admin-welcome.component works!
admin-welcome.component works!
-admin-welcome.component works!
-admin-welcome.component works!
-admin-welcome.component works!
-admin-welcome.component works!
-admin-welcome.component works!
+admin-welcome.component works!
admin-welcome.component works!
admin-welcome.component works!
diff --git a/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.ts b/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.ts index ba7feb2..ad5c822 100644 --- a/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.ts +++ b/jambotron-ui/src/app/modules/admin-module/admin-welcome.component/admin-welcome.component.ts @@ -2,7 +2,9 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-admin-welcome.component', - imports: [], + imports: [ + + ], templateUrl: './admin-welcome.component.html', styleUrl: './admin-welcome.component.scss' }) diff --git a/jambotron-ui/src/styles.scss b/jambotron-ui/src/styles.scss index 79ff90e..4d49d1b 100644 --- a/jambotron-ui/src/styles.scss +++ b/jambotron-ui/src/styles.scss @@ -1,5 +1,8 @@ -@use 'node_modules/@angular/material' as mat; +@import './styles/angular_material_theme.scss'; + + +//--------------------------------------------------------------------------------------------------------------------- //markdown styles @import 'bootstrap/dist/css/bootstrap.min.css'; @import 'prismjs/themes/prism-okaidia.css'; @@ -57,23 +60,3 @@ body { min-height: calc(100vh - 113px); background: #fafafbb3; } - -//// Include the common styles for Angular Material -//@include mat.core(); -// -//// Define your custom palette -//$my-primary: mat.define-palette(mat.$blue-palette, 700); -//$my-accent: mat.define-palette(mat.$orange-palette, A200, A100, A400); -//$my-warn: mat.define-palette(mat.$red-palette); -// -//// Create the theme -//$my-theme: mat.define-light-theme(( -// color: ( -// primary: $my-primary, -// accent: $my-accent, -// warn: $my-warn, -// ) -//)); -// -//// Include theme styles for core and each component used in your app -//@include mat.all-component-themes($my-theme); diff --git a/jambotron-ui/src/styles/angular_material_theme.scss b/jambotron-ui/src/styles/angular_material_theme.scss new file mode 100644 index 0000000..9444ce5 --- /dev/null +++ b/jambotron-ui/src/styles/angular_material_theme.scss @@ -0,0 +1,306 @@ +// File: src/styles/material-theme.scss +// Complete Angular Material theme implementation for Material Design 3 palette + +@use '@angular/material' as mat; + +// Include core styles +@include mat.core(); + +// Convert RGB values to hex for Angular Material palette definition +// Primary: rgb(68 94 145) = #445e91 +// Secondary: rgb(87 94 113) = #575e71 +// Error: rgb(186 26 26) = #ba1a1a + +// Define custom primary palette +$custom-primary: mat.m2-define-palette(( + 50: #e8f0ff, // Lightest shade + 100: #d8e2ff, // Very light + 200: #adc6ff, // Light - close to primary-container + 300: #81a3ff, // Medium light + 400: #5b82ff, // Medium + 500: #445e91, // Your primary color + 600: #2b4578, // Medium dark + 700: #1a2f5f, // Dark + 800: #0d1c47, // Very dark + 900: #030d30, // Darkest + A100: #d8e2ff, + A200: #adc6ff, + A400: #5b82ff, + A700: #1a2f5f, + contrast: ( + 50: rgba(black, 0.87), + 100: rgba(black, 0.87), + 200: rgba(black, 0.87), + 300: rgba(black, 0.87), + 400: white, + 500: white, + 600: white, + 700: white, + 800: white, + 900: white, + A100: rgba(black, 0.87), + A200: rgba(black, 0.87), + A400: white, + A700: white, + ) +)); + +// Define custom accent/secondary palette +$custom-accent: mat.m2-define-palette(( + 50: #f0f2f8, + 100: #dbe2f9, // Close to secondary-container + 200: #bfc8f1, + 300: #a0ace8, + 400: #8396d1, + 500: #575e71, // Your secondary color + 600: #4a5264, + 700: #3d4456, + 800: #313749, + 900: #252b3c, + A100: #dbe2f9, + A200: #bfc8f1, + A400: #8396d1, + A700: #3d4456, + contrast: ( + 50: rgba(black, 0.87), + 100: rgba(black, 0.87), + 200: rgba(black, 0.87), + 300: rgba(black, 0.87), + 400: white, + 500: white, + 600: white, + 700: white, + 800: white, + 900: white, + A100: rgba(black, 0.87), + A200: rgba(black, 0.87), + A400: white, + A700: white, + ) +)); + +// Define custom warn/error palette +$custom-warn: mat.m2-define-palette(( + 50: #ffebee, + 100: #ffcdd2, + 200: #ef9a9a, + 300: #e57373, + 400: #ef5350, + 500: #ba1a1a, // Your error color + 600: #a51a1a, + 700: #8f1616, + 800: #7a1313, + 900: #651010, + A100: #ff8a80, + A200: #ff5252, + A400: #ff1744, + A700: #d50000, + contrast: ( + 50: rgba(black, 0.87), + 100: rgba(black, 0.87), + 200: rgba(black, 0.87), + 300: rgba(black, 0.87), + 400: rgba(black, 0.87), + 500: white, + 600: white, + 700: white, + 800: white, + 900: white, + A100: rgba(black, 0.87), + A200: white, + A400: white, + A700: white, + ) +)); + +// Create the light theme +$light-theme: mat.m2-define-light-theme(( + color: ( + primary: $custom-primary, + accent: $custom-accent, + warn: $custom-warn, + ), + typography: mat.m2-define-typography-config( + $font-family: '"Roboto", sans-serif', + ), + density: 0, +)); + +// Apply the theme to all Angular Material components +@include mat.all-component-themes($light-theme); + +// Apply Material Design 3 color tokens as CSS custom properties +:root, +.light { + // Primary colors + --md-sys-color-primary: rgb(68 94 145); + --md-sys-color-surface-tint: rgb(68 94 145); + --md-sys-color-on-primary: rgb(255 255 255); + --md-sys-color-primary-container: rgb(216 226 255); + --md-sys-color-on-primary-container: rgb(43 70 120); + + // Secondary colors + --md-sys-color-secondary: rgb(87 94 113); + --md-sys-color-on-secondary: rgb(255 255 255); + --md-sys-color-secondary-container: rgb(219 226 249); + --md-sys-color-on-secondary-container: rgb(63 71 89); + + // Tertiary colors + --md-sys-color-tertiary: rgb(113 85 115); + --md-sys-color-on-tertiary: rgb(255 255 255); + --md-sys-color-tertiary-container: rgb(251 215 252); + --md-sys-color-on-tertiary-container: rgb(88 62 91); + + // Error colors + --md-sys-color-error: rgb(186 26 26); + --md-sys-color-on-error: rgb(255 255 255); + --md-sys-color-error-container: rgb(255 218 214); + --md-sys-color-on-error-container: rgb(147 0 10); + + // Surface colors + --md-sys-color-background: rgb(249 249 255); + --md-sys-color-on-background: rgb(26 27 32); + --md-sys-color-surface: rgb(249 249 255); + --md-sys-color-on-surface: rgb(26 27 32); + --md-sys-color-surface-variant: rgb(225 226 236); + --md-sys-color-on-surface-variant: rgb(68 71 79); + + // Outline colors + --md-sys-color-outline: rgb(117 119 127); + --md-sys-color-outline-variant: rgb(196 198 208); + + // Utility colors + --md-sys-color-shadow: rgb(0 0 0); + --md-sys-color-scrim: rgb(0 0 0); + + // Inverse colors + --md-sys-color-inverse-surface: rgb(47 48 54); + --md-sys-color-inverse-on-surface: rgb(240 240 247); + --md-sys-color-inverse-primary: rgb(173 198 255); + + // Fixed colors + --md-sys-color-primary-fixed: rgb(216 226 255); + --md-sys-color-on-primary-fixed: rgb(0 26 65); + --md-sys-color-primary-fixed-dim: rgb(173 198 255); + --md-sys-color-on-primary-fixed-variant: rgb(43 70 120); + --md-sys-color-secondary-fixed: rgb(219 226 249); + --md-sys-color-on-secondary-fixed: rgb(20 27 44); + --md-sys-color-secondary-fixed-dim: rgb(191 198 220); + --md-sys-color-on-secondary-fixed-variant: rgb(63 71 89); + --md-sys-color-tertiary-fixed: rgb(251 215 252); + --md-sys-color-on-tertiary-fixed: rgb(41 19 45); + --md-sys-color-tertiary-fixed-dim: rgb(222 188 223); + --md-sys-color-on-tertiary-fixed-variant: rgb(88 62 91); + + // Surface container colors + --md-sys-color-surface-dim: rgb(217 217 224); + --md-sys-color-surface-bright: rgb(249 249 255); + --md-sys-color-surface-container-lowest: rgb(255 255 255); + --md-sys-color-surface-container-low: rgb(243 243 250); + --md-sys-color-surface-container: rgb(238 237 244); + --md-sys-color-surface-container-high: rgb(232 231 238); + --md-sys-color-surface-container-highest: rgb(226 226 233); + + // Override Angular Material CSS variables to use MD3 tokens + --mdc-theme-primary: var(--md-sys-color-primary); + --mdc-theme-on-primary: var(--md-sys-color-on-primary); + --mdc-theme-secondary: var(--md-sys-color-secondary); + --mdc-theme-on-secondary: var(--md-sys-color-on-secondary); + --mdc-theme-error: var(--md-sys-color-error); + --mdc-theme-on-error: var(--md-sys-color-on-error); + --mdc-theme-surface: var(--md-sys-color-surface); + --mdc-theme-on-surface: var(--md-sys-color-on-surface); + --mdc-theme-background: var(--md-sys-color-background); + --mdc-theme-on-background: var(--md-sys-color-on-background); + + // Material Components Web variables + --mdc-outlined-text-field-outline-color: var(--md-sys-color-outline); + --mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-primary); + --mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary); + --mdc-text-field-filled-container-color: var(--md-sys-color-surface-container-highest); +} + +// Apply background color to body +body { + background-color: var(--md-sys-color-background); + color: var(--md-sys-color-on-background); + margin: 0; + font-family: 'Roboto', sans-serif; +} + +// Custom component overrides using Material Design 3 tokens +.mat-mdc-card { + background-color: var(--md-sys-color-surface-container) !important; + color: var(--md-sys-color-on-surface) !important; +} + +.mat-mdc-elevated-button { + &.mat-primary { + background-color: var(--md-sys-color-primary) !important; + color: var(--md-sys-color-on-primary) !important; + } + + &.mat-accent { + background-color: var(--md-sys-color-secondary) !important; + color: var(--md-sys-color-on-secondary) !important; + } +} + +.mat-mdc-outlined-button { + &.mat-primary { + border-color: var(--md-sys-color-outline) !important; + color: var(--md-sys-color-primary) !important; + + &:hover { + background-color: var(--md-sys-color-primary-container) !important; + color: var(--md-sys-color-on-primary-container) !important; + } + } +} + +.mat-mdc-form-field { + &.mat-focused { + .mdc-notched-outline__leading, + .mdc-notched-outline__notch, + .mdc-notched-outline__trailing { + border-color: var(--md-sys-color-primary) !important; + } + } +} + +// Toolbar styling +.mat-toolbar { + &.mat-primary { + background-color: var(--md-sys-color-primary-container) !important; + color: var(--md-sys-color-on-primary-container) !important; + } +} + +// Utility classes for direct use of Material Design 3 tokens +.md3-surface { background-color: var(--md-sys-color-surface); } +.md3-surface-container { background-color: var(--md-sys-color-surface-container); } +.md3-surface-container-high { background-color: var(--md-sys-color-surface-container-high); } +.md3-surface-container-highest { background-color: var(--md-sys-color-surface-container-highest); } + +.md3-primary { color: var(--md-sys-color-primary); } +.md3-on-primary { color: var(--md-sys-color-on-primary); } +.md3-primary-container { background-color: var(--md-sys-color-primary-container); } +.md3-on-primary-container { color: var(--md-sys-color-on-primary-container); } + +.md3-secondary { color: var(--md-sys-color-secondary); } +.md3-on-secondary { color: var(--md-sys-color-on-secondary); } +.md3-secondary-container { background-color: var(--md-sys-color-secondary-container); } +.md3-on-secondary-container { color: var(--md-sys-color-on-secondary-container); } + +.md3-tertiary { color: var(--md-sys-color-tertiary); } +.md3-on-tertiary { color: var(--md-sys-color-on-tertiary); } +.md3-tertiary-container { background-color: var(--md-sys-color-tertiary-container); } +.md3-on-tertiary-container { color: var(--md-sys-color-on-tertiary-container); } + +.md3-error { color: var(--md-sys-color-error); } +.md3-on-error { color: var(--md-sys-color-on-error); } +.md3-error-container { background-color: var(--md-sys-color-error-container); } +.md3-on-error-container { color: var(--md-sys-color-on-error-container); } + +.md3-outline { border-color: var(--md-sys-color-outline); } +.md3-outline-variant { border-color: var(--md-sys-color-outline-variant); }