<commit_before>// Templates for discussion clerk script by [[User:The Earwig]]

// Development and bug reports: https://github.com/earwig/tfdclerk

// To install, add:
//     importScript("User:The Earwig/tfdclerk.js");  // [[User:The Earwig/tfdclerk.js]]
// to [[Special:MyPage/common.js]] or [[Special:MyPage/skin.js]]

/*
Copyright (C) 2015 Ben Kurtovic <ben.kurtovic@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

mw.loader.using(["mediawiki.api", "mediawiki.ui", "jquery.ui.core"], function() {
    if (mw.config.get("wgAction") != "view" ||
        mw.config.get("wgIsProbablyEditable") != true ||
        mw.config.get("wgRevisionId") != mw.config.get("wgCurRevisionId") ||
        mw.config.get("wgNamespaceNumber") != 4 || (
        mw.config.get("wgTitle") != "Templates for discussion" &&
        mw.config.get("wgTitle").indexOf("Templates for discussion/Log/2") != 0))
        return;

    TFDClerk = {
        api: new mw.Api(),
        sysop: $.inArray("sysop", mw.config.get("wgUserGroups")) >= 0,
        counter: 1
    };

    TFDClerk._get_today = function() {
        return new Date().toISOString().slice(0, 10);
    };

    TFDClerk._guard = function(head) {
        if (head.data("guard"))
            return false;
        head.data("guard", true);
        return true;
    };

    TFDClerk._unguard = function(head) {
        head.removeData("guard");
    };

    TFDClerk._get_section = function(head) {
        var url = head.find(".mw-editsection a").first().prop("href");
        var match = url.match(/section=(.*?)(\&|$)/);
        return match ? match[1] : null;
    };

    TFDClerk._error = function(box, msg, extra) {
        var elem = $("<span/>", {
            text: "Error: " + (extra ? msg + ": " : msg),
            style: "color: #A00;"
        });
        if (extra)
            elem.append($("<span/>", {
                text: extra,
                style: "font-family: monospace;"
            }));
        elem.insertAfter(box.find("h5"));
        $("#" + box.prop("id") + "-submit").prop("disabled", true);
    };

    TFDClerk._remove_option_box = function(box) {
        var head = box.prev("h4");
        box.remove();
        TFDClerk._unguard(head);
    };

    TFDClerk._add_option_box = function(head, verb, title, callback, options) {
        var box_id = "tfdclerk-" + verb + "-box-" + TFDClerk.counter++;
        var box = $("<div/>", {
            id: box_id,
            addClass: "tfdclerk-" + verb + "-box"
        })
            .css("border", "1px solid #AAA")
            .css("color", "#000")
            .css("background-color", "#F9F9F9")
            .css("margin", "0.5em 0")
            .css("padding", "1em")
            .append($("<h5/>", {
                text: title,
                style: "margin: 0; padding: 0 0 0.25em 0;"
            }));
        options(box, head, box_id + "-");
        box.append($("<button/>", {
                id: box_id + "-submit",
                text: verb.charAt(0).toUpperCase() + verb.slice(1),
                addClass: "mw-ui-button mw-ui-progressive",
                style: "margin-right: 0.5em;",
                click: function() {
                    callback(head, box);
                }
            }))
            .append($("<button/>", {
                id: box_id + "-cancel",
                text: "Cancel",
                addClass: "mw-ui-button",
                click: function() {
                    TFDClerk._remove_option_box(box);
                }
            }))
            .insertAfter(head);
    };

    TFDClerk._add_option_table = function(box, options) {
        var table = $("<table/>", {style: "border-spacing: 0;"});
        $.each(options, function(i, opt) {
            table.append($("<tr/>")
                .append(
                    $("<td/>", {
                        style: "padding-bottom: 0.75em; padding-right: 0.5em;"
                    }).append(opt[0]))
                .append(
                    $("<td/>", {
                        style: "padding-bottom: 0.75em;"
                    }).append(opt[1]))
            );
        });
        box.append(table);
    };

    TFDClerk._do_close = function(head, box) {
        // TODO
        TFDClerk._remove_option_box(box);
    };

    TFDClerk._do_relist = function(head, box) {
        // TODO
        TFDClerk._remove_option_box(box);
    };

    TFDClerk._is_merge = function(head) {
        return head.nextUntil("h4").filter("p").first().find("b")
            .text() == "Propose merging";
    };

    TFDClerk._build_close_results = function(head) {
        if (TFDClerk._is_merge(head))
            var choices = ["Merge", "Do not merge", "No consensus"];
        else
            var choices = ["Delete", "Keep", "Redirect", "No consensus"];

        var elems = $("<div/>");
        $("<label/>").append($("<input/>", {
                name: "result-speedy",
                type: "checkbox",
                value: "true"
            })).append($("<span/>", {
                text: "Speedy",
                style: "margin: 0 1.25em 0 0.25em;"
            })).appendTo(elems);
        $.each(choices, function(i, choice) {
            $("<label/>").append($("<input/>", {
                    name: "result",
                    type: "radio",
                    value: choice
                })).append($("<span/>", {
                    text: choice,
                    style: "margin: 0 1.25em 0 0.25em;"
                })).appendTo(elems);
        });
        $("<label/>").append($("<input/>", {
                name: "result",
                type: "radio",
                value: "Other"
            })).append($("<span/>", {
                text: "Other: ",
                style: "margin: 0 0.25em;"
            })).append($("<input/>", {
                name: "result-other",
                type: "text"
            })).appendTo(elems);
        return elems;
    };

    TFDClerk._add_close_actions = function(box, head, prefix) {  // prefix?
        var section = TFDClerk._get_section(head);
        if (section === null)
            return TFDClerk._error(box, "couldn't get section number");

        TFDClerk.api.get({
            action: "query",
            prop: "revisions",
            rvprop: "content",
            rvsection: section,
            revids: mw.config.get("wgRevisionId")
        }).done(function(data) {
            // TODO
            console.log(data);
        }).fail(function(err) {
            TFDClerk._error(box, "API query failure", err);
        });
    };

    TFDClerk.close = function(head) {
        if (!TFDClerk._guard(head))
            return;

        TFDClerk._add_option_box(
            head, "close", "Closing discussion", TFDClerk._do_close,
            function(box, head, prefix) {
                TFDClerk._add_option_table(box, [
                    [
                        $("<span/>", {text: "Result:"}),
                        TFDClerk._build_close_results(head)
                    ],
                    [
                        $("<label/>", {
                            for: prefix + "comments",
                            text: "Comments:"
                        }),
                        $("<textarea/>", {
                            id: prefix + "comments",
                            name: "comments",
                            rows: 2,
                            cols: 60,
                            placeholder: "Optional. Do not sign."
                        })
                    ],
                    [
                        $("<span/>", {text: "Actions:"}),
                        $("<div/>", {id: prefix + "actions"}).append(
                            $("<span/>", {
                                text: "Fetching...",
                                style: "font-style: italic; color: #777;"
                            })),
                    ]
                ]);
                TFDClerk._add_close_actions(box, head, prefix);
            });
    };

    TFDClerk.relist = function(head) {
        if (!TFDClerk._guard(head))
            return;

        TFDClerk._add_option_box(
            head, "relist", "Relisting discussion", TFDClerk._do_relist,
            function(box, head, prefix) {
                TFDClerk._add_option_table(box, [
                    [
                        $("<label/>", {
                            for: prefix + "date",
                            text: "New date:"
                        }),
                        $("<input/>", {
                            id: prefix + "date",
                            name: "date",
                            type: "date",
                            value: TFDClerk._get_today()
                        })
                    ],
                    [
                        $("<label/>", {
                            for: prefix + "comments",
                            text: "Comments:"
                        }),
                        $("<textarea/>", {
                            id: prefix + "comments",
                            name: "comments",
                            rows: 2,
                            cols: 60,
                            placeholder: "Optional. Do not sign."
                        })
                    ]
                ]);
            });
    };

    TFDClerk._build_hook = function(head, verb, callback) {
        return $("<span/>", {style: "margin-left: 1em;"})
            .append($("<span/>", {addClass: "mw-editsection-bracket", text: "["}))
            .append($("<a/>", {
                href: "#",
                text: verb,
                title: "tfdclerk: " + verb + " discussion",
                click: function() {
                    callback($(head));
                    return false;
                }
            }))
            .append($("<span/>", {addClass: "mw-editsection-bracket", text: "]"}));
    };

    TFDClerk.install = function() {
        $("h4").each(function(i, head) {
            if ($(head).next().hasClass("tfd-closed"))
                return;

            $("<span/>", {addClass: "tfdclerk-hooks"})
                .append(TFDClerk._build_hook(head, "close", TFDClerk.close))
                .append(TFDClerk._build_hook(head, "relist", TFDClerk.relist))
                .appendTo($(head).find(".mw-editsection"));
        });
    };

    $(TFDClerk.install);
});
<commit_msg>More on API queries for templates.<commit_after>// Templates for discussion clerk script by [[User:The Earwig]]

// Development and bug reports: https://github.com/earwig/tfdclerk

// To install, add:
//     importScript("User:The Earwig/tfdclerk.js");  // [[User:The Earwig/tfdclerk.js]]
// to [[Special:MyPage/common.js]] or [[Special:MyPage/skin.js]]

/*
Copyright (C) 2015 Ben Kurtovic <ben.kurtovic@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

var dependencies = [
    "mediawiki.api",
    "mediawiki.ui",
    "mediawiki.util",
    "jquery.ui.core"
];

var is_tfd_page = function() {
    return mw.config.get("wgAction") == "view" &&
           mw.config.get("wgIsProbablyEditable") == true &&
           mw.config.get("wgRevisionId") == mw.config.get("wgCurRevisionId") &&
           mw.config.get("wgNamespaceNumber") == 4 && (
           mw.config.get("wgTitle") == "Templates for discussion" ||
           mw.config.get("wgTitle").indexOf("Templates for discussion/Log/2") == 0);
}

if (is_tfd_page()) {
    mw.loader.using(dependencies, function() {

/* Main script starts here */

TFDClerk = {
    api: new mw.Api(),
    sysop: $.inArray("sysop", mw.config.get("wgUserGroups")) >= 0,
    // TODO: access time?
    _counter: 1,
    _wikitext_cache: {},
    _wikitext_cache_extra: {}
};

TFDClerk._get_today = function() {
    return new Date().toISOString().slice(0, 10);
};

