Merge branch 'dev' into SES-119

This commit is contained in:
Karol Górzyński 2021-01-02 13:03:33 +01:00
commit ebbd30fc30
50 changed files with 1361 additions and 171 deletions

View File

@ -0,0 +1,838 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SessionCompanion.Database;
namespace SessionCompanion.Database.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20201228114303_Class name fix")]
partial class Classnamefix
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseIdentityColumns()
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.0");
modelBuilder.Entity("SessionCompanion.Database.Tables.Alignment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.HasKey("Id");
b.ToTable("Alignments");
b.HasData(
new
{
Id = 1
},
new
{
Id = 2
},
new
{
Id = 3
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Background", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.HasKey("Id");
b.ToTable("Backgrounds");
b.HasData(
new
{
Id = 1
},
new
{
Id = 2
},
new
{
Id = 3
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Biography", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("AlignmentId")
.HasColumnType("int");
b.Property<int>("BackgroundId")
.HasColumnType("int");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("ClassId")
.HasColumnType("int");
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.Property<int>("RaceId")
.HasColumnType("int");
b.Property<string>("Sex")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("AlignmentId");
b.HasIndex("BackgroundId");
b.HasIndex("CharacterId")
.IsUnique();
b.HasIndex("ClassId");
b.HasIndex("RaceId");
b.ToTable("Biographies");
b.HasData(
new
{
Id = 1,
AlignmentId = 1,
BackgroundId = 1,
CharacterId = 1,
ClassId = 1,
Name = "Bob",
RaceId = 1,
Sex = "Male"
},
new
{
Id = 2,
AlignmentId = 2,
BackgroundId = 2,
CharacterId = 2,
ClassId = 2,
Name = "Queen Daenerys Stormborn of the House Targaryen, the First of Her Name, Queen of the Andals, the Rhoynar and the First Men, Lady of the Seven Kingdoms and Protector of the Realm, Lady of Dragonstone, Queen of Meereen, Khaleesi of the Great Grass Sea, the Unburnt, Breaker of Chains and Mother of Dragons.",
RaceId = 2,
Sex = "Female"
},
new
{
Id = 3,
AlignmentId = 3,
BackgroundId = 3,
CharacterId = 3,
ClassId = 3,
Name = "Gandalf the White",
RaceId = 3,
Sex = "Both"
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Character", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Characters");
b.HasData(
new
{
Id = 1,
UserId = 1
},
new
{
Id = 2,
UserId = 2
},
new
{
Id = 3,
UserId = 3
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Charisma", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<bool>("CanDeception")
.HasColumnType("bit");
b.Property<bool>("CanIntimidation")
.HasColumnType("bit");
b.Property<bool>("CanPerformance")
.HasColumnType("bit");
b.Property<bool>("CanPersuasion")
.HasColumnType("bit");
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("Deception")
.HasColumnType("int");
b.Property<int>("Intimidation")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("Performance")
.HasColumnType("int");
b.Property<int>("Persuasion")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Charismas");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Class", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Classes");
b.HasData(
new
{
Id = 1,
Name = "Fighter"
},
new
{
Id = 2,
Name = "Paladin"
},
new
{
Id = 3,
Name = "Cleric"
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Constitution", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Constitutions");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Dexterity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("Acrobatics")
.HasColumnType("int");
b.Property<bool>("CanAcrobatics")
.HasColumnType("bit");
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<bool>("CanSleightOfHand")
.HasColumnType("bit");
b.Property<bool>("CanStealth")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("SleightOfHand")
.HasColumnType("int");
b.Property<int>("Stealth")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Dexterities");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Intelligence", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("Arcana")
.HasColumnType("int");
b.Property<bool>("CanArcana")
.HasColumnType("bit");
b.Property<bool>("CanHistory")
.HasColumnType("bit");
b.Property<bool>("CanInvestigation")
.HasColumnType("bit");
b.Property<bool>("CanNature")
.HasColumnType("bit");
b.Property<bool>("CanReligion")
.HasColumnType("bit");
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("History")
.HasColumnType("int");
b.Property<int>("Investigation")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("Nature")
.HasColumnType("int");
b.Property<int>("Religion")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Intelligences");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Race", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<string>("Name")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Races");
b.HasData(
new
{
Id = 1,
Name = "Human"
},
new
{
Id = 2,
Name = "Dwarf"
},
new
{
Id = 3,
Name = "Elf"
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Statistics", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("ArmorClass")
.HasColumnType("int");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("CurrentHealthPoints")
.HasColumnType("int");
b.Property<int>("ExperiencePoints")
.HasColumnType("int");
b.Property<int>("HealthPoints")
.HasColumnType("int");
b.Property<int>("Initiative")
.HasColumnType("int");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<int>("Proficiency")
.HasColumnType("int");
b.Property<int>("Speed")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Statistics");
b.HasData(
new
{
Id = 1,
ArmorClass = 9,
CharacterId = 1,
CurrentHealthPoints = 18,
ExperiencePoints = 2,
HealthPoints = 20,
Initiative = 12,
Level = 1,
Proficiency = 1,
Speed = 5
},
new
{
Id = 2,
ArmorClass = 12,
CharacterId = 2,
CurrentHealthPoints = 26,
ExperiencePoints = 0,
HealthPoints = 26,
Initiative = 7,
Level = 1,
Proficiency = 1,
Speed = 10
},
new
{
Id = 3,
ArmorClass = 2,
CharacterId = 3,
CurrentHealthPoints = 7,
ExperiencePoints = 24,
HealthPoints = 7,
Initiative = 18,
Level = 1,
Proficiency = 2,
Speed = 15
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Strength", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("Athletics")
.HasColumnType("int");
b.Property<bool>("CanAthletics")
.HasColumnType("bit");
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Strengths");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<string>("Password")
.HasColumnType("nvarchar(max)");
b.Property<string>("Username")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
b.HasData(
new
{
Id = 1,
Password = "123",
Username = "Morwiec"
},
new
{
Id = 2,
Password = "123",
Username = "Cichoklepiec"
},
new
{
Id = 3,
Password = "123",
Username = "Ruletka"
});
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Wisdom", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.UseIdentityColumn();
b.Property<int>("AnimalHandling")
.HasColumnType("int");
b.Property<bool>("CanAnimalHandling")
.HasColumnType("bit");
b.Property<bool>("CanInsight")
.HasColumnType("bit");
b.Property<bool>("CanMedicine")
.HasColumnType("bit");
b.Property<bool>("CanPerception")
.HasColumnType("bit");
b.Property<bool>("CanSaveThrows")
.HasColumnType("bit");
b.Property<bool>("CanSurvival")
.HasColumnType("bit");
b.Property<int>("CharacterId")
.HasColumnType("int");
b.Property<int>("Insight")
.HasColumnType("int");
b.Property<int>("Medicine")
.HasColumnType("int");
b.Property<int>("Modification")
.HasColumnType("int");
b.Property<int>("Perception")
.HasColumnType("int");
b.Property<int>("SavingThrows")
.HasColumnType("int");
b.Property<int>("Survival")
.HasColumnType("int");
b.Property<int>("Value")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CharacterId")
.IsUnique();
b.ToTable("Wisdoms");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Biography", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Alignment", "Alignment")
.WithMany("Biography")
.HasForeignKey("AlignmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SessionCompanion.Database.Tables.Background", "Background")
.WithMany("Biography")
.HasForeignKey("BackgroundId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Biography")
.HasForeignKey("SessionCompanion.Database.Tables.Biography", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SessionCompanion.Database.Tables.Class", "Class")
.WithMany("Biography")
.HasForeignKey("ClassId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("SessionCompanion.Database.Tables.Race", "Race")
.WithMany("Biography")
.HasForeignKey("RaceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Alignment");
b.Navigation("Background");
b.Navigation("Character");
b.Navigation("Class");
b.Navigation("Race");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Character", b =>
{
b.HasOne("SessionCompanion.Database.Tables.User", "User")
.WithMany("Character")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Charisma", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Charisma")
.HasForeignKey("SessionCompanion.Database.Tables.Charisma", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Constitution", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Constitution")
.HasForeignKey("SessionCompanion.Database.Tables.Constitution", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Dexterity", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Dexterity")
.HasForeignKey("SessionCompanion.Database.Tables.Dexterity", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Intelligence", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Intelligence")
.HasForeignKey("SessionCompanion.Database.Tables.Intelligence", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Statistics", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Statistics")
.HasForeignKey("SessionCompanion.Database.Tables.Statistics", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Strength", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Strength")
.HasForeignKey("SessionCompanion.Database.Tables.Strength", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Wisdom", b =>
{
b.HasOne("SessionCompanion.Database.Tables.Character", "Character")
.WithOne("Wisdom")
.HasForeignKey("SessionCompanion.Database.Tables.Wisdom", "CharacterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Character");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Alignment", b =>
{
b.Navigation("Biography");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Background", b =>
{
b.Navigation("Biography");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Character", b =>
{
b.Navigation("Biography");
b.Navigation("Charisma");
b.Navigation("Constitution");
b.Navigation("Dexterity");
b.Navigation("Intelligence");
b.Navigation("Statistics");
b.Navigation("Strength");
b.Navigation("Wisdom");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Class", b =>
{
b.Navigation("Biography");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.Race", b =>
{
b.Navigation("Biography");
});
modelBuilder.Entity("SessionCompanion.Database.Tables.User", b =>
{
b.Navigation("Character");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,55 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace SessionCompanion.Database.Migrations
{
public partial class Classnamefix : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 1,
column: "Name",
value: "Fighter");
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 2,
column: "Name",
value: "Paladin");
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 3,
column: "Name",
value: "Cleric");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 1,
column: "Name",
value: "Warrior");
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 2,
column: "Name",
value: "Knight");
migrationBuilder.UpdateData(
table: "Classes",
keyColumn: "Id",
keyValue: 3,
column: "Name",
value: "Priest");
}
}
}

View File

@ -255,17 +255,17 @@ namespace SessionCompanion.Database.Migrations
new
{
Id = 1,
Name = "Warrior"
Name = "Fighter"
},
new
{
Id = 2,
Name = "Knight"
Name = "Paladin"
},
new
{
Id = 3,
Name = "Priest"
Name = "Cleric"
});
});

View File

@ -66,17 +66,17 @@ namespace SessionCompanion.Database
new Class
{
Id = 1,
Name = "Warrior"
Name = "Fighter"
},
new Class
{
Id = 2,
Name = "Knight"
Name = "Paladin"
},
new Class
{
Id = 3,
Name = "Priest"
Name = "Cleric"
}
};
return classes;

View File

@ -23,7 +23,8 @@ namespace SessionCompanion.Services.Profiles
CreateMap<Character, CharacterBasicStatsViewModel>()
.ForMember(vm => vm.Name, conf => conf.MapFrom(charact => charact.Biography.Name))
.ForMember(vm => vm.Level, conf => conf.MapFrom(charact => charact.Statistics.Level))
.ForMember(vm => vm.CurrentHealthPoints, conf => conf.MapFrom(charact => charact.Statistics.CurrentHealthPoints)).ReverseMap();
.ForMember(vm => vm.CurrentHealthPoints, conf => conf.MapFrom(charact => charact.Statistics.CurrentHealthPoints))
.ForMember(vm => vm.Class, conf => conf.MapFrom(charact => charact.Biography.Class.Name)).ReverseMap();
}
}
}

View File

@ -46,6 +46,7 @@ namespace SessionCompanion.Services.Services
{
var characters = await Repository.Get(c => charactersId.Contains(c.Id))
.Include(x => x.Biography)
.ThenInclude(x => x.Class)
.Include(x => x.Statistics).ToListAsync();
var result = Mapper.Map<IEnumerable<CharacterBasicStatsViewModel>>(characters);
return result;

View File

@ -21,5 +21,10 @@
/// Aktualna ilość życia postaci
/// </summary>
public int CurrentHealthPoints { get; set; }
/// <summary>
/// Klasa postaci
/// </summary>
public string Class { get; set; }
}
}

View File

@ -100,6 +100,11 @@
Aktualna ilość życia postaci
</summary>
</member>
<member name="P:SessionCompanion.ViewModels.CharacterViewModels.CharacterBasicStatsViewModel.Class">
<summary>
Klasa postaci
</summary>
</member>
<member name="P:SessionCompanion.ViewModels.CharacterViewModels.CharacterForLoginViewModel.Id">
<summary>
Identyfikator postaci

View File

@ -0,0 +1,3 @@
{
"singleQuote": true
}

View File

@ -9747,6 +9747,12 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
"dev": true
},
"prettier": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
"dev": true
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@ -12040,6 +12046,12 @@
}
}
},
"tslint-config-prettier": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz",
"integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==",
"dev": true
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",

View File

@ -53,6 +53,7 @@
"karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"prettier": "2.2.1",
"typescript": "3.5.3"
},
"optionalDependencies": {

View File

@ -1,9 +1,17 @@
import { Component } from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {SessionCompanionIconsRegistry} from './shared/sc-icons/session-companion-icons-registry.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
export class AppComponent implements OnInit{
title = 'Session Companion';
constructor(private iconService: SessionCompanionIconsRegistry) {
}
ngOnInit() {
this.iconService.registerIcons();
}
}

View File

@ -23,9 +23,9 @@ import {
import {UserService} from '../services/user.service';
import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { reducers} from './reducers';
import {AppReducer} from './store/reducers/app.reducer';
import {environment} from '../environments/environment';
import {reducers} from './store/models/app-state.model';
import {CharacterService} from '../services/character.service';
@NgModule({
declarations: [
@ -54,13 +54,14 @@ BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
MatSidenavModule,
MatToolbarModule,
MatListModule,
StoreModule.forRoot({appState: AppReducer}),
StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument({
logOnly: environment.production
})
],
providers: [
UserService
UserService,
CharacterService
],
bootstrap: [AppComponent]
})

View File

@ -1,56 +1,96 @@
<div class="root-container" >
<mat-sidenav-container class="sidenav-container">
<mat-sidenav class="leftnav" opened mode="side" [@onSideNavChange]="leftSidenavExpanded ? 'open' : 'close'">
<div style="background-color: #292F36">
<button mat-icon-button (click)="UpdateSidenavStatus('left', !leftSidenavTextExpanded)" style="margin: 12px; ">
<mat-icon aria-label="Menu">menu</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-nav-list>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span [@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'" style="color: white">Link 1</span>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span [@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'" style="color: white">Link 2</span>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span [@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'" style="color: white">Link 3</span>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content >
<mat-toolbar color="primary" class="gm-toolbar">
<span>SessionCompanion</span>
</mat-toolbar>
</mat-sidenav-content>
<mat-sidenav class="rightnav" opened mode="side" position="end" [@onSideNavChange]="rightSidenavExpanded ? 'open' : 'close'">
<div style="background-color: #4F5B69">
<button mat-icon-button (click)="UpdateSidenavStatus('right', !rightSidenavExpanded)" style="margin: 12px; ">
<mat-icon aria-label="Menu">chat</mat-icon>
</button>
<button mat-icon-button *ngIf="rightSidenavTextExpanded" (click)="UpdateSidenavStatus('right', !rightSidenavExpanded)" style="margin: 12px; position: absolute; right: 10px;">
<mat-icon aria-label="Menu">close</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-nav-list>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<a [@animateText]="rightSidenavTextExpanded ? 'show' : 'hide'" mat-list-item href="#" style="color: white">Link 1</a>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<a [@animateText]="rightSidenavTextExpanded ? 'show' : 'hide'" mat-list-item href="#" style="color: white">Link 2</a>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<a [@animateText]="rightSidenavTextExpanded ? 'show' : 'hide'" mat-list-item href="#" style="color: white">Link 3</a>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
</mat-sidenav-container>
<div class="root-container">
<mat-sidenav-container class="sidenav-container">
<mat-sidenav
class="leftnav"
opened
mode="side"
[@onSideNavChange]="leftSidenavExpanded ? 'open' : 'close'"
>
<div style="background-color: #292f36">
<button
mat-icon-button
(click)="UpdateSidenavStatus('left', !leftSidenavTextExpanded)"
style="margin: 12px"
>
<mat-icon aria-label="Menu">menu</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-nav-list>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span
[@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'"
style="color: white"
>Link 1</span
>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span
[@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'"
style="color: white"
>Link 2</span
>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon>folder</mat-icon>
<span
[@animateText]="leftSidenavTextExpanded ? 'show' : 'hide'"
style="color: white"
>Link 3</span
>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary" class="gm-toolbar">
<span>SessionCompanion</span>
</mat-toolbar>
</mat-sidenav-content>
<mat-sidenav
class="rightnav"
opened
mode="side"
position="end"
[@onSideNavChange]="rightSidenavExpanded ? 'open' : 'close'"
>
<div style="background-color: #4f5b69">
<button
mat-icon-button
(click)="UpdateSidenavStatus('right', !rightSidenavExpanded)"
style="margin: 12px"
>
<mat-icon aria-label="Menu">chat</mat-icon>
</button>
<button
mat-icon-button
*ngIf="rightSidenavTextExpanded"
(click)="UpdateSidenavStatus('right', !rightSidenavExpanded)"
style="margin: 12px; position: absolute; right: 10px"
>
<mat-icon aria-label="Menu">close</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-nav-list>
<mat-list-item *ngFor="let loggedCharacter of loggedCharacters">
<mat-icon
svgIcon="{{ loggedCharacter.class.toLowerCase() }}"
mat-list-icon
style="font-size: 0"
></mat-icon>
<span
[@animateText]="rightSidenavTextExpanded ? 'show' : 'hide'"
style="color: white"
>{{
loggedCharacter.name.length > 12
? (loggedCharacter.name | slice: 0:12) + '..'
: loggedCharacter.name
}}</span
>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
</mat-sidenav-container>
</div>

View File

@ -1,20 +1,37 @@
import {Component, OnInit} from '@angular/core';
import {animateText, onSideNavChange} from '../../shared/animations/sidenav-animations';
import {GMSignalRService} from '../../shared/signalR-service/gm-signalR.service';
import { Component, OnDestroy, OnInit } from '@angular/core';
import {
animateText,
onSideNavChange,
} from '../../shared/animations/sidenav-animations';
import { GMSignalRService } from '../../shared/signalR-service/gm-signalR.service';
import { CharacterService } from '../../../services/character.service';
import { Subscription } from 'rxjs';
import { ErrorResponse } from '../../../types/ErrorResponse';
import { HttpErrorResponse } from '@angular/common/http';
import { LoggedCharactersViewModel } from '../../../types/viewmodels/character-viewmodels/LoggedCharactersViewModel';
import { first } from 'rxjs/operators';
@Component({
selector: 'app-game-master-dashboard',
templateUrl: './game-master-dashboard.component.html',
styleUrls: ['./game-master-dashboard.component.css'],
animations: [onSideNavChange, animateText]
animations: [onSideNavChange, animateText],
})
export class GameMasterDashboardComponent implements OnInit {
export class GameMasterDashboardComponent implements OnInit, OnDestroy {
allSubscriptions = new Subscription();
leftSidenavExpanded = false;
leftSidenavTextExpanded = false;
rightSidenavExpanded = false;
rightSidenavTextExpanded = false;
constructor(private signalRService: GMSignalRService) {}
loggedCharacters: LoggedCharactersViewModel[];
constructor(
private signalRService: GMSignalRService,
private characterService: CharacterService
) {
this.SubscribeToEvents();
}
ngOnInit() {
this.signalRService.Login();
@ -36,4 +53,36 @@ export class GameMasterDashboardComponent implements OnInit {
break;
}
}
UpdateCharactersList(): void {
this.characterService
.getLoggedCharacters()
.pipe(first())
.subscribe(
(success) => {
this.loggedCharacters = success;
},
(error: ErrorResponse | HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse;
}
console.error(error.message);
}
);
}
private SubscribeToEvents(): void {
this.signalRService.message.subscribe((message: string) => {
if (
message === 'New player connected' ||
message === 'Player disconnected'
) {
this.UpdateCharactersList();
}
});
}
ngOnDestroy() {
this.allSubscriptions.unsubscribe();
}
}

View File

@ -1,6 +1,6 @@
<div [formGroup]="signUpFormGroup" class="container">
<div formGroupName="newAccount" class="container">
<mat-icon matSuffix class="arrow-back" (click)="GoToLoginPage()">arrow_back</mat-icon>
<mat-icon matSuffix class="arrow-back arrow-select" (click)="GoToLoginPage()">arrow_back</mat-icon>
<div class="primary-text header">Create an Account</div>
<mat-form-field class="form-container">
@ -11,7 +11,7 @@
type="text"
required
name="username">
<mat-error *ngIf="signUpFormGroup?.get('newAccount')?.controls?.username?.hasError('required')">
<mat-error *ngIf="signUpFormGroup?.get('newAccount')['controls']?.username?.hasError('required')">
Username is required
</mat-error>
<mat-icon matSuffix>person</mat-icon>
@ -26,7 +26,7 @@
type="password"
name="password"/>
<mat-icon matSuffix>lock</mat-icon>
<mat-error *ngIf="signUpFormGroup?.get('newAccount')?.controls?.password?.hasError('required')">
<mat-error *ngIf="signUpFormGroup?.get('newAccount')['controls']?.password?.hasError('required')">
Password is required
</mat-error>
</mat-form-field>
@ -40,10 +40,10 @@
type="password"
name="confirmPassword"/>
<mat-icon matSuffix >lock</mat-icon>
<mat-error *ngIf="signUpFormGroup?.get('newAccount')?.controls?.confirmPassword?.hasError('required')">
<mat-error *ngIf="signUpFormGroup?.get('newAccount')['controls']?.confirmPassword?.hasError('required')">
Confirm your password
</mat-error>
<mat-error class="password-mismatch" *ngIf="signUpFormGroup?.get('newAccount')?.controls?.confirmPassword?.hasError('mismatch')">
<mat-error class="password-mismatch" *ngIf="signUpFormGroup?.get('newAccount')['controls']?.confirmPassword?.hasError('mismatch')">
Please make sure your passwords match
</mat-error>
</mat-form-field>

View File

@ -6,7 +6,6 @@ import {Subscription} from 'rxjs';
import {ErrorResponse} from '../../../types/ErrorResponse';
import {UserRegisterViewModel} from '../../../types/viewmodels/user-viewmodels/UserRegisterViewModel';
import {HttpErrorResponse} from '@angular/common/http';
import {type} from 'os';
@Component({
selector: 'app-registration',
@ -36,27 +35,33 @@ export class RegistrationComponent implements OnDestroy {
}
Register() {
const userRegisterModel = new class implements UserRegisterViewModel {
password: string;
username: string;
};
if (this.signUpFormGroup.valid) {
const userRegisterModel = new class implements UserRegisterViewModel {
password: string;
username: string;
};
userRegisterModel.username = this.signUpFormGroup.get('newAccount').value['username'];
userRegisterModel.password = this.signUpFormGroup.get('newAccount').value['password'];
userRegisterModel.username = this.signUpFormGroup.get('newAccount').value['username'];
userRegisterModel.password = this.signUpFormGroup.get('newAccount').value['password'];
this.allSubscriptions.add(
this.userService.registerUser(userRegisterModel).subscribe(
() => {
this.router.navigate(['login']);
},
(error: ErrorResponse | HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse;
this.allSubscriptions.add(
this.userService.registerUser(userRegisterModel).subscribe(
() => {
this.router.navigate(['login']);
},
(error: ErrorResponse | HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse;
}
this.apiError = true;
this.apiErrorMessage = error.message;
}
this.apiError = true;
this.apiErrorMessage = error.message;
}
));
));
} else {
this.signUpFormGroup.get('newAccount').get('username').markAsTouched();
this.signUpFormGroup.get('newAccount').get('password').markAsTouched();
this.signUpFormGroup.get('newAccount').get('confirmPassword').markAsTouched();
}
}
ngOnDestroy() {

View File

@ -47,10 +47,6 @@ input {
font-size: 20px;
}
.align-to-right {
text-align: right;
}
@media (max-width: 400px) {
.container {
margin-left: 0%;

View File

@ -1,21 +1,15 @@
<div class="container">
<mat-icon matSuffix class="arrow-back" (click)="onArrowBackClick()">arrow_back</mat-icon>
<mat-icon matSuffix class="arrow-back arrow-select" (click)="onArrowBackClick()">arrow_back</mat-icon>
<div class="primary-text header">Select character</div>
<mat-list >
<mat-list>
<mat-divider></mat-divider>
<mat-list-item> Oweja
<mat-icon matSuffix class="arrow-forward align-to-right" (click)="onCharacterClick()">arrow_forward</mat-icon>
<mat-list-item *ngFor="let character of charactersList">
<mat-icon mat-list-icon>account_circle</mat-icon>
<div mat-line>{{character.name}}</div>
<mat-icon matSuffix class="arrow-forward arrow-select" (click)="onCharacterClick(character.id)">arrow_forward</mat-icon>
<div mat-line> {{character.className}} level: {{character.level}}</div>
<mat-divider></mat-divider>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item> James
<mat-icon matSuffix class="arrow-forward align-to-right" (click)="onCharacterClick()">arrow_forward</mat-icon>
</mat-list-item>
<mat-divider></mat-divider>
<mat-list-item> Legolas
<mat-icon matSuffix class="arrow-forward align-to-right" (click)="onCharacterClick()">arrow_forward</mat-icon>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-list>
</div>

View File

@ -1,30 +1,49 @@
import { Component } from '@angular/core';
import {Component, OnInit} from '@angular/core';
import { Router } from '@angular/router';
import {first} from 'rxjs/operators';
import {ClearUserId} from '../../store/actions/app.actions';
import {ErrorResponse} from '../../../types/ErrorResponse';
import {HttpErrorResponse} from '@angular/common/http';
import {Store} from '@ngrx/store';
import {AppState} from '../../store/models/app-state.model';
import {CharacterService} from '../../../services/character.service';
import {CharacterForLoginViewModel} from '../../../types/viewmodels/character-viewmodels/CharacterForLoginViewModel';
import {AddCharacterId} from '../../store/actions/player.action';
@Component({
selector: 'app-select-character',
templateUrl: './select-character.component.html',
styleUrls: ['./select-character.component.css']
})
export class SelectCharacterComponent {
isExpanded = false;
export class SelectCharacterComponent implements OnInit {
charactersList: CharacterForLoginViewModel[];
collapse() {
this.isExpanded = false;
constructor(private router: Router, private store: Store<AppState>, private characterService: CharacterService) {}
ngOnInit() {
this.getUserCharactersList();
}
toggle() {
this.isExpanded = !this.isExpanded;
getUserCharactersList() {
this.store.select(s => s.appStore.userId).pipe(first()).subscribe((userId) => {
this.characterService.getUserCharactersList(userId).pipe(first()).subscribe((charactersList) => {
this.charactersList = charactersList;
}, (error: ErrorResponse | HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
error = error.error as ErrorResponse;
}
console.error(error.message);
} );
});
}
constructor(private router: Router) {}
onCharacterClick(){
this.router.navigate(['player'])
onCharacterClick(characterId: number) {
this.store.dispatch(new AddCharacterId({characterId}));
this.router.navigate(['player']);
}
onArrowBackClick(){
this.router.navigate(['login'])
onArrowBackClick() {
this.store.dispatch(new ClearUserId());
this.router.navigate(['login']);
}
}

View File

@ -12,7 +12,8 @@ import {AddRole} from '../../store/actions/app.actions';
export class SelectRoleComponent {
isExpanded = false;
constructor(private router: Router, private store: Store<{ role: string }>) {}
constructor(private router: Router, private store: Store<{ role: string }>) {
}
collapse() {
this.isExpanded = false;

View File

@ -1,6 +1,6 @@
<div [formGroup]="signInFormGroup" class="container">
<div formGroupName="signIn" class="container">
<mat-icon matSuffix class="arrow-back" (click)="onArrowBackClick()">arrow_back</mat-icon>
<mat-icon matSuffix class="arrow-back arrow-select" (click)="onArrowBackClick()">arrow_back</mat-icon>
<div id="SignInText" class="primary-text header">Sign In</div>
<mat-form-field class="form-container">
@ -12,7 +12,7 @@
type="text"
required
name="username">
<mat-error *ngIf="signInFormGroup?.get('signIn')?.controls?.username?.hasError('required')">
<mat-error *ngIf="signInFormGroup?.get('signIn')['controls']?.username?.hasError('required')">
Username is required
</mat-error>
<mat-icon matSuffix>person</mat-icon>
@ -28,7 +28,7 @@
type="password"
name="password"/>
<mat-icon matSuffix>lock</mat-icon>
<mat-error *ngIf="signInFormGroup?.get('signIn')?.controls?.password?.hasError('required')">
<mat-error *ngIf="signInFormGroup?.get('signIn')['controls']?.password?.hasError('required')">
Password is required
</mat-error>
</mat-form-field>

View File

@ -6,9 +6,10 @@ import {ErrorResponse} from '../../../types/ErrorResponse';
import {Observable, Subscription} from 'rxjs';
import {HttpErrorResponse} from '@angular/common/http';
import {AppStoreModel} from '../../store/models/app-store.model';
import { Store } from '@ngrx/store';
import {select, Store} from '@ngrx/store';
import {AddUserId} from '../../store/actions/app.actions';
import { AppState } from 'src/app/store/models/app-state.model';
import {AppState} from 'src/app/store/models/app-state.model';
import {first} from "rxjs/operators";
@Component({
selector: 'app-sign-in',
@ -38,12 +39,12 @@ export class SignInComponent implements OnDestroy, OnInit {
});
ngOnInit() {
this.role$ = this.store.select(s => s.appState);
this.role$ = this.store.select(s => s.appStore);
}
onLoginButtonClick() {
let role = '';
this.store.select(s => s.appState.role).subscribe((v)=>{
this.store.select(s => s.appStore.role).pipe(first()).subscribe((v) => {
role = v;
});
this.allSubscriptions.add(
@ -52,7 +53,6 @@ export class SignInComponent implements OnDestroy, OnInit {
this.signInFormGroup.get('signIn').value['password']).subscribe(
(success) => {
this.store.dispatch(new AddUserId({userId: success}));
//TODO zmienić na jedna linie
if (role === 'player') {
this.router.navigate(['select-character']);
} else {
@ -69,13 +69,12 @@ export class SignInComponent implements OnDestroy, OnInit {
));
}
onRegisterButtonClick(){
this.router.navigate(['register'])
//TODO connect with backend
onRegisterButtonClick() {
this.router.navigate(['register']);
}
onArrowBackClick(){
this.router.navigate([''])
onArrowBackClick() {
this.router.navigate(['']);
}
collapse() {

View File

@ -1,19 +0,0 @@
import {
ActionReducer,
ActionReducerMap,
createFeatureSelector,
createSelector,
MetaReducer
} from '@ngrx/store';
import { environment } from '../../environments/environment';
export interface State {
}
export const reducers: ActionReducerMap<State> = {
};
export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];

View File

@ -0,0 +1,4 @@
Moduł został już dodany i wstrzyknięty do roota apki.
Aby dodać nową ikonkę, plik svg wstawiamy do folderu assets/icons/svg-icons.
Oraz dodajym kolejnego enuma w pliku sc-icon.model.ts

View File

@ -0,0 +1,22 @@
import {Injectable} from '@angular/core';
import {scIcon} from '../../../assets/icons/sc-icon.model';
import {MatIconRegistry} from '@angular/material';
import {DomSanitizer} from '@angular/platform-browser';
@Injectable({
providedIn: 'root'
})
export class SessionCompanionIconsRegistry {
constructor(private registry: MatIconRegistry, private sanitizer: DomSanitizer) {
}
public registerIcons(): void {
this.loadIcons(Object.values(scIcon), '../assets/icons/svg-icons');
}
private loadIcons(iconKeys: string[], iconUrl: string): void {
iconKeys.forEach((icon: string) => {
this.registry.addSvgIcon(icon, this.sanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${icon}.svg`));
});
}
}

View File

@ -1,12 +1,15 @@
import { Inject, Injectable } from '@angular/core';
import { SignalRService } from './base/signalR.service';
import {Subject} from 'rxjs';
@Injectable({ providedIn: 'root' })
export class GMSignalRService {
signalR: SignalRService;
message: Subject<string>;
constructor(@Inject('BASE_URL') baseUrl: string) {
this.signalR = new SignalRService(baseUrl);
this.message = new Subject<string>();
this.registerOnServerEvents();
}
@ -17,10 +20,15 @@ export class GMSignalRService {
if (this.signalR.connectionEstablished$.getValue() === true) {
this.signalR.hubConnection.send('GameMasterLogin');
}
});
}).unsubscribe();
}
private registerOnServerEvents(): void {
this.signalR.hubConnection.on('Welcome', (message: string) => {
this.message.next('New player connected');
});
this.signalR.hubConnection.on('GoodBye', (message: string) => {
this.message.next('Player disconnected');
});
}
}

View File

@ -1,9 +1,9 @@
import {AppStoreModel} from '../models/app-store.model';
import { Action } from '@ngrx/store';
import {Action} from '@ngrx/store';
export enum AppActionTypes {
ADD_USER_ID = '[APP] Add user id',
ADD_ROLE = '[APP] Add role'
ADD_ROLE = '[APP] Add role',
CLEAR_USER_ID = '[APP] Clear user id'
}
export class AddUserId implements Action {
@ -20,4 +20,13 @@ export class AddRole implements Action {
}
}
export type AppAction = AddUserId | AddRole;
export class ClearUserId implements Action {
readonly type = AppActionTypes.CLEAR_USER_ID;
constructor() {
}
}
export type AppAction = AddUserId | AddRole | ClearUserId;

View File

@ -0,0 +1,15 @@
import {Action} from "@ngrx/store";
export enum PlayerActionTypes {
ADD_CHARACTER_ID= '[PLAYER] Add character id'
}
export class AddCharacterId implements Action {
readonly type = PlayerActionTypes.ADD_CHARACTER_ID;
constructor(public payload: {characterId: number}) {
}
}
export type PlayerAction = AddCharacterId;

View File

@ -1,5 +1,15 @@
import {AppStoreModel} from './app-store.model';
import {ActionReducerMap} from '@ngrx/store';
import {AppReducer} from '../reducers/app.reducer';
import {PlayerStoreModel} from './player-store.model';
import {PlayerReducer} from '../reducers/player.reducer';
export interface AppState {
appState: AppStoreModel;
appStore: AppStoreModel;
playerStore: PlayerStoreModel;
}
export const reducers: ActionReducerMap<AppState> = {
appStore: AppReducer,
playerStore: PlayerReducer,
};

View File

@ -0,0 +1,3 @@
export interface PlayerStoreModel {
characterId: number;
}

View File

@ -12,6 +12,8 @@ export function AppReducer(state: AppStoreModel = initialState, action: AppActio
return {...state, userId: action.payload.userId};
case AppActionTypes.ADD_ROLE:
return {...state, role: action.payload.role};
case AppActionTypes.CLEAR_USER_ID:
return {...state, userId: null};
default:
return state;
}

View File

@ -0,0 +1,15 @@
import {PlayerStoreModel} from '../models/player-store.model';
import {PlayerAction, PlayerActionTypes} from '../actions/player.action';
const initialState: PlayerStoreModel = {
characterId: null
};
export function PlayerReducer(state: PlayerStoreModel = initialState, action: PlayerAction) {
switch (action.type) {
case PlayerActionTypes.ADD_CHARACTER_ID:
return {...state, characterId: action.payload.characterId};
default:
return state;
}
}

View File

@ -0,0 +1,14 @@
export enum scIcon {
Barbarian = 'barbarian',
Bard = 'bard',
Cleric = 'cleric',
Druid = 'druid',
Fighter = 'fighter',
Monk = 'monk',
Paladin = 'paladin',
Ranger = 'ranger',
rogue = 'rogue',
Sorcerer = 'sorcerer',
Warlock = 'warlock',
Wizard = 'wizard'
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M284.736 29.215c-2.334-.015-4.68.001-7.035.049-32.975.664-67.786 7.496-98.318 21.232-34.895 15.698-64.057 40.163-79.979 74.672-15 32.512-18.36 74.591-2.508 128.285a201.433 201.433 0 0 1 13.502-5.59c-9.866-43.961-5.617-80.245 8.301-109.01 15.464-31.958 42.464-54.15 72.95-68.302 30.484-14.153 64.583-20.494 95.738-20.95 1.947-.028 3.882-.035 5.804-.019 22.847.186 43.814 3.494 60.614 9.836 7.12-3.36 13.61-6.894 18.914-10.852-20.447-11.111-49.38-18.154-81.016-19.212a257.951 257.951 0 0 0-6.967-.14zm8.293 38.373c-1.78-.019-3.574-.015-5.379.012-28.88.421-60.75 6.43-88.421 19.277-27.671 12.847-51.013 32.303-64.327 59.818-11.852 24.495-16.052 55.773-7.242 95.895 12.372-2.904 23.747-3.494 33.565-1.195 9.93 2.325 18.916 9.147 21.732 19.312.306 1.106.52 2.235.701 3.373l102.203-102.203c-11.857-18.99-15.828-34.784-12.218-48.416 4.005-15.125 16.44-24.638 30.048-31.797 7.436-3.912 15.487-7.412 23.547-10.8-10.343-1.974-21.956-3.15-34.209-3.276zm83.057 68.326l-48.508 9.701-34.242 34.242h38.807v38.805l34.242-34.242zm87.348 3.367c-3.956 5.301-7.489 11.788-10.848 18.905 6.876 18.213 10.179 41.335 9.812 66.427-.455 31.155-6.796 65.254-20.949 95.739-14.153 30.485-36.344 57.485-68.303 72.949-28.764 13.918-65.048 18.167-109.01 8.3a201.436 201.436 0 0 1-5.59 13.503c53.695 15.852 95.774 12.492 128.286-2.508 34.51-15.922 58.974-45.084 74.672-79.979 15.698-34.894 22.379-75.376 21.142-112.32-1.058-31.637-8.1-60.569-19.212-81.016zm-22.297 45.48c-3.39 8.06-6.89 16.112-10.801 23.548-7.159 13.608-16.672 26.043-31.797 30.048-13.632 3.61-29.425-.361-48.416-12.218L247.92 328.342c1.138.181 2.267.395 3.373.701 10.165 2.816 16.987 11.802 19.312 21.732 2.3 9.818 1.709 21.193-1.195 33.565 40.122 8.81 71.4 4.61 95.895-7.242 27.515-13.314 46.971-36.656 59.818-64.327 12.847-27.67 18.856-59.542 19.277-88.421.208-14.228-1.004-27.742-3.263-39.588zm-160.528 13.096v33.534h33.534v-33.534zm-18 12.727l-34.244 34.244-9.699 48.506 48.506-9.7 34.244-34.243h-38.807zm-57.19 57.19l-37.034 37.035 38.806 38.806 37.036-37.035-48.508 9.701zm-49.76 49.761l-25.925 25.922 38.809 38.809 25.922-25.924zm-38.651 38.65L16 457.194V496h38.807l101.007-101.008z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M120.7 27.53l-28.93 8.56C112.1 187.8 125.6 321.9 183.9 455H228c-40-140.6-84.2-280.4-107.3-427.47zm19.9 10.36c2.6 16.05 5.5 32.03 8.7 47.95 9.8 2.67 19.9 6.9 30.1 11.85 18.3 8.71 37.3 19.81 56.1 29.51 18.8 9.7 37.3 17.9 53.6 21.1 16.4 3.2 29.8 1.7 41.6-7 22.2-16.4 38.4-26.2 51.3-31.4 12.8-5.2 23.3-5.9 31.6-1.8 7.8 4 11.5 11.1 14.2 17.1l5.1-11.3c-7.3-12.9-18.1-21.38-32.9-23.26-16.2-2.05-38.4 4.06-66 25.66-14.4 11.3-33 9.7-50.6 2.8-17.5-6.9-35.7-18.9-54.2-31.64-18.6-12.74-37.3-26.21-54.8-35.98-12.3-6.86-23.8-11.66-33.8-13.59zm12.8 68.31c4.8 23 10 45.9 15.6 68.7v-62.2c-5.4-2.6-10.6-4.8-15.6-6.5zM404.8 124c-27 110.6-55.1 223.8-97.7 331h38.6c34.5-94.4 51-203.5 70.3-311.3-1.8-3.8-3-7.4-4.3-10.4-2.3-5.3-4.3-8.1-6.3-9.1-.2-.1-.4-.2-.6-.2zM199 128.1v160.4c5.9 21.1 11.9 42.1 18 63.1V137.8c-6.1-3.2-12.1-6.5-18-9.7zM361 142c-5.4 3.6-11.4 7.8-18 12.6V288h1c5.9-20.9 11.5-41.8 17-62.8V142zm-114 10.8V455h18V160.2c-6-2.2-12-4.7-18-7.4zm66 14.3c-5.9.7-11.9.8-18 .2v269.8c6.3-16.4 12.3-32.9 18-49.6V167.1zM163.9 473l-15.1 16h214.4l-15.1-16H163.9z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M300.56 39.29c-2.418.023-5.135 1.13-7.27 3.065-2.137 1.935-3.507 4.53-3.77 6.932-.26 2.402.174 4.782 3.033 7.94l6.037 6.67 40.35 44.56 6.042 6.672c2.86 3.156 5.184 3.824 7.6 3.802 2.416-.023 5.135-1.13 7.272-3.065 2.136-1.934 3.506-4.53 3.767-6.93.262-2.404-.17-4.783-3.03-7.94L308.16 43.09c-2.86-3.158-5.185-3.823-7.6-3.8zm-15.31 36.69l-38.604 34.952-6.04-6.672c-23.138-25.555-36.56-26.794-53.106-27.586L23.285 225.364 151.018 366.43 315.23 217.74c.85-16.544.946-30.02-22.193-55.576l-6.04-6.672 38.6-34.953-40.347-44.56zm-112.146 54.276l33.86 37.396 37.397-33.86 19.66 21.714-37.393 33.86 33.86 37.396-21.714 19.662-33.86-37.397-95.3 86.29-19.664-21.713 95.302-86.29-33.86-37.396 21.712-19.662zm197.378 4.363s-25.86 52.77-16 73.81c6.237 13.306 25.764 13.306 32 0 9.862-21.04-16-73.81-16-73.81zm2.196 103.02l-5.655 46.28c1.168-.316 2.47-.504 3.967-.504 2.408 0 4.445.504 6.23 1.307l-4.542-47.082zm-58.967 15l28.087 66.067c2.457-5.83 5.08-11.178 7.744-15.855l-35.83-50.213zm117.536 1.497l-37.244 49.48c2.66 4.666 5.212 9.943 7.568 15.662l29.676-65.143zM270.143 295.11l63.375 47.704c.57-2.11 1.164-4.208 1.8-6.275 1.07-3.48 2.227-6.874 3.446-10.17l-68.62-31.26zm203.572 2.595l-69.135 29.39c1.103 3.1 2.144 6.29 3.104 9.546.665 2.257 1.273 4.55 1.855 6.858l64.175-45.793zm-102.32 4.95c-1.514 1.696-3.56 4.516-5.706 8.193-4.528 7.762-9.47 18.968-13.167 30.984-3.697 12.016-6.155 24.906-6.185 35.992-.03 11.087 2.422 19.947 6.97 25.225 2.532 2.935 9.886 5.884 17.682 5.884 7.796 0 15.153-2.95 17.684-5.885 4.597-5.335 7.19-14.28 7.344-25.376.154-11.097-2.07-23.966-5.6-35.945-3.53-11.98-8.384-23.133-12.965-30.798-2.252-3.768-4.46-6.66-6.058-8.276zm-38.727 43.402l-79.022 7.62 75.75 9.26c.754-5.654 1.88-11.318 3.272-16.88zm77.754 1.045c1.273 5.56 2.263 11.213 2.88 16.845l75.413-7.275-78.293-9.57zm-81.756 22.716l-60.02 42.828 60.15-25.57c-.322-3.063-.467-6.175-.458-9.303.007-2.63.122-5.286.328-7.955zm85.225 1.516c.107 2.21.156 4.41.126 6.59-.05 3.527-.286 7.03-.752 10.46l58.957 26.856-58.33-43.906zm-79.935 34.746l-22.84 50.135 30-39.858c-.494-.498-.973-1.016-1.44-1.556-2.315-2.685-4.193-5.616-5.72-8.72zm73.358 1.434c-1.403 2.574-3.05 5.02-5.004 7.287-.782.907-1.615 1.737-2.474 2.526l28.816 40.385-21.34-50.196zm-42.073 19.144l4.444 46.05 5.613-45.92c-1.436.1-2.876.146-4.307.146-1.912 0-3.835-.094-5.75-.276z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M257.563 25.156c353.16 276.87 16.918 408.895-87.875 293.25l-40.75 37.125 50.812 50.345c217.562 181.363 524.73-252.058 77.813-380.72zM110.75 364.28c-5.525 1.065-8.975 2.957-11.313 5.25-1.956 1.922-3.248 4.556-4.25 7.564l55.188 52.844c5.468-1.008 9.264-2.796 11.28-4.688 1.997-1.872 3.095-3.864 3.095-7.53l-54-53.44zm-24.72 30.314L30.407 445.28C13.67 472.28 45.1 506.478 81.5 489.94l51.53-50.282-47-45.062z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 521 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#fff" d="M66.54 18.002c-.327-.007-.655-.005-.98.006-4.064.136-8.105 1.634-11.39 4.535-7.508 6.632-8.218 18.094-1.586 25.602 4.394 4.974 10.906 6.945 16.986 5.792l57.838 65.475-50.373 44.498 24.188 27.38c9.69-21.368 22.255-39.484 37.427-54.65l6.91 36.188c25.092-6.29 49.834-10.563 74.366-12.873l-23.912-27.07-38.66-12.483c17.117-12.9 36.734-22.97 58.62-30.474l-24.19-27.385-50.37 44.496-57.92-65.57c1.79-5.835.617-12.43-3.72-17.34-3.498-3.96-8.34-6.03-13.235-6.128zm384.397 0c-4.895.1-9.735 2.168-13.232 6.127-4.338 4.91-5.514 11.506-3.723 17.343l-57.92 65.568-50.37-44.497-24.188 27.385c21.884 7.504 41.5 17.573 58.62 30.472l-38.66 12.485-23.255 26.324c24.71 1.863 49.367 5.706 74.118 11.46l6.498-34.03c15.173 15.166 27.74 33.282 37.43 54.65l24.185-27.38-50.372-44.498 57.838-65.475c6.08 1.153 12.593-.818 16.987-5.792 6.63-7.508 5.92-18.97-1.586-25.602-3.285-2.9-7.326-4.4-11.39-4.535-.326-.01-.653-.013-.98-.006zm-186.425 158.51c-39.56-.098-79.467 5.226-120.633 16.095-2.046 90.448 34.484 209.35 118.47 259.905 81.295-49.13 122.402-169.902 120.552-259.914-39.75-10.496-78.91-15.988-118.39-16.086zm-117.176 153.5L60.47 428.35l-12.2 63.894 61.9-19.994 68.49-77.535c-12.86-20.108-23.246-42.03-31.324-64.703zm228.203 6.11c-8.69 22.238-19.577 43.634-32.706 63.142l64.473 72.986 61.898 19.994-12.2-63.894-81.466-92.23z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M329.8 235.69l62.83-82.71 42.86 32.56-62.83 82.75zm-12.86-9.53l66.81-88-45-34.15-66.81 88zm-27.48-97.78l-19.3 39.57 57-75-42.51-32.3-36.24 47.71zm-20.74-73.24l-46.64-35.43-42 55.31 53.67 26.17zm107 235.52l-139-102.71-9.92.91 4.56 2 62.16 138.43-16.52 2.25-57.68-128.5-40-17.7-4-30.84 39.41 19.42 36.36-3.33 17-34.83-110.9-54.09-80.68 112.51L177.6 346.67l-22.7 145.62H341V372.62l35.29-48.93L387 275.77z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 518 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M107.3 26c-4.146 0-8.6 22.976-13.214 42.934l32.187 100.97-39.052-69.726c-2.932 14.342-5.414 28.62-7.002 42.771l43.176 58.246-44.838-36.824c-.435 11.08-.15 22.056 1.078 32.897l45.515 36.597-40.89-13.285c2.558 9.025 5.94 18.077 9.812 27.049l40.819 26.943-30.065-4.312c13.83 26.954 29.823 52.218 38.697 72.506 2.565 5.13 8.023 16.754 10.926 28.168 3.89 15.695-4.529 35.939-21.271 38.322 12.285-14.291 13.245-23.507 11.02-32.535-13.242-.192-19.112 15.916-19.112 15.916s-12.527 23.473 15.717 59.369c28.244 35.895 67.176 33.974 67.176 33.974s-2.243-55.044-1.036-79.96c1.22-25.165 8.354-69.758 8.354-69.758s-19.998.093-42.443-15.8c-28.167-19.942-17.51-32.621-24.663-51.077-14.417-37.201-4.68-95.143-4.68-95.143s-10.858-42.59-17.85-72.822C119.864 76.366 110.398 26 107.3 26zm297.4 0c-3.099 0-12.565 50.366-18.36 75.42-6.993 30.232-17.852 72.822-17.852 72.822s9.738 57.942-4.68 95.143c-7.152 18.456 3.505 31.135-24.662 51.078-22.445 15.892-42.443 15.8-42.443 15.8s7.134 44.592 8.354 69.757c1.207 24.916-1.036 79.962-1.036 79.962s38.932 1.92 67.176-33.976 15.717-59.37 15.717-59.37-5.87-16.107-19.111-15.915c-2.226 9.028-1.266 18.246 11.02 32.537-16.743-2.383-25.162-22.629-21.272-38.324 2.903-11.414 8.361-23.037 10.926-28.168 8.874-20.288 24.868-45.552 38.699-72.506l-30.067 4.312 40.819-26.943c3.872-8.972 7.254-18.024 9.812-27.049l-40.89 13.285 45.515-36.597c1.228-10.84 1.513-21.817 1.078-32.897l-44.838 36.824 43.176-58.246c-1.588-14.15-4.07-28.429-7.002-42.771l-39.052 69.726 32.187-100.968C413.3 48.978 408.846 26 404.7 26zm-148.702.463c-19.388 0-64.1 45.402-88.344 75.728-7.017 8.779-15.795 29.823-15.795 29.823l9.194 37.289s-1.154 8.452-2.604 30.49c-1.091 16.591-1.054 32.803-1.054 32.803l52.677-16.893c4.003-22.545 11.506-52.087 20.246-77.21 7.007-20.141 25.68-58.575 25.68-58.575s19.2 36.655 26.072 56.107c9.115 25.801 15.807 57.482 19.856 79.678l52.678 16.893s.036-16.212-1.055-32.803c-1.45-22.038-2.604-30.49-2.604-30.49l9.194-37.29s-6.09-19.371-12.035-27.349c-24.096-32.334-72.718-78.201-92.106-78.201zm.002 77.09s-10.719 28.18-15.37 50.697c-4.299 20.818-11.898 66.635-11.898 66.635s11.983 11.928 5.682 18.256c-6.301 6.328-17.043-5.705-17.043-5.705l-56.435 17.128 3.337 13.217 53.098 19.854s10.656-12.118 17.043-5.703c6.388 6.414-5.682 23.959-5.682 23.959s3.879 16.06 5.995 24.045c3.45 13.022 10.927 38.908 10.927 38.908l10.344 2.867 10.346-2.867s6.8-24.203 10.047-36.346c2.366-8.85 6.875-26.607 6.875-26.607s-12.07-17.545-5.682-23.96c6.388-6.414 17.043 5.704 17.043 5.704l53.098-19.854 3.337-13.217-56.435-17.128s-10.742 12.033-17.043 5.705c-6.301-6.328 5.682-18.256 5.682-18.256s-7.547-42.316-11.897-65.81C267.12 132.121 256 103.552 256 103.552zm0 136.369c5.02 0 9.088 8.172 9.088 18.254 0 10.081-4.068 18.256-9.088 18.256s-9.09-8.175-9.09-18.256c0-10.082 4.07-18.254 9.09-18.254z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M114.4 35.99l36.8 85.91c4 2.4 7.9 4.9 11.8 7.5V66.55c-16-11.07-32.2-21.32-48.6-30.56zM181 50.56V160c0 .2.7 2.4 3.4 4.9 2.7 2.5 6.9 5.1 10.9 6.7 3.2 1.3 5.9 1.7 7.7 1.8V64c0-.25-.7-2.39-3.4-4.92s-6.9-5.11-10.9-6.72c-3.2-1.26-5.9-1.69-7.7-1.8zm40 60.54v63.2c48.3 43.4 88.2 95.2 118.7 145 22.3 36.5 39.5 71.9 51.2 102.5 9.9 25.8 16 47.9 17.6 65.2h93.1c-3.4-15.2-13.9-41.6-31-72.9-21.2-38.8-52-85.9-89.7-134.6C336 221.7 281.2 161.7 221 111.1zm-38 74.7V486h18V191.5c-4.2-.3-8.3-1.5-12.3-3.1-1.9-.8-3.8-1.7-5.7-2.6z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" ><path d="M254.1 18.63c-81.4 0-231.43 155.97-171.63 300.77 8 25.3 27.83 50.4 49.13 77.1 24.4 30.6 51.6 63.2 68.7 96.9h20.5c-18.1-39.8-48.5-75.9-74.6-108.6-27.4-34.3-48.73-65.2-48.73-87.9.1-9.1 2.23-18.1 5.53-26.3 23-61.4 114-119.7 148.5-135l3.6-2 3.9 1.3c60.9 20.9 129.3 66.7 154 135.7 4.1 11.7 5.9 18 5.6 27.3-.5 15.8-24.5 54.7-55 88.7-29.1 32.4-62.4 67.7-80 106.7h20.5c16.8-32.2 46.2-64 73.3-94.2 23.2-25.6 45.3-50 54.9-74.8 52.9-124-99.2-305.67-178.2-305.67zm.8 135.47c-38.7 21.5-85.1 52.2-113.7 88.2 9.7 83 59 146.1 118.3 146.1 59.2 0 108.3-62.7 118.2-145.3-28.9-42.1-78-72.9-122.8-89zm-58.3 83h2.4c13.1.1 26.1 2.7 39.1 7.4-16.8 40.6-59 42-78.1 0 12.2-4.8 24.4-7.2 36.6-7.4zm124.9 0c13-.1 26 2.3 39.1 7.4-19.2 42-61.3 40.6-78.2 0 13.1-4.7 26.1-7.3 39.1-7.4z" fill="#fff" fill-opacity="1"></path></svg>

After

Width:  |  Height:  |  Size: 868 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M166 121c0 90 90 105 90 180 0 30-30 75-75 75s-75-45-45-120c-45 30-60 60-60 90 0 75 75 150 180 150s180-45 180-135c.67-133.125-153.4-177.596-195-240-30-45-15-75 15-105-60 15-90 57-90 105z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#fff" d="M256 16l-32 112 32 32 32-32-32-112zM64 96l32 80 64 16-96-96zm384 0l-96 96 64-16 32-80zm-192 80l-64 48-128 32c80 16 128 96 192 128 64-32 112.476-110.213 192-128l-128-28.31L256 176zm-39.512 52.682l28.342 8.863-7.45 20.955L256 310.895l18.62-52.395-7.45-20.955 28.342-8.863c14.923 10.97 24.488 28.03 24.488 47.283C320 309.237 291.47 336 256 336s-64-26.763-64-60.035c0-19.254 9.565-36.314 24.488-47.283zM96 336l-64 48-16 64 32-32 64-48s-16-27.61-16-32zm320 0l-16 32 64 48 32 32-16-64-64-48zm-272 64l-16 64 48-48-32-16zm112 0l-48 16 48 80 48-80-48-16zm112 0l-32 16 48 48-16-64z"/></svg>

After

Width:  |  Height:  |  Size: 664 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M335.656 19.53c-24.51.093-48.993 5.235-71.062 15.626-22.46 10.577-43.112 34.202-58.375 62.563-15.264 28.36-25.182 61.262-27.69 88.75-7.487 82.112-51.926 155.352-159.78 252.56l-.188 21.44C89.216 403.443 139.915 346.632 176.313 290l.063.03c-9.293 32.473-22.623 63.18-43.594 87.97-31.47 35.584-69.222 71.1-114.468 106.53l-.062 8.25 25 .064h.47l1.28-1.156c24.405-16.498 48.607-31.488 72.594-41.5l.187.187-46.436 42.5 28.937.063c48.372-41.685 94.714-90.58 129.626-137 33.587-44.658 56.02-87.312 60.688-116.844-1.268-2.32-2.552-4.628-3.656-7.094-18.833-42.06-4.273-96.424 40.218-116.063 32.73-14.45 74.854-3.165 90.438 31.344.15.333.324.634.47.97 13.302 24.062 6.175 49.48-9.345 61.97-7.866 6.328-18.442 9.528-28.75 6.56-10.31-2.966-19.043-11.772-24.5-25.124l17.28-7.062c3.992 9.764 8.667 13.15 12.375 14.22 3.708 1.066 7.767.148 11.875-3.158 8.216-6.61 14.282-21.91 4.406-39.03l-.28-.47-.22-.5c-10.7-24.82-41.96-33.333-66.22-22.625-34.063 15.037-45.594 58.052-30.686 91.345 20.527 45.846 77.97 61.177 122.375 40.875 60.157-27.5 80.13-103.328 53.094-161.813-24.737-53.503-81.41-82.484-138.908-83.843-1.633-.04-3.272-.07-4.906-.063zm-25.75 26.72c3.238.035 6.363.348 9.406.906 10.343 1.898 19.946 6.753 29.032 13.25-30.623-5.437-58.324 4.612-80.78 24.782-22.44 20.152-39.16 50.59-45.783 84.718-4.655-11.358-7.166-21.462-6.686-31.72.296-6.343 1.715-12.956 4.78-20.217 9.094-18.016 21.032-33.946 35.22-46.69 7.824-7.026 16.39-13.07 25.53-17.905 10.932-5.212 20.522-7.22 29.282-7.125zm122.938 62.313c22.583 13.167 34.365 41.86 32.937 70.656-.564 11.395-3.466 22.975-8.905 33.624-12.48 18.937-35.53 25.51-49.97 20.875l-.092-.25c27.943-10.365 39.18-32.377 40.312-55.19.124-2.5.115-4.994-.03-7.468 1.447-13.31-.412-28.793-5.47-43.437-2.244-6.496-5.15-12.89-8.844-18.72l.064-.093zm-135.563 1.312c-20.97 19.342-29.406 35.252-33.25 51.25-3.848 16.023-2.788 32.84-2.905 52.875-.14 23.79-2.56 51.542-18.438 85.688-.005.012-.025.018-.03.03-21.095 26.753-45.276 52.25-68.907 67.376l-.063-.03c64.195-71.545 68.527-114.792 68.75-153.19.112-19.197-1.253-37.594 3.438-57.124.57-2.37 1.233-4.742 2-7.125h.03c8.098-17.036 16.572-26.058 25.47-31.563 7.18-4.44 15.035-6.697 23.906-8.187z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,44 @@
import {Inject, Injectable} from '@angular/core';
import {HttpClient, HttpParams} from '@angular/common/http';
import {Observable, of, throwError} from 'rxjs';
import {ErrorResponse} from '../types/ErrorResponse';
import {Either} from '../types/Either';
import {CharacterForLoginViewModel} from '../types/viewmodels/character-viewmodels/CharacterForLoginViewModel';
import {switchMap, retry} from 'rxjs/operators';
import {LoggedCharactersViewModel} from '../types/viewmodels/character-viewmodels/LoggedCharactersViewModel';
Injectable({
providedIn: 'root'
})
export class CharacterService {
private baseUrl = 'api/character/';
constructor(private http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
this.baseUrl = baseUrl + this.baseUrl;
}
getLoggedCharacters(): Observable<LoggedCharactersViewModel[]> {
return this.http.get<Either<LoggedCharactersViewModel[], ErrorResponse>>(this.baseUrl + 'loggedCharacters').pipe(
switchMap(response => {
if (response.isLeft) {
return of(response.left);
} else {
return throwError(response.right);
}
}),
retry(3)
);
}
getUserCharactersList(userId: number): Observable<CharacterForLoginViewModel[]> {
const params = new HttpParams().set('userId', userId.toString())
return this.http.get<Either<CharacterForLoginViewModel[], ErrorResponse>>(this.baseUrl + 'userCharactersList', {params}).pipe(
switchMap(response => {
if (response.isLeft) {
return of(response.left);
} else {
return throwError(response.right);
}
})
);
}
}

View File

@ -73,6 +73,10 @@ mat-divider {
border-top-color: #e9cca7 !important;
}
.arrow-select {
cursor: pointer;
}
html,
body {
height: 100%;

View File

@ -0,0 +1,7 @@
export interface CharacterForLoginViewModel {
id: number;
userId: number;
name: string;
className: string;
level: number;
}

View File

@ -0,0 +1,7 @@
export interface LoggedCharactersViewModel {
id: number;
name: string;
level: number;
currentHealthPoints: number;
class: string;
}