Skip to content

Commit bfcfb3c

Browse files
committed
refactor
1 parent 435b35b commit bfcfb3c

File tree

4 files changed

+86
-71
lines changed

4 files changed

+86
-71
lines changed

web_ui/app.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
Main Sanic application with htpy templates and Datastar integration
44
"""
55

6-
from sanic import Sanic, Request
7-
from sanic.response import html, json
8-
from sanic_ext import Extend
9-
from datastar_py.sanic import ServerSentEventGenerator, datastar_respond, SSE_HEADERS
10-
import htpy as h
116
import asyncio
12-
from typing import List, Dict, Any
137
import json as json_module
148
import os
15-
from datetime import datetime
169
import uuid
10+
from datetime import datetime
11+
from typing import Any, Dict, List
12+
13+
import htpy as h
14+
from datastar_py.sanic import (SSE_HEADERS, ServerSentEventGenerator,
15+
datastar_respond)
16+
from sanic import Request, Sanic
17+
from sanic.response import html, json
18+
from sanic_ext import Extend
1719

1820
# Initialize Sanic app
1921
app = Sanic("FlowerPowerWeb")

web_ui/config.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,80 +3,93 @@
33
"""
44

55
import os
6-
from typing import Dict, Any
6+
from typing import Any, Dict
7+
78

89
class Config:
910
"""Base configuration class"""
10-
11+
1112
# Server settings
1213
HOST = os.getenv("FLOWERPOWER_WEB_HOST", "0.0.0.0")
1314
PORT = int(os.getenv("FLOWERPOWER_WEB_PORT", "8000"))
1415
DEBUG = os.getenv("FLOWERPOWER_WEB_DEBUG", "true").lower() == "true"
15-
16+
1617
# Application settings
1718
APP_NAME = "FlowerPowerWeb"
1819
VERSION = "1.0.0"
19-
20+
2021
# CORS settings
2122
CORS_ORIGINS = os.getenv("FLOWERPOWER_WEB_CORS_ORIGINS", "*")
22-
23+
2324
# Static files
2425
STATIC_DIR = os.path.join(os.path.dirname(__file__), "static")
25-
26+
2627
# Database settings (for future use)
2728
DATABASE_URL = os.getenv("FLOWERPOWER_DATABASE_URL", "sqlite:///flowerpower.db")
28-
29+
2930
# Security settings
30-
SECRET_KEY = os.getenv("FLOWERPOWER_SECRET_KEY", "dev-secret-key-change-in-production")
31-
31+
SECRET_KEY = os.getenv(
32+
"FLOWERPOWER_SECRET_KEY", "dev-secret-key-change-in-production"
33+
)
34+
3235
# Datastar settings
3336
DATASTAR_STREAM_ENDPOINT = "/datastar/stream"
34-
37+
3538
# Pagination settings
3639
PROJECTS_PER_PAGE = int(os.getenv("FLOWERPOWER_PROJECTS_PER_PAGE", "10"))
37-
40+
3841
@classmethod
3942
def get_settings(cls) -> Dict[str, Any]:
4043
"""Get all configuration settings as a dictionary"""
4144
return {
4245
key: getattr(cls, key)
4346
for key in dir(cls)
44-
if not key.startswith('_') and not callable(getattr(cls, key))
47+
if not key.startswith("_") and not callable(getattr(cls, key))
4548
}
4649

50+
4751
class DevelopmentConfig(Config):
4852
"""Development configuration"""
53+
4954
DEBUG = True
5055
HOST = "127.0.0.1"
5156

57+
5258
class ProductionConfig(Config):
5359
"""Production configuration"""
60+
5461
DEBUG = False
5562
SECRET_KEY = os.getenv("FLOWERPOWER_SECRET_KEY")
56-
63+
5764
@classmethod
5865
def validate(cls):
5966
"""Validate production configuration"""
6067
if not os.getenv("FLOWERPOWER_SECRET_KEY"):
61-
raise ValueError("FLOWERPOWER_SECRET_KEY environment variable must be set in production")
68+
raise ValueError(
69+
"FLOWERPOWER_SECRET_KEY environment variable must be set in production"
70+
)
71+
6272