TFDClerk._guard = function(head) {
    if (head.data("guard"))
        return false;
    head.data("guard", true);
    return true;
};

TFDClerk._unguard = function(head) {
    head.removeData("guard");
};

TFDClerk._get_section_number = function(head) {
    var url = head.find(".mw-editsection a").first().prop("href");
    var match = url.match(/section=(.*?)(\&|$)/);
    return match ? match[1] : null;
};

TFDClerk._error = function(box, msg, extra) {
    var elem = $("<span/>", {
        text: "Error: " + (extra ? msg + ": " : msg),
        style: "color: #A00;"
    });
    if (extra)
        elem.append($("<span/>", {
            text: extra,
            style: "font-family: monospace;"
        }));
    elem.insertAfter(box.find("h5"));
    box.find(".tfdclerk-submit").prop("disabled", true);
};

TFDClerk._with_section_content = function(head, box, callback) {
    var section = TFDClerk._get_section_number(head);
    if (section === null)
        return TFDClerk._error(box, "couldn't get section number");

    var cache = TFDClerk._wikitext_cache,
        extra_cache = TFDClerk._wikitext_cache_extra;
    if (section in cache) {
        if (cache[section] === null) {
            if (section in extra_cache)
                extra_cache[section].push(callback);
            else
                extra_cache[section] = [callback];
        } else
            callback(cache[section]);
        return;
    }
    cache[section] = null;

    TFDClerk.api.get({
        action: "query",
        prop: "revisions",
        rvprop: "content",
        rvsection: section,
        revids: mw.config.get("wgRevisionId")
    }).done(function(data) {
        var pageid = mw.config.get("wgArticleId");
        var content = data.query.pages[pageid].revisions[0]["*"];
        cache[section] = content;
        callback(content);
        if (section in extra_cache) {
            for (var i in extra_cache[section])
                extra_cache[section][i](content);
        }
    }).fail(function(err) {
        TFDClerk._error(box, "API query failure", err);
    }).always(function() {
        if (section in extra_cache)
            delete extra_cache[section];
    });
};

TFDClerk._remove_option_box = function(box) {
    var head = box.prev("h4");
    box.remove();
    TFDClerk._unguard(head);
};

TFDClerk._add_option_box = function(head, verb, title, callback, options) {
    var box_id = "tfdclerk-" + verb + "-box-" + TFDClerk._counter++;
    var box = $("<div/>", {
        id: box_id,
        addClass: "tfdclerk-" + verb + "-box"
    })
        .css("border", "1px solid #AAA")
        .css("color", "#000")
        .css("background-color", "#F9F9F9")
        .css("margin", "0.5em 0")
        .css("padding", "1em")
        .append($("<h5/>", {
            text: title,
            style: "margin: 0; padding: 0 0 0.25em 0;"
        }));
    options(box, head, box_id + "-");
    box.append($("<button/>", {
            id: box_id + "-submit",
            text: verb.charAt(0).toUpperCase() + verb.slice(1),
            addClass: "tfdclerk-submit mw-ui-button mw-ui-progressive",
            style: "margin-right: 0.5em;",
            click: function() {
                callback(head, box);
            }
        }))
        .append($("<button/>", {
            id: box_id + "-cancel",
            text: "Cancel",
            addClass: "mw-ui-button",
            click: function() {
                TFDClerk._remove_option_box(box);
            }
        }))
        .insertAfter(head);
};

TFDClerk._add_option_table = function(box, options) {
    var table = $("<table/>", {style: "border-spacing: 0;"});
    $.each(options, function(i, opt) {
        table.append($("<tr/>")
            .append(
                $("<td/>", {
                    style: "padding-bottom: 0.75em; padding-right: 0.5em;"
                }).append(opt[0]))
            .append(
                $("<td/>", {
                    style: "padding-bottom: 0.75em;"
                }).append(opt[1]))
        );
    });
    box.append(table);
};

TFDClerk._do_close = function(head, box) {
    // TODO
    TFDClerk._remove_option_box(box);
};

TFDClerk._do_relist = function(head, box) {
    // TODO
    TFDClerk._remove_option_box(box);
};

TFDClerk._is_merge = function(head) {
    return head.nextUntil("h4").filter("p").first().find("b")
        .text() == "Propose merging";
};

TFDClerk._build_close_results = function(head) {
    if (TFDClerk._is_merge(head))
        var choices = ["Merge", "Do not merge", "No consensus"];
    else
        var choices = ["Delete", "Keep", "Redirect", "No consensus"];

    var elems = $("<div/>");
    $("<label/>").append($("<input/>", {
            name: "result-speedy",
            type: "checkbox",
            value: "true"
        })).append($("<span/>", {
            text: "Speedy",
            style: "margin: 0 1.25em 0 0.25em;"
        })).appendTo(elems);
    $.each(choices, function(i, choice) {
        $("<label/>").append($("<input/>", {
                name: "result",
                type: "radio",
                value: choice
            })).append($("<span/>", {
                text: choice,
                style: "margin: 0 1.25em 0 0.25em;"
            })).appendTo(elems);
    });
    $("<label/>").append($("<input/>", {
            name: "result",
            type: "radio",
            value: "Other"
        })).append($("<span/>", {
            text: "Other: ",
            style: "margin: 0 0.25em;"
        })).append($("<input/>", {
            name: "result-other",
            type: "text"
        })).appendTo(elems);
    return elems;
};

TFDClerk._add_close_actions = function(box, head) {
    TFDClerk._with_section_content(head, box, function(content) {
        var regex = /\{\{tfd links\|(.*?)(\||\}\})/gi,
            match = regex.exec(content);
        if (match === null)
            return TFDClerk._error(box, "no templates found in section");

        var actions = box.find(".tfdclerk-actions"),
            list = $("<ul/>", {style: "margin: 0 0 0 1em;"});
        do {
            var page = "Template:" + match[1];
            $("<li/>").append($("<a/>", {
                href: mw.util.getUrl(page),
                title: page,
                text: page
            })).appendTo(list);
        } while ((match = regex.exec(content)) !== null);
        actions.empty();
        actions.append(list);
    });
};

TFDClerk.close = function(head) {
    if (!TFDClerk._guard(head))
        return;

    TFDClerk._add_option_box(
        head, "close", "Closing discussion", TFDClerk._do_close,
        function(box, head, prefix) {
            TFDClerk._add_option_table(box, [
                [
                    $("<span/>", {text: "Result:"}),
                    TFDClerk._build_close_results(head)
                ],
                [
                    $("<label/>", {
                        for: prefix + "comments",
                        text: "Comments:"
                    }),
                    $("<textarea/>", {
                        id: prefix + "comments",
                        name: "comments",
                        rows: 2,
                        cols: 60,
                        placeholder: "Optional. Do not sign."
                    })
                ],
                [
                    $("<span/>", {text: "Actions:"}),
                    $("<div/>", {addClass: "tfdclerk-actions"}).append(
                        $("<span/>", {
                            text: "Fetching...",
                            style: "font-style: italic; color: #777;"
                        })),
                ]
            ]);
            TFDClerk._add_close_actions(box, head);
        });
};

TFDClerk.relist = function(head) {
    if (!TFDClerk._guard(head))
        return;

    TFDClerk._add_option_box(
        head, "relist", "Relisting discussion", TFDClerk._do_relist,
        function(box, head, prefix) {
            TFDClerk._add_option_table(box, [
                [
                    $("<label/>", {
                        for: prefix + "date",
                        text: "New date:"
                    }),
                    $("<input/>", {
                        id: prefix + "date",
                        name: "date",
                        type: "date",
                        value: TFDClerk._get_today()
                    })
                ],
                [
                    $("<label/>", {
                        for: prefix + "comments",
                        text: "Comments:"
                    }),
                    $("<textarea/>", {
                        id: prefix + "comments",
                        name: "comments",
                        rows: 2,
                        cols: 60,
                        placeholder: "Optional. Do not sign."
                    })
                ]
            ]);
        });
};

TFDClerk._build_hook = function(head, verb, callback) {
    return $("<span/>", {style: "margin-left: 1em;"})
        .append($("<span/>", {addClass: "mw-editsection-bracket", text: "["}))
        .append($("<a/>", {
            href: "#",
            text: verb,
            title: "tfdclerk: " + verb + " discussion",
            click: function() {
                callback($(head));
                return false;
            }
        }))
        .append($("<span/>", {addClass: "mw-editsection-bracket", text: "]"}));
};

TFDClerk.install = function() {
    $("h4").each(function(i, head) {
        if ($(head).next().hasClass("tfd-closed"))
            return;

        $("<span/>", {addClass: "tfdclerk-hooks"})
            .append(TFDClerk._build_hook(head, "close", TFDClerk.close))
            .append(TFDClerk._build_hook(head, "relist", TFDClerk.relist))
            .appendTo($(head).find(".mw-editsection"));
    });
};

$(TFDClerk.install);

/* Main script ends here */

    });
}
<|endoftext|>


<commit_before><commit_msg>Added example redis transporter<commit_after>'use strict';

module.exports = function(redisInstance) {
    var redis = redisInstance;

    function callbackHandler(callback) {
        return function(error, data) {
            callback(error, data);
        };
    }

    return {
        get: function(url, callback) {
            redis.get(url, callbackHandler(callback));
        },

        set: function(url, response, callback) {
            redis.set(url, response, callbackHandler(callback));
        },

        purge: function(url, callback) {
            redis.del(url, callbackHandler(callback));
        }
    };
};<|endoftext|>


<commit_before>import clone from 'lodash/cloneDeep'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withLoginRequired } from 'use-auth0-hooks'

import { routeTo } from '../../actions/ui'
import { addOrUpdateUser, isNewUser } from '../../actions/user'
import AppNav from '../app/app-nav'

import AccountSetupFinishPane from './account-setup-finish-pane'
import ExistingAccountDisplay from './existing-account-display'
import FavoriteLocationsPane from './favorite-locations-pane'
import NewAccountWizard from './new-account-wizard'
import NotificationPrefsPane from './notification-prefs-pane'
import PhoneVerificationPane from './phone-verification-pane'
import TermsOfUsePane from './terms-of-use-pane'
import VerifyEmailScreen from './verify-email-screen'
import withLoggedInUserSupport from './with-logged-in-user-support'

/**
 * This screen handles creating/updating OTP user account settings.
 */
class UserAccountScreen extends Component {
  constructor (props) {
    super(props)

    const { loggedInUser } = props
    this.state = {
      userData: clone(loggedInUser)
    }
  }

