Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6812a15
ELLE-378 | Update base admin page, add prerequisites for other admin …
robkukke Apr 15, 2026
900df18
ELLE-378 | Update AdminController, add getPublishedTextDetails
robkukke Apr 16, 2026
0e7d066
ELLE-378 | Add getDonatedTextDetails
robkukke Apr 17, 2026
4728ebb
ELLE-378 | Add updatePublishedText, more refactoring
robkukke Apr 18, 2026
4225480
ELLE-378 | Add updateDonatedText
robkukke Apr 19, 2026
89ae7cb
ELLE-378 | Add deleteDonatedText and deletePublishedText
robkukke Apr 20, 2026
fe9b4e8
ELLE-378 | Add publishDonatedText
robkukke Apr 20, 2026
00e694d
ELLE-378 | Add getDonatedTexts and getPublishedTexts
robkukke Apr 23, 2026
77ea66d
ELLE-378 | Add getDonatedTexts and getPublishedTexts
robkukke May 5, 2026
f825fd7
ELLE-378 | Add getDonatedTexts and getPublishedTexts
robkukke May 6, 2026
1e3d42e
ELLE-378 | Add search form and results table for donated and publishe…
robkukke May 7, 2026
2483371
ELLE-378 | Add details modal for donated and published texts
robkukke Jun 1, 2026
2305563
ELLE-378 | Update publishDonatedText
robkukke Jun 4, 2026
a05178f
ELLE-378 | fix haridus property source when adding texts
Jun 10, 2026
cb30a0a
ELLE-378 | remove wildcard imports
Jun 10, 2026
7703722
ELLE-378 | simplify PropertyMatch inner class
Jun 10, 2026
e61ef68
ELLE-378 | add 2026-2030 year range, fix first akad_oppematerjal valu…
Jun 10, 2026
021e118
ELLE-378 | add delete grant to api_user for necessary tables
Jun 11, 2026
cccc023
ELLE-378 | fix emakeel parsing in UI
Jun 11, 2026
c64f3fa
ELLE-378 | derive aasta and ajavahemik correctly, fix parsing and sav…
Jun 11, 2026
b6c58f7
ELLE-378 | remove unused mapper component
Jun 11, 2026
ba69cae
ELLE-378 | add test stage to jenkins pipelines
Jun 11, 2026
4270fa4
ELLE-378 | reduce @Transactional declarations
Jun 11, 2026
b06e3aa
ELLE-378 | reduce unnecessary logging
Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ee.tlu.evkk.api.constant;

import lombok.NoArgsConstructor;

import static lombok.AccessLevel.PRIVATE;

@NoArgsConstructor(access = PRIVATE)
public class TextPropertyConstants {

// Property names
public static final String PROP_TITLE = "title";
public static final String PROP_DESCRIPTION = "kirjeldus";
public static final String PROP_TYPE = "tekstityyp";
public static final String PROP_CORPUS = "korpus";
public static final String PROP_TEXT_LANGUAGE = "tekstikeel";
public static final String PROP_USED_MATERIALS = "abivahendid";
public static final String PROP_ACADEMIC_MATERIALS = "akad_oppematerjal";
public static final String PROP_ACADEMIC_MATERIALS_OTHER = "akad_oppematerjal_muu";
public static final String PROP_ACADEMIC_SUBTYPE = "akad_alamliik";
public static final String PROP_NON_ACADEMIC_SUBTYPE = "mitteakad_alamliik";
public static final String PROP_DOMAIN = "valdkond";
public static final String PROP_ARTICLE_PUBLICATION = "artikkel_valjaanne";
public static final String PROP_ARTICLE_YEAR = "artikkel_aasta";
public static final String PROP_ARTICLE_NUMBER = "artikkel_number";
public static final String PROP_ARTICLE_PAGES = "artikkel_lehekyljed";
public static final String PROP_AGE_RAW = "vanus";
public static final String PROP_AGE_RANGE = "vanusevahemik";
public static final String PROP_YEAR = "aasta";
public static final String PROP_YEAR_RANGE = "ajavahemik";
public static final String PROP_GENDER = "sugu";
public static final String PROP_EDUCATION = "haridus";
public static final String PROP_STUDY_LEVEL = "oppeaste";
public static final String PROP_DEGREE = "teaduskraad";
public static final String PROP_NATIVE_LANGUAGE = "emakeel";
public static final String PROP_OTHER_LANGUAGES = "muudkeeled";
public static final String PROP_COUNTRY = "riik";

// Main text type values
public static final String TEXT_TYPE_ACADEMIC = "akadeemiline";

// Subtype values requiring exact matching
public static final String SUBTYPE_K2_PROFICIENCY_EXAM = "k2eesti_riiklik_eksamitoo";
public static final String SUBTYPE_K2_OLYMPIADE = "k2eesti_ol_loovkirjutis";

// Subtype prefix values
public static final String SUBTYPE_PREFIX_K1_ESTONIAN = "k1eesti";
public static final String SUBTYPE_PREFIX_K1_RUSSIAN = "k1vene";
public static final String SUBTYPE_PREFIX_K2_ESTONIAN = "k2eesti";
public static final String SUBTYPE_PREFIX_K3_RUSSIAN = "k3vene";

// Corpus IDs
public static final String CORPUS_ACADEMIC_ESTONIAN = "cwUSEqQLt";
public static final String CORPUS_L1_ESTONIAN = "cYDRkpymb";
public static final String CORPUS_L1_RUSSIAN = "cgSRJPKTr";
public static final String CORPUS_L2_ESTONIAN = "cFOoRQekA";
public static final String CORPUS_L2_OLYMPIADE = "cFqPphvYi";
public static final String CORPUS_L2_PROFICIENCY_EXAMS = "clWmOIrLa";
public static final String CORPUS_L3_RUSSIAN = "cZjHWUPtD";

// Text language values
public static final String LANGUAGE_ESTONIAN = "eesti";
public static final String LANGUAGE_RUSSIAN = "vene";

// Age range codes
public static final String AGE_RANGE_UP_TO_18 = "kuni18";
public static final String AGE_RANGE_19_TO_26 = "kuni26";
public static final String AGE_RANGE_27_TO_40 = "kuni40";
public static final String AGE_RANGE_41_PLUS = "41plus";

// Year range codes
public static final String YEAR_RANGE_2000_2005 = "2000-2005";
public static final String YEAR_RANGE_2006_2010 = "2006-2010";
public static final String YEAR_RANGE_2011_2015 = "2011-2015";
public static final String YEAR_RANGE_2016_2020 = "2016-2020";
public static final String YEAR_RANGE_2021_2025 = "2021-2025";
public static final String YEAR_RANGE_2026_2030 = "2026-2030";
}
86 changes: 81 additions & 5 deletions api/src/main/java/ee/tlu/evkk/api/controller/AdminController.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,98 @@
package ee.tlu.evkk.api.controller;

