Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display global rating on ContestGlobalRatingView #1187

Merged
merged 22 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
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
8 changes: 6 additions & 2 deletions save-backend/backend-api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1764,7 +1764,7 @@
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Organization"
"$ref": "#/components/schemas/OrganizationDto"
}
}
}
Expand All @@ -1777,7 +1777,7 @@
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Organization"
"$ref": "#/components/schemas/OrganizationDto"
}
}
}
Expand Down Expand Up @@ -7166,6 +7166,10 @@
"VIEWER"
]
}
},
"globalRating": {
"type": "number",
"format": "double"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,20 @@ internal class OrganizationController(
description = "Get non-deleted organizations.",
)
@ApiResponse(responseCode = "200", description = "Successfully fetched non-deleted projects.")
petertrr marked this conversation as resolved.
Show resolved Hide resolved
fun getNotDeletedOrganizations(@RequestBody(required = false) organizationFilters: OrganizationFilters?) =
organizationService.getNotDeletedOrganizations(organizationFilters).toFlux()
fun getNotDeletedOrganizations(
@RequestBody(required = false) organizationFilters: OrganizationFilters?,
authentication: Authentication,
): Flux<OrganizationDto> =
organizationService.getNotDeletedOrganizations(organizationFilters)
.toFlux<Organization>()
.flatMap { organization ->
organizationService.getGlobalRating(organization.name, authentication).map {
organization to it
}
}
.map { (organization, rating) ->
organization.toDto().copy(globalRating = rating)
}

@GetMapping("/{organizationName}")
@PreAuthorize("permitAll()")
Expand Down Expand Up @@ -458,10 +470,7 @@ internal class OrganizationController(
"Could not find an organization with name $organizationName."
}
.flatMap {
projectService.getNotDeletedProjectsByOrganizationName(organizationName, authentication).collectList()
}
.map { projectsList ->
projectsList.sumOf { it.contestRating }
organizationService.getGlobalRating(organizationName, authentication)
}

private fun cleanupStorageData(testSuite: TestSuite) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.saveourtool.save.domain.OrganizationSaveStatus
import com.saveourtool.save.entities.Organization
import com.saveourtool.save.entities.OrganizationStatus
import com.saveourtool.save.filters.OrganizationFilters
import org.springframework.security.core.Authentication
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

Expand All @@ -15,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional
*/
@Service
class OrganizationService(
private val projectService: ProjectService,
private val organizationRepository: OrganizationRepository,
) {
/**
Expand Down Expand Up @@ -115,4 +117,16 @@ class OrganizationService(
* @return all organizations that were registered in SAVE
*/
fun findAll(): List<Organization> = organizationRepository.findAll()

/**
* @param organizationName
* @param authentication
* @return global rating of organization by name [organizationName] based on ratings of all projects under this organization
*/
fun getGlobalRating(organizationName: String, authentication: Authentication) =
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
projectService.getNotDeletedProjectsByOrganizationName(organizationName, authentication)
.collectList()
.map { projectsList ->
projectsList.sumOf { it.contestRating }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import kotlinx.serialization.Serializable
* @property description
* @property canCreateContests
* @property userRoles map where keys are usernames and values are their [Role]s
* @property globalRating
*/
@Serializable
data class OrganizationDto(
Expand All @@ -25,6 +26,7 @@ data class OrganizationDto(
val description: String = "",
val canCreateContests: Boolean = false,
val userRoles: Map<String, Role> = emptyMap(),
val globalRating: Double? = null,
Fixed Show fixed Hide fixed
) : Validatable {
/**
* Validation of organization name
Expand All @@ -47,12 +49,13 @@ data class OrganizationDto(
* Value that represents an empty [OrganizationDto]
*/
val empty = OrganizationDto(
"",
null,
null,
"",
false,
emptyMap(),
name = "",
dateCreated = null,
avatar = null,
description = "",
canCreateContests = false,
userRoles = emptyMap(),
globalRating = null,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package com.saveourtool.save.frontend.components.basic

import com.saveourtool.save.frontend.utils.toFixed
import csstype.*
import react.FC
import react.Props
Expand Down Expand Up @@ -80,7 +81,7 @@ private fun scoreCard() = FC<ScoreCardProps> { props ->
alignItems = AlignItems.center
alignSelf = AlignSelf.start
}
+"${props.contestScore}"
+"${props.contestScore.toFixed(2)}"
}
}
div {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
package com.saveourtool.save.frontend.components.views.contests

import com.saveourtool.save.domain.Role
import com.saveourtool.save.entities.Organization
import com.saveourtool.save.entities.OrganizationDto
import com.saveourtool.save.entities.Project
import com.saveourtool.save.filters.OrganizationFilters
import com.saveourtool.save.filters.ProjectFilters
Expand Down Expand Up @@ -63,7 +63,7 @@ external interface ContestGlobalRatingViewState : State, HasSelectedMenu<UserRat
/**
* All organizations
*/
var organizations: Array<Organization>
var organizations: Array<OrganizationDto>

/**
* All projects
Expand Down Expand Up @@ -91,7 +91,7 @@ class ContestGlobalRatingView : AbstractView<ContestGlobalRatingProps, ContestGl
"STRING_TEMPLATE_QUOTES",
)
private val tableWithOrganizationRating = tableComponent(
columns = columns<Organization> {
columns = columns<OrganizationDto> {
column(id = "index", header = "Position") {
Fragment.create {
td {
Expand Down Expand Up @@ -121,10 +121,10 @@ class ContestGlobalRatingView : AbstractView<ContestGlobalRatingProps, ContestGl
}
}
}
column(id = "rating", header = "Rating") {
column(id = "rating", header = "Rating") { cellProps ->
Fragment.create {
td {
+"4560"
+"${cellProps.value.globalRating?.toFixed(2)}"
}
}
}
Expand Down Expand Up @@ -185,10 +185,10 @@ class ContestGlobalRatingView : AbstractView<ContestGlobalRatingProps, ContestGl
}
}
}
column(id = "rating", header = "Rating") {
column(id = "rating", header = "Rating") { cellProps ->
Fragment.create {
td {
+"1370"
+"${cellProps.value.contestRating.toFixed(2)}"
}
}
}
Expand Down Expand Up @@ -236,7 +236,7 @@ class ContestGlobalRatingView : AbstractView<ContestGlobalRatingProps, ContestGl

private fun getOrganization(filterValue: OrganizationFilters) {
scope.launch {
val organizationsFromBackend: List<Organization> = post(
val organizationsFromBackend: List<OrganizationDto> = post(
url = "$apiUrl/organizations/not-deleted",
headers = jsonHeaders,
body = Json.encodeToString(filterValue),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

package com.saveourtool.save.frontend.components.views.contests

import com.saveourtool.save.entities.Organization
import com.saveourtool.save.entities.OrganizationDto
import com.saveourtool.save.entities.Project
import com.saveourtool.save.frontend.TabMenuBar
import com.saveourtool.save.frontend.externals.fontawesome.faArrowRight
Expand Down Expand Up @@ -39,7 +39,7 @@ enum class UserRatingTab {

companion object : TabMenuBar<UserRatingTab> {
// The string is the postfix of a [regexForUrlClassification] for parsing the url
private val postfixInRegex = values().map { it.name.lowercase() }.joinToString("|")
private val postfixInRegex = values().joinToString("|") { it.name.lowercase() }
override val nameOfTheHeadUrlSection = ""
override val defaultTab: UserRatingTab = UserRatingTab.ORGS
override val regexForUrlClassification = Regex("/${FrontendRoutes.CONTESTS_GLOBAL_RATING.path}/($postfixInRegex)")
Expand Down Expand Up @@ -76,18 +76,17 @@ private fun ChildrenBuilder.renderingProjectChampionsTable(projects: Set<Project
}
}

// FixMe: add rating after kirill's changes
div {
className = ClassName("col-lg-4")
p {
+"4560"
+"${project.contestRating.toFixed(2)}"
}
}
}
}
}

private fun ChildrenBuilder.renderingOrganizationChampionsTable(organizations: Set<Organization>) {
private fun ChildrenBuilder.renderingOrganizationChampionsTable(organizations: Set<OrganizationDto>) {
organizations.forEachIndexed { i, organization ->
div {
className = ClassName("row text-muted pb-3 mb-3 border-bottom border-gray mx-2")
Expand Down Expand Up @@ -115,11 +114,10 @@ private fun ChildrenBuilder.renderingOrganizationChampionsTable(organizations: S
}
}

// FixMe: add rating after kirill's changes
div {
className = ClassName("col-lg-4")
p {
+"4560"
+"${organization.globalRating?.toFixed(2)}"
}
}
}
Expand All @@ -133,9 +131,9 @@ private fun ChildrenBuilder.renderingOrganizationChampionsTable(organizations: S
private fun userRating() = VFC {
val (selectedTab, setSelectedTab) = useState(UserRatingTab.ORGS)

val (organizations, setOrganizations) = useState<Set<Organization>>(emptySet())
val (organizations, setOrganizations) = useState<Set<OrganizationDto>>(emptySet())
useRequest {
val organizationsFromBackend: List<Organization> = post(
val organizationsFromBackend: List<OrganizationDto> = post(
url = "$apiUrl/organizations/not-deleted",
headers = jsonHeaders,
body = undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,8 @@ internal fun ChildrenBuilder.multilineTextWithIndices(text: String) {
* @return true if string is invalid
*/
internal fun String?.isInvalid(maxLength: Int) = this.isNullOrBlank() || this.contains(" ") || this.length > maxLength

/**
* @param digits number of digits to round to
*/
internal fun Double.toFixed(digits: Int) = asDynamic().toFixed(digits)