Skip to content

Commit

Permalink
Add Guice Tab to Misk admin dashboard
Browse files Browse the repository at this point in the history
The new Guice tab includes a searchable table to more easily look up a
type and find where it is being bound and other relevant DI metadata.

![Screenshot 2024-07-25 at 11 11
31 AM](https://github.com/user-attachments/assets/eb64cb0d-07ec-4a86-ae65-5226bab88083)

---------

Co-authored-by: David Amar <[email protected]>
GitOrigin-RevId: 578885bb01f8e9d1d3529d54c23bcfeb9ce57bd7
  • Loading branch information
2 people authored and svc-squareup-copybara committed Jul 25, 2024
1 parent e019b30 commit 918a819
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 113 deletions.
14 changes: 14 additions & 0 deletions misk-admin/api/misk-admin.api
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,20 @@ public final class misk/web/metadata/database/DatabaseQueryMetadataAction$Respon
public abstract interface annotation class misk/web/metadata/database/NoAdminDashboardDatabaseAccess : java/lang/annotation/Annotation {
}

public final class misk/web/metadata/guice/GuiceDashboardTabModule : misk/inject/KAbstractModule {
public fun <init> ()V
}

public final class misk/web/metadata/guice/GuiceTabIndexAction : misk/web/actions/WebAction {
public static final field Companion Lmisk/web/metadata/guice/GuiceTabIndexAction$Companion;
public static final field PATH Ljava/lang/String;
public fun <init> (Lmisk/web/v2/DashboardPageLayout;Lmisk/web/metadata/guice/GuiceMetadataProvider;)V
public final fun get ()Ljava/lang/String;
}

public final class misk/web/metadata/guice/GuiceTabIndexAction$Companion {
}

public final class misk/web/metadata/webaction/WebActionsDashboardTabModule : misk/inject/KAbstractModule {
public fun <init> (Z)V
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import misk.security.authz.AccessAnnotationEntry
import misk.web.metadata.config.ConfigDashboardTabModule
import misk.web.metadata.config.ConfigMetadataAction
import misk.web.metadata.database.DatabaseDashboardTabModule
import misk.web.metadata.guice.GuiceDashboardTabModule
import misk.web.metadata.webaction.WebActionsDashboardTabModule
import misk.web.v2.NavbarModule

Expand Down Expand Up @@ -33,6 +34,7 @@ class AdminDashboardModule @JvmOverloads constructor(
// Default container admin tabs
install(ConfigDashboardTabModule(isDevelopment, configTabMode))
install(DatabaseDashboardTabModule(isDevelopment))
install(GuiceDashboardTabModule())
install(WebActionsDashboardTabModule(isDevelopment))
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package misk.web.metadata.guice

import misk.inject.KAbstractModule
import misk.web.WebActionModule
import misk.web.dashboard.AdminDashboard
import misk.web.dashboard.AdminDashboardAccess
import misk.web.dashboard.DashboardModule

class GuiceDashboardTabModule: KAbstractModule() {
override fun configure() {
install(WebActionModule.create<GuiceTabIndexAction>())
install(DashboardModule.createHotwireTab<AdminDashboard, AdminDashboardAccess>(
slug = "guice",
urlPathPrefix = GuiceTabIndexAction.PATH,
menuCategory = "Container Admin",
menuLabel = "Guice",
))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package misk.web.metadata.guice

import jakarta.inject.Inject
import jakarta.inject.Singleton
import kotlinx.html.InputType
import kotlinx.html.div
import kotlinx.html.h1
import kotlinx.html.input
import kotlinx.html.script
import kotlinx.html.table
import kotlinx.html.tbody
import kotlinx.html.td
import kotlinx.html.th
import kotlinx.html.thead
import kotlinx.html.tr
import misk.web.Get
import misk.web.ResponseContentType
import misk.web.actions.WebAction
import misk.web.dashboard.AdminDashboardAccess
import misk.web.mediatype.MediaTypes
import misk.web.v2.DashboardPageLayout

@Singleton
class GuiceTabIndexAction @Inject constructor(
private val dashboardPageLayout: DashboardPageLayout,
private val guiceMetadataProvider: GuiceMetadataProvider,
) : WebAction {
@Get(PATH)
@ResponseContentType(MediaTypes.TEXT_HTML)
@AdminDashboardAccess
fun get(): String = dashboardPageLayout
.newBuilder()
.headBlock {
val controllers = listOf(
"search_bar_controller",
)
controllers.forEach {
script {
type = "module"
src = "/static/controllers/$it.js"
}
}
}
.build { _, _, _ ->
val registrations = guiceMetadataProvider.get().guice.bindingMetadata

val checkIcon = ""

div("p-4 sm:p-6 lg:p-8") {
h1("text-3xl font-medium mb-8") {
+"""Guice"""
}
div {
attributes["data-controller"] = "search-bar"
div {
input(
type = InputType.search,
classes = "flex h-10 w-full bg-gray-100 hover:bg-gray-200 duration-500 border-none rounded-lg text-sm"
) {
attributes["data-action"] = "input->search-bar#search"
placeholder = "Search"
}
}
div("mt-8 flow-root") {
div("-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8") {
div("inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8") {
table("min-w-full divide-y divide-gray-300") {
thead {
tr {
th(classes = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900") {
+"""Type"""
}
th(classes = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900") {
+"""Source"""
}
th(classes = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900") {
+"""Annotation"""
}
th(classes = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900") {
+"""Scope"""
}
th(classes = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900") {
+"""Provider"""
}
}
}
tbody("divide-y divide-gray-200") {
registrations.map {
tr("registration") {
td("whitespace-normal px-3 py-4 text-sm") {
+it.type
}
td("whitespace-normal px-3 py-4 text-sm") {
+it.source
}
td(
"whitespace-normal px-3 py-4 text-sm"
) { + (it.annotation ?: "") }
td("whitespace-normal px-3 py-4 text-sm") {
+ (it.scope ?: "")
}
td("whitespace-normal px-3 py-4 text-sm") {
+it.provider
}
}
}
}
}
}
}
}
}
}
}

companion object {
const val PATH = "/_admin/guice/"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Application, Controller } from "../cache/stimulus/3.1.0/stimulus.min.js";
window.Stimulus = Application.start();

Stimulus.register("search-bar", class extends Controller {
search(ev) {
const input = ev.target.value.toLowerCase();
document.querySelectorAll(".registration").forEach(registration => {
let hide = true;
registration.querySelectorAll("*").forEach(col => {
if (col.textContent.toLowerCase().includes(input)) {
hide = false;
}
});
if (hide) {
registration.classList.contains("hidden") || registration.classList.add("hidden");
} else {
registration.classList.remove("hidden");
}
})
}
})
52 changes: 52 additions & 0 deletions misk/api/misk.api
Original file line number Diff line number Diff line change
Expand Up @@ -2124,6 +2124,58 @@ public abstract interface class misk/web/mdc/LogContextProvider {
public abstract fun get (Ljavax/servlet/http/HttpServletRequest;)Ljava/lang/String;
}

public final class misk/web/metadata/guice/GuiceMetadata : misk/web/metadata/Metadata {
public fun <init> (Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;)V
public final fun component1 ()Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;
public final fun copy (Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;)Lmisk/web/metadata/guice/GuiceMetadata;
public static synthetic fun copy$default (Lmisk/web/metadata/guice/GuiceMetadata;Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;ILjava/lang/Object;)Lmisk/web/metadata/guice/GuiceMetadata;
public fun equals (Ljava/lang/Object;)Z
public final fun getGuice ()Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class misk/web/metadata/guice/GuiceMetadataProvider : misk/web/metadata/MetadataProvider {
public field injector Lcom/google/inject/Injector;
public fun <init> ()V
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Lmisk/web/metadata/guice/GuiceMetadata;
public final fun getAllBindings ()Ljava/util/Map;
public fun getId ()Ljava/lang/String;
public final fun getInjector ()Lcom/google/inject/Injector;
public final fun setInjector (Lcom/google/inject/Injector;)V
}

public final class misk/web/metadata/guice/GuiceMetadataProvider$BindingMetadata {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lmisk/web/metadata/guice/GuiceMetadataProvider$BindingMetadata;
public static synthetic fun copy$default (Lmisk/web/metadata/guice/GuiceMetadataProvider$BindingMetadata;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lmisk/web/metadata/guice/GuiceMetadataProvider$BindingMetadata;
public fun equals (Ljava/lang/Object;)Z
public final fun getAnnotation ()Ljava/lang/String;
public final fun getProvider ()Ljava/lang/String;
public final fun getScope ()Ljava/lang/String;
public final fun getSource ()Ljava/lang/String;
public final fun getType ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class misk/web/metadata/guice/GuiceMetadataProvider$Metadata {
public fun <init> (Ljava/util/Set;)V
public final fun component1 ()Ljava/util/Set;
public final fun copy (Ljava/util/Set;)Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;
public static synthetic fun copy$default (Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;Ljava/util/Set;ILjava/lang/Object;)Lmisk/web/metadata/guice/GuiceMetadataProvider$Metadata;
public fun equals (Ljava/lang/Object;)Z
public final fun getBindingMetadata ()Ljava/util/Set;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class misk/web/metadata/webaction/WebActionMetadata {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;)V
public fun <init> (Ljava/lang/String;Lkotlin/reflect/KFunction;Ljava/util/List;Ljava/lang/String;Ljava/util/List;Lokhttp3/MediaType;Ljava/util/List;Ljava/util/List;Lkotlin/reflect/KType;Lkotlin/reflect/KType;Lkotlin/reflect/KType;Lmisk/web/PathPattern;Ljava/util/List;Ljava/util/List;Lmisk/web/DispatchMechanism;Ljava/util/Set;Ljava/util/Set;)V
Expand Down
Loading

0 comments on commit 918a819

Please sign in to comment.