restore flagging options and login page

This commit is contained in:
Ali Abid 2021-06-17 13:04:22 -07:00
parent 26ba1634ac
commit e7f970791b
10 changed files with 95 additions and 51 deletions

View File

@ -22,7 +22,8 @@ iface = gr.Interface(calculator,
[0, "subtract", 1.2],
],
title="test calculator",
description="heres a sample toy calculator. enjoy!"
description="heres a sample toy calculator. enjoy!",
flagging_options=["this", "or", "that"]
)
if __name__ == "__main__":

View File

@ -119,7 +119,7 @@ export class GradioInterface extends React.Component {
});
});
}
flag() {
flag(flag_option) {
if (!this.state.complete) {
return;
}
@ -134,6 +134,7 @@ export class GradioInterface extends React.Component {
window.setTimeout(() => {
this.setState({ "just_flagged": false });
}, 1000)
component_state["flag_option"] = flag_option;
this.props.fn(component_state, "flag");
}
interpret() {
@ -240,11 +241,17 @@ export class GradioInterface extends React.Component {
<button className="panel_button hidden">Screenshot</button>
: false}
{this.props.allow_flagging ?
<button className={classNames("panel_button", { "disabled": this.state.complete === false })}
onClick={this.flag}>
{this.state.just_flagged ? "Flagged" : "Flag"}
{/* <div className="dropcontent"></div> */}
</button>
(this.props.flagging_options === null ?
<button className={classNames("panel_button", "flag", { "disabled": this.state.complete === false })}
onClick={this.flag.bind(this, null)}>
{this.state.just_flagged ? "Flagged" : "Flag"}
</button> :
<button className={classNames("panel_button", "flag", { "disabled": this.state.complete === false })}>
{this.state.just_flagged ? "Flagged" : "Flag ▼"}
<div className="dropcontent">
{this.props.flagging_options.map(item => <div onClick={this.flag.bind(this, item)}>{item}</div>)}
</div>
</button>)
: false}
</div>
</div>

View File

@ -1,6 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import GradioInterface from './gradio';
import Login from './login';
let fn = async (data, action) => {
const output = await fetch(process.env.REACT_APP_BACKEND_URL + "api/" + action + "/", {
@ -20,17 +21,21 @@ async function get_config() {
return config;
} else {
return window.config;
}
}
}
get_config().then(config => {
ReactDOM.render(
<div class="gradio_page">
{config.title ? <h1 className="title">{config.title}</h1> : false}
{config.description ? <p className="description">{config.description}</p> : false}
<GradioInterface {...config} fn={fn} />
{config.article ? <p className="article prose" dangerouslySetInnerHTML={{"__html": config.article}} /> : false}
</div>,
document.getElementById('root')
);
})
if (config.auth_required) {
ReactDOM.render(<Login {...config} />, document.getElementById('root'))
} else {
ReactDOM.render(
<div class="gradio_page">
{config.title ? <h1 className="title">{config.title}</h1> : false}
{config.description ? <p className="description">{config.description}</p> : false}
<GradioInterface {...config} fn={fn} />
{config.article ? <p className="article prose" dangerouslySetInnerHTML={{ "__html": config.article }} /> : false}
</div>,
document.getElementById('root')
);
}
});

15
frontend/src/login.jsx Normal file
View File

@ -0,0 +1,15 @@
import('./themes/defaults.scss');
export default function Login(props) {
return <div class="login">
<form id="login" method="POST" action={process.env.REACT_APP_BACKEND_URL + "login"}>
<h2>login</h2>
{props.auth_message ? <div dangerouslySetInnerHTML={{"__html": props.auth_message}}></div> : false}
<label for="username">username</label>
<input type="text" name="username"></input>
<label for="password">password</label>
<input type="password" name="password"></input>
<input class="link" type="submit" className="submit"></input>
</form>
</div>
}

View File

@ -15,6 +15,25 @@
}
}
.login {
@apply container mt-8;
form {
@apply mx-auto p-4 bg-gray-50 shadow-md w-1/2;
}
h2 {
@apply text-2xl font-semibold my-2;
}
label {
@apply block uppercase mt-4;
}
input {
@apply p-2 block;
}
.submit {
@apply bg-yellow-500 hover:bg-yellow-400 transition px-4 py-2 rounded text-white font-semibold cursor-pointer mt-4;
}
}
.gradio_interface[theme="default"] {
.loading {
@apply absolute right-1;
@ -46,6 +65,23 @@
.panel_buttons {
@apply flex gap-4 my-4;
}
.flag {
@apply relative;
.dropcontent {
@apply hidden absolute top-8 left-0 bg-white border-gray-200 border-2 w-full;
div {
@apply p-2;
}
div:hover {
@apply bg-gray-100;
}
}
}
.flag:hover:not(.disabled) {
.dropcontent {
@apply block;
}
}
.screenshot_set {
@apply hidden flex hidden flex-grow;
}

View File

@ -39,12 +39,13 @@ gradio/frontend/static/css/main.380e3222.css
gradio/frontend/static/css/main.380e3222.css.map
gradio/frontend/static/css/main.4aea80f8.css
gradio/frontend/static/css/main.4aea80f8.css.map
gradio/frontend/static/css/main.4f157d97.css
gradio/frontend/static/css/main.4f157d97.css.map
gradio/frontend/static/css/main.99922310.css
gradio/frontend/static/css/main.99922310.css.map
gradio/frontend/static/css/main.acb02c85.css
gradio/frontend/static/css/main.acb02c85.css.map
gradio/frontend/static/media/logo_loading.e93acd82.jpg
gradio/templates/login.html
test/test_demos.py
test/test_inputs.py
test/test_interfaces.py

View File

@ -1,17 +1,17 @@
{
"files": {
"main.css": "/static/css/main.2b64a968.css",
"main.css": "/static/css/main.4f157d97.css",
"main.js": "/static/bundle.js",
"main.js.map": "/static/bundle.js.map",
"index.html": "/index.html",
"static/bundle.css.map": "/static/bundle.css.map",
"static/bundle.js.LICENSE.txt": "/static/bundle.js.LICENSE.txt",
"static/css/main.2b64a968.css.map": "/static/css/main.2b64a968.css.map",
"static/css/main.4f157d97.css.map": "/static/css/main.4f157d97.css.map",
"static/media/logo_loading.e93acd82.jpg": "/static/media/logo_loading.e93acd82.jpg"
},
"entrypoints": [
"static/bundle.css",
"static/css/main.2b64a968.css",
"static/css/main.4f157d97.css",
"static/bundle.js"
]
}

View File

@ -8,4 +8,4 @@
window.config = {{ config|tojson }};
} catch (e) {
window.config = {};
}</script><title>Gradio</title><link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet"><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.2b64a968.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>
}</script><title>Gradio</title><link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet"><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.4f157d97.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>

View File

@ -138,7 +138,8 @@ def static_resource(path):
@app.route('/login', methods=["GET", "POST"])
def login():
if request.method == "GET":
return render_template("login.html", current_user=current_user, auth_message=app.interface.auth_message)
config = get_config()
return render_template("index.html", config=config)
elif request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
@ -150,10 +151,11 @@ def login():
@app.route("/config/", methods=["GET"])
@login_check
def config():
return jsonify(app.interface.config)
def get_config():
if current_user.is_authenticated:
return jsonify(app.interface.config)
else:
return {"auth_required": True, "auth_message": app.interface.auth_message}
@app.route("/enable_sharing/<path:path>", methods=["GET"])
@login_check

View File

@ -1,23 +0,0 @@
<html>
<head>
<title>Gradio Login</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/gradio.css') }}">
<meta name="viewport" content="width=device-width">
</head>
<body id="lib">
<div class="container">
<form id="login" method="POST" action="/login">
<h2>login</h2>
{% if auth_message is not none %}
<p>{{ auth_message|safe }}</p>
{% endif %}
<label for="username">username</label>
<input type="text" name="username">
<label for="password">password</label>
<input type="password" name="password">
<input class="link" type="submit">
</form>
</div>
</body>
</html>