6373
class TestingConfig(Config):
6474
"""Testing configuration"""
75+
6576
DEBUG = True
6677
TESTING = True
6778
DATABASE_URL = "sqlite:///:memory:"
6879

80+
6981
# Configuration mapping
7082
config = {
71-
'development': DevelopmentConfig,
72-
'production': ProductionConfig,
73-
'testing': TestingConfig,
74-
'default': DevelopmentConfig
83+
"development": DevelopmentConfig,
84+
"production": ProductionConfig,
85+
"testing": TestingConfig,
86+
"default": DevelopmentConfig,
7587
}
7688

89+
7790
def get_config(config_name: str = None) -> Config:
7891
"""Get configuration class based on environment"""
7992
if config_name is None:
80-
config_name = os.getenv('FLOWERPOWER_WEB_ENV', 'default')
81-
82-
return config.get(config_name, DevelopmentConfig)
93+
config_name = os.getenv("FLOWERPOWER_WEB_ENV", "default")
94+
95+
return config.get(config_name, DevelopmentConfig)

web_ui/run.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,22 @@
33
Startup script for FlowerPower Web UI
44
"""
55

6-
import sys
76
import subprocess
7+
import sys
88
from pathlib import Path
99

10+
1011
def check_dependencies():
1112
"""Check if required dependencies are installed"""
12-
required_packages = [
13-
'sanic',
14-
'htpy',
15-
'datastar_py'
16-
]
17-
13+
required_packages = ["sanic", "htpy", "datastar_py"]
14+
1815
missing_packages = []
1916
for package in required_packages:
2017
try:
2118
__import__(package)
2219
except ImportError:
2320
missing_packages.append(package)
24-
21+
2522
if missing_packages:
2623
print("❌ Missing required packages:")
2724
for package in missing_packages:
@@ -31,38 +28,41 @@ def check_dependencies():
3128
print(" # or with uv:")
3229
print(" uv pip install -r requirements.txt")
3330
return False
34-
31+
3532
print("✅ All dependencies are installed")
3633
return True
3734

35+
3836
def main():
3937
"""Main startup function"""
4038
print("🌸 FlowerPower Web UI Startup")
4139
print("=" * 40)
42-
40+
4341
# Check if we're in the right directory
4442
if not Path("app.py").exists():
4543
print("❌ Error: app.py not found")
4644
print("💡 Make sure you're running this from the web_ui directory")
4745
sys.exit(1)
48-
46+
4947
# Check dependencies
5048
if not check_dependencies():
5149
sys.exit(1)
52-
50+
5351
# Start the application
5452
print("\n🚀 Starting FlowerPower Web UI...")
5553
print("📍 URL: http://localhost:8000")
5654
print("🛑 Press Ctrl+C to stop\n")
57-
55+
5856
try:
5957
from app import app
58+
6059
app.run(host="0.0.0.0", port=8000, debug=True)
6160
except KeyboardInterrupt:
6261
print("\n👋 FlowerPower Web UI stopped")
6362
except Exception as e:
6463
print(f"❌ Error starting application: {e}")
6564
sys.exit(1)
6665

66+
6767
if __name__ == "__main__":
68-
main()
68+
main()

web_ui/test_app.py

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,128 +4,128 @@
44

55
import asyncio
66
import json
7+
78
from app import app
89

10+
911
async def test_routes():
1012
"""Test basic route accessibility"""
1113
print("🧪 Testing FlowerPower Web UI Routes")
1214
print("=" * 40)
13-
15+
1416
# Create test client
1517
request, response = await app.asgi_client.get("/")
1618
assert response.status == 200
1719
assert "FlowerPower" in response.text
1820
print("✅ Home page loads correctly")
19-
21+
2022
# Test projects list
2123
request, response = await app.asgi_client.get("/projects")
2224
assert response.status == 200
2325
assert "Projects" in response.text
2426
print("✅ Projects page loads correctly")
25-
27+
2628
# Test new project form
2729
request, response = await app.asgi_client.get("/projects/new")
2830
assert response.status == 200
2931
assert "Create New Project" in response.text
3032
print("✅ New project form loads correctly")
31-
33+
3234
# Test API endpoint
3335
request, response = await app.asgi_client.get("/api/projects")
3436
assert response.status == 200
3537
data = json.loads(response.text)
3638
assert "projects" in data
3739
print("✅ API endpoint works correctly")
38-
40+
3941
# Test project detail
4042
request, response = await app.asgi_client.get("/projects/1")
4143
assert response.status == 200
4244
print("✅ Project detail page loads correctly")
43-
45+
4446
# Test non-existent project
4547
request, response = await app.asgi_client.get("/projects/999")
4648
assert response.status == 200
4749
assert "Project Not Found" in response.text
4850
print("✅ 404 handling works correctly")
49-
51+
5052
print("\n🎉 All tests passed!")
5153

54+
5255
async def test_project_creation():
5356
"""Test project creation via form submission"""
5457
print("\n🧪 Testing Project Creation")
5558
print("=" * 30)
56-
59+
5760
# Test valid project creation
58-
form_data = {
59-
"name": "Test Project",
60-
"description": "A test project for validation"
61-
}
62-
61+
form_data = {"name": "Test Project", "description": "A test project for validation"}
62+
6363
request, response = await app.asgi_client.post("/projects", data=form_data)
6464
assert response.status == 200
6565
data = json.loads(response.text)
6666
assert data["status"] == "success"
6767
print("✅ Project creation works correctly")
68-
68+
6969
# Test empty name validation
70-
form_data = {
71-
"name": "",
72-
"description": "Project with empty name"
73-
}
74-
70+
form_data = {"name": "", "description": "Project with empty name"}
71+
7572
request, response = await app.asgi_client.post("/projects", data=form_data)
7673
assert response.status == 200
7774
data = json.loads(response.text)
7875
assert data["status"] == "error"
7976
print("✅ Empty name validation works correctly")
80-
77+
8178
print("\n🎉 Project creation tests passed!")
8279

80+
8381
def test_template_generation():
8482
"""Test htpy template generation"""
8583
print("\n🧪 Testing Template Generation")
8684
print("=" * 30)
87-
85+
8886
from app import base_layout, project_card
8987
from htpy import html as h
90-
88+
9189
# Test base layout
9290
content = h.div("Test content")
9391
layout = base_layout("Test Page", content)
9492
assert "Test Page - FlowerPower" in layout
9593
assert "Test content" in layout
9694
assert "data-ds-stream" in layout
9795
print("✅ Base layout generation works correctly")
98-
96+
9997
# Test project card
10098
test_project = {
10199
"id": 1,
102100
"name": "Test Project",
103101
"description": "Test description",
104-
"created_at": "2025-01-23T12:00:00Z"
102+
"created_at": "2025-01-23T12:00:00Z",
105103
}
106-
104+
107105
card_html = str(project_card(test_project))
108106
assert "Test Project" in card_html
109107
assert "Test description" in card_html
110108
assert "2025-01-23" in card_html
111109
print("✅ Project card generation works correctly")
112-
110+
113111
print("\n🎉 Template generation tests passed!")
114112

113+
115114
async def main():
116115
"""Run all tests"""
117116
try:
118117
test_template_generation()
119118
await test_routes()
120119
await test_project_creation()
121-
120+
122121
print("\n" + "=" * 50)
123122
print("🎉 All FlowerPower Web UI tests passed!")
124123
print("✨ Application is ready for deployment")
125-
124+
126125
except Exception as e:
127126
print(f"\n❌ Test failed: {e}")
128127
raise
129128

129+
130130
if __name__ == "__main__":
131-
asyncio.run(main())
131+
asyncio.run(main())

0 commit comments

Comments
 (0)