Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to customize html-static-task-example submit button #879

Merged
merged 8 commits into from
Aug 3, 2022
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.md
**/build/*
docs/web/static/python_api/*
wrap_crowd_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React from "react";
import ReactDOM from "react-dom";
import { Button } from "react-bootstrap";
import { useMephistoTask, postData } from "mephisto-task";
import { useMephistoGlobalConfig } from "./hooks";
const axios = require("axios");

/* global
Expand Down Expand Up @@ -110,6 +111,14 @@ function MainApp() {

function SubmitFrame({ children, onSubmit, currentTask }) {
const [submitting, setSubmitting] = React.useState(false);
const [
isSubmitButtonHidden,
setIsSubmitButtonHidden,
] = useMephistoGlobalConfig(
"HIDE_SUBMIT_BUTTON",
false,
(val) => typeof val === "boolean"
);

React.useEffect(() => {
// Reset submitting when switching from onboarding
Expand All @@ -133,13 +142,20 @@ function SubmitFrame({ children, onSubmit, currentTask }) {
{children}
<div>
<div style={{ display: "flex", justifyContent: "center" }}>
<Button type="submit" disabled={submitting} data-cy="submit-button">
<span
style={{ marginRight: 5 }}
className="glyphicon glyphicon-ok"
/>
{submitting ? "Submitting..." : "Submit"}
</Button>
{!isSubmitButtonHidden && (
<Button
id="html-task-submit-button"
type="submit"
disabled={submitting}
data-cy="submit-button"
>
<span
style={{ marginRight: 5 }}
className="glyphicon glyphicon-ok"
/>
{submitting ? "Submitting..." : "Submit"}
</Button>
)}
</div>
</div>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useState, useCallback, useEffect } from "react";

/**
* This hook is to be used with events that are supposed to update state when they are consumed.
* @param {string} configName
* @param {any} defaultValue
* @param {function} validatorFunction
* @returns [any any]
*/
export function useMephistoGlobalConfig(
Copy link
Contributor

@pringshia pringshia Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method looks great implementation-wise! Thanks for the jsdocs as well :)

configName,
defaultValue,
validatorFunction
) {
const [configState, setConfigState] = useState(defaultValue ?? false);

const handleEvent = useCallback(
(eventValue) => {
if (validatorFunction) {
if (validatorFunction(eventValue)) {
setConfigState(eventValue);
}
} else setConfigState(eventValue);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both conditional paths are calling setConfigState here...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm, i see one is for the outer branch

},
[setConfigState]
);

useEffect(() => {
window._MEPHISTO_CONFIG_.EVENT_EMITTER.on(configName, handleEvent);
}, [setConfigState]);

return [configState, setConfigState];
}
22 changes: 21 additions & 1 deletion mephisto/abstractions/providers/mock/wrap_crowd_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Returning None for the assignment_id means that the task is being
previewed by the given worker.
\------------------------------------------*/

// The following is the nanoevents npm library (https://github.com/ai/nanoevents/blob/main/index.js) manually processed as such:
// 1. transpiled to support more browser targets using the Babel transpiler (https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&corejs=false&spec=false&loose=false), and
// 2. minified using a JS minifier (https://www.toptal.com/developers/javascript-minifier)
var eventEmitter=function(){return{events:{},emit:function(f){for(var b=this.events[f]||[],c=arguments.length,e=new Array(c>1?c-1:0),a=1;a<c;a++)e[a-1]=arguments[a];for(var d=0,g=b.length;d<g;d++)b[d].apply(b,e)},on:function(b,c){var a,d=this;return(null===(a=this.events[b])|| void 0===a?void 0:a.push(c))||(this.events[b]=[c]),function(){var a;d.events[b]=null===(a=d.events[b])|| void 0===a?void 0:a.filter(function(a){return c!==a})}}}}

