mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-26 15:46:28 +00:00
Implement instance tree visualization
This commit is contained in:
@@ -11,22 +11,29 @@
|
|||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width:100%;
|
||||||
|
max-height:100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 0 auto;
|
margin: 0.5rem auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 50rem;
|
max-width: 50rem;
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
@@ -48,8 +55,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-logo {
|
.main-logo {
|
||||||
flex: 0 0;
|
flex: 0 0 10rem;
|
||||||
width: 10rem;
|
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +77,8 @@ body {
|
|||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: space-around;
|
||||||
|
margin: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@@ -80,3 +87,24 @@ body {
|
|||||||
padding: 0.3em 1em;
|
padding: 0.3em 1em;
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instance {
|
||||||
|
border: 1px solid #666;
|
||||||
|
border-right-style: none;
|
||||||
|
border-bottom-style: none;
|
||||||
|
background-color: #fff;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance-properties {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance-children {
|
||||||
|
padding: 0.5rem 0 0.5rem 1rem;
|
||||||
|
}
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::{fs, path::Path};
|
|
||||||
|
|
||||||
static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png");
|
static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png");
|
||||||
static ICON: &[u8] = include_bytes!("../../assets/icon-32.png");
|
static ICON: &[u8] = include_bytes!("../../assets/icon-32.png");
|
||||||
static HOME_CSS: &str = include_str!("../../assets/index.css");
|
static HOME_CSS: &str = include_str!("../../assets/index.css");
|
||||||
@@ -8,12 +6,14 @@ macro_rules! declare_asset {
|
|||||||
($name: ident, $path: expr) => {
|
($name: ident, $path: expr) => {
|
||||||
pub fn $name() -> &'static str {
|
pub fn $name() -> &'static str {
|
||||||
if cfg!(feature = "dev-live-assets") {
|
if cfg!(feature = "dev-live-assets") {
|
||||||
|
use std::{fs::read_to_string, path::Path};
|
||||||
|
|
||||||
let file_path = Path::new(file!());
|
let file_path = Path::new(file!());
|
||||||
let asset_path = file_path.parent().unwrap().join($path);
|
let asset_path = file_path.parent().unwrap().join($path);
|
||||||
|
|
||||||
println!("Reloading {}", asset_path.display());
|
println!("Reloading {}", asset_path.display());
|
||||||
|
|
||||||
let content = fs::read_to_string(asset_path)
|
let content = read_to_string(asset_path)
|
||||||
.expect("Couldn't read dev live asset")
|
.expect("Couldn't read dev live asset")
|
||||||
.into_boxed_str();
|
.into_boxed_str();
|
||||||
|
|
||||||
|
|||||||
100
src/web/ui.rs
100
src/web/ui.rs
@@ -4,11 +4,13 @@ use std::{sync::Arc, time::Duration};
|
|||||||
|
|
||||||
use futures::{future, Future};
|
use futures::{future, Future};
|
||||||
use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode};
|
use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode};
|
||||||
use ritz::{html, HtmlContent};
|
use rbx_dom_weak::{RbxId, RbxValue};
|
||||||
|
use ritz::{html, Fragment, HtmlContent};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imfs::ImfsFetcher,
|
imfs::ImfsFetcher,
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
|
snapshot::RojoTree,
|
||||||
web::{
|
web::{
|
||||||
assets,
|
assets,
|
||||||
interface::{ErrorResponse, SERVER_VERSION},
|
interface::{ErrorResponse, SERVER_VERSION},
|
||||||
@@ -80,19 +82,103 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_show_instances(&self) -> Response<Body> {
|
fn handle_show_instances(&self) -> Response<Body> {
|
||||||
|
let tree = self.serve_session.tree();
|
||||||
|
let root_id = tree.get_root_id();
|
||||||
|
|
||||||
|
let page = self.normal_page(html! {
|
||||||
|
{ Self::instance(&tree, root_id) }
|
||||||
|
});
|
||||||
|
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.header(header::CONTENT_TYPE, "text/plain")
|
.header(header::CONTENT_TYPE, "text/html")
|
||||||
.body(Body::from("TODO: /show-instances"))
|
.body(Body::from(format!("<!DOCTYPE html>{}", page)))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_show_imfs(&self) -> Response<Body> {
|
fn handle_show_imfs(&self) -> Response<Body> {
|
||||||
|
let page = self.normal_page(html! {
|
||||||
|
"TODO /show/imfs"
|
||||||
|
});
|
||||||
|
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.header(header::CONTENT_TYPE, "text/plain")
|
.header(header::CONTENT_TYPE, "text/html")
|
||||||
.body(Body::from("TODO: /show-imfs"))
|
.body(Body::from(format!("<!DOCTYPE html>{}", page)))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn instance(tree: &RojoTree, id: RbxId) -> HtmlContent<'_> {
|
||||||
|
let instance = tree.get_instance(id).unwrap();
|
||||||
|
let children_list: Vec<_> = instance
|
||||||
|
.children()
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(|id| Self::instance(tree, id))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let children_container = if children_list.is_empty() {
|
||||||
|
HtmlContent::None
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
<div class="instance-children">
|
||||||
|
{ Fragment::new(children_list) }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut properties: Vec<_> = instance.properties().iter().collect();
|
||||||
|
properties.sort_by_key(|pair| pair.0);
|
||||||
|
|
||||||
|
let property_list: Vec<_> = properties
|
||||||
|
.into_iter()
|
||||||
|
.map(|(key, value)| {
|
||||||
|
html! {
|
||||||
|
<div class="instance-property" title={ Self::display_value(value) }>
|
||||||
|
{ key.clone() } ": " { format!("{:?}", value.get_type()) }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let property_container = if property_list.is_empty() {
|
||||||
|
HtmlContent::None
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
<div class="instance-properties">
|
||||||
|
{ Fragment::new(property_list) }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let class_name_specifier = if instance.name() == instance.class_name() {
|
||||||
|
HtmlContent::None
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
<span>
|
||||||
|
" (" { instance.class_name().to_owned() } ")"
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<div class="instance">
|
||||||
|
<div class="instance-title">
|
||||||
|
{ instance.name().to_owned() }
|
||||||
|
{ class_name_specifier }
|
||||||
|
</div>
|
||||||
|
{ property_container }
|
||||||
|
{ children_container }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_value(value: &RbxValue) -> String {
|
||||||
|
match value {
|
||||||
|
RbxValue::String { value } => value.clone(),
|
||||||
|
RbxValue::Bool { value } => value.to_string(),
|
||||||
|
_ => format!("{:?}", value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn stat_item<S: Into<String>>(name: &str, value: S) -> HtmlContent<'_> {
|
fn stat_item<S: Into<String>>(name: &str, value: S) -> HtmlContent<'_> {
|
||||||
html! {
|
html! {
|
||||||
<span class="stat">
|
<span class="stat">
|
||||||
@@ -124,7 +210,9 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
Self::page(html! {
|
Self::page(html! {
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<img class="main-logo" src="/logo.png" />
|
<a class="main-logo" href="/">
|
||||||
|
<img src="/logo.png" />
|
||||||
|
</a>
|
||||||
<div class="stats">
|
<div class="stats">
|
||||||
{ Self::stat_item("Server Version", SERVER_VERSION) }
|
{ Self::stat_item("Server Version", SERVER_VERSION) }
|
||||||
{ Self::stat_item("Project", project_name) }
|
{ Self::stat_item("Project", project_name) }
|
||||||
|
|||||||
Reference in New Issue
Block a user