main sections, sessions, games in left menu

This commit is contained in:
svensken 2022-10-22 18:28:02 +03:00
parent d8804c0030
commit ac43777da9
60 changed files with 803 additions and 83 deletions

14
package-lock.json generated
View File

@ -25,6 +25,7 @@
"@tinkoff/ng-dompurify": "3.0.0", "@tinkoff/ng-dompurify": "3.0.0",
"dompurify": "2.2.9", "dompurify": "2.2.9",
"fast-average-color": "^9.1.1", "fast-average-color": "^9.1.1",
"moment": "^2.29.4",
"rxjs": "~7.5.0", "rxjs": "~7.5.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
@ -8044,6 +8045,14 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -17786,6 +17795,11 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
}, },
"moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View File

@ -27,6 +27,7 @@
"@tinkoff/ng-dompurify": "3.0.0", "@tinkoff/ng-dompurify": "3.0.0",
"dompurify": "2.2.9", "dompurify": "2.2.9",
"fast-average-color": "^9.1.1", "fast-average-color": "^9.1.1",
"moment": "^2.29.4",
"rxjs": "~7.5.0", "rxjs": "~7.5.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"

View File

@ -9,5 +9,10 @@
background-color: var(--sk-accent); background-color: var(--sk-accent);
border: none; border: none;
border-radius: var(--sk-br-m); border-radius: var(--sk-br-m);
cursor: pointer;
&:hover {
opacity: 0.9;
}
} }
} }

View File

@ -0,0 +1,10 @@
<div class="sk-game">
<skirda-image-icon [src]="game.image"></skirda-image-icon>
<div class="sk-game-info">
<div class="info-game-line">
<skirda-heading size="6">{{game.title}}</skirda-heading>
</div>
<skirda-text>description</skirda-text>
</div>
<skirda-icon name="play" size="16" (click)="run(game)" color="var(--sk-accent)"></skirda-icon>
</div>

View File

