charbelmalo commited on
Commit
084d624
·
1 Parent(s): 85da4c7

Update Gradio SDK version to 5.5.0 and add new JSON entries for user data

Browse files
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
127.0.0.1/username-2ca5yTRsxiA.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
127.0.0.1/username-JDpPDlmi1KA.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
2024-11-13/charbelmalo.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
None/username-J-IG_DLHxw4.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
None/username-PmxrGNiqPfU.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
None/username-RomFxrKCAQE.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
None/username-YAMKd4ALrwo.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
None/username-s4aGziZftC4.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13 16:25:36.058089"}]
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 🍬🔗
4
  colorFrom: green
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 3.40.1
8
  app_file: app.py
9
  pinned: true
10
  license: apache-2.0
 
4
  colorFrom: green
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 5.5.0
8
  app_file: app.py
9
  pinned: true
10
  license: apache-2.0
app.py CHANGED
@@ -4,24 +4,60 @@ from datetime import datetime
4
  import json
5
  import pandas as pd
6
  import os
 
 
 
 
 
 
7
 
 
8
  shortcuts_list = []
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def save_shortcuts():
11
- with open('shortcuts.json', 'w') as f:
12
- json.dump(shortcuts_list, f, default=str)
 
 
 
13
 
14
  def load_shortcuts():
15
  global shortcuts_list
 
 
 
16
  if os.path.exists('shortcuts.json'):
17
- with open('shortcuts.json', 'r') as f:
18
- shortcuts_list = json.load(f)
19
- for shortcut in shortcuts_list:
 
 
20
  shortcut['date_added'] = datetime.fromisoformat(shortcut['date_added'])
 
 
21
  else:
22
  shortcuts_list = []
23
 
 
24
  def add_shortcut(name, tags, link, emojis, color_from, color_to, short_description):
 
