mrfakename commited on
Commit
2bfaee6
·
1 Parent(s): cfcca52
Files changed (2) hide show
  1. app.py +47 -3
  2. templates/dashboard.html +13 -3
app.py CHANGED
@@ -4,6 +4,7 @@ import urllib.parse
4
  import sqlite3
5
  import json
6
  import time
 
7
  from flask import Flask, redirect, request, session, render_template, url_for, g
8
  import requests
9
 
@@ -25,6 +26,39 @@ CACHE_TTL = 300 # 5 minutes
25
  DB_PATH = "cache.db"
26
 
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  def get_db():
29
  if "db" not in g:
30
  g.db = sqlite3.connect(DB_PATH)
@@ -126,7 +160,7 @@ def fetch_space_discussions(space_id, token=None):
126
  return discussions
127
 
128
 
129
- def get_discussions_feed(username, token=None):
130
  spaces = fetch_user_spaces(username, token)
131
 
132
  all_discussions = []
@@ -136,9 +170,17 @@ def get_discussions_feed(username, token=None):
136
 
137
  for d in discussions:
138
  owner_responded = d.get("repoOwner", {}).get("isParticipating", False)
 
 
 
139
  base_score = d.get("numComments", 0) + d.get("numReactionUsers", 0) * 2
 
140
  # Demote if owner has responded
141
- score = base_score - 100 if owner_responded else base_score
 
 
 
 
142
  all_discussions.append({
143
  "space_id": space_id,
144
  "space_name": space_id.split("/")[-1] if "/" in space_id else space_id,
@@ -149,11 +191,13 @@ def get_discussions_feed(username, token=None):
149
  "author": d.get("author", {}).get("name", "unknown"),
150
  "author_avatar": d.get("author", {}).get("avatarUrl", ""),
151
  "created_at": d.get("createdAt", ""),
 
152
  "num_comments": d.get("numComments", 0),
153
  "num_reactions": d.get("numReactionUsers", 0),
154
  "top_reactions": d.get("topReactions", []),
155
  "score": score,
156
  "owner_responded": owner_responded,
 
157
  "url": f"https://huggingface.co/spaces/{space_id}/discussions/{d.get('num')}",
158
  })
159
 
@@ -260,7 +304,7 @@ def dashboard():
260
  filter_status = request.args.get("status", "open")
261
 
262
  spaces = fetch_user_spaces(username, token)
263
- discussions = get_discussions_feed(username, token)
264
 
265
  # Filter by status
266
  if filter_status == "open":
 
4
  import sqlite3
5
  import json
6
  import time
7
+ from datetime import datetime, timezone
8
  from flask import Flask, redirect, request, session, render_template, url_for, g
9
  import requests
10
 
 
26
  DB_PATH = "cache.db"
27
 
28
 
