Spaces:
Paused
Paused
unknown Claude Opus 5.5 commited on
Commit ·
690a6a7
1
Parent(s): 9471d62
Journal Formatter and Journal Finder locked to signed-in users: each tab shows a sign-in card (what the tool does, free with an account) until the visitor signs in, and the server refuses a run without an account; Pricing and the free-use note say "free with an account"
Browse files- app.py +33 -14
- plans.py +1 -1
- tests/test_auth_outputs.py +8 -0
app.py
CHANGED
|
@@ -82,6 +82,12 @@ def suite_panel(ai_before, ai_after, original, revised, labels=None, extra=None,
|
|
| 82 |
EMPTY = """<div class="cs-scores cs-empty"><div>Scores appear here after processing.</div></div>"""
|
| 83 |
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
def _locked(what):
|
| 86 |
if what == "dashboard": # not an upload: the customer's own history and files
|
| 87 |
return ('<div class="cs-lock"><div class="cs-lock-ico">🔒</div>'
|
|
@@ -93,6 +99,11 @@ def _locked(what):
|
|
| 93 |
'<div class="cs-lock-t">Sign in to get your Turnitin report</div>'
|
| 94 |
'<div class="cs-lock-s">A free account takes a minute. Then pay for each report with PhonePe (UPI, '
|
| 95 |
'cards, net banking) right on this page; a report that cannot be produced is refunded.</div></div>')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
|
| 97 |
f'<div class="cs-lock-t">Sign in to upload {what}</div>'
|
| 98 |
f'<div class="cs-lock-s">A free account takes a minute, and your first document is free. '
|
|
@@ -2542,6 +2553,8 @@ def JOB(status):
|
|
| 2542 |
def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool=""):
|
| 2543 |
"""The Journal Formatter / Finder jobs: like H._run_live, but keyed by visitor + tool + input, so a page that
|
| 2544 |
reconnects after a dropped connection picks up the running (or finished) job instead of starting it over."""
|
|
|
|
|
|
|
| 2545 |
key = _job_key(user, request, tool, args) if tool else None
|
| 2546 |
with _START_LOCK:
|
| 2547 |
job = H.find_job(key)
|
|
@@ -2558,7 +2571,7 @@ def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool
|
|
| 2558 |
_FREE_NOTE = (f"Free with a free account: pasted text up to {P.PLANS['free']['paste_words']} words "
|
| 2559 |
f"({P.PLANS['free']['pastes']} a day), {P.FREE_TRIAL_DOCS} trial document up to "
|
| 2560 |
f"{P.PLANS['free']['doc_words']:,} words and {P.FREE_DETECT_DAY} AI detector reports a day. The Journal "
|
| 2561 |
-
"Formatter and the Journal Finder are free. Customers who already have credits or a plan keep using "
|
| 2562 |
"them until they run out; after that, runs are paid from the wallet.")
|
| 2563 |
TOOLS_UI = dict(wait=WAIT, hid=HID, job=JOB, run_live=_run_tool, log=DB.log_run, user=None)
|
| 2564 |
|
|
@@ -2915,20 +2928,26 @@ with gr.Blocks(title=SITE_TITLE, theme=theme, css=CSS + UI.css() + FND.CSS, js=F
|
|
| 2915 |
# Both tools run inside this Space (formatter_tab.py / finder_tab.py). TOOLS_EMBED=1 shows the earlier
|
| 2916 |
# separately hosted apps in a frame instead.
|
| 2917 |
with gr.Tab("Journal Formatter", id="formatter"):
|
| 2918 |
-
|
| 2919 |
-
|
| 2920 |
-
|
| 2921 |
-
|
| 2922 |
-
|
| 2923 |
-
|
| 2924 |
-
|
|
|
|
|
|
|
|
|
|
| 2925 |
with gr.Tab("Journal Finder", id="finder"):
|
| 2926 |
-
|
| 2927 |
-
|
| 2928 |
-
|
| 2929 |
-
|
| 2930 |
-
|
| 2931 |
-
|
|
|
|
|
|
|
|
|
|
| 2932 |
|
| 2933 |
# ============================ PRICING ============================
|
| 2934 |
with gr.Tab("Pricing", id="pricing") as pricing_tab:
|
|
|
|
| 82 |
EMPTY = """<div class="cs-scores cs-empty"><div>Scores appear here after processing.</div></div>"""
|
| 83 |
|
| 84 |
|
| 85 |
+
COMPANION_LOCKS = { # the companion tools need a signed-in account
|
| 86 |
+
"Journal Formatter": "Arrange your manuscript to a journal's format, as a Word file and Overleaf-ready LaTeX.",
|
| 87 |
+
"Journal Finder": "Find journals that match your title, with indexing, quartile, review time and acceptance odds.",
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
|
| 91 |
def _locked(what):
|
| 92 |
if what == "dashboard": # not an upload: the customer's own history and files
|
| 93 |
return ('<div class="cs-lock"><div class="cs-lock-ico">🔒</div>'
|
|
|
|
| 99 |
'<div class="cs-lock-t">Sign in to get your Turnitin report</div>'
|
| 100 |
'<div class="cs-lock-s">A free account takes a minute. Then pay for each report with PhonePe (UPI, '
|
| 101 |
'cards, net banking) right on this page; a report that cannot be produced is refunded.</div></div>')
|
| 102 |
+
if what in COMPANION_LOCKS: # free with an account (signed-in users only)
|
| 103 |
+
return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
|
| 104 |
+
f'<div class="cs-lock-t">Sign in to use the {what}</div>'
|
| 105 |
+
f'<div class="cs-lock-s">{COMPANION_LOCKS[what]} It is included with your free account; '
|
| 106 |
+
'sign in or create one in a minute.</div></div>')
|
| 107 |
return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
|
| 108 |
f'<div class="cs-lock-t">Sign in to upload {what}</div>'
|
| 109 |
f'<div class="cs-lock-s">A free account takes a minute, and your first document is free. '
|
|
|
|
| 2553 |
def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool=""):
|
| 2554 |
"""The Journal Formatter / Finder jobs: like H._run_live, but keyed by visitor + tool + input, so a page that
|
| 2555 |
reconnects after a dropped connection picks up the running (or finished) job instead of starting it over."""
|
| 2556 |
+
if tool in COMPANION_LOCKS and not user: # (the tab is locked; this stops a direct call too)
|
| 2557 |
+
raise gr.Error(f"Please sign in to use the {tool}.", title="Sign in needed")
|
| 2558 |
key = _job_key(user, request, tool, args) if tool else None
|
| 2559 |
with _START_LOCK:
|
| 2560 |
job = H.find_job(key)
|
|
|
|
| 2571 |
_FREE_NOTE = (f"Free with a free account: pasted text up to {P.PLANS['free']['paste_words']} words "
|
| 2572 |
f"({P.PLANS['free']['pastes']} a day), {P.FREE_TRIAL_DOCS} trial document up to "
|
| 2573 |
f"{P.PLANS['free']['doc_words']:,} words and {P.FREE_DETECT_DAY} AI detector reports a day. The Journal "
|
| 2574 |
+
"Formatter and the Journal Finder are free with an account (sign in to use them). Customers who already have credits or a plan keep using "
|
| 2575 |
"them until they run out; after that, runs are paid from the wallet.")
|
| 2576 |
TOOLS_UI = dict(wait=WAIT, hid=HID, job=JOB, run_live=_run_tool, log=DB.log_run, user=None)
|
| 2577 |
|
|
|
|
| 2928 |
# Both tools run inside this Space (formatter_tab.py / finder_tab.py). TOOLS_EMBED=1 shows the earlier
|
| 2929 |
# separately hosted apps in a frame instead.
|
| 2930 |
with gr.Tab("Journal Formatter", id="formatter"):
|
| 2931 |
+
_, fm_open, fm_lockbtn = lock_gate("Journal Formatter") # signed-in users only
|
| 2932 |
+
GOTO_ACCOUNT.append(fm_lockbtn)
|
| 2933 |
+
with fm_open:
|
| 2934 |
+
if TOOLS_EMBED:
|
| 2935 |
+
gr.HTML(companion_tab_html(FORMAT_URL, "Journal Formatter.",
|
| 2936 |
+
"Upload your (humanized) manuscript and give a template, the journal's "
|
| 2937 |
+
"guidelines or just the journal name: the file is rearranged to that "
|
| 2938 |
+
"format (Word and LaTeX)."))
|
| 2939 |
+
else:
|
| 2940 |
+
FMT.build(TOOLS_UI)
|
| 2941 |
with gr.Tab("Journal Finder", id="finder"):
|
| 2942 |
+
_, fn_open, fn_lockbtn = lock_gate("Journal Finder")
|
| 2943 |
+
GOTO_ACCOUNT.append(fn_lockbtn)
|
| 2944 |
+
with fn_open:
|
| 2945 |
+
if TOOLS_EMBED:
|
| 2946 |
+
gr.HTML(companion_tab_html(FINDER_URL, "Journal Finder.",
|
| 2947 |
+
"Enter your paper's title to get matching journals with indexing "
|
| 2948 |
+
"(Scopus, PubMed, ABDC), quartile, review time and acceptance odds."))
|
| 2949 |
+
else:
|
| 2950 |
+
FND.build(TOOLS_UI)
|
| 2951 |
|
| 2952 |
# ============================ PRICING ============================
|
| 2953 |
with gr.Tab("Pricing", id="pricing") as pricing_tab:
|
plans.py
CHANGED
|
@@ -720,7 +720,7 @@ def pricing_html(currency=None, billing="Monthly"):
|
|
| 720 |
f'detector reports a day, 1 journal-formatting file a month. '
|
| 721 |
f'<b>Monthly and yearly plans</b> give the same credits every month; a yearly plan is paid once for '
|
| 722 |
f'twelve months. '
|
| 723 |
-
f'<b>Journal Finder:</b> free
|
| 724 |
f'{price_of("format", cur)} per file. <b>Institutions and agencies:</b> from '
|
| 725 |
f'{price_of("institution", cur)}/month for {PLANS["institution"]["docs_month"]} credits, several logins and '
|
| 726 |
f'a GST invoice, contact us.'
|
|
|
|
| 720 |
f'detector reports a day, 1 journal-formatting file a month. '
|
| 721 |
f'<b>Monthly and yearly plans</b> give the same credits every month; a yearly plan is paid once for '
|
| 722 |
f'twelve months. '
|
| 723 |
+
f'<b>Journal Finder:</b> free with a free account. <b>Journal formatting</b> on its own: '
|
| 724 |
f'{price_of("format", cur)} per file. <b>Institutions and agencies:</b> from '
|
| 725 |
f'{price_of("institution", cur)}/month for {PLANS["institution"]["docs_month"]} credits, several logins and '
|
| 726 |
f'a GST invoice, contact us.'
|
tests/test_auth_outputs.py
CHANGED
|
@@ -74,3 +74,11 @@ def test_a_recovery_key_is_verified_the_same_way():
|
|
| 74 |
assert app.do_check_reset(email, "AAAA-BBBB-CCCC-DDDD")[1]["visible"] is False
|
| 75 |
assert app.do_check_reset(email, key)[1]["visible"] is True
|
| 76 |
assert app.do_reset_key(email, key, "brandnewpass1", "brandnewpass1")[0]["email"] == email
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
assert app.do_check_reset(email, "AAAA-BBBB-CCCC-DDDD")[1]["visible"] is False
|
| 75 |
assert app.do_check_reset(email, key)[1]["visible"] is True
|
| 76 |
assert app.do_reset_key(email, key, "brandnewpass1", "brandnewpass1")[0]["email"] == email
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def test_journal_formatter_and_finder_need_a_signed_in_account():
|
| 80 |
+
import pytest
|
| 81 |
+
for tool in ("Journal Formatter", "Journal Finder"):
|
| 82 |
+
assert tool in app.COMPANION_LOCKS and f"Sign in to use the {tool}" in app._locked(tool)
|
| 83 |
+
with pytest.raises(app.gr.Error):
|
| 84 |
+
next(app._run_tool(lambda rep: ("x",), (), 1, 0, user=None, request=None, tool=tool))
|