NumbersController.reveal
This commit is contained in:
parent
985924086e
commit
81bf02be9b
@ -6,8 +6,8 @@ export class GroupUuid {
|
||||
// -
|
||||
}
|
||||
|
||||
is(other: GroupUuid | null) {
|
||||
return other !== null && this.uuid === other.uuid;
|
||||
is(other: GroupUuid | null | undefined) {
|
||||
return other !== null && other !== undefined && this.uuid === other.uuid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -59,7 +59,10 @@ export class GroupService {
|
||||
|
||||
join(groupUuid: string, password: string, next: Next<Group>): void {
|
||||
const data = new GroupJoinRequest(groupUuid, password);
|
||||
this.api.postSingle(['Group', 'join'], data, Group.fromJson, next);
|
||||
this.api.postSingle(['Group', 'join'], data, Group.fromJson, group => {
|
||||
this.userService.fetchUser(); // to update userService with possible freshly created user
|
||||
next(group);
|
||||
});
|
||||
}
|
||||
|
||||
leave(group: Group, next: Next<void>): void {
|
||||
|
||||
@ -2,6 +2,7 @@ import {Group} from "../../group/Group";
|
||||
import {validateDate, validateList, validateString} from "../../common/validators";
|
||||
import {NumbersLot} from "./NumbersLot";
|
||||
import {UserPrivate} from "../../User/UserPrivate";
|
||||
import {UserPublic} from "../../User/UserPublic";
|
||||
|
||||
export class Numbers {
|
||||
|
||||
@ -24,11 +25,38 @@ export class Numbers {
|
||||
}
|
||||
|
||||
getMine(user: UserPrivate | null): NumbersLot | null {
|
||||
return this.lots.filter(u => u.user.is(user))[0];
|
||||
return this.lots.filter(lot => lot.is(user))[0];
|
||||
}
|
||||
|
||||
sameGroup(numbers: Numbers): boolean {
|
||||
return this.group.equals(numbers.group);
|
||||
}
|
||||
|
||||
getLotsByUserName(): NumbersLot[] {
|
||||
return this.lots.sort((a, b) => UserPublic.compareName(a.user, b.user));
|
||||
}
|
||||
|
||||
canIReveal(user: UserPrivate | null): boolean {
|
||||
const mine = this.getMine(user);
|
||||
if (mine === null) {
|
||||
return false;
|
||||
}
|
||||
return !mine.revealed;
|
||||
}
|
||||
|
||||
is(numbers: Numbers | null): boolean {
|
||||
return this.uuid === numbers?.uuid;
|
||||
}
|
||||
|
||||
isNewerThan(numbers: Numbers | null): boolean {
|
||||
if (numbers === null) {
|
||||
return false;
|
||||
}
|
||||
return numbers.date.getTime() < this.date.getTime();
|
||||
}
|
||||
|
||||
allRevealed(): boolean {
|
||||
return this.lots.every(lot => lot.revealed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import {UserPublic} from "../../User/UserPublic";
|
||||
import {validateNumberOrNull} from "../../common/validators";
|
||||
import {validateBoolean, validateNumberOrNull} from "../../common/validators";
|
||||
import {UserPrivate} from "../../User/UserPrivate";
|
||||
|
||||
export class NumbersLot {
|
||||
|
||||
constructor(
|
||||
readonly user: UserPublic,
|
||||
readonly number: number | null,
|
||||
readonly revealed: boolean,
|
||||
) {
|
||||
// -
|
||||
}
|
||||
@ -14,7 +16,12 @@ export class NumbersLot {
|
||||
return new NumbersLot(
|
||||
UserPublic.fromJson(json['user']),
|
||||
validateNumberOrNull(json['number']),
|
||||
validateBoolean(json['revealed']),
|
||||
);
|
||||
}
|
||||
|
||||
is(user: UserPrivate | null) {
|
||||
return this.user.is(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -44,4 +44,8 @@ export class NumbersService {
|
||||
this.router.navigate(['Numbers', numbers.uuid]);
|
||||
}
|
||||
|
||||
reveal(numbersUuid: string) {
|
||||
this.api.postNone(['Numbers', 'reveal'], numbersUuid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,22 +1,36 @@
|
||||
<div
|
||||
*ngIf="numbers"
|
||||
[class.date_fresh]="now.getTime() - numbers.date.getTime() < 60 * 1000"
|
||||
[class.date_middle]="now.getTime() - numbers.date.getTime() >= 60 * 1000"
|
||||
[class.date_old]="now.getTime() - numbers.date.getTime() >= 5 * 60 * 1000"
|
||||
>
|
||||
<ng-container *ngIf="numbers">
|
||||
|
||||
<div class="date">
|
||||
{{ numbers.date | relative:now }}
|
||||
<div class="tileContainer">
|
||||
<div class="tile">
|
||||
<div class="tileInner">
|
||||
<div class="tileTitle">
|
||||
Aktuelle Runde
|
||||
</div>
|
||||
|
||||
<div class="huge" (click)="gotoGroup()">
|
||||
{{ numbers.getMine(userService.user)?.number || '-' }}
|
||||
<div class="tileContent">
|
||||
<table>
|
||||
<tr *ngFor="let lot of numbers.getLotsByUserName()">
|
||||
<td>
|
||||
{{ lot.user.name }}
|
||||
</td>
|
||||
<td class="buttons">
|
||||
<div class="button buttonRight buttonNext" *ngIf="lot.is(userService.user) && numbers.canIReveal(userService.user)" (click)="numbersService.reveal(numbers.uuid)">
|
||||
Offen legen
|
||||
</div>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
{{ lot.number }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<div class="buttons">
|
||||
<div class="button buttonRight buttonNext" *ngIf="userService.iOwn(numbers.group)" (click)="numbersService.create(numbers.group.uuid)">
|
||||
<div class="button buttonRight buttonNext" *ngIf="userService.iOwn(numbers.group) && numbers.allRevealed()" (click)="numbersService.create(numbers.group.uuid)">
|
||||
Nächste Runde
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@ -2,13 +2,14 @@ import {Component, HostListener, OnDestroy, OnInit} from '@angular/core';
|
||||
import {Numbers} from "../../../api/tools/Numbers/Numbers";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {NumbersService} from "../../../api/tools/Numbers/numbers.service";
|
||||
import {NgIf} from "@angular/common";
|
||||
import {NgForOf, NgIf} from "@angular/common";
|
||||
import {FormsModule} from "@angular/forms";
|
||||
import {PasswordTileComponent} from "../../../shared/password-tile/password-tile.component";
|
||||
import {GroupService} from "../../../api/group/group.service";
|
||||
import {UserService} from "../../../api/User/user.service";
|
||||
import {RelativePipe} from "../../../shared/relative.pipe";
|
||||
import {Subscription, timer} from "rxjs";
|
||||
import {Group} from "../../../api/group/Group";
|
||||
|
||||
@Component({
|
||||
selector: 'app-numbers',
|
||||
@ -17,7 +18,8 @@ import {Subscription, timer} from "rxjs";
|
||||
NgIf,
|
||||
FormsModule,
|
||||
PasswordTileComponent,
|
||||
RelativePipe
|
||||
RelativePipe,
|
||||
NgForOf
|
||||
],
|
||||
templateUrl: './numbers.component.html',
|
||||
styleUrl: './numbers.component.less'
|
||||
@ -30,6 +32,8 @@ export class NumbersComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected now: Date = new Date();
|
||||
|
||||
private uuid: string | null = null;
|
||||
|
||||
constructor(
|
||||
protected readonly activatedRoute: ActivatedRoute,
|
||||
protected readonly numbersService: NumbersService,
|
||||
@ -43,10 +47,11 @@ export class NumbersComponent implements OnInit, OnDestroy {
|
||||
this.subs.push(timer(1000, 1000).subscribe(() => this.now = new Date()));
|
||||
this.subs.push(this.activatedRoute.params.subscribe(params => {
|
||||
const uuid = params['uuid'];
|
||||
this.uuid = uuid;
|
||||
if (uuid) {
|
||||
this.numbersService.canAccess(uuid, granted => {
|
||||
if (granted) {
|
||||
this.numbersService.byUuid(uuid, numbers => this.numbers = numbers);
|
||||
this.fetchNumbers();
|
||||
} else {
|
||||
this.numbersService.getGroupUuid(uuid, groupUuid => this.groupService.goto(groupUuid));
|
||||
}
|
||||
@ -56,10 +61,23 @@ export class NumbersComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}));
|
||||
this.userService.subscribePush(Numbers, numbers => {
|
||||
if (this.numbers?.sameGroup(numbers)) {
|
||||
if (numbers.is(this.numbers)) {
|
||||
this.numbers = numbers;
|
||||
} else if (numbers.isNewerThan(this.numbers)) {
|
||||
this.numbersService.goto(numbers);
|
||||
}
|
||||
});
|
||||
this.userService.subscribePush(Group, group => {
|
||||
if (group.is(this.numbers?.group)) {
|
||||
this.fetchNumbers();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private fetchNumbers() {
|
||||
if (this.uuid) {
|
||||
this.numbersService.byUuid(this.uuid, numbers => this.numbers = numbers);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package de.ph87.tools.group.uuid;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import de.ph87.tools.common.uuid.AbstractUuid;
|
||||
import de.ph87.tools.common.uuid.UuidSerializer;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@JsonSerialize(using = UuidSerializer.class)
|
||||
public class GroupUuid extends AbstractUuid {
|
||||
|
||||
public GroupUuid(@NonNull final String uuid) {
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
package de.ph87.tools.tools.numbers;
|
||||
|
||||
import de.ph87.tools.tools.numbers.lot.NumberLot;
|
||||
import de.ph87.tools.user.User;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class NumbersAccess {
|
||||
@ -20,4 +23,9 @@ public class NumbersAccess {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Optional<NumberLot> findPrincipalLot() {
|
||||
return numbers.getLots().stream().filter(lot -> lot.getUser().equals(principal)).findFirst();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package de.ph87.tools.tools.numbers;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import de.ph87.tools.common.uuid.UuidSerializer;
|
||||
import de.ph87.tools.group.uuid.GroupUuid;
|
||||
import de.ph87.tools.tools.numbers.uuid.NumbersUuid;
|
||||
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -30,20 +33,27 @@ public class NumbersController {
|
||||
}
|
||||
|
||||
@PostMapping("canAccess")
|
||||
public boolean canAccess(@NonNull final UserPrivateUuid privateUuid, final NumbersUuid numbersUuid) {
|
||||
public boolean canAccess(@Nullable final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
return numbersService.canAccess(privateUuid, numbersUuid);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@PostMapping("getGroupUuid")
|
||||
@JsonSerialize(using = UuidSerializer.class)
|
||||
public GroupUuid getGroupUuid(final NumbersUuid numbersUuid) {
|
||||
return numbersService.getGroupUuid(numbersUuid);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@PostMapping("byUuid")
|
||||
public NumbersDto byUuid(@NonNull final UserPrivateUuid privateUuid, final NumbersUuid numbersUuid) {
|
||||
public NumbersDto byUuid(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
return numbersService.byUuid(privateUuid, numbersUuid);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@PostMapping("reveal")
|
||||
public NumbersDto reveal(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
return numbersService.reveal(privateUuid, numbersUuid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,11 +5,13 @@ import de.ph87.tools.group.access.GroupAccess;
|
||||
import de.ph87.tools.group.access.GroupAccessService;
|
||||
import de.ph87.tools.group.dto.GroupDto;
|
||||
import de.ph87.tools.group.uuid.GroupUuid;
|
||||
import de.ph87.tools.tools.numbers.lot.NumberLot;
|
||||
import de.ph87.tools.tools.numbers.uuid.NumbersUuid;
|
||||
import de.ph87.tools.user.User;
|
||||
import de.ph87.tools.user.UserAccessService;
|
||||
import de.ph87.tools.user.push.UserPushService;
|
||||
import de.ph87.tools.user.uuid.UserPrivateUuid;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -22,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -42,17 +45,20 @@ public class NumbersService {
|
||||
public void create(@NonNull final UserPrivateUuid userPrivateUuid, @NonNull final GroupUuid groupUuid) {
|
||||
final GroupAccess access = groupAccessService.ownerAccess(userPrivateUuid, groupUuid);
|
||||
final Numbers numbers = numbersRepository.save(new Numbers(access.group));
|
||||
pushAllLots(numbers);
|
||||
push(numbers);
|
||||
}
|
||||
|
||||
public boolean canAccess(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
public boolean canAccess(@Nullable final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
if (privateUuid == null) {
|
||||
return false;
|
||||
}
|
||||
final NumbersAccess access = access(privateUuid, numbersUuid);
|
||||
return access.numbers.getGroup().getUsers().contains(access.principal);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public GroupUuid getGroupUuid(@NonNull final NumbersUuid numbersUuid) {
|
||||
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
|
||||
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(newBadRequest());
|
||||
return numbers.getGroup().getUuid();
|
||||
}
|
||||
|
||||
@ -62,6 +68,15 @@ public class NumbersService {
|
||||
return toDto(lotAccess);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public NumbersDto reveal(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
final NumbersAccess lotAccess = access(privateUuid, numbersUuid);
|
||||
final NumberLot lot = lotAccess.findPrincipalLot().orElseThrow(newBadRequest());
|
||||
lot.reveal();
|
||||
push(lotAccess.numbers);
|
||||
return toDto(lotAccess);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Page<NumbersDto> page(@NonNull final UserPrivateUuid privateUuid, @NonNull final GroupUuid groupUuid, final int page, final int pageSize) {
|
||||
final GroupAccess groupAccess = groupAccessService.access(privateUuid, groupUuid);
|
||||
@ -74,7 +89,7 @@ public class NumbersService {
|
||||
@NonNull
|
||||
private NumbersAccess access(@NonNull final UserPrivateUuid privateUuid, @NonNull final NumbersUuid numbersUuid) {
|
||||
final User principal = userAccessService.access(privateUuid);
|
||||
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
|
||||
final Numbers numbers = numbersRepository.findById(numbersUuid.uuid).orElseThrow(newBadRequest());
|
||||
if (!numbers.getGroup().getUsers().contains(principal)) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
@ -83,7 +98,7 @@ public class NumbersService {
|
||||
|
||||
/* PUSH, DTO ------------------------------------------------------------------------------------ */
|
||||
|
||||
private void pushAllLots(@NonNull final Numbers numbers) {
|
||||
private void push(@NonNull final Numbers numbers) {
|
||||
numbers.getLots()
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
@ -97,4 +112,10 @@ public class NumbersService {
|
||||
return new NumbersDto(lotAccess, group);
|
||||
}
|
||||
|
||||
/* BAD REQUEST ---------------------------------------------------------------------------------- */
|
||||
|
||||
private static @NonNull Supplier<ResponseStatusException> newBadRequest() {
|
||||
return () -> new ResponseStatusException(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,4 +34,8 @@ public class NumberLot {
|
||||
return this.user.equals(user);
|
||||
}
|
||||
|
||||
public void reveal() {
|
||||
this.revealed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -14,11 +14,14 @@ public class NumberLotDto {
|
||||
@NonNull
|
||||
private final UserPublicDto user;
|
||||
|
||||
private final boolean revealed;
|
||||
|
||||
@Nullable
|
||||
private final Integer number;
|
||||
|
||||
public NumberLotDto(@NonNull final NumberLot lot, @NonNull final User principal) {
|
||||
this.user = new UserPublicDto(lot.getUser());
|
||||
this.revealed = lot.isRevealed();
|
||||
this.number = lot.isRevealed() || lot.getUser().equals(principal) ? lot.getNumber() : null;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user