@ -0,0 +1,31 @@
:host {
display: block;
.sk-game {
display: flex;
align-items: center;
gap: var(--sk-gap-l);
padding: var(--sk-gap-l);
border-radius: var(--sk-br-m);
transition: 0.1s ease;
opacity: 0.5;
cursor: pointer;
&:hover {
opacity: 1;
background-color: rgba(255, 255, 255, 0.05);
}
.sk-game-info {
flex: 1;
}
}
&.active {
.sk-game {
opacity: 1;
background-color: rgba(255, 255, 255, 0.1);
}
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { GameComponent } from './game.component';
describe('GameComponent', () => {
let component: GameComponent;
let fixture: ComponentFixture<GameComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ GameComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(GameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,20 @@
import { Component, Input, OnInit } from '@angular/core';
import { Game } from 'src/app/interfaces/game.interface'
@Component({
selector: 'skirda-game[game]',
templateUrl: './game.component.html',
styleUrls: ['./game.component.scss']
})
export class GameComponent implements OnInit {
@Input() game!: Game
constructor() { }
ngOnInit(): void {
}
run(game: Game) {
console.log('Game to run ' + game.title)
}
}

View File

@ -0,0 +1,24 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GameComponent } from './game.component';
import { ImageIconModule } from '../image-icon/image-icon.module'
import { TypographyModule } from '../typography/typography.module'
import { TagModule } from '../tag/tag.module'
import { IconModule } from '../icon/icon.module'
@NgModule({
declarations: [
GameComponent
],
imports: [
CommonModule,
ImageIconModule,
TypographyModule,
TagModule,
IconModule
],
exports: [
GameComponent
]
})
export class GameModule { }

View File

@ -1,7 +1,8 @@
export interface Session { export interface Session {
id: string;
icon: string; icon: string;
title: string; title: string;
status?: string; status?: string;
version: string; version: string;
expires: string | Date; expires: Date;
} }

View File

@ -0,0 +1,8 @@
import { CountdownPipe } from './countdown.pipe';
describe('CountdownPipe', () => {
it('create an instance', () => {
const pipe = new CountdownPipe();
expect(pipe).toBeTruthy();
});
});

View File

@ -0,0 +1,28 @@
import { Pipe, PipeTransform } from '@angular/core';
import moment from 'moment'
import { map, min, timer } from 'rxjs'
@Pipe({
name: 'countdown'
})
export class CountdownPipe implements PipeTransform {
transform(value: Date) {
return timer(0, 1000).pipe(map((_) => this.getCountDown(value)))
}
getCountDown (value: Date) {
let currentTime = new Date()
let duration = moment.duration(value.getTime() - currentTime.getTime(), 'milliseconds')
let days = duration.days(), hours = duration.hours(), minutes = duration.minutes(), seconds = duration.seconds()
if (days > 0)
return `${days} ${days == 1 ? 'day' : 'days'}`
else
return `${this.pad(hours)}:${this.pad(minutes)}:${this.pad(seconds)}`
}
private pad (value: number) {
return value.toString().padStart(2, '0')
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CountdownPipe } from './countdown.pipe';
@NgModule({
declarations: [
CountdownPipe
],
imports: [
CommonModule
],
exports: [
CountdownPipe
]
})
export class PipesModule { }

View File

@ -9,32 +9,13 @@
align-items: center; align-items: center;
padding: var(--sk-gap-l); padding: var(--sk-gap-l);
gap: var(--sk-gap-l); gap: var(--sk-gap-l);
opacity: 0.75; opacity: 0.5;
mix-blend-mode: overlay; transition: 0.1s ease;
transition: 0.2s ease;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
opacity: 1; opacity: 1;
background-color: rgba(255, 255, 255, 0.05);
&:before {
opacity: 0.5;
}
}
&:before {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.2);
width: 100%;
height: 100%;
mix-blend-mode: overlay;
z-index: -1;
opacity: 0;
transition: 0.2s ease;
} }
} }
@ -42,11 +23,7 @@
.sk-section { .sk-section {
opacity: 1; opacity: 1;
mix-blend-mode: normal; background-color: rgba(255, 255, 255, 0.1);
&:before {
opacity: 1;
}
} }
} }
} }

View File

@ -1,7 +1,13 @@
<div class="sk-session"> <div class="sk-session">
<skirda-image-icon [src]="session.icon"></skirda-image-icon> <skirda-image-icon [src]="session.icon"></skirda-image-icon>
<div class="sk-session-info"> <div class="sk-session-info">
<skirda-heading size="6">{{session.title}}</skirda-heading> <div class="info-heading-line">
<skirda-text *ngIf="session.status">{{session.status}}</skirda-text> <skirda-heading size="6">{{session.title}}</skirda-heading>
<skirda-tag>{{session.expires | countdown | async}}</skirda-tag>
</div>
<div class="info-line">
<skirda-tag class="filled">{{session.version}}</skirda-tag>
<skirda-text *ngIf="session.status">{{session.status}}</skirda-text>
</div>
</div> </div>
</div> </div>

View File

@ -1,22 +1,55 @@
:host { :host {
display: block; display: block;
&.active {
.sk-session {
background-color: var(--image-accent);
}
}
.sk-session { .sk-session {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--sk-gap-l); gap: var(--sk-gap-l);
padding: var(--sk-gap-l); padding: var(--sk-gap-l);
border-radius: var(--sk-br-m); border-radius: var(--sk-br-m);
transition: 0.1s ease;
opacity: 0.5;
cursor: pointer;
&:hover {
opacity: 1;
background-color: rgba(255, 255, 255, 0.05);
}
.sk-session-info { .sk-session-info {
flex: 1;
display: flex;
flex-direction: column;
gap: var(--sk-gap-s);
.info-heading-line {
display: flex;
justify-content: space-between;
align-items: baseline;
}
.info-line {
display: flex;
align-items: baseline;
gap: var(--sk-gap-m);
max-width: 248px;
skirda-text {
flex: 1;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: block;
}
}
}
}
&.active {
.sk-session {
opacity: 1;
background-color: rgba(255, 255, 255, 0.1);
} }
} }
} }

