Spaces:
Running
Running
| import os.path | |
| import re | |
| import gradio as gr | |
| from functools import partial | |
| from .main_page import sort_with_pyuca | |
| def split_intro_text(intro_text): | |
| lines = intro_text.strip().split("\n") | |
| if lines and lines[0].startswith("#"): | |
| title = lines[0] | |
| body = "\n".join(lines[1:]) | |
| return title, body | |
| return "", intro_text | |
| # Basic, permissive email format check (local@domain.tld). Used only to gate the | |
| # "Continue" button so users don't proceed with an obviously malformed address. | |
| _EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$") | |
| def _looks_like_email(value): | |
| return bool(_EMAIL_RE.match((value or "").strip())) | |
| def update_language_options(selected_country, metadata): | |
| with open(metadata["USA"]["English"]["Intro"], "r", encoding="utf-8") as f: | |
| INTRO_TEXT = f.read() # default | |
| # Retrieve the list of languages available for the selected country. | |
| if selected_country in metadata: | |
| languages = sort_with_pyuca(list(metadata[selected_country].keys())) | |
| if len(languages) == 0: | |
| gr.Warning("No languages available for the selected country.") | |
| t, b = split_intro_text(INTRO_TEXT) | |
| return gr.update(choices=[], interactive=False, value=None), gr.update(value=t), gr.update(value=b) | |
| # select the first language as default | |
| fn = metadata[selected_country][languages[0]]["Intro"] | |
| if os.path.exists(fn): | |
| with open(fn, "r", encoding="utf-8") as f: | |
| INTRO_TEXT = f.read() | |
| # Use gr.Dropdown.update to change the choices of the language dropdown. | |
| val = languages[0] if len(languages) == 1 else None | |
| t, b = split_intro_text(INTRO_TEXT) | |
| return gr.update(choices=languages, interactive=True, value=val, allow_custom_value=False), gr.update(value=t), gr.update(value=b) | |
| else: | |
| t, b = split_intro_text(INTRO_TEXT) | |
| return gr.update(choices=[], interactive=False, value=None, allow_custom_value=False), gr.update(value=t), gr.update(value=b) | |
| def enable_country(): | |
| return gr.update(interactive=True) | |
| def update_profile_button_state(email): | |
| email = (email or "").strip() | |
| valid = _looks_like_email(email) | |
| # Reveal the primary "Continue" button as soon as the user starts typing an | |
| # email, but only enable it once the address looks valid. HF login auto-fills | |
| # a valid email, so this enables Continue automatically in that path too. | |
| return gr.update(interactive=valid, visible=bool(email)) | |
| def prefill_country_language(saved_country, saved_language, current_country, current_language, metadata): | |
| """ | |
| Build updates for country/language dropdowns from persisted values. | |
| Country is set first so the existing country->language cascade remains valid. | |
| """ | |
| if current_country: | |
| return ( | |
| gr.skip(), | |
| gr.skip(), | |
| gr.skip(), | |
| gr.skip(), | |
| ) | |
| countries = sort_with_pyuca(list(metadata.keys())) | |
| if not saved_country or saved_country not in metadata: | |
| return ( | |
| gr.skip(), | |
| gr.skip(), | |
| gr.skip(), | |
| gr.skip(), | |
| ) | |
| # Compute language options directly to avoid relying on component instance attrs. | |
| valid_languages = sort_with_pyuca(list(metadata[saved_country].keys())) | |
| final_language = saved_language if saved_language in valid_languages else (valid_languages[0] if len(valid_languages) == 1 else None) | |
| fn = metadata[saved_country][valid_languages[0]]["Intro"] if valid_languages else metadata["USA"]["English"]["Intro"] | |
| intro_text = "" | |
| if os.path.exists(fn): | |
| with open(fn, "r", encoding="utf-8") as f: | |
| intro_text = f.read() | |
| if intro_text: | |
| t, b = split_intro_text(intro_text) | |
| return ( | |
| gr.update(choices=countries, value=saved_country, interactive=True), | |
| gr.update(choices=valid_languages, value=final_language, interactive=True), | |
| gr.update(value=t), | |
| gr.update(value=b), | |
| ) | |
| return ( | |
| gr.update(choices=countries, value=saved_country, interactive=True), | |
| gr.update(choices=valid_languages, value=final_language, interactive=True), | |
| gr.skip(), | |
| gr.skip(), | |
| ) | |
| def build_selection_page(metadata_dict): | |
| with gr.Column(visible=True, elem_classes=["compact-container"]) as selection_page: | |
| with open(metadata_dict["USA"]["English"]["Intro"], "r", encoding="utf-8") as f: | |
| INTRO_TEXT = f.read() | |
| title, body = split_intro_text(INTRO_TEXT) | |
| intro_title = gr.Markdown(title) | |
| # Locale choice dropdowns next to each other | |
| countries = sort_with_pyuca(list(metadata_dict.keys())) | |
| with gr.Row(): | |
| country_choice = gr.Dropdown( | |
| choices=countries, | |
| label="Country", | |
| allow_custom_value=False, | |
| value=None, | |
| interactive=True, | |
| ) | |
| language_choice = gr.Dropdown( | |
| choices=[], | |
| label="Language", | |
| allow_custom_value=False, | |
| interactive=False, # Initially disabled. | |
| ) | |
| intro_body = gr.Markdown(body) | |
| with gr.Column(visible=True) as signin_section: | |
| signin_title = gr.Markdown("## Please select your profile") | |
| login_btn = gr.LoginButton("Sign in with Hugging Face (optional)") # TODO: Multilingual | |
| user_name = gr.Markdown("", visible=False) | |
| username = gr.Markdown("", visible=False) | |
| email_inp = gr.Textbox( | |
| label="Email", | |
| type="email", | |
| placeholder="you@example.com", | |
| info="Add your email to save your work and review or edit it later.", | |
| ) | |
| # Primary call-to-action. Hidden until the user starts entering an | |
| # email and only enabled for a valid address (see | |
| # update_profile_button_state). HF login auto-fills the email. | |
| prof_btn = gr.Button("Continue", variant="primary", visible=False, interactive=False) | |
| # Secondary, de-emphasized escape hatch with an explicit consequence | |
| # so the trade-off of anonymous submissions is clear up front. | |
| anon_note = gr.Markdown( | |
| "<span style='opacity:0.7;font-size:0.85em;'>" | |
| "Prefer not to log in? You can continue anonymously, but you won't be able to review, edit, or delete your submissions later. " | |
| "Also, at the end of the data collection campaign, we will use account information to create a list of all contributors and provide rewards to the best ones. " | |
| "For details, see our website [https://team-wonders.github.io/](https://team-wonders.github.io/)." | |
| "</span>" | |
| ) | |
| anon_btn = gr.Button("Proceed as Anonymous", variant="secondary", size="sm") | |
| with gr.Column(visible=False) as selection_section: | |
| selection_title = gr.Markdown("## Please select your country", visible=False) | |
| proceed_btn = gr.Button("Annotate", variant="primary", visible=False) | |
| # When the country selection changes, update the language dropdown. | |
| country_choice.change( | |
| fn=partial(update_language_options, metadata=metadata_dict), | |
| inputs=country_choice, | |
| outputs=[language_choice, intro_title, intro_body] | |
| ) | |
| # Event listeners | |
| # username.change( | |
| # fn=enable_country, | |
| # outputs=[country_choice], | |
| # ) | |
| email_inp.change( | |
| fn=update_profile_button_state, | |
| inputs=[email_inp], | |
| outputs=[prof_btn], | |
| ) | |
| # with gr.Row(): | |
| # username = gr.Textbox(label="Email (optional)", type="email", elem_id="username_text") | |
| # password = gr.Textbox(label="Password (optional)", type="password", elem_id="password_text") | |
| # with gr.Row(): | |
| # login_btn = gr.Button("Login", elem_id="login_btn") | |
| # sign_up_btn = gr.Button("Sign up", elem_id="sign_up_btn") | |
| # reset_password_btn = gr.Button("Reset Password", elem_id="reset_password_btn") | |
| # logout_btn = gr.Button("Logout", elem_id="logout_btn",visible=False) | |
| # gr.Markdown("### Choose how you want to continue") | |
| # with gr.Row(): | |
| # login_btn = gr.LoginButton("Sign in with Hugging Face") # TODO: Multilingual | |
| # anon_btn = gr.Button("Proceed as Anonymous") | |
| # username = gr.Markdown("", visible=False) | |
| # login_status = gr.Markdown("") | |
| # with gr.Row(): | |
| # change_password_field = gr.Textbox( | |
| # label="Change Password", type="password", elem_id="change_password_field", visible=True | |
| # ) | |
| # change_password_field_confirm = gr.Textbox( | |
| # label="Confirm New Password", type="password", elem_id="change_password_field_confirm", visible=True | |
| # ) | |
| # with gr.Row(): | |
| # change_password_btn = gr.Button("Change Password", elem_id="change_password_btn", visible=True) | |
| # change_password_status = gr.Markdown("") | |
| return ( | |
| selection_page, country_choice, language_choice, proceed_btn, anon_btn, login_btn, prof_btn, | |
| username, user_name, email_inp, intro_title, intro_body, signin_title, selection_title, | |
| signin_section, selection_section, | |
| ) | |