import ee.tlu.evkk.dal.dao.TextAddedDao;
import ee.evkk.dto.CorpusRequestDto;
import ee.evkk.dto.DonatedTextRequestDto;
import ee.evkk.dto.TextDetailsResponseDto;
import ee.evkk.dto.TextUpdateRequestDto;
import ee.evkk.dto.TextsToReviewResponseDto;
import ee.tlu.evkk.api.service.AdminTextService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.UUID;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RestController
@RequiredArgsConstructor
@RequestMapping("/admin")
@Secured("ROLE_ADMIN")
public class AdminController {

private final TextAddedDao textAddedDao;
private final AdminTextService adminTextService;

@GetMapping("/texts-to-review")
public ResponseEntity<TextsToReviewResponseDto> getTextsToReview() {
return ResponseEntity.ok(adminTextService.getTextsToReview());
}

@PostMapping(value = "/donated-texts", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<String> getDonatedTexts(@RequestBody DonatedTextRequestDto request) {
return ResponseEntity.ok(adminTextService.getDonatedTexts(request));
}

@GetMapping("/donated-texts/{id}")
public ResponseEntity<TextDetailsResponseDto> getDonatedTextDetails(@PathVariable UUID id) {
return adminTextService.getDonatedTextDetails(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

@PutMapping("/donated-texts/{id}")
public ResponseEntity<TextDetailsResponseDto> updateDonatedText(
@PathVariable UUID id,
@RequestBody @Valid TextUpdateRequestDto request
) {
return ResponseEntity.ok(adminTextService.updateDonatedText(id, request));
}

@DeleteMapping("/donated-texts/{id}")
public ResponseEntity<Void> deleteDonatedText(@PathVariable UUID id) {
adminTextService.deleteDonatedText(id);
return ResponseEntity.noContent().build();
}

@PostMapping("/donated-texts/{id}/publish")
public ResponseEntity<TextDetailsResponseDto> publishDonatedText(
@PathVariable UUID id,
@RequestBody(required = false) @Valid TextUpdateRequestDto request
) {
return ResponseEntity.ok(adminTextService.publishDonatedText(id, request));
}

@PostMapping(value = "/published-texts", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<String> getPublishedTexts(@RequestBody CorpusRequestDto request) {
return ResponseEntity.ok(adminTextService.getPublishedTexts(request));
}

@GetMapping("/published-texts/{id}")
public ResponseEntity<TextDetailsResponseDto> getPublishedTextDetails(@PathVariable UUID id) {
return adminTextService.getPublishedTextDetails(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}

@PutMapping("/published-texts/{id}")
public ResponseEntity<TextDetailsResponseDto> updatePublishedText(
@PathVariable UUID id,
@RequestBody @Valid TextUpdateRequestDto request
) {
return ResponseEntity.ok(adminTextService.updatePublishedText(id, request));
}

@GetMapping("texts-to-review")
public Integer textsToReview() {
return textAddedDao.count();
@DeleteMapping("/published-texts/{id}")
public ResponseEntity<Void> deletePublishedText(@PathVariable UUID id) {
adminTextService.deletePublishedText(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public ResponseEntity<List<String>> mitmekesisus(@RequestBody CommonTextRequestD

@PostMapping("/detailneparing")
public ResponseEntity<String> detailneparing(@RequestBody CorpusRequestDto vaartused) {
return ok(textService.detailneparing(vaartused));
return ok(textService.detailneparing(vaartused, false));
}

@PostMapping("/tekstidfailina")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import ee.tlu.evkk.api.controller.error.ErrorEntity;
import ee.tlu.evkk.api.controller.error.ErrorEntityFactory;
import ee.tlu.evkk.api.exception.AbstractBusinessException;
import ee.tlu.evkk.api.exception.EntityNotFoundException;
import ee.tlu.evkk.api.exception.RateLimitExceededException;
import ee.tlu.evkk.api.exception.UnauthorizedException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

Expand All @@ -20,6 +22,7 @@
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

Expand Down Expand Up @@ -58,6 +61,16 @@ public ResponseEntity<Object> handleRateLimitExceededException() {
return new ResponseEntity<>(TOO_MANY_REQUESTS);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleMethodArgumentNotValidException() {
return new ResponseEntity<>(BAD_REQUEST);
}

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<Object> handleEntityNotFoundException() {
return new ResponseEntity<>(NOT_FOUND);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleException(Exception ex) {
log.error("Internal Server Error occurred", ex);
Expand Down
Loading