View File

@ -3,10 +3,12 @@ import { CommonModule } from '@angular/common';
import { SessionComponent } from './session.component'; import { SessionComponent } from './session.component';
import { ImageIconModule } from '../image-icon/image-icon.module'; import { ImageIconModule } from '../image-icon/image-icon.module';
import { TypographyModule } from '../typography/typography.module'; import { TypographyModule } from '../typography/typography.module';
import { TagModule } from '../tag/tag.module'
import { PipesModule } from '../pipes/pipes.module'
@NgModule({ @NgModule({
declarations: [SessionComponent], declarations: [SessionComponent],
imports: [CommonModule, ImageIconModule, TypographyModule], imports: [CommonModule, ImageIconModule, TypographyModule, TagModule, PipesModule],
exports: [SessionComponent], exports: [SessionComponent],
}) })
export class SessionModule {} export class SessionModule {}

View File

@ -0,0 +1,5 @@
<div class="sk-tag">
<skirda-text>
<ng-content></ng-content>
</skirda-text>
</div>

View File

@ -0,0 +1,13 @@
:host {
&.filled .sk-tag {
background-color: var(--sk-accent);
}
.sk-tag {
display: inline-block;
padding: 0px var(--sk-gap-m);
border-radius: var(--sk-br-s);
background-color: rgba(255, 255, 255, 0.05);
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TagComponent } from './tag.component';
describe('TagComponent', () => {
let component: TagComponent;
let fixture: ComponentFixture<TagComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TagComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(TagComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'skirda-tag',
templateUrl: './tag.component.html',
styleUrls: ['./tag.component.scss']
})
export class TagComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TagComponent } from './tag.component';
import { TypographyModule } from '../typography/typography.module'
@NgModule({
declarations: [
TagComponent
],
imports: [
CommonModule,
TypographyModule
],
exports: [
TagComponent
]
})
export class TagModule { }

View File

@ -7,6 +7,9 @@ import { TypographyModule } from './typography/typography.module';
import { SectionLabelModule } from './section-label/section-label.module'; import { SectionLabelModule } from './section-label/section-label.module';
import { ImageIconModule } from './image-icon/image-icon.module'; import { ImageIconModule } from './image-icon/image-icon.module';
import { ButtonModule } from './button/button.module'; import { ButtonModule } from './button/button.module';
import { TagModule } from './tag/tag.module';
import { PipesModule } from './pipes/pipes.module';
import { GameModule } from './game/game.module';
@NgModule({ @NgModule({
declarations: [], declarations: [],
@ -19,6 +22,9 @@ import { ButtonModule } from './button/button.module';
SectionLabelModule, SectionLabelModule,
ImageIconModule, ImageIconModule,
ButtonModule, ButtonModule,
TagModule,
PipesModule,
GameModule,
], ],
exports: [ exports: [
IconModule, IconModule,
@ -28,6 +34,9 @@ import { ButtonModule } from './button/button.module';
TypographyModule, TypographyModule,
SectionLabelModule, SectionLabelModule,
ImageIconModule, ImageIconModule,
TagModule,
PipesModule,
GameModule
], ],
}) })
export class UiModule {} export class UiModule {}

View File

@ -10,3 +10,6 @@ export * from './lib/section/section.module';
export * from './lib/typography/typography.module'; export * from './lib/typography/typography.module';
export * from './lib/section-label/section-label.module'; export * from './lib/section-label/section-label.module';
export * from './lib/image-icon/image-icon.module'; export * from './lib/image-icon/image-icon.module';
export * from './lib/tag/tag.module';
export * from './lib/pipes/pipes.module';
export * from './lib/game/game.module';

View File