  _updateUserState = newUserData => {
    const { userData } = this.state
    this.setState({
      userData: {
        ...userData,
        ...newUserData
      }
    })
  }

  _updateUserPrefs = async () => {
    // TODO: Change state of Save button while the update action takes place.

    const { addOrUpdateUser } = this.props
    const { userData } = this.state
    await addOrUpdateUser(userData)

    // TODO: Handle UI feedback (currently an alert() dialog inside addOrUpdateUser).
  }

  _handleExit = () => {
    // On exit, route to default search route.
    this.props.routeTo('/')
  }

  _handleExitAndSave = async () => {
    await this._updateUserPrefs()
    this._handleExit()
  }

  /**
   * Hook userData, onUserDataChange on some panes upon rendering.
   * This returns a new render function for the passed component
   * that allows passing other props to it later if needed.
   */
  _hookUserData = Pane => props => {
    const { userData } = this.state
    return (
      <Pane
        onUserDataChange={this._updateUserState}
        userData={userData}
        {...props}
      />
    )
  }

  // Make an index of pane components, so we don't render all panes at once on every render.
  // Hook some panes the userData and onUserDataChange props.
  _panes = {
    terms: this._hookUserData(TermsOfUsePane),
    notifications: this._hookUserData(NotificationPrefsPane),
    verifyPhone: PhoneVerificationPane,
    locations: this._hookUserData(FavoriteLocationsPane),
    finish: AccountSetupFinishPane
  }

  // TODO: Update title bar during componentDidMount.

  render () {
    const { auth, loggedInUser } = this.props
    const { userData } = this.state

    let formContents
    if (isNewUser(loggedInUser)) {
      if (!auth.user.email_verified) {
        // Check and prompt for email verification first to avoid extra user wait.
        formContents = <VerifyEmailScreen />
      } else {
        // New users are shown "wizard" (step-by-step) mode
        // (includes when a "new" user clicks 'My Account' from the account menu in the nav bar).
        formContents = (
          <NewAccountWizard
            onComplete={this._handleExitAndSave}
            panes={this._panes}
            userData={userData}
          />
        )
      }
    } else {
      formContents = (
        // Existing users are shown all panes together.
        <ExistingAccountDisplay
          onCancel={this._handleExit}
          onComplete={this._handleExitAndSave}
          panes={this._panes}
        />
      )
    }

    return (

        {/* TODO: Do mobile view. */}
        <AppNav />
        <form className='container'>
          {formContents}
        </form>

    )
  }
}

// connect to the redux store

const mapStateToProps = (state, ownProps) => {
  return {
    accessToken: state.user.accessToken,
    loggedInUser: state.user.loggedInUser
  }
}

const mapDispatchToProps = {
  addOrUpdateUser,
  routeTo
}

export default withLoggedInUserSupport(
  withLoginRequired(connect(mapStateToProps, mapDispatchToProps)(UserAccountScreen)),
  true
)
<commit_msg>refactor: Remove unused imports.<commit_after>import clone from 'lodash/cloneDeep'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withLoginRequired } from 'use-auth0-hooks'

import { routeTo } from '../../actions/ui'
import { addOrUpdateUser, isNewUser } from '../../actions/user'
import AppNav from '../app/app-nav'

import AccountSetupFinishPane from './account-setup-finish-pane'
import ExistingAccountDisplay from './existing-account-display'
import FavoriteLocationsPane from './favorite-locations-pane'
import NewAccountWizard from './new-account-wizard'
import NotificationPrefsPane from './notification-prefs-pane'
import PhoneVerificationPane from './phone-verification-pane'
import TermsOfUsePane from './terms-of-use-pane'
import VerifyEmailScreen from './verify-email-screen'
import withLoggedInUserSupport from './with-logged-in-user-support'

/**
 * This screen handles creating/updating OTP user account settings.
 */
class UserAccountScreen extends Component {
  constructor (props) {
    super(props)

    this.state = {
      userData: clone(props.loggedInUser)
    }
  }

  _updateUserState = newUserData => {
    const { userData } = this.state
    this.setState({
      userData: {
        ...userData,
        ...newUserData
      }
    })
  }

  _updateUserPrefs = async () => {
    // TODO: Change state of Save button while the update action takes place.

    const { addOrUpdateUser } = this.props
    const { userData } = this.state
    await addOrUpdateUser(userData)

    // TODO: Handle UI feedback (currently an alert() dialog inside addOrUpdateUser).
  }

  _handleExit = () => {
    // On exit, route to default search route.
    this.props.routeTo('/')
  }

  _handleExitAndSave = async () => {
    await this._updateUserPrefs()
    this._handleExit()
  }

  /**
   * Hook userData, onUserDataChange on some panes upon rendering.
   * This returns a new render function for the passed component
   * that allows passing other props to it later if needed.
   */
  _hookUserData = Pane => props => {
    const { userData } = this.state
    return (
      <Pane
        onUserDataChange={this._updateUserState}
        userData={userData}
        {...props}
      />
    )
  }

  // Make an index of pane components, so we don't render all panes at once on every render.
  // Hook some panes the userData and onUserDataChange props.
  _panes = {
    terms: this._hookUserData(TermsOfUsePane),
    notifications: this._hookUserData(NotificationPrefsPane),
    verifyPhone: PhoneVerificationPane,
    locations: this._hookUserData(FavoriteLocationsPane),
    finish: AccountSetupFinishPane
  }

  // TODO: Update title bar during componentDidMount.

  render () {
    const { auth, loggedInUser } = this.props
    const { userData } = this.state

    let formContents
    if (isNewUser(loggedInUser)) {
      if (!auth.user.email_verified) {
        // Check and prompt for email verification first to avoid extra user wait.
        formContents = <VerifyEmailScreen />
      } else {
        // New users are shown "wizard" (step-by-step) mode
        // (includes when a "new" user clicks 'My Account' from the account menu in the nav bar).
        formContents = (
          <NewAccountWizard
            onComplete={this._handleExitAndSave}
            panes={this._panes}
            userData={userData}
          />
        )
      }
    } else {
      formContents = (
        // Existing users are shown all panes together.
        <ExistingAccountDisplay
          onCancel={this._handleExit}
          onComplete={this._handleExitAndSave}
          panes={this._panes}
        />
      )
    }

    return (

        {/* TODO: Do mobile view. */}
        <AppNav />
        <form className='container'>
          {formContents}
        </form>

    )
  }
}

// connect to the redux store

const mapStateToProps = (state, ownProps) => {
  return {
    loggedInUser: state.user.loggedInUser
  }
}

const mapDispatchToProps = {
  addOrUpdateUser,
  routeTo
}

export default withLoggedInUserSupport(
  withLoginRequired(connect(mapStateToProps, mapDispatchToProps)(UserAccountScreen)),
  true
)
<|endoftext|>


