This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • development/sharing/codeability-sharing-platform
1 result
Show changes
Showing
with 310 additions and 116 deletions
......@@ -3,11 +3,9 @@ package at.ac.uibk.gitsearch.service.mapper;
import at.ac.uibk.gitsearch.domain.Review;
import at.ac.uibk.gitsearch.domain.ReviewRating;
import at.ac.uibk.gitsearch.service.dto.ReviewDTO;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
......@@ -38,11 +36,4 @@ public interface ReviewMapper extends EntityMapper<ReviewDTO, Review> {
default Set<ReviewRating> map(List<String> value) {
return new HashSet<>();
}
default List<String> map(Set<ReviewRating> value) {
if (value == null) {
return Collections.emptyList();
}
return value.stream().map(rr -> rr.getComment()).collect(Collectors.toList());
}
}
......@@ -17,10 +17,11 @@ import org.mapstruct.NullValuePropertyMappingStrategy;
/**
* Mapper for the entity {@link ReviewRating} and its DTO {@link ReviewRatingDTO}.
*/
@Mapper(componentModel = "spring", uses = { ReviewMapper.class, UserMapper.class })
@Mapper(componentModel = "spring", uses = { ReviewMapper.class, UserMapper.class, ReviewCommentMapper.class })
public interface ReviewRatingMapper extends EntityMapper<ReviewRatingDTO, ReviewRating> {
@Override
@Mapping(target = "user.authorities", source = "user.authorities", qualifiedByName = "authSet2")
@Mapping(target = "comment", source = "comment")
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
ReviewRating toEntity(ReviewRatingDTO dto);
......@@ -31,6 +32,7 @@ public interface ReviewRatingMapper extends EntityMapper<ReviewRatingDTO, Review
void partialUpdate(@MappingTarget ReviewRating entity, ReviewRatingDTO dto);
@Override
@Mapping(target = "comment", source = "comment")
@Mapping(target = "review", source = "review", qualifiedByName = "resource")
@Mapping(target = "user", source = "user", qualifiedByName = "id")
@Mapping(target = "user.authorities", source = "user.authorities", qualifiedByName = "authToStringSet")
......
......@@ -26,8 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UtilityService {
@SuppressWarnings("unused")
private final Logger log = LoggerFactory.getLogger(UtilityService.class);
private static final Logger LOGGER = LoggerFactory.getLogger(UtilityService.class);
@Autowired
private Map<String, JpaRepository<?, ?>> dbRepositories;
......@@ -52,12 +51,12 @@ public class UtilityService {
ResolvableType resolvableType = ResolvableType.forClass(repositoryClass).as(JpaRepository.class);
ResolvableType entityType = resolvableType.getGeneric(0);
String dbRepositoryBeanName = dbRepositoryEntry.getKey();
log.info("Trying to sync Repository {} for {}", dbRepositoryBeanName, entityType.getType().getTypeName());
LOGGER.info("Trying to sync Repository {} for {}", dbRepositoryBeanName, entityType.getType().getTypeName());
String searchRepositoryBeanName = dbRepositoryBeanName.replace("Repository", "SearchRepository");
ElasticsearchRepository<?, ?> searchRepository = searchRepositories.get(searchRepositoryBeanName);
if (searchRepository == null) {
log.debug("Cannot find ES Repository {} for DB Repository {}", dbRepositoryBeanName, searchRepositoryBeanName);
LOGGER.debug("Cannot find ES Repository {} for DB Repository {}", dbRepositoryBeanName, searchRepositoryBeanName);
continue;
}
treatedRepositories.add(dbRepositoryBeanName);
......@@ -91,7 +90,7 @@ public class UtilityService {
} catch (
NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e
) {
log.error("Cannot sync {} to {}", dataRepository, searchRepository, e);
LOGGER.error("Cannot sync {} to {}", dataRepository, searchRepository, e);
}
}
}
......@@ -57,6 +57,8 @@ import org.springframework.web.servlet.HandlerMapping;
@RequestMapping("/api")
public class ExerciseResource {
private static final String THERE_WAS_AN_ERROR_FINDING_YOUR_EXERCISE_FORMAT = "There was an error finding your exercise %s.";
private static final String NOT_FOUND = "not found";
private static final String ENTITY_NAME = "ExerciseResource";
......@@ -114,7 +116,7 @@ public class ExerciseResource {
true,
REPOSITORYFILE,
NOT_FOUND,
"There was an error finding your exercise " + exerciseId + "."
String.format(THERE_WAS_AN_ERROR_FINDING_YOUR_EXERCISE_FORMAT, exerciseId)
)
)
.build();
......@@ -165,7 +167,7 @@ public class ExerciseResource {
* @return the ResponseEntity with status 200 (OK) and with the searchresult, or with status 404 (Not Found)
*/
@GetMapping("/exercise/**")
public ResponseEntity<SearchResultDTO> getExerciseById(HttpServletRequest request) throws IOException {
public ResponseEntity<SearchResultDTO> getExerciseById(HttpServletRequest request) {
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
String exerciseId = RestUtils.decodeURL(request, pattern);
......@@ -203,7 +205,7 @@ public class ExerciseResource {
true,
REPOSITORYFILE,
NOT_FOUND,
"There was an error finding your exercise " + exerciseId + "."
String.format(THERE_WAS_AN_ERROR_FINDING_YOUR_EXERCISE_FORMAT, exerciseId)
)
)
.build();
......@@ -246,7 +248,7 @@ public class ExerciseResource {
true,
REPOSITORYFILE,
NOT_FOUND,
"There was an error finding your exercise " + exerciseId + "."
String.format(THERE_WAS_AN_ERROR_FINDING_YOUR_EXERCISE_FORMAT, exerciseId)
)
)
.build();
......@@ -384,7 +386,7 @@ public class ExerciseResource {
@RequestBody ArtemisExerciseInfo exerciseInfo,
@PathVariable("exerciseToken") String exerciseToken,
@PathVariable("gitlabGroupId") Long gitlabGroupId
) throws GitLabApiException, GitAPIException, IOException, ArtemisImportError {
) throws GitLabApiException, IOException, ArtemisImportError {
if (SecurityUtils.isAuthenticated()) {
exerciseImportService.importExercise(exerciseInfo, exerciseToken, gitlabGroupId);
return Response.ok().build();
......
......@@ -144,8 +144,12 @@ public class ReviewResource {
@PreAuthorize(USER_ROLE)
public ResponseEntity<Void> requestReviewForExercise(@RequestBody ReviewRequest reviewRequest) {
log.debug("REST request to request a review for exercise: {}", reviewRequest.getResource());
reviewService.requestReviewForExercise(reviewRequest);
return ResponseEntity.ok().build();
Boolean created = reviewService.requestReviewForExercise(reviewRequest);
if (created) {
return ResponseEntity.ok().build();
} else {
return ResponseEntity.badRequest().build();
}
}
@PostMapping("/review/notifyReviewers")
......@@ -168,6 +172,14 @@ public class ReviewResource {
return ResponseEntity.ok().build();
}
@PostMapping("/review/removeBadge")
@PreAuthorize(ADMIN_ROLE)
public ResponseEntity<Void> removeBadge(@RequestBody ReviewDTO review) {
log.debug("REST request to remove badge for resource: {}", review.getResource());
reviewService.removeBadge(review.getId());
return ResponseEntity.ok().build();
}
@PostMapping("/review/changeStatus")
@PreAuthorize(USER_ROLE)
public ResponseEntity<UserDTO> changeStatus(@RequestBody boolean status) {
......
......@@ -26,7 +26,6 @@ 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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import tech.jhipster.web.util.HeaderUtil;
......@@ -190,23 +189,22 @@ public class SavedSearchesResource {
.headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString()))
.build();
}
/**
* {@code SEARCH /_search/saved-searches?query=:query} : search for the savedSearches corresponding
* to the query.
*
* @param query the query of the savedSearches search.
* @param pageable the pagination information.
* @return the result of the search.
*/
@GetMapping("/_search/saved-searches")
public ResponseEntity<List<SavedSearchesDTO>> searchSavedSearches(
@RequestParam String query,
@org.springdoc.api.annotations.ParameterObject Pageable pageable
) {
log.debug("REST request to search for a page of SavedSearches for query {}", query);
Page<SavedSearchesDTO> page = savedSearchesService.search(query, pageable);
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
return ResponseEntity.ok().headers(headers).body(page.getContent());
}
// /**
// * {@code SEARCH /_search/saved-searches?query=:query} : search for the savedSearches corresponding
// * to the query.
// *
// * @param query the query of the savedSearches search.
// * @param pageable the pagination information.
// * @return the result of the search.
// */
// @GetMapping("/_search/saved-searches")
// public ResponseEntity<List<SavedSearchesDTO>> searchSavedSearches(
// @RequestParam String query,
// @org.springdoc.api.annotations.ParameterObject Pageable pageable
// ) {
// log.debug("REST request to search for a page of SavedSearches for query {}", query);
// Page<SavedSearchesDTO> page = savedSearchesService.search(query, pageable);
// HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
// return ResponseEntity.ok().headers(headers).body(page.getContent());
// }
}
......@@ -41,7 +41,7 @@ import org.springframework.web.bind.annotation.RestController;
public class SearchResource {
// @Value("${jhipster.clientApp.name}") // warning: inconsistent rename of gitSearchApp to gitSearchV2App :-(
private static final String applicationName = "gitsearchApp";
private static final String APPLICATION_NAME = "gitsearchApp";
private static final String ENTITY_NAME = "SearchResource";
......@@ -99,8 +99,7 @@ public class SearchResource {
* @throws IOException
*/
@GetMapping("/search/keywordsAutoComplete")
public List<AutoCompleteEntry> getKeywordsAutoComplete(@RequestParam String keyWordPrefix, @RequestParam(defaultValue = "10") int max)
throws IOException {
public List<AutoCompleteEntry> getKeywordsAutoComplete(@RequestParam String keyWordPrefix, @RequestParam(defaultValue = "10") int max) {
return metaDataRepository.getKeywordsAutoComplete(keyWordPrefix, max);
}
......@@ -110,11 +109,9 @@ public class SearchResource {
* @param formatPrefix
* @param max the maximum number of hits returned
* @return
* @throws IOException
*/
@GetMapping("/search/formatsAutoComplete")
public List<AutoCompleteEntry> getFormatsAutoComplete(@RequestParam String formatPrefix, @RequestParam(defaultValue = "10") int max)
throws IOException {
public List<AutoCompleteEntry> getFormatsAutoComplete(@RequestParam String formatPrefix, @RequestParam(defaultValue = "10") int max) {
return metaDataRepository.getFormatsAutoComplete(formatPrefix, max);
}
......@@ -124,11 +121,9 @@ public class SearchResource {
* @param creatorPrefix
* @param max the maximum number of hits returned
* @return
* @throws IOException
*/
@GetMapping("/search/creatorAutoComplete")
public List<AutoCompleteEntry> getCreatorAutoComplete(@RequestParam String creatorPrefix, @RequestParam(defaultValue = "10") int max)
throws IOException {
public List<AutoCompleteEntry> getCreatorAutoComplete(@RequestParam String creatorPrefix, @RequestParam(defaultValue = "10") int max) {
return metaDataRepository.getCreatorAutoComplete(creatorPrefix, max);
}
......@@ -138,13 +133,11 @@ public class SearchResource {
* @param contributorPrefix
* @param max the maximum number of hits returned
* @return
* @throws IOException
*/
@GetMapping("/search/contributorAutoComplete")
public List<AutoCompleteEntry> getContributorAutoComplete(
@RequestParam String contributorPrefix,
@RequestParam(defaultValue = "10") int max
) throws IOException {
) {
return metaDataRepository.getContributorAutoComplete(contributorPrefix, max);
}
......@@ -154,11 +147,9 @@ public class SearchResource {
* @param contributorPrefix
* @param max the maximum number of hits returned
* @return
* @throws IOException
*/
@GetMapping("/search/contributorCreatorAutoComplete")
public List<AutoCompleteEntry> getContributorCreatorAutoComplete(String contributorPrefix, @RequestParam(defaultValue = "10") int max)
throws IOException {
public List<AutoCompleteEntry> getContributorCreatorAutoComplete(String contributorPrefix, @RequestParam(defaultValue = "10") int max) {
return metaDataRepository.getContributorCreatorAutoComplete(contributorPrefix, max);
}
......@@ -168,13 +159,12 @@ public class SearchResource {
* @param programmingLanguagePrefix
* @param max the maximum number of hits returned
* @return
* @throws IOException
*/
@GetMapping("/search/programmingLanguageAutoComplete")
public List<AutoCompleteEntry> getProgrammingLanguageAutoComplete(
@RequestParam String programmingLanguagePrefix,
@RequestParam(defaultValue = "10") int max
) throws IOException {
) {
return metaDataRepository.getProgrammingLanguageAutoComplete(programmingLanguagePrefix, max);
}
......@@ -199,7 +189,7 @@ public class SearchResource {
.badRequest()
.headers(
HeaderUtil.createFailureAlert(
applicationName,
APPLICATION_NAME,
true,
ENTITY_NAME,
"internalServerError",
......
......@@ -50,7 +50,7 @@ public class StatisticsResource {
private static final String ENTITY_NAME = "statistics";
// @Value("${jhipster.clientApp.name}") // warning: inconsistent rename of gitSearchApp to gitSearchV2App :-(
private static final String applicationName = "gitsearchApp";
private static final String APPLICATION_NAME = "gitsearchApp";
private final StatisticsService statisticsService;
......@@ -101,7 +101,7 @@ public class StatisticsResource {
statisticsDTO.setId(newStats.get().getId());
return ResponseEntity
.created(new URI("/api/statistics/" + statisticsDTO.getId()))
.headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, statisticsDTO.getId().toString()))
.headers(HeaderUtil.createEntityCreationAlert(APPLICATION_NAME, true, ENTITY_NAME, statisticsDTO.getId().toString()))
.body(statisticsDTO);
}
......@@ -126,7 +126,7 @@ public class StatisticsResource {
StatisticsDTO result = statisticsService.save(statisticsDTO);
return ResponseEntity
.ok()
.headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, statisticsDTO.getId().toString()))
.headers(HeaderUtil.createEntityUpdateAlert(APPLICATION_NAME, true, ENTITY_NAME, statisticsDTO.getId().toString()))
.body(result);
}
......@@ -188,7 +188,7 @@ public class StatisticsResource {
try {
exerciseId = ExerciseId.fromString(exerciseIdString);
} catch (ParseException e) {
log.info("Cannot parse " + exerciseIdString);
log.info("Cannot parse {}", exerciseIdString);
return ResponseUtil.wrapOrNotFound(statisticsDTO);
}
// TODO there is a race condition, if several parallel requests do not find an entry.
......@@ -220,28 +220,10 @@ public class StatisticsResource {
statisticsService.delete(id);
return ResponseEntity
.noContent()
.headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString()))
.headers(HeaderUtil.createEntityDeletionAlert(APPLICATION_NAME, true, ENTITY_NAME, id.toString()))
.build();
}
// /**
// * {@code SEARCH /_search/statistics?query=:query} : search for the statistics
// * corresponding to the query.
// *
// * @param query the query of the statistics search.
// * @param pageable the pagination information.
// * @return the result of the search.
// */
// @GetMapping("/_search/statistics")
// @PreAuthorize("hasAnyRole('ADMIN')")
// public ResponseEntity<List<StatisticsDTO>> searchStatistics(@RequestParam String query, Pageable pageable) {
// log.debug("REST request to search for a page of Statistics for query {}", query);
// Page<StatisticsDTO> page = statisticsService.search(query, pageable);
// HttpHeaders headers = PaginationUtil
// .generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
// return ResponseEntity.ok().headers(headers).body(page.getContent());
// }
@GetMapping("/statistics/numberOfWatchlistEntries/**")
public ResponseEntity<Integer> getNumberOfWatchListEntriesForExerciseID(HttpServletRequest request) {
String pattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
......
#H2 Server Properties
#Fri May 05 15:53:11 CEST 2023
#Thu Aug 03 15:07:30 CEST 2023
0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/gitsearch|gitsearch
webSSL=false
webAllowOthers=true
......
......@@ -87,7 +87,7 @@ spring:
client:
provider:
oidc:
issuer-uri: https://keycloak.codeability-austria.uibk.ac.at/auth/realms/gitsearch
issuer-uri: https://keycloak.sharing-codeability.uibk.ac.at/auth/realms/gitsearch
registration:
oidc:
client-id: ${OIDC_KEYCLOAK_CLIENTID}
......
......@@ -55,6 +55,7 @@ spring:
mail:
host: smtp.uibk.ac.at
port: 25
from: artemis-support-informatik@uibk.ac.at
username: ${MAIL_USERNAME}
password: ${MAIL_PASSWORD}
from: no-reply@uibk.ac.at
......@@ -143,6 +144,8 @@ jhipster:
token-validity-in-seconds-for-remember-me: 2592000
mail: # specific JHipster mail property, for standard properties see MailProperties
base-url: https://search.sharing-codeability.uibk.ac.at/ # Modify according to your server's URL
from: no-reply@uibk.ac.at
enabled: true
logging:
use-json-format: false # By default, logs are not in Json format
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
......
......@@ -66,8 +66,14 @@ spring:
mail:
host: smtp.uibk.ac.at
port: 25
from: artemis-support-informatik@uibk.ac.at
username: ${MAIL_USERNAME}
password: ${MAIL_PASSWORD}
smtp:
auth: true
starttls:
enable: true
required: true
messages:
cache-duration: PT1S # 1 second, see the ISO 8601 standard
thymeleaf:
......@@ -77,7 +83,7 @@ spring:
client:
provider:
oidc:
issuer-uri: https://keycloak.codeability-austria.uibk.ac.at/auth/realms/gitsearch
issuer-uri: https://keycloak.sharing-codeability.uibk.ac.at/auth/realms/gitsearch
# gitlabOidc:
# issuer-uri: ${SECURITY_OAUTH2_CLIENT_PROVIDER_GITLABOIDC_ISSUERURI}
registration:
......
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.6.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<!--
Update the comment column in ReviewRating table.
-->
<changeSet id="20230731162350-2" author="eduard">
<preConditions onFail="MARK_RAN">
<columnExists tableName="review_rating" columnName="comment"/>
</preConditions>
<modifyDataType tableName="review_rating" columnName="comment" newDataType="text"/>
</changeSet>
<!-- jhipster-needle-liquibase-add-changeset - JHipster will add changesets here -->
</databaseChangeLog>
......@@ -37,6 +37,7 @@
<include file="config/liquibase/changelog/20230421162350_added_entity_constraints_ReviewRating.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/changelog/20230421090354_added_entity_constraints_ReviewHistoryEntry.xml" relativeToChangelogFile="false"/>
<include file="config/liquibase/changelog/20230731241110_update_review_rating_comment.xml" relativeToChangelogFile="false"/>
<!-- jhipster-needle-liquibase-add-constraints-changelog - JHipster will add liquibase constraints changelogs here -->
<!-- jhipster-needle-liquibase-add-incremental-changelog - JHipster will add incremental liquibase changelogs here -->
</databaseChangeLog>
......@@ -93,7 +93,7 @@
}
</style>
<select id="social-providers-dropdown" class="${properties.kcFormSocialAccountListClass!} select2-dropdown">
<option style="width: 300px!important;" selected>Select a Social Provider</option>
<option style="width: 300px!important;" selected>${msg("listTitle")}</option>
<#list social.providers?sort_by("displayName") as p>
<option style="width: 300px!important;" value="${p.loginUrl}">${p.displayName!}</option>
</#list>
......
......@@ -22,7 +22,8 @@ kerberosNotConfiguredTitle=Kerberos nicht konfiguriert
bypassKerberosDetail=Sie sind entweder nicht mit Kerberos angemeldet, oder Ihr Browser ist nicht f\u00FCr eine Anmeldung mit Kerberos konfiguriert. Bitte klicken Sie auf Weiter, damit Sie sich auf eine andere Art anmelden k\u00F6nnen
kerberosNotSetUp=Kerberos ist nicht konfiguriert. Sie k\u00F6nnen sich damit nicht anmelden.
registerTitle=Registrierung
loginAccountTitle=Mit Ihrem Uni-Account anmelden
loginAccountTitle=W\u00E4hlen sie eine Login-Methode
listTitle="Liste \u00F6ffnen"
loginTitle=Anmeldung bei {0}
loginTitleHtml={0}
impersonateTitle={0} Identit\u00E4tswechsel
......
......@@ -22,7 +22,8 @@ kerberosNotConfiguredTitle=Kerberos Not Configured
bypassKerberosDetail=Either you are not logged in by Kerberos or your browser is not set up for Kerberos login. Please click continue to login in through other means
kerberosNotSetUp=Kerberos is not set up. You cannot login.
registerTitle=Register
loginAccountTitle=Sign in with your university account
loginAccountTitle=Choose a login method
listTitle="Open list"
loginTitle=Sign in to {0}
loginTitleHtml={0}
impersonateTitle={0} Impersonate User
......
......@@ -17,8 +17,8 @@ export class AchievementsComponent implements OnInit {
constructor(private accountService: AccountService, protected searchService: SearchService, private httpClient: HttpClient) {}
public getTotalNumberOfViewsAndDownloads(): void {
this.searchService.getStatisticsForUser().subscribe(
(data: Statistics) => {
this.searchService.getStatisticsForUser().subscribe({
next: (data: Statistics) => {
if (data) {
this.statistics = data;
this.statistics.id = 1;
......@@ -31,8 +31,8 @@ export class AchievementsComponent implements OnInit {
this.statistics.views = 0;
}
},
() => alert('Could not load statistics for User')
);
error: () => alert('Could not load statistics for User'),
});
}
ngOnInit(): void {
......
......@@ -28,7 +28,6 @@
style="margin-top: 20px"
data-toggle="modal"
data-target="#detailModal0"
(click)="(true)"
[disabled]="!user?.reviewingEnabled"
>
<fa-icon icon="plus"></fa-icon>
......@@ -78,13 +77,13 @@
data-target="#detailModal"
(click)="selectedResult = selectExercise(review.link!)"
>
<span class="d-none d-md-inline" jhiTranslate="review.create.view">View Resource</span>
<span class="d-none d-md-inline" jhiTranslate="review.create.view"> Resource</span>
</button>
</div>
</td>
<td>
<div *ngFor="let level of review.status">
<span class="badge badge-info">{{ level }}</span>
<span class="badge badge-info">{{ 'review.create.' + level | translate }}</span>
</div>
<div *ngIf="review.status?.length == 0 && !review.badgeRewarded">
<span class="badge badge-warning" jhiTranslate="review.create.requested">Review Requested</span>
......@@ -102,7 +101,7 @@
data-target="#detailModal3"
(click)="selectedReview = review"
>
<span class="d-none d-md-inline" jhiTranslate="review.create.comments">View comments</span>
<span class="d-none d-md-inline" jhiTranslate="review.create.comments"> comments</span>
</button>
</div>
</td>
......@@ -117,7 +116,7 @@
(click)="selectedReview = review; selectedStatus = review.status![0]"
>
<fa-icon icon="times"></fa-icon>
<span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit Review</span>
<span class="d-none d-md-inline" jhiTranslate="review.create.editReview">Edit Review</span>
</button>
<button
*ngIf="review.requestedBy == user?.email && review!.status?.includes('IMPROVEMENTS_REQUESTED')"
......@@ -148,7 +147,7 @@
</tr>
</ng-container>
</tbody>
<tbody *ngIf="otherReviews.length === 0">
<tbody *ngIf="otherReviews?.length === 0">
<tr>
<td colspan="6">
<div class="alert alert-warning">
......@@ -192,7 +191,7 @@
data-target="#detailModal"
(click)="selectedResult = selectExercise(review.link!)"
>
<span class="d-none d-md-inline" jhiTranslate="review.create.view">View Resource</span>
<span class="d-none d-md-inline" jhiTranslate="review.create.view"> Resource</span>
</button>
</div>
</td>
......@@ -216,7 +215,7 @@
data-target="#detailModal3"
(click)="selectedReview = review"
>
<span class="d-none d-md-inline" jhiTranslate="review.create.comments">View comments</span>
<span class="d-none d-md-inline" jhiTranslate="review.create.comments"> comments</span>
</button>
</div>
</td>
......@@ -262,7 +261,7 @@
</tr>
</ng-container>
</tbody>
<tbody *ngIf="userReviews.length === 0">
<tbody *ngIf="userReviews?.length === 0">
<tr>
<td colspan="6">
<div class="alert alert-warning">
......@@ -274,7 +273,7 @@
</table>
</div>
<jhi-exercise-modal-details [exercise]="selectedResult"></jhi-exercise-modal-details>
<jhi-exercise-modal-details [referencedExercise]="selectedResult"></jhi-exercise-modal-details>
<div>
<div class="modal fade" id="detailModal0">
<div class="modal-dialog modal-lg modal-dialog-centered">
......@@ -291,7 +290,7 @@
<label for="users" jhiTranslate="review.create.selectExercise">Select exercise:</label>
<jhi-multi-select-dropdown-exercise [list]="results" (shareExercise)="shareExercise($event)">
</jhi-multi-select-dropdown-exercise>
<div *ngIf="results.length === 0" class="alert alert-warning">
<div *ngIf="results?.length === 0" class="alert alert-warning">
<span jhiTranslate="review.create.noResourcesOne">No resources with publisher </span> {{ user?.email }}
<span jhiTranslate="review.create.noResourcesTwo"> found. Check if you have already shared resources.</span>
</div>
......@@ -334,14 +333,126 @@
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<label for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="selectedReview.comments![0]" rows="5"></textarea>
<label for="" jhiTranslate="review.create.changeStatus">Change Status</label>
<!-- New fields -->
<div class="pt-2">
<label *ngFor="let option of options" class="row">
<input type="checkbox" [checked]="selectedStatus === option" (change)="selectedStatus = option" />
<span class="pl-2">{{ option }}</span>
</label>
<label class="font-weight-bold" jhiTranslate="review.create.clarity">Clarity and Understandability:</label>
<div>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].descriptionIsClear" />
<span class="pl-2">{{ 'review.create.clarityQuestion1' | translate }}</span>
</label>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].requirementsAreClear" />
<span class="pl-2">{{ 'review.create.clarityQuestion2' | translate }}</span>
</label>
<label class="" for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea
class="form-control"
[(ngModel)]="selectedReview.comments![0].descriptionComment"
#descriptionCommentTextArea="ngModel"
maxlength="13000"
rows="5"
></textarea>
<p class="character-count">
{{ 'review.create.characters' | translate }} {{ 13000 - descriptionCommentTextArea.value?.length }}
</p>
</div>
<label class="font-weight-bold" jhiTranslate="review.create.completeness">Completeness:</label>
<div>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].informationRequiredComplete" />
<span class="pl-2">{{ 'review.create.completenessQuestion1' | translate }}</span>
</label>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].allMaterialsAvailable" />
<span class="pl-2">{{ 'review.create.completenessQuestion2' | translate }}</span>
</label>
<label class="" for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea
class="form-control"
[(ngModel)]="selectedReview.comments![0].informationRequiredComment"
#informationRequiredCommentTextArea="ngModel"
maxlength="13000"
rows="5"
></textarea>
<p class="character-count">
{{ 'review.create.characters' | translate }} {{ 13000 - informationRequiredCommentTextArea.value?.length }}
</p>
</div>
<label class="font-weight-bold" jhiTranslate="review.create.format">Format and Structure:</label>
<div>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].isStructured" />
<span class="pl-2">{{ 'review.create.formatQuestion1' | translate }}</span>
</label>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].subExercisesAreClear" />
<span class="pl-2">{{ 'review.create.formatQuestion2' | translate }}</span>
</label>
<label class="" for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea
class="form-control"
[(ngModel)]="selectedReview.comments![0].structuredComment"
#structuredCommentTextArea="ngModel"
maxlength="13000"
rows="5"
></textarea>
<p class="character-count">
{{ 'review.create.characters' | translate }} {{ 13000 - structuredCommentTextArea.value?.length }}
</p>
</div>
<label class="font-weight-bold" jhiTranslate="review.create.validity">Validity and Correctness:</label>
<div>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].solutionIsCorrect" />
<span class="pl-2">{{ 'review.create.validityQuestion1' | translate }}</span>
</label>
<label class="" for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea
class="form-control"
[(ngModel)]="selectedReview.comments![0].solutionComment"
#solutionCommentTextArea="ngModel"
maxlength="13000"
rows="5"
></textarea>
<p class="character-count">
{{ 'review.create.characters' | translate }} {{ 13000 - solutionCommentTextArea.value?.length }}
</p>
</div>
<label class="font-weight-bold" jhiTranslate="review.create.requirements">Requirements and Metadata:</label>
<div>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].metadataIsComplete" />
<span class="pl-2">{{ 'review.create.requirementsQuestion1' | translate }}</span>
</label>
<label class="row">
<input type="checkbox" [(ngModel)]="selectedReview.comments![0].metadataIsCorrect" />
<span class="pl-2">{{ 'review.create.requirementsQuestion2' | translate }}</span>
</label>
<label class="" for="" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea
class="form-control"
[(ngModel)]="selectedReview.comments![0].metadataComment"
#metadataCommentTextArea="ngModel"
maxlength="13000"
rows="5"
></textarea>
<p class="character-count">
{{ 'review.create.characters' | translate }} {{ 13000 - metadataCommentTextArea.value?.length }}
</p>
</div>
<div class="pt-2">
<label class="font-weight-bold" for="" jhiTranslate="review.create.changeStatus">Change Status</label>
<div *ngFor="let option of statusOptions" class="row">
<input type="checkbox" [checked]="selectedStatus === option.value" (change)="selectedStatus = option.value" />
<span class="pl-2">{{ option.translationKey | translate }}</span>
</div>
</div>
</div>
</div>
</div>
......@@ -368,16 +479,87 @@
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<div class="pb-3" *ngFor="let comment of selectedReview.comments; let i = index">
<label>{{ selectedReview.users![i] }}</label>
<textarea class="form-control" disabled rows="8">{{ comment }}</textarea>
<div class="form-group" *ngFor="let comment of selectedReview.comments; let i = index">
<!-- User name -->
<h5 class="pt-4">{{ selectedReview.users![i] }}</h5>
<!-- Clarity and Understandability -->
<label class="font-weight-bold pt-2" jhiTranslate="review.create.clarity">Clarity and Understandability:</label>
<div>
<div>
<input type="checkbox" [(ngModel)]="comment.descriptionIsClear" disabled />
<label class="pl-2">{{ 'review.create.clarityQuestion1' | translate }}</label>
</div>
<div>
<input type="checkbox" [(ngModel)]="comment.requirementsAreClear" disabled />
<label class="pl-2">{{ 'review.create.clarityQuestion2' | translate }}</label>
</div>
<label class="pt-2" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="comment.descriptionComment" disabled rows="5"></textarea>
</div>
<!-- Completeness -->
<label class="font-weight-bold pt-2" jhiTranslate="review.create.completeness">Completeness:</label>
<div>
<div>
<input type="checkbox" [(ngModel)]="comment.informationRequiredComplete" disabled />
<label class="pl-2">{{ 'review.create.completenessQuestion1' | translate }}</label>
</div>
<div>
<input type="checkbox" [(ngModel)]="comment.allMaterialsAvailable" disabled />
<label class="pl-2">{{ 'review.create.completenessQuestion2' | translate }}</label>
</div>
<label class="pt-2" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="comment.informationRequiredComment" disabled rows="5"></textarea>
</div>
<!-- Format and Structure -->
<label class="font-weight-bold pt-2" jhiTranslate="review.create.format">Format and Structure:</label>
<div>
<div>
<input type="checkbox" [(ngModel)]="comment.isStructured" disabled />
<label class="pl-2">{{ 'review.create.formatQuestion1' | translate }}</label>
</div>
<div>
<input type="checkbox" [(ngModel)]="comment.subExercisesAreClear" disabled />
<label class="pl-2">{{ 'review.create.formatQuestion2' | translate }}</label>
</div>
<label class="pt-2" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="comment.structuredComment" disabled rows="5"></textarea>
</div>
<!-- Validity and Correctness -->
<label class="font-weight-bold pt-2" jhiTranslate="review.create.validity">Validity and Correctness:</label>
<div>
<div>
<input type="checkbox" [(ngModel)]="comment.solutionIsCorrect" disabled />
<label class="pl-2">{{ 'review.create.validityQuestion1' | translate }}</label>
</div>
<label class="pt-2" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="comment.solutionComment" disabled rows="5"></textarea>
</div>
<!-- Requirements and Metadata -->
<label class="font-weight-bold pt-2" jhiTranslate="review.create.requirements">Requirements and Metadata:</label>
<div>
<div>
<input type="checkbox" [(ngModel)]="comment.metadataIsComplete" disabled />
<label class="pl-2">{{ 'review.create.requirementsQuestion1' | translate }}</label>
</div>
<div>
<input type="checkbox" [(ngModel)]="comment.metadataIsCorrect" disabled />
<label class="pl-2">{{ 'review.create.requirementsQuestion2' | translate }}</label>
</div>
<label class="pt-2" jhiTranslate="review.create.changeComment">Change Comment</label>
<textarea class="form-control" [(ngModel)]="comment.metadataComment" disabled rows="5"></textarea>
</div>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer"></div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" (click)="downloadPDF()">Download Feedback as PDF</button>
</div>
</div>
</div>
</div>
......
......@@ -8,3 +8,8 @@
.color {
background-color: slategray;
}
.custom-user-name {
font-size: 24px; /* adjust this value as needed */
font-weight: bold;
}