charbelmalo commited on
Commit
9811ae6
Β·
1 Parent(s): 084d624

revert to old commit but with updated readme

Browse files
Files changed (1) hide show
  1. app.py +38 -137
app.py CHANGED
@@ -4,60 +4,24 @@ from datetime import datetime
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,18 +34,12 @@ def add_shortcut(name, tags, link, emojis, color_from, color_to, short_descripti
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,9 +60,7 @@ def get_shortcuts_dataframe(sort_by='Recently Added', search_query='', filter_ta
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,36 +98,33 @@ def generate_cards_html(datafra):
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,9 +132,7 @@ def toggle_pin(index):
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,21 +140,8 @@ def toggle_favorite(index):
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,22 +184,6 @@ window.hideDeleteIcons = function() {{
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,9 +201,8 @@ window.deleteShortcut = function(idx) {{
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,9 +217,6 @@ with gr.Blocks(theme="charbelgrower/Crystal", js=js_code) as demo:
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,12 +228,10 @@ with gr.Blocks(theme="charbelgrower/Crystal", js=js_code) as demo:
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,53 +243,38 @@ with gr.Blocks(theme="charbelgrower/Crystal", js=js_code) as demo:
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()
 
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
  '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
  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
  </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
  # 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
  # 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
  }});
185
  }};
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  window.deleteShortcut = function(idx) {{
188
  // Implement the delete functionality, e.g., call an API endpoint
189
  fetch('/delete_shortcut', {{
 
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
 
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
  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
  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)