<commit_before>(function(){

angular.module('crowdy')
 .controller("tagTaskController", ['$http', '$sce', '$httpParamSerializerJQLike', '$log', '$modal',
        '$scope', '$rootScope', '$routeParams', function($http, $sce, $httpParamSerializerJQLike,
        $log, $modal, $scope, $rootScope, $routeParams) {

    var BACKEND_SERVER = "."; // e.g. http://localhost:3000
    // Set Item template
    $scope.include = "/templates/tagging/"+ $routeParams.condition +"-index.html";
    $scope.forms = {};
    $scope.time = {};

    // Instructions
    $scope.instructions = {
        title: "Assign word labels ('tags') to describe images",
    };
    $scope.time = {
        limit: null,
        left: null,
        estimate: null
    };

    // Params
    $scope.condition = $routeParams.condition;
    if ($scope.condition === 'fast'){
        var phases = ['instructions', 'tasks', 'feedback'];
        $scope.phase = phases.shift();
    }

    $scope.pressEnter = function($event){
        if($event.keyCode !== 13) {
            return;
        } else {
            $log.info("Enter pressed. Pushing next task, if valid.");
            // commit any pending view values (in case Enter was pressed before the input debounce time)
            $scope.forms.turkForm.$commitViewValue();
            // Add next task
            $scope.pushStagedTask();
        }
    };

    $scope.preview = ($routeParams.assignmentId === 'ASSIGNMENT_ID_NOT_AVAILABLE' );
    $scope.assignmentId = $routeParams.assignmentId;

    $rootScope.debug = $routeParams.debug;
    if(!$rootScope.debug && !$routeParams.turkSubmitTo && !$scope.preview){
        $log.error("No turkSubmitTo, but not in debug or preview!.");
        $scope.openModal({
            message: "Something wrong with Turk URL. Don't continue this task because payment might not go through!"
        });
        return;
    } else if ($rootScope.debug) {
        $scope.formSubmitTo = null;
    } else {
        $scope.formSubmitTo = $sce.trustAsResourceUrl($routeParams.turkSubmitTo + "/mturk/externalSubmit");
    }

    $scope.type = "tagging";
    $scope.taskset = {};
    $scope.taskset.tasks = []; // Initialize empty, set when it's available

    //Modal
    $scope.openModal = function (opts) {
      $modal.open({
        animation: true,
        templateUrl: 'templates/modal.html',
        controller: 'ModalInstanceCtrl',
        backdrop: 'static',
        size: 'lg',
        resolve: {
          opts: function () {
          return opts;
          }
        }
      });
    };

    $scope.toggleAnimation = function () {
      $scope.animationsEnabled = !$scope.animationsEnabled;
    };

    var postResultsToAmazon = function(results, errors){
        if ($rootScope.debug){
            $log.warn("Not POSTing to Amazon when debugging.");
            return;
        }
        $scope.hiddenErrors = errors;
        // Add an action to the main form.
        // It couldn't be there before because of interference with our submit method.
        // MTurk requires a post from the client, though.
        angular.element("#turkHiddenForm").submit();
        return;
    };

    // Go to next phase in fast condition
    $scope.nextPhase = function() {
        if (phases.length === 0) {
            $log.error("Something went wrong: finished all phases and tried to keep going.");
            return;
        }
        $log.info("Switching phase from "+$scope.phase+" to " + phases[0]);
        $scope.phase = phases.shift();
        // When switching to the last (feedback) phase
        if ($scope.phase === 'feedback') {
            // block submission temporarily to prevent accidental submission
            $scope.submitBlocked = true;
            setTimeout(function(){$scope.submitBlocked=false; $scope.$apply();}, 1100);

            // If invalid, first try popping the last contribution
            if ($scope.forms.turkForm.$invalid){
                $scope.taskset.tasks.pop();
                $scope.$apply();
                if($scope.forms.turkForm.$invalid) {
                     // Forcing form to valid because there's no going back now and workers
                     // should always be paid
                     _.each($scope.forms.itemForms, function(form){
                         form.contrib.$setValidity('required', true);
                         form.contrib.$setValidity('pattern', true);
                     });
                }
            } else {
                updateBonusCounts();
            }
        }
    };

    // Add task to end of tasks. Meant for Fast condition
    $scope.pushStagedTask = function(){
        // Validate condition
        if ($scope.condition !== 'fast') {
            $log.error("pushing staged task is meant for fast condition.");
        }

        // Check form
        if (!$scope.forms.turkForm.$valid){
            // Showing checking without submit window
            $scope.forms.turkForm.check = true;
            return;
        }

        // If no more tasks left, then we push to the next phase
        if ($scope.stagingTasks.length === 0){
            $log.warn("No more tasks left!");
            $scope.nextPhase();
            return;
        }

        updateBonusCounts();
        // Turn off error/warning and push next item
        $scope.forms.turkForm.check = false;
        var task = $scope.stagingTasks.shift();
        $scope.taskset.tasks.push(task);
    };

    var timeSince = function(startTime){ return Math.floor((new Date() - startTime)/1000);};
    $scope.startTimer = function() {
        var start = new Date();
        var interval = setInterval(function(){
            $scope.time.left = $scope.time.limit - timeSince(start);
            // Doublecheck that phase didn't change elsewhere
            if ($scope.phase === 'feedback') {
                clearInterval(interval);
                return;
            }
            $scope.$apply();
            if ($scope.time.left <= 0){
                clearInterval(interval);
                $scope.nextPhase();
                $log.debug($scope);
            }
          }, 1000);
    };

    // Construct JSON callback
    var params = {
      callback: "JSON_CALLBACK",
      user: $scope.preview ? "PREVIEWUSER" : $routeParams.workerId,
      taskset_id:$scope.preview ? "TEST" : $routeParams.assignmentId,
      hit_id: $routeParams.hit_id,
      assignment_id: $routeParams.assignmentId,
      lock: !($scope.preview)
    };

    var endpoint;
    if ($routeParams.debugHIT) {
        endpoint = 'data/debug-image-hit.json';
       } else {
        endpoint = BACKEND_SERVER + "/hit";
       }

    // Count completed items
    $scope.completedItems = function(){
        var completed = ($scope.taskset.tasks || []).length -
            ($scope.forms.turkForm.$error.pattern || []).length -
            ($scope.forms.turkForm.$error.required || []).length;
        return completed;
    }

    var updateBonusCounts = function() {
        // Count Bonus for Fast task
        // Sum first N bonuses, where N is the number of successfully completed items.
        var completed = $scope.completedItems();
        if (!completed && !$scope.bonusStructure.items) return 0;
        var blist = $scope.bonusStructure.items;
        if (completed < blist.length) {
            blist = _.slice(blist, 0, completed);
            $scope.nextItemBonus = blist[completed]; //Zero indexed, but + 1
        } else {
            $scope.nextItemBonus = _.last(blist);
        }
        total = _.reduce(blist, function(x,y) { return x + y });
        // If more tasks completed than there's info for, repeat
        // last value
        if (completed > blist.length) {
            total += (completed - blist.length) * _.last(blist)
        }
        $scope.taskset.bonus = total;
    };

    // LOAD TASK
    $http.jsonp(endpoint, {params:params})
     .success(function(data){
        if (data.status && data.status===500){
            $rootScope.error = true;
            $scope.openModal({
                show: { ok: false},
                title: "Error",
                message: data.message
              });
            return;
        }

        if (data.taskset.tasks.length === 0) {
          $rootScope.error = "No tasks";
          $scope.openModal({
            show: { ok: false},
            title: "Out of tasks :(",
            message: "Sorry, we ran out of tasks that are available at the moment.<br/>We're really sorry about that, we know it sucks."
          });
        }

        // Set taskset for Crowdy
        $scope.taskset = data.taskset;
        // Add other info
        $scope.taskset.payment = data.payment.base;
        $scope.bonusStructure = data.payment.bonus;
        $scope.taskset.bonus = 0;
        $scope.nextItemBonus = 0;

        if ($scope.condition === 'fast') {
            // Moves items to a staging object if in
            // Fast condition. They'll be re-added as the
            // user completes more tasks.
            $scope.stagingTasks = data.taskset.tasks;
            $scope.taskset.tasks = [$scope.stagingTasks.shift()];

            if (!data.timer) {
                $log.error("No timer info provided for fast conditions.");
                $scope.openModal({
                    show:{ok:false},
                    title:"We made an error!",
                    message:"Something broke. It was our fault, sorry!"
                });
                return;
            }
            if (data.itemTimeEstimate) {
                $log.warn("Ignoring time.estimate for fast condition, using timer.");
            }
            $scope.time.limit = $rootScope.debug ? 15 : data.timer;
            $scope.time.left = $scope.time.limit;
            $scope.time.estimate = $scope.time.limit;
        } else if ($scope.condition === 'basic') {
            if (data.timer) {
                $log.warn("Ignoring timer for basic condition.");
                if (!data.itemTimeEstimate) {
                    $scope.time.estimate = 60 * 3.5;
                } else {
                    $scope.time.estimate = Math.round(10 * data.itemTimeEstimate * $scope.taskset.tasks.length)/10;
                }
            }
            //do something
        } else {
            $log.error("This condition is not supported.");
        }

    }).error(function(err){
        $rootScope.error = true;
        var msg, title;
        if ('message' in err){
            title = "Error";
            msg = err.message;
        } else {
            title = "Unknown error.";
            msg = "Sorry, an unknown error occurred. We don't know what happened";
        }
        $scope.openModal({
            show: {ok:false},
            title: title,
            message: msg
        });
    });

    // SAVE TASK
    $scope.submitForm = function() {
        // Don't submit if fast interface, unless the task phase is done
        if ($scope.condition === 'fast' && $scope.phase !== 'feedback'){
            // Not ready to submit yet.
            return;
        }

        if ($scope.forms.turkForm.$valid) {
          // Submit form toServer
          $http.post(BACKEND_SERVER+"/save/hit", $scope.taskset)
            .success(function(res){
                postResultsToAmazon(res, null);
            })
            .error(function(err){
                // Still send results to amazon in case of error
                $scope.taskset.err = err;
                postResultsToAmazon($scope.taskset, err);
            });
          // Submit form back to Amazon
        } else {
          // Reload masonry, in case any errors pop up
          $rootScope.$broadcast("masonry.reload");
        }
    };

  }]); //END CONTROLLER
// END ANONYMOUS FUNCTION
})();
<commit_msg>Linting style fixes<commit_after>(function(){

angular.module('crowdy')
 .controller("tagTaskController", ['$http', '$sce', '$httpParamSerializerJQLike', '$log', '$modal',
        '$scope', '$rootScope', '$routeParams', function($http, $sce, $httpParamSerializerJQLike,
        $log, $modal, $scope, $rootScope, $routeParams) {

    var BACKEND_SERVER = "."; // e.g. http://localhost:3000
    // Set Item template
    $scope.include = "/templates/tagging/"+ $routeParams.condition +"-index.html";
    $scope.forms = {};
    $scope.time = {};

    // Instructions
    $scope.instructions = {
        title: "Assign word labels ('tags') to describe images",
    };
    $scope.time = {
        limit: null,
        left: null,
        estimate: null
    };

    // Params
    $scope.condition = $routeParams.condition;
    if ($scope.condition === 'fast'){
        var phases = ['instructions', 'tasks', 'feedback'];
        $scope.phase = phases.shift();
    }

    $scope.pressEnter = function($event){
        if($event.keyCode !== 13) {
            return;
        } else {
            $log.info("Enter pressed. Pushing next task, if valid.");
            // commit any pending view values (in case Enter was pressed before the input debounce time)
            $scope.forms.turkForm.$commitViewValue();
            // Add next task
            $scope.pushStagedTask();
        }
    };

    $scope.preview = ($routeParams.assignmentId === 'ASSIGNMENT_ID_NOT_AVAILABLE' );
    $scope.assignmentId = $routeParams.assignmentId;

    $rootScope.debug = $routeParams.debug;
    if(!$rootScope.debug && !$routeParams.turkSubmitTo && !$scope.preview){
        $log.error("No turkSubmitTo, but not in debug or preview!.");
        $scope.openModal({
            message: "Something wrong with Turk URL. Don't continue this task because payment might not go through!"
        });
        return;
    } else if ($rootScope.debug) {
        $scope.formSubmitTo = null;
    } else {
        $scope.formSubmitTo = $sce.trustAsResourceUrl($routeParams.turkSubmitTo + "/mturk/externalSubmit");
    }

    $scope.type = "tagging";
    $scope.taskset = {};
    $scope.taskset.tasks = []; // Initialize empty, set when it's available

    //Modal
    $scope.openModal = function (opts) {
      $modal.open({
        animation: true,
        templateUrl: 'templates/modal.html',
        controller: 'ModalInstanceCtrl',
        backdrop: 'static',
        size: 'lg',
        resolve: {
          opts: function () {
          return opts;
          }
        }
      });
    };

    $scope.toggleAnimation = function () {
      $scope.animationsEnabled = !$scope.animationsEnabled;
    };

    var postResultsToAmazon = function(results, errors){
        if ($rootScope.debug){
            $log.warn("Not POSTing to Amazon when debugging.");
            return;
        }
        $scope.hiddenErrors = errors;
        // Add an action to the main form.
        // It couldn't be there before because of interference with our submit method.
        // MTurk requires a post from the client, though.
        angular.element("#turkHiddenForm").submit();
        return;
    };

    // Go to next phase in fast condition
    $scope.nextPhase = function() {
        if (phases.length === 0) {
            $log.error("Something went wrong: finished all phases and tried to keep going.");
            return;
        }
        $log.info("Switching phase from "+$scope.phase+" to " + phases[0]);
        $scope.phase = phases.shift();
        // When switching to the last (feedback) phase
        if ($scope.phase === 'feedback') {
            // block submission temporarily to prevent accidental submission
            $scope.submitBlocked = true;
            setTimeout(function(){$scope.submitBlocked=false; $scope.$apply();}, 1100);

            // If invalid, first try popping the last contribution
            if ($scope.forms.turkForm.$invalid){
                $scope.taskset.tasks.pop();
                $scope.$apply();
                if($scope.forms.turkForm.$invalid) {
                     // Forcing form to valid because there's no going back now and workers
                     // should always be paid
                     _.each($scope.forms.itemForms, function(form){
                         form.contrib.$setValidity('required', true);
                         form.contrib.$setValidity('pattern', true);
                     });
                }
            } else {
                updateBonusCounts();
            }
        }
    };

    // Add task to end of tasks. Meant for Fast condition
    $scope.pushStagedTask = function(){
        // Validate condition
        if ($scope.condition !== 'fast') {
            $log.error("pushing staged task is meant for fast condition.");
        }

        // Check form
        if (!$scope.forms.turkForm.$valid){
            // Showing checking without submit window
            $scope.forms.turkForm.check = true;
            return;
        }

        // If no more tasks left, then we push to the next phase
        if ($scope.stagingTasks.length === 0){
            $log.warn("No more tasks left!");
            $scope.nextPhase();
            return;
        }

        updateBonusCounts();
        // Turn off error/warning and push next item
        $scope.forms.turkForm.check = false;
        var task = $scope.stagingTasks.shift();
        $scope.taskset.tasks.push(task);
    };

    var timeSince = function(startTime){ return Math.floor((new Date() - startTime)/1000);};
    $scope.startTimer = function() {
        var start = new Date();
        var interval = setInterval(function(){
            $scope.time.left = $scope.time.limit - timeSince(start);
            // Doublecheck that phase didn't change elsewhere
            if ($scope.phase === 'feedback') {
                clearInterval(interval);
                return;
            }
            $scope.$apply();
            if ($scope.time.left <= 0){
                clearInterval(interval);
                $scope.nextPhase();
                $log.debug($scope);
            }
          }, 1000);
    };

    // Construct JSON callback
    var params = {
      callback: "JSON_CALLBACK",
      user: $scope.preview ? "PREVIEWUSER" : $routeParams.workerId,
      taskset_id:$scope.preview ? "TEST" : $routeParams.assignmentId,
      hit_id: $routeParams.hit_id,
      assignment_id: $routeParams.assignmentId,
      lock: !($scope.preview)
    };

    var endpoint;
    if ($routeParams.debugHIT) {
        endpoint = 'data/debug-image-hit.json';
       } else {
        endpoint = BACKEND_SERVER + "/hit";
       }

    // Count completed items
    $scope.completedItems = function(){
        var completed = ($scope.taskset.tasks || []).length -
            ($scope.forms.turkForm.$error.pattern || []).length -
            ($scope.forms.turkForm.$error.required || []).length;
        return completed;
    };

    var updateBonusCounts = function() {
        // Count Bonus for Fast task
        // Sum first N bonuses, where N is the number of successfully completed items.
        var completed = $scope.completedItems();
        if (!completed && !$scope.bonusStructure.items) { return 0; }
        var blist = $scope.bonusStructure.items;
        if (completed < blist.length) {
            blist = _.slice(blist, 0, completed);
            $scope.nextItemBonus = blist[completed]; //Zero indexed, but + 1
        } else {
            $scope.nextItemBonus = _.last(blist);
        }
        var total = _.reduce(blist, function(x,y) { return x + y; });
        // If more tasks completed than there's info for, repeat
        // last value
        if (completed > blist.length) {
            total += (completed - blist.length) * _.last(blist);
        }
        $scope.taskset.bonus = total;
    };

    // LOAD TASK
    $http.jsonp(endpoint, {params:params})
     .success(function(data){
        if (data.status && data.status===500){
            $rootScope.error = true;
            $scope.openModal({
                show: { ok: false},
                title: "Error",
                message: data.message
              });
            return;
        }

        if (data.taskset.tasks.length === 0) {
          $rootScope.error = "No tasks";
          $scope.openModal({
            show: { ok: false},
            title: "Out of tasks :(",
            message: "Sorry, we ran out of tasks that are available at the moment.<br/>We're really sorry about that, we know it sucks."
          });
        }

        // Set taskset for Crowdy
        $scope.taskset = data.taskset;
        // Add other info
        $scope.taskset.payment = data.payment.base;
        $scope.bonusStructure = data.payment.bonus;
        $scope.taskset.bonus = 0;
        $scope.nextItemBonus = 0;

        if ($scope.condition === 'fast') {
            // Moves items to a staging object if in
            // Fast condition. They'll be re-added as the
            // user completes more tasks.
            $scope.stagingTasks = data.taskset.tasks;
            $scope.taskset.tasks = [$scope.stagingTasks.shift()];

            if (!data.timer) {
                $log.error("No timer info provided for fast conditions.");
                $scope.openModal({
                    show:{ok:false},
                    title:"We made an error!",
                    message:"Something broke. It was our fault, sorry!"
                });
                return;
            }
            if (data.itemTimeEstimate) {
                $log.warn("Ignoring time.estimate for fast condition, using timer.");
            }
            $scope.time.limit = $rootScope.debug ? 15 : data.timer;
            $scope.time.left = $scope.time.limit;
            $scope.time.estimate = $scope.time.limit;
        } else if ($scope.condition === 'basic') {
            if (data.timer) {
                $log.warn("Ignoring timer for basic condition.");
                if (!data.itemTimeEstimate) {
                    $scope.time.estimate = 60 * 3.5;
                } else {
                    $scope.time.estimate = Math.round(10 * data.itemTimeEstimate * $scope.taskset.tasks.length)/10;
                }
            }
            //do something
        } else {
            $log.error("This condition is not supported.");
        }

    }).error(function(err){
        $rootScope.error = true;
        var msg, title;
        if ('message' in err){
            title = "Error";
            msg = err.message;
        } else {
            title = "Unknown error.";
            msg = "Sorry, an unknown error occurred. We don't know what happened";
        }
        $scope.openModal({
            show: {ok:false},
            title: title,
            message: msg
        });
    });

    // SAVE TASK
    $scope.submitForm = function() {
        // Don't submit if fast interface, unless the task phase is done
        if ($scope.condition === 'fast' && $scope.phase !== 'feedback'){
            // Not ready to submit yet.
            return;
        }

        if ($scope.forms.turkForm.$valid) {
          // Submit form toServer
          $http.post(BACKEND_SERVER+"/save/hit", $scope.taskset)
            .success(function(res){
                postResultsToAmazon(res, null);
            })
            .error(function(err){
                // Still send results to amazon in case of error
                $scope.taskset.err = err;
                postResultsToAmazon($scope.taskset, err);
            });
          // Submit form back to Amazon
        } else {
          // Reload masonry, in case any errors pop up
          $rootScope.$broadcast("masonry.reload");
        }
    };

  }]); //END CONTROLLER
// END ANONYMOUS FUNCTION
})();
<|endoftext|>


