migrations

This commit is contained in:
peter
2020-03-25 23:49:54 +01:00
parent b28f8bc7ce
commit 9ff98d92ae
62 changed files with 711 additions and 483 deletions
+3
View File
@@ -58,6 +58,9 @@
"configurations": {
"production": {
"aot": true,
"optimization": true,
"extractCss": true,
"sourceMap": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
+11 -3
View File
@@ -15742,13 +15742,21 @@
"integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
},
"rpclibrary": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.9.2.tgz",
"integrity": "sha512-MOtVm0IBRLryXag1IwkYNPVFegbvW10+MbCjhr3GptO3MA7nHZ545ammgoCWnREtGOgFeN4Jib/EBDOJ9Ep41Q==",
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.10.2.tgz",
"integrity": "sha512-uf4FtylK+tyVo1O8YVihxYxaI4KHnKBzq05SsLYe8ZPXdO8Hqrv7Je5cwv3bfx0FBCO1vVrSc8DT1P6ypGY6uQ==",
"requires": {
"bsock": "^0.1.9",
"crypto-js": "^4.0.0",
"http": "0.0.0",
"uuid": "^3.3.3"
},
"dependencies": {
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
"integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
}
}
},
"run-async": {
+3 -2
View File
@@ -29,7 +29,8 @@
"prepush": "npm run lint:ci",
"release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
"add": "ng add @nguniversal/express-engine",
"tsc": "tsc --project src/tsconfig.server.json && webpack --config extra-webpack.config.js"
"tsc": "tsc --project src/tsconfig.server.json && webpack --config extra-webpack.config.js",
"knex": "knex"
},
"dependencies": {
"@agm/core": "^1.0.0-beta.5",
@@ -75,7 +76,7 @@
"normalize.css": "6.0.0",
"pace-js": "1.0.2",
"roboto-fontface": "0.8.0",
"rpclibrary": "^1.9.2",
"rpclibrary": "^1.10.2",
"rxjs": "6.5.2",
"rxjs-compat": "6.3.0",
"socicon": "3.0.5",
+8 -3
View File
@@ -13,7 +13,7 @@ global['document'] = win.document;
global['alert'] = console.log
global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
export async function attachExpress(app, staticDir = "./dist") {
export async function attachExpress(app, staticDir = "./dist", loggerService = console) {
const STATIC_FOLDER = resolve(process.cwd(), staticDir);
enableProdMode();
@@ -21,7 +21,7 @@ export async function attachExpress(app, staticDir = "./dist") {
const bundle = require(staticDir + '/server/main');
const ServerApiService = bundle.ServerApiService
const serviceObj = new ServerApiService()
const serviceObj = new ServerApiService(loggerService)
await serviceObj.initialize()
app.set('view engine', 'html');
@@ -31,10 +31,15 @@ export async function attachExpress(app, staticDir = "./dist") {
bootstrap: bundle.AppServerModuleNgFactory,
providers: [
provideModuleMap(bundle.LAZY_MODULE_MAP),
{
provide: bundle.LoggerService,
deps: [],
useValue: loggerService
},
{
provide: bundle.IApiService,
deps: [],
useValue: serviceObj,
deps: []
}
]
})
@@ -29,7 +29,8 @@
</nb-action>
<nb-action class="user-action">
<nb-user [nbContextMenu]="userMenu"
<nb-user style="text-transform: capitalize;"
[nbContextMenu]="userMenu"
[onlyPicture]="false"
[name]="user?.username">
</nb-user>
@@ -5,7 +5,7 @@ import { LayoutService } from '../../../@core/utils';
import { map, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { User } from '../../../../../../backend/Types/Types';
import { Router } from '@angular/router';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { ChatComponent } from './chat.component';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@@ -41,7 +41,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
];
currentTheme = 'default';
userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
userMenu: NbMenuItem[] = [];
sendMessage: any = console.log
chatwindow: ChatComponent
@@ -50,13 +50,29 @@ export class HeaderComponent implements OnInit, OnDestroy {
lastmessage = "asdasd"
modifyPermissions
constructor(private sidebarService: NbSidebarService,
private router: Router,
private themeService: NbThemeService,
private layoutService: LayoutService,
private api: IApiService,
private dialogService : NbDialogService
) {}
constructor(
private sidebarService: NbSidebarService,
private router: Router,
private themeService: NbThemeService,
private layoutService: LayoutService,
private api: IApiService,
private dialogService: NbDialogService,
private route: ActivatedRoute
) { }
private setUserMenu = (redirect = this.router.url) => {
if (this.user.username === 'Guest' && this.user.rank === 'Guest'){
this.userMenu = [
{ title: 'Login', link: '/auth/login', queryParams: { redirect: redirect } },
{ title: 'Register', link: '/auth/register', queryParams: { redirect: redirect } },
]
}else{
this.userMenu = [
{ title: 'Profile', link: '/frontcraft/user/' + this.user.username },
{ title: 'Log out', link: '/auth/logout', queryParams: { redirect: redirect } },
]
}
}
ngOnInit() {
this.themeService.changeTheme("dark");
@@ -64,28 +80,36 @@ export class HeaderComponent implements OnInit, OnDestroy {
this.currentTheme = this.themeService.currentTheme;
this.modifyPermissions = this.api.get('modifyPermissions')
this.user = this.api.getCurrentUser()
if(this.user)
this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
this.setUserMenu()
this.router.events.subscribe((val) => {
if(val instanceof NavigationEnd) {
this.setUserMenu(val.urlAfterRedirects)
}
})
this.api.get('GuildManager').getGuildInfo().then(info => {
this.title = info.name
})
this.api.connectShoutbox((msg) => {
this.chatlog.push(msg)
msg['reply']=false
msg['reply'] = false
if(msg.message != this.lastmessage){
if (msg.message != this.lastmessage) {
this.newmessage = true
msg['reply']=true
msg['reply'] = true
}
if(this.chatwindow) this.chatwindow.messages.push(msg)
if (this.chatwindow) this.chatwindow.messages.push(msg)
}).then(sendMsg => {
this.sendMessage = (msg) => {
sendMsg(msg)
this.lastmessage = msg.message
}
this.api.get('Shoutbox').getFeed().then(log => {this.chatlog = log})
this.api.get('Shoutbox').getFeed().then(log => { this.chatlog = log })
})
this.themeService.onThemeChange()
@@ -96,14 +120,14 @@ export class HeaderComponent implements OnInit, OnDestroy {
.subscribe(themeName => this.currentTheme = themeName);
}
openChat(){
openChat() {
this.newmessage = false
const ref = this.dialogService.open(ChatComponent, {
context: {
sendMessage: this.sendMessage,
}
});
ref.onClose.subscribe(()=>{
ref.onClose.subscribe(() => {
this.chatwindow = null
})
this.chatwindow = ref.componentRef.instance
@@ -122,7 +146,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
toggleSidebar(): boolean {
this.sidebarService.toggle(true, 'menu-sidebar');
this.layoutService.changeLayoutSize();
return false;
}
+1 -6
View File
@@ -9,9 +9,4 @@ import { Component, OnInit } from '@angular/core';
selector: 'ngx-app',
template: '<router-outlet></router-outlet>',
})
export class AppComponent implements OnInit {
constructor() { }
ngOnInit(): void { }
}
export class AppComponent { }
+5 -5
View File
@@ -5,11 +5,15 @@
*/
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule, APP_INITIALIZER, NgZone, Injector } from '@angular/core';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ThemeModule } from './@theme/theme.module';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { CoreModule } from './@core/core.module';
import { FrontcraftPagesModule } from './frontcraft/pages/pages.module';
import { MyAuthModule } from './frontcraft/auth/auth.module';
import { PermissionsModule } from './frontcraft/permissions/permissions.module';
import {
NbChatModule,
NbDatepickerModule,
@@ -19,10 +23,6 @@ import {
NbToastrModule,
NbWindowModule,
} from '@nebular/theme';
import { CoreModule } from './@core/core.module';
import { FrontcraftPagesModule } from './frontcraft/pages/pages.module';
import { MyAuthModule } from './frontcraft/auth/auth.module';
import { PermissionsModule } from './frontcraft/permissions/permissions.module';
@NgModule({
declarations: [
+1 -1
View File
@@ -1,5 +1,5 @@
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
@@ -0,0 +1,57 @@
import { Router, NavigationStart } from '@angular/router'
import { IApiService } from './services/ApiService'
import { AnyFunction } from 'rpclibrary'
import { LoggerService } from './services/logger.service'
import { OnDestroy } from '@angular/core'
export abstract class UpdatingComponent implements OnDestroy {
private _uuid: string
private _routerCancel: Function
constructor(
private _router: Router,
private _api: IApiService,
private _logger: LoggerService
) { }
protected subscribe = (
topic: string,
callback: AnyFunction,
) => {
const sub = this._router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.ngOnDestroy()
}
})
this._routerCancel = () => { sub.unsubscribe() }
this._api.get('PubSub').subscribe(topic, callback).then(uuid => {
this._logger.collapsed(`New subscription ${topic}`, "table", {
topic: topic,
uuid: uuid
})
this._uuid = uuid
}).catch(e => {
this._logger.warn(`Subscribe for ${topic} failed, ${String(e)}`)
delete this._uuid
})
}
//Note angular may call this function several times
ngOnDestroy() {
if (this._uuid) {
const id = this._uuid
delete this._uuid
this._api.get('PubSub').unsubscribe(id).then(() => {
this._logger.log(`Unsubscribed from ${id}`)
})
}
if (this._routerCancel) {
try {
this._routerCancel()
} catch (e) {
this._logger.warn(e)
}
delete this._routerCancel
}
}
}
@@ -1,6 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
@Component({
selector: 'auth-layout',
@@ -48,5 +48,5 @@
<section class="another-action" aria-label="Register">
Don't have an account? <a class="text-link" routerLink="/auth/register">Register</a>
Don't have an account? <a class="text-link" routerLink="/auth/register" [queryParams]="{redirect: '/frontcraft'}">Register</a>
</section>
@@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { IApiService } from '../../services/ApiService';
import { NbToastrService } from '@nebular/theme';
@@ -24,7 +23,8 @@ export class MyLoginComponent implements OnInit{
constructor(
private router : Router,
private api : IApiService,
private toastr: NbToastrService
private toastr: NbToastrService,
private route: ActivatedRoute
){}
ngOnInit(){
@@ -41,8 +41,9 @@ export class MyLoginComponent implements OnInit{
this.toastr.danger("Login failed", "Error")
return
}else{
window['r'] = this.router
this.router.navigate(["/froncraft"])
this.route.queryParamMap.subscribe(params => {
this.router.navigate([params.get('redirect')])
})
}
}
}
@@ -1 +1 @@
You will be redirected shortly. If not click here <a href="/auth/login">click</a>
You will be redirected shortly. If not click here <a routerLink="/auth/login" [queryParams]="{redirect: '/frontcraft'}">click</a>
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { IApiService } from '../../services/ApiService';
import { Router } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
@Component({
selector: 'mylogout',
@@ -10,12 +10,15 @@ export class LogoutComponent implements OnInit{
constructor(
private api : IApiService,
private router: Router
private router: Router,
private route: ActivatedRoute
){}
ngOnInit(){
this.api.logout().then(() => {
this.router.navigate(['/auth/login'])
this.route.queryParamMap.subscribe(params => {
this.router.navigate([params.get('redirect')])
})
})
}
}
@@ -92,5 +92,5 @@
<section class="another-action" aria-label="Register">
Back to <a class="text-link" routerLink="auth/login">Login</a>
Go to <a class="text-link" routerLink="auth/login" [queryParams]="{redirect: '/frontcraft'}">Login</a>
</section>
@@ -1,9 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types'
import { specs } from '../../../../../../backend/Types/PlayerSpecs'
import { race } from 'rxjs';
import { hash, IApiService } from '../../services/ApiService';
@@ -33,7 +31,8 @@ export class RegisterComponent implements OnInit{
submitted = false
constructor(
private router : Router,
private router : Router,
private route : ActivatedRoute,
private api : IApiService
){}
@@ -84,6 +83,11 @@ export class RegisterComponent implements OnInit{
userid: this.api.getAuth().user.id!,
race: char.race
})
this.route.queryParamMap.subscribe(params => {
this.router.navigate([params.get('redirect')])
})
}catch(e){
alert("Error creating character"+e)
return
@@ -2,7 +2,6 @@ import { Component, OnInit } from '@angular/core';
import { Item, Stats } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme';
import { ClientApiService } from '../../services/client-login-api';
import { IApiService } from '../../services/ApiService';
@Component({
@@ -1,6 +1,5 @@
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { ActivatedRoute } from '@angular/router';
import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items';
@@ -1,10 +1,8 @@
import { Component, AfterContentInit, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { NbMenuItem } from '@nebular/theme';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
import { IApiService } from '../services/ApiService';
declare const Cookies
@Component({
selector: 'page-layout',
@@ -16,7 +14,7 @@ declare const Cookies
</ngx-one-column-layout>
`,
})
export class PagesLayoutComponent implements OnInit{
export class PagesLayoutComponent{
menu:NbMenuItem[] = [{
icon: 'image',
@@ -36,18 +34,6 @@ export class PagesLayoutComponent implements OnInit{
link: '/frontcraft/armory'
}]
constructor(
private api : IApiService,
private router : Router
){}
constructor(){}
ngOnInit(): void {
/*
const u = this.api.getCurrentUser()
if(!u){
this.router.navigate(['/auth/login'])
}
*/
}
}
@@ -9,7 +9,6 @@ import {
NbInputModule,
NbMenuModule,
NbCardModule,
NbTreeGridModule,
NbListModule,
NbTabsetModule,
NbIconModule,
@@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { RaidData } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@@ -34,7 +33,7 @@ export class FrontcraftArchiveComponent implements OnInit{
tanks:[],
healers: []
}
tokens = {}
tokens: {[key in string]:any[]} = {}
displayedtokens = {}
search = ""
@@ -53,6 +52,10 @@ export class FrontcraftArchiveComponent implements OnInit{
const raidManager = this.api.get('RaidManager')
const raiddata = await raidManager.getArchiveRaid(parseInt(param))
console.log(raiddata);
this.raid = raiddata
this.isTier = raiddata.tier != null
this.tokens = raiddata.tokens
@@ -69,8 +72,18 @@ export class FrontcraftArchiveComponent implements OnInit{
this.changeSearch()
}
changeSearch = () => {
this.tokens = this.raid.tokens;
this.displayedtokens = this.raid.tokens;
changeSearch(){
if(!this.search || this.search == ""){
this.displayedtokens = this.tokens
}else{
this.displayedtokens = {}
Object.entries(this.tokens).forEach((e) => {
const filteredTokens = e[1].filter(item => {
return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
})
if(filteredTokens.length > 0)
this.displayedtokens[e[0]] = filteredTokens
})
}
}
}
@@ -3,34 +3,41 @@
Pick Character
</nb-card-header>
<nb-card-body>
<div *ngFor="let character of characters">
<img [src]="'../../../../assets/images/'+character.class.toLowerCase()+'.png'" />
<span [ngStyle]="{'color': character.color}">
<textarea
placeholder="Add a note (optional)"
rows="7"
cols="50"
nbInput style="white-space: pre-line;"
[(ngModel)]="memo">
</textarea>
<br />
<br />
<nb-card *ngFor="let character of characters">
<nb-card-header [ngStyle]="{'color': character.color}">
<img [src]="'../../../../assets/images/'+character.class.toLowerCase()+'.png'" />
{{character.charactername}}
</span>
<br >
<br >
<br >
<button
(click)="signup(character, false)"
nbButton
outline
status="success"
size="medium">
<nb-icon icon="checkmark-outline"></nb-icon> On Time
</button>
&nbsp;
&nbsp;
&nbsp;
<button
(click)="signup(character, true)"
nbButton
outline
status="warning"
size="medium">
<nb-icon icon="clock-outline"></nb-icon> Late
</button>
</div>
</nb-card-header>
<nb-card-body>
<button
(click)="signup(character, false)"
nbButton
outline
status="success"
size="medium">
<nb-icon icon="checkmark-outline"></nb-icon> On Time
</button>
&nbsp;
&nbsp;
&nbsp;
<button
(click)="signup(character, true)"
nbButton
outline
status="warning"
size="medium">
<nb-icon icon="clock-outline"></nb-icon> Late
</button>
</nb-card-body>
</nb-card>
</nb-card-body>
</nb-card>
@@ -1,7 +1,6 @@
import { OnInit, Component } from '@angular/core';
import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme';
import { NbToastrService, NbDialogRef } from '@nebular/theme';
import { RaidData, Character } from '../../../../../../backend/Types/Types';
import { ClientApiService } from '../../services/client-login-api';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@@ -13,6 +12,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
raid : RaidData
characters: Character[]
memo: string
constructor(
protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>,
@@ -25,7 +25,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
const signup = this.api.get('signup')
if(!signup) return
await signup.sign(auth.token.value, character, this.raid, late)
await signup.sign(auth.token.value, character, this.raid, late, this.memo)
this.toast.show('Signup', 'Success', { status: 'success' })
this.dialogRef.close()
}
@@ -5,34 +5,47 @@
<nb-tabset>
<nb-tab tabTitle="Info">
<h1>
<img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
<img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
style="height: 100px" />
{{raid.title}}
</h1>
<p>
{{raid.signupcount}} / {{raid.size}} signups
</p>
<p>
<p style="white-space: pre-line;">
{{raid.description}}
</p>
<div *ngIf="canSignup">
<div *ngIf="isSignedup">
<p>
You are signed as: {{mySignup.charactername}} ({{mySignup.race}}
{{mySignup.specname}}
{{mySignup.class}})<br />
Status: {{mySignup.status}}
<div *ngIf="isSignedup" style="width: 100%;">
<p style="white-space: pre-line;">
You are signed as: <span
style="text-transform: capitalize; word-break: keep-all;">{{mySignup.charactername}}</span>
({{mySignup.race}} {{mySignup.specname}} {{mySignup.class}})
<br />
Status: {{mySignup.status}}<br /><br />
<textarea [status]="mySignup.status === 'Attending'?'success':'warning'"
placeholder="Add a note (optional)" rows="10" cols="50" nbInput
style="white-space: pre-line;" [(ngModel)]="mySignup.memo">
</textarea>
</p>
<button (click)="setLate(true)" *ngIf="mySignup.status !== 'Late'" nbButton outline
status="warning" size="medium">
<nb-icon icon="clock-outline"></nb-icon> Late
</button>
<button (click)="setLate(false)" *ngIf="mySignup.status === 'Late'" nbButton outline
<button *ngIf="mySignup.status === 'Late'" (click)="setLate(false)" nbButton outline
status="success" size="medium">
<nb-icon icon="checkmark-outline"></nb-icon> On Time
</button>
<button *ngIf="mySignup.status === 'Attending'" (click)="setLate(false)" nbButton
outline status="success" size="medium">
<nb-icon icon="checkmark-outline"></nb-icon> Update
</button>
<button *ngIf="mySignup.status === 'Late'" (click)="setLate(true)" nbButton outline
status="warning" size="medium">
<nb-icon icon="clock-outline"></nb-icon> Update
</button>
<button *ngIf="mySignup.status === 'Attending'" (click)="setLate(true)" nbButton outline
status="warning" size="medium">
<nb-icon icon="clock-outline"></nb-icon> Late
</button>
<button (click)="unsign()" nbButton outline status="danger" size="medium">
<nb-icon icon="close"></nb-icon>unsign
</button>
@@ -46,7 +59,6 @@
</nb-tab>
<nb-tab tabTitle="Signups" [badgeText]="raid.signupcount" badgePosition="top right"
[badgeStatus]="raid.signupcount<40?'warning':'success'">
<div class="row">
<nb-card class="col-12 col-md-6" *ngIf="raid.tanks.length > 0">
<nb-card-header>Tanks ({{raid.tanks.length}})</nb-card-header>
@@ -63,11 +75,28 @@
<a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
[routerLink]="'/frontcraft/character/'+participant.charactername">
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
[src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
[src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<ng-template #template>
<div style="padding: 10px">
<p
style="white-space: pre-line; max-width: 50vw; word-wrap: break-word;">
{{participant.memo}}
</p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}}
</div>
</ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
<nb-icon *ngIf="participant.memo != null && participant.memo != ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
@@ -90,11 +119,27 @@
<a [ngStyle]="{'color': participant.color}" style="text-transform: capitalize;"
[routerLink]="'/frontcraft/character/'+participant.charactername">
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
[src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
[src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<ng-template #template>
<div style="padding: 10px">
<p style="white-space: pre-line;">
{{participant.memo}}
</p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}}
</div>
</ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
<nb-icon *ngIf="participant.memo != null && participant.memo != ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
@@ -119,11 +164,27 @@
style="text-transform: capitalize;"
[routerLink]="'/frontcraft/character/'+participant.charactername">
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
[src]="'/assets/images/'+participant.race.toLowerCase()+'_xs.gif'" />
<img style="width:20px; height:20px"
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
[src]="'/assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<ng-template #template>
<div style="padding: 10px">
<p style="white-space: pre-line;">
{{participant.memo}}
</p>
{{participant.timestamp | date : 'HH:mm EEE MMM d'}}
</div>
</ng-template>
<nb-icon *ngIf="participant.memo == null || participant.memo == ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="clock-outline"></nb-icon>
<nb-icon *ngIf="participant.memo != null && participant.memo != ''"
[nbPopover]="template" nbPopoverTrigger="hover"
style="width: 0.75em; height: 0.75em;" icon="message-circle-outline" status="info">
</nb-icon>
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
@@ -147,7 +208,8 @@
<nb-card-body>
<nb-tabset>
<nb-tab tabTitle="Reserves" [active]="reservesShown">
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search"
fullWidth="true">
<nb-list class="">
<nb-list-item *ngFor="let item of displayedtokens | keyvalue">
@@ -161,15 +223,13 @@
<tr>
<td>
<div class="row">
<div
*ngFor="let token of item.value"
class="col-12 col-md-6 col-xl-4">
<div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
<span
[ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
<span style="text-transform: capitalize;">
[&nbsp;{{token.level}}&nbsp;]&nbsp;
<span style="text-transform: capitalize; white-space: nowrap;">
[ {{token.level}} ]&nbsp;
<a [routerLink]="'/frontcraft/character/'+token.charactername"
[ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
[ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
{{token.charactername}}
</a>
</span>
@@ -179,13 +239,14 @@
Becomes valid when promoted to Raider
</div>
</ng-template>
<span *ngIf="token.rank=='Trial'" style="font-size: 9px;" [nbPopover]="tooltip"
nbPopoverTrigger="hover" nbPopoverPlacement="top">
<span *ngIf="token.rank=='Trial'" style="font-size: 9px;"
[nbPopover]="tooltip" nbPopoverTrigger="hover"
nbPopoverPlacement="top">
Trial
</span><br />
</div>
</div>
</td>
</tr>
</table>
@@ -1,19 +1,22 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router, NavigationStart } from '@angular/router';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
import { NbToastrService, NbDialogService } from '@nebular/theme';
import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
import { allItems } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
import { UpdatingComponent } from '../../UpdatingComponent';
import { LoggerService } from '../../services/logger.service';
@Component({
selector: 'raid',
templateUrl: './raid.component.html',
})
export class FrontcraftRaidComponent implements OnInit, OnDestroy{
export class FrontcraftRaidComponent
extends UpdatingComponent
implements OnInit{
canSignup = false
isSignedup = false
@@ -43,41 +46,28 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
tokens: {[itemname in string]: (Character & SRToken & Item)[]} = {}
displayedtokens = {}
search = ""
uuid
constructor(
private api: IApiService,
private route: ActivatedRoute,
private router: Router,
private dialogService : NbDialogService,
private toast: NbToastrService
private toast: NbToastrService,
logger: LoggerService
){
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.ngOnDestroy()
}
})
super(router, api, logger)
}
ngOnDestroy = () => {
if(this.uuid)
this.api.get('PubSub').unsubscribe(this.uuid)
}
async ngOnInit(){
ngOnInit(){
this.manageRaid = this.api.get('manageRaid')
const signupFeature = this.api.get('signup')
if(signupFeature){
this.canSignup = true
}
await this.refresh()
const res = await this.api.get('PubSub').subscribe(""+this.raid.id!, (data: RaidData) => {
this.display(data)
this.refresh().then(() => {
this.subscribe(String(this.raid.id), (data: RaidData) => this.display(data))
})
this.uuid = res.uuid
}
itemSelect = async(item) => {
@@ -143,7 +133,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
await signup.sign(auth.token.value, {
...this.mySignup,
id: this.mySignup.characterid,
}, this.raid, value)
}, this.raid, value, this.mySignup.memo)
this.toast.show('Signup', 'Success', { status: 'success' })
}
@@ -163,9 +153,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
const raiddata = await raidManager.getRaidData(<any>{
id: param
})
this.display(raiddata)
}
display = async (raiddata:RaidData) => {
@@ -179,15 +167,17 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
})
const user = this.api.getCurrentUser()
const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
const matchingSignup = Object.values(raiddata.participants).flat().find(char => user && char.userid === user.id!)
if(matchingSignup){
this.isSignedup = true
this.mySignup = matchingSignup
this.isSignedup = true
this.mySignup['status'] = matchingSignup['benched']?'Bench':matchingSignup['late']?'Late':'Attending'
}else{
this.isSignedup = false
this.mySignup = null
}
this.changeSearch()
}
@@ -202,9 +192,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
})
if(filteredTokens.length > 0)
this.displayedtokens[e[0]] = filteredTokens
})
console.log(this.displayedtokens);
})
}
}
@@ -1,7 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService } from '../../services/client-login-api';
import { Raid, RaidData } from '../../../../../../backend/Types/Types';
import { NbWindowRef, NbDialogRef } from '@nebular/theme';
import { NbDialogRef } from '@nebular/theme';
import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@@ -31,7 +30,7 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
private api: IApiService
) {}
loadNext(cardData) {
loadNext() {
}
onTierSelect(){
@@ -1,64 +1,70 @@
<nb-card class="col-12 col-xl-9">
<nb-card-header>
Upcoming raids
<nb-icon
style="color:orange"
*ngIf="manageRaid"
(click)="create()"
icon="plus-square-outline"></nb-icon>
<nb-icon style="color:orange" *ngIf="manageRaid" (click)="create()" icon="plus-square-outline"></nb-icon>
</nb-card-header>
<nb-list
nbInfiniteList
listenWindowScroll
[threshold]="500">
<nb-list-item *ngFor="let raid of raids"
[routerLink]="'/frontcraft/raid/'+raid.id"
class="raidlist"
style="cursor: pointer;">
<div class="row">
<img [src]="'../../../../assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
style="object-fit: contain"
class="col-1 col-s-3" />
<div class="col-11 col-s-9" >
<div class="row">
<div class="col-12" style="padding-top: 5px">
<nb-list nbInfiniteList listenWindowScroll [threshold]="500">
<nb-list-item *ngFor="let raid of raids" class="raidlist">
<a [routerLink]="'/frontcraft/raid/'+raid.id">
<div class="row">
<table>
<tr>
<td rowspan="2" style="padding-right: 20px;">
<img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
style="max-width: 50px; object-fit: contain" />
</td>
<h4>
{{raid.title}}
</h4>
</div>
</div>
<div class="row" style="padding-top: 5px; padding-bottom: 5px; color:darkgray">
<div class="col-6 col-md-3">
<nb-icon icon="checkmark-circle"></nb-icon> {{raid.signupcount}} / {{raid.size}}<br>
</div>
<div class="col-6 col-md-3">
<nb-icon icon="clock-outline"></nb-icon> {{raid.start | date : 'HH:mm'}}
</div>
<div class="col-12 col-md-6">
<nb-icon icon="calendar-outline"></nb-icon> {{raid.start | date : 'EEE MMM d'}}
</div>
</div>
</tr>
<tr>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br>
</td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
</td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
</td>
</tr>
</table>
</div>
</div>
</a>
</nb-list-item>
</nb-list>
</nb-card>
<nb-card class="col-12 col-xl-9">
<nb-card-header>Previous raids</nb-card-header>
<nb-list
nbInfiniteList
listenWindowScroll
[threshold]="500">
<nb-list nbInfiniteList listenWindowScroll [threshold]="500">
<nb-list-item *ngFor="let raid of oldraids" [routerLink]="'/frontcraft/archive/'+raid.id">
<b>{{raid.title}}</b><br>
{{raid.signupcount}} / {{raid.size}}<br>
{{raid.start | date : 'EEEE d MMMM @ HH:mm'}}<br>
{{raid.description}}<br>
<a [routerLink]="'/frontcraft/archive/'+raid.id">
<div class="row">
<table>
<tr>
<td rowspan="2" style="padding-right: 20px;">
<img [src]="'/assets/images/'+(raid.tier || 'null').toLowerCase()+'.png'"
style="max-width: 50px;;object-fit: contain; filter: grayscale(75%)" />
</td>
<h4>
{{raid.title}}
</h4>
</tr>
<tr>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="checkmark-circle"></nb-icon>&nbsp;{{raid.signupcount}}&nbsp;/&nbsp;{{raid.size}}<br>
</td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="clock-outline"></nb-icon>&nbsp;{{raid.start | date : 'HH:mm'}}
</td>
<td style="padding-right: 25px; white-space: nowrap; color: lightslategray;">
<nb-icon icon="calendar-outline"></nb-icon>&nbsp;{{raid.start | date : 'EEE MMM d'}}
</td>
</tr>
</table>
</div>
</a>
</nb-list-item>
</nb-list>
</nb-card>
</nb-card>
@@ -1,69 +1,59 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ClientApiService } from '../../services/client-login-api';
import { NbWindowService, NbDialogService } from '@nebular/theme';
import { NbDialogService } from '@nebular/theme';
import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
import { Router, NavigationStart } from '@angular/router';
import { IApiService } from '../../services/ApiService';
import { UpdatingComponent } from '../../UpdatingComponent';
import { LoggerService } from '../../services/logger.service';
@Component({
selector: 'raids',
templateUrl: 'raids.component.html',
styleUrls: ['raids.component.scss'],
})
export class FrontcraftRaidsComponent implements OnInit, OnDestroy{
export class FrontcraftRaidsComponent
extends UpdatingComponent
implements OnInit {
manageRaid
raids = []
oldraids = []
pageSize = 10;
uuid
constructor(
private api: IApiService,
private router: Router,
private dialogService: NbDialogService
router: Router,
private dialogService: NbDialogService,
logger: LoggerService
) {
this.manageRaid = this.api.get('manageRaid')
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.ngOnDestroy()
}
})
super(router, api, logger)
}
ngOnDestroy = () => {
if(this.uuid)
this.api.get('PubSub').unsubscribe(this.uuid)
ngOnDestroy(){
super.ngOnDestroy()
}
async ngOnInit() {
const res = await this.api.get('PubSub').subscribe("raids", () => {
this.refresh()
})
this.uuid = res.uuid
this.subscribe("raids", () => this.refresh())
this.manageRaid = this.api.get('manageRaid')
this.refresh()
}
refresh() {
this.api.get('RaidManager').getRaids().then(raids => {
this.raids = raids
})
async refresh() {
this.raids = await this.api.get('RaidManager').getRaids()
const raidManager = this.api.get('RaidManager')
raidManager.getPastRaids(10).then(raiddata => {
this.oldraids = raiddata
})
this.oldraids = await raidManager.getPastRaids(10)
}
create(){
this.dialogService.open(FrontcraftCreateRaidsComponent, {
create() {
this.dialogService.open(FrontcraftCreateRaidsComponent, {
closeOnBackdropClick: true,
closeOnEsc: true,
context: {
templates: this.oldraids
}
}
})
}
}
@@ -1,10 +1,8 @@
import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { FrontcraftItemSelectComponent } from './itemselector.component';
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
import { Component, OnInit, Input } from '@angular/core';
import { NbToastrService, NbDialogRef } from '@nebular/theme';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
import { _Tiers, Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({
@@ -24,8 +24,16 @@ export class FrontcraftItemSelectComponent implements OnInit{
async ngOnInit(){
Promise.all(this.items.map(itemname =>
this.api.get('ItemManager').getItem(itemname)
Promise.all(this.items.map(async itemname => {
try{
return await this.api.get('ItemManager').getItem(itemname)
}catch(e){
console.log(itemname);
}
}
)).then(items => {
this.allItems = items
this.displayedItems = this.allItems
@@ -1,6 +1,4 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { NbDialogService } from '@nebular/theme';
import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
@@ -57,7 +57,7 @@ accent="info">
</form>
<br />
<h3>Avaiable Reserves</h3>
<h3>Available Reserves</h3>
{{user.MC}} MC |
{{user.BWL}} BWL |
{{user.ZG}} ZG |
@@ -1,6 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router';
import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types'
import { NbToastrService } from '@nebular/theme';
import { IApiService } from '../../services/ApiService';
@@ -1,5 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
@Component({
@@ -1,23 +1,30 @@
import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
import { saltedHash } from '../../../../../backend/Util/hash';
import { RPCSocket } from 'rpclibrary';
import { RPCSocket, ConnectedSocket } from 'rpclibrary';
export class IApiService{
getUnprivilegedSocket: () => RPCSocket & FrontcraftIfc
getUnprivilegedSocket: () => ConnectedSocket<FrontcraftIfc>
getAuth: () => Auth | undefined
checkLogin: () => Promise<boolean>
initialize: () => Promise<any>
getCurrentUser: () => User | undefined
getCurrentUser: () => User
login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
connectShoutbox: (callback:Function) => Promise<Function>
kick: () => Promise<void>
logout: () => Promise<void>
get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
never
get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc
? FrontcraftIfc[K]
: K extends keyof FrontcraftFeatureIfc
? (FrontcraftFeatureIfc[K] | void)
: never
}
export async function hash(value:string) : Promise<string>{
return saltedHash(value, "")
}
export const GuestUser: User = {
username: 'Guest',
pwhash: '',
rank: 'Guest'
}
@@ -1,24 +1,28 @@
import { Injectable } from "@angular/core";
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
import { RPCSocket } from 'rpclibrary/js/src/Frontend'
import { ConnectedSocket } from "rpclibrary"
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
import { hash, IApiService } from './ApiService';
import { hash, IApiService, GuestUser } from './ApiService';
import { LoggerService } from './logger.service';
declare const Cookies
@Injectable()
export class ClientApiService implements IApiService{
private socket:RPCSocket & FrontcraftIfc;
private socket:ConnectedSocket<FrontcraftIfc>
private auth:Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
private privSocket: RPCSocket<SomeOf<FrontcraftFeatureIfc>>
constructor(){
constructor(
private logger: LoggerService
){
window['s'] = this
}
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket<SomeOf<FrontcraftFeatureIfc>>> => {
if(this.privSocket) {
return this.privSocket
}
@@ -38,17 +42,17 @@ export class ClientApiService implements IApiService{
sock.hook('getUserData', () => auth)
sock.on('close', async () => {
console.log("priv#close");
this.logger.log("priv#close");
//handled via unprivileged socket
})
sock.on('error', async (e) => {
console.log("priv#error", e);
this.logger.log("priv#error", e);
//handled via unprivileged socket
})
const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
const authSock = await sock.connect(auth.token.value)
this.auth = auth
this.privSocket = authSock
@@ -74,8 +78,8 @@ export class ClientApiService implements IApiService{
}
}
getCurrentUser = () : User | undefined => {
return this.auth?this.auth.user:undefined
getCurrentUser = () : User => {
return this.auth?this.auth.user:GuestUser
}
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
@@ -102,8 +106,8 @@ export class ClientApiService implements IApiService{
}
async connectShoutbox(callback:Function) : Promise<Function>{
const res = await this.get('Shoutbox').subscribe(callback)
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
const uuid = await this.get('Shoutbox').subscribe(callback)
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(uuid, msg)
}
kick = async () => {
@@ -113,6 +117,7 @@ export class ClientApiService implements IApiService{
logout = async () => {
Cookies.remove('token')
if(this.privSocket) this.privSocket.unhook('kick')
if(this.auth){
try{
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
@@ -133,11 +138,11 @@ export class ClientApiService implements IApiService{
}
try{
let conn = new RPCSocket(20000, window.location.hostname)
let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
conn.on('close', async () => {
})
this.socket = await conn.connect<FrontcraftIfc>()
this.socket = await conn.connect()
}catch(e){
alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
location.reload()
@@ -0,0 +1,37 @@
import { Injectable } from "@angular/core";
import { environment } from '../../../environments/environment';
interface ILoggerService{
log,
warn,
error,
table,
collapsed
}
@Injectable()
export class LoggerService implements ILoggerService {
constructor(
private logger = console
) { }
log = (...args) => { this.LOG('log', args) }
warn = (...args) => { this.LOG('warn', args) }
error = (...args) => { this.LOG('error', args) }
table = (...args) => { this.LOG('table', args) }
collapsed = (groupname: string, type: keyof ILoggerService, ...args) => {
if(type === "collapsed")
return this.log(args)
console.groupCollapsed(groupname)
this[type as any].apply(this.logger, args)
console.groupEnd()
}
private LOG(type, ...args) {
if (!environment.production) {
this.logger[type].apply(this.logger, ...args)
}
}
}
@@ -1,19 +1,23 @@
import { Injectable } from "@angular/core";
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
import { hash, IApiService } from './ApiService';
import { hash, IApiService, GuestUser } from './ApiService';
import { LoggerService } from './logger.service';
import { ConnectedSocket } from 'rpclibrary';
declare const Cookies
@Injectable()
export class ServerApiService implements IApiService{
private socket:RPCSocket & FrontcraftIfc;
private socket:ConnectedSocket<FrontcraftIfc>
private auth:Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
constructor(){}
constructor(
private logger: LoggerService
){}
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
getUnprivilegedSocket = () : ConnectedSocket<FrontcraftIfc> => this.socket
get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
@@ -22,8 +26,8 @@ export class ServerApiService implements IApiService{
return this.socket[feature]
}
getCurrentUser = () : User | undefined => {
return this.auth?this.auth.user:undefined
getCurrentUser = () : User => {
return GuestUser
}
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
@@ -42,13 +46,13 @@ export class ServerApiService implements IApiService{
//attach error handler now so failed logins dont trigger reloads
this.socket.on('error', async (err) => {
console.log(err);
this.logger.log(err);
})
}
async connectShoutbox(callback:Function) : Promise<Function>{
return console.log
return this.logger.log
}
kick = async () => {
@@ -60,7 +64,7 @@ export class ServerApiService implements IApiService{
try{
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
}catch(e){
console.warn(e);
this.logger.warn(e);
}
}
@@ -76,13 +80,13 @@ export class ServerApiService implements IApiService{
}
try{
let conn = new RPCSocket(20000, window.location.hostname)
let conn = new RPCSocket<FrontcraftIfc>(20000, window.location.hostname)
conn.on('close', async () => {
})
this.socket = await conn.connect<FrontcraftIfc>()
this.socket = await conn.connect()
}catch(e){
console.log(e);
this.logger.log(e);
throw new Error("Websocket cannot connect")
}
}
+1 -1
View File
@@ -6,4 +6,4 @@ export { AppServerModule } from './app/app.server.module';
import { IApiService } from './app/frontcraft/services/ApiService';
export { IApiService }
export { ServerApiService } from './app/frontcraft/services/server-login-api';
export { LoggerService } from './app/frontcraft/services/logger.service'
+7 -2
View File
@@ -10,18 +10,23 @@ import { FrontcraftAppModule } from './app/app.module';
import { environment } from './environments/environment';
import { IApiService } from "./app/frontcraft/services/ApiService"
import { ClientApiService } from './app/frontcraft/services/client-login-api';
import { LoggerService } from './app/frontcraft/services/logger.service';
if (environment.production) {
enableProdMode();
}
const serviceObj = new ClientApiService()
const loggerService = new LoggerService()
const serviceObj = new ClientApiService(loggerService)
serviceObj.initialize().then(_ => {
platformBrowserDynamic([
{
provide: IApiService,
deps: [],
useValue: serviceObj
},{
provide: LoggerService,
deps: [],
useValue: loggerService
}
]).bootstrapModule(FrontcraftAppModule)
.catch(err => console.error(err));
+1
View File
@@ -1,6 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"strict": false,
"outDir": "./out-tsc/app",
"paths": {
"@angular/*": [