29
+ def relative_time(iso_timestamp):
30
+ if not iso_timestamp:
31
+ return ""
32
+ try:
33
+ dt = datetime.fromisoformat(iso_timestamp.replace("Z", "+00:00"))
34
+ now = datetime.now(timezone.utc)
35
+ diff = now - dt
36
+
37
+ seconds = diff.total_seconds()
38
+ if seconds < 60:
39
+ return "now"
40
+ elif seconds < 3600:
41
+ mins = int(seconds // 60)
42
+ return f"{mins}m"
43
+ elif seconds < 86400:
44
+ hours = int(seconds // 3600)
45
+ return f"{hours}h"
46
+ elif seconds < 604800:
47
+ days = int(seconds // 86400)
48
+ return f"{days}d"
49
+ elif seconds < 2592000:
50
+ weeks = int(seconds // 604800)
51
+ return f"{weeks}w"
52
+ elif seconds < 31536000:
53
+ months = int(seconds // 2592000)
54
+ return f"{months}mo"
55
+ else:
56
+ years = int(seconds // 31536000)
57
+ return f"{years}y"
58
+ except Exception:
59
+ return ""
60
+
61
+
62
  def get_db():
63
  if "db" not in g:
64
  g.db = sqlite3.connect(DB_PATH)
 
160
  return discussions
161
 
162
 
163
+ def get_discussions_feed(username, token=None, logged_in_user=None):
164
  spaces = fetch_user_spaces(username, token)
165
 
166
  all_discussions = []
 
170
 
171
  for d in discussions:
172
  owner_responded = d.get("repoOwner", {}).get("isParticipating", False)
173
+ discussion_author = d.get("author", {}).get("name", "")
174
+ is_own_discussion = logged_in_user and discussion_author.lower() == logged_in_user.lower()
175
+
176
  base_score = d.get("numComments", 0) + d.get("numReactionUsers", 0) * 2
177
+ score = base_score
178
  # Demote if owner has responded
179
+ if owner_responded:
180
+ score -= 100
181
+ # Heavily demote if user started it themselves
182
+ if is_own_discussion:
183
+ score -= 1000
184
  all_discussions.append({
185
  "space_id": space_id,
186
  "space_name": space_id.split("/")[-1] if "/" in space_id else space_id,
 
191
  "author": d.get("author", {}).get("name", "unknown"),
192
  "author_avatar": d.get("author", {}).get("avatarUrl", ""),
193
  "created_at": d.get("createdAt", ""),
194
+ "relative_time": relative_time(d.get("createdAt", "")),
195
  "num_comments": d.get("numComments", 0),
196
  "num_reactions": d.get("numReactionUsers", 0),
197
  "top_reactions": d.get("topReactions", []),
198
  "score": score,
199
  "owner_responded": owner_responded,
200
+ "is_own": is_own_discussion,
201
  "url": f"https://huggingface.co/spaces/{space_id}/discussions/{d.get('num')}",
202
  })
203
 
 
304
  filter_status = request.args.get("status", "open")
305
 
306
  spaces = fetch_user_spaces(username, token)
307
+ discussions = get_discussions_feed(username, token, logged_in_user=username)
308
 
309
  # Filter by status
310
  if filter_status == "open":
templates/dashboard.html CHANGED
@@ -256,11 +256,20 @@
256
  .feed-item.responded {
257
  opacity: 0.5;
258
  }
259
- .responded-badge {
 
 
 
 
260
  font-size: 0.625rem;
261
  color: #555;
262
  margin-left: 0.25rem;
263
  }
 
 
 
 
 
264
  </style>
265
  </head>
266
  <body>
@@ -320,14 +329,15 @@
320
  {% if discussions %}
321
  <div class="feed">
322
  {% for d in discussions %}
323
- <a href="{{ d.url }}" target="_blank" class="feed-item status-{{ d.status }}{{ ' is-report' if 'report' in d.title|lower else '' }}{{ ' responded' if d.owner_responded else '' }}">
324
  <div class="feed-meta">
325
  <span class="feed-space">{{ d.space_name }}</span>
326
  <span class="feed-type {{ 'pr' if d.is_pr else 'discussion' }}">
327
  {{ 'PR' if d.is_pr else 'Discussion' }}
328
  </span>
329
  <span class="feed-status {{ d.status }}">{{ d.status }}</span>
330
- {% if d.owner_responded %}<span class="responded-badge">replied</span>{% endif %}
 
331
  </div>
332
  <div class="feed-title">{{ d.title }}</div>
333
  <div class="feed-stats">
 
256
  .feed-item.responded {
257
  opacity: 0.5;
258
  }
259
+ .feed-item.is-own {
260
+ opacity: 0.35;
261
+ }
262
+ .responded-badge,
263
+ .own-badge {
264
  font-size: 0.625rem;
265
  color: #555;
266
  margin-left: 0.25rem;
267
  }
268
+ .feed-time {
269
+ font-size: 0.75rem;
270
+ color: #444;
271
+ margin-left: auto;
272
+ }
273
  </style>
274
  </head>
275
  <body>
 
329
  {% if discussions %}
330
  <div class="feed">
331
  {% for d in discussions %}
332
+ <a href="{{ d.url }}" target="_blank" class="feed-item status-{{ d.status }}{{ ' is-report' if 'report' in d.title|lower else '' }}{{ ' responded' if d.owner_responded else '' }}{{ ' is-own' if d.is_own else '' }}">
333
  <div class="feed-meta">
334
  <span class="feed-space">{{ d.space_name }}</span>
335
  <span class="feed-type {{ 'pr' if d.is_pr else 'discussion' }}">
336
  {{ 'PR' if d.is_pr else 'Discussion' }}
337
  </span>
338
  <span class="feed-status {{ d.status }}">{{ d.status }}</span>
339
+ {% if d.is_own %}<span class="own-badge">you</span>{% elif d.owner_responded %}<span class="responded-badge">replied</span>{% endif %}
340
+ {% if d.relative_time %}<span class="feed-time">{{ d.relative_time }}</span>{% endif %}
341
  </div>
342
  <div class="feed-title">{{ d.title }}</div>
343
  <div class="feed-stats">