<commit_before>// Get all the "··· More" menus
var menus = getMenusArray();

addQuoteButtons(menus);
addMutationListener();

/**
 ** FUNCTIONS
 **/

function addMutationListener() {
    $('#stream-items-id').arrive('li[data-item-type=tweet]', function() {
        addQuoteButtons($(this).find('li.more-tweet-actions .dropdown-menu > ul').toArray());
    });
}

function addQuoteButtons(menus) {
    for (var index in menus) {
        var newItem = $(document.createElement('li'));
        var innerButton = $(document.createElement('button'));
        var menu = $(menus[index]);
        var quoteButtonText = chrome.i18n.getMessage("quote");

        // Set up the button
        innerButton.attr('class', 'dropdown-link');
        innerButton.attr('role', 'menuitem');
        innerButton.attr('type', 'button');
        // Attach it the click listener
        innerButton.click(onClickQuoteButton);
        // Set the button's text
        innerButton.text(quoteButtonText);
        // Add the "Quote" button
        newItem.prepend(innerButton);
        // Add the item to the list
        menu.prepend(newItem);
    }
}

function getMenusArray() {
    return [].filter.call(
                document.querySelectorAll("li.more-tweet-actions .dropdown-menu > ul"),
                function(value, index, array) {
                    return true;
                },
                []);
}

function getTweetAuthor(element) {
    return $(element).closest('.tweet').find('.username').text();
}

function getTweetText(element) {
    return $(element).closest('.tweet').find('.tweet-text').text();
}

function onClickQuoteButton(event) {
    // Get the btn's parent tweet's author
    var author = getTweetAuthor(event.currentTarget);
    // Get the btn's parent tweet's text
    var text = getTweetText(event.currentTarget);
    // Set the focus on the text field first (so the tweet form will be expanded)
    $('#tweet-box-mini-home-profile').focus();
    // Set the tweet text as its value
    $('#tweet-box-mini-home-profile').first().text('RT ' + author + ': ' + text);
    // Set the scroll bar at the top of the page
    $(document).scrollTop(0);
    // Close the dropdown menu
    $(event.currentTarget).closest('.tweet').find('.dropdown-toggle').click();
}
<commit_msg>timeline> Added back & refactored 'addQuoteButton(menu)'<commit_after>addQuoteButtons(getMenusArray());
addMutationListener();

/**
 ** FUNCTIONS
 **/

function addMutationListener() {
    $('#stream-items-id').arrive('li[data-item-type=tweet]', function() {
        addQuoteButton($(this).find('li.more-tweet-actions .dropdown-menu > ul'));
    });
}

function addQuoteButton(menu) {
    var newItem = $(document.createElement('li'));
    var innerButton = $(document.createElement('button'));
    var quoteButtonText = chrome.i18n.getMessage("quote");

    // Set up the button
    innerButton.attr('class', 'dropdown-link');
    innerButton.attr('role', 'menuitem');
    innerButton.attr('type', 'button');
    // Attach it the click listener
    innerButton.click(onClickQuoteButton);
    // Set the button's text
    innerButton.text(quoteButtonText);
    // Add the "Quote" button
    newItem.prepend(innerButton);
    // Add the item to the list
    menu.prepend(newItem);
}

function addQuoteButtons(menus) {
    for (var index in menus) {
        addQuoteButton($(menus[index]));
    }
}

function getMenusArray() {
    return [].filter.call(
                document.querySelectorAll("li.more-tweet-actions .dropdown-menu > ul"),
                function(value, index, array) {
                    return true;
                },
                []);
}

function getTweetAuthor(element) {
    return $(element).closest('.tweet').find('.username').text();
}

