Added report and voting entities, and api status controller.
This commit is contained in:
parent
080c44c467
commit
aa843227d2
|
@ -0,0 +1,15 @@
|
|||
package nl.andrewlalis.gymboard_api;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class StatusController {
|
||||
@GetMapping(path = "/status")
|
||||
public ResponseEntity<?> getServiceStatus() {
|
||||
return ResponseEntity.ok(Map.of("online", true));
|
||||
}
|
||||
}
|
|
@ -47,7 +47,10 @@ public class SecurityConfig {
|
|||
"/leaderboards",
|
||||
"/gyms/**",
|
||||
"/submissions/**",
|
||||
"/auth/reset-password"
|
||||
"/auth/reset-password",
|
||||
"/auth/users/*",
|
||||
"/auth/users/*/followers",
|
||||
"/auth/users/*/following"
|
||||
).permitAll()
|
||||
.requestMatchers(// Allow the following POST endpoints to be public.
|
||||
HttpMethod.POST,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.controller;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.CompoundGymId;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionPayload;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionPayload;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.GymResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.GymService;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.submission.ExerciseSubmissionService;
|
||||
|
@ -32,15 +32,15 @@ public class GymController {
|
|||
}
|
||||
|
||||
@GetMapping(path = "/recent-submissions")
|
||||
public List<ExerciseSubmissionResponse> getRecentSubmissions(@PathVariable String compoundId) {
|
||||
public List<SubmissionResponse> getRecentSubmissions(@PathVariable String compoundId) {
|
||||
return gymService.getRecentSubmissions(CompoundGymId.parse(compoundId));
|
||||
}
|
||||
|
||||
@PostMapping(path = "/submissions")
|
||||
public ExerciseSubmissionResponse createSubmission(
|
||||
public SubmissionResponse createSubmission(
|
||||
@PathVariable String compoundId,
|
||||
@AuthenticationPrincipal User user,
|
||||
@RequestBody ExerciseSubmissionPayload payload
|
||||
@RequestBody SubmissionPayload payload
|
||||
) {
|
||||
return submissionService.createSubmission(CompoundGymId.parse(compoundId), user.getId(), payload);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.controller;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.LeaderboardService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -21,7 +21,7 @@ public class LeaderboardController {
|
|||
}
|
||||
|
||||
@GetMapping
|
||||
public Page<ExerciseSubmissionResponse> getLeaderboard(
|
||||
public Page<SubmissionResponse> getLeaderboard(
|
||||
@RequestParam(name = "exercise") Optional<String> exerciseShortName,
|
||||
@RequestParam(name = "gyms") Optional<String> gymCompoundIdsString,
|
||||
@RequestParam(name = "t") Optional<String> timeframe,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.controller;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.submission.ExerciseSubmissionService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
@ -17,7 +17,7 @@ public class SubmissionController {
|
|||
}
|
||||
|
||||
@GetMapping(path = "/{submissionId}")
|
||||
public ExerciseSubmissionResponse getSubmission(@PathVariable String submissionId) {
|
||||
public SubmissionResponse getSubmission(@PathVariable String submissionId) {
|
||||
return submissionService.getSubmission(submissionId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dao.exercise;
|
||||
package nl.andrewlalis.gymboard_api.domains.api.dao;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dao.exercise;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.ExerciseSubmission;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ExerciseSubmissionRepository extends JpaRepository<ExerciseSubmission, String>, JpaSpecificationExecutor<ExerciseSubmission> {
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dao.submission;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.submission.Submission;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SubmissionRepository extends JpaRepository<Submission, String>, JpaSpecificationExecutor<Submission> {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dto;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
|
||||
public record ExerciseResponse(
|
||||
String shortName,
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dto;
|
||||
|
||||
public record ExerciseSubmissionPayload(
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record SubmissionPayload(
|
||||
String exerciseShortName,
|
||||
LocalDateTime performedAt,
|
||||
float weight,
|
||||
String weightUnit,
|
||||
int reps,
|
|
@ -1,10 +1,10 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.dto;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.ExerciseSubmission;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.submission.Submission;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.dto.UserResponse;
|
||||
import nl.andrewlalis.gymboard_api.util.StandardDateFormatter;
|
||||
|
||||
public record ExerciseSubmissionResponse(
|
||||
public record SubmissionResponse(
|
||||
String id,
|
||||
String createdAt,
|
||||
GymSimpleResponse gym,
|
||||
|
@ -17,7 +17,7 @@ public record ExerciseSubmissionResponse(
|
|||
double metricWeight,
|
||||
int reps
|
||||
) {
|
||||
public ExerciseSubmissionResponse(ExerciseSubmission submission) {
|
||||
public SubmissionResponse(Submission submission) {
|
||||
this(
|
||||
submission.getId(),
|
||||
StandardDateFormatter.format(submission.getCreatedAt()),
|
|
@ -1,4 +1,4 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.model.exercise;
|
||||
package nl.andrewlalis.gymboard_api.domains.api.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
|
@ -1,18 +1,18 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.model.exercise;
|
||||
package nl.andrewlalis.gymboard_api.domains.api.model.submission;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Gym;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "exercise_submission")
|
||||
public class ExerciseSubmission {
|
||||
@Table(name = "submission")
|
||||
public class Submission {
|
||||
@Id
|
||||
@Column(nullable = false, updatable = false, length = 26)
|
||||
private String id;
|
||||
|
@ -53,9 +53,9 @@ public class ExerciseSubmission {
|
|||
@Column(nullable = false)
|
||||
private int reps;
|
||||
|
||||
public ExerciseSubmission() {}
|
||||
public Submission() {}
|
||||
|
||||
public ExerciseSubmission(String id, Gym gym, Exercise exercise, User user, LocalDateTime performedAt, String videoFileId, BigDecimal rawWeight, WeightUnit unit, BigDecimal metricWeight, int reps) {
|
||||
public Submission(String id, Gym gym, Exercise exercise, User user, LocalDateTime performedAt, String videoFileId, BigDecimal rawWeight, WeightUnit unit, BigDecimal metricWeight, int reps) {
|
||||
this.id = id;
|
||||
this.gym = gym;
|
||||
this.exercise = exercise;
|
|
@ -0,0 +1,63 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.model.submission;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "submission_report")
|
||||
public class SubmissionReport {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
private Submission submission;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private User user;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String reason;
|
||||
|
||||
@Column(length = 1024)
|
||||
private String description;
|
||||
|
||||
public SubmissionReport() {}
|
||||
|
||||
public SubmissionReport(Submission submission, User user, String reason, String description) {
|
||||
this.submission = submission;
|
||||
this.user = user;
|
||||
this.reason = reason;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public Submission getSubmission() {
|
||||
return submission;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.model.submission;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||
|
||||
@Entity
|
||||
@Table(
|
||||
name = "submission_vote",
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"submission_id", "user_id"})
|
||||
)
|
||||
public class SubmissionVote {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
private Submission submission;
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
private User user;
|
||||
|
||||
public SubmissionVote() {}
|
||||
|
||||
public SubmissionVote(Submission submission, User user) {
|
||||
this.submission = submission;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Submission getSubmission() {
|
||||
return submission;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.service;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.ExerciseRepository;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.service;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.CompoundGymId;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.GymResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.GymRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseSubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.submission.SubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Gym;
|
||||
import nl.andrewlalis.gymboard_api.util.PredicateBuilder;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -22,9 +22,9 @@ public class GymService {
|
|||
private static final Logger log = LoggerFactory.getLogger(GymService.class);
|
||||
|
||||
private final GymRepository gymRepository;
|
||||
private final ExerciseSubmissionRepository submissionRepository;
|
||||
private final SubmissionRepository submissionRepository;
|
||||
|
||||
public GymService(GymRepository gymRepository, ExerciseSubmissionRepository submissionRepository) {
|
||||
public GymService(GymRepository gymRepository, SubmissionRepository submissionRepository) {
|
||||
this.gymRepository = gymRepository;
|
||||
this.submissionRepository = submissionRepository;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public class GymService {
|
|||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<ExerciseSubmissionResponse> getRecentSubmissions(CompoundGymId id) {
|
||||
public List<SubmissionResponse> getRecentSubmissions(CompoundGymId id) {
|
||||
Gym gym = gymRepository.findByCompoundId(id)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||
return submissionRepository.findAll((root, query, criteriaBuilder) -> {
|
||||
|
@ -49,7 +49,7 @@ public class GymService {
|
|||
.with(criteriaBuilder.equal(root.get("gym"), gym))
|
||||
.build();
|
||||
}, PageRequest.of(0, 10))
|
||||
.map(ExerciseSubmissionResponse::new)
|
||||
.map(SubmissionResponse::new)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.service;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.CompoundGymId;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.GymRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseSubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.submission.SubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Gym;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.LeaderboardTimeframe;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.util.PredicateBuilder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -27,18 +27,18 @@ import java.util.Optional;
|
|||
*/
|
||||
@Service
|
||||
public class LeaderboardService {
|
||||
private final ExerciseSubmissionRepository submissionRepository;
|
||||
private final SubmissionRepository submissionRepository;
|
||||
private final ExerciseRepository exerciseRepository;
|
||||
private final GymRepository gymRepository;
|
||||
|
||||
public LeaderboardService(ExerciseSubmissionRepository submissionRepository, ExerciseRepository exerciseRepository, GymRepository gymRepository) {
|
||||
public LeaderboardService(SubmissionRepository submissionRepository, ExerciseRepository exerciseRepository, GymRepository gymRepository) {
|
||||
this.submissionRepository = submissionRepository;
|
||||
this.exerciseRepository = exerciseRepository;
|
||||
this.gymRepository = gymRepository;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<ExerciseSubmissionResponse> getTopSubmissions(
|
||||
public Page<SubmissionResponse> getTopSubmissions(
|
||||
Optional<String> exerciseShortName,
|
||||
Optional<String> gymCompoundIdsString,
|
||||
Optional<String> optionalTimeframe,
|
||||
|
@ -68,7 +68,7 @@ public class LeaderboardService {
|
|||
}
|
||||
|
||||
return pb.build();
|
||||
}, pageable).map(ExerciseSubmissionResponse::new);
|
||||
}, pageable).map(SubmissionResponse::new);
|
||||
}
|
||||
|
||||
private List<Gym> parseGymCompoundIdsString(String s) {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.api.service.submission;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.GymRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseSubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.submission.SubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.CompoundGymId;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionPayload;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.ExerciseSubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionPayload;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dto.SubmissionResponse;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Gym;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.ExerciseSubmission;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.submission.Submission;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.dao.UserRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.model.User;
|
||||
import nl.andrewlalis.gymboard_api.util.ULID;
|
||||
|
@ -21,7 +21,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
|
@ -35,25 +34,25 @@ public class ExerciseSubmissionService {
|
|||
private final GymRepository gymRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final ExerciseRepository exerciseRepository;
|
||||
private final ExerciseSubmissionRepository exerciseSubmissionRepository;
|
||||
private final SubmissionRepository submissionRepository;
|
||||
private final ULID ulid;
|
||||
|
||||
public ExerciseSubmissionService(GymRepository gymRepository,
|
||||
UserRepository userRepository, ExerciseRepository exerciseRepository,
|
||||
ExerciseSubmissionRepository exerciseSubmissionRepository,
|
||||
SubmissionRepository submissionRepository,
|
||||
ULID ulid) {
|
||||
this.gymRepository = gymRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.exerciseRepository = exerciseRepository;
|
||||
this.exerciseSubmissionRepository = exerciseSubmissionRepository;
|
||||
this.submissionRepository = submissionRepository;
|
||||
this.ulid = ulid;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ExerciseSubmissionResponse getSubmission(String submissionId) {
|
||||
ExerciseSubmission submission = exerciseSubmissionRepository.findById(submissionId)
|
||||
public SubmissionResponse getSubmission(String submissionId) {
|
||||
Submission submission = submissionRepository.findById(submissionId)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||
return new ExerciseSubmissionResponse(submission);
|
||||
return new SubmissionResponse(submission);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,7 +63,7 @@ public class ExerciseSubmissionService {
|
|||
* @return The saved submission.
|
||||
*/
|
||||
@Transactional
|
||||
public ExerciseSubmissionResponse createSubmission(CompoundGymId id, String userId, ExerciseSubmissionPayload payload) {
|
||||
public SubmissionResponse createSubmission(CompoundGymId id, String userId, SubmissionPayload payload) {
|
||||
User user = userRepository.findById(userId)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.FORBIDDEN));
|
||||
Gym gym = gymRepository.findByCompoundId(id)
|
||||
|
@ -81,7 +80,7 @@ public class ExerciseSubmissionService {
|
|||
if (weightUnit == WeightUnit.POUNDS) {
|
||||
metricWeight = WeightUnit.toKilograms(rawWeight);
|
||||
}
|
||||
ExerciseSubmission submission = exerciseSubmissionRepository.saveAndFlush(new ExerciseSubmission(
|
||||
Submission submission = submissionRepository.saveAndFlush(new Submission(
|
||||
ulid.nextULID(),
|
||||
gym,
|
||||
exercise,
|
||||
|
@ -93,6 +92,6 @@ public class ExerciseSubmissionService {
|
|||
metricWeight,
|
||||
payload.reps()
|
||||
));
|
||||
return new ExerciseSubmissionResponse(submission);
|
||||
return new SubmissionResponse(submission);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package nl.andrewlalis.gymboard_api.domains.auth.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "auth_user_report")
|
||||
public class UserReport {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@CreationTimestamp
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@ManyToOne(optional = false, fetch = FetchType.LAZY)
|
||||
private User user;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private User reportedBy;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String reason;
|
||||
|
||||
@Column(length = 1024)
|
||||
private String description;
|
||||
|
||||
public UserReport(User user, User reportedBy, String reason, String description) {
|
||||
this.user = user;
|
||||
this.reportedBy = reportedBy;
|
||||
this.reason = reason;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public User getReportedBy() {
|
||||
return reportedBy;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package nl.andrewlalis.gymboard_api.util.sample_data;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.util.CsvUtil;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package nl.andrewlalis.gymboard_api.util.sample_data;
|
||||
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.GymRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.exercise.ExerciseSubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.ExerciseRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.dao.submission.SubmissionRepository;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Gym;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.WeightUnit;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.exercise.ExerciseSubmission;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.Exercise;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.model.submission.Submission;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.cdn_client.CdnClient;
|
||||
import nl.andrewlalis.gymboard_api.domains.api.service.submission.ExerciseSubmissionService;
|
||||
import nl.andrewlalis.gymboard_api.domains.auth.dao.UserRepository;
|
||||
|
@ -29,13 +29,13 @@ public class SampleSubmissionGenerator implements SampleDataGenerator {
|
|||
private final UserRepository userRepository;
|
||||
private final ExerciseRepository exerciseRepository;
|
||||
private final ExerciseSubmissionService submissionService;
|
||||
private final ExerciseSubmissionRepository submissionRepository;
|
||||
private final SubmissionRepository submissionRepository;
|
||||
private final ULID ulid;
|
||||
|
||||
@Value("${app.cdn-origin}")
|
||||
private String cdnOrigin;
|
||||
|
||||
public SampleSubmissionGenerator(GymRepository gymRepository, UserRepository userRepository, ExerciseRepository exerciseRepository, ExerciseSubmissionService submissionService, ExerciseSubmissionRepository submissionRepository, ULID ulid) {
|
||||
public SampleSubmissionGenerator(GymRepository gymRepository, UserRepository userRepository, ExerciseRepository exerciseRepository, ExerciseSubmissionService submissionService, SubmissionRepository submissionRepository, ULID ulid) {
|
||||
this.gymRepository = gymRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.exerciseRepository = exerciseRepository;
|
||||
|
@ -94,7 +94,7 @@ public class SampleSubmissionGenerator implements SampleDataGenerator {
|
|||
rawWeight = metricWeight.multiply(new BigDecimal("2.2046226218"));
|
||||
}
|
||||
|
||||
submissionRepository.save(new ExerciseSubmission(
|
||||
submissionRepository.save(new Submission(
|
||||
ulid.nextULID(),
|
||||
randomChoice(gyms, random),
|
||||
randomChoice(exercises, random),
|
||||
|
|
|
@ -7,6 +7,8 @@ export interface User {
|
|||
activated: boolean;
|
||||
email: string;
|
||||
name: string;
|
||||
personalDetails?: UserPersonalDetails;
|
||||
preferences?: UserPreferences;
|
||||
}
|
||||
|
||||
export enum PersonSex {
|
||||
|
@ -20,6 +22,7 @@ export interface UserPersonalDetails {
|
|||
birthDate?: string;
|
||||
currentWeight?: number;
|
||||
currentWeightUnit?: number;
|
||||
currentMetricWeight?: number;
|
||||
sex: PersonSex;
|
||||
}
|
||||
|
||||
|
@ -45,9 +48,18 @@ class AuthModule {
|
|||
|
||||
private tokenRefreshTimer?: Timeout;
|
||||
|
||||
/**
|
||||
* Attempts to use the given credentials to obtain an access token for
|
||||
* sending authenticated requests.
|
||||
* @param authStore The auth store to use to update app state.
|
||||
* @param credentials The credentials for logging in.
|
||||
*/
|
||||
public async login(authStore: AuthStoreType, credentials: TokenCredentials) {
|
||||
authStore.token = await this.fetchNewToken(credentials);
|
||||
authStore.user = await this.fetchMyUser(authStore);
|
||||
authStore.token = await this.getNewToken(credentials);
|
||||
authStore.user = await this.getMyUser(authStore);
|
||||
// Load the user's attached data right away too.
|
||||
authStore.user.personalDetails = await this.getMyPersonalDetails(authStore);
|
||||
authStore.user.preferences = await this.getMyPreferences(authStore);
|
||||
|
||||
clearTimeout(this.tokenRefreshTimer);
|
||||
this.tokenRefreshTimer = setTimeout(
|
||||
|
@ -71,7 +83,7 @@ class AuthModule {
|
|||
return response.data;
|
||||
}
|
||||
|
||||
public async fetchNewToken(credentials: TokenCredentials): Promise<string> {
|
||||
public async getNewToken(credentials: TokenCredentials): Promise<string> {
|
||||
const response = await api.post('/auth/token', credentials);
|
||||
return response.data.token;
|
||||
}
|
||||
|
@ -81,12 +93,12 @@ class AuthModule {
|
|||
authStore.token = response.data.token;
|
||||
}
|
||||
|
||||
public async fetchMyUser(authStore: AuthStoreType): Promise<User> {
|
||||
public async getMyUser(authStore: AuthStoreType): Promise<User> {
|
||||
const response = await api.get('/auth/me', authStore.axiosConfig);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async fetchUser(userId: string, authStore: AuthStoreType): Promise<User> {
|
||||
public async getUser(userId: string, authStore: AuthStoreType): Promise<User> {
|
||||
const response = await api.get(`/auth/users/${userId}`, authStore.axiosConfig);
|
||||
return response.data;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{{ submission.exercise.displayName }}
|
||||
</q-item-label>
|
||||
<q-item-label caption>
|
||||
{{ submission.submitterName }}
|
||||
{{ submission.user.name }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side top>
|
||||
|
|
|
@ -39,6 +39,12 @@ export default {
|
|||
submit: 'Submit',
|
||||
},
|
||||
},
|
||||
userPage: {
|
||||
notFound: {
|
||||
title: 'User Not Found',
|
||||
description: 'We couldn\'t find the user you\'re looking for.'
|
||||
}
|
||||
},
|
||||
accountMenuItem: {
|
||||
logIn: 'Login',
|
||||
myAccount: 'My Account',
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{{ submission.exercise.displayName }}
|
||||
</h3>
|
||||
<p>{{ submission.reps }} reps</p>
|
||||
<p>by {{ submission.submitterName }}</p>
|
||||
<p>by <router-link :to="'/users/' + submission.user.id">{{ submission.user.name }}</router-link></p>
|
||||
<p>At <router-link :to="getGymRoute(submission.gym)">{{ submission.gym.displayName }}</router-link></p>
|
||||
<p>
|
||||
{{ submission.createdAt.setLocale($i18n.locale).toLocaleString(DateTime.DATETIME_MED) }}
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
<p>{{ user?.email }}</p>
|
||||
<p v-if="isOwnUser">This is your account!</p>
|
||||
</StandardCenteredPage>
|
||||
<StandardCenteredPage v-if="userNotFound">
|
||||
<h3>{{ $t('userPage.notFound.title') }}</h3>
|
||||
<p>{{ $t('userPage.notFound.description') }}</p>
|
||||
</StandardCenteredPage>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
|
@ -29,10 +33,22 @@ const user: Ref<User | undefined> = ref();
|
|||
*/
|
||||
const isOwnUser = ref(false);
|
||||
|
||||
/**
|
||||
* Flag used to indicate whether we should show a "not found" message instead
|
||||
* of the usual user page.
|
||||
*/
|
||||
const userNotFound = ref(false);
|
||||
|
||||
onMounted(async () => {
|
||||
const userId = route.params.userId as string;
|
||||
user.value = await api.auth.fetchUser(userId, authStore);
|
||||
isOwnUser.value = user.value.id === authStore.user?.id;
|
||||
try {
|
||||
user.value = await api.auth.getUser(userId, authStore);
|
||||
} catch (error: any) {
|
||||
if (error.response && error.response.code === 404) {
|
||||
userNotFound.value = true;
|
||||
}
|
||||
}
|
||||
isOwnUser.value = authStore.loggedIn && user.value.id === authStore.user?.id;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useCounterStore = defineStore('counter', {
|
||||
state: () => ({
|
||||
counter: 0,
|
||||
}),
|
||||
getters: {
|
||||
doubleCount: (state) => state.counter * 2,
|
||||
},
|
||||
actions: {
|
||||
increment() {
|
||||
this.counter++;
|
||||
},
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue