From 4358da496312eb11665cfbc35734dd3629ab9e8b Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Tue, 12 Nov 2024 09:44:33 -0500 Subject: [PATCH] Ability to filter Code References by Owner --- .../src/jsMain/kotlin/MainComposables.kt | 5 +- .../squareup/invert/common/charts/ChartsJs.kt | 8 +- .../common/navigation/NavRouteManager.kt | 2 +- .../common/pages/CodeReferencesReportPage.kt | 75 ++++++++++++++++--- .../history/JavaScriptNavigationAndHistory.kt | 18 +++-- .../jsMain/kotlin/ui/BootstrapComposables.kt | 10 ++- 6 files changed, 92 insertions(+), 26 deletions(-) diff --git a/invert-report/src/jsMain/kotlin/MainComposables.kt b/invert-report/src/jsMain/kotlin/MainComposables.kt index 52e4d15..2e7b484 100644 --- a/invert-report/src/jsMain/kotlin/MainComposables.kt +++ b/invert-report/src/jsMain/kotlin/MainComposables.kt @@ -57,13 +57,14 @@ fun invertComposeMain( @OptIn(DelicateCoroutinesApi::class) fun setupNavigation(routeManager: NavRouteManager, navRouteRepo: NavRouteRepo) { + val javaScriptNavigationAndHistory = JavaScriptNavigationAndHistory(routeManager, navRouteRepo) // Update Route on Every Change navRouteRepo.navRoute.onEach { - JavaScriptNavigationAndHistory.setUrlFromNavRoute(it) + javaScriptNavigationAndHistory.setUrlFromNavRoute(it) }.launchIn(GlobalScope) // Register for Browser Back/Forward Button Events - JavaScriptNavigationAndHistory.registerForPopstate(routeManager, navRouteRepo) + javaScriptNavigationAndHistory.registerForPopstate() } @Composable diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/charts/ChartsJs.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/charts/ChartsJs.kt index f798a7f..cd14891 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/charts/ChartsJs.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/charts/ChartsJs.kt @@ -40,14 +40,14 @@ object ChartsJs { @Serializable data class ChartJsDataset( val label: String, - val data: List, + val data: Collection, val borderWidth: Int = 1, ) @Serializable data class ChartJsData( - val labels: List, - val datasets: List, + val labels: Collection, + val datasets: Collection, ) @Serializable @@ -73,7 +73,7 @@ private fun ChartJsComposable( style(LineStyle.Solid) color = Color.black } - maxHeight(300.px) + maxHeight(400.px) maxWidth(100.percent) } }) diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavRouteManager.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavRouteManager.kt index bd2bb54..4b877db 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavRouteManager.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavRouteManager.kt @@ -3,7 +3,7 @@ package com.squareup.invert.common.navigation import androidx.compose.runtime.Composable import com.squareup.invert.common.navigation.routes.BaseNavRoute import com.squareup.invert.common.pages.HomeReportPage -import history.JavaScriptNavigationAndHistory.toMap +import history.JavaScriptNavigationAndHistory.Companion.toMap import org.w3c.dom.url.URL import kotlin.reflect.KClass import kotlin.reflect.cast diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/CodeReferencesReportPage.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/CodeReferencesReportPage.kt index 519a282..237f297 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/CodeReferencesReportPage.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/CodeReferencesReportPage.kt @@ -32,6 +32,7 @@ import kotlin.reflect.KClass data class CodeReferencesNavRoute( val statKey: String? = null, val owner: String? = null, + val module: String? = null, ) : BaseNavRoute(CodeReferencesReportPage.navPage) { override fun toSearchParams(): Map = toParamsWithOnlyPageId(this) @@ -42,12 +43,16 @@ data class CodeReferencesNavRoute( if (!owner.isNullOrBlank()) { params[OWNER_PARAM] = owner } + if (!module.isNullOrBlank()) { + params[MODULE_PARAM] = module + } } companion object { private const val STATKEY_PARAM = "statkey" private const val OWNER_PARAM = "owner" + private const val MODULE_PARAM = "module" fun parser(params: Map): CodeReferencesNavRoute { val statKey = params[STATKEY_PARAM] @@ -58,9 +63,17 @@ data class CodeReferencesNavRoute( null } } + val module = params[MODULE_PARAM]?.trim()?.let { + if (it.isNotBlank()) { + it + } else { + null + } + } return CodeReferencesNavRoute( statKey = statKey, owner = owner, + module = module, ) } } @@ -168,32 +181,76 @@ fun CodeReferencesComposable( } val filteredByOwner: List = allCodeReferencesForStat + // Filter By Module + .filter { moduleOwnerAndCodeReference: ModuleOwnerAndCodeReference -> + val moduleFromModule = moduleOwnerAndCodeReference.module + val moduleFromNavRoute = codeReferencesNavRoute.module + if (!moduleFromNavRoute.isNullOrBlank()) { + moduleFromNavRoute == moduleOwnerAndCodeReference.module || moduleFromNavRoute == moduleFromModule + } else { + true + } + + } + // Filter by Owner .filter { ownerAndCodeReference: ModuleOwnerAndCodeReference -> - if (!codeReferencesNavRoute.owner.isNullOrBlank()) { - ownerAndCodeReference.codeReference.owner == codeReferencesNavRoute.owner || codeReferencesNavRoute.owner == ownerAndCodeReference.owner + val ownerOfModule = ownerAndCodeReference.owner + val codeReferenceOwner = ownerAndCodeReference.codeReference.owner + val ownerFromNavRoute = codeReferencesNavRoute.owner + if (!ownerFromNavRoute.isNullOrBlank()) { + ownerFromNavRoute == codeReferenceOwner || ownerFromNavRoute == ownerOfModule } else { true } } val codeReferencesByOwner = allCodeReferencesForStat.groupBy { it.owner } - val totalCount = allCodeReferencesForStat.size + val totalCodeReferenceCount = allCodeReferencesForStat.size BootstrapRow { - BootstrapColumn(12) { + BootstrapColumn(6) { H3 { Text("Filter by Owner") BootstrapSelectDropdown( - placeholderText = "-- All Owners ($totalCount Total) --", - currentValue = codeReferencesNavRoute.owner ?: "", + placeholderText = "-- All Owners ($totalCodeReferenceCount Total) --", + currentValue = codeReferencesNavRoute.owner, options = codeReferencesByOwner.map { BootstrapSelectOption( value = it.key, - displayText = "${it.key} (${it.value.size} of $totalCount)" + displayText = "${it.key} (${it.value.size} of $totalCodeReferenceCount)" + ) + }.sortedBy { it.displayText } + ) { + navRouteRepo.updateNavRoute( + CodeReferencesNavRoute( + statKey = statKey, + owner = it?.value, + module = codeReferencesNavRoute.module, + ) + ) + } + } + } + val codeReferencesByModule = + allCodeReferencesForStat.groupBy { it.module } + BootstrapColumn(6) { + H3 { + Text("Filter by Module") + BootstrapSelectDropdown( + placeholderText = "-- All Modules --",// (${codeReferencesByModule.size} Total) --", + currentValue = codeReferencesNavRoute.module, + options = codeReferencesByModule.map { + BootstrapSelectOption( + value = it.key, + displayText = "${it.key}",// (${it.value.size} of $totalCodeReferenceCount)" ) }.sortedBy { it.displayText } ) { navRouteRepo.updateNavRoute( - codeReferencesNavRoute.copy(owner = it) + CodeReferencesNavRoute( + statKey = codeReferencesNavRoute.statKey, + owner = codeReferencesNavRoute.owner, + module = it?.value + ) ) } } @@ -207,7 +264,7 @@ fun CodeReferencesComposable( val listOfExtraValues: List = extraKeys.map { key -> it.codeReference.extras[key] ?: "" } listOf( it.module, - it.codeReference.owner ?: (it.owner + " (Module Owner)"), + it.codeReference.owner ?: (it.owner + " (Owns Module)"), it.codeReference.toHrefLink(projectMetadata!!, false), it.codeReference.code ?: "" ) + listOfExtraValues diff --git a/invert-report/src/jsMain/kotlin/history/JavaScriptNavigationAndHistory.kt b/invert-report/src/jsMain/kotlin/history/JavaScriptNavigationAndHistory.kt index 4a31376..c2e9bb0 100644 --- a/invert-report/src/jsMain/kotlin/history/JavaScriptNavigationAndHistory.kt +++ b/invert-report/src/jsMain/kotlin/history/JavaScriptNavigationAndHistory.kt @@ -15,14 +15,20 @@ import org.w3c.dom.PopStateEvent import org.w3c.dom.url.URL import org.w3c.dom.url.URLSearchParams -object JavaScriptNavigationAndHistory { - fun URLSearchParams.toMap(): Map { - val map = mutableMapOf() - keysForObject(this).forEach { map[it] = this.get(it) } - return map +class JavaScriptNavigationAndHistory( + private val routeManager: NavRouteManager, + private val navRouteRepo: NavRouteRepo +) { + + companion object { + fun URLSearchParams.toMap(): Map { + val map = mutableMapOf() + keysForObject(this).forEach { map[it] = this.get(it) } + return map + } } - fun registerForPopstate(routeManager: NavRouteManager, navRouteRepo: NavRouteRepo) { + fun registerForPopstate() { window.addEventListener("popstate", { Log.d("History Event Count: ${window.history.length}") if (it is PopStateEvent) { diff --git a/invert-report/src/jsMain/kotlin/ui/BootstrapComposables.kt b/invert-report/src/jsMain/kotlin/ui/BootstrapComposables.kt index 270ee4f..581b2fb 100644 --- a/invert-report/src/jsMain/kotlin/ui/BootstrapComposables.kt +++ b/invert-report/src/jsMain/kotlin/ui/BootstrapComposables.kt @@ -521,14 +521,16 @@ data class BootstrapSelectOption( fun BootstrapSelectDropdown( placeholderText: String, options: List, - currentValue: String, - onValueChange: (String?) -> Unit + currentValue: String?, + onValueChange: (BootstrapSelectOption?) -> Unit ) { Select({ classes(listOf("form-select")) attr("aria-label", placeholderText) - attr("value", currentValue) - onChange { event -> onValueChange(event.value) } + currentValue?.let { + attr("value", currentValue) + } + onChange { event -> onValueChange(options.firstOrNull { event.value == it.value }) } }) { Option(value = "") { Text(placeholderText)