function getTweetText(element) {
    return $(element).closest('.tweet').find('.tweet-text').text();
}

function onClickQuoteButton(event) {
    // Get the btn's parent tweet's author
    var author = getTweetAuthor(event.currentTarget);
    // Get the btn's parent tweet's text
    var text = getTweetText(event.currentTarget);
    // Set the focus on the text field first (so the tweet form will be expanded)
    $('#tweet-box-mini-home-profile').focus();
    // Set the tweet text as its value
    $('#tweet-box-mini-home-profile').first().text('RT ' + author + ': ' + text);
    // Set the scroll bar at the top of the page
    $(document).scrollTop(0);
    // Close the dropdown menu
    $(event.currentTarget).closest('.tweet').find('.dropdown-toggle').click();
}
<|endoftext|>


<commit_before>
;(function () {
  if (global === this) {

    global.window = global;

    global.XMLHttpRequest = function XMLHttpRequest() {
      var xhr = Ti.Network.createHTTPClient();

      if (typeof xhr.getResponseHeaders !== 'undefined') {
        xhr.getAllResponseHeaders = getAllResponseHeaders;
      }

      function getAllResponseHeaders() {
        var headers = xhr.getResponseHeaders();
        return Object.keys(headers).map(function (header) {
          return header + ':' + headers[header];
        }).join('\n') + '\n';
      }

      return xhr;
    };
  }
})();

var request = require('superagent');

function getXHR() {
  return new XMLHttpRequest();
}

request.Request.prototype.end = function (fn) {
  var self = this;
  var xhr = this.xhr = getXHR();
  var query = this._query.join('&');
  var timeout = this._timeout;
  var redirects = this._redirects;
  var data = this._data;

  // store callback
  this._callback = fn || noop;

  // state change
  xhr.onreadystatechange = function(){
    if (4 != xhr.readyState) return;
    if (0 == xhr.status) {
      if (self.aborted) return self.timeoutError();
      return;
    }
    if (self._finished) return;
    self._finished = true;
    self.emit('end');
  };

  xhr.onload = function () {
    if (self._finished) return;
    self._finished = true;
    self.emit('end');
  };

  xhr.onerror = function (error) {
    if (xhr.status > 0) {
      if (self._finished) return;
      self._finished = true;
      self.emit('end');
    }
    else {
      self.genericError(error);
    }
  };

  // timeout
  if (timeout) {
    xhr.timeout = timeout;
  }

  if (redirects != null) {
    this.redirects(redirects);
  }

  // querystring
  if (query) {
    query = request.serializeObject(query);
    this.url += ~this.url.indexOf('?')
      ? '&' + query
      : '?' + query;
  }

  // initiate request
  xhr.open(this.method, this.url, true);

  // CORS
  if (this._withCredentials) xhr.withCredentials = true;

  // body
  if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) {
    // serialize stuff
    var serialize = request.serialize[this.getHeader('Content-Type')];
    if (serialize) data = serialize(data);
  }

  // set header fields
  for (var field in this.header) {
    if (null == this.header[field]) continue;
    xhr.setRequestHeader(field, this.header[field]);
  }

  // send stuff
  xhr.send(data);
  return this;
};

request.Request.prototype.genericError = function(error) {
  var err = new Error(error.error || 'Unknown error');

  for (var k in error) {
    if (k === 'source') continue;
    err[k] = error[k];
  }

  if (/timed?\s*out/i.test(err + '')) {
    err.timeout = this._timeout;
  }

  this.callback(err);
};

request.Request.prototype.timeout = function (timeout) {
  this._timeout = timeout;
  if (this.xhr) throw new Error("Cannot set the timeout once the HTTPClient has been created");
  return this;
};

request.Request.prototype.redirects = function (redirects) {
  this._redirects = redirects;
  if (redirects > 0 || redirects === true) {
    if (this.xhr) this.xhr.autoRedirect = true;
  }
  else if (redirects <= 0 || redirects === false) {
    if (this.xhr) this.xhr.autoRedirect = false;
  }
  return this;
};

// Not necessary in Titanium SDK 3.4, HTTPClient#getResponseHeader is (as the
// standard states) case insensitive.
// See https://jira.appcelerator.org/browse/TIMOB-17585 for reference,
// and https://github.com/appcelerator/titanium_mobile/pull/6053

var originalSetHeaderProperties = request.Response.prototype.setHeaderProperties;
request.Response.prototype.setHeaderProperties = function (header) {
  this.header['content-type'] =
    this.xhr.getResponseHeader('content-type') ||
    this.xhr.getResponseHeader('Content-Type');
  return originalSetHeaderProperties.call(this, header);
};

function isHost(obj) {
  var str = {}.toString.call(obj);

  switch (str) {
    case '[object File]':
    case '[object Blob]':
    case '[object FormData]':
      return true;
    default:
      return false;
  }
}

function noop() {}

module.exports = request;
<commit_msg>Compatibility with superagent 0.19<commit_after>
;(function () {
  if (global === this) {

    global.window = global;

    global.XMLHttpRequest = function XMLHttpRequest() {
      var xhr = Ti.Network.createHTTPClient();

      if (typeof xhr.getResponseHeaders !== 'undefined') {
        xhr.getAllResponseHeaders = getAllResponseHeaders;
      }

      function getAllResponseHeaders() {
        var headers = xhr.getResponseHeaders();
        return Object.keys(headers).map(function (header) {
          return header + ':' + headers[header];
        }).join('\n') + '\n';
      }

      return xhr;
    };
  }
})();

var request = require('superagent');

function getXHR() {
  return new XMLHttpRequest();
}

request.Request.prototype.end = function (fn) {
  var self = this;
  var xhr = this.xhr = getXHR();
  var query = this._query.join('&');
  var timeout = this._timeout;
  var redirects = this._redirects;
  var data = this._data;

  // store callback
  this._callback = fn || noop;

  // state change
  xhr.onreadystatechange = function(){
    if (4 != xhr.readyState) return;
    if (0 == xhr.status) {
      if (self.aborted) return self.timeoutError();
      return;
    }
    if (self._finished) return;
    self._finished = true;
    self.emit('end');
  };

  xhr.onload = function () {
    if (self._finished) return;
    self._finished = true;
    self.emit('end');
  };

  xhr.onerror = function (error) {
    if (xhr.status > 0) {
      if (self._finished) return;
      self._finished = true;
      self.emit('end');
    }
    else {
      self.genericError(error);
    }
  };

  // timeout
  if (timeout) {
    xhr.timeout = timeout;
  }

  if (redirects != null) {
    this.redirects(redirects);
  }

  // querystring
  if (query) {
    query = request.serializeObject(query);
    this.url += ~this.url.indexOf('?')
      ? '&' + query
      : '?' + query;
  }

  // initiate request
  xhr.open(this.method, this.url, true);

  // CORS
  if (this._withCredentials) xhr.withCredentials = true;

  // body
  if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) {
    // serialize stuff
    var serialize = request.serialize[this.getHeader('Content-Type')];
    if (serialize) data = serialize(data);
  }

  // set header fields
  for (var field in this.header) {
    if (null == this.header[field]) continue;
    xhr.setRequestHeader(field, this.header[field]);
  }

  // send stuff
  this.emit('request', this);
  xhr.send(data);
  return this;
};

request.Request.prototype.genericError = function(error) {
  var err = new Error(error.error || 'Unknown error');

  for (var k in error) {
    if (k === 'source') continue;
    err[k] = error[k];
  }

  if (/timed?\s*out/i.test(err + '')) {
    err.timeout = this._timeout;
  }

  this.callback(err);
};

request.Request.prototype.timeout = function (timeout) {
  this._timeout = timeout;
  if (this.xhr) throw new Error("Cannot set the timeout once the HTTPClient has been created");
  return this;
};

request.Request.prototype.redirects = function (redirects) {
  this._redirects = redirects;
  if (redirects > 0 || redirects === true) {
    if (this.xhr) this.xhr.autoRedirect = true;
  }
  else if (redirects <= 0 || redirects === false) {
    if (this.xhr) this.xhr.autoRedirect = false;
  }
  return this;
};

// Not necessary in Titanium SDK 3.4, HTTPClient#getResponseHeader is (as the
// standard states) case insensitive.
// See https://jira.appcelerator.org/browse/TIMOB-17585 for reference,
// and https://github.com/appcelerator/titanium_mobile/pull/6053

var originalSetHeaderProperties = request.Response.prototype.setHeaderProperties;
request.Response.prototype.setHeaderProperties = function (header) {
  this.header['content-type'] =
    this.xhr.getResponseHeader('content-type') ||
    this.xhr.getResponseHeader('Content-Type');
  return originalSetHeaderProperties.call(this, header);
};

function isHost(obj) {
  var str = {}.toString.call(obj);

  switch (str) {
    case '[object File]':
    case '[object Blob]':
    case '[object FormData]':
      return true;
    default:
      return false;
  }
}

function noop() {}

module.exports = request;
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
    res.render('index', { title: 'Index' });
});

module.exports = router;
<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>$(function() {
	console.log("me again");
  $(document).on("click", "a", function(){
    $(this).text("It works!");
	});
});

<commit_msg>experimenting<commit_after>$(function() {
	console.log("sweet");
  $(".entries").on("click", "a", function(){
    $(this).text("It works!");
	});
});

<|endoftext|>


<commit_before>var $ = require("jquery");
var _ = require("underscore");
var Backbone = require("backbone");
window.smark = require("smark");

var genericCollection = require("./genericCollection.js");
var genericAllView = require("./genericCollectionView.js");
var appRouter = require("./routes.js");

var app = app || {
	categories: {
		partialURL: "http://localhost/ual_futures/wp-json/futures_categories/"
		// partialURL: "http://ualfutures-backend.default.ualfutures.uk0.bigv.io/wp-json/futures_categories/"
	},
	features: {
		postType: "features",
		collectionConstructor: require("./features/collection.js"),
		allViewConstructor: require("./features/allView.js"),
		singleViewConstructor: require("./features/singleView.js"),
	},
	events: {
		postType: "events",
		collectionConstructor: require("./events/collection.js"),
		allViewConstructor: require("./events/allView.js"),
		singleViewConstructor: require("./events/singleView.js"),
	},
	opportunities: {
		postType: "opportunities",
		collectionConstructor: require("./opportunities/collection.js"),
		allViewConstructor: require("./opportunities/allView.js"),
		singleViewConstructor: require("./opportunities/singleView.js"),
	},
	directories: {
		postType: "directories",
		collectionConstructor: require("./directories/collection.js"),
		allViewConstructor: require("./directories/allView.js"),
		singleViewConstructor: require("./directories/singleView.js"),
	},
	slideshow: {
		// url: "http://localhost/ual_futures/wp-json/wp/v2/slideshow?per_page=1&page=1"
		url: "http://ualfutures-backend.default.ualfutures.uk0.bigv.io/wp-json/wp/v2/slideshow?per_page=1&page=1"
	},
	helpers: {}
};
app.features.collection = new app.features.collectionConstructor();
app.features.allView = new app.features.allViewConstructor();
app.features.singleView = new app.features.singleViewConstructor();

app.directories.collection = new app.directories.collectionConstructor(null, app);
app.directories.allView = new app.directories.allViewConstructor();
app.directories.singleView = new app.directories.singleViewConstructor();

app.events.collection = new app.events.collectionConstructor(null, app);
app.events.allView = new app.events.allViewConstructor();
app.events.singleView = new app.events.singleViewConstructor();

app.opportunities.collection = new app.opportunities.collectionConstructor(null, app);
app.opportunities.allView = new app.opportunities.allViewConstructor();
app.opportunities.singleView = new app.opportunities.singleViewConstructor();

app.init = function(){
	var deffereds = [];

	deffereds.push(app.features.collection.fetch());
	deffereds.push(app.events.collection.fetch());
	deffereds.push(app.opportunities.collection.fetch());
	deffereds.push(app.directories.collection.fetch());
	deffereds.push(
		$.getJSON(app.slideshow.url, function(data) {
			app.slideshow.data = data;
		})
	);

	$.when.apply($, deffereds)
		.then(app.start, app.errorFetchingData);
};

app.start = function(){
	// Put all models into the generic collection and prepare its view
	app.collection = new genericCollection();
	app.collection.add(app.features.collection.toJSON());
	app.collection.add(app.events.collection.toJSON());
	app.collection.add(app.opportunities.collection.toJSON());
	app.collection.add(app.directories.collection.toJSON());

	app.router = new appRouter();
	app.registerRoutes(app.router);

	Backbone.history.start();
};

app.renderSlideshow = function(){
	var slideshowTemplate = _.template($("#slideshow-template").html());

	$("#page-content .grid").before(slideshowTemplate(app.slideshow.data[0]));
	$("#page-content .main-lists .slideshow").slick({
		dots: true,
		autoplay: true,
		autoplaySpeed: 5000,
		prevArrow: '',
		nextArrow: '',
	});

	app.helpers.dynamicImageSize($("#page-content .slideshow .slide"));
};

app.renderGrid = function(collection, type, view, viewConstructor){
	var gridView = view;
	var $grid = $("#page-content .grid");

	app.startMasonry($grid, type);
	$grid.masonry("remove", $("#page-content .grid .grid-item"));

	$grid.removeClass("directories-grid");

	if(viewConstructor){
		gridView = new viewConstructor(collection);
		$grid.html(gridView.render());
	}else{
		$("#page-content .grid").html(gridView.render(collection));

		if(type == "directories"){
			$grid.addClass("directories-grid");
		}
	}

	$grid.append("");
	$grid.masonry("appended", $("#page-content .grid .grid-item")).masonry();

	app.helpers.dynamicImageSize($("#page-content .grid .grid-item .bg-image-container"));
};

app.renderPost = function(slug, type){
	var model = app[type].collection.findWhere({slug: slug});

	if(typeof model == "undefined" || app.helpers.redirectHomeFlag){
		app.router.navigate("");
	}

	if(type == "events" && typeof model.toJSON().ebData == "undefined"){
		$("#page-content .post-content").html("");
		$("#page-content .post-content").html(app[type].singleView.render(model));
	}else{
		$("#page-content .post-content").html(app[type].singleView.render(model));
	}
};

app.registerRoutes = function(router){
	router.route("", function(){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").addClass("hide");

		$("#page-header .main-header").addClass("hide");
		$("#page-header .main-header").addClass("transparent");
		$("#page-header .home-header").removeClass("hide");

		$("#page-content").addClass("home-page");
		$("#page-content .main-lists .page-description").addClass("hide");
		// $("#page-content .main-lists .page-description").text("Connecting UAL students, graduates and industry.");

		if(!($("#page-content .main-lists .slideshow").hasClass("slick-initialized"))){
			app.renderSlideshow();
		}

		var $grid = $("#page-content .grid");

		app.renderGrid(app.collection, "", null, genericAllView);

		app.bindEvents();

		$(window).scrollTop(0);
	});

	router.route("media(/:type)(/p:page)", function(type, page){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-description").text("Connecting students to knowledge, inspiration, resources, events & opportunities.");

		var $grid = $("#page-content .grid");

		$("#page-content .main-lists .secondary-header").remove();

		if(type === null){
			$("#page-content .main-lists .page-name").text("Media");
			app.renderGrid(app.collection, type, null, genericAllView);
		}else{
			$("#page-content .main-lists .page-name").text(app.helpers.makeTitleCase(type));
			app.renderGrid(app[type].collection, type, app[type].allView);

			$("#page-content .main-lists .page-description").addClass("hide");
			$grid.before(app[type].allView.renderHeader());
		}

		app.bindEvents();

		$(window).scrollTop(0);
	});

	router.route("media/:type/category=:category(/p:page)", function(type, category, page){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-name").text(app.helpers.makeTitleCase(type));
		$("#page-content .main-lists .page-description").text("Connecting students to knowledge, inspiration, resources, events & opportunities.");

		var $grid = $("#page-content .grid");

		var filtered = new app[type].collectionConstructor(app[type].collection.filter(function(model){
			var comparator = model.toJSON().category;
			comparator = app.helpers.makeCompressCase(comparator);

			return comparator == category.toLowerCase();
		}), app);

		app.renderGrid(filtered, type, app[type].allView);

		$("#page-content .main-lists .page-description").addClass("hide");
		$("#page-content .main-lists .secondary-header").remove();
		$grid.before(app[type].allView.renderHeader());
	});

	router.route("media/:type/post=:slug", function(type, slug){
		$("#page-content .main-lists").addClass("hide");
		$("#page-content .post-content").removeClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");

		app.renderPost(slug, type);

		$("#page-content .main-lists .secondary-header").remove();
		$("#page-content .main-content").before(app[type].allView.renderHeader());

		app.helpers.bindSidebarEvents();
		app.bindEvents();

		$(window).scrollTop(0);
	});

	// Tags -------------------------------------------------------------------------------------------
	router.route("media/tags=:tags", function(tags){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-name").text("Futures");

		var tagsArray = tags.split("+");

		var filtered = app.helpers.filterCollection(app.collection, genericCollection, function(modelObject){
			var intersect = false;
			_.each(tagsArray, function(el1, i){
				var chosenTag = decodeURI(el1).toLowerCase();

				_.each(modelObject.tags, function(el2, i){
					var givenTag = decodeURIComponent(el2).toLowerCase();

					if(chosenTag == givenTag){
						intersect = true;
					}
				});
			});

			return intersect;
		});

		app.renderGrid(filtered, "", null, genericAllView);

		$(window).scrollTop(0);
	});

	// Studio page ---------------------------------------------------------------------------------
	router.route("studio(/:page)", function(page){
		$("#page-content .main-lists").addClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .studio-page").removeClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");

		$("#page-content .studio-page .intro").removeClass("hide");
		$("#page-content .studio-page .register").addClass("hide");
		$("#page-content .studio-page .method").addClass("hide");

		if(page == "register"){
			$("#page-content .studio-page .intro").addClass("hide");
			$("#page-content .studio-page .register").removeClass("hide");

			$("#page-content .studio-page .register .registration-form .radio-buttons label").click(function(e) {
				$(this).addClass("selected").find("input").attr("checked", true);
				$(this).siblings("label").removeClass("selected").find("input").attr("checked", false);
			});
		}else if(page == "method"){
			$("#page-content .studio-page .intro").addClass("hide");
			$("#page-content .studio-page .method").removeClass("hide");

			// Draw the SVG and apply hover and click events on them
			$(window).scroll(function(e) {
				if($(this).scrollTop() > 50){
					var opacity = app.helpers.map($(this).scrollTop(), 50, 450, 1.0, 0.0);
					$("#page-content .studio-page .method .graphics").css("opacity", opacity);
				}
			});
		}
	});
};

app.startMasonry = function($selector, postType){
	if(postType == "directories"){
		$selector.masonry({
			columnWidth: ".grid-item",
			itemSelector: ".grid-item",
			gutter: 20
		});
	}else{
		$selector.masonry({
			columnWidth: ".grid-item.level-0",
			itemSelector: ".grid-item",
			gutter: 20
		});
	}
};

app.bindEvents = function(){
	this.helpers.bindNavEvents();
	this.helpers.bindCardEvents(app.router);
};

///////////////////////////////////////////////////////
//						Helpers                      //
///////////////////////////////////////////////////////

app.helpers = require("./helpers.js");

app.errorFetchingData = function(e){
	console.error(e.status + " " + e.statusText);
	var reloadCnt = window.sessionStorage.getItem( "reloadCounter") ? parseInt(window.sessionStorage.getItem( "reloadCounter")) + 1 : 1;
	window.sessionStorage.setItem( "reloadCounter", reloadCnt );
	if ( reloadCnt <= 3 ){
		location.reload(true);
	}
};

module.exports = app;<commit_msg>Bind events on pages missing it<commit_after>var $ = require("jquery");
var _ = require("underscore");
var Backbone = require("backbone");
window.smark = require("smark");

var genericCollection = require("./genericCollection.js");
var genericAllView = require("./genericCollectionView.js");
var appRouter = require("./routes.js");

