Skip to content

Commit

Permalink
Merge pull request #5 from baloise-incubator/drag_sync_feature
Browse files Browse the repository at this point in the history
Drag sync feature
  • Loading branch information
l-brendle authored Oct 22, 2023
2 parents 9121ad1 + 9cb76a3 commit 4760160
Show file tree
Hide file tree
Showing 24 changed files with 286 additions and 73 deletions.
8 changes: 6 additions & 2 deletions angular-frontend/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<bal-app class="has-sticky-footer" style="position: relative;" (mousemove)="mouseMoved($event)">
<bal-app class="has-sticky-footer" style="position: relative;" (pointermove)="pointerMoved($event)">
<div>
<app-dragged-item *ngFor="let draggedItem of draggedItems" style="z-index: 1200; position: absolute;"
[itemDragInfo]="draggedItem" [ngStyle]="{'top': draggedItem.posY + 'px', 'left': draggedItem.posX + 'px'}"></app-dragged-item>
</div>
<div>
<bal-text class="has-text-shadow" *ngFor="let cursor of cursors" style="z-index: 1100; position: absolute;"
[ngStyle]="{'top': cursor.posY + 'px', 'left': cursor.posX + 25 + 'px'}"
Expand Down Expand Up @@ -31,7 +35,7 @@
<div class="column is-9">
<div class="inventories-container">
<app-inventory class="p-medium inventory-container" *ngFor="let inventory of inventories"
[inventory]="inventory" (itemCreated)="onItemCreated($event, inventory)"
[inventory]="inventory" [client]="client" (itemCreated)="onItemCreated($event, inventory)"
(hoverOverItem)="onHoverOverItem($event)" (exitItem)="onExitItem($event)"
(moveItem)="onItemMoved($event)"></app-inventory>
</div>
Expand Down
73 changes: 59 additions & 14 deletions angular-frontend/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import {Component, OnDestroy, HostListener} from '@angular/core';
import {Component, OnDestroy, HostListener, Injectable} from '@angular/core';
import { Client } from '@stomp/stompjs';
import {
Credentials,
Cursor,
User,
Inventory,
Character,
Item,
ItemBase,
ItemLockMessage,
ItemTransferMessage, UserColor
ItemTransferMessage,
UserColor,
ItemDragInfo
} from "../model";
import { HttpService } from 'src/http.service';
import {CreateItemEvent} from "../events";
import store from "../store";
import {HttpClient} from "@angular/common/http";

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
@Injectable()
export class AppComponent implements OnDestroy {

client: Client;
httpService: HttpService;
users: User[] = [];
cursors: Cursor[] = [];
inventories?: Inventory[];
draggedItems : ItemDragInfo[] = [];

get currentUser(): string {
return store.currentUser;
Expand All @@ -36,15 +40,32 @@ export class AppComponent implements OnDestroy {
store.currentUser = currentUser;
}

constructor() {
this.httpService = new HttpService();
constructor(private http: HttpClient) {
this.httpService = new HttpService(http);
this.client = new Client();
}

ngOnDestroy(): void {
this.closeWebSocketConnection();
}

onConnectToBackend(credentials: Credentials) {
this.httpService.getRegistrationURL(credentials)
.subscribe(isValid => {
if (isValid) {
console.log("registered user")
sessionStorage.setItem(
'token',
btoa(credentials.username + ':' + credentials.password))
this.openWebSocketConnection(credentials)
this.currentUser = credentials.username;
} else {
console.log("registering user failed")
alert("Authentication failed.")
}
})
}

openWebSocketConnection(credentials : Credentials) {
this.client.configure({
debug: (msg) => console.debug(msg),
Expand All @@ -57,8 +78,9 @@ export class AppComponent implements OnDestroy {
this.client.subscribe("/topic/cursor", (payload => this.updateCursors(JSON.parse(payload.body))));
this.client.subscribe("/app/inventory", (payload => this.updateInventory(JSON.parse(payload.body))));
this.client.subscribe("/topic/inventory", (payload => this.updateInventory(JSON.parse(payload.body))));
this.client.subscribe("/topic/itembases", (payload => this.updateItemBases(JSON.parse(payload.body))))
this.client.subscribe("/app/itembases", (payload => this.updateItemBases(JSON.parse(payload.body))))
this.client.subscribe("/topic/itembases", (payload => this.updateItemBases(JSON.parse(payload.body))));
this.client.subscribe("/app/itembases", (payload => this.updateItemBases(JSON.parse(payload.body))));
this.client.subscribe("/topic/itemdrag", (payload => this.updateDraggedItems(JSON.parse(payload.body))));
};

this.client.onWebSocketError = (error) => {
Expand All @@ -78,12 +100,7 @@ export class AppComponent implements OnDestroy {
}
}

onConnectToBackend(credentials: Credentials) {
this.openWebSocketConnection(credentials);
this.currentUser = credentials.username;
}

mouseMoved(event: MouseEvent) {
pointerMoved(event: PointerEvent) {
if(this.client.connected) {
const payload = {posX: event.pageX, posY: event.pageY};
this.client?.publish({destination: "/app/cursor", body: JSON.stringify(payload)});
Expand Down Expand Up @@ -115,7 +132,6 @@ export class AppComponent implements OnDestroy {
}

private updateInventory(inventories: Inventory[]) {
console.log("inventory update", inventories)
if (!this.inventories) {
this.inventories = inventories;
return;
Expand Down Expand Up @@ -199,4 +215,33 @@ export class AppComponent implements OnDestroy {
destination: "/app/itemtransfer", body: JSON.stringify(event)
});
}

private updateDraggedItems(itemDrag: ItemDragInfo) {
if (itemDrag.draggingPlayer != this.currentUser) {
console.log("Dragging received" + itemDrag.id)
const index = this.draggedItems.findIndex(item => item.id === itemDrag.id)
if (index >= 0) {
if (itemDrag.finished) {
this.draggedItems.splice(index, 1);
} else {
this.draggedItems[index] = itemDrag;
this.updateCursorOfDraggingUserIfNeeded(itemDrag);
}
} else {
if (!itemDrag.finished) {
this.draggedItems.push(itemDrag);
this.updateCursorOfDraggingUserIfNeeded(itemDrag);
}
}
}
}

private updateCursorOfDraggingUserIfNeeded(itemDragInfo : ItemDragInfo) {
let cursor = this.cursors.find(cursor => cursor.name === itemDragInfo.draggingPlayer);
if(cursor != undefined){
cursor.posY = itemDragInfo.posY;
cursor.posX = itemDragInfo.posX;
}
}

}
5 changes: 4 additions & 1 deletion angular-frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import { UserBarComponent } from './components/user-bar/user-bar.component';
import { GameComponent } from './components/game/game.component';
import { balIconAccount, balIconSend, balIconStarShape, balIconStarFull, balIconWeb, balIconX} from '@baloise/design-system-icons'
import { ItemBaseSelectionComponent } from './components/item-base-selection/item-base-selection.component'
import {HttpClientModule} from "@angular/common/http";
import {DraggedItemComponent} from "./components/dragged-item/dragged-item.component";

@NgModule({
declarations: [AppComponent, CheckInComponent, InventoryComponent, InventoryItemComponent, ChatComponent, GameComponent, StockComponent, UserBarComponent, ItemBaseSelectionComponent],
declarations: [AppComponent, CheckInComponent, InventoryComponent, InventoryItemComponent, ChatComponent, GameComponent, StockComponent, UserBarComponent, ItemBaseSelectionComponent, DraggedItemComponent],
imports: [
BrowserModule,
HttpClientModule,
// Provide all components and value accessors to the app module.
BaloiseDesignSystemModule.forRoot({
defaults: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<bal-card class="checkin-form-card">
<bal-card-content>
<form [formGroup]="form">
<bal-input [invalid]="form.controls.username.invalid && form.controls.username.touched" formControlName="username" placeholder="Please pick a username"></bal-input>
<bal-input class="mt-small" type="password" [invalid]="form.controls.passcode.invalid && form.controls.passcode.touched" formControlName="passcode" placeholder="Enter room passcode"></bal-input>
<bal-input [invalid]="form.controls.username.invalid && form.controls.username.touched" formControlName="username" placeholder="Please choose a username"></bal-input>
<bal-input class="mt-small" type="password" [invalid]="form.controls.password.invalid && form.controls.password.touched" formControlName="password" placeholder="Enter/choose your password"></bal-input>
<bal-button class="mt-medium" expanded="" (click)="onCheckIn()">Enter Board</bal-button>
</form>
</bal-card-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class CheckInComponent {

form = new FormGroup({
username: new FormControl("", BalValidators.isRequired()),
passcode: new FormControl("", BalValidators.isRequired())
password: new FormControl("", BalValidators.isRequired())
});

onCheckIn() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="dragged-item" [ngClass]="'ghost-item'">
<img [alt]="itemDragInfo" [src]="'assets/items/' + itemDragInfo.name + '.png'"/>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.ghost-item {
width:50px;
height:50px;
border-radius:9px;
margin:3px;
border-width:2px;
border-style: dashed;
border-color: gray;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {Component, Input} from '@angular/core';
import {ItemDragInfo} from "../../../model";

@Component({
selector: 'app-dragged-item',
templateUrl: './dragged-item.component.html',
styleUrls: ['./dragged-item.component.scss']
})
export class DraggedItemComponent {
@Input()
itemDragInfo!: ItemDragInfo
}
2 changes: 2 additions & 0 deletions angular-frontend/src/app/components/game/game.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class GameComponent implements OnInit, OnDestroy {
|| keyCode === "ArrowRight"
|| keyCode === "ArrowDown"
|| keyCode === "ArrowUp") {
event.preventDefault();
const payload = {keyCode : keyCode, pressed : false}
this.client?.publish({destination: "/app/game/character_control", body: JSON.stringify(payload)})
}
Expand All @@ -74,6 +75,7 @@ export class GameComponent implements OnInit, OnDestroy {
|| keyCode === "ArrowRight"
|| keyCode === "ArrowDown"
|| keyCode === "ArrowUp") {
event.preventDefault();
const payload = {keyCode : keyCode, pressed : true}
this.client?.publish({destination: "/app/game/character_control", body: JSON.stringify(payload)})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="inventory-item" [ngClass]="item.userLock ? store.getColorForUserName(item.userLock): ''"
[draggable]="item.userLock === currentUser" (dragstart)="onDragStart($event)">
[draggable]="item.userLock === currentUser" (dragstart)="onDragStart($event)" (drag)="onDragging($event)" (dragend)="onDragEnd($event)">
<img [alt]="item" [src]="'assets/items/' + item.name + '.png'"/>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Component, Input, OnInit} from '@angular/core';
import {Item} from "../../../model";
import {Item, ItemDragInfo} from "../../../model";
import store from "../../../store";
import {Client} from "@stomp/stompjs/esm6";

@Component({
selector: 'app-inventory-item',
Expand All @@ -10,6 +11,9 @@ import store from "../../../store";
export class InventoryItemComponent implements OnInit {
@Input()
item!: Item

@Input() client!: Client;

get currentUser(): string {
return store.currentUser;
}
Expand All @@ -25,6 +29,32 @@ export class InventoryItemComponent implements OnInit {
event.dataTransfer?.setData("application/json", JSON.stringify(this.item))
}

onDragging(event : DragEvent) {
this.sendDragInfo(event, false)
}

onDragEnd(event : DragEvent) {
this.sendDragInfo(event, true)
}

sendDragInfo(event : DragEvent, finished : boolean) {
if (this.item.userLock !== this.currentUser) {
console.warn("Nein -doch - oohhhhhh")
} else {
const itemDragInfo : ItemDragInfo = {
name : this.item.name,
posX: event.pageX,
posY : event.pageY,
id:this.item.id,
draggingPlayer: this.item.userLock,
finished: finished
}
this.client?.publish({destination: "/app/item-dragging", body: JSON.stringify(itemDragInfo)
});
}
}


ngOnInit(): void {
console.log("hey?")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</bal-card-title>
<bal-card-content>
<div class="inventory-grid" (dragenter)="onDragEnter()">
<app-inventory-item [item]="item" (mouseenter)="onHoverOverItem(item)" (mouseleave)="onExitItem(item)" *ngFor="let item of inventory.items"></app-inventory-item>
<app-inventory-item [item]="item" [client]="client" (mouseenter)="onHoverOverItem(item)" (mouseleave)="onExitItem(item)" *ngFor="let item of inventory.items"></app-inventory-item>
<div class="inventory-add-button">
<bal-button square="" inverted="" icon="plus" (click)="onCreateNew()"></bal-button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Inventory, Item, ItemBase, ItemTransferMessage} from "../../../model";
import {CreateItemEvent} from "../../../events";
import {BalModalService} from "@baloise/design-system-components-angular";
import {ItemBaseSelectionComponent} from "../item-base-selection/item-base-selection.component";
import {Client} from "@stomp/stompjs";

@Component({
selector: 'app-inventory',
Expand All @@ -14,6 +15,9 @@ export class InventoryComponent implements OnInit {
@Input()
inventory!: Inventory

@Input()
client!: Client

@Output()
itemCreated = new EventEmitter<CreateItemEvent>

Expand Down
13 changes: 11 additions & 2 deletions angular-frontend/src/http.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { Credentials } from "./model";
import { environment } from "./environments/environment";
import {HttpClient} from "@angular/common/http";
import {catchError, Observable} from "rxjs";
import {Injectable} from "@angular/core";

@Injectable()
export class HttpService {
host: String;
protocol: String;

constructor() {
constructor(private http: HttpClient) {
this.host = environment.backend.host;
this.protocol = environment.backend.protocol;
}

getWebSocket(credentials: Credentials): WebSocket {
console.log("Create web socket to: '" + this.host + "'");
return new WebSocket(`${this.protocol}://${credentials.username}:${credentials.passcode}@${this.host}/api/connect`);
return new WebSocket(`${this.protocol}://${credentials.username}:${credentials.password}@${this.host}/api/connect`);
}

getRegistrationURL(credentials : Credentials) : Observable<boolean> {
return this.http.post<boolean>(`http://${this.host}/api/user/registration`, credentials)
}

}
11 changes: 10 additions & 1 deletion angular-frontend/src/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface Button {

export interface Credentials {
username: string
passcode: string
password: string
}

export interface User {
Expand Down Expand Up @@ -80,4 +80,13 @@ export interface ItemTransferMessage {
export interface UserColor {
name: string;
color: string;
}

export interface ItemDragInfo {
name: string;
id : number;
posX: number;
posY: number;
finished : boolean;
draggingPlayer : string;
}
Loading

0 comments on commit 4760160

Please sign in to comment.