Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -10,48 +10,6 @@ import json
|
|
| 10 |
# --- Constants ---
|
| 11 |
MELBOURNE_TIMEZONE = 'Australia/Melbourne'
|
| 12 |
|
| 13 |
-
# --- Custom CSS for simplified UI ---
|
| 14 |
-
def load_css():
|
| 15 |
-
st.markdown("""
|
| 16 |
-
<style>
|
| 17 |
-
.main-header {
|
| 18 |
-
padding: 2rem;
|
| 19 |
-
text-align: center;
|
| 20 |
-
margin-bottom: 2rem;
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
.citation-output {
|
| 24 |
-
background: #f8f8f8;
|
| 25 |
-
border: 1px solid #e0e0e0;
|
| 26 |
-
border-radius: 4px;
|
| 27 |
-
padding: 1rem;
|
| 28 |
-
margin: 1rem 0;
|
| 29 |
-
font-family: 'Courier New', monospace;
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
-
.copy-button {
|
| 33 |
-
background: #e0e0e0;
|
| 34 |
-
color: black;
|
| 35 |
-
border: none;
|
| 36 |
-
padding: 0.5rem 1rem;
|
| 37 |
-
border-radius: 4px;
|
| 38 |
-
cursor: pointer;
|
| 39 |
-
font-size: 0.9rem;
|
| 40 |
-
Gentiles
|
| 41 |
-
|
| 42 |
-
System: <xaiArtifact artifact_id="9742b08f-bd1c-4ab1-9763-3ba142fe8ff2" artifact_version_id="905b7ac0-d0b9-4b2e-b9ad-4814e3320ff5" title="app.py" contentType="text/python">
|
| 43 |
-
import streamlit as st
|
| 44 |
-
import streamlit.components.v1 as components
|
| 45 |
-
import hashlib
|
| 46 |
-
import urllib.parse
|
| 47 |
-
from datetime import datetime
|
| 48 |
-
import pytz
|
| 49 |
-
import pandas as pd
|
| 50 |
-
import json
|
| 51 |
-
|
| 52 |
-
# --- Constants ---
|
| 53 |
-
MELBOURNE_TIMEZONE = 'Australia/Melbourne'
|
| 54 |
-
|
| 55 |
# --- Custom CSS for simplified UI ---
|
| 56 |
def load_css():
|
| 57 |
st.markdown("""
|
|
@@ -112,7 +70,8 @@ def load_css():
|
|
| 112 |
|
| 113 |
.footer {
|
| 114 |
text-align: center;
|
| 115 |
-
padding: 2rem
|
|
|
|
| 116 |
border-top: 1px solid #e0e0e0;
|
| 117 |
font-size: 0.9rem;
|
| 118 |
}
|
|
@@ -158,21 +117,21 @@ def generate_citation_hash(author, year, url, fragment_text, cited_text, usernam
|
|
| 158 |
data = f"{author}, {year} | {url} | {fragment_text} | {cited_text} | {username} | {task_name} | {current_date} | {current_time}"
|
| 159 |
return hashlib.sha256(data.encode('utf-8')).hexdigest()
|
| 160 |
|
| 161 |
-
def format_citation_html(url, fragment_text,
|
| 162 |
encoded_fragment = urllib.parse.quote(fragment_text)
|
| 163 |
full_url = f"{url}#:~:text={encoded_fragment}"
|
| 164 |
-
return f'<a href="{full_url}" data-hash="{scc_hash}"
|
| 165 |
|
| 166 |
def check_for_fragment(url):
|
| 167 |
return '#:~:text=' in url
|
| 168 |
|
| 169 |
-
def copy_to_clipboard_js(
|
| 170 |
-
"""Generate JavaScript for copying
|
| 171 |
-
# Encode the
|
| 172 |
-
|
| 173 |
return f"""
|
| 174 |
<div>
|
| 175 |
-
<textarea id="copy_text_{button_id}" style="display: none;">{
|
| 176 |
<button onclick="copyToClipboard_{button_id}()" class="copy-button">Copy to Clipboard</button>
|
| 177 |
<span id="copy_status_{button_id}" style="margin-left: 10px; font-weight: bold;"></span>
|
| 178 |
</div>
|
|
@@ -180,47 +139,33 @@ def copy_to_clipboard_js(html_text, button_id):
|
|
| 180 |
function copyToClipboard_{button_id}() {{
|
| 181 |
console.log('Copy function triggered for {button_id}');
|
| 182 |
const textElement = document.getElementById('copy_text_{button_id}');
|
| 183 |
-
const
|
| 184 |
-
if (!
|
| 185 |
console.error('No text to copy for {button_id}');
|
| 186 |
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 187 |
if (statusElement) statusElement.innerHTML = 'No text to copy';
|
| 188 |
return;
|
| 189 |
}}
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
range.selectNodeContents(tempDiv);
|
| 198 |
-
const selection = window.getSelection();
|
| 199 |
-
selection.removeAllRanges();
|
| 200 |
-
selection.addRange(range);
|
| 201 |
-
|
| 202 |
-
// Copy to clipboard as HTML
|
| 203 |
-
try {{
|
| 204 |
-
const successful = document.execCommand('copy');
|
| 205 |
-
console.log('Copy command executed for {button_id}: ' + (successful ? 'success' : 'failed'));
|
| 206 |
-
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 207 |
-
if (statusElement) {{
|
| 208 |
-
statusElement.innerHTML = successful ? 'Copied!' : 'Copy failed';
|
| 209 |
-
if (successful) {{
|
| 210 |
-
setTimeout(() => {{
|
| 211 |
statusElement.innerHTML = '';
|
| 212 |
}}, 2000);
|
| 213 |
}}
|
| 214 |
-
}}
|
| 215 |
-
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 218 |
-
if (statusElement) statusElement.innerHTML = '
|
| 219 |
}}
|
| 220 |
-
|
| 221 |
-
// Clean up
|
| 222 |
-
selection.removeAllRanges();
|
| 223 |
-
document.body.removeChild(tempDiv);
|
| 224 |
}}
|
| 225 |
</script>
|
| 226 |
"""
|
|
@@ -363,8 +308,8 @@ with tabs[0]:
|
|
| 363 |
""", unsafe_allow_html=True)
|
| 364 |
else:
|
| 365 |
scc_hash = generate_citation_hash(author_name, publication_year, source_url, annotated_text, annotated_text, username, task_name, current_date, current_time)
|
| 366 |
-
citation_link_start =
|
| 367 |
-
citation_link_end =
|
| 368 |
|
| 369 |
st.markdown("## Generated Citations")
|
| 370 |
col_html1, col_html2 = st.columns(2)
|
|
@@ -479,7 +424,7 @@ with tabs[1]:
|
|
| 479 |
"Year": verify_publication_year,
|
| 480 |
"URL": verify_source_url,
|
| 481 |
"Fragment text": verify_annotated_text,
|
| 482 |
-
"
|
| 483 |
"Username": verify_username,
|
| 484 |
"Task name": verify_task_name,
|
| 485 |
"Date": verify_date,
|
|
@@ -536,7 +481,7 @@ with tabs[1]:
|
|
| 536 |
# Clear history button
|
| 537 |
if st.button("Clear Verification History", type="secondary"):
|
| 538 |
st.session_state.verified_hashes = []
|
| 539 |
-
st.
|
| 540 |
|
| 541 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 542 |
|
|
|
|
| 10 |
# --- Constants ---
|
| 11 |
MELBOURNE_TIMEZONE = 'Australia/Melbourne'
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
# --- Custom CSS for simplified UI ---
|
| 14 |
def load_css():
|
| 15 |
st.markdown("""
|
|
|
|
| 70 |
|
| 71 |
.footer {
|
| 72 |
text-align: center;
|
| 73 |
+
padding: 2rem;
|
| 74 |
+
margin-top: 2rem;
|
| 75 |
border-top: 1px solid #e0e0e0;
|
| 76 |
font-size: 0.9rem;
|
| 77 |
}
|
|
|
|
| 117 |
data = f"{author}, {year} | {url} | {fragment_text} | {cited_text} | {username} | {task_name} | {current_date} | {current_time}"
|
| 118 |
return hashlib.sha256(data.encode('utf-8')).hexdigest()
|
| 119 |
|
| 120 |
+
def format_citation_html(url, fragment_text, author, year, scc_hash):
|
| 121 |
encoded_fragment = urllib.parse.quote(fragment_text)
|
| 122 |
full_url = f"{url}#:~:text={encoded_fragment}"
|
| 123 |
+
return f'<a href="{full_url}" data-hash="{scc_hash}">{author} ({year})</a>'
|
| 124 |
|
| 125 |
def check_for_fragment(url):
|
| 126 |
return '#:~:text=' in url
|
| 127 |
|
| 128 |
+
def copy_to_clipboard_js(text, button_id):
|
| 129 |
+
"""Generate JavaScript for copying text to clipboard using a textarea."""
|
| 130 |
+
# Encode the text as a JavaScript-safe string
|
| 131 |
+
escaped_text = json.dumps(text, ensure_ascii=False)[1:-1].replace('</', '<\\/')
|
| 132 |
return f"""
|
| 133 |
<div>
|
| 134 |
+
<textarea id="copy_text_{button_id}" style="display: none;">{escaped_text}</textarea>
|
| 135 |
<button onclick="copyToClipboard_{button_id}()" class="copy-button">Copy to Clipboard</button>
|
| 136 |
<span id="copy_status_{button_id}" style="margin-left: 10px; font-weight: bold;"></span>
|
| 137 |
</div>
|
|
|
|
| 139 |
function copyToClipboard_{button_id}() {{
|
| 140 |
console.log('Copy function triggered for {button_id}');
|
| 141 |
const textElement = document.getElementById('copy_text_{button_id}');
|
| 142 |
+
const textToCopy = textElement ? textElement.value : '';
|
| 143 |
+
if (!textToCopy) {{
|
| 144 |
console.error('No text to copy for {button_id}');
|
| 145 |
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 146 |
if (statusElement) statusElement.innerHTML = 'No text to copy';
|
| 147 |
return;
|
| 148 |
}}
|
| 149 |
+
if (navigator.clipboard) {{
|
| 150 |
+
navigator.clipboard.writeText(textToCopy).then(function() {{
|
| 151 |
+
console.log('Text copied successfully for {button_id}: ' + textToCopy);
|
| 152 |
+
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 153 |
+
if (statusElement) {{
|
| 154 |
+
statusElement.innerHTML = 'Copied!';
|
| 155 |
+
setTimeout(function() {{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
statusElement.innerHTML = '';
|
| 157 |
}}, 2000);
|
| 158 |
}}
|
| 159 |
+
}}, function(err) {{
|
| 160 |
+
console.error('Copy failed for {button_id}: ', err);
|
| 161 |
+
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 162 |
+
if (statusElement) statusElement.innerHTML = 'Copy failed';
|
| 163 |
+
}});
|
| 164 |
+
}} else {{
|
| 165 |
+
console.error('Clipboard API not supported');
|
| 166 |
const statusElement = document.getElementById('copy_status_{button_id}');
|
| 167 |
+
if (statusElement) statusElement.innerHTML = 'Clipboard API not supported';
|
| 168 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
}}
|
| 170 |
</script>
|
| 171 |
"""
|
|
|
|
| 308 |
""", unsafe_allow_html=True)
|
| 309 |
else:
|
| 310 |
scc_hash = generate_citation_hash(author_name, publication_year, source_url, annotated_text, annotated_text, username, task_name, current_date, current_time)
|
| 311 |
+
citation_link_start = f'<a href="{source_url}#:~:text={urllib.parse.quote(annotated_text)}" data-hash="{scc_hash}">{author_name} ({publication_year})</a>'
|
| 312 |
+
citation_link_end = f'<a href="{source_url}#:~:text={urllib.parse.quote(annotated_text)}" data-hash="{scc_hash}">({author_name}, {publication_year})</a>'
|
| 313 |
|
| 314 |
st.markdown("## Generated Citations")
|
| 315 |
col_html1, col_html2 = st.columns(2)
|
|
|
|
| 424 |
"Year": verify_publication_year,
|
| 425 |
"URL": verify_source_url,
|
| 426 |
"Fragment text": verify_annotated_text,
|
| 427 |
+
"Outlined text": verify_annotated_text,
|
| 428 |
"Username": verify_username,
|
| 429 |
"Task name": verify_task_name,
|
| 430 |
"Date": verify_date,
|
|
|
|
| 481 |
# Clear history button
|
| 482 |
if st.button("Clear Verification History", type="secondary"):
|
| 483 |
st.session_state.verified_hashes = []
|
| 484 |
+
st.experimental_rerun()
|
| 485 |
|
| 486 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 487 |
|