Skip to content

Commit 29236ff

Browse files
pkvachjelmer
andauthored
admin: Add support for comment search by URL (#1000)
* admin: Add support for comment search by URL Fixes #642 Co-authored-by: Jelmer Vernooij <jelmer@jelmer.uk>
1 parent d3d8ae5 commit 29236ff

5 files changed

Lines changed: 104 additions & 8 deletions

File tree

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ New Features
99

1010
- Add Catalan localisation (`#966`_, welpo)
1111
- Make <code class="language-$lang"> for syntax highlighting (`#998`_, pkvach)
12+
- Add search for comments by URL in the admin interface (`#1000`_, pkvach)
1213
- Add CSS variables for better organization and flexibility (`#1001`_, pkvach)
1314

15+
.. _#966: https://github.com/posativ/isso/pull/966
16+
.. _#998: https://github.com/isso-comments/isso/pull/998
17+
.. _#1000: https://github.com/isso-comments/isso/pull/1000
1418
.. _#966: https://github.com/posativ/isso/pull/966
1519
.. _#998: https://github.com/isso-comments/isso/pull/998
1620
.. _#1001: https://github.com/isso-comments/isso/pull/1001

isso/css/admin.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,40 @@ a {
126126
float: left;
127127
margin-left: 2em;
128128
}
129+
130+
.search {
131+
float: right;
132+
}
133+
134+
.search .search__input {
135+
margin: 0 .3em;
136+
padding: .3em 10px;
137+
width: 18em;
138+
border-radius: 3px;
139+
background-color: #fff;
140+
border: 1px solid rgba(0, 0, 0, 0.2);
141+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
142+
}
143+
.search .search__input:focus {
144+
outline: 2px solid #3584e4;
145+
}
146+
147+
.search .search__button {
148+
margin: 0 .3em;
149+
padding: .3em;
150+
border-radius: 2px;
151+
border: 1px solid #ccc;
152+
background-color: #ddd;
153+
cursor: pointer;
154+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
155+
}
156+
.search .search__button:hover {
157+
background-color: #ccc;
158+
}
159+
.search .search__button:active {
160+
background-color: #bbb;
161+
}
162+
129163
.editable {
130164
border: 1px solid #aaa;
131165
border-radius: 5px;

isso/db/comments.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def count_modes(self):
167167
return dict(comment_count)
168168

169169
def fetchall(self, mode=5, after=0, parent='any', order_by='id',
170-
limit=100, page=0, asc=1):
170+
limit=100, page=0, asc=1, comment_id=None):
171171
"""
172172
Return comments for admin with :param:`mode`.
173173
"""
@@ -182,8 +182,14 @@ def fetchall(self, mode=5, after=0, parent='any', order_by='id',
182182
sql = ['SELECT ' + sql_comments_fields + ', ' + sql_threads_fields + ' '
183183
'FROM comments INNER JOIN threads '
184184
'ON comments.tid=threads.id '
185-
'WHERE comments.mode = ? ']
186-
sql_args = [mode]
185+
'WHERE ']
186+
187+
if comment_id:
188+
sql.append('comments.id = ? ')
189+
sql_args = [comment_id]
190+
else:
191+
sql.append('comments.mode = ? ')
192+
sql_args = [mode]
187193

188194
if parent != 'any':
189195
if parent is None:

isso/templates/admin.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ <h2>Administration</h2>
7171
</span>
7272
</a>
7373
{% endfor %}
74+
<div class="search">
75+
<form action="/admin/" method="get">
76+
<input type="hidden" name="mode" value="0" />
77+
<label>Comment URL
78+
<input type="search" class="search__input" name="comment_url" value="{{comment_url}}" spellcheck="false"
79+
required placeholder="https://example.com/demo/#isso-1" />
80+
</label>
81+
<button type="submit" class="search__button">Search</button>
82+
</form>
83+
</div>
7484
</div>
7585
</div>
7686
<div id="isso-root">

isso/views/comments.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from html import escape
1313
from io import BytesIO as StringIO
1414
from os import path as os_path
15-
from urllib.parse import unquote, urlparse
15+
from urllib.parse import unquote, urlparse, urlsplit
1616
from xml.etree import ElementTree as ET
1717

1818
from itsdangerous import SignatureExpired, BadSignature
@@ -84,6 +84,38 @@ def dec(self, env, req, *args, **kwargs):
8484
return dec
8585

8686

87+
def get_comment_id_from_url(comment_url):
88+
"""
89+
Extracts the comment ID from a given comment URL.
90+
91+
Args:
92+
comment_url (str): The URL of the comment.
93+
94+
Returns:
95+
int or None: The extracted comment ID if successful, None otherwise.
96+
"""
97+
try:
98+
# Parse the comment URL to extract the comment ID from the fragment
99+
parsed_url = urlsplit(comment_url)
100+
except ValueError:
101+
# Handle malformed URL
102+
return None
103+
104+
fragment = parsed_url.fragment
105+
if not fragment or '-' not in fragment:
106+
# Handle missing fragment or fragment without hyphen
107+
return None
108+
109+
last_element = fragment.split('-')[-1]
110+
try:
111+
comment_id = int(last_element)
112+
except ValueError:
113+
# Handle invalid comment ID
114+
return None
115+
116+
return comment_id
117+
118+
87119
class API(object):
88120

89121
FIELDS = set(['id', 'parent', 'text', 'author', 'website',
@@ -1376,6 +1408,8 @@ def login(self, env, req):
13761408
Comment ordering
13771409
@apiQuery {Number{0,1}} [asc=0]
13781410
Ascending
1411+
@apiQuery {String} comment_url
1412+
Search comment by URL
13791413
13801414
@apiExample {curl} Listing of published comments:
13811415
curl 'https://comments.example.com/admin/?mode=1&page=0&order_by=modified&asc=1' -b cookie.txt
@@ -1396,10 +1430,17 @@ def admin(self, env, req):
13961430
order_by = req.args.get('order_by', 'created')
13971431
asc = int(req.args.get('asc', 0))
13981432
mode = int(req.args.get('mode', 2))
1399-
comments = self.comments.fetchall(mode=mode, page=page,
1400-
limit=page_size,
1401-
order_by=order_by,
1402-
asc=asc)
1433+
comment_url = req.args.get('comment_url', '')
1434+
1435+
# Search for a specific comment by URL
1436+
if comment_url:
1437+
comment_id = get_comment_id_from_url(comment_url)
1438+
comments = self.comments.fetchall(comment_id=comment_id, limit=1) if comment_id else []
1439+
else:
1440+
comments = self.comments.fetchall(mode=mode, page=page,
1441+
limit=page_size,
1442+
order_by=order_by,
1443+
asc=asc)
14031444
comments_enriched = []
14041445
for comment in list(comments):
14051446
comment['hash'] = self.isso.sign(comment['id'])
@@ -1411,6 +1452,7 @@ def admin(self, env, req):
14111452
conf=self.conf, max_page=max_page,
14121453
counts=comment_mode_count,
14131454
order_by=order_by, asc=asc,
1455+
comment_url=comment_url,
14141456
isso_host_script=isso_host_script)
14151457
"""
14161458
@api {get} /latest latest

0 commit comments

Comments
 (0)