feat: initial commit

This commit is contained in:
nikola
2026-05-19 14:53:39 +02:00
commit 6d1b20c4b0
90 changed files with 243385 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Wolkabout GDrive Visual Inspector</title>
<style>
:root {
--bg: #ebf1f5;
--panel: #ffffff;
--ink: #0f172a;
--muted: #4b5563;
--line: #d5dde6;
--accent: #0f766e;
--accent-2: #1d4ed8;
--danger: #b91c1c;
--shadow: 0 8px 24px rgba(15,23,42,.08);
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
color: var(--ink);
background:
radial-gradient(1200px 500px at 5% -20%, #dce8ef 0%, transparent 60%),
radial-gradient(1100px 500px at 105% 0%, #d9efe9 0%, transparent 58%),
var(--bg);
}
.wrap { width: 100%; max-width: none; margin: 0; padding: 14px; }
.panel {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 14px;
box-shadow: var(--shadow);
padding: 14px;
}
.header {
display: grid;
grid-template-columns: 1.4fr 1fr;
gap: 12px;
align-items: stretch;
}
.title { font-size: 1.65rem; font-weight: 800; margin: 0 0 5px; }
.subtitle { color: var(--muted); margin: 0; }
.upload-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 10px; }
input[type="file"] { border: 1px dashed #bcc8d6; background: #f8fafc; border-radius: 9px; padding: 10px; min-width: 280px; }
button, .btn {
border: 0;
border-radius: 9px;
padding: 10px 14px;
font-weight: 700;
text-decoration: none;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
}
button { background: var(--accent); color: #fff; }
.btn.secondary { background: var(--accent-2); color: #fff; }
.stats {
margin-top: 12px;
display: grid;
grid-template-columns: repeat(auto-fit,minmax(170px,1fr));
gap: 8px;
}
.stat { border: 1px solid var(--line); border-radius: 10px; padding: 10px; background: #f8fbfe; }
.k { color: var(--muted); font-size: .76rem; text-transform: uppercase; letter-spacing: .04em; }
.v { font-size: 1.23rem; font-weight: 800; margin-top: 3px; }
.error {
margin-top: 10px;
border: 1px solid #fecaca;
background: #fef2f2;
color: var(--danger);
border-radius: 10px;
padding: 10px 12px;
font-weight: 600;
}
.diagram-wrap { margin-top: 12px; }
iframe {
width: 100%;
height: 860px;
border: 1px solid var(--line);
border-radius: 14px;
background: #fff;
box-shadow: var(--shadow);
}
.small { color: var(--muted); font-size: .9rem; margin-top: 6px; }
.info-panel {
margin-top: 10px;
border: 1px solid var(--line);
border-radius: 10px;
background: #f8fbfe;
padding: 10px;
}
.info-panel .row {
font-size: .9rem;
margin: 5px 0;
color: #1f2937;
}
.status-title { font-weight: 800; margin-bottom: 8px; }
.status-grid {
display: grid;
grid-template-columns: repeat(2,minmax(0,1fr));
gap: 8px;
}
.status-box {
border: 1px solid var(--line);
border-radius: 10px;
background: #f8fbfe;
padding: 8px 10px;
font-size: .85rem;
color: #1f2937;
}
.status-box b { display:block; color:#334155; margin-bottom: 2px; font-size: .76rem; text-transform: uppercase; letter-spacing: .03em; }
@media (max-width: 1100px) {
.header { grid-template-columns: 1fr; }
iframe { height: 72vh; }
}
</style>
</head>
<body>
<div class="wrap">
<div class="header">
<section class="panel">
<h1 class="title">Wolkabout GDrive Visual Inspector</h1>
<p class="subtitle">Upload GAM CSV -> auto-parse -> interactive org-chart diagram + CSV exports</p>
<form class="upload-form" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="csv_file" accept=".csv" required />
<button type="submit">Upload And Generate</button>
{% if has_data %}
<a class="btn secondary" href="{{ cleaned_path }}">Download Cleaned CSV</a>
<a class="btn secondary" href="{{ summary_path }}">Download Summary CSV</a>
<a class="btn secondary" href="{{ sharing_matrix_path }}">Download Sharing Matrix CSV</a>
{% endif %}
</form>
<div class="small">Use tree + sunburst for structure, and share network for access flow.</div>
{% if error %}
<div class="error">{{ error }}</div>
{% endif %}
{% if has_data %}
<div class="stats">
<div class="stat"><div class="k">Total items</div><div class="v">{{ stats.total_items }}</div></div>
<div class="stat"><div class="k">Folders</div><div class="v">{{ stats.total_folders }}</div></div>
<div class="stat"><div class="k">Public</div><div class="v">{{ stats.public_items }}</div></div>
<div class="stat"><div class="k">Domain</div><div class="v">{{ stats.domain_items }}</div></div>
<div class="stat"><div class="k">Shared users</div><div class="v">{{ stats.shared_user_items }}</div></div>
</div>
<div class="small">Tip: click a folder/file to sync tree, sunburst and network on the same item.</div>
{% endif %}
</section>
<section class="panel">
<div class="status-title">Live Status</div>
<div class="status-grid">
<div class="status-box"><b>Build ID</b>{{ build_id or "-" }}</div>
<div class="status-box"><b>Rows Parsed</b>{{ curated_count or "-" }}</div>
<div class="status-box"><b>Last Upload</b>{{ last_upload_time or "-" }}</div>
<div class="status-box"><b>Processing Time</b>{{ process_ms or "-" }} ms</div>
</div>
<div class="small" style="margin-top:10px;">This panel is informational and updates after each CSV upload.</div>
{% if build_id %}
<div class="small" style="margin-top:8px;"><b>Status ID:</b> {{ build_id }}</div>
{% endif %}
</section>
</div>
{% if has_data %}
<div class="diagram-wrap">
<iframe src="{{ explorer_url or explorer_path }}"></iframe>
</div>
{% endif %}
</div>
</body>
</html>