internationalscholarsprogram commited on
Commit
9e57130
·
1 Parent(s): dbfc012

fix: layout refinements + update deps

Browse files

- Section labels: zero top-margin on first-child in section-block
- Bullets: remove duplicate disc via list-style:none!important, remove inline bullet char in school_profile
- Page numbers: light-blue (#1C75BC) footer color
- Remove 'Summary info' heading from university templates
- Bump all dependency floors to current stable versions
- Dockerfile base image python:3.11-slim -> 3.12-slim

Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM python:3.11-slim
2
 
3
  # Playwright/Chromium system dependencies
4
  RUN apt-get update && apt-get install -y --no-install-recommends \
 
1
+ FROM python:3.12-slim
2
 
3
  # Playwright/Chromium system dependencies
4
  RUN apt-get update && apt-get install -y --no-install-recommends \
app/core/database.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Database engine and session factory (SQLAlchemy).
2
+
3
+ Engine is created lazily to avoid crash on startup when no DB is available
4
+ (e.g. Hugging Face Spaces without MySQL).
5
+ """
6
+
7
+ import logging
8
+ from sqlalchemy import create_engine
9
+ from sqlalchemy.orm import sessionmaker, DeclarativeBase
10
+
11
+ from app.core.config import get_settings
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class Base(DeclarativeBase):
17
+ pass
18
+
19
+
20
+ _engine = None
21
+
22
+
23
+ def _get_engine():
24
+ global _engine
25
+ if _engine is None:
26
+ _settings = get_settings()
27
+ try:
28
+ _engine = create_engine(
29
+ _settings.database_url,
30
+ pool_pre_ping=True,
31
+ pool_recycle=3600,
32
+ echo=_settings.debug,
33
+ )
34
+ except Exception as exc:
35
+ logger.warning("Database engine creation failed: %s", exc)
36
+ raise
37
+ return _engine
38
+
39
+
40
+ def get_db():
41
+ """FastAPI dependency: yields a DB session, closes on exit."""
42
+ engine = _get_engine()
43
+ Session = sessionmaker(autocommit=False, autoflush=False, bind=engine)
44
+ db = Session()
45
+ try:
46
+ yield db
47
+ finally:
48
+ db.close()
app/services/pdf_renderer.py CHANGED
@@ -168,7 +168,7 @@ async def render_pdf_from_html(
168
  header_template='<span></span>',
169
  footer_template=(
170
  '<div style="width:100%;text-align:center;font-size:10px;'
171
- 'font-family:Century Gothic,Segoe UI,sans-serif;color:#333;'
172
  'padding:0 0 4px 0;">'
173
  '<span class="pageNumber"></span></div>'
174
  ),
 
168
  header_template='<span></span>',
169
  footer_template=(
170
  '<div style="width:100%;text-align:center;font-size:10px;'
171
+ 'font-family:Century Gothic,Segoe UI,sans-serif;color:#1C75BC;'
172
  'padding:0 0 4px 0;">'
173
  '<span class="pageNumber"></span></div>'
174
  ),
app/static/css/print.css CHANGED
@@ -182,7 +182,7 @@ a:visited {
182
  .hb-bullet-list,
183
  .ul,
184
  ul.hb-bullet-list {
185
- list-style: none;
186
  margin: 0 0 8pt 16pt;
187
  padding: 0;
188
  font-size: 10pt;
@@ -640,6 +640,10 @@ table.programs td:nth-child(5) {
640
  border: none;
641
  }
642
 
 
 
 
 
643
  .summary-section {
644
  display: block;
645
  }
 
182
  .hb-bullet-list,
183
  .ul,
184
  ul.hb-bullet-list {
185
+ list-style: none !important;
186
  margin: 0 0 8pt 16pt;
187
  padding: 0;
188
  font-size: 10pt;
 
640
  border: none;
641
  }
642
 
643
+ .section-block> :first-child {
644
+ margin-top: 0;
645
+ }
646
+
647
  .summary-section {
648
  display: block;
649
  }
app/templates/partials/blocks/school_profile.html CHANGED
@@ -18,7 +18,6 @@
18
  <tr>
19
  <td class="hb-school-top-summary">
20
  {% if block.data.overview %}
21
- <div class="hb-summary-title">Summary info</div>
22
  <ul class="hb-summary-ul">
23
  {% if block.data.overview.founded %}<li><span class="hb-lbl">Founded:</span> {{
24
  block.data.overview.founded | e }}</li>{% endif %}
@@ -70,7 +69,7 @@
70
  <ul class="hb-benefits-ul">
71
  {% for b in block.data.benefits %}
72
  {% if b %}
73
- <li class="hb-benefit-item"><span class="hb-benefit-text">{{ b | e }}</span></li>
74
  {% endif %}
75
  {% endfor %}
76
  </ul>
 
18
  <tr>
19
  <td class="hb-school-top-summary">
20
  {% if block.data.overview %}
 
21
  <ul class="hb-summary-ul">
22
  {% if block.data.overview.founded %}<li><span class="hb-lbl">Founded:</span> {{
23
  block.data.overview.founded | e }}</li>{% endif %}
 
69
  <ul class="hb-benefits-ul">
70
  {% for b in block.data.benefits %}
71
  {% if b %}
72
+ <li class="hb-benefit-item"><span class="hb-benefit-text">{{ b | e }}</span></li>
73
  {% endif %}
74
  {% endfor %}
75
  </ul>
app/templates/partials/university.html CHANGED
@@ -18,7 +18,6 @@
18
  <tr>
19
  <td class="school-top-summary">
20
  {% if uni.overview %}
21
- <div class="summary-title">Summary info</div>
22
  <ul class="summary-ul">
23
  {% if uni.overview.founded %}<li><span class="lbl">Founded:</span> {{ uni.overview.founded | e }}
24
  </li>{% endif %}
 
18
  <tr>
19
  <td class="school-top-summary">
20
  {% if uni.overview %}
 
21
  <ul class="summary-ul">
22
  {% if uni.overview.founded %}<li><span class="lbl">Founded:</span> {{ uni.overview.founded | e }}
23
  </li>{% endif %}
requirements.txt CHANGED
@@ -1,10 +1,10 @@
1
- fastapi>=0.110.0
2
- uvicorn[standard]>=0.27.0
3
- pydantic>=2.5.0
4
- pydantic-settings>=2.1.0
5
- httpx>=0.27.0
6
- jinja2>=3.1.0
7
- markupsafe>=2.1.0
8
- playwright>=1.40.0
9
- pypdf>=4.0.0
10
- python-dotenv>=1.0.0
 
1
+ fastapi>=0.135.0
2
+ uvicorn[standard]>=0.34.0
3
+ pydantic>=2.10.0
4
+ pydantic-settings>=2.7.0
5
+ httpx>=0.28.0
6
+ jinja2>=3.1.4
7
+ markupsafe>=3.0.0
8
+ playwright>=1.50.0
9
+ pypdf>=5.0.0
10
+ python-dotenv>=1.0.1