25
  new_shortcut = {
26
  'name': name.strip(),
27
  'tags': [tag.strip() for tag in tags.split('/') if tag.strip()],
@@ -34,12 +70,18 @@ def add_shortcut(name, tags, link, emojis, color_from, color_to, short_descripti
34
  'favorited': False,
35
  'date_added': datetime.now().isoformat()
36
  }
37
- shortcuts_list.append(new_shortcut)
38
  save_shortcuts()
39
  # Return updated HTML
40
  return update_display()
41
 
 
 
 
 
 
42
  def get_shortcuts_dataframe(sort_by='Recently Added', search_query='', filter_tags=[]):
 
43
  datafra = pd.DataFrame(shortcuts_list)
44
  if datafra.empty:
45
  return datafra
@@ -60,7 +102,9 @@ def get_shortcuts_dataframe(sort_by='Recently Added', search_query='', filter_ta
60
  datafra = datafra.reset_index(drop=True)
61
  return datafra
62
 
 
63
  def generate_cards_html(datafra):
 
64
  if datafra.empty:
65
  return "<p>No shortcuts available.</p>"
66
  cards_html = '<div style="display: flex; flex-wrap: wrap;">'
@@ -98,33 +142,36 @@ def generate_cards_html(datafra):
98
  </div>
99
  """
100
  card_html = f"""
101
- <div style="{style}" onmouseover="handleHover({idx})" id="card-{idx}" onmouseout="handleHoverOut({idx})">
 
 
102
  {labels_html}
103
  <div style='font-size: 40px; text-align: center;'>{shortcut['emojis']}</div>
104
  <h3 style='text-align: center;'>{shortcut['name']}</h3>
105
  <p style='text-align: center;'>{shortcut['short_description']}</p>
106
  <div style='text-align: center;'>
107
- <button style="background: none; border: none; cursor: pointer; {pin_style}" onclick="togglePin({idx})">{pin_icon}</button>
108
- <button style="background: none; border: none; cursor: pointer;" onclick="toggleFavorite({idx})">{favorite_icon}</button>
109
  <button onclick="window.open('{shortcut['link']}', '_blank')">🔗 Open</button>
110
  </div>
111
- <div id="delete-{idx}" style="display: none; position: absolute; top: 10px; left: 10px; cursor: pointer;" onclick="deleteShortcut({idx})">
112
  🗑️
113
  </div>
114
  </div>
115
  """
116
  cards_html += card_html
117
  cards_html += '</div>'
118
-
119
- # Add JavaScript for handling hover and command/control key
120
-
121
  return cards_html
122
 
 
123
  def update_display(sort_by='Recently Added', search_query='', filter_tags=[]):
 
124
  datafra = get_shortcuts_dataframe(sort_by, search_query, filter_tags)
125
  return generate_cards_html(datafra)
126
 
 
127
  def toggle_pin(index):
 
128
  index = int(index)
129
  if 0 <= index < len(shortcuts_list):
130
  shortcuts_list[index]['pinned'] = not shortcuts_list[index]['pinned']
@@ -132,7 +179,9 @@ def toggle_pin(index):
132
  # Return updated HTML
133
  return update_display()
134
 
 
135
  def toggle_favorite(index):
 
136
  index = int(index)
137
  if 0 <= index < len(shortcuts_list):
138
  shortcuts_list[index]['favorited'] = not shortcuts_list[index]['favorited']
@@ -140,8 +189,21 @@ def toggle_favorite(index):
140
  # Return updated HTML
141
  return update_display()
142
 
 
 
 
 
 
 
 
 
 
 
143
  load_shortcuts()
144
 
 
 
 
145
  js_code = f"""
146
  function my_func() {{
147
  window.isCmdOrCtrl = false;
@@ -184,6 +246,22 @@ window.hideDeleteIcons = function() {{
184
  }});
185
  }};
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  window.deleteShortcut = function(idx) {{
188
  // Implement the delete functionality, e.g., call an API endpoint
189
  fetch('/delete_shortcut', {{
@@ -201,8 +279,9 @@ window.deleteShortcut = function(idx) {{
201
  }};
202
  }}
203
  """
 
204
  # Build the Gradio App
205
- with gr.Blocks(theme="charbelgrower/Crystal",js=js_code) as demo:
206
 
207
  gr.Markdown("## Website Shortcuts")
208
  with gr.Row():
@@ -217,6 +296,9 @@ with gr.Blocks(theme="charbelgrower/Crystal",js=js_code) as demo:
217
 
218
  grid_output = gr.HTML(value=update_display(), elem_id="grid_output")
219
 
 
 
 
220
  gr.Markdown("## Add a New Website Shortcut")
221
  with gr.Row():
222
  name = gr.Textbox(label="Name")
@@ -228,10 +310,12 @@ with gr.Blocks(theme="charbelgrower/Crystal",js=js_code) as demo:
228
  color_to = gr.ColorPicker(label="Gradient Color To")
229
  short_description = gr.Textbox(label="Short Description")
230
  add_button = gr.Button("Add Shortcut")
231
-
232
  # Update display when filters change
233
- def refresh_display(search_query, sort_by, filter_tags):
234
- return update_display(sort_by, search_query, filter_tags)
 
 
235
 
236
  search_bar.change(fn=refresh_display, inputs=[search_bar, sort_options, filter_tags], outputs=grid_output)
237
  sort_options.change(fn=refresh_display, inputs=[search_bar, sort_options, filter_tags], outputs=grid_output)
@@ -243,38 +327,53 @@ with gr.Blocks(theme="charbelgrower/Crystal",js=js_code) as demo:
243
  inputs=[name, tags, link, emojis, color_from, color_to, short_description],
244
  outputs=grid_output
245
  )
246
- # Expose endpoints for toggle functions
 
 
 
247
  api = FastAPI()
 
 
248
 
249
- @api.post("/toggle_pin")
250
- async def toggle_pin_route(request: Request):
251
  data = await request.json()
252
- index = data['index']
253
- grid_html = toggle_pin(index)
254
  return {'grid_html': grid_html}
255
 
256
- @api.post("/delete_shortcut")
257
- async def delete_shortcut_route(request: Request):
258
  data = await request.json()
259
- index = int(data['index'])
260
- if 0 <= index < len(shortcuts_list):
261
- del shortcuts_list[index]
262
- save_shortcuts()
263
- # Return updated HTML
264
- grid_html = update_display()
265
  return {'grid_html': grid_html}
266
 
267
- @api.post("/toggle_favorite")
268
- async def toggle_favorite_route(request: Request):
269
  data = await request.json()
270
- index = data['index']
271
- grid_html = toggle_favorite(index)
272
  return {'grid_html': grid_html}
273
 
274
- # Mount the Gradio app onto the FastAPI app
275
- app = gr.mount_gradio_app(api, demo, path="/")
 
 
 
 
276
 
 
 
277
  if __name__ == "__main__":
278
  import uvicorn
279
- load_shortcuts()
280
- uvicorn.run(app, host="127.0.0.1", port=7860)
 
 
 
 
 
 
 
 
 
 
4
  import json
5
  import pandas as pd
6
  import os
7
+ from watchdog.observers import Observer
8
+ from watchdog.events import FileSystemEventHandler
9
+ from functools import wraps
10
+ from pathlib import Path
11
+ import shutil
12
+ import getpass
13
 
14
+ global shortcuts_list
15
  shortcuts_list = []
16
 
17
+ user_dir = Path(__file__).parent / datetime.now().strftime('%Y-%m-%d')
18
+
19
+ # Add file change handler
20
+ class JSONFileHandler(FileSystemEventHandler):
21
+ def on_modified(self, event):
22
+ if event.src_path.endswith('.json'):
23
+ load_shortcuts()
24
+
25
+ # Add decorator for file operations
26
+ def ensure_fresh_data(func):
27
+ @wraps(func)
28
+ def wrapper(*args, **kwargs):
29
+ load_shortcuts() # Reload before each operation
30
+ result = func(*args, **kwargs)
31
+ return result
32
+ return wrapper
33
+
34
  def save_shortcuts():
35
+ global shortcuts_list
36
+ path = user_dir / f"{getpass.getuser()}.json"
37
+ with open(path, 'w') as f:
38
+ json.dump(path, f, default=str)
39
+ load_shortcuts()
40
 
41
  def load_shortcuts():
42
  global shortcuts_list
43
+ # user_dir: Path = current_dir / datetime.now().strftime('%Y-%m-%d')
44
+ user_dir.mkdir(exist_ok=True)
45
+ path = user_dir / f"{getpass.getuser()}.json"
46
  if os.path.exists('shortcuts.json'):
47
+ # Open the file in binary mode with no buffering to avoid cached data
48
+ with open('shortcuts.json', 'rb', buffering=0) as f:
49
+ data = f.read()
50
+ tmpshortcuts_list = json.loads(data.decode('utf-8'))
51
+ for shortcut in tmpshortcuts_list:
52
  shortcut['date_added'] = datetime.fromisoformat(shortcut['date_added'])
53
+ shortcuts_list = tmpshortcuts_list
54
+ json.dump(tmpshortcuts_list, open(path, 'w'), default=str)
55
  else:
56
  shortcuts_list = []
57
 
58
+ @ensure_fresh_data
59
  def add_shortcut(name, tags, link, emojis, color_from, color_to, short_description):
60
+ global shortcuts_list
61
  new_shortcut = {
62
  'name': name.strip(),
63
  'tags': [tag.strip() for tag in tags.split('/') if tag.strip()],
 
70
  'favorited': False,
71
  'date_added': datetime.now().isoformat()
72
  }
73
+ shortcuts_list = shortcuts_list.append(new_shortcut)
74
  save_shortcuts()
75
  # Return updated HTML
76
  return update_display()
77
 
78
+ def delete_directory():
79
+ shutil.rmtree(str(user_dir))
80
+
81
+
82
+ @ensure_fresh_data
83
  def get_shortcuts_dataframe(sort_by='Recently Added', search_query='', filter_tags=[]):
84
+ global shortcuts_list
85
  datafra = pd.DataFrame(shortcuts_list)
86
  if datafra.empty:
87
  return datafra
 
102
  datafra = datafra.reset_index(drop=True)
103
  return datafra
104
 
105
+ @ensure_fresh_data
106
  def generate_cards_html(datafra):
107
+ global shortcuts_list
108
  if datafra.empty:
109
  return "<p>No shortcuts available.</p>"
110
  cards_html = '<div style="display: flex; flex-wrap: wrap;">'
 
142
  </div>
143
  """
144
  card_html = f"""
145
+ <div style="{style}"
146
+ onmouseover="window.handleHover(event, {idx})"
147
+ onmouseout="window.handleHoverOut(event, {idx})">
148
  {labels_html}
149
  <div style='font-size: 40px; text-align: center;'>{shortcut['emojis']}</div>
150
  <h3 style='text-align: center;'>{shortcut['name']}</h3>
151
  <p style='text-align: center;'>{shortcut['short_description']}</p>
152
  <div style='text-align: center;'>
153
+ <button style="background: none; border: none; cursor: pointer; {pin_style}" onclick="window.togglePin({idx})">{pin_icon}</button>
154
+ <button style="background: none; border: none; cursor: pointer;" onclick="window.toggleFavorite({idx})">{favorite_icon}</button>
155
  <button onclick="window.open('{shortcut['link']}', '_blank')">🔗 Open</button>
156
  </div>
157
+ <div id="delete-{idx}" style="display: none; position: absolute; top: 10px; left: 10px; cursor: pointer;" onclick="window.deleteShortcut({idx})">
158
  🗑️
159
  </div>
160
  </div>
161
  """
162
  cards_html += card_html
163
  cards_html += '</div>'
 
 
 
164
  return cards_html
165
 
166
+ @ensure_fresh_data
167
  def update_display(sort_by='Recently Added', search_query='', filter_tags=[]):
168
+ global shortcuts_list
169
  datafra = get_shortcuts_dataframe(sort_by, search_query, filter_tags)
170
  return generate_cards_html(datafra)
171
 
172
+ @ensure_fresh_data
173
  def toggle_pin(index):
174
+ global shortcuts_list
175
  index = int(index)
176
  if 0 <= index < len(shortcuts_list):
177
  shortcuts_list[index]['pinned'] = not shortcuts_list[index]['pinned']
 
179
  # Return updated HTML
180
  return update_display()
181
 
182
+ @ensure_fresh_data
183
  def toggle_favorite(index):
184
+ global shortcuts_list
185
  index = int(index)
186
  if 0 <= index < len(shortcuts_list):
187
  shortcuts_list[index]['favorited'] = not shortcuts_list[index]['favorited']
 
189
  # Return updated HTML
190
  return update_display()
191
 
192
+ @ensure_fresh_data
193
+ def delete_shortcut(index):
194
+ global shortcuts_list
195
+ index = int(index)
196
+ if 0 <= index < len(shortcuts_list):
197
+ del shortcuts_list[index]
198
+ save_shortcuts()
199
+ # Return updated HTML
200
+ return update_display()
201
+
202
  load_shortcuts()
203
 
204
+
205
+ # JavaScript code attached to window object
206
+
207
  js_code = f"""
208
  function my_func() {{
209
  window.isCmdOrCtrl = false;
 
246
  }});
247
  }};
248
 
249
+ window.togglePin = function(idx) {{
250
+ // Implement the delete functionality, e.g., call an API endpoint
251
+ fetch('/toggle_pin', {{
252
+ method: 'POST',
253
+ headers: {{
254
+ 'Content-Type': 'application/json'
255
+ }},
256
+ body: JSON.stringify({{ index: idx }})
257
+ }})
258
+ .then(response => response.json())
259
+ .then(data => {{
260
+ // Update the grid display
261
+ document.getElementById('grid_output').innerHTML = data.grid_html;
262
+ }});
263
+ }};
264
+
265
  window.deleteShortcut = function(idx) {{
266
  // Implement the delete functionality, e.g., call an API endpoint
267
  fetch('/delete_shortcut', {{
 
279
  }};
280
  }}
281
  """
282
+
283
  # Build the Gradio App
284
+ with gr.Blocks(theme="charbelgrower/Crystal", js=js_code) as demo:
285
 
286
  gr.Markdown("## Website Shortcuts")
287
  with gr.Row():
 
296
 
297
  grid_output = gr.HTML(value=update_display(), elem_id="grid_output")
298
 
299
+ # demo.load(t)
300
+ load_shortcuts()
301
+
302
  gr.Markdown("## Add a New Website Shortcut")
303
  with gr.Row():
304
  name = gr.Textbox(label="Name")
 
310
  color_to = gr.ColorPicker(label="Gradient Color To")
311
  short_description = gr.Textbox(label="Short Description")
312
  add_button = gr.Button("Add Shortcut")
313
+
314
  # Update display when filters change
315
+ def refresh_display(search_query='', sort_by='Recently Added', filter_tags=[]):
316
+ grid_html = update_display(sort_by, search_query, filter_tags)
317
+ filter_tags_options = get_all_tags()
318
+ return grid_html, gr.update(choices=filter_tags_options)
319
 
320
  search_bar.change(fn=refresh_display, inputs=[search_bar, sort_options, filter_tags], outputs=grid_output)
321
  sort_options.change(fn=refresh_display, inputs=[search_bar, sort_options, filter_tags], outputs=grid_output)
 
327
  inputs=[name, tags, link, emojis, color_from, color_to, short_description],
328
  outputs=grid_output
329
  )
330
+ state = gr.State(value=[], delete_callback=lambda v: print("STATE DELETED"))
331
+ load_shortcuts()
332
+ # demo.load(get_shortcuts_dataframe)
333
+ # Expose endpoints for custom functions using FastAPI
334
  api = FastAPI()
335
+ load_shortcuts()
336
+
337
 
338
+ @api.post('/save_shortcut')
339
+ async def save_shortcut_endpoint(request: Request):
340
  data = await request.json()
341
+ grid_html = save_shortcut(data)
 
342
  return {'grid_html': grid_html}
343
 
344
+ @api.post('/delete_shortcut')
345
+ async def delete_shortcut_endpoint(request: Request):
346
  data = await request.json()
347
+ index = data.get('index')
348
+ grid_html = delete_shortcut(index)
 
 
 
 
349
  return {'grid_html': grid_html}
350
 
351
+ @api.post('/toggle_pin')
352
+ async def toggle_pin_endpoint(request: Request):
353
  data = await request.json()
354
+ index = data.get('index')
355
+ grid_html = toggle_pin(index)
356
  return {'grid_html': grid_html}
357
 
358
+ @api.post('/toggle_favorite')
359
+ async def toggle_favorite_endpoint(request: Request):
360
+ data = await request.json()
361
+ index = data.get('index')
362
+ grid_html = toggle_favorite(index)
363
+ return {'grid_html': grid_html}
364
 
365
+ app = gr.mount_gradio_app(api, demo,"/")
366
+ # Initialize file watcher
367
  if __name__ == "__main__":
368
  import uvicorn
369
+ event_handler = JSONFileHandler()
370
+ observer = Observer()
371
+ observer.schedule(event_handler, path=str(user_dir / f"{getpass.getuser()}.json"), recursive=False)
372
+ observer.start()
373
+
374
+ try:
375
+ uvicorn.run(app, host="127.0.0.1", port=7860)
376
+ finally:
377
+ demo.unload(delete_directory)
378
+ observer.stop()
379
+ observer.join()
requirements.txt CHANGED
@@ -1,7 +1,7 @@
1
  APScheduler
2
  black
3
  datasets
4
- gradio==3.40.1
5
  gradio[oauth]
6
  gradio_client
7
  huggingface-hub>=0.18.0
@@ -14,4 +14,5 @@ transformers
14
  tokenizers>=0.15.0
15
  sentencepiece
16
  uvicorn
17
- fastapi
 
 
1
  APScheduler
2
  black
3
  datasets
4
+ gradio==5.5.0
5
  gradio[oauth]
6
  gradio_client
7
  huggingface-hub>=0.18.0
 
14
  tokenizers>=0.15.0
15
  sentencepiece
16
  uvicorn
17
+ fastapi
18
+ watchdog>=2.1.6
shortcuts.json CHANGED
@@ -1 +1 @@
1
- [{"name": "", "tags": [], "link": "", "emojis": "", "color_from": "#000000", "color_to": "#000000", "short_description": "", "pinned": false, "favorited": false, "date_added": "2024-11-12 23:05:43.625612"}]
 
1
+ [{"name": "Charbel", "tags": ["Personal"], "link": "example.com", "emojis": "\ud83e\udd70", "color_from": "rgba(157.78125, 125.2561677631579, 125.2561677631579, 1)", "color_to": "rgba(255, 0, 0, 1)", "short_description": "ssadasd", "pinned": false, "favorited": false, "date_added": "2024-11-13T16:25:36.058089"}]