Skip to content

Commit

Permalink
update ui
Browse files Browse the repository at this point in the history
  • Loading branch information
XiangpengHao committed Nov 7, 2024
1 parent 2bb0e1c commit bf08561
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/info_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn InfoSection(parquet_info: super::ParquetInfo) -> impl IntoView {
view! {
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-semibold mb-4">"Basic Information"</h2>
<div class="grid grid-cols-2 gap-4">
<div class="grid grid-cols-2 gap-4 bg-gray-50 p-4 rounded-md mb-8">
<div class="space-y-2">
<span class="text-gray-600 text-sm">"File size"</span>
<span class="block font-medium">
Expand Down
27 changes: 23 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,22 @@ fn stats_to_string(stats: Option<Statistics>) -> String {
parts.push(format!("max: {:.2}", max));
}
}
_ => {}
Statistics::ByteArray(s) => {
s.min_opt()
.and_then(|min| min.as_utf8().ok())
.map(|min_utf8| parts.push(format!("min: {:?}", min_utf8)));
s.max_opt()
.and_then(|max| max.as_utf8().ok())
.map(|max_utf8| parts.push(format!("max: {:?}", max_utf8)));
}
Statistics::FixedLenByteArray(s) => {
s.min_opt()
.and_then(|min| min.as_utf8().ok())
.map(|min_utf8| parts.push(format!("min: {:?}", min_utf8)));
s.max_opt()
.and_then(|max| max.as_utf8().ok())
.map(|max_utf8| parts.push(format!("max: {:?}", max_utf8)));
}
}

if let Some(null_count) = stats.null_count_opt() {
Expand Down Expand Up @@ -408,9 +423,13 @@ fn App() -> impl IntoView {
match info {
Some(info) => {
view! {
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<InfoSection parquet_info=info.clone() />
<SchemaSection parquet_info=info.clone() />
<div class="flex gap-6">
<div class="w-96 flex-none">
<InfoSection parquet_info=info.clone() />
</div>
<div class="flex-1">
<SchemaSection parquet_info=info.clone() />
</div>
</div>
}
.into_view()
Expand Down
130 changes: 104 additions & 26 deletions src/schema_section.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
use leptos::*;

#[derive(Clone, Debug, PartialEq)]
struct ColumnData {
id: usize,
name: String,
data_type: String,
compressed_size: u64,
uncompressed_size: u64,
compression_ratio: f64,
}

#[derive(Clone, Copy, PartialEq)]
enum SortField {
Id,
Name,
DataType,
CompressedSize,
UncompressedSize,
CompressionRatio,
}

#[component]
pub fn SchemaSection(parquet_info: super::ParquetInfo) -> impl IntoView {
let schema = parquet_info.schema.clone();
Expand All @@ -14,6 +34,64 @@ pub fn SchemaSection(parquet_info: super::ParquetInfo) -> impl IntoView {
}
}

let (sort_field, set_sort_field) = create_signal(SortField::Id);
let (sort_ascending, set_sort_ascending) = create_signal(true);

// Transform the data into ColumnData structs
let column_data = create_memo(move |_| {
let mut data: Vec<ColumnData> = schema
.fields
.iter()
.enumerate()
.map(|(i, field)| {
let compressed = column_info[i].0;
let uncompressed = column_info[i].1;
ColumnData {
id: i,
name: field.name().to_string(),
data_type: format!("{}", field.data_type()),
compressed_size: compressed,
uncompressed_size: uncompressed,
compression_ratio: if uncompressed > 0 {
compressed as f64 / uncompressed as f64
} else {
0.0
},
}
})
.collect();

// Sort the data based on current sort field
data.sort_by(|a, b| {
let cmp = match sort_field.get() {
SortField::Id => a.id.cmp(&b.id),
SortField::Name => a.name.cmp(&b.name),
SortField::DataType => a.data_type.cmp(&b.data_type),
SortField::CompressedSize => a.compressed_size.cmp(&b.compressed_size),
SortField::UncompressedSize => a.uncompressed_size.cmp(&b.uncompressed_size),
SortField::CompressionRatio => a
.compression_ratio
.partial_cmp(&b.compression_ratio)
.unwrap(),
};
if sort_ascending.get() {
cmp
} else {
cmp.reverse()
}
});
data
});

let sort_by = move |field: SortField| {
if sort_field.get() == field {
set_sort_ascending.update(|v| *v = !*v);
} else {
set_sort_field.set(field);
set_sort_ascending.set(true);
}
};

fn format_size(size: u64) -> String {
if size > 1_048_576 {
// 1MB
Expand All @@ -28,31 +106,31 @@ pub fn SchemaSection(parquet_info: super::ParquetInfo) -> impl IntoView {

view! {
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-semibold mb-4">"Arrow schema"</h2>
<div class="space-y-2">
{schema
.fields
.into_iter()
.enumerate()
.map(|(i, field)| {
let data_type_name = format!("{}", field.data_type());
let output = format!(
"{}/{}",
format_size(column_info[i].0),
format_size(column_info[i].1),
);
view! {
<div class="flex items-center justify-between p-2 hover:bg-gray-50 rounded">
<div class="flex flex-col">
<span class="text-gray-700">{format!("{}.{}", i, field.name())}</span>
<span class="text-xs text-gray-400">{output}</span>
</div>
<span class="text-sm text-gray-500">{data_type_name}</span>
</div>
}
})
.collect::<Vec<_>>()}
</div>
<h2 class="text-xl font-semibold mb-4">"Arrow Schema"</h2>
<table class="min-w-full">
<thead>
<tr class="bg-gray-50">
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::Id)>"ID"</th>
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::Name)>"Name"</th>
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::DataType)>"Type"</th>
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::CompressedSize)>"Compressed"</th>
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::UncompressedSize)>"Uncompressed"</th>
<th class="px-4 py-2 cursor-pointer hover:bg-gray-100" on:click=move |_| sort_by(SortField::CompressionRatio)>"Ratio"</th>
</tr>
</thead>
<tbody>
{move || column_data.get().into_iter().map(|col| view! {
<tr class="hover:bg-gray-50">
<td class="px-4 py-2 text-gray-700">{col.id}</td>
<td class="px-4 py-2 text-gray-700">{col.name}</td>
<td class="px-4 py-2 text-gray-500">{col.data_type}</td>
<td class="px-4 py-2 text-gray-500">{format_size(col.compressed_size)}</td>
<td class="px-4 py-2 text-gray-500">{format_size(col.uncompressed_size)}</td>
<td class="px-4 py-2 text-gray-500">{format!("{:.2}%", col.compression_ratio * 100.0)}</td>
</tr>
}).collect::<Vec<_>>()}
</tbody>
</table>
</div>
}
}
}

0 comments on commit bf08561

Please sign in to comment.