Create UI and demo homepage #18
|
@ -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 @@
|
|||
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';
|
||||
import { Route, RouterModule } from '@angular/router';
|
||||
import { NotFoundComponent } from './modules/shared/components/not-found/not-found.component';
|
||||
|
||||
const routes: Routes = [];
|
||||
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(routes)],
|
||||
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';
|
||||
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 { 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
|
||||
AppComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
TranslateModule.forRoot({
|
||||
defaultLanguage: 'en',
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: HttpLoaderFactory,
|
||||
deps: [HttpClient]
|
||||
}
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
AppService,
|
||||
ThemeService,
|
||||
BrowserStorageService,
|
||||
],
|
||||
providers: [],
|
||||
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"
|
||||
}
|
||||
}
|
|
@ -2,10 +2,14 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Frontend</title>
|
||||
<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>
|
||||
|
|
|
@ -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