@@ -1598,12 +1598,6 @@ def search():
15981598
15991599@app .route ("/keys" , methods = ["GET" ])
16001600def available_keys ():
1601- """
1602- Public page listing 'search keys':
1603- - Materials properties (slug + pretty title + item counts)
1604- - Clip titles
1605- Works with either a 'properties' table or by falling back to uploads_log.
1606- """
16071601 PRETTY_FALLBACK = {
16081602 "bandgap" : "Band Gap" ,
16091603 "formation_energy" : "Formation Energy" ,
@@ -1613,19 +1607,21 @@ def available_keys():
16131607
16141608 def table_exists (conn , name ):
16151609 cur = conn .cursor ()
1616- cur .execute (
1617- "SELECT 1 FROM sqlite_master WHERE type='table' AND name=?" ,
1618- (name ,),
1619- )
1610+ cur .execute ("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?" , (name ,))
16201611 return cur .fetchone () is not None
16211612
1622- props = [] # list of dicts: {slug, title, count}
1623- clip_titles = []
1613+ def column_exists (conn , table , col ):
1614+ cur = conn .cursor ()
1615+ cur .execute (f"PRAGMA table_info({ table } )" )
1616+ return any (r [1 ].lower () == col .lower () for r in cur .fetchall ())
1617+
1618+ props = [] # [{slug, title, count}]
1619+ clip_titles = [] # [str]
16241620
16251621 with sqlite3 .connect (DB_NAME ) as conn :
16261622 conn .row_factory = sqlite3 .Row
16271623
1628- # Count how many items per property in uploads_log (Drive-only)
1624+ # Count files per property (Drive-only rows )
16291625 counts = {}
16301626 if table_exists (conn , "uploads_log" ):
16311627 cur = conn .cursor ()
@@ -1638,42 +1634,50 @@ def table_exists(conn, name):
16381634 for r in cur .fetchall ():
16391635 counts [r ["property" ]] = r ["c" ]
16401636
1641- # Prefer a ' properties' table if you have it
1637+ # Properties: prefer properties table if present, else derive from uploads_log
16421638 if table_exists (conn , "properties" ):
1639+ has_title = column_exists (conn , "properties" , "title" )
16431640 cur = conn .cursor ()
1644- cur . execute ( "SELECT slug, title FROM properties ORDER BY title" )
1645- for r in cur .fetchall ():
1646- slug = r [ "slug" ]
1647- title = r [ "title" ] or PRETTY_FALLBACK . get ( slug , slug . replace ( "_" , " " ). title ())
1648- props . append ({
1649- "slug" : slug ,
1650- " title" : title ,
1651- "count" : counts . get ( slug , 0 ),
1652- })
1653- else :
1654- # Fall back to any properties that actually exist in uploads_log
1655- if counts :
1656- for slug , c in sorted ( counts . items (), key = lambda t : t [ 0 ]):
1641+ if has_title :
1642+ cur .execute ( "SELECT slug, title FROM properties ORDER BY COALESCE(title, slug)" )
1643+ rows = cur . fetchall ()
1644+ for r in rows :
1645+ slug = r [ "slug" ]
1646+ title = ( r [ "title" ] or "" ). strip () or PRETTY_FALLBACK . get ( slug , slug . replace ( "_" , " " ). title ())
1647+ props . append ({ "slug" : slug , " title" : title , "count" : counts . get ( slug , 0 )})
1648+ else :
1649+ # No title column—use slug and prettify
1650+ cur . execute ( "SELECT slug FROM properties ORDER BY slug" )
1651+ rows = cur . fetchall ()
1652+ for r in rows :
1653+ slug = r [ "slug" ]
16571654 title = PRETTY_FALLBACK .get (slug , slug .replace ("_" , " " ).title ())
1658- props .append ({"slug" : slug , "title" : title , "count" : c })
1655+ props .append ({"slug" : slug , "title" : title , "count" : counts .get (slug , 0 )})
1656+ else :
1657+ # No properties table—fall back to whatever exists in uploads_log
1658+ for slug , c in sorted (counts .items (), key = lambda t : t [0 ]):
1659+ title = PRETTY_FALLBACK .get (slug , slug .replace ("_" , " " ).title ())
1660+ props .append ({"slug" : slug , "title" : title , "count" : c })
16591661
1660- # Clip titles (if table exists)
1662+ # Clips: pick a reasonable title-like column if available
16611663 if table_exists (conn , "clips" ):
16621664 cur = conn .cursor ()
1663- # Be forgiving about schema variations
1664- try :
1665- cur .execute ("""
1666- SELECT title
1665+ # find a likely title column
1666+ cur .execute ("PRAGMA table_info(clips)" )
1667+ cols = [r [1 ].lower () for r in cur .fetchall ()]
1668+ title_col = None
1669+ for cand in ("title" , "name" , "label" ):
1670+ if cand in cols :
1671+ title_col = cand
1672+ break
1673+ if title_col :
1674+ cur .execute (f"""
1675+ SELECT DISTINCT { title_col } AS t
16671676 FROM clips
1668- WHERE title IS NOT NULL AND TRIM(title)!=''
1669- ORDER BY title COLLATE NOCASE
1670- """ )
1671- except Exception :
1672- # Fallback: try a likely column name
1673- cur .execute ("""
1674- SELECT COALESCE(title, '') AS title FROM clips
1677+ WHERE { title_col } IS NOT NULL AND TRIM({ title_col } )!=''
1678+ ORDER BY t COLLATE NOCASE
16751679 """ )
1676- clip_titles = [r [0 ] for r in cur .fetchall () if (r [0 ] or "" ).strip ()]
1680+ clip_titles = [r ["t" ] for r in cur .fetchall () if (r ["t" ] or "" ).strip ()]
16771681
16781682 return render_template ("available_keys.html" , props = props , clip_titles = clip_titles )
16791683##############################################################################################################################################################
0 commit comments