Skip to content

Commit

Permalink
ContestSummaryMenu improvements
Browse files Browse the repository at this point in the history
### What's done:
 * Slightly improved `ContestSummaryMenu`
 * Fixed styles for execution labels for non-contest executions.

(#1035)
  • Loading branch information
sanyavertolet committed Aug 26, 2022
1 parent 2129944 commit 6bd8557
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,17 @@ internal class ExecutionStatisticsValues(executionDto: ExecutionDto?) {
* Function that renders Project version label, execution statistics label, pass rate label and rerun button.
* Rerun button is rendered only if [onRerunExecution] is provided.
*
* @param executionDto
* @param executionDto execution that should be used as data source
* @param isContest flag that defines whether to use contest styles or not
* @param classes [ClassName]s that will be applied to highest div
* @param innerClasses [ClassName]s that will be applied to each label
* @param height height of label
* @param onRerunExecution
*/
@Suppress("TOO_MANY_PARAMETERS", "LongParameterList")
fun ChildrenBuilder.displayExecutionInfoHeader(
executionDto: ExecutionDto?,
isContest: Boolean,
classes: String = "",
innerClasses: String = "col flex-wrap m-2",
height: String = "h-100",
Expand All @@ -145,29 +148,32 @@ fun ChildrenBuilder.displayExecutionInfoHeader(
val relativeWidth = onRerunExecution?.let { "min-vw-25" } ?: "min-vw-33"
div {
className = ClassName(classes)
displayProjectVersion(executionDto, "$relativeWidth $innerClasses", height)
displayPassRate(executionDto, "$relativeWidth $innerClasses", height)
displayStatistics(executionDto, "$relativeWidth $innerClasses", height)
displayRerunExecutionButton(executionDto, "$relativeWidth $innerClasses", height, onRerunExecution)
displayProjectVersion(executionDto, isContest, "$relativeWidth $innerClasses", height)
displayPassRate(executionDto, isContest, "$relativeWidth $innerClasses", height)
displayStatistics(executionDto, isContest, "$relativeWidth $innerClasses", height)
displayRerunExecutionButton(executionDto, isContest, "$relativeWidth $innerClasses", height, onRerunExecution)
}
}

/**
* Function that renders Rerun execution button
*
* @param executionDto
* @param executionDto execution that should be used as data source
* @param isContest flag that defines whether to use contest styles or not
* @param classes [ClassName]s that will be applied to highest div
* @param height height of label
* @param onRerunExecution onClick callback
*/
fun ChildrenBuilder.displayRerunExecutionButton(
executionDto: ExecutionDto?,
isContest: Boolean,
classes: String = "",
height: String = "h-100",
onRerunExecution: ((MouseEvent<HTMLAnchorElement, *>) -> Unit)?,
) {
onRerunExecution?.let {
val borderColor = when {
!isContest -> "info"
executionDto == null -> "secondary"
executionDto.status == ExecutionStatus.ERROR || executionDto.failedTests != 0L -> "danger"
executionDto.status == ExecutionStatus.RUNNING || executionDto.status == ExecutionStatus.PENDING -> "info"
Expand Down Expand Up @@ -198,16 +204,19 @@ fun ChildrenBuilder.displayRerunExecutionButton(
/**
* Function that renders label with project version
*
* @param executionDto
* @param executionDto execution that should be used as data source
* @param isContest flag that defines whether to use contest styles or not
* @param classes [ClassName]s that will be applied to highest div
* @param height height of label
*/
fun ChildrenBuilder.displayProjectVersion(
executionDto: ExecutionDto?,
isContest: Boolean,
classes: String = "",
height: String = "h-100",
) {
val statusColor = when {
!isContest -> "bg-info"
executionDto == null -> "bg-secondary"
executionDto.status == ExecutionStatus.ERROR || executionDto.failedTests != 0L -> "bg-danger"
executionDto.status == ExecutionStatus.RUNNING || executionDto.status == ExecutionStatus.PENDING -> "bg-info"
Expand All @@ -233,7 +242,7 @@ fun ChildrenBuilder.displayProjectVersion(
/**
* A function that displays a GIF if tests not found
*
* @param executionDto
* @param executionDto execution that should be used as data source
*/
fun ChildrenBuilder.displayTestNotFound(executionDto: ExecutionDto?) {
val count = executionDto?.allTests
Expand Down Expand Up @@ -266,21 +275,28 @@ fun ChildrenBuilder.displayTestNotFound(executionDto: ExecutionDto?) {
/**
* Function that renders pass rate label
*
* @param executionDto
* @param executionDto execution that should be used as data source
* @param isContest flag that defines whether to use contest styles or not
* @param classes [ClassName]s that will be applied to highest div
* @param height height of label
*/
@Suppress("MAGIC_NUMBER", "TOO_LONG_FUNCTION")
fun ChildrenBuilder.displayPassRate(
executionDto: ExecutionDto?,
isContest: Boolean,
classes: String = "",
height: String = "h-100",
) {
val values = ExecutionStatisticsValues(executionDto)
div {
className = ClassName(classes)
val styles = if (isContest) {
values.style
} else {
"info"
}
div {
className = ClassName("card border-left-${values.style} shadow $height py-2")
className = ClassName("card border-left-$styles shadow $height py-2")
div {
className = ClassName("card-body")
div {
Expand Down Expand Up @@ -333,13 +349,15 @@ fun ChildrenBuilder.displayPassRate(
/**
* Function that renders execution statistics label
*
* @param executionDto
* @param executionDto execution that should be used as data source
* @param isContest flag that defines whether to use contest styles or not
* @param classes [ClassName]s that will be applied to highest div
* @param height height of label
*/
@Suppress("TOO_LONG_FUNCTION", "LongMethod")
fun ChildrenBuilder.displayStatistics(
executionDto: ExecutionDto?,
isContest: Boolean,
classes: String = "",
height: String = "h-100",
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
package com.saveourtool.save.frontend.components.basic.contests

import com.saveourtool.save.entities.ContestResult
import com.saveourtool.save.frontend.components.basic.scoreCard
import com.saveourtool.save.frontend.utils.*

import csstype.*
Expand All @@ -12,6 +11,8 @@ import react.*
import react.dom.html.ReactHTML.a
import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.h6
import react.dom.html.ReactHTML.li
import react.dom.html.ReactHTML.ul

import kotlinx.js.jso

Expand All @@ -30,6 +31,72 @@ external interface ContestSummaryMenuProps : Props {
var contestName: String
}

private fun ChildrenBuilder.displayTopProjects(sortedResults: List<ContestResult>) {
ul {
className = ClassName("col-10 mb-2 list-group")
displayResult(
"Top position",
"Project",
"Organization",
"Score",
null
)
sortedResults.filter {
it.score != null
}
.forEachIndexed { index, contestResult ->
displayResult(
"${index + 1}. ",
contestResult.projectName,
contestResult.organizationName,
contestResult.score.toString(),
"#/${contestResult.organizationName}/${contestResult.projectName}"
)
}
}
}

private fun ChildrenBuilder.displayResult(
topPositionLabel: String,
projectName: String,
organizationName: String,
score: String,
linkToProject: String?,
) {
li {
val disabled = linkToProject?.let { "" } ?: "disabled bg-light"
className = ClassName("list-group-item $disabled")
linkToProject?.let {
a {
href = it
className = ClassName("stretched-link")
}
}
div {
className = ClassName("d-flex justify-content-between")
div {
className = ClassName("row col")
div {
className = ClassName("mr-1 col text-left")
+topPositionLabel
}
div {
className = ClassName("ml-1 col text-center")
+projectName
}
}
div {
className = ClassName("col text-center")
+organizationName
}
div {
className = ClassName("col-1 text-right")
+score
}
}
}
}

/**
* @return ReactElement
*/
Expand All @@ -40,9 +107,9 @@ external interface ContestSummaryMenuProps : Props {
"AVOID_NULL_CHECKS"
)
private fun contestSummaryMenu() = FC<ContestSummaryMenuProps> { props ->
val (results, setResults) = useState<List<ContestResult>>(emptyList())
val (sortedResults, setSortedResults) = useState<List<ContestResult>>(emptyList())
useRequest {
val projectResults = get(
val results = get(
url = "$apiUrl/contests/${props.contestName}/scores",
headers = Headers().also {
it.set("Accept", "application/json")
Expand All @@ -53,7 +120,7 @@ private fun contestSummaryMenu() = FC<ContestSummaryMenuProps> { props ->
it.decodeFromJsonString<Array<ContestResult>>()
}
.sortedByDescending { it.score }
setResults(projectResults)
setSortedResults(results)
}
div {
className = ClassName("mb-3")
Expand All @@ -63,24 +130,13 @@ private fun contestSummaryMenu() = FC<ContestSummaryMenuProps> { props ->
flexDirection = FlexDirection.column
alignItems = AlignItems.center
}
if (results.isEmpty()) {
if (sortedResults.isEmpty()) {
h6 {
className = ClassName("text-center")
+"There are no participants yet. You can be the first one to participate in it!"
}
}
results.forEach { contestResult ->
div {
className = ClassName("col-10 mb-2")
a {
href = "#/${contestResult.organizationName}/${contestResult.projectName}"
className = ClassName("stretched-link")
}
scoreCard {
name = "${contestResult.organizationName}/${contestResult.projectName}"
contestScore = contestResult.score ?: 0.0
}
}
} else {
displayTopProjects(sortedResults)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class ContestExecutionView : AbstractView<ContestExecutionViewProps, State>(fals
colSpan = tableInstance.columns.size
div {
className = ClassName("row")
displayExecutionInfoHeader(row.original, "row col-11")
displayExecutionInfoHeader(row.original, true, "row col-11")
div {
className = ClassName("col-1")
pieChart(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class ExecutionView : AbstractView<ExecutionProps, ExecutionState>(false) {
override fun ChildrenBuilder.render() {
div {
div {
displayExecutionInfoHeader(state.executionDto, "row mb-2") { event ->
displayExecutionInfoHeader(state.executionDto, false, "row mb-2") { event ->
scope.launch {
val response = post(
"$apiUrl/run/re-trigger?executionId=${props.executionId}",
Expand Down

0 comments on commit 6bd8557

Please sign in to comment.