@ -8,18 +8,21 @@
</button> </button>
</div> </div>
<div class="sk-sections"> <div class="sk-sections">
<skirda-section class="active"> <!-- Здесь class="active" для подсвечивания активного раздела прописывается автоматически,
если URL после перехода соддержит routerLink (класс прописывается в routerLinkActive) -->
<skirda-section [routerLink]="['servers']" routerLinkActive="active">
<skirda-icon name="server"></skirda-icon> <skirda-icon name="server"></skirda-icon>
<skirda-heading size="6">Servers</skirda-heading> <skirda-heading size="6">Servers</skirda-heading>
</skirda-section> </skirda-section>
<skirda-section> <skirda-section [routerLink]="['games']" routerLinkActive="active">
<skirda-icon name="game"></skirda-icon> <skirda-icon name="game"></skirda-icon>
<skirda-heading size="6">Games</skirda-heading> <skirda-heading size="6">Games</skirda-heading>
</skirda-section> </skirda-section>
<skirda-section> <skirda-section [routerLink]="['friends']" routerLinkActive="active">
<skirda-icon name="friends"></skirda-icon> <skirda-icon name="friends"></skirda-icon>
<skirda-heading size="6">Friends</skirda-heading> <skirda-heading size="6">Friends</skirda-heading>
</skirda-section> </skirda-section>
</div> </div>
<app-menu-sessions></app-menu-sessions> <app-menu-sessions></app-menu-sessions>
<app-menu-games></app-menu-games>
</menu> </menu>

View File

@ -0,0 +1,10 @@
<skirda-section-label>
Pinned games <div class="count">{{games.length}}</div>
</skirda-section-label>
<div class="games">
<skirda-game
[routerLink]="['/game/' + game.gameId]" routerLinkActive="active"
*ngFor="let game of games; index as i"
[game]="game"
></skirda-game>
</div>

View File

