Skip to content

Commit aad9984

Browse files
committed
Add support for filtering code references by values in 'extras'
1 parent 35d9943 commit aad9984

File tree

1 file changed

+123
-30
lines changed

1 file changed

+123
-30
lines changed

invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/CodeReferencesReportPage.kt

Lines changed: 123 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ import com.squareup.invert.models.ModulePath
2222
import com.squareup.invert.models.OwnerName
2323
import com.squareup.invert.models.StatKey
2424
import com.squareup.invert.models.StatMetadata
25+
import org.jetbrains.compose.web.css.CSSUnit
2526
import org.jetbrains.compose.web.dom.H1
2627
import org.jetbrains.compose.web.dom.H3
2728
import org.jetbrains.compose.web.dom.H4
29+
import org.jetbrains.compose.web.dom.H5
2830
import org.jetbrains.compose.web.dom.Li
2931
import org.jetbrains.compose.web.dom.P
3032
import org.jetbrains.compose.web.dom.Text
@@ -46,6 +48,7 @@ data class CodeReferencesNavRoute(
4648
val module: String? = null,
4749
val treemap: Boolean? = null,
4850
val chart: Boolean? = null,
51+
val extras: Map<String, String>? = null
4952
) : BaseNavRoute(CodeReferencesReportPage.navPage) {
5053

5154
override fun toSearchParams(): Map<String, String> = toParamsWithOnlyPageId(this)
@@ -65,6 +68,11 @@ data class CodeReferencesNavRoute(
6568
chart?.let {
6669
params[CHART_PARAM] = chart.toString()
6770
}
71+
extras?.let {
72+
it.forEach { (key, value) ->
73+
params["extra_$key"] = value
74+
}
75+
}
6876
}
6977

7078
companion object {
@@ -74,37 +82,51 @@ data class CodeReferencesNavRoute(
7482
private const val OWNER_PARAM = "owner"
7583
private const val MODULE_PARAM = "module"
7684
private const val TREEMAP_PARAM = "treemap"
85+
private const val EXTRAS_PARAM_PREFIX = "extra_"
86+
7787

7888
fun parser(params: Map<String, String?>): NavRoute {
79-
val statKey = params[STATKEY_PARAM]
80-
val owner = params[OWNER_PARAM]?.trim()?.let {
81-
if (it.isNotBlank()) {
82-
it
83-
} else {
84-
null
85-
}
86-
}
87-
val module = params[MODULE_PARAM]?.trim()?.let {
88-
if (it.isNotBlank()) {
89-
it
90-
} else {
91-
null
92-
}
93-
}
94-
val treemap = params[TREEMAP_PARAM]?.trim()?.let {
95-
if (it.isNotBlank()) {
96-
it.toBoolean()
97-
} else {
98-
null
89+
var statKey: String? = null
90+
var owner: String? = null
91+
var module: String? = null
92+
var treemap: Boolean? = null
93+
var chart: Boolean? = null
94+
var extras: MutableMap<String, String> = mutableMapOf()
95+
params.forEach { (key, value) ->
96+
val trimmedValue = value?.trim()?.let {
97+
if (it.isNotBlank()) {
98+
it
99+
} else {
100+
null
101+
}
99102
}
100-
}
101-
val chart = params[CHART_PARAM]?.trim()?.let {
102-
if (it.isNotBlank()) {
103-
it.toBoolean()
104-
} else {
105-
null
103+
if (trimmedValue != null) {
104+
when (key) {
105+
STATKEY_PARAM -> {
106+
statKey = trimmedValue
107+
}
108+
OWNER_PARAM -> {
109+
owner = trimmedValue
110+
}
111+
MODULE_PARAM -> {
112+
module = trimmedValue
113+
}
114+
TREEMAP_PARAM -> {
115+
treemap = trimmedValue.toBoolean()
116+
}
117+
CHART_PARAM -> {
118+
chart = trimmedValue.toBoolean()
119+
}
120+
else -> {
121+
if (key.startsWith(EXTRAS_PARAM_PREFIX)) {
122+
val extraKey = key.substring(EXTRAS_PARAM_PREFIX.length)
123+
extras[extraKey] = trimmedValue
124+
}
125+
}
126+
}
106127
}
107128
}
129+
108130
return if (statKey == null) {
109131
AllStatsNavRoute()
110132
} else {
@@ -114,6 +136,7 @@ data class CodeReferencesNavRoute(
114136
module = module,
115137
treemap = treemap,
116138
chart = chart,
139+
extras = extras.let { if (it.isEmpty()) null else it }
117140
)
118141
}
119142
}
@@ -293,6 +316,18 @@ fun CodeReferencesComposable(
293316
true
294317
}
295318
}
319+
// Filter by extras
320+
.filter { ownerAndCodeReference: ModuleOwnerAndCodeReference ->
321+
val codeReference = ownerAndCodeReference.codeReference
322+
val extras = codeReferencesNavRoute.extras ?: mapOf()
323+
if (extras.isEmpty()) {
324+
true
325+
} else {
326+
extras.all { (key, value) ->
327+
codeReference.extras[key] == value
328+
}
329+
}
330+
}
296331

297332
if (codeReferencesNavRoute.treemap == true) {
298333
BootstrapRow {
@@ -337,12 +372,18 @@ fun CodeReferencesComposable(
337372
}
338373
}
339374

375+
BootstrapRow {
376+
H3 {
377+
Text("Filters")
378+
}
379+
}
380+
340381
val codeReferencesByOwner = allCodeReferencesForStat.groupBy { it.owner }
341382
val totalCodeReferenceCount = allCodeReferencesForStat.size
342383
BootstrapRow {
343384
BootstrapColumn(6) {
344-
H3 {
345-
Text("Filter by Owner")
385+
H5 {
386+
Text("Owner")
346387
BootstrapSelectDropdown(
347388
placeholderText = "-- All Owners ($totalCodeReferenceCount Total) --",
348389
currentValue = codeReferencesNavRoute.owner,
@@ -364,8 +405,8 @@ fun CodeReferencesComposable(
364405
val codeReferencesByModule =
365406
allCodeReferencesForStat.groupBy { it.module }
366407
BootstrapColumn(6) {
367-
H3 {
368-
Text("Filter by Module")
408+
H5 {
409+
Text("Module")
369410
BootstrapSelectDropdown(
370411
placeholderText = "-- All Modules --",// (${codeReferencesByModule.size} Total) --",
371412
currentValue = codeReferencesNavRoute.module,
@@ -385,6 +426,58 @@ fun CodeReferencesComposable(
385426
}
386427
}
387428
}
429+
// Limit filterable extras to ones where the amount of possible values is within a reasonable limit
430+
val filterableExtraCountLimit = 5000
431+
val allExtraValuesByKey = allCodeReferencesForStat.flatMap {
432+
it.codeReference.extras.entries.toList()
433+
}.groupBy { it.key }.mapValues { it.value.map { entry -> entry.value }.toSet().sorted() }
434+
val filterableExtras = currentStatMetadata.extras.filter {
435+
val extraValues = allExtraValuesByKey[it.key] ?: emptyList()
436+
(it.type == ExtraDataType.STRING || it.type == ExtraDataType.BOOLEAN) &&
437+
extraValues.size < filterableExtraCountLimit
438+
}.sortedBy { it.description }
439+
if (filterableExtras.isNotEmpty()) {
440+
filterableExtras.chunked(size = 2).map { extraGroup ->
441+
BootstrapRow {
442+
extraGroup.forEach { extra ->
443+
BootstrapColumn(6) {
444+
H5 {
445+
Text(extra.description)
446+
BootstrapSelectDropdown(
447+
placeholderText = "-- All Values --",
448+
currentValue = codeReferencesNavRoute.extras?.get(extra.key),
449+
options = allCodeReferencesForStat.mapNotNull {
450+
it.codeReference.extras[extra.key]
451+
}.toSet().map {
452+
BootstrapSelectOption(
453+
value = it,
454+
displayText = it,
455+
)
456+
}.sortedBy { it.displayText }
457+
) {
458+
val value = it?.value
459+
var newExtras: Map<String, String>? = null
460+
val currentExtras = codeReferencesNavRoute.extras ?: mapOf()
461+
if (value != null) {
462+
newExtras = currentExtras + mapOf(extra.key to value)
463+
} else {
464+
newExtras = currentExtras.minus(extra.key)
465+
if (newExtras.isEmpty()) {
466+
newExtras = null
467+
}
468+
}
469+
navRouteRepo.pushNavRoute(
470+
codeReferencesNavRoute.copy(
471+
extras = newExtras
472+
)
473+
)
474+
}
475+
}
476+
}
477+
}
478+
}
479+
}
480+
}
388481

389482
BootstrapTable(
390483
headers = listOf(

0 commit comments

Comments
 (0)