// MOCK IMPLEMENTATION
function getWorkerName() {
// Mock worker name is passed via url params
Expand Down Expand Up @@ -45,8 +50,23 @@ function handleSubmitToProvider(task_data) {
return true;
}

/* === UI error handling code ======= */
const events = eventEmitter();

window._MEPHISTO_CONFIG_ = window._MEPHISTO_CONFIG_ || {};
window._MEPHISTO_CONFIG_.EVENT_EMITTER = events;

window._MEPHISTO_CONFIG_.get = (property) => {
if (!(property in window._MEPHISTO_CONFIG_))
throw new Error(`${property} does not exist in window.MEPHISTO_CONFIG`);
else return window._MEPHISTO_CONFIG_[property];
};

window._MEPHISTO_CONFIG_.set = (property, value) => {
window._MEPHISTO_CONFIG_[property] = value;
events.emit(property, value);
};
Comment on lines +58 to +67
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getter and setter methods for the window.MEPHISTO_CONFIG object

Copy link
Contributor

@pringshia pringshia Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm really torn / undecided if throwing an Error here at runtime is desirable or not. The downside is having tasks crash when launched on mTurk, the upside is that we flag logical errors quickly and loudly - developers should be able to detect these crashes immediately usually after an initial launch of their task.

I think ultimately this might be fine... still undecided though


/* === UI error handling code ======= */
window._MEPHISTO_CONFIG_.AUTO_SUBMIT_ERRORS = false;
window._MEPHISTO_CONFIG_.ADD_ERROR_HANDLING = false;
window._MEPHISTO_CONFIG_.ERROR_REPORT_TO_EMAIL = null;
Expand Down
21 changes: 20 additions & 1 deletion mephisto/abstractions/providers/mturk/wrap_crowd_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Returning None for the assignment_id means that the task is being
previewed by the given worker.
\------------------------------------------*/

// The following is the nanoevents npm library (https://github.com/ai/nanoevents/blob/main/index.js) manually processed as such:
// 1. transpiled to support more browser targets using the Babel transpiler (https://babeljs.io/repl#?browsers=defaults&build=&builtIns=false&corejs=false&spec=false&loose=false), and
// 2. minified using a JS minifier (https://www.toptal.com/developers/javascript-minifier)
var eventEmitter=function(){return{events:{},emit:function(f){for(var b=this.events[f]||[],c=arguments.length,e=new Array(c>1?c-1:0),a=1;a<c;a++)e[a-1]=arguments[a];for(var d=0,g=b.length;d<g;d++)b[d].apply(b,e)},on:function(b,c){var a,d=this;return(null===(a=this.events[b])|| void 0===a?void 0:a.push(c))||(this.events[b]=[c]),function(){var a;d.events[b]=null===(a=d.events[b])|| void 0===a?void 0:a.filter(function(a){return c!==a})}}}}

function getWorkerName() {
// MTurk worker name is passed via url params
let urlParams = new URLSearchParams(window.location.search);
Expand Down Expand Up @@ -64,15 +69,29 @@ function handleSubmitToProvider(task_data) {
HTMLFormElement.prototype.submit.call(form);
}

/* === UI error handling code ======= */
window._MEPHISTO_CONFIG_ = window._MEPHISTO_CONFIG_ || {};
window._MEPHISTO_CONFIG_.EVENT_EMITTER = events;

window._MEPHISTO_CONFIG_.get = (property) => {
if (!(property in window._MEPHISTO_CONFIG_))
throw new Error(`${property} does not exist in window.MEPHISTO_CONFIG`);
else return window._MEPHISTO_CONFIG_[property];
};

window._MEPHISTO_CONFIG_.set = (property, value) => {
window._MEPHISTO_CONFIG_[property] = value;
events.emit(property, value);
};

/* === UI error handling code ======= */
window._MEPHISTO_CONFIG_.AUTO_SUBMIT_ERRORS = false;
window._MEPHISTO_CONFIG_.ADD_ERROR_HANDLING = false;
window._MEPHISTO_CONFIG_.ERROR_REPORT_TO_EMAIL = null;

let numErrorsCaught = 0;
let numErrorsReported = 0;
let userDisabledErrorPrompts = false;

// Adding event listener instead of using window.onerror prevents the error to be caught twice
window.addEventListener("error", function (event) {
if (event.error.hasBeenCaught === true) {
Expand Down