Create UI and demo homepage (#18)
Co-authored-by: Sieciech <www.sieciech@gmail.com> Reviewed-on: http://git.fufle.net/Community/CureNet/pulls/18 Co-Authored-By: Sieciech <sieciech@noreply.fufle.net> Co-Committed-By: Sieciech <sieciech@noreply.fufle.net>
This commit is contained in:
		
							parent
							
								
									7fabb5170a
								
							
						
					
					
						commit
						0a7896ac94
					
				| 
						 | 
				
			
			@ -1,5 +1,15 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
echo "> Configure cache"
 | 
			
		||||
    mkdir -p /tmp/app/{vendor/node_modules}
 | 
			
		||||
    ln -s /tmp/app/node_modules /web/frontend/node_modules
 | 
			
		||||
    ln -s /tmp/app/vendor /web/backend/vendor
 | 
			
		||||
 | 
			
		||||
echo "> Configure user"
 | 
			
		||||
    useradd developer
 | 
			
		||||
    chown developer:developer /web/frontend -R
 | 
			
		||||
    chown developer:developer /web/backend -R
 | 
			
		||||
 | 
			
		||||
echo "> Configure logs"
 | 
			
		||||
    mkdir -p /var/log/{apache2,nginx,pgadmin,postgresql}
 | 
			
		||||
    chown postgres:adm /var/log/postgresql -R
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +49,7 @@ echo "> Configure symfony"
 | 
			
		|||
 | 
			
		||||
echo "> Configure angular"
 | 
			
		||||
    cd /web/frontend
 | 
			
		||||
    npm ci
 | 
			
		||||
    su developer -c 'time npm ci'
 | 
			
		||||
 | 
			
		||||
echo "> Starting angular"
 | 
			
		||||
    ng serve --disable-host-check --host 0.0.0.0 --poll
 | 
			
		||||
    su developer -c 'ng serve --disable-host-check --host 0.0.0.0 --poll'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,17 @@
 | 
			
		|||
              "src/assets"
 | 
			
		||||
            ],
 | 
			
		||||
            "styles": [
 | 
			
		||||
              "src/styles.scss"
 | 
			
		||||
              "src/styles.scss",
 | 
			
		||||
              {
 | 
			
		||||
                "input": "src/app/styles/light.scss",
 | 
			
		||||
                "bundleName": "light",
 | 
			
		||||
                "inject": false
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                "input": "src/app/styles/dark.scss",
 | 
			
		||||
                "bundleName": "dark",
 | 
			
		||||
                "inject": false
 | 
			
		||||
              }
 | 
			
		||||
            ],
 | 
			
		||||
            "scripts": [],
 | 
			
		||||
            "vendorChunk": true,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -291,6 +291,23 @@
 | 
			
		|||
        "tslib": "^2.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@angular/cdk": {
 | 
			
		||||
      "version": "12.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-uCWHk/PjddNJsdrmexasphWGbf4kYtYyhUCSd4HEBrIDjYz166MTVSr3FHgn/s8/tlVou7uTnaEZM+ILWoe2iQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "parse5": "^5.0.0",
 | 
			
		||||
        "tslib": "^2.2.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "parse5": {
 | 
			
		||||
          "version": "5.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@angular/cli": {
 | 
			
		||||
      "version": "12.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.1.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -491,6 +508,14 @@
 | 
			
		|||
        "tslib": "^2.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@angular/material": {
 | 
			
		||||
      "version": "12.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@angular/material/-/material-12.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-ekkg3MDEN133NhcE0du7a69lFAIFyvK6Va+YRTxYQE0BCNVMTWXtGbOXZLovDMjgo1xdXwrEJrMRBeYo+FIttA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "tslib": "^2.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@angular/platform-browser": {
 | 
			
		||||
      "version": "12.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.1.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -1699,6 +1724,22 @@
 | 
			
		|||
        "enhanced-resolve": "5.8.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@ngx-translate/core": {
 | 
			
		||||
      "version": "13.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-13.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-+tzEp8wlqEnw0Gc7jtVRAJ6RteUjXw6JJR4O65KlnxOmJrCGPI0xjV/lKRnQeU0w4i96PQs/jtpL921Wrb7PWg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "tslib": "^2.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@ngx-translate/http-loader": {
 | 
			
		||||
      "version": "6.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-6.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-LCekn6qCbeXWlhESCxU1rAbZz33WzDG0lI7Ig0pYC1o5YxJWrkU9y3Y4tNi+jakQ7R6YhTR2D3ox6APxDtA0wA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "tslib": "^2.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@nodelib/fs.scandir": {
 | 
			
		||||
      "version": "2.1.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2725,6 +2766,16 @@
 | 
			
		|||
      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "bindings": {
 | 
			
		||||
      "version": "1.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
 | 
			
		||||
      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "file-uri-to-path": "1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "bl": {
 | 
			
		||||
      "version": "4.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2819,6 +2870,11 @@
 | 
			
		|||
      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "bootstrap": {
 | 
			
		||||
      "version": "5.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-1Ge963tyEQWJJ+8qtXFU6wgmAVj9gweEjibUdbmcCEYsn38tVwRk8107rk2vzt6cfQcRr3SlZ8aQBqaD8aqf+Q=="
 | 
			
		||||
    },
 | 
			
		||||
    "brace-expansion": {
 | 
			
		||||
      "version": "1.1.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4978,6 +5034,13 @@
 | 
			
		|||
        "escape-string-regexp": "^1.0.5"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "file-uri-to-path": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true
 | 
			
		||||
    },
 | 
			
		||||
    "fill-range": {
 | 
			
		||||
      "version": "7.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5075,6 +5138,11 @@
 | 
			
		|||
      "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "font-awesome": {
 | 
			
		||||
      "version": "4.7.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
 | 
			
		||||
      "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
 | 
			
		||||
    },
 | 
			
		||||
    "for-in": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -7430,6 +7498,13 @@
 | 
			
		|||
      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "nan": {
 | 
			
		||||
      "version": "2.14.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
 | 
			
		||||
      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true
 | 
			
		||||
    },
 | 
			
		||||
    "nanoid": {
 | 
			
		||||
      "version": "3.1.23",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -12599,7 +12674,11 @@
 | 
			
		|||
          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
 | 
			
		||||
          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "bindings": "^1.5.0",
 | 
			
		||||
            "nan": "^2.12.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "glob-parent": {
 | 
			
		||||
          "version": "3.1.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,13 +12,19 @@
 | 
			
		|||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@angular/animations": "~12.1.3",
 | 
			
		||||
    "@angular/cdk": "^12.1.3",
 | 
			
		||||
    "@angular/common": "~12.1.3",
 | 
			
		||||
    "@angular/compiler": "~12.1.3",
 | 
			
		||||
    "@angular/core": "~12.1.3",
 | 
			
		||||
    "@angular/forms": "~12.1.3",
 | 
			
		||||
    "@angular/material": "^12.1.3",
 | 
			
		||||
    "@angular/platform-browser": "~12.1.3",
 | 
			
		||||
    "@angular/platform-browser-dynamic": "~12.1.3",
 | 
			
		||||
    "@angular/router": "~12.1.3",
 | 
			
		||||
    "@ngx-translate/core": "^13.0.0",
 | 
			
		||||
    "@ngx-translate/http-loader": "^6.0.0",
 | 
			
		||||
    "bootstrap": "^5.0.2",
 | 
			
		||||
    "font-awesome": "^4.7.0",
 | 
			
		||||
    "rxjs": "~6.5.5",
 | 
			
		||||
    "tslib": "^2.0.0",
 | 
			
		||||
    "zone.js": "~0.11.4"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,9 +33,9 @@
 | 
			
		|||
    "@angular-devkit/build-angular": "~12.1.3",
 | 
			
		||||
    "@angular/cli": "~12.1.3",
 | 
			
		||||
    "@angular/compiler-cli": "~12.1.3",
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
    "@types/jasmine": "~3.6.0",
 | 
			
		||||
    "@types/jasminewd2": "~2.0.3",
 | 
			
		||||
    "@types/node": "^12.11.1",
 | 
			
		||||
    "codelyzer": "^6.0.0",
 | 
			
		||||
    "jasmine-core": "~3.6.0",
 | 
			
		||||
    "jasmine-spec-reporter": "~5.0.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,3 @@
 | 
			
		|||
docker.exe compose -p curenet exec app bash -c 'cd /web/frontend && bash'
 | 
			
		||||
cd ../../docker
 | 
			
		||||
docker.exe compose -p curenet exec app bash -c 'cd /web/frontend && bash'
 | 
			
		||||
cd ../src/frontend
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,102 @@
 | 
			
		|||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { Routes, RouterModule } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forRoot(routes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class AppRoutingModule { }
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { Route, RouterModule } from '@angular/router';
 | 
			
		||||
import { NotFoundComponent } from './modules/shared/components/not-found/not-found.component';
 | 
			
		||||
 | 
			
		||||
interface AppMenuEntry {
 | 
			
		||||
  label: string;
 | 
			
		||||
  icon: string;
 | 
			
		||||
  path?: string;
 | 
			
		||||
  matchExact?: boolean;
 | 
			
		||||
  level?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface AppRoute extends Route {
 | 
			
		||||
  menuEntries?: AppMenuEntry[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const appRoutes: AppRoute[] = [
 | 
			
		||||
  {
 | 
			
		||||
    path: '',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.HOME',
 | 
			
		||||
        icon: 'fa fa-home',
 | 
			
		||||
        matchExact: true,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'profile',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.PROFILE',
 | 
			
		||||
        icon: 'fa fa-user',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'community',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.COMMUNITY',
 | 
			
		||||
        icon: 'fa fa-users',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'messages',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.MESSAGES',
 | 
			
		||||
        icon: 'fa fa-comments',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'tests',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.TESTS',
 | 
			
		||||
        icon: 'fa fa-heartbeat',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'research',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.RESEARCH',
 | 
			
		||||
        icon: 'fa fa-flask',
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'admin',
 | 
			
		||||
    loadChildren: () => import('./modules/admin/admin.module').then(m => m.AdminModule),
 | 
			
		||||
    menuEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        label: 'MENU.ADMIN',
 | 
			
		||||
        icon: 'fa fa-id-card',
 | 
			
		||||
        matchExact: true,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'admin/users',
 | 
			
		||||
        label: 'MENU.USERS',
 | 
			
		||||
        icon: 'fa fa-users',
 | 
			
		||||
        level: 1,
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forRoot(appRoutes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class AppRoutingModule { }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,73 @@
 | 
			
		|||
<router-outlet></router-outlet>
 | 
			
		||||
It's works, you can start coding :)
 | 
			
		||||
 | 
			
		||||
<ng-template #toolbar>
 | 
			
		||||
    <mat-toolbar [color]="isDark ? null : 'primary'">
 | 
			
		||||
        <button mat-icon-button (click)="toggleSidebar()">
 | 
			
		||||
          <i class="fa fa-bars"></i>
 | 
			
		||||
        </button>
 | 
			
		||||
        <span>{{ 'APP.NAME' | translate }}</span>
 | 
			
		||||
        <span class="flex-grow-1"></span>
 | 
			
		||||
    </mat-toolbar>
 | 
			
		||||
</ng-template>
 | 
			
		||||
<ng-container *ngIf="!isMobile">
 | 
			
		||||
    <ng-container *ngTemplateOutlet="toolbar"></ng-container>
 | 
			
		||||
</ng-container>
 | 
			
		||||
<mat-drawer-container class="flex-grow-1">
 | 
			
		||||
    <mat-drawer [mode]="sidebarMode" [opened]="isSidebarOpen" (openedChange)="onSidebarOpenedChange($event)">
 | 
			
		||||
        <div class="menu">
 | 
			
		||||
            <div>
 | 
			
		||||
                <ng-container *ngFor="let route of appRoutes">
 | 
			
		||||
                    <ng-container *ngIf="route.menuEntries">
 | 
			
		||||
                        <div
 | 
			
		||||
                            *ngFor="let menu of route.menuEntries"
 | 
			
		||||
                            class="menu-item"
 | 
			
		||||
                            [attr.style]="menu.level ? 'margin-left: '+(menu.level * 20)+'px' : ''"
 | 
			
		||||
                            [routerLink]="menu.path ? menu.path : route.path"
 | 
			
		||||
                            routerLinkActive="active"
 | 
			
		||||
                            [routerLinkActiveOptions]="{exact: menu.matchExact}">
 | 
			
		||||
                                <i [class]="menu.icon" [title]="menu.label | translate"></i>
 | 
			
		||||
                                <span>{{ menu.label | translate }}</span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </ng-container>
 | 
			
		||||
                </ng-container>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
            <div>
 | 
			
		||||
                <div class="d-flex user-box">
 | 
			
		||||
                    <div class="avatar" [style.background-image]="url(user.avatar)"></div>
 | 
			
		||||
                    <div class="d-flex align-items-center flex-grow-1 p-2">{{ user.name }} {{ user.surname }}</div>
 | 
			
		||||
                    <div class="user-menu-container">
 | 
			
		||||
                        <div class="user-menu">
 | 
			
		||||
                            <button mat-icon-button [matMenuTriggerFor]="usermenu">
 | 
			
		||||
                                <i class="fa fa-cog"></i>
 | 
			
		||||
                            </button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <mat-menu #usermenu="matMenu" yPosition="above" xPosition="before" class="w-220">
 | 
			
		||||
                            <mat-form-field class="w-100 px-3">
 | 
			
		||||
                                <mat-label>{{ 'APP.LANGUAGE' | translate }}</mat-label>
 | 
			
		||||
                                <mat-select [formControl]="langControl">
 | 
			
		||||
                                    <mat-option *ngFor="let lang of langs" [value]="lang">{{ 'LANGUAGE.'+lang.toUpperCase() | translate }}</mat-option>
 | 
			
		||||
                                </mat-select>
 | 
			
		||||
                            </mat-form-field>
 | 
			
		||||
            
 | 
			
		||||
                            <mat-form-field class="w-100 px-3">
 | 
			
		||||
                                <mat-label>{{ 'APP.THEME' | translate }}</mat-label>
 | 
			
		||||
                                <mat-select [formControl]="themeControl">
 | 
			
		||||
                                    <mat-option *ngFor="let theme of themes" [value]="theme">{{ 'THEME.'+theme.toUpperCase() | translate }}</mat-option>
 | 
			
		||||
                                </mat-select>
 | 
			
		||||
                            </mat-form-field>
 | 
			
		||||
                        </mat-menu>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </mat-drawer>
 | 
			
		||||
  
 | 
			
		||||
    <ng-container *ngIf="isMobile">
 | 
			
		||||
        <ng-container *ngTemplateOutlet="toolbar"></ng-container>
 | 
			
		||||
    </ng-container>
 | 
			
		||||
    
 | 
			
		||||
    <div class="example-sidenav-content">
 | 
			
		||||
      <router-outlet></router-outlet>
 | 
			
		||||
    </div>
 | 
			
		||||
</mat-drawer-container>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
$sidebar-width: 250px;
 | 
			
		||||
:host{
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
    left: 0px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
.menu{
 | 
			
		||||
    width: $sidebar-width;
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    > :first-child{
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
    }
 | 
			
		||||
    > * {
 | 
			
		||||
        width: $sidebar-width;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
.avatar{
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    height: 48px;
 | 
			
		||||
    border-radius: 10px;
 | 
			
		||||
    background-color: rgba(0,0,0, 0.25);
 | 
			
		||||
    background-position: center;
 | 
			
		||||
    background-repeat: no-repeat;
 | 
			
		||||
    background-size: cover;
 | 
			
		||||
}
 | 
			
		||||
.menu-item{
 | 
			
		||||
    display: flex;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
    transition-duration: 400ms !important;
 | 
			
		||||
    transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important;
 | 
			
		||||
    transition-property: all !important;
 | 
			
		||||
    &:after{
 | 
			
		||||
        display: block;
 | 
			
		||||
        content: "";
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 50%;
 | 
			
		||||
        right: 0px;
 | 
			
		||||
        width: 3px;
 | 
			
		||||
        height: 0%;
 | 
			
		||||
        background: var(--primary-color);
 | 
			
		||||
        transition-duration: 400ms !important;
 | 
			
		||||
        transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important;
 | 
			
		||||
        transition-property: all !important;
 | 
			
		||||
    }
 | 
			
		||||
    &.active{
 | 
			
		||||
        &:after{
 | 
			
		||||
            top: 0%;
 | 
			
		||||
            height: 100%;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    i {
 | 
			
		||||
        width: 30px;
 | 
			
		||||
        height: 30px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        margin-right: 10px;
 | 
			
		||||
        transition: all 0.4s ease;
 | 
			
		||||
    }
 | 
			
		||||
    span{
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
        opacity: 0.75;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
.user-box{
 | 
			
		||||
    padding: 6px;
 | 
			
		||||
}
 | 
			
		||||
.user-menu-container{
 | 
			
		||||
    width: 46px;
 | 
			
		||||
    .user-menu{
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        bottom: 6px;
 | 
			
		||||
        right: 6px;
 | 
			
		||||
        height: 48px;
 | 
			
		||||
        width: 46px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,127 @@
 | 
			
		|||
import { Component } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-root',
 | 
			
		||||
  templateUrl: './app.component.html',
 | 
			
		||||
  styleUrls: ['./app.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class AppComponent {
 | 
			
		||||
  title = 'CureNet';
 | 
			
		||||
}
 | 
			
		||||
import { Component } from '@angular/core';
 | 
			
		||||
import { FormControl } from '@angular/forms';
 | 
			
		||||
import { appRoutes } from './app-routing.module';
 | 
			
		||||
import { AppService, WindowSize } from './modules/shared/services/app/app.service';
 | 
			
		||||
import { BrowserStorageService } from './modules/shared/services/browser-storage/browser-storage.service';
 | 
			
		||||
import { ThemeService } from './modules/shared/services/theme/theme.service';
 | 
			
		||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
 | 
			
		||||
 | 
			
		||||
enum SidebarOpenEnum {
 | 
			
		||||
  Default,
 | 
			
		||||
  Open,
 | 
			
		||||
  Closed,
 | 
			
		||||
}
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-root',
 | 
			
		||||
  templateUrl: './app.component.html',
 | 
			
		||||
  styleUrls: ['./app.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class AppComponent {
 | 
			
		||||
  isMobile = true;
 | 
			
		||||
  title = 'CureNet';
 | 
			
		||||
  sidebarOpen = SidebarOpenEnum.Default;
 | 
			
		||||
  sidebarMode = 'over';
 | 
			
		||||
  defaultSidebarOpen = false;
 | 
			
		||||
  lang: string;
 | 
			
		||||
  theme: string;
 | 
			
		||||
  langs: string[] = [];
 | 
			
		||||
  themes: string[] = [];
 | 
			
		||||
  themeControl = new FormControl();
 | 
			
		||||
  langControl = new FormControl();
 | 
			
		||||
  isDark = true;
 | 
			
		||||
  appRoutes = appRoutes;
 | 
			
		||||
  user = {
 | 
			
		||||
      name: 'Name',
 | 
			
		||||
      surname: 'Surname',
 | 
			
		||||
      avatar: 'https://www.gravatar.com/avatar/81b206a89f89d5b1123b87606075c6a8?s=514&d=robohash',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  get isSidebarOpen() {
 | 
			
		||||
    switch (this.sidebarOpen) {
 | 
			
		||||
      case SidebarOpenEnum.Open:
 | 
			
		||||
        return true;
 | 
			
		||||
        break;
 | 
			
		||||
      case SidebarOpenEnum.Closed:
 | 
			
		||||
        return false;
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        return this.defaultSidebarOpen;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    appService: AppService,
 | 
			
		||||
    themeService: ThemeService,
 | 
			
		||||
    private browserStorageService: BrowserStorageService,
 | 
			
		||||
    private sanitizer: DomSanitizer,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.themes = themeService.getThemes();
 | 
			
		||||
    this.langs = appService.getLangs();
 | 
			
		||||
    this.lang = appService.getLang();
 | 
			
		||||
 | 
			
		||||
    this.themeControl.valueChanges.subscribe(theme => {
 | 
			
		||||
      themeService.setTheme(theme);
 | 
			
		||||
    });
 | 
			
		||||
    appService.changeLang(this.lang);
 | 
			
		||||
    this.langControl.valueChanges.subscribe(lang => {
 | 
			
		||||
      appService.changeLang(lang);
 | 
			
		||||
    });
 | 
			
		||||
    this.onThemeChanged(themeService.getTheme());
 | 
			
		||||
    themeService.themeChange.subscribe(theme => {
 | 
			
		||||
      this.onThemeChanged(theme);
 | 
			
		||||
    });
 | 
			
		||||
    this.onResize(appService.size);
 | 
			
		||||
    appService.sizeChange.subscribe(size => {
 | 
			
		||||
      this.onResize(size);
 | 
			
		||||
    });
 | 
			
		||||
    this.onLangChanged(appService.getLang());
 | 
			
		||||
    appService.langChange.subscribe(lang => {
 | 
			
		||||
      this.onLangChanged(lang);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const sidebarUserPrefference = this.browserStorageService.getItem('sidebar.open');
 | 
			
		||||
    if (sidebarUserPrefference !== null) {
 | 
			
		||||
      this.sidebarOpen = sidebarUserPrefference;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onThemeChanged(theme: string) {
 | 
			
		||||
    if (theme === undefined) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.theme = theme;
 | 
			
		||||
    this.themeControl.setValue(theme);
 | 
			
		||||
    this.isDark = theme.indexOf('dark') !== -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onResize(size: WindowSize) {
 | 
			
		||||
    if (size === undefined) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.isMobile = size.isMobile;
 | 
			
		||||
    this.defaultSidebarOpen = !size.isMobile;
 | 
			
		||||
    this.sidebarMode = this.isMobile ? 'over' : 'side';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onLangChanged(lang: string) {
 | 
			
		||||
    if (lang === undefined) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.lang = lang;
 | 
			
		||||
    this.langControl.setValue(lang);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  toggleSidebar() {
 | 
			
		||||
    this.sidebarOpen = this.isSidebarOpen ? SidebarOpenEnum.Closed : SidebarOpenEnum.Open;
 | 
			
		||||
    this.browserStorageService.setItem('sidebar.open', this.sidebarOpen);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onSidebarOpenedChange(opened: boolean) {
 | 
			
		||||
    this.sidebarOpen = opened ? SidebarOpenEnum.Open : SidebarOpenEnum.Closed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  url(url: string): SafeStyle {
 | 
			
		||||
    return this.sanitizer.bypassSecurityTrustStyle(`url('${url}')`);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +1,47 @@
 | 
			
		|||
import { BrowserModule } from '@angular/platform-browser';
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { AppRoutingModule } from './app-routing.module';
 | 
			
		||||
import { AppComponent } from './app.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    AppComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    BrowserModule,
 | 
			
		||||
    AppRoutingModule
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [],
 | 
			
		||||
  bootstrap: [AppComponent]
 | 
			
		||||
})
 | 
			
		||||
export class AppModule { }
 | 
			
		||||
import { BrowserModule } from '@angular/platform-browser';
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { HttpClientModule, HttpClient } from '@angular/common/http';
 | 
			
		||||
import { AppRoutingModule } from './app-routing.module';
 | 
			
		||||
import { AppComponent } from './app.component';
 | 
			
		||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 | 
			
		||||
import { MaterialModule } from './modules/material/material.module';
 | 
			
		||||
import { AppService } from './modules/shared/services/app/app.service';
 | 
			
		||||
import { ThemeService } from './modules/shared/services/theme/theme.service';
 | 
			
		||||
import { BrowserStorageService } from './modules/shared/services/browser-storage/browser-storage.service';
 | 
			
		||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 | 
			
		||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
 | 
			
		||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
 | 
			
		||||
 | 
			
		||||
export function HttpLoaderFactory(http: HttpClient) {
 | 
			
		||||
  return new TranslateHttpLoader(http, '/assets/lang/', '.json');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    AppComponent,
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    BrowserModule,
 | 
			
		||||
    AppRoutingModule,
 | 
			
		||||
    BrowserAnimationsModule,
 | 
			
		||||
    MaterialModule,
 | 
			
		||||
    FormsModule,
 | 
			
		||||
    ReactiveFormsModule,
 | 
			
		||||
    HttpClientModule,
 | 
			
		||||
    TranslateModule.forRoot({
 | 
			
		||||
      defaultLanguage: 'en',
 | 
			
		||||
      loader: {
 | 
			
		||||
        provide: TranslateLoader,
 | 
			
		||||
        useFactory: HttpLoaderFactory,
 | 
			
		||||
        deps: [HttpClient]
 | 
			
		||||
      }
 | 
			
		||||
    }),
 | 
			
		||||
  ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    AppService,
 | 
			
		||||
    ThemeService,
 | 
			
		||||
    BrowserStorageService,
 | 
			
		||||
  ],
 | 
			
		||||
  bootstrap: [AppComponent]
 | 
			
		||||
})
 | 
			
		||||
export class AppModule { }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Route } from '@angular/router';
 | 
			
		||||
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
 | 
			
		||||
 | 
			
		||||
const routes: Route[] = [
 | 
			
		||||
  {
 | 
			
		||||
    path: '',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: 'users',
 | 
			
		||||
    component: NotFoundComponent,
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  imports: [RouterModule.forChild(routes)],
 | 
			
		||||
  exports: [RouterModule]
 | 
			
		||||
})
 | 
			
		||||
export class AdminRoutingModule { }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { CommonModule } from '@angular/common';
 | 
			
		||||
 | 
			
		||||
import { AdminRoutingModule } from './admin-routing.module';
 | 
			
		||||
import { SharedModule } from '../shared/shared.module';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    AdminRoutingModule,
 | 
			
		||||
    SharedModule,
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class AdminModule { }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { CommonModule } from '@angular/common';
 | 
			
		||||
import {MatToolbarModule} from '@angular/material/toolbar';
 | 
			
		||||
import {MatButtonModule} from '@angular/material/button';
 | 
			
		||||
import {MatSidenavModule} from '@angular/material/sidenav';
 | 
			
		||||
import {MatSelectModule} from '@angular/material/select';
 | 
			
		||||
import {MatMenuModule} from '@angular/material/menu';
 | 
			
		||||
 | 
			
		||||
const itemsToExport = [
 | 
			
		||||
  MatToolbarModule,
 | 
			
		||||
  MatButtonModule,
 | 
			
		||||
  MatSidenavModule,
 | 
			
		||||
  MatSelectModule,
 | 
			
		||||
  MatMenuModule,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    ...itemsToExport,
 | 
			
		||||
  ],
 | 
			
		||||
  exports: [
 | 
			
		||||
    ...itemsToExport,
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class MaterialModule { }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
<div class="m-3 p-3">
 | 
			
		||||
    {{ 'ERROR.PAGE_NOT_FOUND' | translate }}
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-not-found',
 | 
			
		||||
  templateUrl: './not-found.component.html',
 | 
			
		||||
  styleUrls: ['./not-found.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class NotFoundComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  constructor() { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { fromEvent, Subject } from 'rxjs';
 | 
			
		||||
import { BrowserStorageService } from '../browser-storage/browser-storage.service';
 | 
			
		||||
 | 
			
		||||
export class WindowSize {
 | 
			
		||||
  isMobile: boolean;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    public width: number,
 | 
			
		||||
    public height: number,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.isMobile = this.width <= 700;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  update() {
 | 
			
		||||
    this.width = window.innerWidth;
 | 
			
		||||
    this.height = window.innerHeight;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static generate() {
 | 
			
		||||
    return new WindowSize(window.innerWidth, window.innerHeight);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class AppService {
 | 
			
		||||
  private lang = 'en';
 | 
			
		||||
  private defaultLang = 'en';
 | 
			
		||||
  langChange = new Subject<string>();
 | 
			
		||||
  size: WindowSize;
 | 
			
		||||
  sizeChange = new Subject<WindowSize>();
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    browserStorageService: BrowserStorageService,
 | 
			
		||||
    private translate: TranslateService,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.langChange.subscribe(lang => {
 | 
			
		||||
      this.lang = lang;
 | 
			
		||||
      browserStorageService.setItem('language', lang);
 | 
			
		||||
    });
 | 
			
		||||
    this.sizeChange.subscribe(size => this.size = size);
 | 
			
		||||
    this.sizeChange.next(WindowSize.generate());
 | 
			
		||||
    let lang = browserStorageService.getItem('language');
 | 
			
		||||
    if (!lang) {
 | 
			
		||||
      lang = this.defaultLang;
 | 
			
		||||
    }
 | 
			
		||||
    this.translate.setDefaultLang(this.defaultLang);
 | 
			
		||||
    this.changeLang(lang);
 | 
			
		||||
    fromEvent(window, 'resize').subscribe(e => {
 | 
			
		||||
      this.sizeChange.next(WindowSize.generate());
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  changeLang(lang: string) {
 | 
			
		||||
    if (lang !== this.lang) {
 | 
			
		||||
      this.translate.use(lang);
 | 
			
		||||
      this.langChange.next(lang);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getLang() {
 | 
			
		||||
    return this.lang;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getLangs() {
 | 
			
		||||
    return [
 | 
			
		||||
      'pl',
 | 
			
		||||
      'en',
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
import { Injectable } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class BrowserStorageService {
 | 
			
		||||
 | 
			
		||||
  private storage: Storage;
 | 
			
		||||
  private namespace: string;
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.storage = localStorage;
 | 
			
		||||
    this.namespace = 'default';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setNamespace(namespace: string) {
 | 
			
		||||
    this.namespace = namespace;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getNamespace(namespace: string | null = null): string {
 | 
			
		||||
    return namespace ?? this.namespace;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setItem(key: string, value: any, namespace: string | null = null) {
 | 
			
		||||
    namespace = this.getNamespace(namespace);
 | 
			
		||||
    const path = `${namespace}.${key}`;
 | 
			
		||||
    this.storage.setItem(path, JSON.stringify(value));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getItem(key: string, namespace: string | null = null): any {
 | 
			
		||||
    namespace = this.getNamespace(namespace);
 | 
			
		||||
    const path = `${namespace}.${key}`;
 | 
			
		||||
    return JSON.parse(this.storage.getItem(path) ?? 'null');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getItemOrDefault(key: string, defaultValue: any, namespace: string | null = null): any {
 | 
			
		||||
    return this.getItem(key, namespace) ?? defaultValue;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
import { BrowserStorageService } from '../browser-storage/browser-storage.service';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class ThemeService {
 | 
			
		||||
    private theme: string;
 | 
			
		||||
    themeChange = new Subject<string>();
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        browserStorageService: BrowserStorageService
 | 
			
		||||
    ) {
 | 
			
		||||
        this.themeChange.subscribe(theme => {
 | 
			
		||||
            this.theme = theme;
 | 
			
		||||
            browserStorageService.setItem('current-theme', theme);
 | 
			
		||||
        });
 | 
			
		||||
        let userTheme = browserStorageService.getItem('current-theme');
 | 
			
		||||
        if (!userTheme) {
 | 
			
		||||
            userTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
 | 
			
		||||
        }
 | 
			
		||||
        this.setTheme(userTheme);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getTheme() {
 | 
			
		||||
        return this.theme;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTheme(theme: string) {
 | 
			
		||||
        if (theme !== this.theme) {
 | 
			
		||||
            this.themeChange.next(theme);
 | 
			
		||||
            document.getElementById('current-theme').setAttribute('href', `/${theme}.css`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getThemes(): string[] {
 | 
			
		||||
        return [
 | 
			
		||||
            'light',
 | 
			
		||||
            'dark',
 | 
			
		||||
        ];
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { CommonModule } from '@angular/common';
 | 
			
		||||
import { NotFoundComponent } from './components/not-found/not-found.component';
 | 
			
		||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
 | 
			
		||||
import { HttpLoaderFactory } from 'src/app/app.module';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    NotFoundComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
    TranslateModule.forRoot({
 | 
			
		||||
        defaultLanguage: 'en',
 | 
			
		||||
        loader: {
 | 
			
		||||
          provide: TranslateLoader,
 | 
			
		||||
          useFactory: HttpLoaderFactory,
 | 
			
		||||
          deps: [HttpClient]
 | 
			
		||||
        }
 | 
			
		||||
      }),
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class SharedModule { }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
@use 'sass:map';
 | 
			
		||||
 | 
			
		||||
$primary-color: map.get($theme, color, primary, 500);
 | 
			
		||||
body {
 | 
			
		||||
    --primary-color: #{$primary-color};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,398 @@
 | 
			
		|||
$theme: (
 | 
			
		||||
  color: (
 | 
			
		||||
    primary: (
 | 
			
		||||
      50: #e8eaf6,
 | 
			
		||||
      100: #c5cae9,
 | 
			
		||||
      200: #9fa8da,
 | 
			
		||||
      300: #7986cb,
 | 
			
		||||
      400: #5c6bc0,
 | 
			
		||||
      500: #3f51b5,
 | 
			
		||||
      600: #3949ab,
 | 
			
		||||
      700: #303f9f,
 | 
			
		||||
      800: #283593,
 | 
			
		||||
      900: #1a237e,
 | 
			
		||||
      A100: #8c9eff,
 | 
			
		||||
      A200: #536dfe,
 | 
			
		||||
      A400: #3d5afe,
 | 
			
		||||
      A700: #304ffe,
 | 
			
		||||
      contrast: (
 | 
			
		||||
        50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        300: white,
 | 
			
		||||
        400: white,
 | 
			
		||||
        500: white,
 | 
			
		||||
        600: white,
 | 
			
		||||
        700: white,
 | 
			
		||||
        800: white,
 | 
			
		||||
        900: white,
 | 
			
		||||
        A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        A200: white,
 | 
			
		||||
        A400: white,
 | 
			
		||||
        A700: white,
 | 
			
		||||
      ),
 | 
			
		||||
      default: #3f51b5,
 | 
			
		||||
      lighter: #c5cae9,
 | 
			
		||||
      darker: #303f9f,
 | 
			
		||||
      text: #3f51b5,
 | 
			
		||||
      default-contrast: white,
 | 
			
		||||
      lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      darker-contrast: white,
 | 
			
		||||
      "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "300-contrast": white,
 | 
			
		||||
      "400-contrast": white,
 | 
			
		||||
      "500-contrast": white,
 | 
			
		||||
      "600-contrast": white,
 | 
			
		||||
      "700-contrast": white,
 | 
			
		||||
      "800-contrast": white,
 | 
			
		||||
      "900-contrast": white,
 | 
			
		||||
      "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "A200-contrast": white,
 | 
			
		||||
      "A400-contrast": white,
 | 
			
		||||
      "A700-contrast": white,
 | 
			
		||||
      "contrast-contrast": null,
 | 
			
		||||
    ),
 | 
			
		||||
    accent: (
 | 
			
		||||
      50: #fce4ec,
 | 
			
		||||
      100: #f8bbd0,
 | 
			
		||||
      200: #f48fb1,
 | 
			
		||||
      300: #f06292,
 | 
			
		||||
      400: #ec407a,
 | 
			
		||||
      500: #e91e63,
 | 
			
		||||
      600: #d81b60,
 | 
			
		||||
      700: #c2185b,
 | 
			
		||||
      800: #ad1457,
 | 
			
		||||
      900: #880e4f,
 | 
			
		||||
      A100: #ff80ab,
 | 
			
		||||
      A200: #ff4081,
 | 
			
		||||
      A400: #f50057,
 | 
			
		||||
      A700: #c51162,
 | 
			
		||||
      contrast: (
 | 
			
		||||
        50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        300: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        400: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        500: white,
 | 
			
		||||
        600: white,
 | 
			
		||||
        700: white,
 | 
			
		||||
        800: white,
 | 
			
		||||
        900: white,
 | 
			
		||||
        A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        A200: white,
 | 
			
		||||
        A400: white,
 | 
			
		||||
        A700: white,
 | 
			
		||||
      ),
 | 
			
		||||
      default: #ff4081,
 | 
			
		||||
      lighter: #ff80ab,
 | 
			
		||||
      darker: #f50057,
 | 
			
		||||
      text: #ff4081,
 | 
			
		||||
      default-contrast: white,
 | 
			
		||||
      lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      darker-contrast: white,
 | 
			
		||||
      "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "300-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "400-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "500-contrast": white,
 | 
			
		||||
      "600-contrast": white,
 | 
			
		||||
      "700-contrast": white,
 | 
			
		||||
      "800-contrast": white,
 | 
			
		||||
      "900-contrast": white,
 | 
			
		||||
      "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "A200-contrast": white,
 | 
			
		||||
      "A400-contrast": white,
 | 
			
		||||
      "A700-contrast": white,
 | 
			
		||||
      "contrast-contrast": null,
 | 
			
		||||
    ),
 | 
			
		||||
    warn: (
 | 
			
		||||
      50: #ffebee,
 | 
			
		||||
      100: #ffcdd2,
 | 
			
		||||
      200: #ef9a9a,
 | 
			
		||||
      300: #e57373,
 | 
			
		||||
      400: #ef5350,
 | 
			
		||||
      500: #f44336,
 | 
			
		||||
      600: #e53935,
 | 
			
		||||
      700: #d32f2f,
 | 
			
		||||
      800: #c62828,
 | 
			
		||||
      900: #b71c1c,
 | 
			
		||||
      A100: #ff8a80,
 | 
			
		||||
      A200: #ff5252,
 | 
			
		||||
      A400: #ff1744,
 | 
			
		||||
      A700: #d50000,
 | 
			
		||||
      contrast: (
 | 
			
		||||
        50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        300: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        400: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        500: white,
 | 
			
		||||
        600: white,
 | 
			
		||||
        700: white,
 | 
			
		||||
        800: white,
 | 
			
		||||
        900: white,
 | 
			
		||||
        A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
        A200: white,
 | 
			
		||||
        A400: white,
 | 
			
		||||
        A700: white,
 | 
			
		||||
      ),
 | 
			
		||||
      default: #f44336,
 | 
			
		||||
      lighter: #ffcdd2,
 | 
			
		||||
      darker: #d32f2f,
 | 
			
		||||
      text: #f44336,
 | 
			
		||||
      default-contrast: white,
 | 
			
		||||
      lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      darker-contrast: white,
 | 
			
		||||
      "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "300-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "400-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "500-contrast": white,
 | 
			
		||||
      "600-contrast": white,
 | 
			
		||||
      "700-contrast": white,
 | 
			
		||||
      "800-contrast": white,
 | 
			
		||||
      "900-contrast": white,
 | 
			
		||||
      "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
      "A200-contrast": white,
 | 
			
		||||
      "A400-contrast": white,
 | 
			
		||||
      "A700-contrast": white,
 | 
			
		||||
      "contrast-contrast": null,
 | 
			
		||||
    ),
 | 
			
		||||
    is-dark: true,
 | 
			
		||||
    foreground: (
 | 
			
		||||
      base: white,
 | 
			
		||||
      divider: rgba(255, 255, 255, 0.12),
 | 
			
		||||
      dividers: rgba(255, 255, 255, 0.12),
 | 
			
		||||
      disabled: rgba(255, 255, 255, 0.5),
 | 
			
		||||
      disabled-button: rgba(255, 255, 255, 0.3),
 | 
			
		||||
      disabled-text: rgba(255, 255, 255, 0.5),
 | 
			
		||||
      elevation: black,
 | 
			
		||||
      hint-text: rgba(255, 255, 255, 0.5),
 | 
			
		||||
      secondary-text: rgba(255, 255, 255, 0.7),
 | 
			
		||||
      icon: white,
 | 
			
		||||
      icons: white,
 | 
			
		||||
      text: white,
 | 
			
		||||
      slider-min: white,
 | 
			
		||||
      slider-off: rgba(255, 255, 255, 0.3),
 | 
			
		||||
      slider-off-active: rgba(255, 255, 255, 0.3),
 | 
			
		||||
    ),
 | 
			
		||||
    background: (
 | 
			
		||||
      status-bar: black,
 | 
			
		||||
      app-bar: #212121,
 | 
			
		||||
      background: #303030,
 | 
			
		||||
      hover: rgba(255, 255, 255, 0.04),
 | 
			
		||||
      card: #424242,
 | 
			
		||||
      dialog: #424242,
 | 
			
		||||
      disabled-button: rgba(255, 255, 255, 0.12),
 | 
			
		||||
      raised-button: #424242,
 | 
			
		||||
      focused-button: rgba(255, 255, 255, 0.12),
 | 
			
		||||
      selected-button: #212121,
 | 
			
		||||
      selected-disabled-button: #424242,
 | 
			
		||||
      disabled-button-toggle: black,
 | 
			
		||||
      unselected-chip: #616161,
 | 
			
		||||
      disabled-list-option: black,
 | 
			
		||||
      tooltip: #616161,
 | 
			
		||||
    ),
 | 
			
		||||
  ),
 | 
			
		||||
  primary: (
 | 
			
		||||
    50: #e8eaf6,
 | 
			
		||||
    100: #c5cae9,
 | 
			
		||||
    200: #9fa8da,
 | 
			
		||||
    300: #7986cb,
 | 
			
		||||
    400: #5c6bc0,
 | 
			
		||||
    500: #3f51b5,
 | 
			
		||||
    600: #3949ab,
 | 
			
		||||
    700: #303f9f,
 | 
			
		||||
    800: #283593,
 | 
			
		||||
    900: #1a237e,
 | 
			
		||||
    A100: #8c9eff,
 | 
			
		||||
    A200: #536dfe,
 | 
			
		||||
    A400: #3d5afe,
 | 
			
		||||
    A700: #304ffe,
 | 
			
		||||
    contrast: (
 | 
			
		||||
      50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      300: white,
 | 
			
		||||
      400: white,
 | 
			
		||||
      500: white,
 | 
			
		||||
      600: white,
 | 
			
		||||
      700: white,
 | 
			
		||||
      800: white,
 | 
			
		||||
      900: white,
 | 
			
		||||
      A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      A200: white,
 | 
			
		||||
      A400: white,
 | 
			
		||||
      A700: white,
 | 
			
		||||
    ),
 | 
			
		||||
    default: #3f51b5,
 | 
			
		||||
    lighter: #c5cae9,
 | 
			
		||||
    darker: #303f9f,
 | 
			
		||||
    text: #3f51b5,
 | 
			
		||||
    default-contrast: white,
 | 
			
		||||
    lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
    darker-contrast: white,
 | 
			
		||||
    "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "300-contrast": white,
 | 
			
		||||
    "400-contrast": white,
 | 
			
		||||
    "500-contrast": white,
 | 
			
		||||
    "600-contrast": white,
 | 
			
		||||
    "700-contrast": white,
 | 
			
		||||
    "800-contrast": white,
 | 
			
		||||
    "900-contrast": white,
 | 
			
		||||
    "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "A200-contrast": white,
 | 
			
		||||
    "A400-contrast": white,
 | 
			
		||||
    "A700-contrast": white,
 | 
			
		||||
    "contrast-contrast": null,
 | 
			
		||||
  ),
 | 
			
		||||
  accent: (
 | 
			
		||||
    50: #fce4ec,
 | 
			
		||||
    100: #f8bbd0,
 | 
			
		||||
    200: #f48fb1,
 | 
			
		||||
    300: #f06292,
 | 
			
		||||
    400: #ec407a,
 | 
			
		||||
    500: #e91e63,
 | 
			
		||||
    600: #d81b60,
 | 
			
		||||
    700: #c2185b,
 | 
			
		||||
    800: #ad1457,
 | 
			
		||||
    900: #880e4f,
 | 
			
		||||
    A100: #ff80ab,
 | 
			
		||||
    A200: #ff4081,
 | 
			
		||||
    A400: #f50057,
 | 
			
		||||
    A700: #c51162,
 | 
			
		||||
    contrast: (
 | 
			
		||||
      50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      300: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      400: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      500: white,
 | 
			
		||||
      600: white,
 | 
			
		||||
      700: white,
 | 
			
		||||
      800: white,
 | 
			
		||||
      900: white,
 | 
			
		||||
      A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      A200: white,
 | 
			
		||||
      A400: white,
 | 
			
		||||
      A700: white,
 | 
			
		||||
    ),
 | 
			
		||||
    default: #ff4081,
 | 
			
		||||
    lighter: #ff80ab,
 | 
			
		||||
    darker: #f50057,
 | 
			
		||||
    text: #ff4081,
 | 
			
		||||
    default-contrast: white,
 | 
			
		||||
    lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
    darker-contrast: white,
 | 
			
		||||
    "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "300-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "400-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "500-contrast": white,
 | 
			
		||||
    "600-contrast": white,
 | 
			
		||||
    "700-contrast": white,
 | 
			
		||||
    "800-contrast": white,
 | 
			
		||||
    "900-contrast": white,
 | 
			
		||||
    "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "A200-contrast": white,
 | 
			
		||||
    "A400-contrast": white,
 | 
			
		||||
    "A700-contrast": white,
 | 
			
		||||
    "contrast-contrast": null,
 | 
			
		||||
  ),
 | 
			
		||||
  warn: (
 | 
			
		||||
    50: #ffebee,
 | 
			
		||||
    100: #ffcdd2,
 | 
			
		||||
    200: #ef9a9a,
 | 
			
		||||
    300: #e57373,
 | 
			
		||||
    400: #ef5350,
 | 
			
		||||
    500: #f44336,
 | 
			
		||||
    600: #e53935,
 | 
			
		||||
    700: #d32f2f,
 | 
			
		||||
    800: #c62828,
 | 
			
		||||
    900: #b71c1c,
 | 
			
		||||
    A100: #ff8a80,
 | 
			
		||||
    A200: #ff5252,
 | 
			
		||||
    A400: #ff1744,
 | 
			
		||||
    A700: #d50000,
 | 
			
		||||
    contrast: (
 | 
			
		||||
      50: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      200: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      300: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      400: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      500: white,
 | 
			
		||||
      600: white,
 | 
			
		||||
      700: white,
 | 
			
		||||
      800: white,
 | 
			
		||||
      900: white,
 | 
			
		||||
      A100: rgba(0, 0, 0, 0.87),
 | 
			
		||||
      A200: white,
 | 
			
		||||
      A400: white,
 | 
			
		||||
      A700: white,
 | 
			
		||||
    ),
 | 
			
		||||
    default: #f44336,
 | 
			
		||||
    lighter: #ffcdd2,
 | 
			
		||||
    darker: #d32f2f,
 | 
			
		||||
    text: #f44336,
 | 
			
		||||
    default-contrast: white,
 | 
			
		||||
    lighter-contrast: rgba(0, 0, 0, 0.87),
 | 
			
		||||
    darker-contrast: white,
 | 
			
		||||
    "50-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "200-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "300-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "400-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "500-contrast": white,
 | 
			
		||||
    "600-contrast": white,
 | 
			
		||||
    "700-contrast": white,
 | 
			
		||||
    "800-contrast": white,
 | 
			
		||||
    "900-contrast": white,
 | 
			
		||||
    "A100-contrast": rgba(0, 0, 0, 0.87),
 | 
			
		||||
    "A200-contrast": white,
 | 
			
		||||
    "A400-contrast": white,
 | 
			
		||||
    "A700-contrast": white,
 | 
			
		||||
    "contrast-contrast": null,
 | 
			
		||||
  ),
 | 
			
		||||
  is-dark: true,
 | 
			
		||||
  foreground: (
 | 
			
		||||
    base: white,
 | 
			
		||||
    divider: rgba(255, 255, 255, 0.12),
 | 
			
		||||
    dividers: rgba(255, 255, 255, 0.12),
 | 
			
		||||
    disabled: rgba(255, 255, 255, 0.5),
 | 
			
		||||
    disabled-button: rgba(255, 255, 255, 0.3),
 | 
			
		||||
    disabled-text: rgba(255, 255, 255, 0.5),
 | 
			
		||||
    elevation: black,
 | 
			
		||||
    hint-text: rgba(255, 255, 255, 0.5),
 | 
			
		||||
    secondary-text: rgba(255, 255, 255, 0.7),
 | 
			
		||||
    icon: white,
 | 
			
		||||
    icons: white,
 | 
			
		||||
    text: white,
 | 
			
		||||
    slider-min: white,
 | 
			
		||||
    slider-off: rgba(255, 255, 255, 0.3),
 | 
			
		||||
    slider-off-active: rgba(255, 255, 255, 0.3),
 | 
			
		||||
  ),
 | 
			
		||||
  background: (
 | 
			
		||||
    status-bar: black,
 | 
			
		||||
    app-bar: #212121,
 | 
			
		||||
    background: #303030,
 | 
			
		||||
    hover: rgba(255, 255, 255, 0.04),
 | 
			
		||||
    card: #424242,
 | 
			
		||||
    dialog: #424242,
 | 
			
		||||
    disabled-button: rgba(255, 255, 255, 0.12),
 | 
			
		||||
    raised-button: #424242,
 | 
			
		||||
    focused-button: rgba(255, 255, 255, 0.12),
 | 
			
		||||
    selected-button: #212121,
 | 
			
		||||
    selected-disabled-button: #424242,
 | 
			
		||||
    disabled-button-toggle: black,
 | 
			
		||||
    unselected-chip: #616161,
 | 
			
		||||
    disabled-list-option: black,
 | 
			
		||||
    tooltip: #616161,
 | 
			
		||||
  ),
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
// Custom Theming for Angular Material
 | 
			
		||||
// For more information: https://material.angular.io/guide/theming
 | 
			
		||||
@use '~@angular/material' as mat;
 | 
			
		||||
// Plus imports for other components in your app.
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// Be sure that you only ever include this mixin once!
 | 
			
		||||
@include mat.core();
 | 
			
		||||
 | 
			
		||||
// Define the palettes for your theme using the Material Design palettes available in palette.scss
 | 
			
		||||
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
 | 
			
		||||
// hue. Available color palettes: https://material.io/design/color/
 | 
			
		||||
$theme-primary: mat.define-palette(mat.$blue-palette);
 | 
			
		||||
$theme-accent: mat.define-palette(mat.$green-palette, A200, A100, A400);
 | 
			
		||||
 | 
			
		||||
// The warn palette is optional (defaults to red).
 | 
			
		||||
$theme-warn: mat.define-palette(mat.$red-palette);
 | 
			
		||||
 | 
			
		||||
// Create the theme object. A theme consists of configurations for individual
 | 
			
		||||
// theming systems such as "color" or "typography".
 | 
			
		||||
$theme: mat.define-dark-theme((
 | 
			
		||||
  color: (
 | 
			
		||||
    primary: $theme-primary,
 | 
			
		||||
    accent: $theme-accent,
 | 
			
		||||
    warn: $theme-warn,
 | 
			
		||||
  )
 | 
			
		||||
));
 | 
			
		||||
 | 
			
		||||
// Include theme styles for core and each component used in your app.
 | 
			
		||||
// Alternatively, you can import and @include the theme mixins for each component
 | 
			
		||||
// that you are using.
 | 
			
		||||
@include mat.all-component-themes($theme);
 | 
			
		||||
 | 
			
		||||
@import "./base";
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
// Custom Theming for Angular Material
 | 
			
		||||
// For more information: https://material.angular.io/guide/theming
 | 
			
		||||
@use '~@angular/material' as mat;
 | 
			
		||||
// Plus imports for other components in your app.
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// Be sure that you only ever include this mixin once!
 | 
			
		||||
@include mat.core();
 | 
			
		||||
 | 
			
		||||
// Define the palettes for your theme using the Material Design palettes available in palette.scss
 | 
			
		||||
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
 | 
			
		||||
// hue. Available color palettes: https://material.io/design/color/
 | 
			
		||||
$theme-primary: mat.define-palette(mat.$indigo-palette);
 | 
			
		||||
$theme-accent: mat.define-palette(mat.$light-blue-palette, A200, A100, A400);
 | 
			
		||||
 | 
			
		||||
// The warn palette is optional (defaults to red).
 | 
			
		||||
$theme-warn: mat.define-palette(mat.$red-palette);
 | 
			
		||||
 | 
			
		||||
// Create the theme object. A theme consists of configurations for individual
 | 
			
		||||
// theming systems such as "color" or "typography".
 | 
			
		||||
$theme: mat.define-light-theme((
 | 
			
		||||
  color: (
 | 
			
		||||
    primary: $theme-primary,
 | 
			
		||||
    accent: $theme-accent,
 | 
			
		||||
    warn: $theme-warn,
 | 
			
		||||
  )
 | 
			
		||||
));
 | 
			
		||||
 | 
			
		||||
// Include theme styles for core and each component used in your app.
 | 
			
		||||
// Alternatively, you can import and @include the theme mixins for each component
 | 
			
		||||
// that you are using.
 | 
			
		||||
@include mat.all-component-themes($theme);
 | 
			
		||||
 | 
			
		||||
@import "./base";
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
{
 | 
			
		||||
    "APP": {
 | 
			
		||||
        "NAME": "CureNet",
 | 
			
		||||
        "THEME": "Theme",
 | 
			
		||||
        "LANGUAGE": "Language"
 | 
			
		||||
    },
 | 
			
		||||
    "ERROR": {
 | 
			
		||||
        "PAGE_NOT_FOUND": "Page not found or not implemented yet!"
 | 
			
		||||
    },
 | 
			
		||||
    "THEME": {
 | 
			
		||||
        "LIGHT": "Light",
 | 
			
		||||
        "DARK": "Dark"
 | 
			
		||||
    },
 | 
			
		||||
    "LANGUAGE": {
 | 
			
		||||
        "PL": "Polish",
 | 
			
		||||
        "EN": "English"
 | 
			
		||||
    },
 | 
			
		||||
    "MENU": {
 | 
			
		||||
        "HOME": "Dashboard",
 | 
			
		||||
        "PROFILE": "Profile",
 | 
			
		||||
        "COMMUNITY": "Community",
 | 
			
		||||
        "MESSAGES": "Messages",
 | 
			
		||||
        "TESTS": "Laboratory tests",
 | 
			
		||||
        "RESEARCH": "Research",
 | 
			
		||||
        "ADMIN": "Admin",
 | 
			
		||||
        "USERS": "Users"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
{
 | 
			
		||||
    "APP": {
 | 
			
		||||
        "NAME": "CureNet",
 | 
			
		||||
        "THEME": "Motyw",
 | 
			
		||||
        "LANGUAGE": "Język"
 | 
			
		||||
    },
 | 
			
		||||
    "ERROR": {
 | 
			
		||||
        "PAGE_NOT_FOUND": "Nie znaleziono strony lub nie została ona jeszcze zaimplementowana!"
 | 
			
		||||
    },
 | 
			
		||||
    "THEME": {
 | 
			
		||||
        "LIGHT": "Jasny",
 | 
			
		||||
        "DARK": "Ciemny"
 | 
			
		||||
    },
 | 
			
		||||
    "LANGUAGE": {
 | 
			
		||||
        "PL": "Polski",
 | 
			
		||||
        "EN": "Angielski"
 | 
			
		||||
    },
 | 
			
		||||
    "MENU": {
 | 
			
		||||
        "HOME": "Kokpit",
 | 
			
		||||
        "PROFILE": "Profil",
 | 
			
		||||
        "COMMUNITY": "Społeczność",
 | 
			
		||||
        "MESSAGES": "Wiadomości",
 | 
			
		||||
        "TESTS": "Wyniki badań",
 | 
			
		||||
        "RESEARCH": "Badania naukowe",
 | 
			
		||||
        "ADMIN": "Panel administratora",
 | 
			
		||||
        "USERS": "Użytkownicy"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,17 @@
 | 
			
		|||
<!doctype html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="utf-8">
 | 
			
		||||
  <title>Frontend</title>
 | 
			
		||||
  <base href="/">
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
  <link rel="icon" type="image/x-icon" href="favicon.ico">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
  <app-root></app-root>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="utf-8">
 | 
			
		||||
  <title>CureNet</title>
 | 
			
		||||
  <base href="/">
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
  <link rel="icon" type="image/x-icon" href="favicon.ico">
 | 
			
		||||
  <link rel="preconnect" href="https://fonts.gstatic.com">
 | 
			
		||||
  <link rel="stylesheet" href="/light.css" id="current-theme">
 | 
			
		||||
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
 | 
			
		||||
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
  <app-root></app-root>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,45 @@
 | 
			
		|||
/* You can add global styles to this file, and also import other style files */
 | 
			
		||||
 | 
			
		||||
html, body { height: 100%; }
 | 
			
		||||
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
 | 
			
		||||
 | 
			
		||||
@import "~bootstrap/dist/css/bootstrap.css";
 | 
			
		||||
@import "~font-awesome/css/font-awesome.css";
 | 
			
		||||
 | 
			
		||||
body .mat-drawer.mat-drawer-side {
 | 
			
		||||
  visibility: visible !important;
 | 
			
		||||
  transform: none !important;
 | 
			
		||||
  width: 250px;
 | 
			
		||||
  &,
 | 
			
		||||
  & .mat-drawer-inner-container{
 | 
			
		||||
    transition-duration: 400ms !important;
 | 
			
		||||
    transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important;
 | 
			
		||||
    transition-property: transform, margin-left, margin-right, width !important;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
  }
 | 
			
		||||
  & ~ .mat-drawer-content{
 | 
			
		||||
    margin-left: 250px !important;
 | 
			
		||||
  }
 | 
			
		||||
  &:not(.mat-drawer-opened) {
 | 
			
		||||
    width: 60px;
 | 
			
		||||
    .menu-item{
 | 
			
		||||
      margin-left: 0px !important;
 | 
			
		||||
      &:after{
 | 
			
		||||
        right: 190px;
 | 
			
		||||
      }
 | 
			
		||||
      & > i{
 | 
			
		||||
        width: 40px;
 | 
			
		||||
        font-size: 120%;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .hide-on-side-opened{
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
    & ~ .mat-drawer-content {
 | 
			
		||||
      margin-left: 60px !important;
 | 
			
		||||
    }  
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.w-220{
 | 
			
		||||
  width: 220px;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue