Skip to content

Commit

Permalink
Merge branch 'develop' into user-profile-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
GODrums authored Oct 14, 2024
2 parents ecda310 + 135bcee commit 26ca6b9
Show file tree
Hide file tree
Showing 32 changed files with 610 additions and 121 deletions.
24 changes: 24 additions & 0 deletions server/application-server/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ paths:
type: array
items:
$ref: "#/components/schemas/PullRequest"
/meta:
get:
tags:
- meta
operationId: getMetaData
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/MetaDataDTO"
/leaderboard:
get:
tags:
Expand All @@ -125,6 +137,11 @@ paths:
schema:
type: string
format: date
- name: repository
in: query
required: false
schema:
type: string
responses:
"200":
description: OK
Expand Down Expand Up @@ -586,6 +603,13 @@ components:
type: array
items:
$ref: "#/components/schemas/PullRequestReview"
MetaDataDTO:
type: object
properties:
repositoriesToMonitor:
type: array
items:
type: string
LeaderboardEntry:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class SecurityConfig {
interface AuthoritiesConverter extends Converter<Map<String, Object>, Collection<GrantedAuthority>> {
}

@SuppressWarnings("unchecked")
@Bean
AuthoritiesConverter realmRolesAuthoritiesConverter() {
return claims -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ SELECT new UserDTO(u.id, u.login, u.email, u.name, u.url)
FROM User u
JOIN FETCH u.reviews re
WHERE re.createdAt BETWEEN :after AND :before
AND (:repository IS NULL OR re.pullRequest.repository.nameWithOwner = :repository)
""")
List<User> findAllInTimeframe(@Param("after") OffsetDateTime after, @Param("before") OffsetDateTime before);
List<User> findAllInTimeframe(@Param("after") OffsetDateTime after, @Param("before") OffsetDateTime before,
@Param("repository") Optional<String> repository);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ public List<User> getAllUsers() {
return userRepository.findAll().stream().toList();
}

public List<User> getAllUsersInTimeframe(OffsetDateTime after, OffsetDateTime before) {
logger.info("Getting all users in timeframe between " + after + " and " + before);
return userRepository.findAllInTimeframe(after, before);
public List<User> getAllUsersInTimeframe(OffsetDateTime after, OffsetDateTime before, Optional<String> repository) {
logger.info("Getting all users in timeframe between " + after + " and " + before + " for repository: "
+ repository.orElse("all"));
return userRepository.findAllInTimeframe(after, before, repository);
}

public Optional<UserProfileDTO> getUserProfileDTO(String login) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public LeaderboardController(LeaderboardService leaderboardService) {
@GetMapping
public ResponseEntity<List<LeaderboardEntry>> getLeaderboard(
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Optional<LocalDate> after,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Optional<LocalDate> before) {
return ResponseEntity.ok(leaderboardService.createLeaderboard(after, before));
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Optional<LocalDate> before,
@RequestParam Optional<String> repository) {
return ResponseEntity.ok(leaderboardService.createLeaderboard(after, before, repository));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ public LeaderboardService(UserService userService) {
this.userService = userService;
}

public List<LeaderboardEntry> createLeaderboard(Optional<LocalDate> after, Optional<LocalDate> before) {
public List<LeaderboardEntry> createLeaderboard(Optional<LocalDate> after, Optional<LocalDate> before,
Optional<String> repository) {
logger.info("Creating leaderboard dataset");

LocalDateTime afterCutOff = after.isPresent() ? after.get().atStartOfDay()
: LocalDate.now().minusDays(timeframe).atStartOfDay();
Optional<LocalDateTime> beforeCutOff = before.map(date -> date.plusDays(1).atStartOfDay());

List<User> users = userService.getAllUsersInTimeframe(afterCutOff.atOffset(ZoneOffset.UTC),
beforeCutOff.map(b -> b.atOffset(ZoneOffset.UTC)).orElse(OffsetDateTime.now()));
beforeCutOff.map(b -> b.atOffset(ZoneOffset.UTC)).orElse(OffsetDateTime.now()), repository);

logger.info("Found " + users.size() + " users for the leaderboard");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.tum.in.www1.hephaestus.meta;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/meta")
public class MetaController {

private final MetaService metaService;

public MetaController(MetaService metaService) {
this.metaService = metaService;
}

@GetMapping
public ResponseEntity<MetaDataDTO> getMetaData() {
return ResponseEntity.ok(metaService.getMetaData());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.tum.in.www1.hephaestus.meta;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record MetaDataDTO(String[] repositoriesToMonitor) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package de.tum.in.www1.hephaestus.meta;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class MetaService {
private static final Logger logger = LoggerFactory.getLogger(MetaService.class);

@Value("${monitoring.repositories}")
private String[] repositoriesToMonitor;

public MetaDataDTO getMetaData() {
logger.info("Getting meta data...");
return new MetaDataDTO(repositoriesToMonitor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
import de.tum.in.www1.hephaestus.codereview.user.User;
import de.tum.in.www1.hephaestus.codereview.user.UserConverter;
import de.tum.in.www1.hephaestus.codereview.user.UserRepository;
import jakarta.transaction.Transactional;

@Transactional
@Service
public class GitHubDataSyncService {
private static final Logger logger = LoggerFactory.getLogger(GitHubDataSyncService.class);
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/app/core/modules/openapi/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ api/admin.serviceInterface.ts
api/api.ts
api/leaderboard.service.ts
api/leaderboard.serviceInterface.ts
api/meta.service.ts
api/meta.serviceInterface.ts
api/pull-request.service.ts
api/pull-request.serviceInterface.ts
api/user.service.ts
Expand All @@ -18,6 +20,7 @@ index.ts
model/issue-comment-dto.ts
model/issue-comment.ts
model/leaderboard-entry.ts
model/meta-data-dto.ts
model/models.ts
model/pull-request-dto.ts
model/pull-request-label.ts
Expand Down
5 changes: 4 additions & 1 deletion webapp/src/app/core/modules/openapi/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ export * from './admin.serviceInterface';
export * from './leaderboard.service';
import { LeaderboardService } from './leaderboard.service';
export * from './leaderboard.serviceInterface';
export * from './meta.service';
import { MetaService } from './meta.service';
export * from './meta.serviceInterface';
export * from './pull-request.service';
import { PullRequestService } from './pull-request.service';
export * from './pull-request.serviceInterface';
export * from './user.service';
import { UserService } from './user.service';
export * from './user.serviceInterface';
export const APIS = [AdminService, LeaderboardService, PullRequestService, UserService];
export const APIS = [AdminService, LeaderboardService, MetaService, PullRequestService, UserService];
13 changes: 9 additions & 4 deletions webapp/src/app/core/modules/openapi/api/leaderboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ export class LeaderboardService implements LeaderboardServiceInterface {
/**
* @param after
* @param before
* @param repository
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getLeaderboard(after?: string, before?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Array<LeaderboardEntry>>;
public getLeaderboard(after?: string, before?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Array<LeaderboardEntry>>>;
public getLeaderboard(after?: string, before?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Array<LeaderboardEntry>>>;
public getLeaderboard(after?: string, before?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
public getLeaderboard(after?: string, before?: string, repository?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<Array<LeaderboardEntry>>;
public getLeaderboard(after?: string, before?: string, repository?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<Array<LeaderboardEntry>>>;
public getLeaderboard(after?: string, before?: string, repository?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<Array<LeaderboardEntry>>>;
public getLeaderboard(after?: string, before?: string, repository?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {

let localVarQueryParameters = new HttpParams({encoder: this.encoder});
if (after !== undefined && after !== null) {
Expand All @@ -115,6 +116,10 @@ export class LeaderboardService implements LeaderboardServiceInterface {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>before, 'before');
}
if (repository !== undefined && repository !== null) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>repository, 'repository');
}

let localVarHeaders = this.defaultHeaders;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export interface LeaderboardServiceInterface {
*
* @param after
* @param before
* @param repository
*/
getLeaderboard(after?: string, before?: string, extraHttpRequestParams?: any): Observable<Array<LeaderboardEntry>>;
getLeaderboard(after?: string, before?: string, repository?: string, extraHttpRequestParams?: any): Observable<Array<LeaderboardEntry>>;

}
157 changes: 157 additions & 0 deletions webapp/src/app/core/modules/openapi/api/meta.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* Hephaestus API
* API documentation for the Hephaestus application server.
*
* The version of the OpenAPI document: 0.0.1
* Contact: [email protected]
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams,
HttpResponse, HttpEvent, HttpParameterCodec, HttpContext
} from '@angular/common/http';
import { CustomHttpParameterCodec } from '../encoder';
import { Observable } from 'rxjs';

// @ts-ignore
import { MetaDataDTO } from '../model/meta-data-dto';

// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration';
import {
MetaServiceInterface
} from './meta.serviceInterface';



@Injectable({
providedIn: 'root'
})
export class MetaService implements MetaServiceInterface {

protected basePath = 'http://localhost';
public defaultHeaders = new HttpHeaders();
public configuration = new Configuration();
public encoder: HttpParameterCodec;

constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string|string[], @Optional() configuration: Configuration) {
if (configuration) {
this.configuration = configuration;
}
if (typeof this.configuration.basePath !== 'string') {
const firstBasePath = Array.isArray(basePath) ? basePath[0] : undefined;
if (firstBasePath != undefined) {
basePath = firstBasePath;
}

if (typeof basePath !== 'string') {
basePath = this.basePath;
}
this.configuration.basePath = basePath;
}
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
}


// @ts-ignore
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
if (typeof value === "object" && value instanceof Date === false) {
httpParams = this.addToHttpParamsRecursive(httpParams, value);
} else {
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
}
return httpParams;
}

private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
if (value == null) {
return httpParams;
}

if (typeof value === "object") {
if (Array.isArray(value)) {
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
} else if (value instanceof Date) {
if (key != null) {
httpParams = httpParams.append(key, (value as Date).toISOString().substring(0, 10));
} else {
throw Error("key may not be null if value is Date");
}
} else {
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
httpParams, value[k], key != null ? `${key}.${k}` : k));
}
} else if (key != null) {
httpParams = httpParams.append(key, value);
} else {
throw Error("key may not be null if value is not object or array");
}
return httpParams;
}

/**
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getMetaData(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<MetaDataDTO>;
public getMetaData(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<MetaDataDTO>>;
public getMetaData(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<MetaDataDTO>>;
public getMetaData(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {

let localVarHeaders = this.defaultHeaders;

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}

let localVarTransferCache: boolean | undefined = options && options.transferCache;
if (localVarTransferCache === undefined) {
localVarTransferCache = true;
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/meta`;
return this.httpClient.request<MetaDataDTO>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
transferCache: localVarTransferCache,
reportProgress: reportProgress
}
);
}

}
Loading

0 comments on commit 26ca6b9

Please sign in to comment.