@ -0,0 +1,9 @@
:host {
display: block;
.games {
display: flex;
flex-direction: column;
gap: 3px;
}
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuGamesComponent } from './menu-games.component';
describe('MenuGamesComponent', () => {
let component: MenuGamesComponent;
let fixture: ComponentFixture<MenuGamesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MenuGamesComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(MenuGamesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,29 @@
import { Component, OnInit } from '@angular/core';
import { Game } from 'src/app/interfaces/game.interface'
@Component({
selector: 'app-menu-games',
templateUrl: './menu-games.component.html',
styleUrls: ['./menu-games.component.scss']
})
export class MenuGamesComponent implements OnInit {
games: Game[] = [{
gameId: 'id:minecraft',
title: 'Minecraft',
image: '/assets/games/minecraft/icon.png',
}, {
gameId: 'id:garrysmod',
title: 'Garry\'s mod',
image: '/assets/games/garrysmod/icon.png',
}, {
gameId: 'id:openarena',
title: 'OpenArena',
image: '/assets/games/openarena/icon.png',
}]
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,6 +1,10 @@
<skirda-section-label> <skirda-section-label>
Active sessions <div class="count">3</div> Active sessions <div class="count">{{sessions.length}}</div>
</skirda-section-label> </skirda-section-label>
<div class="sessions"> <div class="sessions">
<skirda-session [ngClass]="{'active': i == 1}" *ngFor="let session of sessions; index as i" [session]="session"></skirda-session> <skirda-session
[routerLink]="['/session/' + session.id]" routerLinkActive="active"
*ngFor="let session of sessions; index as i"
[session]="session"
></skirda-session>
</div> </div>

View File

@ -9,23 +9,26 @@ import { Session } from 'projects/ui/src/lib/interfaces/session';
export class MenuSessionsComponent implements OnInit { export class MenuSessionsComponent implements OnInit {
sessions: Session[] = [ sessions: Session[] = [
{ {
id: 'minecraft-001',
icon: '/assets/games/minecraft/icon.png', icon: '/assets/games/minecraft/icon.png',
title: 'Minecraft', title: 'Minecraft',
version: '000', version: '1.19.2',
status: 'text', status: 'Before returning the same line, console log the same logic',
expires: new Date(), expires: new Date('2022-10-30'),
}, },
{ {
id: 'minecraft-002',
icon: '/assets/games/garrysmod/icon.png', icon: '/assets/games/garrysmod/icon.png',
title: 'Minecraft 2', title: 'Minecraft 2',
version: '000', version: '1.12-dev',
expires: new Date(), expires: new Date('2022-10-22T20:00:00'),
}, },
{ {
id: 'minecraft-003',
icon: '/assets/games/minecraft/icon.png', icon: '/assets/games/minecraft/icon.png',
title: 'Minecraft 3', title: 'Minecraft 3',
version: '000', version: '1.7.10',
expires: new Date(), expires: new Date('2022-10-30T20:00:00'),
}, },
]; ];

View File

@ -1,7 +1,6 @@
<div class="main-wrapper" [style]="'--image-accent:' + color?.rgba"> <div class="main-wrapper" [style.background-image]="'url(' + image + ')'">
<img [src]="image" id="image">
<app-main-menu></app-main-menu> <app-main-menu></app-main-menu>
<div class="content"> <div class="content">
content will be here <router-outlet></router-outlet>
</div> </div>
</div> </div>

View File

@ -25,8 +25,6 @@
flex: 1; flex: 1;
background-color: rgba(0,0,0,0.05); background-color: rgba(0,0,0,0.05);
display: flex; display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(1rem); backdrop-filter: blur(1rem);
} }
} }

View File

@ -1,5 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { FastAverageColor, FastAverageColorResult } from 'fast-average-color';
@Component({ @Component({
selector: 'app-main-root', selector: 'app-main-root',
@ -8,29 +7,8 @@ import { FastAverageColor, FastAverageColorResult } from 'fast-average-color';
}) })
export class MainRootComponent implements OnInit { export class MainRootComponent implements OnInit {
image: string = 'assets/games/minecraft/backgrounds/5.webp'; image: string = 'assets/games/minecraft/backgrounds/5.webp';
color?: FastAverageColorResult;
constructor() {} constructor() {}
ngAfterViewInit(): void {
//Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
//Add 'implements AfterViewInit' to the class.
window.addEventListener('load', () => {
this.setColors();
});
}
ngOnInit(): void {} ngOnInit(): void {}
setColors() {
// extractColors(this.image).then((value) => {
// console.log(value);
// });
let fac = new FastAverageColor();
this.color = fac.getColor(
document.getElementById('image') as HTMLImageElement
);
console.log(this.color);
}
} }

View File

@ -3,12 +3,52 @@ import { CommonModule } from '@angular/common';
import { MainRootComponent } from './main-root/main-root.component'; import { MainRootComponent } from './main-root/main-root.component';
import { MainMenuComponent } from './main-menu/main-menu.component'; import { MainMenuComponent } from './main-menu/main-menu.component';
import { UiModule } from 'projects/ui/src/lib/ui.module'; import { UiModule } from 'projects/ui/src/lib/ui.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule,
ReactiveFormsModule } from '@angular/forms';
import { MenuSessionsComponent } from './main-menu/menu-sessions/menu-sessions.component'; import { MenuSessionsComponent } from './main-menu/menu-sessions/menu-sessions.component';
import { MenuGamesComponent } from './main-menu/menu-games/menu-games.component';
import { ServersPageComponent } from './sections/servers-page/servers-page.component';
import { FriendsPageComponent } from './sections/friends-page/friends-page.component';
import { GamesPageComponent } from './sections/games-page/games-page.component';
import { SessionPageComponent } from './sections/session-page/session-page.component';
import { GamePageComponent } from './sections/game-page/game-page.component';
import { MainRoutingModule } from './routing.module'
import { ButtonModule } from 'projects/ui/src/lib/button/button.module'
import { TypographyModule } from 'projects/ui/src/lib/typography/typography.module'
import { IconModule } from 'projects/ui/src/lib/icon/icon.module'
@NgModule({ @NgModule({
declarations: [MainRootComponent, MainMenuComponent, MenuSessionsComponent], declarations: [
imports: [CommonModule, UiModule, ReactiveFormsModule, FormsModule], MainRootComponent,
exports: [MainRootComponent, MainMenuComponent, MenuSessionsComponent], MainMenuComponent,
MenuSessionsComponent,
MenuGamesComponent,
ServersPageComponent,
FriendsPageComponent,
GamesPageComponent,
SessionPageComponent,
GamePageComponent
],
imports: [
CommonModule,
UiModule,
ReactiveFormsModule,
FormsModule,
MainRoutingModule,
TypographyModule,
ButtonModule,
IconModule
],
exports: [
MainRootComponent,
MainMenuComponent,
MenuSessionsComponent,
MenuGamesComponent,
ServersPageComponent,
FriendsPageComponent,
GamesPageComponent,
SessionPageComponent,
GamePageComponent
]
}) })
export class MainModule {} export class MainModule {}

View File

@ -0,0 +1,35 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'
import { MainRootComponent } from './main-root/main-root.component'
import { FriendsPageComponent } from './sections/friends-page/friends-page.component'
import { GamePageComponent } from './sections/game-page/game-page.component'
import { GamesPageComponent } from './sections/games-page/games-page.component'
import { ServersPageComponent } from './sections/servers-page/servers-page.component'
import { SessionPageComponent } from './sections/session-page/session-page.component'
const routes: Routes = [{
path: '',
component: MainRootComponent,
children: [{
path: 'servers',
component: ServersPageComponent
}, {
path: 'friends',
component: FriendsPageComponent
}, {
path: 'games',
component: GamesPageComponent
}, {
path: 'session/:id',
component: SessionPageComponent
}, {
path: 'game/:id',
component: GamePageComponent
}]
}]
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class MainRoutingModule { }

View File

@ -0,0 +1,17 @@
@mixin page {
.section {
padding: 3rem;
.section-head {
.head-title {
padding-bottom: var(--sk-gap-xl);
}
}
.section-content {
padding: var(--sk-gap-xl) 0rem;
}
}
}

View File

@ -0,0 +1,8 @@
<div class="section">
<div class="section-head">
<div class="head-title">
<skirda-heading size="1">Friends</skirda-heading>
</div>
<div class="head-subtitle">Friends page will be here</div>
</div>
</div>

View File

@ -0,0 +1,7 @@
@use '../global';
:host {
display: block;
@include global.page();
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FriendsPageComponent } from './friends-page.component';
describe('FriendsPageComponent', () => {
let component: FriendsPageComponent;
let fixture: ComponentFixture<FriendsPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FriendsPageComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(FriendsPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-friends-page',
templateUrl: './friends-page.component.html',
styleUrls: ['./friends-page.component.scss']
})
export class FriendsPageComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,14 @@
<div class="section">
<div class="section-head">
<div class="head-title">
<skirda-heading size="1">Game</skirda-heading>
</div>
<div class="head-subtitle">Game page will be here</div>
</div>
<div class="section-content">
<skirda-button>
<skirda-icon name="play" size="16"></skirda-icon>
Run game
</skirda-button>
</div>
</div>

View File

@ -0,0 +1,7 @@
@use '../global';
:host {
display: block;
@include global.page();
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { GamePageComponent } from './game-page.component';
describe('GamePageComponent', () => {
let component: GamePageComponent;
let fixture: ComponentFixture<GamePageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ GamePageComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(GamePageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-game-page',
templateUrl: './game-page.component.html',
styleUrls: ['./game-page.component.scss']
})
export class GamePageComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,8 @@
<div class="section">
<div class="section-head">
<div class="head-title">
<skirda-heading size="1">Games</skirda-heading>
</div>
<div class="head-subtitle">Games page will be here</div>
</div>
</div>

View File

@ -0,0 +1,7 @@
@use '../global';
:host {
display: block;
@include global.page();
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { GamesPageComponent } from './games-page.component';
describe('GamesPageComponent', () => {
let component: GamesPageComponent;
let fixture: ComponentFixture<GamesPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ GamesPageComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(GamesPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-games-page',
templateUrl: './games-page.component.html',
styleUrls: ['./games-page.component.scss']
})
export class GamesPageComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,8 @@
<div class="section">
<div class="section-head">
<div class="head-title">
<skirda-heading size="1">Servers</skirda-heading>
</div>
<div class="head-subtitle">Servers page will be here</div>
</div>
</div>

View File

@ -0,0 +1,7 @@
@use '../global';
:host {
display: block;
@include global.page();
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ServersPageComponent } from './servers-page.component';
describe('ServersPageComponent', () => {
let component: ServersPageComponent;
let fixture: ComponentFixture<ServersPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ServersPageComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(ServersPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-servers-page',
templateUrl: './servers-page.component.html',
styleUrls: ['./servers-page.component.scss']
})
export class ServersPageComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,14 @@
<div class="section">
<div class="section-head">
<div class="head-title">
<skirda-heading size="1">Session</skirda-heading>
</div>
<div class="head-subtitle">Session page will be here</div>
</div>
<div class="section-content">
<skirda-button>
<skirda-icon name="play" size="16"></skirda-icon>
Run session
</skirda-button>
</div>
</div>

View File

@ -0,0 +1,7 @@
@use '../global';
:host {
display: block;
@include global.page();
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SessionPageComponent } from './session-page.component';
describe('SessionPageComponent', () => {
let component: SessionPageComponent;
let fixture: ComponentFixture<SessionPageComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SessionPageComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SessionPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-session-page',
templateUrl: './session-page.component.html',
styleUrls: ['./session-page.component.scss']
})
export class SessionPageComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -3,5 +3,5 @@ export interface Game {
gameId: string gameId: string
title: string; title: string;
image: string; image: string;
description: string; description?: string;
} }

View File

@ -1,6 +1,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { MainRootComponent } from '../components/main/main-root/main-root.component'; import { MainRootComponent } from '../components/main/main-root/main-root.component';
import { MainRoutingModule } from '../components/main/routing.module'
import { PlaygroundComponent } from '../components/playground/playground.component'; import { PlaygroundComponent } from '../components/playground/playground.component';
import { SandboxComponent } from '../components/sandbox/sandbox.component'; import { SandboxComponent } from '../components/sandbox/sandbox.component';
import { SignInComponent } from '../components/sign-in/sign-in.component'; import { SignInComponent } from '../components/sign-in/sign-in.component';
@ -12,7 +13,7 @@ const routes: Routes = [
}, },
{ {
path: 'main', path: 'main',
component: MainRootComponent, loadChildren: () => MainRoutingModule
}, },
{ {
path: 'sandbox', path: 'sandbox',

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 4.82985V19.1721C2 22.1095 5.1779 23.9529 7.71426 22.4842L13.906 18.9023L20.0977 15.3055C22.6341 13.8368 22.6341 10.1651 20.0977 8.6964L13.906 5.0996L7.71426 1.5178C5.1779 0.0491071 2 1.87747 2 4.82985Z" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 403 B

View File

@ -5,6 +5,7 @@ html, body {
} }
:root { :root {
--sk-gap-xs: 0.125rem;
--sk-gap-s: 0.25rem; --sk-gap-s: 0.25rem;
--sk-gap-m: 0.5rem; --sk-gap-m: 0.5rem;
--sk-gap-l: 0.75rem; --sk-gap-l: 0.75rem;
@ -17,5 +18,6 @@ html, body {
--sk-accent-dark: #2A3B39; --sk-accent-dark: #2A3B39;
// border-radius // border-radius
--sk-br-s: 0.25rem;
--sk-br-m: 0.5rem; --sk-br-m: 0.5rem;
} }