var app = app || {
	categories: {
		// partialURL: "http://localhost/ual_futures/wp-json/futures_categories/"
		partialURL: "http://ualfutures-backend.default.ualfutures.uk0.bigv.io/wp-json/futures_categories/"
	},
	features: {
		postType: "features",
		collectionConstructor: require("./features/collection.js"),
		allViewConstructor: require("./features/allView.js"),
		singleViewConstructor: require("./features/singleView.js"),
	},
	events: {
		postType: "events",
		collectionConstructor: require("./events/collection.js"),
		allViewConstructor: require("./events/allView.js"),
		singleViewConstructor: require("./events/singleView.js"),
	},
	opportunities: {
		postType: "opportunities",
		collectionConstructor: require("./opportunities/collection.js"),
		allViewConstructor: require("./opportunities/allView.js"),
		singleViewConstructor: require("./opportunities/singleView.js"),
	},
	directories: {
		postType: "directories",
		collectionConstructor: require("./directories/collection.js"),
		allViewConstructor: require("./directories/allView.js"),
		singleViewConstructor: require("./directories/singleView.js"),
	},
	slideshow: {
		// url: "http://localhost/ual_futures/wp-json/wp/v2/slideshow?per_page=1&page=1"
		url: "http://ualfutures-backend.default.ualfutures.uk0.bigv.io/wp-json/wp/v2/slideshow?per_page=1&page=1"
	},
	helpers: {}
};
app.features.collection = new app.features.collectionConstructor();
app.features.allView = new app.features.allViewConstructor();
app.features.singleView = new app.features.singleViewConstructor();

app.directories.collection = new app.directories.collectionConstructor(null, app);
app.directories.allView = new app.directories.allViewConstructor();
app.directories.singleView = new app.directories.singleViewConstructor();

app.events.collection = new app.events.collectionConstructor(null, app);
app.events.allView = new app.events.allViewConstructor();
app.events.singleView = new app.events.singleViewConstructor();

app.opportunities.collection = new app.opportunities.collectionConstructor(null, app);
app.opportunities.allView = new app.opportunities.allViewConstructor();
app.opportunities.singleView = new app.opportunities.singleViewConstructor();

app.init = function(){
	var deffereds = [];

	deffereds.push(app.features.collection.fetch());
	deffereds.push(app.events.collection.fetch());
	deffereds.push(app.opportunities.collection.fetch());
	deffereds.push(app.directories.collection.fetch());
	deffereds.push(
		$.getJSON(app.slideshow.url, function(data) {
			app.slideshow.data = data;
		})
	);

	$.when.apply($, deffereds)
		.then(app.start, app.errorFetchingData);
};

app.start = function(){
	// Put all models into the generic collection and prepare its view
	app.collection = new genericCollection();
	app.collection.add(app.features.collection.toJSON());
	app.collection.add(app.events.collection.toJSON());
	app.collection.add(app.opportunities.collection.toJSON());
	app.collection.add(app.directories.collection.toJSON());

	app.router = new appRouter();
	app.registerRoutes(app.router);

	Backbone.history.start();
};

app.renderSlideshow = function(){
	var slideshowTemplate = _.template($("#slideshow-template").html());

	$("#page-content .grid").before(slideshowTemplate(app.slideshow.data[0]));
	$("#page-content .main-lists .slideshow").slick({
		dots: true,
		autoplay: true,
		autoplaySpeed: 5000,
		prevArrow: '',
		nextArrow: '',
	});

	app.helpers.dynamicImageSize($("#page-content .slideshow .slide"));
};

app.renderGrid = function(collection, type, view, viewConstructor){
	var gridView = view;
	var $grid = $("#page-content .grid");

	app.startMasonry($grid, type);
	$grid.masonry("remove", $("#page-content .grid .grid-item"));

	$grid.removeClass("directories-grid");

	if(viewConstructor){
		gridView = new viewConstructor(collection);
		$grid.html(gridView.render());
	}else{
		$("#page-content .grid").html(gridView.render(collection));

		if(type == "directories"){
			$grid.addClass("directories-grid");
		}
	}

	$grid.append("");
	$grid.masonry("appended", $("#page-content .grid .grid-item")).masonry();

	app.helpers.dynamicImageSize($("#page-content .grid .grid-item .bg-image-container"));
};

app.renderPost = function(slug, type){
	var model = app[type].collection.findWhere({slug: slug});

	if(typeof model == "undefined" || app.helpers.redirectHomeFlag){
		app.router.navigate("");
	}

	if(type == "events" && typeof model.toJSON().ebData == "undefined"){
		$("#page-content .post-content").html("");
		$("#page-content .post-content").html(app[type].singleView.render(model));
	}else{
		$("#page-content .post-content").html(app[type].singleView.render(model));
	}
};

app.registerRoutes = function(router){
	router.route("", function(){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").addClass("hide");

		$("#page-header .main-header").addClass("hide");
		$("#page-header .main-header").addClass("transparent");
		$("#page-header .home-header").removeClass("hide");

		$("#page-content").addClass("home-page");
		$("#page-content .main-lists .page-description").addClass("hide");
		// $("#page-content .main-lists .page-description").text("Connecting UAL students, graduates and industry.");

		if(!($("#page-content .main-lists .slideshow").hasClass("slick-initialized"))){
			app.renderSlideshow();
		}

		var $grid = $("#page-content .grid");

		app.renderGrid(app.collection, "", null, genericAllView);

		app.bindEvents();

		$(window).scrollTop(0);
	});

	router.route("media(/:type)(/p:page)", function(type, page){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-description").text("Connecting students to knowledge, inspiration, resources, events & opportunities.");

		var $grid = $("#page-content .grid");

		$("#page-content .main-lists .secondary-header").remove();

		if(type === null){
			$("#page-content .main-lists .page-name").text("Media");
			app.renderGrid(app.collection, type, null, genericAllView);
		}else{
			$("#page-content .main-lists .page-name").text(app.helpers.makeTitleCase(type));
			app.renderGrid(app[type].collection, type, app[type].allView);

			$("#page-content .main-lists .page-description").addClass("hide");
			$grid.before(app[type].allView.renderHeader());
		}

		app.bindEvents();

		$(window).scrollTop(0);
	});

	router.route("media/:type/category=:category(/p:page)", function(type, category, page){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-name").text(app.helpers.makeTitleCase(type));
		$("#page-content .main-lists .page-description").text("Connecting students to knowledge, inspiration, resources, events & opportunities.");

		var $grid = $("#page-content .grid");

		var filtered = new app[type].collectionConstructor(app[type].collection.filter(function(model){
			var comparator = model.toJSON().category;
			comparator = app.helpers.makeCompressCase(comparator);

			return comparator == category.toLowerCase();
		}), app);

		app.renderGrid(filtered, type, app[type].allView);

		$("#page-content .main-lists .page-description").addClass("hide");
		$("#page-content .main-lists .secondary-header").remove();
		$grid.before(app[type].allView.renderHeader());

		app.bindEvents();

		$(window).scrollTop(0);
	});

	router.route("media/:type/post=:slug", function(type, slug){
		$("#page-content .main-lists").addClass("hide");
		$("#page-content .post-content").removeClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");

		app.renderPost(slug, type);

		$("#page-content .main-lists .secondary-header").remove();
		$("#page-content .main-content").before(app[type].allView.renderHeader());

		app.helpers.bindSidebarEvents();
		app.bindEvents();

		$(window).scrollTop(0);
	});

	// Tags -------------------------------------------------------------------------------------------
	router.route("media/tags=:tags", function(tags){
		$("#page-content .main-lists").removeClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .main-lists .page-name").removeClass("hide");
		$("#page-content .studio-page").addClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");
		$("#page-content .main-lists .page-description").removeClass("hide");
		$("#page-header .nav-slide-in").css("display", "none");
		$("#page-content .main-lists .slideshow").remove();

		$("#page-content .main-lists .page-name").text("Futures");

		var tagsArray = tags.split("+");

		var filtered = app.helpers.filterCollection(app.collection, genericCollection, function(modelObject){
			var intersect = false;
			_.each(tagsArray, function(el1, i){
				var chosenTag = decodeURI(el1).toLowerCase();

				_.each(modelObject.tags, function(el2, i){
					var givenTag = decodeURIComponent(el2).toLowerCase();

					if(chosenTag == givenTag){
						intersect = true;
					}
				});
			});

			return intersect;
		});

		app.renderGrid(filtered, "", null, genericAllView);

		app.bindEvents();

		$(window).scrollTop(0);
	});

	// Studio page ---------------------------------------------------------------------------------
	router.route("studio(/:page)", function(page){
		$("#page-content .main-lists").addClass("hide");
		$("#page-content .post-content").addClass("hide");
		$("#page-content .studio-page").removeClass("hide");

		$("#page-header .main-header").removeClass("hide");
		$("#page-header .main-header").removeClass("transparent");
		$("#page-header .home-header").addClass("hide");

		$("#page-content").removeClass("home-page");

		$("#page-content .studio-page .intro").removeClass("hide");
		$("#page-content .studio-page .register").addClass("hide");
		$("#page-content .studio-page .method").addClass("hide");

		if(page == "register"){
			$("#page-content .studio-page .intro").addClass("hide");
			$("#page-content .studio-page .register").removeClass("hide");

			$("#page-content .studio-page .register .registration-form .radio-buttons label").click(function(e) {
				$(this).addClass("selected").find("input").attr("checked", true);
				$(this).siblings("label").removeClass("selected").find("input").attr("checked", false);
			});
		}else if(page == "method"){
			$("#page-content .studio-page .intro").addClass("hide");
			$("#page-content .studio-page .method").removeClass("hide");

			// Draw the SVG and apply hover and click events on them
			$(window).scroll(function(e) {
				if($(this).scrollTop() > 50){
					var opacity = app.helpers.map($(this).scrollTop(), 50, 450, 1.0, 0.0);
					$("#page-content .studio-page .method .graphics").css("opacity", opacity);
				}
			});
		}

		app.bindEvents();

		$(window).scrollTop(0);
	});
};

app.startMasonry = function($selector, postType){
	if(postType == "directories"){
		$selector.masonry({
			columnWidth: ".grid-item",
			itemSelector: ".grid-item",
			gutter: 20
		});
	}else{
		$selector.masonry({
			columnWidth: ".grid-item.level-0",
			itemSelector: ".grid-item",
			gutter: 20
		});
	}
};

app.bindEvents = function(){
	this.helpers.bindNavEvents();
	this.helpers.bindCardEvents(app.router);
};

///////////////////////////////////////////////////////
//						Helpers                      //
///////////////////////////////////////////////////////

app.helpers = require("./helpers.js");

app.errorFetchingData = function(e){
	console.error(e.status + " " + e.statusText);
	var reloadCnt = window.sessionStorage.getItem( "reloadCounter") ? parseInt(window.sessionStorage.getItem( "reloadCounter")) + 1 : 1;
	window.sessionStorage.setItem( "reloadCounter", reloadCnt );
	if ( reloadCnt <= 3 ){
		location.reload(true);
	}
};

module.exports = app;<|endoftext|>