Fix dropdown menu duplicates and reorder items
- Fix CSS breakpoints to sync header tabs with dropdown menu visibility - Add missing apps (docs, sheet, slides, social) to hide/show logic - Remove incorrect paper breakpoint (not in header tabs) - Reorder dropdown: dynamic items first (header tab apps), then static items - Move People after dynamic items (after social) - Remove duplicate Social entry from dropdown menu - All 26 suite app folders have menu entries (no orphans)
This commit is contained in:
parent
a0817363c4
commit
03ced8e327
5 changed files with 49 additions and 177 deletions
49
PROMPT.md
49
PROMPT.md
|
|
@ -219,9 +219,9 @@ match x {
|
|||
```
|
||||
gb/
|
||||
├── botapp/ # Desktop app (Tauri)
|
||||
├── botserver/ # Main server (Axum API)
|
||||
├── botserver/ # Main server (Axum API) - port 8088
|
||||
├── botlib/ # Shared library
|
||||
├── botui/ # Web UI
|
||||
├── botui/ # Web UI server - port 3000
|
||||
├── botbook/ # Documentation
|
||||
├── bottest/ # Integration tests
|
||||
└── PROMPT.md # THIS FILE
|
||||
|
|
@ -229,6 +229,51 @@ gb/
|
|||
|
||||
---
|
||||
|
||||
## 🖥️ UI Architecture (botui + botserver)
|
||||
|
||||
### Two Servers During Development
|
||||
|
||||
| Server | Port | Purpose |
|
||||
|--------|------|---------|
|
||||
| **botui** | 3000 | Serves UI files + proxies API to botserver |
|
||||
| **botserver** | 8088 | Backend API + embedded UI fallback |
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
Browser → localhost:3000 → botui (serves HTML/CSS/JS)
|
||||
→ /api/* proxied to botserver:8088
|
||||
→ /suite/* served from botui/ui/suite/
|
||||
```
|
||||
|
||||
### Adding New Suite Apps
|
||||
|
||||
When adding a new app (e.g., `video`, `learn`):
|
||||
|
||||
1. Create folder: `botui/ui/suite/<appname>/`
|
||||
2. Add to `SUITE_DIRS` in `botui/src/ui_server/mod.rs`:
|
||||
```rust
|
||||
const SUITE_DIRS: &[&str] = &[
|
||||
"chat", "mail", "calendar", ...,
|
||||
"video", // ← add new app here
|
||||
"learn",
|
||||
];
|
||||
```
|
||||
3. Rebuild botui: `cargo build -p botui`
|
||||
4. Add menu entry in `botui/ui/suite/index.html`
|
||||
|
||||
### Hot Reload
|
||||
|
||||
- **UI files (HTML/CSS/JS)**: Edit & refresh browser (no restart)
|
||||
- **botui Rust code**: Rebuild + restart botui
|
||||
- **botserver Rust code**: Rebuild + restart botserver
|
||||
|
||||
### Production (Single Binary)
|
||||
|
||||
When `botui/ui/suite/` folder not found, botserver uses **embedded UI** compiled into binary via `rust-embed`.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 OFFLINE ERROR FIXING WORKFLOW
|
||||
|
||||
### Step 1: Analyze Error List
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit a8444f0d2400f60d966341c59a7a3df4577c69d2
|
||||
Subproject commit 1b0a5cbec7f4a0e8576757f36d04a89c80f9406a
|
||||
2
botui
2
botui
|
|
@ -1 +1 @@
|
|||
Subproject commit cb33a75d39f2cf53de952622f72e8e6ef4ea0690
|
||||
Subproject commit 80c91f63046dd5d11e2874bb355ec2d967a70b55
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"base_url": "http://localhost:8300",
|
||||
"default_org": {
|
||||
"id": "353226116074307598",
|
||||
"name": "default",
|
||||
"domain": "default.localhost"
|
||||
},
|
||||
"default_user": {
|
||||
"id": "admin",
|
||||
"username": "admin",
|
||||
"email": "admin@localhost",
|
||||
"password": "",
|
||||
"first_name": "Admin",
|
||||
"last_name": "User"
|
||||
},
|
||||
"admin_token": "XzjmsXoVy7mDKK8gyWtJNp3w3enVW3EKGPdfLbz0nX9vMsDpg27UtAROOcKMXsoc0fDwv98",
|
||||
"project_id": "",
|
||||
"client_id": "353226118456737806",
|
||||
"client_secret": "5uH0r2elIQ3xji4N4aTOARZjEDDUWC0cfIybGaFkvhwlA6gvygMHOdmodVg4K6PJ"
|
||||
}
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
LOCALES_DIR="${1:-locales}"
|
||||
BASE_LOCALE="${2:-en}"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
if [ ! -d "$LOCALES_DIR" ]; then
|
||||
echo -e "${RED}Error: Locales directory not found: $LOCALES_DIR${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$LOCALES_DIR/$BASE_LOCALE" ]; then
|
||||
echo -e "${RED}Error: Base locale not found: $LOCALES_DIR/$BASE_LOCALE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
extract_keys() {
|
||||
local file="$1"
|
||||
grep -E '^[a-z][a-z0-9-]*\s*=' "$file" 2>/dev/null | cut -d'=' -f1 | tr -d ' ' | sort -u
|
||||
}
|
||||
|
||||
count_keys() {
|
||||
local dir="$1"
|
||||
local count=0
|
||||
for file in "$dir"/*.ftl; do
|
||||
if [ -f "$file" ]; then
|
||||
local file_count
|
||||
file_count=$(extract_keys "$file" | wc -l)
|
||||
count=$((count + file_count))
|
||||
fi
|
||||
done
|
||||
echo "$count"
|
||||
}
|
||||
|
||||
echo "========================================"
|
||||
echo " General Bots i18n Coverage Report"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
base_count=$(count_keys "$LOCALES_DIR/$BASE_LOCALE")
|
||||
echo -e "Base locale: ${GREEN}$BASE_LOCALE${NC} ($base_count keys)"
|
||||
echo ""
|
||||
|
||||
declare -A all_base_keys
|
||||
for file in "$LOCALES_DIR/$BASE_LOCALE"/*.ftl; do
|
||||
if [ -f "$file" ]; then
|
||||
filename=$(basename "$file")
|
||||
while IFS= read -r key; do
|
||||
all_base_keys["$filename:$key"]=1
|
||||
done < <(extract_keys "$file")
|
||||
fi
|
||||
done
|
||||
|
||||
total_missing=0
|
||||
total_extra=0
|
||||
|
||||
for locale_dir in "$LOCALES_DIR"/*/; do
|
||||
locale=$(basename "$locale_dir")
|
||||
|
||||
if [ "$locale" = "$BASE_LOCALE" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
locale_count=$(count_keys "$locale_dir")
|
||||
|
||||
if [ "$base_count" -gt 0 ]; then
|
||||
coverage=$((locale_count * 100 / base_count))
|
||||
else
|
||||
coverage=0
|
||||
fi
|
||||
|
||||
if [ "$coverage" -ge 90 ]; then
|
||||
color=$GREEN
|
||||
elif [ "$coverage" -ge 50 ]; then
|
||||
color=$YELLOW
|
||||
else
|
||||
color=$RED
|
||||
fi
|
||||
|
||||
echo -e "Locale: ${color}$locale${NC} - $locale_count/$base_count keys (${coverage}%)"
|
||||
|
||||
missing_keys=()
|
||||
extra_keys=()
|
||||
|
||||
for file in "$LOCALES_DIR/$BASE_LOCALE"/*.ftl; do
|
||||
if [ -f "$file" ]; then
|
||||
filename=$(basename "$file")
|
||||
target_file="$locale_dir/$filename"
|
||||
|
||||
if [ ! -f "$target_file" ]; then
|
||||
while IFS= read -r key; do
|
||||
missing_keys+=("$filename: $key")
|
||||
done < <(extract_keys "$file")
|
||||
else
|
||||
while IFS= read -r key; do
|
||||
if ! grep -q "^$key\s*=" "$target_file" 2>/dev/null; then
|
||||
missing_keys+=("$filename: $key")
|
||||
fi
|
||||
done < <(extract_keys "$file")
|
||||
|
||||
while IFS= read -r key; do
|
||||
if ! grep -q "^$key\s*=" "$file" 2>/dev/null; then
|
||||
extra_keys+=("$filename: $key")
|
||||
fi
|
||||
done < <(extract_keys "$target_file")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_keys[@]} -gt 0 ]; then
|
||||
echo -e " ${RED}Missing keys (${#missing_keys[@]}):${NC}"
|
||||
for key in "${missing_keys[@]:0:10}"; do
|
||||
echo " - $key"
|
||||
done
|
||||
if [ ${#missing_keys[@]} -gt 10 ]; then
|
||||
echo " ... and $((${#missing_keys[@]} - 10)) more"
|
||||
fi
|
||||
total_missing=$((total_missing + ${#missing_keys[@]}))
|
||||
fi
|
||||
|
||||
if [ ${#extra_keys[@]} -gt 0 ]; then
|
||||
echo -e " ${YELLOW}Extra keys (${#extra_keys[@]}):${NC}"
|
||||
for key in "${extra_keys[@]:0:5}"; do
|
||||
echo " - $key"
|
||||
done
|
||||
if [ ${#extra_keys[@]} -gt 5 ]; then
|
||||
echo " ... and $((${#extra_keys[@]} - 5)) more"
|
||||
fi
|
||||
total_extra=$((total_extra + ${#extra_keys[@]}))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "========================================"
|
||||
echo " Summary"
|
||||
echo "========================================"
|
||||
echo "Base keys: $base_count"
|
||||
echo -e "Total missing: ${RED}$total_missing${NC}"
|
||||
echo -e "Total extra: ${YELLOW}$total_extra${NC}"
|
||||
|
||||
if [ "$total_missing" -eq 0 ] && [ "$total_extra" -eq 0 ]; then
|
||||
echo -e "${GREEN}All translations are complete!${NC}"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Add table
Reference in a new issue