11import streamlit as st
22import pandas as pd
3- import tempfile
4- import os
5- from googleapiclient .discovery import build
6- from googleapiclient .http import MediaFileUpload
7- from google .oauth2 .credentials import Credentials
8- from google .auth .transport .requests import Request
93
10- # --- 1. SETTINGS & AUTHENTICATION ---
11- # Ensure SHEET_ID and FOLDER_ID are in your Streamlit Secrets
12- SPREADSHEET_ID = st .secrets ["SHEET_ID" ]
13- FOLDER_ID = st .secrets ["FOLDER_ID" ]
14- SHEET_ID = SPREADSHEET_ID
15-
16- def get_gdrive_service ():
17- """Authenticates using the OAuth Refresh Token from st.secrets"""
18- creds_info = st .secrets ["google_oauth" ]
19-
20- # Create credentials object using your specific Refresh Token
21- creds = Credentials (
22- token = None ,
23- refresh_token = creds_info ["refresh_token" ],
24- client_id = creds_info ["client_id" ],
25- client_secret = creds_info ["client_secret" ],
26- token_uri = "https://oauth2.googleapis.com/token"
27- )
28-
29- # Refresh the access token automatically if it's expired
30- if not creds .valid :
31- creds .refresh (Request ())
32-
33- # Build the services for Drive and Sheets
34- drive_service = build ('drive' , 'v3' , credentials = creds )
35- sheets_service = build ('sheets' , 'v4' , credentials = creds )
36-
37- return drive_service , sheets_service
38-
39- # Initialize the services
40- try :
41- drive_service , sheets_service = get_gdrive_service ()
42- except Exception as e :
43- st .error (f"Authentication Failed: { e } " )
44- st .stop ()
45-
46- # --- 2. APP INTERFACE ---
47- st .set_page_config (page_title = "Scientific Slide Library" , layout = "wide" , page_icon = "🔬" )
48- st .title ("🔬 Scientific Slide Library" )
49-
50- # Create tabs for Uploading and Browsing
51- tab1 , tab2 = st .tabs (["📤 Upload New Slides" , "📚 Browse Library" ])
4+ # 5) BACKGROUND COLOR - Tag: BACKGROUND_STYLE
5+ # This injects custom CSS to change the main app background to light grey
6+ st .markdown (
7+ """
8+ <style>
9+ .stApp {
10+ background-color: #f0f0f0;
11+ }
12+ </style>
13+ """ ,
14+ unsafe_content_as_allowed = True
15+ )
16+
17+ # 4) HEADER TEXT - Tag: HEADER_SECTION
18+ # Edit the strings below to customize your page introduction
19+ st .title ("Document Management Library" )
20+ st .markdown ("""
21+ Welcome to the Digital Library. Here you can browse all stored files,
22+ view them directly in Google Sheets, or download them to your local device.
23+ """ )
24+ # --- END HEADER SECTION ---
25+
26+ # 1) SWAP TABS - "Library" is now the first index (Default)
27+ tab1 , tab2 = st .tabs (["📚 View Library" , "📤 Upload New File" ])
5228
5329with tab1 :
54- st .header ("Contribute to the Library" )
55- st .write ("Upload your slides and fill out the details below." )
56-
57- with st .form ("upload_form" , clear_on_submit = True ):
58- person = st .text_input ("Your Name" )
59- name = st .text_input ("Presentation Title" )
60- description = st .text_area ("Topic/Description" )
61- keywords = st .text_input ("Keywords (comma separated)" )
62- uploaded_file = st .file_uploader ("Choose Presentation File (PDF, PPTX, etc.)" )
63-
64- submit_button = st .form_submit_button ("Submit Entry" )
65-
66- if submit_button :
67- if not name or not description :
68- st .warning ("Please provide at least a title and a description." )
69- else :
70- with st .spinner ("Processing upload... please wait." ):
71- file_link = "No file uploaded"
72-
73- # --- STEP A: UPLOAD TO GOOGLE DRIVE ---
74- if uploaded_file is not None :
75- with tempfile .NamedTemporaryFile (delete = False ) as tmp :
76- tmp .write (uploaded_file .getvalue ())
77- tmp_path = tmp .name
78-
79- try :
80- file_metadata = {
81- "name" : uploaded_file .name ,
82- "parents" : [FOLDER_ID ]
83- }
84- media = MediaFileUpload (tmp_path , resumable = True )
85-
86- uploaded_drive_file = drive_service .files ().create (
87- body = file_metadata ,
88- media_body = media ,
89- fields = "id, webViewLink"
90- ).execute ()
91-
92- file_link = uploaded_drive_file .get ("webViewLink" )
93- except Exception as e :
94- st .error (f"Drive Error: { e } " )
95- finally :
96- if os .path .exists (tmp_path ):
97- os .remove (tmp_path )
98-
99- # --- STEP B: UPDATE GOOGLE SHEET ---
100- try :
101- # Prepare row data: Title, Description, Keywords, Link, Person
102- row_data = [[name , description , keywords , file_link , person ]]
103-
104- sheets_service .spreadsheets ().values ().append (
105- spreadsheetId = SHEET_ID ,
106- range = "Sheet1!A1" ,
107- valueInputOption = "USER_ENTERED" ,
108- body = {"values" : row_data }
109- ).execute ()
110-
111- st .success ("✅ Entry recorded successfully!" )
112- st .balloons ()
113- # Rerun to automatically update the Library tab
114- st .rerun ()
115- except Exception as e :
116- st .error (f"Sheets Error: { e } " )
30+ # Sample Data - Replace this with your actual Google Sheet / Dataframe logic
31+ data = {
32+ "File Name" : ["Project_Alpha_Specs.pdf" , "Budget_2024.xlsx" , "Team_Contact_List.csv" ],
33+ "Description" : [
34+ "Full technical specifications for the Alpha project initiative including timeline." ,
35+ "Complete budget breakdown for the upcoming fiscal year 2024." ,
36+ "Internal contact directory for all department heads and primary stakeholders."
37+ ],
38+ "View Link" : ["https://docs.google.com/spreadsheets/d/1" , "https://docs.google.com/spreadsheets/d/2" , "https://docs.google.com/spreadsheets/d/3" ],
39+ "Download Link" : ["https://example.com/download1" , "https://example.com/download2" , "https://example.com/download3" ]
40+ }
41+ df = pd .DataFrame (data )
42+
43+ # 2) NARROWER TABLE & WORD WRAP
44+ # 3) TWO LINK COLUMNS
45+ # We use st.column_config to turn URLs into clickable buttons/links
46+ st .dataframe (
47+ df ,
48+ column_config = {
49+ "File Name" : st .column_config .TextColumn ("File Name" , width = "medium" ),
50+ "Description" : st .column_config .TextColumn ("Description" , width = "large" ),
51+ "View Link" : st .column_config .LinkColumn ("View File" , display_text = "Open in Sheets" ),
52+ "Download Link" : st .column_config .LinkColumn ("Download" , display_text = "Direct Download" )
53+ },
54+ hide_index = True ,
55+ use_container_width = True # This ensures it fits the "narrower" container feel
56+ )
11757
11858with tab2 :
119- st .header ("Library Database" )
120- st .write ("Search, filter, and access all stored presentations." )
121-
122- try :
123- # Fetch all data from the Google Sheet
124- result = sheets_service .spreadsheets ().values ().get (
125- spreadsheetId = SHEET_ID , range = "Sheet1!A:Z"
126- ).execute ()
127-
128- values = result .get ('values' , [])
129-
130- if not values :
131- st .info ("The library is currently empty. Start by uploading a file!" )
132- else :
133- # Create a DataFrame (assumes the first row of your sheet contains headers)
134- # Recommended headers: Name, Description, Keywords, Link, Person
135- df = pd .DataFrame (values [1 :], columns = values [0 ])
136-
137- # Interactive Search (Built-in to st.dataframe, but we can add a manual one too)
138- search_query = st .text_input ("Quick Filter" , placeholder = "Search by name, topic, or keyword..." )
139-
140- if search_query :
141- # Filters rows across all columns that contain the search text
142- df = df [df .apply (lambda row : row .astype (str ).str .contains (search_query , case = False ).any (), axis = 1 )]
143-
144- # Display the interactive table with clickable links
145- st .dataframe (
146- df ,
147- use_container_width = True ,
148- hide_index = True ,
149- column_config = {
150- # Adjust "Link" below to match your exact column header name in Google Sheets
151- "Link" : st .column_config .LinkColumn ("Access Slides" , display_text = "Open File" )
152- }
153- )
154-
155- if st .button ("Refresh Database" ):
156- st .rerun ()
157-
158- except Exception as e :
159- st .error (f"Could not load the database: { e } " )
59+ st .header ("Upload Section" )
60+ st .file_uploader ("Select a file to upload to the library" )
0 commit comments