SalexAI commited on
Commit
c631550
·
verified ·
1 Parent(s): f2bac6c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +228 -215
app.py CHANGED
@@ -1,220 +1,233 @@
1
- from fastapi import FastAPI, Request
2
- from fastapi.responses import HTMLResponse
3
- from fastapi.middleware.cors import CORSMiddleware
4
  import json
5
- import os
 
 
 
6
 
7
  app = FastAPI()
8
- DATA_FILE = "data.json"
9
-
10
- # Allow CORS for frontend fetch if needed
11
- app.add_middleware(
12
- CORSMiddleware,
13
- allow_origins=["*"],
14
- allow_methods=["*"],
15
- allow_headers=["*"],
16
- )
17
-
18
- # Initialize data file
19
- if not os.path.exists(DATA_FILE):
20
- with open(DATA_FILE, "w") as f:
21
- json.dump([], f)
22
-
23
- @app.post("/store")
24
- async def store(request: Request):
25
- data = await request.json()
26
- with open(DATA_FILE, "w") as f:
27
- json.dump(data, f)
28
- return {"status": "success"}
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  @app.get("/", response_class=HTMLResponse)
31
- async def index():
32
- with open(DATA_FILE, "r") as f:
33
- stored_data = json.load(f)
34
- # Escape the JSON and inject it into the script
35
- return HTMLResponse(content=f"""
36
- <!DOCTYPE html>
37
- <html lang="en">
38
- <head>
39
- <meta charset="UTF-8" />
40
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
41
- <title>UniShare</title>
42
- <style>
43
- body {{
44
- font-family: Arial, sans-serif;
45
- margin: 0;
46
- padding: 0;
47
- background: #f0f2f5;
48
- }}
49
- header {{
50
- background: #3b82f6;
51
- color: white;
52
- padding: 1em;
53
- text-align: center;
54
- font-size: 1.8em;
55
- }}
56
- #overview {{
57
- display: grid;
58
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
59
- gap: 1em;
60
- padding: 1em;
61
- }}
62
- .list-tile {{
63
- background: white;
64
- padding: 1em;
65
- border-radius: 10px;
66
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
67
- cursor: pointer;
68
- transition: transform 0.2s;
69
- }}
70
- .list-tile:hover {{
71
- transform: scale(1.02);
72
- }}
73
- #list-view {{
74
- display: none;
75
- padding: 1em;
76
- }}
77
- .back-button {{
78
- background: #3b82f6;
79
- color: white;
80
- padding: 0.5em 1em;
81
- border: none;
82
- border-radius: 5px;
83
- cursor: pointer;
84
- margin-bottom: 1em;
85
- }}
86
- .card {{
87
- background: white;
88
- padding: 1em;
89
- border-radius: 10px;
90
- box-shadow: 0 2px 5px rgba(0,0,0,0.1);
91
- margin-bottom: 1em;
92
- }}
93
- .submenu {{
94
- margin-top: 1em;
95
- }}
96
- .submenu h4 {{
97
- margin: 0.5em 0;
98
- }}
99
- .grid {{
100
- display: grid;
101
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
102
- gap: 1em;
103
- }}
104
- .item {{
105
- background: #f9f9f9;
106
- padding: 1em;
107
- border-radius: 10px;
108
- box-shadow: 0 1px 3px rgba(0,0,0,0.05);
109
- }}
110
- .item img {{
111
- max-width: 100%;
112
- max-height: 150px;
113
- object-fit: cover;
114
- border-radius: 5px;
115
- margin-bottom: 0.5em;
116
- }}
117
- .item a {{
118
- display: inline-block;
119
- margin-top: 0.5em;
120
- text-decoration: none;
121
- color: #3b82f6;
122
- }}
123
- #toast {{
124
- position: fixed;
125
- bottom: 20px;
126
- right: 20px;
127
- background: #333;
128
- color: white;
129
- padding: 1em;
130
- border-radius: 5px;
131
- display: none;
132
- z-index: 1000;
133
- }}
134
- </style>
135
- </head>
136
- <body>
137
- <header>UniShare</header>
138
- <div id="overview"></div>
139
- <div id="list-view">
140
- <button class="back-button" onclick="backToOverview()">← Back to Overview</button>
141
- <div id="content"></div>
142
- </div>
143
- <div id="toast"></div>
144
-
145
- <script>
146
- const overviewDiv = document.getElementById('overview');
147
- const contentDiv = document.getElementById('content');
148
- const listViewDiv = document.getElementById('list-view');
149
- const toastDiv = document.getElementById('toast');
150
-
151
- const rawData = {json.dumps(stored_data)};
152
- const lists = {{}};
153
-
154
- function showToast(message) {{
155
- toastDiv.textContent = message;
156
- toastDiv.style.display = 'block';
157
- setTimeout(() => {{
158
- toastDiv.style.display = 'none';
159
- }}, 3000);
160
- }}
161
-
162
- function backToOverview() {{
163
- listViewDiv.style.display = 'none';
164
- overviewDiv.style.display = 'grid';
165
- }}
166
-
167
- function showList(name) {{
168
- const sections = lists[name];
169
- contentDiv.innerHTML = '';
170
-
171
- sections.forEach(section => {{
172
- const card = document.createElement('div');
173
- card.className = 'card';
174
- const title = document.createElement('h3');
175
- title.textContent = section.sectionTitle;
176
- card.appendChild(title);
177
-
178
- const grid = document.createElement('div');
179
- grid.className = 'grid';
180
-
181
- section.items.forEach(item => {{
182
- const div = document.createElement('div');
183
- div.className = 'item';
184
- let content = `<strong>${{item.title}}</strong><br>`;
185
- if (item.link.match(/\\.(jpeg|jpg|gif|png)$/)) {{
186
- content += `<img src="${{item.link}}" alt="${{item.title}}" />`;
187
- }}
188
- content += `<a href="${{item.link}}" download>Download</a>`;
189
- div.innerHTML = content;
190
- grid.appendChild(div);
191
- }});
192
-
193
- card.appendChild(grid);
194
- contentDiv.appendChild(card);
195
- }});
196
-
197
- overviewDiv.style.display = 'none';
198
- listViewDiv.style.display = 'block';
199
- }}
200
-
201
- rawData.forEach((list, index) => {{
202
- if (Array.isArray(list)) {{
203
- const listName = `List ${{index + 1}}`;
204
- lists[listName] = list;
205
- const tile = document.createElement('div');
206
- tile.className = 'list-tile';
207
- tile.innerHTML = `<strong>${{listName}}</strong><br>${{list.length}} sections`;
208
- tile.onclick = () => showList(listName);
209
- overviewDiv.appendChild(tile);
210
- showToast(`Loaded ${{listName}}`);
211
- }}
212
- }});
213
-
214
- if (Object.keys(lists).length === 0) {{
215
- overviewDiv.innerHTML = '<p style="padding:1em">No valid list data available.</p>';
216
- }}
217
- </script>
218
- </body>
219
- </html>
220
- """, status_code=200)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import json
2
+ from fastapi import FastAPI, HTTPException
3
+ import gradio as gr
4
+ from pydantic import BaseModel
5
+ from fastapi.responses import HTMLResponse
6
 
