Add config editor and dump viewer (#1)

* Begin working on config editor

* Finish working on config editor

* Add dump viewer

* Fix online mode not showing in dump viewer

* remove debug logging

* Replace " with '

* Fix syntax error

* Add more functionality to dump viewer

* Improve style of plugin popover

* Change card header colour

* Use crypto api for generating uuids

* Fix broken regex

* Add german translations from @onebeastchris

Co-authored-by: chris <github@onechris.mozmail.com>

* Move pretty much all hardcoded text on dump and config viewer pages to translations

* Use old yarn.lock

* Add indicator to show if a plugin is enabled

---------

Co-authored-by: chris <github@onechris.mozmail.com>
This commit is contained in:
Lukeandchris authored and GitHub committed 2024-05-15 16:40:29 +01:00
1 parent be8823e189
commit aa3f447873
12 files changed
+1542 -2

No files matched your search

+18
View File
@@ -132,6 +132,24 @@ const config: Config = {
position: 'left',
className: 'header-blog-link'
},
{
type: 'dropdown',
label: 'Utilities',
className: 'header-utilities-link',
position: 'left',
items: [
{
to: 'utilities/config-editor',
label: 'Config Editor',
},
{
to: 'utilities/dump-viewer',
label: 'Dump Viewer',
}
]
},
{
to: 'download',
label: 'Download',
+111
View File
@@ -230,6 +230,117 @@
"pages.download.description.geyseroptionalpack": {
"message": "An optional Bedrock resource pack to extend Geyser functionality."
},
"pages.configeditor.title": {
"message": "Konfigurationseditor"
},
"pages.configeditor.subheading": {
"message": "Bearbeite deine Geyser Konfigurationsdatei."
},
"pages.configeditor.noconfigselected.heading": {
"message": "No config selected."
},
"pages.configeditor.noconfigselected.subheading": {
"message": "Upload a file or get started with the default config!"
},
"pages.configeditor.button.defaultconfig": {
"message": "Default"
},
"pages.configeditor.button.upload": {
"message": "Upload"
},
"pages.configeditor.button.export": {
"message": "Export"
},
"pages.dumpviewer.title": {
"message": "Dump Betrachter"
},
"pages.dumpviewer.subheading": {
"message": "Schau dir eine Zusammenfassung deines Geyser Dumps an."
},
"pages.dumpviewer.enterdumpid": {
"message": "Enter Dump ID or URL below and click load."
},
"pages.dumpviewer.button.load": {
"message": "Load"
},
"pages.dumpviewer.versions": {
"message": "Versions"
},
"pages.dumpviewer.versions.geyserver": {
"message": "Geyser Version"
},
"pages.dumpviewer.versions.javaver": {
"message": "Java Version"
},
"pages.dumpviewer.versions.os": {
"message": "Operating System"
},
"pages.dumpviewer.geyserver": {
"message": "Geyser Version"
},
"pages.dumpviewer.geyserver.build": {
"message": "Build"
},
"pages.dumpviewer.geyserver.commit": {
"message": "Commit Hash"
},
"pages.dumpviewer.geyserver.branch": {
"message": "Branch"
},
"pages.dumpviewer.platform": {
"message": "Platform Info"
},
"pages.dumpviewer.platform.id": {
"message": "Platform Identifier"
},
"pages.dumpviewer.platform.name": {
"message": "Platform Name"
},
"pages.dumpviewer.platform.version": {
"message": "Platform Version"
},
"pages.dumpviewer.platform.apiver": {
"message": "Platform API Version"
},
"pages.dumpviewer.platform.onlinemode": {
"message": "Online Mode"
},
"pages.dumpviewer.sysinfo": {
"message": "System Info"
},
"pages.dumpviewer.sysinfo.cpucount": {
"message": "CPU Count"
},
"pages.dumpviewer.sysinfo.cpuname": {
"message": "CPU Name"
},
"pages.dumpviewer.sysinfo.ram": {
"message": "RAM"
},
"pages.dumpviewer.sysinfo.javaname": {
"message": "Java Name"
},
"pages.dumpviewer.sysinfo.javavendor": {
"message": "Java Vendor"
},
"pages.dumpviewer.sysinfo.dockercheck": {
"message": "Uses Docker?"
},
"pages.dumpviewer.plugins": {
"message": "Plugins"
},
"pages.dumpviewer.plugins.helptext": {
"message": "Click on a plugin to view more information."
},
"pages.dumpviewer.plugins.noplugins": {
"message": "No plugins to show."
},
"pages.dumpviewer.config": {
"message": "Config"
},
"pages.dumpviewer.viewsource": {
"message": "View dump source"
},
"theme.ErrorPageContent.title": {
"message": "Die Seite ist abgestürzt.",
"description": "The title of the fallback page when the page crashed"
@@ -46,5 +46,165 @@
"sidebar.geyserSidebar.category.Geyser API": {
"message": "Geyser API",
"description": "The label for category Geyser API in sidebar geyserSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org": {
"message": "api.geysermc.org",
"description": "The label for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org.link.generated-index.title": {
"message": "Global API",
"description": "The generated-index page title for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org.link.generated-index.description": {
"message": "Global API",
"description": "The generated-index page description for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.health": {
"message": "health",
"description": "The label for category health in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.link": {
"message": "link",
"description": "The label for category link in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.stats": {
"message": "stats",
"description": "The label for category stats in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.xbox": {
"message": "xbox",
"description": "The label for category xbox in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.skin": {
"message": "skin",
"description": "The label for category skin in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.utils": {
"message": "utils",
"description": "The label for category utils in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.UNTAGGED": {
"message": "UNTAGGED",
"description": "The label for category UNTAGGED in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org": {
"message": "download.geysermc.org",
"description": "The label for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org.link.generated-index.title": {
"message": "Downloads API",
"description": "The generated-index page title for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org.link.generated-index.description": {
"message": "Downloads API",
"description": "The generated-index page description for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.projects-controller": {
"message": "projects-controller",
"description": "The label for category projects-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.project-controller": {
"message": "project-controller",
"description": "The label for category project-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-controller": {
"message": "version-controller",
"description": "The label for category version-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-builds-controller": {
"message": "version-builds-controller",
"description": "The label for category version-builds-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-build-controller": {
"message": "version-build-controller",
"description": "The label for category version-build-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download-controller": {
"message": "download-controller",
"description": "The label for category download-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.doc.Simple server online check": {
"message": "Simple server online check",
"description": "The label for the doc item Simple server online check in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-health-controller-health"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.LinkController.get_bedrock_link_v1": {
"message": "GlobalApiWeb.Api.LinkController.get_bedrock_link_v1",
"description": "The label for the doc item GlobalApiWeb.Api.LinkController.get_bedrock_link_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-bedrock-link-v-1"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.LinkController.get_java_link_v1": {
"message": "GlobalApiWeb.Api.LinkController.get_java_link_v1",
"description": "The label for the doc item GlobalApiWeb.Api.LinkController.get_java_link_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-java-link-v-1"
},
"sidebar.apiSidebar.doc.Get linked Java account from Bedrock xuid": {
"message": "Get linked Java account from Bedrock xuid",
"description": "The label for the doc item Get linked Java account from Bedrock xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-bedrock-link-v-2"
},
"sidebar.apiSidebar.doc.Get linked Bedrock account from Java UUID": {
"message": "Get linked Bedrock account from Java UUID",
"description": "The label for the doc item Get linked Bedrock account from Java UUID in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-java-link-v-2"
},
"sidebar.apiSidebar.doc.Get all publicly available Global Api statistics": {
"message": "Get all publicly available Global Api statistics",
"description": "The label for the doc item Get all publicly available Global Api statistics in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-stats-controller-get-all-stats-2"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.XboxController.get_gamertag_v1": {
"message": "GlobalApiWeb.Api.XboxController.get_gamertag_v1",
"description": "The label for the doc item GlobalApiWeb.Api.XboxController.get_gamertag_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-gamertag-v-1"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.XboxController.get_xuid_v1": {
"message": "GlobalApiWeb.Api.XboxController.get_xuid_v1",
"description": "The label for the doc item GlobalApiWeb.Api.XboxController.get_xuid_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-xuid-v-1"
},
"sidebar.apiSidebar.doc.Get the gamertag from a xuid": {
"message": "Get the gamertag from a xuid",
"description": "The label for the doc item Get the gamertag from a xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-gamertag-v-2"
},
"sidebar.apiSidebar.doc.Get the xuid from a gamertag": {
"message": "Get the xuid from a gamertag",
"description": "The label for the doc item Get the xuid from a gamertag in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-xuid-v-2"
},
"sidebar.apiSidebar.doc.Get a list of the most recently uploaded skins": {
"message": "Get a list of the most recently uploaded skins",
"description": "The label for the doc item Get a list of the most recently uploaded skins in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-skin-controller-get-recent-uploads"
},
"sidebar.apiSidebar.doc.Get the most recently converted skin of a Bedrock player": {
"message": "Get the most recently converted skin of a Bedrock player",
"description": "The label for the doc item Get the most recently converted skin of a Bedrock player in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-skin-controller-get-skin"
},
"sidebar.apiSidebar.doc.Utility endpoint to get either a Java UUID or a Bedrock xuid": {
"message": "Utility endpoint to get either a Java UUID or a Bedrock xuid",
"description": "The label for the doc item Utility endpoint to get either a Java UUID or a Bedrock xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-utils-controller-get-bedrock-or-java-uuid"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.RenderController.get_front_texture": {
"message": "GlobalApiWeb.Api.RenderController.get_front_texture",
"description": "The label for the doc item GlobalApiWeb.Api.RenderController.get_front_texture in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-render-controller-get-front-texture"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.RenderController.get_raw_texture": {
"message": "GlobalApiWeb.Api.RenderController.get_raw_texture",
"description": "The label for the doc item GlobalApiWeb.Api.RenderController.get_raw_texture in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-render-controller-get-raw-texture"
},
"sidebar.apiSidebar.doc.Gets a list of all available projects.": {
"message": "Gets a list of all available projects.",
"description": "The label for the doc item Gets a list of all available projects. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/projects"
},
"sidebar.apiSidebar.doc.Gets information about a project.": {
"message": "Gets information about a project.",
"description": "The label for the doc item Gets information about a project. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/project"
},
"sidebar.apiSidebar.doc.Gets information about a version.": {
"message": "Gets information about a version.",
"description": "The label for the doc item Gets information about a version. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/version"
},
"sidebar.apiSidebar.doc.Gets all available builds for a project's version.": {
"message": "Gets all available builds for a project's version.",
"description": "The label for the doc item Gets all available builds for a project's version. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/builds"
},
"sidebar.apiSidebar.doc.Gets information related to a specific build.": {
"message": "Gets information related to a specific build.",
"description": "The label for the doc item Gets information related to a specific build. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/build-latest"
},
"sidebar.apiSidebar.doc.Downloads the given file from a build's data.": {
"message": "Downloads the given file from a build's data.",
"description": "The label for the doc item Downloads the given file from a build's data. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/download-latest"
}
}
@@ -34,5 +34,25 @@
"item.label.Other": {
"message": "Other",
"description": "Navbar item with label Other"
},
"item.label.Blog": {
"message": "Blog",
"description": "Navbar item with label Blog"
},
"item.label.Utilities": {
"message": "Utilities",
"description": "Navbar item with label Utilities"
},
"item.label.REST APIs": {
"message": "REST APIs",
"description": "Navbar item with label REST APIs"
},
"item.label.Config Editor": {
"message": "Config Editor",
"description": "Navbar item with label Config Editor"
},
"item.label.Dump Viewer": {
"message": "Dump Viewer",
"description": "Navbar item with label Dump Viewer"
}
}
+245
View File
@@ -230,6 +230,117 @@
"pages.download.description.geyseroptionalpack": {
"message": "An optional Bedrock resource pack to extend Geyser functionality."
},
"pages.configeditor.title": {
"message": "Config Editor"
},
"pages.configeditor.subheading": {
"message": "Edit your Geyser configuration."
},
"pages.configeditor.noconfigselected.heading": {
"message": "No config selected."
},
"pages.configeditor.noconfigselected.subheading": {
"message": "Upload a file or get started with the default config!"
},
"pages.configeditor.button.defaultconfig": {
"message": "Default"
},
"pages.configeditor.button.upload": {
"message": "Upload"
},
"pages.configeditor.button.export": {
"message": "Export"
},
"pages.dumpviewer.title": {
"message": "Dump Viewer"
},
"pages.dumpviewer.subheading": {
"message": "View the breakdown of your Geyser dump."
},
"pages.dumpviewer.enterdumpid": {
"message": "Enter Dump ID or URL below and click load."
},
"pages.dumpviewer.button.load": {
"message": "Load"
},
"pages.dumpviewer.versions": {
"message": "Versions"
},
"pages.dumpviewer.versions.geyserver": {
"message": "Geyser Version"
},
"pages.dumpviewer.versions.javaver": {
"message": "Java Version"
},
"pages.dumpviewer.versions.os": {
"message": "Operating System"
},
"pages.dumpviewer.geyserver": {
"message": "Geyser Version"
},
"pages.dumpviewer.geyserver.build": {
"message": "Build"
},
"pages.dumpviewer.geyserver.commit": {
"message": "Commit Hash"
},
"pages.dumpviewer.geyserver.branch": {
"message": "Branch"
},
"pages.dumpviewer.platform": {
"message": "Platform Info"
},
"pages.dumpviewer.platform.id": {
"message": "Platform Identifier"
},
"pages.dumpviewer.platform.name": {
"message": "Platform Name"
},
"pages.dumpviewer.platform.version": {
"message": "Platform Version"
},
"pages.dumpviewer.platform.apiver": {
"message": "Platform API Version"
},
"pages.dumpviewer.platform.onlinemode": {
"message": "Online Mode"
},
"pages.dumpviewer.sysinfo": {
"message": "System Info"
},
"pages.dumpviewer.sysinfo.cpucount": {
"message": "CPU Count"
},
"pages.dumpviewer.sysinfo.cpuname": {
"message": "CPU Name"
},
"pages.dumpviewer.sysinfo.ram": {
"message": "RAM"
},
"pages.dumpviewer.sysinfo.javaname": {
"message": "Java Name"
},
"pages.dumpviewer.sysinfo.javavendor": {
"message": "Java Vendor"
},
"pages.dumpviewer.sysinfo.dockercheck": {
"message": "Uses Docker?"
},
"pages.dumpviewer.plugins": {
"message": "Plugins"
},
"pages.dumpviewer.plugins.helptext": {
"message": "Click on a plugin to view more information."
},
"pages.dumpviewer.plugins.noplugins": {
"message": "No plugins to show."
},
"pages.dumpviewer.config": {
"message": "Config"
},
"pages.dumpviewer.viewsource": {
"message": "View dump source"
},
"theme.ErrorPageContent.title": {
"message": "This page crashed.",
"description": "The title of the fallback page when the page crashed"
@@ -516,5 +627,139 @@
"theme.unlistedContent.message": {
"message": "This page is unlisted. Search engines will not index it, and only users having a direct link can access it.",
"description": "The unlisted content banner message"
},
"providers.provider.bloomhost.description": {
"message": "https://docs.bloom.host/plugins/geysermc/"
},
"theme.SearchPage.documentsFound.plurals": {
"message": "One document found|{count} documents found",
"description": "Pluralized label for \"{count} documents found\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.SearchPage.existingResultsTitle": {
"message": "Search results for \"{query}\"",
"description": "The search page title for non-empty query"
},
"theme.SearchPage.emptyResultsTitle": {
"message": "Search the documentation",
"description": "The search page title for empty query"
},
"theme.SearchPage.inputPlaceholder": {
"message": "Type your search here",
"description": "The placeholder for search page input"
},
"theme.SearchPage.inputLabel": {
"message": "Search",
"description": "The ARIA label for search page input"
},
"theme.SearchPage.algoliaLabel": {
"message": "Search by Algolia",
"description": "The ARIA label for Algolia mention"
},
"theme.SearchPage.noResultsText": {
"message": "No results were found",
"description": "The paragraph for empty search result"
},
"theme.SearchPage.fetchingNewResults": {
"message": "Fetching new results...",
"description": "The paragraph for fetching new search results"
},
"theme.SearchBar.label": {
"message": "Search",
"description": "The ARIA label and placeholder for search button"
},
"theme.SearchModal.searchBox.resetButtonTitle": {
"message": "Clear the query",
"description": "The label and ARIA label for search box reset button"
},
"theme.SearchModal.searchBox.cancelButtonText": {
"message": "Cancel",
"description": "The label and ARIA label for search box cancel button"
},
"theme.SearchModal.startScreen.recentSearchesTitle": {
"message": "Recent",
"description": "The title for recent searches"
},
"theme.SearchModal.startScreen.noRecentSearchesText": {
"message": "No recent searches",
"description": "The text when no recent searches"
},
"theme.SearchModal.startScreen.saveRecentSearchButtonTitle": {
"message": "Save this search",
"description": "The label for save recent search button"
},
"theme.SearchModal.startScreen.removeRecentSearchButtonTitle": {
"message": "Remove this search from history",
"description": "The label for remove recent search button"
},
"theme.SearchModal.startScreen.favoriteSearchesTitle": {
"message": "Favorite",
"description": "The title for favorite searches"
},
"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": {
"message": "Remove this search from favorites",
"description": "The label for remove favorite search button"
},
"theme.SearchModal.errorScreen.titleText": {
"message": "Unable to fetch results",
"description": "The title for error screen of search modal"
},
"theme.SearchModal.errorScreen.helpText": {
"message": "You might want to check your network connection.",
"description": "The help text for error screen of search modal"
},
"theme.SearchModal.footer.selectText": {
"message": "to select",
"description": "The explanatory text of the action for the enter key"
},
"theme.SearchModal.footer.selectKeyAriaLabel": {
"message": "Enter key",
"description": "The ARIA label for the Enter key button that makes the selection"
},
"theme.SearchModal.footer.navigateText": {
"message": "to navigate",
"description": "The explanatory text of the action for the Arrow up and Arrow down key"
},
"theme.SearchModal.footer.navigateUpKeyAriaLabel": {
"message": "Arrow up",
"description": "The ARIA label for the Arrow up key button that makes the navigation"
},
"theme.SearchModal.footer.navigateDownKeyAriaLabel": {
"message": "Arrow down",
"description": "The ARIA label for the Arrow down key button that makes the navigation"
},
"theme.SearchModal.footer.closeText": {
"message": "to close",
"description": "The explanatory text of the action for Escape key"
},
"theme.SearchModal.footer.closeKeyAriaLabel": {
"message": "Escape key",
"description": "The ARIA label for the Escape key button that close the modal"
},
"theme.SearchModal.footer.searchByText": {
"message": "Search by",
"description": "The text explain that the search is making by Algolia"
},
"theme.SearchModal.noResultsScreen.noResultsText": {
"message": "No results for",
"description": "The text explains that there are no results for the following search"
},
"theme.SearchModal.noResultsScreen.suggestedQueryText": {
"message": "Try searching for",
"description": "The text for the suggested query when no results are found for the following search"
},
"theme.SearchModal.noResultsScreen.reportMissingResultsText": {
"message": "Believe this query should return results?",
"description": "The text for the question where the user thinks there are missing results"
},
"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": {
"message": "Let us know.",
"description": "The text for the link to report missing results"
},
"theme.SearchModal.placeholder": {
"message": "Search docs",
"description": "The placeholder of the input of the DocSearch pop-up modal"
},
"theme.SearchBar.seeAll": {
"message": "See all {count} results"
}
}
@@ -46,5 +46,165 @@
"sidebar.geyserSidebar.category.Geyser API": {
"message": "Geyser API",
"description": "The label for category Geyser API in sidebar geyserSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org": {
"message": "api.geysermc.org",
"description": "The label for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org.link.generated-index.title": {
"message": "Global API",
"description": "The generated-index page title for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.api.geysermc.org.link.generated-index.description": {
"message": "Global API",
"description": "The generated-index page description for category api.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.health": {
"message": "health",
"description": "The label for category health in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.link": {
"message": "link",
"description": "The label for category link in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.stats": {
"message": "stats",
"description": "The label for category stats in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.xbox": {
"message": "xbox",
"description": "The label for category xbox in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.skin": {
"message": "skin",
"description": "The label for category skin in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.utils": {
"message": "utils",
"description": "The label for category utils in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.UNTAGGED": {
"message": "UNTAGGED",
"description": "The label for category UNTAGGED in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org": {
"message": "download.geysermc.org",
"description": "The label for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org.link.generated-index.title": {
"message": "Downloads API",
"description": "The generated-index page title for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download.geysermc.org.link.generated-index.description": {
"message": "Downloads API",
"description": "The generated-index page description for category download.geysermc.org in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.projects-controller": {
"message": "projects-controller",
"description": "The label for category projects-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.project-controller": {
"message": "project-controller",
"description": "The label for category project-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-controller": {
"message": "version-controller",
"description": "The label for category version-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-builds-controller": {
"message": "version-builds-controller",
"description": "The label for category version-builds-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.version-build-controller": {
"message": "version-build-controller",
"description": "The label for category version-build-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.category.download-controller": {
"message": "download-controller",
"description": "The label for category download-controller in sidebar apiSidebar"
},
"sidebar.apiSidebar.doc.Simple server online check": {
"message": "Simple server online check",
"description": "The label for the doc item Simple server online check in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-health-controller-health"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.LinkController.get_bedrock_link_v1": {
"message": "GlobalApiWeb.Api.LinkController.get_bedrock_link_v1",
"description": "The label for the doc item GlobalApiWeb.Api.LinkController.get_bedrock_link_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-bedrock-link-v-1"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.LinkController.get_java_link_v1": {
"message": "GlobalApiWeb.Api.LinkController.get_java_link_v1",
"description": "The label for the doc item GlobalApiWeb.Api.LinkController.get_java_link_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-java-link-v-1"
},
"sidebar.apiSidebar.doc.Get linked Java account from Bedrock xuid": {
"message": "Get linked Java account from Bedrock xuid",
"description": "The label for the doc item Get linked Java account from Bedrock xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-bedrock-link-v-2"
},
"sidebar.apiSidebar.doc.Get linked Bedrock account from Java UUID": {
"message": "Get linked Bedrock account from Java UUID",
"description": "The label for the doc item Get linked Bedrock account from Java UUID in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-link-controller-get-java-link-v-2"
},
"sidebar.apiSidebar.doc.Get all publicly available Global Api statistics": {
"message": "Get all publicly available Global Api statistics",
"description": "The label for the doc item Get all publicly available Global Api statistics in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-stats-controller-get-all-stats-2"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.XboxController.get_gamertag_v1": {
"message": "GlobalApiWeb.Api.XboxController.get_gamertag_v1",
"description": "The label for the doc item GlobalApiWeb.Api.XboxController.get_gamertag_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-gamertag-v-1"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.XboxController.get_xuid_v1": {
"message": "GlobalApiWeb.Api.XboxController.get_xuid_v1",
"description": "The label for the doc item GlobalApiWeb.Api.XboxController.get_xuid_v1 in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-xuid-v-1"
},
"sidebar.apiSidebar.doc.Get the gamertag from a xuid": {
"message": "Get the gamertag from a xuid",
"description": "The label for the doc item Get the gamertag from a xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-gamertag-v-2"
},
"sidebar.apiSidebar.doc.Get the xuid from a gamertag": {
"message": "Get the xuid from a gamertag",
"description": "The label for the doc item Get the xuid from a gamertag in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-xbox-controller-get-xuid-v-2"
},
"sidebar.apiSidebar.doc.Get a list of the most recently uploaded skins": {
"message": "Get a list of the most recently uploaded skins",
"description": "The label for the doc item Get a list of the most recently uploaded skins in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-skin-controller-get-recent-uploads"
},
"sidebar.apiSidebar.doc.Get the most recently converted skin of a Bedrock player": {
"message": "Get the most recently converted skin of a Bedrock player",
"description": "The label for the doc item Get the most recently converted skin of a Bedrock player in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-skin-controller-get-skin"
},
"sidebar.apiSidebar.doc.Utility endpoint to get either a Java UUID or a Bedrock xuid": {
"message": "Utility endpoint to get either a Java UUID or a Bedrock xuid",
"description": "The label for the doc item Utility endpoint to get either a Java UUID or a Bedrock xuid in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-utils-controller-get-bedrock-or-java-uuid"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.RenderController.get_front_texture": {
"message": "GlobalApiWeb.Api.RenderController.get_front_texture",
"description": "The label for the doc item GlobalApiWeb.Api.RenderController.get_front_texture in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-render-controller-get-front-texture"
},
"sidebar.apiSidebar.doc.GlobalApiWeb.Api.RenderController.get_raw_texture": {
"message": "GlobalApiWeb.Api.RenderController.get_raw_texture",
"description": "The label for the doc item GlobalApiWeb.Api.RenderController.get_raw_texture in sidebar apiSidebar, linking to the doc api/api.geysermc.org/global-api-web-api-render-controller-get-raw-texture"
},
"sidebar.apiSidebar.doc.Gets a list of all available projects.": {
"message": "Gets a list of all available projects.",
"description": "The label for the doc item Gets a list of all available projects. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/projects"
},
"sidebar.apiSidebar.doc.Gets information about a project.": {
"message": "Gets information about a project.",
"description": "The label for the doc item Gets information about a project. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/project"
},
"sidebar.apiSidebar.doc.Gets information about a version.": {
"message": "Gets information about a version.",
"description": "The label for the doc item Gets information about a version. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/version"
},
"sidebar.apiSidebar.doc.Gets all available builds for a project's version.": {
"message": "Gets all available builds for a project's version.",
"description": "The label for the doc item Gets all available builds for a project's version. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/builds"
},
"sidebar.apiSidebar.doc.Gets information related to a specific build.": {
"message": "Gets information related to a specific build.",
"description": "The label for the doc item Gets information related to a specific build. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/build-latest"
},
"sidebar.apiSidebar.doc.Downloads the given file from a build's data.": {
"message": "Downloads the given file from a build's data.",
"description": "The label for the doc item Downloads the given file from a build's data. in sidebar apiSidebar, linking to the doc api/downloads.geysermc.org/download-latest"
}
}
@@ -34,5 +34,25 @@
"item.label.Other": {
"message": "Other",
"description": "Navbar item with label Other"
},
"item.label.Blog": {
"message": "Blog",
"description": "Navbar item with label Blog"
},
"item.label.Utilities": {
"message": "Utilities",
"description": "Navbar item with label Utilities"
},
"item.label.REST APIs": {
"message": "REST APIs",
"description": "Navbar item with label REST APIs"
},
"item.label.Config Editor": {
"message": "Config Editor",
"description": "Navbar item with label Config Editor"
},
"item.label.Dump Viewer": {
"message": "Dump Viewer",
"description": "Navbar item with label Dump Viewer"
}
}
+115 -1
View File
@@ -21,6 +21,7 @@
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
--ifm-font-family-base: 'Montserrat', sans-serif;
--ifm-heading-font-family: 'Montserrat', sans-serif;
--switch-background-color: rgba(0, 0, 0, 0.25);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
@@ -39,6 +40,7 @@
--ifm-background-surface-color: #1a2a3a;
--ifm-horizontal-line-color: rgba(227, 227, 227, 0.2);
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
--switch-background-color: rgb(135, 129, 129);
}
html[data-theme='dark'] {
@@ -96,6 +98,26 @@ html[data-theme='dark'] {
background-color: var(--ifm-navbar-link-hover-color);
}
.header-utilities-link {
display: flex;
align-items: center;
gap: 10px;
}
.header-utilities-link::before {
content: '';
width: 24px;
height: 24px;
display: inline-block;
background-color: var(--ifm-navbar-link-color);
mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <path d="M78.6 5C69.1-2.4 55.6-1.5 47 7L7 47c-8.5 8.5-9.4 22-2.1 31.6l80 104c4.5 5.9 11.6 9.4 19 9.4h54.1l109 109c-14.7 29-10 65.4 14.3 89.6l112 112c12.5 12.5 32.8 12.5 45.3 0l64-64c12.5-12.5 12.5-32.8 0-45.3l-112-112c-24.2-24.2-60.6-29-89.6-14.3l-109-109V104c0-7.5-3.5-14.5-9.4-19L78.6 5zM19.9 396.1C7.2 408.8 0 426.1 0 444.1C0 481.6 30.4 512 67.9 512c18 0 35.3-7.2 48-19.9L233.7 374.3c-7.8-20.9-9-43.6-3.6-65.1l-61.7-61.7L19.9 396.1zM512 144c0-10.5-1.1-20.7-3.2-30.5c-2.4-11.2-16.1-14.1-24.2-6l-63.9 63.9c-3 3-7.1 4.7-11.3 4.7H352c-8.8 0-16-7.2-16-16V102.6c0-4.2 1.7-8.3 4.7-11.3l63.9-63.9c8.1-8.1 5.2-21.8-6-24.2C388.7 1.1 378.5 0 368 0C288.5 0 224 64.5 224 144l0 .8 85.3 85.3c36-9.1 75.8 .5 104 28.7L429 274.5c49-23 83-72.8 83-130.5zM56 432a24 24 0 1 1 48 0 24 24 0 1 1 -48 0z"/> </svg>');
transition: background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default);
}
.header-download-link:hover::before {
background-color: var(--ifm-navbar-link-hover-color);
}
.header-download-link {
display: flex;
align-items: center;
@@ -366,7 +388,8 @@ html[data-theme='dark'] {
max-width: 100%;
}
.openapi-tabs__code-list-container, .tabs-host-type {
.openapi-tabs__code-list-container,
.tabs-host-type {
display: flex !important;
}
}
@@ -392,3 +415,94 @@ html[data-theme='dark'] {
border-radius: var(--ifm-global-radius);
color: #fff
}
.hidden {
display: none;
}
.font-normal {
font-weight: normal;
}
.button {
width: 150px;
outline: 3px solid var(--ifm-tabs-color-active);
outline-offset: -3px;
border: 0;
border-radius: var(--ifm-global-radius);
background-color: transparent;
text-align: center;
font-size: 18px;
font-weight: normal;
transition: background-color 0.5s ease, color 0.5s ease;
padding-top: 10px;
padding-bottom: 10px;
color: var(--ifm-tabs-color-active);
}
.button:hover {
background-color: var(--ifm-color-primary);
color: #fff;
}
.button-secondary {
outline: 3px solid var(--ifm-color-secondary);
}
.button-secondary:hover {
background-color: var(--ifm-color-secondary);
}
.form-input {
border-radius: var(--ifm-global-radius);
outline: 1px solid var(--ifm-color-secondary);
outline-offset: -1px;
padding: 10px;
min-width: 50%;
font-size: 16px;
}
.no-outline {
outline: none;
}
@media screen and (max-width: 768px) {
.form-input {
min-width: 100%;
}
}
/* https://codepen.io/JAGATHISH1123/pen/PvayMB */
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 20px;
background-color: var(--switch-background-color);
border-radius: 20px;
transition: all 0.3s;
}
.switch::after {
content: '';
position: absolute;
width: 18px;
height: 18px;
border-radius: 50%;
background-color: white;
top: 1px;
left: 1px;
transition: all 0.3s;
}
.checkbox:checked+.switch::after {
left: 20px;
}
.checkbox:checked+.switch {
background-color: var(--ifm-color-secondary);
}
.checkbox {
display: none;
}
+301
View File
@@ -0,0 +1,301 @@
import Translate from '@docusaurus/Translate';
import HeroBanner from '@site/src/components/HeroBanner';
import HeroBackground from '@site/static/img/site/split-background.jpg';
import Layout from '@theme/Layout';
import styles from './utilities.module.css';
import { useRef, useState } from 'react';
const ConfigEditorPage: React.FC = () => {
const [config, setConfig] = useState('');
const [parsedConfig, setParsedConfig] = useState<any>({});
const editedConfig = useRef<any>({});
const uploadRef = useRef<any>(null);
const loadDefault = async () => {
try {
const response = await fetch('https://raw.githubusercontent.com/GeyserMC/Geyser/master/core/src/main/resources/config.yml');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const text = await response.text();
handleConfigLoad(text);
} catch (error) {
console.error('Failed to fetch default config:', error);
}
}
const handleUpload = async (e) => {
const fileName = e.target.files[0];
// Makse sure the file is a .yml file
if (!fileName.name.endsWith('.yml')) {
alert('Please select a .yml config file!');
return;
}
// Read the file
const fileReader = new FileReader();
fileReader.onload = (e) => {
handleConfigLoad(e.target.result as string);
}
fileReader.readAsText(fileName);
}
const handleConfigLoad = (config: string) => {
setConfig(config);
setParsedConfig(loadConfig(config));
}
const loadConfig = (config: string) => {
const lines = config.split('\n');
let currentSection = '';
let currentComment = '';
const newConfig = {};
// Parse each line of the config
lines.forEach(line => {
// Reset the section if we are no indented
if (!line.startsWith(' ')) {
currentSection = '';
}
// Ignore any empty lines
line = line.trim()
if (line === '') {
currentComment = '';
return;
}
// Check if we are in a comment
if (line.startsWith('#')) {
currentComment += line.replace(/^# ?/i, '') + '<br>';
return;
}
// Ignore these lines since they will fail to parse
if (!line.includes(':')) {
return;
}
// Get the key and value
const splitLine = line.split(':');
splitLine[0] = splitLine[0].trim();
splitLine[1] = splitLine[1].trim();
// Check if we are in a new section
if (line.endsWith(':')) {
currentSection = splitLine[0];
currentComment = '';
return;
}
// Ignore user auths section
if (currentSection === 'userAuths' || currentSection === 'saved-user-logins') {
return;
}
// Add the config option to the config object
newConfig[currentSection] = newConfig[currentSection] || {};
newConfig[currentSection][splitLine[0]] = {
desc: currentComment,
value: splitLine[1]
};
// Reset the comment
currentComment = '';
})
return newConfig;
}
const generateHTML = (config: any) => {
return Object.keys(config).map(configKey => (
<div key={configKey} className={styles.card}>
<div className={styles.cardHeader}>{configKey === '' ? '.' : configKey}</div>
<div className={styles.cardBody}>
{Object.keys(config[configKey]).map(configOption => {
const configOptionInfo = config[configKey][configOption];
const configOptionKey = configKey === '' ? configOption : `${configKey}.${configOption}`;
return (
<div key={configOptionKey} className={styles.configOption}>
<h3>{configOption}</h3>
<p dangerouslySetInnerHTML={{ __html: configOptionInfo.desc }} />
{getInput(configOptionKey, configOptionInfo.value)}
</div>
)
})}
</div>
</div>
))
}
const handleExport = () => {
let newConfig = config;
Object.entries(editedConfig.current).forEach(([key, value]) => {
const keys = key.split('.');
let currentObj = parsedConfig;
keys.forEach((nestedKey, index) => {
if (currentObj.hasOwnProperty(nestedKey)) {
if (index === keys.length - 1) {
const oldValue = currentObj[nestedKey].value;
newConfig = newConfig.replace(` ${nestedKey}: ${oldValue}`, ` ${nestedKey}: ${value}`);
} else {
currentObj = currentObj[nestedKey];
}
}
});
});
// Trigger a download of the final config
downloadString(newConfig, 'text/plain', 'config.yml');
}
function getInput(name, value) {
const handleChange = (event) => {
const { id, value, type, checked } = event.target;
editedConfig.current = {
...editedConfig.current,
[id]: type === 'checkbox' ? checked.toString() : value
};
}
switch (name) {
// Handle all the dropdowns
case 'remote.auth-type':
return (
<select key={name} className='form-input' id={name} defaultValue={value} onChange={handleChange}>
<option value='offline'>offline</option>
<option value='online'>online</option>
<option value='floodgate'>floodgate</option>
</select>
);
case 'show-cooldown':
return (
<select key={name} className='form-input' id={name} defaultValue={value} onChange={handleChange}>
<option value='title'>title</option>
<option value='actionbar'>actionbar</option>
<option value='false'>false</option>
</select>
);
case 'emote-offhand-workaround':
return (
<select key={name} className='form-input' id={name} defaultValue={value} onChange={handleChange}>
<option value='disabled'>disabled</option>
<option value='no-emotes'>no-emotes</option>
<option value='emotes-and-offhand'>emotes-and-offhand</option>
</select>
);
case 'config-version':
return <input key={name} className='form-input' type='text' disabled defaultValue={value.replace(/"/g, '')} />;
case 'metrics.uuid':
return <input key={name} className='form-input' id={name} type='text' disabled defaultValue={value === 'generateduuid' ? crypto.randomUUID() : value} />;
default:
// Handle all the other inputs
if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {
// Boolean
return (
<div key={name}>
<input className='checkbox' type='checkbox' id={name} defaultChecked={value.toLowerCase() === 'true'} onChange={handleChange} />
<label htmlFor={name} className='switch'></label>
</div>
);
} else if (!isNaN(value)) {
// Number
return <input key={name} className='form-input' type='number' defaultValue={value} id={name} onChange={handleChange} />;
} else {
// String
return <input key={name} className='form-input' type='text' defaultValue={value.replace(/"/g, '')} id={name} onChange={handleChange} />;
}
}
}
// From https://gist.github.com/danallison/3ec9d5314788b337b682
function downloadString(text, fileType, fileName) {
const blob = new Blob([text], { type: fileType })
const a = document.createElement('a')
a.download = fileName
a.href = URL.createObjectURL(blob)
a.dataset.downloadurl = [fileType, a.download, a.href].join(':')
a.style.display = 'none'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
setTimeout(() => { URL.revokeObjectURL(a.href) }, 1500)
}
const NoConfigSection = () => (
<>
<h1><Translate id='pages.configeditor.noconfigselected.heading'>No config selected.</Translate></h1>
<h3 className='font-normal'><Translate id='pages.configeditor.noconfigselected.subheading'>Upload a file or get started with the default config!</Translate></h3>
<div className={styles.buttonsContainer}>
<button className='button' onClick={loadDefault}>
<Translate id='pages.configeditor.button.defaultconfig'>Default</Translate>
</button>
<button className='button' onClick={() => uploadRef.current.click()}>
<input
ref={uploadRef}
type='file'
className='hidden'
accept='.yml'
onChange={handleUpload}
/>
<Translate id='pages.configeditor.button.upload'>Upload</Translate>
</button>
</div>
</>
)
const EditorView = () => (
<>
<div className={styles.buttonsContainer} style={{ marginBottom: '30px' }}>
<button className='button' onClick={handleExport}>
<Translate id='pages.configeditor.button.export'>Export</Translate>
</button>
</div>
{generateHTML(parsedConfig)}
</>
)
return (
<>
<HeroBanner
title={<Translate id='pages.configeditor.title'>Config Editor</Translate>}
subheading={<Translate id='pages.configeditor.subheading'>Edit your Geyser configuration.</Translate>}
backgroundImage={HeroBackground}
/>
<div className='container' style={{ marginTop: '30px' }}>
{Object.keys(parsedConfig).length === 0 ? <NoConfigSection /> : <EditorView />}
</div>
<section id='config-options'></section>
</>
)
}
export default function ConfigEditor(): JSX.Element {
return (
<Layout
title={`Config Editor`}
description='Edit your Geyser configuration.'
>
<main>
<div className='container container--fluid margin-vert--lg'>
<ConfigEditorPage />
</div>
</main>
</Layout>
)
}
+281
View File
@@ -0,0 +1,281 @@
import Translate from '@docusaurus/Translate';
import HeroBanner from '@site/src/components/HeroBanner';
import HeroBackground from '@site/static/img/site/split-background.jpg';
import Layout from '@theme/Layout';
import { useEffect, useRef, useState } from 'react';
import styles from './utilities.module.css';
import { Grid } from '@site/src/components/Grid';
import CodeBlock from '@theme/CodeBlock';
const DumpViewerPage: React.FC = () => {
const [dumpId, setDumpId] = useState('');
const [data, setData] = useState<any>({});
const [statusMessage, setStatusMessage] = useState('');
const [activePlugin, setActivePlugin] = useState<any>({});
const pluginPopoverRef = useRef<any>(null);
useEffect(() => {
const handleClickOutside = (event) => setActivePlugin({});
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [pluginPopoverRef]);
useEffect(() => {
// Get the ID from the URL
let id = window.location.href.includes('?') ? window.location.href.split('?').pop() : '';
if (id === '' || id === undefined) {
id = window.location.hash.slice(1);
}
if (id !== undefined && id !== '') {
setDumpId(id);
handleLoad(id);
}
}, []);
const handleLoadClick = () => {
if (dumpId === '') {
setStatusMessage('You haven\'t entered an ID or URL!');
return;
}
let id = dumpId;
if (dumpId.startsWith('https://dump.geysermc.org/')) {
id = dumpId.split('/').pop();
}
setDumpId(id);
handleLoad(id);
}
const handleLoad = async (dumpId) => {
try {
// Construct the raw dump URL
const url = 'https://dump.geysermc.org/raw/' + dumpId;
const response = await fetch(url);
const data = await response.json();
// Check for error
if (data.message) {
throw new Error(data.message)
}
window.location.hash = '#' + dumpId;
setData(data);
} catch (error) {
setStatusMessage('An error occurred while loading the dump. Please try again later.<br><br>' + error);
}
}
const capitalizeFirstLetter = (string) => {
return string.charAt(0).toUpperCase() + string.slice(1)
}
const handlePluginClick = (plugin) => {
setActivePlugin(plugin);
}
return (
<>
<HeroBanner
title={<Translate id='pages.dumpviewer.title'>Dump Viewer</Translate>}
subheading={<Translate id='pages.dumpviewer.subheading'>View the breakdown of your Geyser dump.</Translate>}
backgroundImage={HeroBackground}
/>
<div className='container' style={{ marginTop: '30px' }}>
{Object.keys(data).length === 0 ? (
<>
<h2><Translate id='pages.dumpviewer.enterdumpid'>Enter Dump ID or URL below and click load.</Translate></h2>
<input id='dump-url' className='form-input no-outline' value={dumpId} onChange={(e) => setDumpId(e.target.value)} placeholder='Dump ID/URL' />
<button className={styles.loadButton} onClick={handleLoadClick}>
<Translate id='pages.dumpviewer.button.load'>Load</Translate>
</button>
{statusMessage !== '' ? (
<div className={styles.statusMessage}>
<p dangerouslySetInnerHTML={{ __html: statusMessage }} />
</div>
) : undefined}
</>
) : (
<>
<div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.versions'>Versions</Translate>
</div>
<div className={styles.cardBody}>
<Grid elementsPerRow={3} gap='8px'>
<div>
<b><Translate id='pages.dumpviewer.versions.geyserver'>Geyser Version</Translate></b><br />
<p id='geyserVersion'>{data.versionInfo.version}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.versions.javaver'>Java Version</Translate></b><br />
<p id='javaVersion'>{data.versionInfo.javaVersion} ({data.versionInfo.architecture})</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.versions.os'>Operating System</Translate></b><br />
<p id='osVersion'>{data.versionInfo.operatingSystem} ({data.versionInfo.operatingSystemVersion})</p>
</div>
</Grid>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.geyserver'>Geyser Version</Translate>
</div>
<div className={styles.cardBody}>
<Grid elementsPerRow={3} gap='8px'>
<div>
<b><Translate id='pages.dumpviewer.geyserver.build'>Build</Translate></b><br />
<p id='buildNumber'>{data.gitInfo['git.build.number'] ?? data.gitInfo.buildNumber}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.geyserver.commit'>Commit Hash</Translate></b><br />
<a id='commit' target='_blank' href={'https://github.com/GeyserMC/Geyser/commit/' + data.gitInfo['git.commit.id']}>{data.gitInfo['git.commit.id.abbrev']}</a>
</div>
<div>
<b><Translate id='pages.dumpviewer.geyserver.branch'>Branch</Translate></b><br />
<p id='branch'>{data.gitInfo['git.branch']}</p>
</div>
</Grid>
</div>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.platform'>Platform Info</Translate>
</div>
<div className={styles.cardBody}>
<Grid elementsPerRow={5} gap='8px'>
<div>
<b><Translate id='pages.dumpviewer.platform.id'>Platform Identifier</Translate></b><br />
<p id='platformIdentifier'>{data.bootstrapInfo.platform.platformName || data.bootstrapInfo.platform}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.platform.name'>Platform Name</Translate></b><br />
<p id='platformName'>{data.bootstrapInfo.platformName ?? capitalizeFirstLetter(data.bootstrapInfo.platform.toLowerCase())}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.platform.version'>Platform Version</Translate></b><br />
<p id='platformVersion'>{data.bootstrapInfo.platformVersion ?? 'N/A'}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.platform.apiver'>Platform API Version</Translate></b><br />
<p id='platformAPIVersion'>{data.bootstrapInfo.platformAPIVersion ?? 'N/A'}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.platform.onlinemode'>Online Mode</Translate></b><br />
<p id='onlineMode'>{data.bootstrapInfo.onlineMode !== null ? data.bootstrapInfo.onlineMode ? 'true' : 'false' : 'N/A'}</p>
</div>
</Grid>
</div>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.sysinfo'>System Info</Translate>
</div>
<div className={styles.cardBody}>
<Grid elementsPerRow={3} gap='8px'>
<div>
<b><Translate id='pages.dumpviewer.cpucount'>CPU Count</Translate></b><br />
<p id='cpuCount'>{data.cpuCount}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.cpuname'>CPU Name</Translate></b><br />
<p id='cpuName'>{data.cpuName}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.ram'>RAM</Translate></b><br />
<p id='ram'>{data.ramInfo.total} MB ({data.ramInfo.free} MB free)</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.javaname'>Java Name</Translate></b><br />
<p id='javaName'>{data.versionInfo.javaName}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.javavendor'>Java Vendor</Translate></b><br />
<p id='javaVendor'>{data.versionInfo.javaVendor}</p>
</div>
<div>
<b><Translate id='pages.dumpviewer.dockercheck'>Uses Docker?</Translate></b><br />
<p id='dockerCheck'>{data.versionInfo.network.dockerCheck ? "true" : "false"}</p>
</div>
</Grid>
</div>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.plugins'>Plugins</Translate> ({data.bootstrapInfo.plugins.length})
</div>
<div className={styles.cardBody}>
{data.bootstrapInfo.plugins.length === 0 ? <p><Translate id='pages.dumpviewer.plugins.noplugins'>No plugins to show.</Translate></p> : (
<>
<p><Translate id='pages.dumpviewer.plugins.helptext'>Click on a plugin to view more information.</Translate></p>
<Grid elementsPerRow={5}>
{data.bootstrapInfo.plugins.map(plugin => (
<div>
<b onClick={() => handlePluginClick(plugin)} className={styles.pluginName}>
{plugin.name} <div className={styles.pluginEnabledIndicator} style={{ backgroundColor: plugin.enabled ? "green" : "red" }} />
</b>
{activePlugin?.main === plugin.main ? (
<div ref={pluginPopoverRef} className={styles.pluginInfoPopover}>
<p className={styles.pluginNamePopover}>{plugin.name}</p>
<p>{plugin.version}</p>
<p className={styles.pluginEnabled} style={{ backgroundColor: plugin.enabled ? "green" : "red" }}>{plugin.enabled ? "Enabled" : "Disabled"}</p>
<p className={styles.pluginAuthorsLabel}>Authors:</p>
<ul>
{plugin.authors.map(author => <li>{author}</li>)}
</ul>
</div>
) : undefined}
</div>
))}
</Grid>
</>
)}
</div>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Translate id='pages.dumpviewer.config'>Config</Translate>
</div>
<div className={styles.cardBody}>
<CodeBlock
language='json'
showLineNumbers
>
{JSON.stringify(data.config, null, 2)}
</CodeBlock>
</div>
</div>
</div>
<a target="_blank" href={`https://dump.geysermc.org/${dumpId}`} className={styles.viewDumpSource}><Translate id="pages.dumpviewer.viewsource">View dump source</Translate> {'>'}</a>
</div>
</>
)}
</div>
</>
)
}
export default function DumpViewer(): JSX.Element {
return (
<Layout
title={`Dump Viewer`}
description='View the breakdown of your Geyser dump.'
>
<main>
<div className='container container--fluid margin-vert--lg'>
<DumpViewerPage />
</div>
</main>
</Layout>
)
}
+110
View File
@@ -0,0 +1,110 @@
:root {
--card-bg-color: #f7f5f5;
}
[data-theme='dark'] {
--card-bg-color: #0b1215 !important;
}
.buttonsContainer {
display: flex;
gap: 10px;
}
.card {
margin-bottom: 30px;
background-color: var(--card-bg-color);
}
.cardHeader {
background-color: var(--ifm-color-primary);
color: white;
padding-left: 16px;
font-size: 22px;
text-transform: capitalize;
}
.cardBody {
padding: 16px;
}
.configOption {
padding-bottom: 20px;
padding-top: 20px;
border-bottom: 1px solid gray;
}
.configOption:last-child {
border-bottom: none;
}
.loadButton {
width: 150px;
outline: 3px solid var(--ifm-tabs-color-active);
outline-offset: -3px;
border: 0;
border-radius: var(--ifm-global-radius);
background-color: transparent;
text-align: center;
font-size: 18px;
font-weight: normal;
transition: background-color 0.5s ease, color 0.5s ease;
padding-top: 10px;
padding-bottom: 10px;
color: var(--ifm-tabs-color-active);
margin-left: 5px;
}
.loadButton:hover {
background-color: var(--ifm-color-primary);
color: #fff;
}
.statusMessage {
margin-top: 20px;
}
.pluginName:hover {
cursor: pointer;
}
.pluginInfoPopover {
position: absolute;
background-color: white;
color: black;
padding: 16px;
z-index: 1000;
min-width: 300px;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
}
.pluginInfoPopover p {
margin: 0;
}
.pluginNamePopover {
font-size: 18px;
font-weight: bold;
}
.pluginEnabled {
border-radius: 10px;
padding: 0 10px;
width: fit-content;
color: white;
}
.pluginAuthorsLabel {
padding-top: 15px;
}
.viewDumpSource {
}
.pluginEnabledIndicator {
display: inline-block;
height: 10px;
width: 10px;
border-radius: 50%;
}
+1 -1
View File
@@ -11911,4 +11911,4 @@ zwitch@^1.0.0:
zwitch@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==
integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==