7
  app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ # Define a model for the incoming request data
10
+ class DataRequest(BaseModel):
11
+ list_name: str
12
+ items: list
13
+
14
+ # Store the lists data
15
+ lists = {}
16
+
17
+ # FastAPI endpoint for POST request to store data
18
+ @app.post("/store_data")
19
+ async def store_data(data: DataRequest):
20
+ list_name = data.list_name
21
+ items = data.items
22
+
23
+ if list_name not in lists:
24
+ lists[list_name] = []
25
+
26
+ lists[list_name].append(items)
27
+ return {"message": f"Data stored successfully for {list_name}"}
28
+
29
+ # FastAPI default root to serve custom HTML
30
  @app.get("/", response_class=HTMLResponse)
31
+ def read_root():
32
+ return """
33
+ <!DOCTYPE html>
34
+ <html lang="en">
35
+ <head>
36
+ <meta charset="UTF-8" />
37
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
38
+ <title>UniShare</title>
39
+ <style>
40
+ body {
41
+ font-family: Arial, sans-serif;
42
+ margin: 0;
43
+ padding: 0;
44
+ background: #f0f2f5;
45
+ }
46
+ header {
47
+ background: #3b82f6;
48
+ color: white;
49
+ padding: 1em;
50
+ text-align: center;
51
+ font-size: 1.8em;
52
+ }
53
+ #overview {
54
+ display: grid;
55
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
56
+ gap: 1em;
57
+ padding: 1em;
58
+ }
59
+ .list-tile {
60
+ background: white;
61
+ padding: 1em;
62
+ border-radius: 10px;
63
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
64
+ cursor: pointer;
65
+ transition: transform 0.2s;
66
+ }
67
+ .list-tile:hover {
68
+ transform: scale(1.02);
69
+ }
70
+ #list-view {
71
+ display: none;
72
+ padding: 1em;
73
+ }
74
+ .back-button {
75
+ background: #3b82f6;
76
+ color: white;
77
+ padding: 0.5em 1em;
78
+ border: none;
79
+ border-radius: 5px;
80
+ cursor: pointer;
81
+ margin-bottom: 1em;
82
+ }
83
+ .card {
84
+ background: white;
85
+ padding: 1em;
86
+ border-radius: 10px;
87
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
88
+ margin-bottom: 1em;
89
+ }
90
+ .submenu {
91
+ margin-top: 1em;
92
+ }
93
+ .submenu h4 {
94
+ margin: 0.5em 0;
95
+ }
96
+ .grid {
97
+ display: grid;
98
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
99
+ gap: 1em;
100
+ }
101
+ .item {
102
+ background: #f9f9f9;
103
+ padding: 1em;
104
+ border-radius: 10px;
105
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
106
+ }
107
+ .item img {
108
+ max-width: 100%;
109
+ max-height: 150px;
110
+ object-fit: cover;
111
+ border-radius: 5px;
112
+ margin-bottom: 0.5em;
113
+ }
114
+ .item a {
115
+ display: inline-block;
116
+ margin-top: 0.5em;
117
+ text-decoration: none;
118
+ color: #3b82f6;
119
+ }
120
+ #toast {
121
+ position: fixed;
122
+ bottom: 20px;
123
+ right: 20px;
124
+ background: #333;
125
+ color: white;
126
+ padding: 1em;
127
+ border-radius: 5px;
128
+ display: none;
129
+ z-index: 1000;
130
+ }
131
+ </style>
132
+ </head>
133
+ <body>
134
+ <header>UniShare</header>
135
+ <div id="overview"></div>
136
+ <div id="list-view">
137
+ <button class="back-button" onclick="backToOverview()">← Back to Overview</button>
138
+ <div id="content"></div>
139
+ </div>
140
+ <div id="toast"></div>
141
+
142
+ <script>
143
+ const overviewDiv = document.getElementById('overview');
144
+ const contentDiv = document.getElementById('content');
145
+ const listViewDiv = document.getElementById('list-view');
146
+ const toastDiv = document.getElementById('toast');
147
+
148
+ const lists = {}
149
+
150
+ function showToast(message) {
151
+ toastDiv.textContent = message;
152
+ toastDiv.style.display = 'block';
153
+ setTimeout(() => {
154
+ toastDiv.style.display = 'none';
155
+ }, 3000);
156
+ }
157
+
158
+ function backToOverview() {
159
+ listViewDiv.style.display = 'none';
160
+ overviewDiv.style.display = 'grid';
161
+ }
162
+
163
+ function showList(name) {
164
+ const sections = lists[name];
165
+ contentDiv.innerHTML = '';
166
+
167
+ sections.forEach(section => {
168
+ const card = document.createElement('div');
169
+ card.className = 'card';
170
+ const title = document.createElement('h3');
171
+ title.textContent = section.sectionTitle;
172
+ card.appendChild(title);
173
+
174
+ const grid = document.createElement('div');
175
+ grid.className = 'grid';
176
+
177
+ section.items.forEach(item => {
178
+ const div = document.createElement('div');
179
+ div.className = 'item';
180
+ let content = `<strong>${item.title}</strong><br>`;
181
+ if (item.link.match(/\.(jpeg|jpg|gif|png)$/)) {
182
+ content += `<img src="${item.link}" alt="${item.title}" />`;
183
+ }
184
+ content += `<a href="${item.link}" download>Download</a>`;
185
+ div.innerHTML = content;
186
+ grid.appendChild(div);
187
+ });
188
+
189
+ card.appendChild(grid);
190
+ contentDiv.appendChild(card);
191
+ });
192
+
193
+ overviewDiv.style.display = 'none';
194
+ listViewDiv.style.display = 'block';
195
+ }
196
+
197
+ // Fetch data and populate the lists dynamically
198
+ fetch('/gradio/data')
199
+ .then(response => response.json())
200
+ .then(data => {
201
+ if (Object.keys(data).length > 0) {
202
+ Object.keys(data).forEach((listName, index) => {
203
+ const list = data[listName];
204
+ const tile = document.createElement('div');
205
+ tile.className = 'list-tile';
206
+ tile.innerHTML = `<strong>${listName}</strong><br>${list.length} sections`;
207
+ tile.onclick = () => showList(listName);
208
+ overviewDiv.appendChild(tile);
209
+ showToast(`Loaded ${listName}`);
210
+ });
211
+ } else {
212
+ overviewDiv.innerHTML = '<p>No lists found</p>';
213
+ }
214
+ });
215
+ </script>
216
+ </body>
217
+ </html>
218
+ """
219
+
220
+ # Gradio Interface for displaying the stored data
221
+ def show_data():
222
+ return lists
223
+
224
+ # Gradio app interface
225
+ gr_interface = gr.Interface(fn=show_data, live=True)
226
+
227
+ # Add the Gradio app to FastAPI
228
+ app = gr.mount_gradio_app(app, gr_interface, path="/gradio")
229
+
230
+ # FastAPI default root (e.g. for status or basic testing)
231
+ @app.get("/gradio/data")
232
+ async def get_data():
233
+ return lists