<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule AppRegistry
 * @flow
 */
'use strict';

const BatchedBridge = require('BatchedBridge');
const BugReporting = require('BugReporting');
const ReactNative = require('ReactNative');

const infoLog = require('infoLog');
const invariant = require('fbjs/lib/invariant');
const renderApplication = require('renderApplication');

const { HeadlessJsTaskSupport } = require('NativeModules');

if (__DEV__) {
  // In order to use Cmd+P to record/dump perf data, we need to make sure
  // this module is available in the bundle
  require('RCTRenderingPerf');
}

type Task = (taskData: any) => Promise<void>;
type TaskProvider = () => Task;
type ComponentProvider = () => ReactClass<any>;
type AppConfig = {
  appKey: string,
  component?: ComponentProvider,
  run?: Function,
  section?: boolean,
};
type Runnable = {
  component?: ComponentProvider,
  run: Function,
};
type Runnables = {
  [appKey: string]: Runnable,
};

const runnables: Runnables = {};
let runCount = 1;
const sections: Runnables = {};
const tasks: Map<string, TaskProvider> = new Map();

/**
 * `AppRegistry` is the JS entry point to running all React Native apps.  App
 * root components should register themselves with
 * `AppRegistry.registerComponent`, then the native system can load the bundle
 * for the app and then actually run the app when it's ready by invoking
 * `AppRegistry.runApplication`.
 *
 * To "stop" an application when a view should be destroyed, call
 * `AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was
 * passed into `runApplication`. These should always be used as a pair.
 *
 * `AppRegistry` should be `require`d early in the `require` sequence to make
 * sure the JS execution environment is setup before other modules are
 * `require`d.
 */
const AppRegistry = {
  registerConfig(config: Array<AppConfig>): void {
    config.forEach((appConfig) => {
      if (appConfig.run) {
        AppRegistry.registerRunnable(appConfig.appKey, appConfig.run);
      } else {
        invariant(
          appConfig.component != null,
          'AppRegistry.registerConfig(...): Every config is expected to set ' +
          'either `run` or `component`, but `%s` has neither.',
          appConfig.appKey
        );
        AppRegistry.registerComponent(
          appConfig.appKey,
          appConfig.component,
          appConfig.section,
        );
      }
    });
  },

  registerComponent(
    appKey: string,
    component: ComponentProvider,
    section?: boolean,
  ): string {
    runnables[appKey] = {
      component,
      run: (appParameters) =>
        renderApplication(component(), appParameters.initialProps, appParameters.rootTag)
    };
    if (section) {
      sections[appKey] = runnables[appKey];
    }
    return appKey;
  },

  registerRunnable(appKey: string, run: Function): string {
    runnables[appKey] = {run};
    return appKey;
  },

  registerSection(appKey: string, component: ComponentProvider): void {
    AppRegistry.registerComponent(appKey, component, true);
  },

  getAppKeys(): Array<string> {
    return Object.keys(runnables);
  },

  getSectionKeys(): Array<string> {
    return Object.keys(sections);
  },

  getSections(): Runnables {
    return {
      ...sections
    };
  },

  getRunnable(appKey: string): ?Runnable {
    return runnables[appKey];
  },

  runApplication(appKey: string, appParameters: any): void {
    const msg =
      'Running application "' + appKey + '" with appParams: ' +
      JSON.stringify(appParameters) + '. ' +
      '__DEV__ === ' + String(__DEV__) +
      ', development-level warning are ' + (__DEV__ ? 'ON' : 'OFF') +
      ', performance optimizations are ' + (__DEV__ ? 'OFF' : 'ON');
    infoLog(msg);
    BugReporting.addSource('AppRegistry.runApplication' + runCount++, () => msg);
    invariant(
      runnables[appKey] && runnables[appKey].run,
      'Application ' + appKey + ' has not been registered. This ' +
      'is either due to a require() error during initialization ' +
      'or failure to call AppRegistry.registerComponent.'
    );
    runnables[appKey].run(appParameters);
  },

  unmountApplicationComponentAtRootTag(rootTag: number): void {
    ReactNative.unmountComponentAtNodeAndRemoveContainer(rootTag);
  },

  /**
   * Register a headless task. A headless task is a bit of code that runs without a UI.
   * @param taskKey the key associated with this task
   * @param task    a promise returning function that takes some data passed from the native side as
   *                the only argument; when the promise is resolved or rejected the native side is
   *                notified of this event and it may decide to destroy the JS context.
   */
  registerHeadlessTask(taskKey: string, task: TaskProvider): void {
    if (tasks.has(taskKey)) {
      console.warn(`registerHeadlessTask called multiple times for same key '${taskKey}'`);
    }
    tasks.set(taskKey, task);
  },

  /**
   * Only called from native code. Starts a headless task.
   *
   * @param taskId the native id for this task instance to keep track of its execution
   * @param taskKey the key for the task to start
   * @param data the data to pass to the task
   */
  startHeadlessTask(taskId: number, taskKey: string, data: any): void {
    const taskProvider = tasks.get(taskKey);
    if (!taskProvider) {
      throw new Error(`No task registered for key ${taskKey}`);
    }
    taskProvider()(data)
      .then(() => HeadlessJsTaskSupport.notifyTaskFinished(taskId))
      .catch(reason => {
        console.error(reason);
        HeadlessJsTaskSupport.notifyTaskFinished(taskId);
      });
  }

};

BatchedBridge.registerCallableModule(
  'AppRegistry',
  AppRegistry
);

module.exports = AppRegistry;
<commit_msg>expose AppRegistry.getRegistry() for app specific handling<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule AppRegistry
 * @flow
 */
'use strict';

const BatchedBridge = require('BatchedBridge');
const BugReporting = require('BugReporting');
const ReactNative = require('ReactNative');

const infoLog = require('infoLog');
const invariant = require('fbjs/lib/invariant');
const renderApplication = require('renderApplication');

const { HeadlessJsTaskSupport } = require('NativeModules');

if (__DEV__) {
  // In order to use Cmd+P to record/dump perf data, we need to make sure
  // this module is available in the bundle
  require('RCTRenderingPerf');
}

type Task = (taskData: any) => Promise<void>;
type TaskProvider = () => Task;
type ComponentProvider = () => ReactClass<any>;
type AppConfig = {
  appKey: string,
  component?: ComponentProvider,
  run?: Function,
  section?: boolean,
};
type Runnable = {
  component?: ComponentProvider,
  run: Function,
};
type Runnables = {
  [appKey: string]: Runnable,
};
type Registry = {
  sections: Array<string>,
  runnables: Runnables,
};

const runnables: Runnables = {};
let runCount = 1;
const sections: Runnables = {};
const tasks: Map<string, TaskProvider> = new Map();

/**
 * `AppRegistry` is the JS entry point to running all React Native apps.  App
 * root components should register themselves with
 * `AppRegistry.registerComponent`, then the native system can load the bundle
 * for the app and then actually run the app when it's ready by invoking
 * `AppRegistry.runApplication`.
 *
 * To "stop" an application when a view should be destroyed, call
 * `AppRegistry.unmountApplicationComponentAtRootTag` with the tag that was
 * passed into `runApplication`. These should always be used as a pair.
 *
 * `AppRegistry` should be `require`d early in the `require` sequence to make
 * sure the JS execution environment is setup before other modules are
 * `require`d.
 */
const AppRegistry = {
  registerConfig(config: Array<AppConfig>): void {
    config.forEach((appConfig) => {
      if (appConfig.run) {
        AppRegistry.registerRunnable(appConfig.appKey, appConfig.run);
      } else {
        invariant(
          appConfig.component != null,
          'AppRegistry.registerConfig(...): Every config is expected to set ' +
          'either `run` or `component`, but `%s` has neither.',
          appConfig.appKey
        );
        AppRegistry.registerComponent(
          appConfig.appKey,
          appConfig.component,
          appConfig.section,
        );
      }
    });
  },

  registerComponent(
    appKey: string,
    component: ComponentProvider,
    section?: boolean,
  ): string {
    runnables[appKey] = {
      component,
      run: (appParameters) =>
        renderApplication(component(), appParameters.initialProps, appParameters.rootTag)
    };
    if (section) {
      sections[appKey] = runnables[appKey];
    }
    return appKey;
  },

  registerRunnable(appKey: string, run: Function): string {
    runnables[appKey] = {run};
    return appKey;
  },

  registerSection(appKey: string, component: ComponentProvider): void {
    AppRegistry.registerComponent(appKey, component, true);
  },

  getAppKeys(): Array<string> {
    return Object.keys(runnables);
  },

  getSectionKeys(): Array<string> {
    return Object.keys(sections);
  },

  getSections(): Runnables {
    return {
      ...sections
    };
  },

  getRunnable(appKey: string): ?Runnable {
    return runnables[appKey];
  },

  getRegistry(): Registry {
    return {
      sections: AppRegistry.getSectionKeys(),
      runnables: {...runnables},
    };
  },

  runApplication(appKey: string, appParameters: any): void {
    const msg =
      'Running application "' + appKey + '" with appParams: ' +
      JSON.stringify(appParameters) + '. ' +
      '__DEV__ === ' + String(__DEV__) +
      ', development-level warning are ' + (__DEV__ ? 'ON' : 'OFF') +
      ', performance optimizations are ' + (__DEV__ ? 'OFF' : 'ON');
    infoLog(msg);
    BugReporting.addSource('AppRegistry.runApplication' + runCount++, () => msg);
    invariant(
      runnables[appKey] && runnables[appKey].run,
      'Application ' + appKey + ' has not been registered. This ' +
      'is either due to a require() error during initialization ' +
      'or failure to call AppRegistry.registerComponent.'
    );
    runnables[appKey].run(appParameters);
  },

  unmountApplicationComponentAtRootTag(rootTag: number): void {
    ReactNative.unmountComponentAtNodeAndRemoveContainer(rootTag);
  },

  /**
   * Register a headless task. A headless task is a bit of code that runs without a UI.
   * @param taskKey the key associated with this task
   * @param task    a promise returning function that takes some data passed from the native side as
   *                the only argument; when the promise is resolved or rejected the native side is
   *                notified of this event and it may decide to destroy the JS context.
   */
  registerHeadlessTask(taskKey: string, task: TaskProvider): void {
    if (tasks.has(taskKey)) {
      console.warn(`registerHeadlessTask called multiple times for same key '${taskKey}'`);
    }
    tasks.set(taskKey, task);
  },

  /**
   * Only called from native code. Starts a headless task.
   *
   * @param taskId the native id for this task instance to keep track of its execution
   * @param taskKey the key for the task to start
   * @param data the data to pass to the task
   */
  startHeadlessTask(taskId: number, taskKey: string, data: any): void {
    const taskProvider = tasks.get(taskKey);
    if (!taskProvider) {
      throw new Error(`No task registered for key ${taskKey}`);
    }
    taskProvider()(data)
      .then(() => HeadlessJsTaskSupport.notifyTaskFinished(taskId))
      .catch(reason => {
        console.error(reason);
        HeadlessJsTaskSupport.notifyTaskFinished(taskId);
      });
  }

};

BatchedBridge.registerCallableModule(
  'AppRegistry',
  AppRegistry
);

module.exports = AppRegistry;
<|endoftext|>


<commit_before>/**
 * This file is part of Shoop.
 *
 * Copyright (c) 2012-2015, Shoop Ltd. All rights reserved.
 *
 * This source code is licensed under the AGPLv3 license found in the
 * LICENSE file in the root directory of this source tree.
 */
const style = require("style!css!autoprefixer!less!./script-editor.less");  // eslint-disable-line no-unused-vars
const cx = require("classnames");
const Messages = window.Messages;

var settings = {};
const names = {};
const infos = {};
var controller = null;
const optionLists = {};

function showSuccessAndError(data) {
    if (data.error) {
        Messages.enqueue({
            text: _.isString(data.error) ? data.error : "An error occurred.",
            tags: "error"
        });
    }
    if (data.success) {
        Messages.enqueue({
            text: _.isString(data.success) ? data.success : "Success.",
            tags: "success"
        });
    }
}

function apiRequest(command, data, options) {
    const request = _.extend({}, {"command": command}, data || {});
    const req = m.request(_.extend({
        method: "POST",
        url: settings.apiUrl,
        data: request,
        config: function(xhr) {
            xhr.setRequestHeader("X-CSRFToken", window.ShoopAdminConfig.csrf);
        }
    }, options));
    req.then(function(response) {
        showSuccessAndError(response);
    }, function() {
        Messages.enqueue({text: "An unspecified error occurred.", tags: "error"});
    });
    return req;
}

function Controller() {
    const ctrl = this;
    ctrl.steps = m.prop([]);
    ctrl.currentItem = m.prop(null);
    ctrl.newStepItemModalInfo = m.prop(null);

    apiRequest("getData").then(function(data) {
        ctrl.steps(data.steps);
    });

    ctrl.removeStepItem = function(step, itemType, item) {
        const listName = itemType + "s";
        step[listName] = _.reject(step[listName], function(i) {
            return i === item;
        });
        if (ctrl.currentItem() === item) {
            ctrl.activateStepItem(null, null, null);
        }
    };

    ctrl.addStepItem = function(step, itemType, identifier, activateForEdit) {
        const item = {"identifier": identifier};
        const listName = itemType + "s";
        step[listName].push(item);
        if (activateForEdit) {
            ctrl.activateStepItem(step, itemType, item);
        }
    };
    ctrl.setStepItemEditorState = function(state) {
        if (state) {
            document.getElementById("step-item-wrapper").style.display = "block";
        } else {
            document.getElementById("step-item-wrapper").style.display = "none";
            document.getElementById("step-item-frame").src = "about:blank";
        }
    };
    ctrl.activateStepItem = function(step, itemType, item) {
        if (step && item) {
            ctrl.currentItem(item);
            const frm = _.extend(document.createElement("form"), {
                target: "step-item-frame",
                method: "POST",
                action: settings.itemEditorUrl
            });
            frm.appendChild(_.extend(document.createElement("input"), {
                name: "init_data",
                type: "hidden",
                value: JSON.stringify({
                    eventIdentifier: settings.eventIdentifier,
                    itemType: itemType,
                    data: item
                })
            }));
            document.body.appendChild(frm);
            frm.submit();
            ctrl.setStepItemEditorState(true);
        } else {
            ctrl.currentItem(null);
            ctrl.setStepItemEditorState(false);
        }
    };
    ctrl.receiveItemEditData = function(data) {
        const currentItem = ctrl.currentItem();
        if (!currentItem) {
            alert("Unexpected edit data received.");
            return;
        }
        m.startComputation();
        ctrl.currentItem(_.extend(currentItem, data));
        m.endComputation();
    };
    ctrl.saveState = function() {
        apiRequest("saveData", {
            steps: ctrl.steps()
        });

        // TODO: Handle errors here?
    };
    ctrl.deleteStep = function(step) {
        ctrl.steps(_.reject(ctrl.steps(), function(s) {
            return s === step;
        }));
    };
    ctrl.addNewStep = function() {
        const step = {
            actions: [],
            conditions: [],
            enabled: true,
            next: "continue",
            condOp: "and"
        };
        const steps = ctrl.steps();
        steps.push(step);
        ctrl.steps(steps);
    };
    ctrl.moveStep = function(step, delta) {
        const steps = ctrl.steps();
        const oldIndex = _.indexOf(steps, step);
        if (oldIndex === -1) {
            return false;
        }
        const newIndex = oldIndex + delta;
        steps.splice(newIndex, 0, steps.splice(oldIndex, 1)[0]);
        ctrl.steps(steps);
    };
    ctrl.promptForNewStepItem = function(step, itemType) {
        ctrl.newStepItemModalInfo({
            step: step,
            itemType: itemType,
            title: "Add new " + itemType
        });
    };
    ctrl.closeNewStepItemModal = function() {
        ctrl.newStepItemModalInfo(null);
    };
    ctrl.createNewStepItemFromModal = function(identifier) {
        const info = ctrl.newStepItemModalInfo();
        ctrl.closeNewStepItemModal();
        if (info === null) {
            return;
        }
        ctrl.addStepItem(info.step, info.itemType, identifier, true);
    };
}

function workflowItemList(ctrl, step, itemType) {
    const listName = itemType + "s";
    const nameMap = names[itemType];
    const items = step[listName];
    const list = m("ul.action-list", items.map(function(item) {
        const name = nameMap[item.identifier] || item.identifier;
        var tag = "li";
        const current = (ctrl.currentItem() === item);
        if (current) {
            tag += ".current";
        }
        return m(tag,
            [
                m("a", {
                    href: "#",
                    onclick: (!current ? _.partial(ctrl.activateStepItem, step, itemType, item) : null)
                }, name),
                " ",
                m("a.delete", {
                    href: "#", onclick: function() {
                        if (!confirm("Delete this item?\nThis can not be undone.")) {
                            return;
                        }
                        ctrl.removeStepItem(step, itemType, item);
                    }
                }, m("i.fa.fa-trash"))
            ]
        );
    }));
    return m("div", [
        list,
        m("div.action-new", [m("a.btn.btn-xs.btn-primary", {
            href: "#",
            onclick: _.partial(ctrl.promptForNewStepItem, step, itemType)
        }, m("i.fa.fa-plus"), " New " + itemType)])
    ]);
}

function stepTableRows(ctrl) {
    return _.map(ctrl.steps(), function(step, index) {
        const condOpSelect = m("select", {
            value: step.cond_op,
            onchange: m.withAttr("value", function(value) {
                step.cond_op = value;  // eslint-disable-line camelcase
            })
        }, optionLists.condOps);
        const stepNextSelect = m("select", {
            value: step.next,
            onchange: m.withAttr("value", function(value) {
                step.next = value;
            })
        }, optionLists.stepNexts);

        return m("div", {
            className: cx("step", {disabled: !step.enabled}),
            key: step.id
        }, [
            m("div.step-buttons", [
                (index > 0 ? m("a", {
                    href: "#",
                    title: "Move Up",
                    onclick: _.partial(ctrl.moveStep, step, -1)
                }, m("i.fa.fa-caret-up")) : null),
                (index < ctrl.steps().length - 1 ? m("a", {
                    href: "#",
                    title: "Move Down",
                    onclick: _.partial(ctrl.moveStep, step, +1)
                }, m("i.fa.fa-caret-down")) : null),
                (step.enabled ?
                    m("a", {
                        href: "#", title: "Disable", onclick: function() {
                            step.enabled = false;
                        }
                    }, m("i.fa.fa-ban")) :
                    m("a", {
                        href: "#", title: "Enable", onclick: function() {
                            step.enabled = true;
                        }
                    }, m("i.fa.fa-check-circle"))
                ),
                m("a", {
                    href: "#", title: "Delete", onclick: function() {
                        if (confirm("Are you sure you wish to delete this step?")) {
                            ctrl.deleteStep(step);
                        }
                    }
                }, m("i.fa.fa-trash"))
            ]),
            m("div.step-conds", [
                m("span.hint", "If ", condOpSelect, " of these conditions hold..."),
                workflowItemList(ctrl, step, "condition")
            ]),
            m("div.step-actions", [
                m("span.hint", "then execute these actions..."),
                workflowItemList(ctrl, step, "action")
            ]),
            m("div.step-next", [
                m("span.hint", "and then..."),
                stepNextSelect
            ])
        ]);
    });
}

function renderNewStepItemModal(ctrl, modalInfo) {
    return m("div.new-step-item-modal-overlay", {onclick: ctrl.closeNewStepItemModal}, [
        m("div.new-step-item-modal", [
            m("div.title", modalInfo.title),
            m("div.item-options", _.map(_.sortBy(_.values(infos[modalInfo.itemType]), "name"), function(item) {
                return m("div.item-option", {onclick: _.partial(ctrl.createNewStepItemFromModal, item.identifier)}, [
                    m("div.item-name", item.name),
                    (item.description ? m("div.item-description", item.description) : null)
                ]);
            }))
        ])
    ]);
}

function view(ctrl) {
    var modal = null, modalInfo = null;
    if ((modalInfo = ctrl.newStepItemModalInfo()) !== null) {
        modal = renderNewStepItemModal(ctrl, modalInfo);
    }
    return m("div.step-list-wrapper", [
        m("div.steps", [
            stepTableRows(ctrl),
            m("hr.script-separator"),
            m(
                "a.new-step-link.btn.btn-info.btn-sm",
                {href: "#", onclick: ctrl.addNewStep},
                m("i.fa.fa-plus"), " New step"
            )
        ]),
        modal
    ]);
}

function generateItemOptions(nameMap) {
    return _.sortBy(_.map(nameMap, function(name, value) {
        return m("option", {value: value}, name);
    }), function(o) {
        return o.children[0].toLowerCase();
    });
}

function itemInfosToNameMap(itemInfos) {
    return _(itemInfos).map((itemInfo, identifier) => [identifier, itemInfo.name]).zipObject().value();
}

function init(iSettings) {
    settings = _.extend({}, iSettings);
    infos.condition = settings.conditionInfos;
    infos.action = settings.actionInfos;
    names.condition = itemInfosToNameMap(infos.condition);
    names.action = itemInfosToNameMap(infos.action);
    optionLists.condOps = generateItemOptions(settings.condOps);
    optionLists.stepNexts = generateItemOptions(settings.stepNexts);

    controller = m.mount(document.getElementById("step-table-container"), {
        controller: Controller,
        view: view
    });
    window.addEventListener("message", function(event) {
        if (event.data.new_data) {
            controller.receiveItemEditData(event.data.new_data);
        }
    }, false);
}

function save() {
    controller.saveState();
}

module.exports.init = init;
module.exports.save = save;
module.exports.hideEditModal = function() {
    if (controller) {
        m.startComputation();
        controller.setStepItemEditorState(false);
        controller.activateStepItem(null);  // Deactivate the modal once data is received
        m.endComputation();
    }
};
<commit_msg>Notify: make js strings translatable<commit_after>/**
 * This file is part of Shoop.
 *
 * Copyright (c) 2012-2015, Shoop Ltd. All rights reserved.
 *
 * This source code is licensed under the AGPLv3 license found in the
 * LICENSE file in the root directory of this source tree.
 */
const style = require("style!css!autoprefixer!less!./script-editor.less");  // eslint-disable-line no-unused-vars
const cx = require("classnames");
const Messages = window.Messages;

var settings = {};
const names = {};
const infos = {};
var controller = null;
const optionLists = {};

function showSuccessAndError(data) {
    if (data.error) {
        Messages.enqueue({
            text: _.isString(data.error) ? data.error : gettext("An error occurred."),
            tags: "error"
        });
    }
    if (data.success) {
        Messages.enqueue({
            text: _.isString(data.success) ? data.success : gettext("Success."),
            tags: "success"
        });
    }
}

function apiRequest(command, data, options) {
    const request = _.extend({}, {"command": command}, data || {});
    const req = m.request(_.extend({
        method: "POST",
        url: settings.apiUrl,
        data: request,
        config: function(xhr) {
            xhr.setRequestHeader("X-CSRFToken", window.ShoopAdminConfig.csrf);
        }
    }, options));
    req.then(function(response) {
        showSuccessAndError(response);
    }, function() {
        Messages.enqueue({text: gettext("An unspecified error occurred."), tags: "error"});
    });
    return req;
}

function Controller() {
    const ctrl = this;
    ctrl.steps = m.prop([]);
    ctrl.currentItem = m.prop(null);
    ctrl.newStepItemModalInfo = m.prop(null);

    apiRequest("getData").then(function(data) {
        ctrl.steps(data.steps);
    });

    ctrl.removeStepItem = function(step, itemType, item) {
        const listName = itemType + "s";
        step[listName] = _.reject(step[listName], function(i) {
            return i === item;
        });
        if (ctrl.currentItem() === item) {
            ctrl.activateStepItem(null, null, null);
        }
    };

    ctrl.addStepItem = function(step, itemType, identifier, activateForEdit) {
        const item = {"identifier": identifier};
        const listName = itemType + "s";
        step[listName].push(item);
        if (activateForEdit) {
            ctrl.activateStepItem(step, itemType, item);
        }
    };
    ctrl.setStepItemEditorState = function(state) {
        if (state) {
            document.getElementById("step-item-wrapper").style.display = "block";
        } else {
            document.getElementById("step-item-wrapper").style.display = "none";
            document.getElementById("step-item-frame").src = "about:blank";
        }
    };
    ctrl.activateStepItem = function(step, itemType, item) {
        if (step && item) {
            ctrl.currentItem(item);
            const frm = _.extend(document.createElement("form"), {
                target: "step-item-frame",
                method: "POST",
                action: settings.itemEditorUrl
            });
            frm.appendChild(_.extend(document.createElement("input"), {
                name: "init_data",
                type: "hidden",
                value: JSON.stringify({
                    eventIdentifier: settings.eventIdentifier,
                    itemType: itemType,
                    data: item
                })
            }));
            document.body.appendChild(frm);
            frm.submit();
            ctrl.setStepItemEditorState(true);
        } else {
            ctrl.currentItem(null);
            ctrl.setStepItemEditorState(false);
        }
    };
    ctrl.receiveItemEditData = function(data) {
        const currentItem = ctrl.currentItem();
        if (!currentItem) {
            alert(gettext("Unexpected edit data received."));
            return;
        }
        m.startComputation();
        ctrl.currentItem(_.extend(currentItem, data));
        m.endComputation();
    };
    ctrl.saveState = function() {
        apiRequest("saveData", {
            steps: ctrl.steps()
        });

        // TODO: Handle errors here?
    };
    ctrl.deleteStep = function(step) {
        ctrl.steps(_.reject(ctrl.steps(), function(s) {
            return s === step;
        }));
    };
    ctrl.addNewStep = function() {
        const step = {
            actions: [],
            conditions: [],
            enabled: true,
            next: "continue",
            condOp: "and"
        };
        const steps = ctrl.steps();
        steps.push(step);
        ctrl.steps(steps);
    };
    ctrl.moveStep = function(step, delta) {
        const steps = ctrl.steps();
        const oldIndex = _.indexOf(steps, step);
        if (oldIndex === -1) {
            return false;
        }
        const newIndex = oldIndex + delta;
        steps.splice(newIndex, 0, steps.splice(oldIndex, 1)[0]);
        ctrl.steps(steps);
    };
    ctrl.promptForNewStepItem = function(step, itemType) {
        ctrl.newStepItemModalInfo({
            step: step,
            itemType: itemType,
            title: gettext("Add new") + " " + itemType
        });
    };
    ctrl.closeNewStepItemModal = function() {
        ctrl.newStepItemModalInfo(null);
    };
    ctrl.createNewStepItemFromModal = function(identifier) {
        const info = ctrl.newStepItemModalInfo();
        ctrl.closeNewStepItemModal();
        if (info === null) {
            return;
        }
        ctrl.addStepItem(info.step, info.itemType, identifier, true);
    };
}

function workflowItemList(ctrl, step, itemType) {
    const listName = itemType + "s";
    const nameMap = names[itemType];
    const items = step[listName];
    const list = m("ul.action-list", items.map(function(item) {
        const name = nameMap[item.identifier] || item.identifier;
        var tag = "li";
        const current = (ctrl.currentItem() === item);
        if (current) {
            tag += ".current";
        }
        return m(tag,
            [
                m("a", {
                    href: "#",
                    onclick: (!current ? _.partial(ctrl.activateStepItem, step, itemType, item) : null)
                }, name),
                " ",
                m("a.delete", {
                    href: "#", onclick: function() {
                        if (!confirm(gettext("Delete this item?\nThis can not be undone."))) {
                            return;
                        }
                        ctrl.removeStepItem(step, itemType, item);
                    }
                }, m("i.fa.fa-trash"))
            ]
        );
    }));
    return m("div", [
        list,
        m("div.action-new", [m("a.btn.btn-xs.btn-primary", {
            href: "#",
            onclick: _.partial(ctrl.promptForNewStepItem, step, itemType)
        }, m("i.fa.fa-plus"), " " + gettext("New") + " " + itemType)])
    ]);
}

function stepTableRows(ctrl) {
    return _.map(ctrl.steps(), function(step, index) {
        const condOpSelect = m("select", {
            value: step.cond_op,
            onchange: m.withAttr("value", function(value) {
                step.cond_op = value;  // eslint-disable-line camelcase
            })
        }, optionLists.condOps);
        const stepNextSelect = m("select", {
            value: step.next,
            onchange: m.withAttr("value", function(value) {
                step.next = value;
            })
        }, optionLists.stepNexts);

        return m("div", {
            className: cx("step", {disabled: !step.enabled}),
            key: step.id
        }, [
            m("div.step-buttons", [
                (index > 0 ? m("a", {
                    href: "#",
                    title: gettext("Move Up"),
                    onclick: _.partial(ctrl.moveStep, step, -1)
                }, m("i.fa.fa-caret-up")) : null),
                (index < ctrl.steps().length - 1 ? m("a", {
                    href: "#",
                    title: gettext("Move Down"),
                    onclick: _.partial(ctrl.moveStep, step, +1)
                }, m("i.fa.fa-caret-down")) : null),
                (step.enabled ?
                    m("a", {
                        href: "#", title: gettext("Disable"), onclick: function() {
                            step.enabled = false;
                        }
                    }, m("i.fa.fa-ban")) :
                    m("a", {
                        href: "#", title: gettext("Enable"), onclick: function() {
                            step.enabled = true;
                        }
                    }, m("i.fa.fa-check-circle"))
                ),
                m("a", {
                    href: "#", title: gettext("Delete"), onclick: function() {
                        if (confirm(gettext("Are you sure you wish to delete this step?"))) {
                            ctrl.deleteStep(step);
                        }
                    }
                }, m("i.fa.fa-trash"))
            ]),
            m("div.step-conds", [
                m("span.hint", interpolate(gettext("If %s of these conditions hold..."), [condOpSelect])),
                workflowItemList(ctrl, step, "condition")
            ]),
            m("div.step-actions", [
                m("span.hint", gettext("then execute these actions...")),
                workflowItemList(ctrl, step, "action")
            ]),
            m("div.step-next", [
                m("span.hint", gettext("and then...")),
                stepNextSelect
            ])
        ]);
    });
}

function renderNewStepItemModal(ctrl, modalInfo) {
    return m("div.new-step-item-modal-overlay", {onclick: ctrl.closeNewStepItemModal}, [
        m("div.new-step-item-modal", [
            m("div.title", modalInfo.title),
            m("div.item-options", _.map(_.sortBy(_.values(infos[modalInfo.itemType]), "name"), function(item) {
                return m("div.item-option", {onclick: _.partial(ctrl.createNewStepItemFromModal, item.identifier)}, [
                    m("div.item-name", item.name),
                    (item.description ? m("div.item-description", item.description) : null)
                ]);
            }))
        ])
    ]);
}

function view(ctrl) {
    var modal = null, modalInfo = null;
    if ((modalInfo = ctrl.newStepItemModalInfo()) !== null) {
        modal = renderNewStepItemModal(ctrl, modalInfo);
    }
    return m("div.step-list-wrapper", [
        m("div.steps", [
            stepTableRows(ctrl),
            m("hr.script-separator"),
            m(
                "a.new-step-link.btn.btn-info.btn-sm",
                {href: "#", onclick: ctrl.addNewStep},
                m("i.fa.fa-plus"), " " + gettext("New step")
            )
        ]),
        modal
    ]);
}

function generateItemOptions(nameMap) {
    return _.sortBy(_.map(nameMap, function(name, value) {
        return m("option", {value: value}, name);
    }), function(o) {
        return o.children[0].toLowerCase();
    });
}

function itemInfosToNameMap(itemInfos) {
    return _(itemInfos).map((itemInfo, identifier) => [identifier, itemInfo.name]).zipObject().value();
}

function init(iSettings) {
    settings = _.extend({}, iSettings);
    infos.condition = settings.conditionInfos;
    infos.action = settings.actionInfos;
    names.condition = itemInfosToNameMap(infos.condition);
    names.action = itemInfosToNameMap(infos.action);
    optionLists.condOps = generateItemOptions(settings.condOps);
    optionLists.stepNexts = generateItemOptions(settings.stepNexts);

    controller = m.mount(document.getElementById("step-table-container"), {
        controller: Controller,
        view: view
    });
    window.addEventListener("message", function(event) {
        if (event.data.new_data) {
            controller.receiveItemEditData(event.data.new_data);
        }
    }, false);
}

function save() {
    controller.saveState();
}

module.exports.init = init;
module.exports.save = save;
module.exports.hideEditModal = function() {
    if (controller) {
        m.startComputation();
        controller.setStepItemEditorState(false);
        controller.activateStepItem(null);  // Deactivate the modal once data is received
        m.endComputation();
    }
};
<|endoftext|>


<commit_before>(function(){
try {
if(localStorage.mainOrder === "undefined" || localStorage.sideOrder === "undefined") {
  localStorage.removeItem('mainOrder');
  localStorage.removeItem('sideOrder');
}

var unmask = function () {
  var s = $('.splash-input').val();
  return s.slice(1,4) + s.slice(6,9) + s.slice(10);
};

timeCheck = function () {
  var now = moment();
  var isBetween = function (m, first, second) {
    return m.isAfter(first) && m.isBefore(second);
  };
  var time = function (h, m) {
    return moment(now).hour(h).minute(m);
  };

  var weekday = parseInt(now.format('d')); //sun=0, mon=1 ..
  if(isBetween(now, time(11,30), time(14,0)) &&  weekday < 6 && weekday > 0) {
    return "Summies Lunch";
  }
  if(isBetween(now, time(17,30), time(21,0))) {
    return "Summies Dinner";
  }
  if(isBetween(now, time(21,30), time(23,59).add(1, 'd'))) {
    return "Late Night";
  }
  if(isBetween(now, time(0,0), time(1,0).add(1, 'd'))) {
    return "Late Night";
  }
  return "No";
};

data = [];

started = false;
//define new router class
var AppRouter = Backbone.Router.extend ({
  routes: {
    '' : function () {
      started = true;
      $('.header>div').hide();
      $('#first-header').show();
      $('.splash-container').hide();
      $('.first-container').show();
    },
    'mainOrder': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var router = this;
      $.getJSON('/menu/' + unmask(), function (d) {
        data = d;
        console.log('Menu for user fetched.');
      });

      var searched = fuzzy.filter($('#second-header input').val(), data.map(function (i) {
        return i.item;
      })).map(function(el) {
        return _(data).findWhere({item: el.string});
      });

      var router = this;
      var num = $('.splash-input').val();

      if(num.length !== 14) {
        this.navigate("", {trigger: true});
        return;
      }
      num = num.match(/\d/g).join("");

      $('.second-container').show();
      $('.header>div').hide();
      $('#second-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.first-container').hide();
        $('.first-container').removeClass('flip');
      }, 500);

      var itemstemplate = $('.second-container #items-template');
      var itemlist = $('.second-container .item-list');
      var processed = _(searched).where({side: false});

      var switcher = $('.foody-switcher span').text();

      var filters = [];
      if($('.vegan').hasClass('foody-checked')){
        filters.push("vegan");
      }
      if($('.gluten-free').hasClass('foody-checked')){
        filters.push("gluten-free");
      }
      //Filters
      processed = processed.filter(function (i) {
        return _.isEqual(filters, _.intersection(filters, i.filter));
      });

      //Sorting
      processed = _(processed).sortBy(function (i) {
        if(switcher === "Cheapest") {
          return i.price;
        }
        if(switcher === "Prev Orders") {
          return i.prev;
        }
        return 5 - i.rating_avg;
      });
      itemlist.html(_.template(itemstemplate.html(), {items: processed}));
      $('.second-container .item-list .pure-g').click(function (e) {
        $('.second-container .item-list .pure-g').removeClass('selected');
        var t = $(e.currentTarget);
        t.addClass('selected');
        localStorage.mainOrder = t.data('id');
        router.navigate('sides', {trigger: true});
      });
    },
    'sides': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var router = this;
      var selectedItem = $('.second-container .item-list .pure-g.selected');
      if(selectedItem.length !== 1) {
        this.navigate('mainOrder', {trigger: true});
      }
      $('#third-header .pure-menu-heading').html('Sides for ' + selectedItem.find('h3').text() + '');

      $('.header>div').hide();
      $('#third-header').show();

      $('.second-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.second-container').removeClass('flip');
        $('.third-container').show();
      }, 500);

      var itemstemplate = $('.third-container #items-template');
      var itemlist = $('.third-container .item-list');
      var processed = _(data).where({side: true});

      itemlist.html(_.template(itemstemplate.html(), {items: processed}));
      $('.third-container .item-list .pure-g').click(function (e) {
        $('.third-container .item-list .pure-g').removeClass('selected');
        var t = $(e.currentTarget);
        t.addClass('selected');
        localStorage.sideOrder = t.data('id');
        router.navigate('special', {trigger: true});
      });
    },
    'special': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var selectedItem = $('.third-container .item-list .pure-g.selected');
      if(selectedItem.length !== 1) {
        this.navigate('sides', {trigger: true});
      }

      $('.header>div').hide();
      $('#fourth-header').show();

      $('.third-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.third-container').removeClass('flip');
        $('.fourth-container').show();
      }, 500);

      var itemstemplate = $('.fourth-container #items-template');
      var itemlist = $('.fourth-container .item-list');

      var mainOrder = $('.second-container .item-list .pure-g.selected');
      var sideOrder = $('.third-container .item-list .pure-g.selected');
      if(mainOrder.length < 1 || sideOrder.length < 1) {
        this.navigate('', {trigger: true});
      }
      itemlist.html(_.template(itemstemplate.html(), {
        mainOrder: mainOrder.find('h3').text(),
        sideOrder: sideOrder.find('h3').text(),
        mainPrice: parseFloat(mainOrder.data('price')),
        sidePrice: parseFloat(sideOrder.data('price'))
      }));

      var prevOption = localStorage.prevOption;
      $('textarea').val(_.isUndefined(prevOption) ? '' : prevOption);
      $('textarea').keyup(function (e) {
        localStorage.prevOption = $('textarea').val();
      });

    },
    sending: function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      $('.header>div').hide();
      $('#first-header').show();

      $('.fourth-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.fourth-container').removeClass('flip');
        $('.fifth-container').show();
      }, 500);
      console.log("sending");
      var cb = function () {
        $('.sending').hide();
        $('.sent').show();
        $('.fifth-container p').show();
      };
      // setTimeout(cb, 2000);

        var orderedMain = _(data).findWhere({_id: localStorage.mainOrder});
        var orderedSide = _(data).findWhere({_id: localStorage.sideOrder});
        if(orderedSide.menu !== orderedMain.menu) {
          console.log('You selected items from different menus.');
          return;
        }

        var toSend = {
          destination: orderedMain.menu,
          item_id: localStorage.mainOrder,
          side_id: localStorage.sideOrder,
          special: localStorage.prevOption,
          number: unmask()
        };

        console.log(toSend);

        $.ajax({
          type: "POST",
          url: "/order",
          data: toSend,
        }).done(function( msg ) {
          console.log(msg);
          cb();
        });
    },
    'repeatLastOrder': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      if(_.isNull(localStorage.getItem('mainOrder')) || _.isNull(localStorage.getItem('sideOrder'))) {
        this.navigate('mainOrder', {trigger: true});
        return;
      }

      $('.header>div').hide();
      $('#fourth-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.first-container').removeClass('flip');
        $('.fourth-container').show();
      }, 500);

      var itemstemplate = $('.fourth-container #items-template');
      var itemlist = $('.fourth-container .item-list');

      var mainOrder = _(data).findWhere({_id: localStorage.mainOrder});
      var sideOrder = _(data).findWhere({_id: localStorage.sideOrder});
      itemlist.html(_.template(itemstemplate.html(), {
        mainOrder: mainOrder.item,
        sideOrder: sideOrder.item,
        mainPrice: mainOrder.price,
        sidePrice: sideOrder.price
      }));

      var prevOption = localStorage.prevOption;
      $('textarea').val(_.isUndefined(prevOption) ? '' : prevOption);
      $('textarea').keyup(function (e) {
        localStorage.prevOption = $('textarea').val();
      });
    },
    'rate': function () {
      if(!started) {this.navigate('',{trigger:true});return;}

      var itemstemplate = $('.rate-container #items-template');
      var itemlist = $('.rate-container .item-list');

      var searched = _(fuzzy.filter($('#rate-header input').val(), data.map(function (i) {
        return i.item;
      })).map(function(el) {
        return _(data).findWhere({item: el.string});
      })).sortBy(function (i) {
        return 5 - i.rating_avg;
      });

      $('.header>div').hide();
      $('#rate-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.first-container').removeClass('flip');
        $('.rate-container').show();
      }, 500);

      var router = this;
      itemlist.html(_.template(itemstemplate.html(), {items: searched}));
      $('.rate-container select.point').change(function (e) {
        var id = $(e.currentTarget).data('id');
        var pt = $(e.currentTarget).val();

        $.ajax({
          type: "POST",
          url: "/ratings",
          data: {item: id, rate: pt}
        }).done(function( msg ) {
          data = data.map(function (i) {
            if(i._id === id) {
              i.rating_avg = parseFloat(msg);
            }
            return i;
          });
          router.navigate("");
          router.navigate("rate", {trigger: true});
        });

      })
    }
  }
});

$(document).ready(function () {
  $('#first-header a').prepend('' + timeCheck() + ' ')

  var prevTel = localStorage.prevTel;
  $('.splash-input').val(_.isUndefined(prevTel) ? '' : prevTel);
  $('.splash-input').keyup(function (e) {
    localStorage.prevTel = $('.splash-input').val();
  });
  var tel = unmask();
  var url;
  if(tel === "") {
    url = "/menu/0";
  } else {
    url = "/menu/" + unmask();
  }
  $.getJSON(url, function (d) {
    data = d;
  });

  $('#second-header input').keyup(function () {
    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  $('#rate-header input').keyup(function () {
    appRouter.navigate("");
    appRouter.navigate("rate", {trigger: true});
  });

  $('.foody-checkbox').click(function (e) {
    var t = $(e.currentTarget);
    t.toggleClass("foody-checked");
    t.find('.fa').toggleClass('fa-check-square-o');
    t.find('.fa').toggleClass('fa-square-o');

    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  $('.foody-switcher').click(function (e) {
    var t = $(e.currentTarget);
    var content = ["Best Rated", "Cheapest", "Prev Orders"];
    var current = t.find('span').text();
    current = content.indexOf(current);
    if(current === 2) {
      current = -1;
    }
    var next = content[current + 1];
    t.find('span').text(next);

    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  var appRouter = new AppRouter();
  Backbone.history.start();
  appRouter.navigate('#');
});

} catch(e) {
  console.log(e);
  Backbone.history.navigate('#');
}
})();
<commit_msg>late night time changes<commit_after>(function(){
try {
if(localStorage.mainOrder === "undefined" || localStorage.sideOrder === "undefined") {
  localStorage.removeItem('mainOrder');
  localStorage.removeItem('sideOrder');
}

var unmask = function () {
  var s = $('.splash-input').val();
  return s.slice(1,4) + s.slice(6,9) + s.slice(10);
};

timeCheck = function () {
  var now = moment();
  var isBetween = function (m, first, second) {
    return m.isAfter(first) && m.isBefore(second);
  };
  var time = function (h, m) {
    return moment(now).hour(h).minute(m);
  };

  var weekday = parseInt(now.format('d')); //sun=0, mon=1 ..
  if(isBetween(now, time(11,30), time(14,0)) &&  weekday < 6 && weekday > 0) {
    return "Summies Lunch";
  }
  if(isBetween(now, time(17,30), time(21,0))) {
    return "Summies Dinner";
  }
  if(isBetween(now, time(21,30), time(23,59))) {
    return "Late Night";
  }
  if(isBetween(now, time(00,00), time(01,00))) {
    return "Late Night";
  }
  return "No";
};

data = [];

started = false;
//define new router class
var AppRouter = Backbone.Router.extend ({
  routes: {
    '' : function () {
      started = true;
      $('.header>div').hide();
      $('#first-header').show();
      $('.splash-container').hide();
      $('.first-container').show();
    },
    'mainOrder': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var router = this;
      $.getJSON('/menu/' + unmask(), function (d) {
        data = d;
        console.log('Menu for user fetched.');
      });

      var searched = fuzzy.filter($('#second-header input').val(), data.map(function (i) {
        return i.item;
      })).map(function(el) {
        return _(data).findWhere({item: el.string});
      });

      var router = this;
      var num = $('.splash-input').val();

      if(num.length !== 14) {
        this.navigate("", {trigger: true});
        return;
      }
      num = num.match(/\d/g).join("");

      $('.second-container').show();
      $('.header>div').hide();
      $('#second-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.first-container').hide();
        $('.first-container').removeClass('flip');
      }, 500);

      var itemstemplate = $('.second-container #items-template');
      var itemlist = $('.second-container .item-list');
      var processed = _(searched).where({side: false});

      var switcher = $('.foody-switcher span').text();

      var filters = [];
      if($('.vegan').hasClass('foody-checked')){
        filters.push("vegan");
      }
      if($('.gluten-free').hasClass('foody-checked')){
        filters.push("gluten-free");
      }
      //Filters
      processed = processed.filter(function (i) {
        return _.isEqual(filters, _.intersection(filters, i.filter));
      });

      //Sorting
      processed = _(processed).sortBy(function (i) {
        if(switcher === "Cheapest") {
          return i.price;
        }
        if(switcher === "Prev Orders") {
          return i.prev;
        }
        return 5 - i.rating_avg;
      });
      itemlist.html(_.template(itemstemplate.html(), {items: processed}));
      $('.second-container .item-list .pure-g').click(function (e) {
        $('.second-container .item-list .pure-g').removeClass('selected');
        var t = $(e.currentTarget);
        t.addClass('selected');
        localStorage.mainOrder = t.data('id');
        router.navigate('sides', {trigger: true});
      });
    },
    'sides': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var router = this;
      var selectedItem = $('.second-container .item-list .pure-g.selected');
      if(selectedItem.length !== 1) {
        this.navigate('mainOrder', {trigger: true});
      }
      $('#third-header .pure-menu-heading').html('Sides for ' + selectedItem.find('h3').text() + '');

      $('.header>div').hide();
      $('#third-header').show();

      $('.second-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.second-container').removeClass('flip');
        $('.third-container').show();
      }, 500);

      var itemstemplate = $('.third-container #items-template');
      var itemlist = $('.third-container .item-list');
      var processed = _(data).where({side: true});

      itemlist.html(_.template(itemstemplate.html(), {items: processed}));
      $('.third-container .item-list .pure-g').click(function (e) {
        $('.third-container .item-list .pure-g').removeClass('selected');
        var t = $(e.currentTarget);
        t.addClass('selected');
        localStorage.sideOrder = t.data('id');
        router.navigate('special', {trigger: true});
      });
    },
    'special': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      var selectedItem = $('.third-container .item-list .pure-g.selected');
      if(selectedItem.length !== 1) {
        this.navigate('sides', {trigger: true});
      }

      $('.header>div').hide();
      $('#fourth-header').show();

      $('.third-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.third-container').removeClass('flip');
        $('.fourth-container').show();
      }, 500);

      var itemstemplate = $('.fourth-container #items-template');
      var itemlist = $('.fourth-container .item-list');

      var mainOrder = $('.second-container .item-list .pure-g.selected');
      var sideOrder = $('.third-container .item-list .pure-g.selected');
      if(mainOrder.length < 1 || sideOrder.length < 1) {
        this.navigate('', {trigger: true});
      }
      itemlist.html(_.template(itemstemplate.html(), {
        mainOrder: mainOrder.find('h3').text(),
        sideOrder: sideOrder.find('h3').text(),
        mainPrice: parseFloat(mainOrder.data('price')),
        sidePrice: parseFloat(sideOrder.data('price'))
      }));

      var prevOption = localStorage.prevOption;
      $('textarea').val(_.isUndefined(prevOption) ? '' : prevOption);
      $('textarea').keyup(function (e) {
        localStorage.prevOption = $('textarea').val();
      });

    },
    sending: function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      $('.header>div').hide();
      $('#first-header').show();

      $('.fourth-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.fourth-container').removeClass('flip');
        $('.fifth-container').show();
      }, 500);
      console.log("sending");
      var cb = function () {
        $('.sending').hide();
        $('.sent').show();
        $('.fifth-container p').show();
      };
      // setTimeout(cb, 2000);

        var orderedMain = _(data).findWhere({_id: localStorage.mainOrder});
        var orderedSide = _(data).findWhere({_id: localStorage.sideOrder});
        if(orderedSide.menu !== orderedMain.menu) {
          console.log('You selected items from different menus.');
          return;
        }

        var toSend = {
          destination: orderedMain.menu,
          item_id: localStorage.mainOrder,
          side_id: localStorage.sideOrder,
          special: localStorage.prevOption,
          number: unmask()
        };

        console.log(toSend);

        $.ajax({
          type: "POST",
          url: "/order",
          data: toSend,
        }).done(function( msg ) {
          console.log(msg);
          cb();
        });
    },
    'repeatLastOrder': function () {
      if(!started) {this.navigate('',{trigger:true});return;}
      if(_.isNull(localStorage.getItem('mainOrder')) || _.isNull(localStorage.getItem('sideOrder'))) {
        this.navigate('mainOrder', {trigger: true});
        return;
      }

      $('.header>div').hide();
      $('#fourth-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.first-container').removeClass('flip');
        $('.fourth-container').show();
      }, 500);

      var itemstemplate = $('.fourth-container #items-template');
      var itemlist = $('.fourth-container .item-list');

      var mainOrder = _(data).findWhere({_id: localStorage.mainOrder});
      var sideOrder = _(data).findWhere({_id: localStorage.sideOrder});
      itemlist.html(_.template(itemstemplate.html(), {
        mainOrder: mainOrder.item,
        sideOrder: sideOrder.item,
        mainPrice: mainOrder.price,
        sidePrice: sideOrder.price
      }));

      var prevOption = localStorage.prevOption;
      $('textarea').val(_.isUndefined(prevOption) ? '' : prevOption);
      $('textarea').keyup(function (e) {
        localStorage.prevOption = $('textarea').val();
      });
    },
    'rate': function () {
      if(!started) {this.navigate('',{trigger:true});return;}

      var itemstemplate = $('.rate-container #items-template');
      var itemlist = $('.rate-container .item-list');

      var searched = _(fuzzy.filter($('#rate-header input').val(), data.map(function (i) {
        return i.item;
      })).map(function(el) {
        return _(data).findWhere({item: el.string});
      })).sortBy(function (i) {
        return 5 - i.rating_avg;
      });

      $('.header>div').hide();
      $('#rate-header').show();

      $('.first-container').addClass('flip');
      setTimeout(function () {
        $('.splash-container').hide();
        $('.first-container').removeClass('flip');
        $('.rate-container').show();
      }, 500);

      var router = this;
      itemlist.html(_.template(itemstemplate.html(), {items: searched}));
      $('.rate-container select.point').change(function (e) {
        var id = $(e.currentTarget).data('id');
        var pt = $(e.currentTarget).val();

        $.ajax({
          type: "POST",
          url: "/ratings",
          data: {item: id, rate: pt}
        }).done(function( msg ) {
          data = data.map(function (i) {
            if(i._id === id) {
              i.rating_avg = parseFloat(msg);
            }
            return i;
          });
          router.navigate("");
          router.navigate("rate", {trigger: true});
        });

      })
    }
  }
});

$(document).ready(function () {
  $('#first-header a').prepend('' + timeCheck() + ' ')

  var prevTel = localStorage.prevTel;
  $('.splash-input').val(_.isUndefined(prevTel) ? '' : prevTel);
  $('.splash-input').keyup(function (e) {
    localStorage.prevTel = $('.splash-input').val();
  });
  var tel = unmask();
  var url;
  if(tel === "") {
    url = "/menu/0";
  } else {
    url = "/menu/" + unmask();
  }
  $.getJSON(url, function (d) {
    data = d;
  });

  $('#second-header input').keyup(function () {
    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  $('#rate-header input').keyup(function () {
    appRouter.navigate("");
    appRouter.navigate("rate", {trigger: true});
  });

  $('.foody-checkbox').click(function (e) {
    var t = $(e.currentTarget);
    t.toggleClass("foody-checked");
    t.find('.fa').toggleClass('fa-check-square-o');
    t.find('.fa').toggleClass('fa-square-o');

    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  $('.foody-switcher').click(function (e) {
    var t = $(e.currentTarget);
    var content = ["Best Rated", "Cheapest", "Prev Orders"];
    var current = t.find('span').text();
    current = content.indexOf(current);
    if(current === 2) {
      current = -1;
    }
    var next = content[current + 1];
    t.find('span').text(next);

    appRouter.navigate("");
    appRouter.navigate("mainOrder", {trigger: true});
  });

  var appRouter = new AppRouter();
  Backbone.history.start();
  appRouter.navigate('#');
});

} catch(e) {
  console.log(e);
  Backbone.history.navigate('#');
}
})();
<|endoftext|>


<commit_before>"use strict"

var db = require('../db');

// A controller for the equipment resource
// This should have methods for all the RESTful actions
class Homepage {

  getHomepageData(req, res) {
    db.get('SELECT * FROM users WHERE is_donut_baron=?', 1, function(err, donutBaron) {
      if (err) {
        console.error(err);
        return res.sendStatus(500);
      }
      db.all('SELECT * FROM upcomingList', function(err, upcomingUsers) {
        if (err) {
          console.error(err);
          return res.sendStatus(500);
        };
        res.render('index', { donutBaron: donutBaron, upcomingUsers: upcomingUsers, user: req.user } );
      });
    });
  }

  RateDonuts(req, res) {
    var reliability = 0;
    if(typeof req.body.delivered == "undefined") {
        reliability = 100;
    }
    db.run("UPDATE users SET has_rated_this_week=1 WHERE userID=?",
          req.user.userID);
    db.get("SELECT * FROM users WHERE is_donut_baron=?",
          1,
      function(err, donutBaron) {
        if (err) {
          console.error(err);
          return res.sendStatus(500);
        }
        db.run("UPDATE users SET donut_quality_rating=?, donut_reliability_rating=?, number_of_ratings=? WHERE userID=?",
          Math.floor((donutBaron.donut_quality_rating + parseInt(req.body.score))/(2) * 100 / 100),
          Math.floor((donutBaron.donut_reliability_rating + reliability)/(2) * 100 / 100),
          donutBaron.number_of_ratings + 1,
          donutBaron.userID);
        db.all('SELECT * FROM upcomingList', function(err, upcomingUsers) {
          if (err) {
            console.error(err);
            return res.sendStatus(500);
          };
          res.redirect("/#rate");
        });
      });
  }

    getComments(req, res) {
        db.all('SELECT * FROM comments', function(err, commentsArray) {
            if(err) {
                console.error(err);
                return res.sendStatus(500);
            }
            res.send(commentsArray);
        });
    }

    addComment(req, res) {
        db.run('INSERT INTO comments (content, fullname, created, upvote_count, user_has_upvoted) values (?,?,?,?,?)',
            req.body.comment.content,
            req.body.currentUser,
            req.body.comment.created,
            parseInt(req.body.comment.upvote_count),
            req.body.comment.user_has_upvoted == 'true' ? 1 : 0
        );
        //Need to convert string values back to their original types.
        req.body.comment.user_has_upvoted = (req.body.comment.user_has_upvoted == 'true' ? true : false);
        req.body.comment.upvote_count = parseInt(req.body.comment.upvote_count);
        req.body.comment.created_by_current_user = (req.body.comment.created_by_current_user == 'true' ? true : false);
        res.send(req.body.comment);
    }

}

module.exports = exports = new Homepage();
<commit_msg>Ratings should be fully functional?<commit_after>"use strict"

var db = require('../db');

// A controller for the equipment resource
// This should have methods for all the RESTful actions
class Homepage {

  getHomepageData(req, res) {
    db.get('SELECT * FROM users WHERE is_donut_baron=?', 1, function(err, donutBaron) {
      if (err) {
        console.error(err);
        return res.sendStatus(500);
      }
      db.all('SELECT * FROM upcomingList', function(err, upcomingUsers) {
        if (err) {
          console.error(err);
          return res.sendStatus(500);
        };
        res.render('index', { donutBaron: donutBaron, upcomingUsers: upcomingUsers, user: req.user } );
      });
    });
  }

  RateDonuts(req, res) {
    var reliability = 0;
    if(typeof req.body.delivered == "undefined") {
        reliability = 100;
    }
    db.run("UPDATE users SET has_rated_this_week=1 WHERE userID=?",
          req.user.userID);
    db.get("SELECT * FROM users WHERE is_donut_baron=?",
          1,
      function(err, donutBaron) {
        if (err) {
          console.error(err);
          return res.sendStatus(500);
        }
        db.run("UPDATE users SET donut_quality_rating=?, donut_reliability_rating=?, number_of_ratings=? WHERE userID=?",
          Math.round(((donutBaron.donut_quality_rating + parseInt(req.body.score))/2) * 10) / 10,
          Math.floor(donutBaron.donut_reliability_rating + reliability)/(2),
          donutBaron.number_of_ratings + 1,
          donutBaron.userID);
        db.all('SELECT * FROM upcomingList', function(err, upcomingUsers) {
          if (err) {
            console.error(err);
            return res.sendStatus(500);
          };
          res.redirect("/#rate");
        });
      });
  }

    getComments(req, res) {
        db.all('SELECT * FROM comments', function(err, commentsArray) {
            if(err) {
                console.error(err);
                return res.sendStatus(500);
            }
            res.send(commentsArray);
        });
    }

    addComment(req, res) {
        db.run('INSERT INTO comments (content, fullname, created, upvote_count, user_has_upvoted) values (?,?,?,?,?)',
            req.body.comment.content,
            req.body.currentUser,
            req.body.comment.created,
            parseInt(req.body.comment.upvote_count),
            req.body.comment.user_has_upvoted == 'true' ? 1 : 0
        );
        //Need to convert string values back to their original types.
        req.body.comment.user_has_upvoted = (req.body.comment.user_has_upvoted == 'true' ? true : false);
        req.body.comment.upvote_count = parseInt(req.body.comment.upvote_count);
        req.body.comment.created_by_current_user = (req.body.comment.created_by_current_user == 'true' ? true : false);
        res.send(req.body.comment);
    }

}

module.exports = exports = new Homepage();
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Opt Schema
 */
var OptSchema = new Schema({
  title: {
    type : String,
    default : '',
    required: 'Please fill Option title',
    trim : true
  },
  body: {
    type : String,
    default : '',
    required: 'Please fill Option body',
    trim : true
  },
  poll: {
    type : Schema.ObjectId,
    ref : 'Poll',
    required: 'Please fill Poll info',
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  voteCnt: {
    type : Number,
    default : 0
  },
  created: {
    type: Date,
    default: Date.now
  }
});
/**
 * Hook a pre save method to hash the password
 */
OptSchema.pre('save', function (next) {
  if (typeof this._id !== 'String') {
    this._id = mongoose.Types.ObjectId(this._id);
  }

  next();
});

mongoose.model('Opt', OptSchema);
<commit_msg>Commited from lenh at 2017年 6月 15日 木曜日 11:08:12<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Opt Schema
 */
var OptSchema = new Schema({
  title: {
    type : String,
    default : '',
    required: 'Please fill Option title',
    trim : true
  },
  body: {
    type : String,
    default : '',
    required: 'Please fill Option body',
    trim : true
  },
  poll: {
    type : Schema.ObjectId,
    ref : 'Poll',
    required: 'Please fill Poll info',
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  voteCnt: {
    type : Number,
    default : 0
  },
  created: {
    type: Date,
    default: Date.now
  }
});
/**
 * Hook a pre save method to hash the password
 */
OptSchema.pre('save', function (next) {
  if (typeof this._id === 'String') {
    this._id = mongoose.Types.ObjectId(this._id);
  }

  next();
});

mongoose.model('Opt', OptSchema);
<|endoftext|>


<commit_before>var mysleep = require('sleep');
var chai = require('chai');
var parentDir = require('path');
var currentDir = parentDir.dirname(module.filename);
var Connection = require(parentDir.dirname(currentDir) + '/dist/api/connection').Connection
var StateType = require(parentDir.dirname(currentDir) + '/dist/api/api').StateType
var IRecipientInfo = require(parentDir.dirname(currentDir) + '/dist/api/api').IRecipientInfo
var path = parentDir.dirname(currentDir) + "/lib/libcxs.so";
var cxs = require('../dist/index.js')
var expect = chai.expect;
var assert = chai.assert;

const sleep = (time) => new Promise((res) => setTimeout(res, time))

const waitFor = async (predicate) => {
    if (!predicate()) {
        await sleep(1000)
        return waitFor(predicate)
    }
    return predicate()
}

// console.log(release(handle)) // tslint:disable-line
describe('A Connection object with ', function () {
    this.timeout(10000)

    before(function() {
        cxs.init_cxs('ENABLE_TEST_MODE')
    });

    //connection_create tests

    it('valid parameters in create should return success', function () {
        const connection = new Connection(path)
        assert.equal(connection.create({
            id: "234",
            DIDself: "456",
            DIDremote: "0"}), 0)
    })

    it('null param in create should return success', function () {
        const connection = new Connection(path)
        assert.equal(connection.create(null), 0)
    })

// connection_connect tests

    it(' a call to connect with connection already created should return success', function () {
        const connection = new Connection(path)
        connection.create("connection_connect tests")
        return connection.connect({sms: true})
    })

    it(' a call to create with no connection created should return unknown error', function () {
        const connection = new Connection(path)
        assert.equal(connection._connect({sms: true}), 1003)
    })

// connection_get_data tests

    it('a call to get_data where connection exists should return back the connections data', function () {
        const connection = new Connection(path)
        connection.create("dog, cat, man")
        var data = connection.getData()
        var jsonData = JSON.parse(data)
        assert.notEqual(data, null)
        assert.equal(jsonData.handle, connection.connectionHandle)
    })

    it('a call to get_data where connection doesnt exist should return a null value', function () {
        const connection = new Connection(path)
        assert.equal(connection.getData(), null)
    })

    it('a call to get_data where connection was released should return a null value', async function () {
        const connection = new Connection(path)
        assert.equal(connection.create("connection_get_data tests"), 0)

        await connection.connect({sms: true})

        assert.equal(connection.getState(),StateType.OfferSent)

        var data = connection.getData()
        assert.notEqual(data, null)
        assert.equal(connection.release(), 0)

        data = connection.getData()
        assert.equal(data, null)
    })

    // connection_getState tests

    it('call to getState where connection exists should return success', async function () {
        const connection = new Connection(path)
        connection.create("connection_getState tests")
        await connection.connect({sms: true})
        assert.equal(connection.getState(),StateType.OfferSent)

    })

    it('call to getState where no connection exists should have a state value of 0', function () {
        const connection = new Connection(path)
        assert.equal(connection.getState(),StateType.None)
    })

    it('call to get_state where connection exists but not connected should have a state value of 1', function () {
        const connection = new Connection(path)
        connection.create("info2")
        return waitFor(() => connection.getState() === StateType.Initialized)
    })

// connection_release tests

    it('call to connection_release where connection exists should return success', async function () {
        const connection = new Connection(path)
        connection.create("connection_release tests")
        await connection.connect({sms: true})
        assert.equal(connection.release(), 0)
        assert.equal(connection._connect({sms: true}), 1003)
        assert.equal(connection.getData(), null)
    })

    it('call to connection_release with no connection should return unknown error', function () {
        const connection = new Connection(path)
        assert.equal(connection.release(), 1003)
    })

    it('connection and GC deletes object should return null whet get_data is called ', function () {
        this.timeout(30000)
        const connection = new Connection(path)
        connection.create("msg")
        connection._connect({sms: true})
        const getData = connection.RUST_API.cxs_connection_get_data
        const handle = connection.connectionHandle
        assert.notEqual(connection.getData(handle), null)

        delete connection
        global.gc()

        // this will timeout if condition is never met
        // get_data will return "" because the connection object was released
        return waitFor(() => !getData(handle))
    })

})
<commit_msg>Fix<commit_after>var mysleep = require('sleep');
var chai = require('chai');
var parentDir = require('path');
var currentDir = parentDir.dirname(module.filename);
var Connection = require(parentDir.dirname(currentDir) + '/dist/api/connection').Connection
var StateType = require(parentDir.dirname(currentDir) + '/dist/api/api').StateType
var IRecipientInfo = require(parentDir.dirname(currentDir) + '/dist/api/api').IRecipientInfo
var path = parentDir.dirname(currentDir) + "/lib/libcxs.so";
var cxs = require('../dist/index.js')
var expect = chai.expect;
var assert = chai.assert;

const sleep = (time) => new Promise((res) => setTimeout(res, time))

const waitFor = async (predicate) => {
    if (!predicate()) {
        await sleep(1000)
        return waitFor(predicate)
    }
    return predicate()
}

// console.log(release(handle)) // tslint:disable-line
describe('A Connection object with ', function () {
    this.timeout(10000)

    before(function() {
        cxs.init_cxs('ENABLE_TEST_MODE')
    });

    //connection_create tests

    it('valid parameters in create should return success', function () {
        const connection = new Connection(path)
        assert.equal(connection.create({
            id: "234",
            DIDself: "456",
            DIDremote: "0"}), 0)
    })

    it('null param in create should return success', function () {
        const connection = new Connection(path)
        assert.equal(connection.create(null), 0)
    })

// connection_connect tests

    it(' a call to connect with connection already created should return success', async function () {
        const connection = new Connection(path)
        await connection.create("connection_connect tests")
        return connection.connect({sms: true})
    })

    it(' a call to create with no connection created should return unknown error', function () {
        const connection = new Connection(path)
        assert.equal(connection._connect({sms: true}), 1003)
    })

// connection_get_data tests

    it('a call to get_data where connection exists should return back the connections data', function () {
        const connection = new Connection(path)
        connection.create("dog, cat, man")
        var data = connection.getData()
        var jsonData = JSON.parse(data)
        assert.notEqual(data, null)
        assert.equal(jsonData.handle, connection.connectionHandle)
    })

    it('a call to get_data where connection doesnt exist should return a null value', function () {
        const connection = new Connection(path)
        assert.equal(connection.getData(), null)
    })

    it('a call to get_data where connection was released should return a null value', async function () {
        const connection = new Connection(path)
        assert.equal(connection.create("connection_get_data tests"), 0)

        await connection.connect({sms: true})

        assert.equal(connection.getState(),StateType.OfferSent)

        var data = connection.getData()
        assert.notEqual(data, null)
        assert.equal(connection.release(), 0)

        data = connection.getData()
        assert.equal(data, null)
    })

    // connection_getState tests

    it('call to getState where connection exists should return success', async function () {
        const connection = new Connection(path)
        connection.create("connection_getState tests")
        await connection.connect({sms: true})
        assert.equal(connection.getState(),StateType.OfferSent)
    })

    it('call to getState where no connection exists should have a state value of 0', function () {
        const connection = new Connection(path)
        assert.equal(connection.getState(),StateType.None)
    })

    it('call to get_state where connection exists but not connected should have a state value of 1', function () {
        const connection = new Connection(path)
        connection.create("info2")
        return waitFor(() => connection.getState() === StateType.Initialized)
    })

// connection_release tests

    it('call to connection_release where connection exists should return success', async function () {
        const connection = new Connection(path)
        connection.create("connection_release tests")
        await connection.connect({sms: true})
        assert.equal(connection.release(), 0)
        assert.equal(connection._connect({sms: true}), 1003)
        assert.equal(connection.getData(), null)
    })

    it('call to connection_release with no connection should return unknown error', function () {
        const connection = new Connection(path)
        assert.equal(connection.release(), 1003)
    })

    it('connection and GC deletes object should return null whet get_data is called ', function () {
        this.timeout(30000)
        const connection = new Connection(path)
        connection.create("msg")
        connection._connect({sms: true})
        const getData = connection.RUST_API.cxs_connection_get_data
        const handle = connection.connectionHandle
        assert.notEqual(connection.getData(handle), null)

        delete connection
        global.gc()

        // this will timeout if condition is never met
        // get_data will return "" because the connection object was released
        return waitFor(() => !getData(handle))
    })

})
<|endoftext|>


<commit_before>$(document).ready(function() {
  if ( $('section#video').length != 0 ) {
    console.log('Performances page!');

    // Get the user's videos
    $.getScript(apiEndpoint + vimeoUsername + '/videos.json?callback=' + videosCallback);
  }
});

var apiEndpoint = 'http://vimeo.com/api/v2/';
var oEmbedEndpoint = 'http://vimeo.com/api/oembed.json'
var oEmbedCallback = 'switchVideo';
var videosCallback = 'setupGallery';
var vimeoUsername = 'user13986449';

function videoWidth() {
  return 550;
}

function videoHeight() {
  return Math.floor((videoWidth() / 1.8));
}

function getVideo(url) {
  $.getScript(oEmbedEndpoint + '?url=' + url + '&byline=false&width='+ videoWidth() +'&height='+videoHeight()+'&callback=' + oEmbedCallback);
}

function setupGallery(videos) {
  // Find video: Sonata (Jan Krzywicki)
  var krzywicki = $.grep(videos, function(e){ return e.id == 51099433; });
  // Load krzywicki
  getVideo(krzywicki[0].url);

  // Add the videos to the gallery
  for (var i = 0; i < videos.length; i++) {
    var html = '
';
    html += '
' + videos[i].title + '

';
    $('div.related ul.thumbnails').append(html);
  }

  // Switch to the video when a thumbnail is clicked
  $('.thumbnails a').click(function(event) {
    event.preventDefault();
    getVideo(this.href);
    return false;
  });

}

function switchVideo(video) {
  $('.embed').html(unescape(video.html));
  $('.details .title').html(unescape(video.title))
  $('.details .description').html(unescape(video.description.replace(/\n/g, '
')))
}
<commit_msg>bugfix: sponsors should be clickable<commit_after>$(document).ready(function() {
  if ( $('section#video').length != 0 ) {
    console.log('Performances page!');

    // Get the user's videos
    $.getScript(apiEndpoint + vimeoUsername + '/videos.json?callback=' + videosCallback);
  }
});

var apiEndpoint = 'http://vimeo.com/api/v2/';
var oEmbedEndpoint = 'http://vimeo.com/api/oembed.json'
var oEmbedCallback = 'switchVideo';
var videosCallback = 'setupGallery';
var vimeoUsername = 'user13986449';

function videoWidth() {
  return 550;
}

function videoHeight() {
  return Math.floor((videoWidth() / 1.8));
}

function getVideo(url) {
  $.getScript(oEmbedEndpoint + '?url=' + url + '&byline=false&width='+ videoWidth() +'&height='+videoHeight()+'&callback=' + oEmbedCallback);
}

function setupGallery(videos) {
  // Find video: Sonata (Jan Krzywicki)
  var krzywicki = $.grep(videos, function(e){ return e.id == 51099433; });
  // Load krzywicki
  getVideo(krzywicki[0].url);

  // Add the videos to the gallery
  for (var i = 0; i < videos.length; i++) {
    var html = '
';
    html += '
' + videos[i].title + '

';
    $('div.related ul.thumbnails').append(html);
  }

  // Switch to the video when a thumbnail is clicked
  $('div.related ul.thumbnails a').click(function(event) {
    event.preventDefault();
    getVideo(this.href);
    return false;
  });

}

function switchVideo(video) {
  $('.embed').html(unescape(video.html));
  $('.details .title').html(unescape(video.title))
  $('.details .description').html(unescape(video.description.replace(/\n/g, '
')))
}
<|endoftext|>


<commit_before>$(document).ready(function() {
  var menuToggle = $('#js-mobile-menu').unbind();
  $('#js-navigation-menu').removeClass("show");

  menuToggle.on('click', function(e) {
    e.preventDefault();
    $('#js-navigation-menu').slideToggle(function(){
      if($('#js-navigation-menu').is(':hidden')) {
        $('#js-navigation-menu').removeAttr('style');
      }
    });
  });
});
<commit_msg>Fix second layer MORE not showing when hovering on navigation<commit_after>$(document).ready(function() {
  var menuToggle = $('#js-mobile-menu').unbind();
  $('#js-navigation-menu').hide().show(0);

  menuToggle.on('click', function(e) {
    e.preventDefault();
    $('#js-navigation-menu').slideToggle(function(){
      if($('#js-navigation-menu').is(':hidden')) {
        $('#js-navigation-menu').removeAttr('style');
      }
    });
  });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';

import {
    SearchBox,
    NoHits,
    Hits,
    HitsStats,
    ItemCheckboxList,
    SortingSelector,
    SelectedFilters,
    MenuFilter,
    Pagination,
    RefinementListFilter,
    ResetFilters,
    SearchkitManager,
    SearchkitProvider,
    Tabs,
    } from "searchkit";

import {
  Layout, TopBar, LayoutBody, LayoutResults,
  ActionBar, ActionBarRow, SideBar
} from "searchkit"

const searchkit = new SearchkitManager("https://kinto-ota.dev.mozaws.net/v1/buckets/build-hub/collections/releasesv2/", {searchUrlPath: "search"})

const HitsTable = (toggleExpand, expandedEntry) => {
  return ({hits}) => {
    return (

              Product
              Version
              Platform
              Channel
              Locale
              Published on

            {hits.map(hit => {
              const revisionUrl = (hit._source.source.revision)
                ? ({hit._source.source.revision})
                : "";
              const filename = hit._source.download.url.split("/").reverse()[0];
              const clickHandler = (event, data) => toggleExpand(event, data, hit._id);
              if (expandedEntry === hit._id) {
                return (

Product: {hit._source.source.product}

Version: {hit._source.target.version}

Platform: {hit._source.target.platform}

Channel: {hit._source.target.channel}

Locale: {hit._source.target.locale}

Published on: {hit._source.download.date}

Tree: {hit._source.source.tree}

Revision: {revisionUrl}

URL: {filename}

Mimetype: {hit._source.download.mimetype}

Size: {hit._source.download.size}

Build date: {hit._source.build && hit._source.build.date}

Id: {hit._source.build && hit._source.build.id}

                )
              } else {
                return (

                    {hit._source.source.product}
                    {hit._source.target.version}
                    {hit._source.target.platform}
                    {hit._source.target.channel}
                    {hit._source.target.locale}
                    {hit._source.download.date}

                )
              }
            })}

    );
  };
};

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expandedEntry: null
    };
  }

  toggleExpand(event, data, id) {
    if (this.state.expandedEntry === id) {
      this.setState({expandedEntry: null});
    } else {
      this.setState({expandedEntry: id});
    }
  }

  render() {
    return (

        <SearchkitProvider searchkit={searchkit}>
          <Layout>

            <TopBar>
              <SearchBox
              autofocus={true}
              searchOnChange={true}
              placeholder="Search a build ID, eg: 201706*"
              queryFields={["build.id"]}/>
            </TopBar>

            <LayoutBody>
              <SideBar>
                <RefinementListFilter field="target.version"
                            title="Version"
                            id="versions"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            orderDirection="desc"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All versions"}}/>
                <RefinementListFilter field="target.platform"
                            title="Platform"
                            id="platform"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All platforms"}}/>
                <RefinementListFilter field="target.channel"
                            title="Channel"
                            id="channel"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All channels"}}/>
                <RefinementListFilter field="target.locale"
                            title="Locale"
                            id="locale"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All locales"}}/>
              </SideBar>

              <LayoutResults>

                <ActionBar>
                  <ActionBarRow>
                    <HitsStats/>
                    <SortingSelector options={[
                      {label: "Published on", field:"download.date", order: "desc", defaultOption: true},
                      {label: "Build date", field:"build.date", order: "desc"}
                    ]}/>
                  </ActionBarRow>

                  <ActionBarRow>
                    <SelectedFilters/>
                    <ResetFilters/>
                  </ActionBarRow>

                  <MenuFilter field="source.product"
                              title="Product"
                              id="products"
                              listComponent={Tabs}
                              translations={{"All":"All products"}}/>
                </ActionBar>

                <Hits hitsPerPage={30} listComponent={HitsTable(this.toggleExpand.bind(this), this.state.expandedEntry)}/>
                <NoHits translations={{
                  "NoHits.NoResultsFound":"No release found were found for {query}",
                  "NoHits.DidYouMean":"Search for {suggestion}",
                  "NoHits.SearchWithoutFilters":"Search for {query} without filters"}} suggestionsField="target.version"/>

                <Pagination showNumbers={true}/>

               </LayoutResults>
            </LayoutBody>
          </Layout>
        </SearchkitProvider>

    );
  }
}

export default App;
<commit_msg>First attempt at fixing #150: (slightly) better styling for expanded information<commit_after>import React, { Component } from 'react';
import './App.css';

import {
    SearchBox,
    NoHits,
    Hits,
    HitsStats,
    ItemCheckboxList,
    SortingSelector,
    SelectedFilters,
    MenuFilter,
    Pagination,
    RefinementListFilter,
    ResetFilters,
    SearchkitManager,
    SearchkitProvider,
    Tabs,
    } from "searchkit";

import {
  Layout, TopBar, LayoutBody, LayoutResults,
  ActionBar, ActionBarRow, SideBar
} from "searchkit"

const searchkit = new SearchkitManager("https://kinto-ota.dev.mozaws.net/v1/buckets/build-hub/collections/releasesv2/", {searchUrlPath: "search"})

const HitsTable = (toggleExpand, expandedEntry) => {
  const tableStyle = {width: "100%", boxSizing: 'border-box'};
  return ({hits}) => {
    return (

              Product
              Version
              Platform
              Channel
              Locale
              Published on

            {hits.map(hit => {
              const revisionUrl = (hit._source.source.revision)
                ? ({hit._source.source.revision})
                : "";
              const filename = hit._source.download.url.split("/").reverse()[0];
              const clickHandler = (event, data) => toggleExpand(event, data, hit._id);
              if (expandedEntry === hit._id) {
                return (

                            Product
                            Tree
                            Revision

                            {hit._source.source.product}
                            {hit._source.source.tree}
                            {revisionUrl}

Target

                            Version
                            Platform
                            Channel
                            Locale

                            {hit._source.target.version}
                            {hit._source.target.platform}
                            {hit._source.target.channel}
                            {hit._source.target.locale}

Download

                            URL
                            Mimetype
                            Size
                            Published on

                            {filename}
                            {hit._source.download.mimetype}
                            {hit._source.download.size}
                            {hit._source.download.date}

Build

                            id
                            Date

                            {hit._source.build && hit._source.build.id}
                            {hit._source.build && hit._source.build.date}

                )
              } else {
                return (

                    {hit._source.source.product}
                    {hit._source.target.version}
                    {hit._source.target.platform}
                    {hit._source.target.channel}
                    {hit._source.target.locale}
                    {hit._source.download.date}

                )
              }
            })}

    );
  };
};

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expandedEntry: null
    };
  }

  toggleExpand(event, data, id) {
    if (this.state.expandedEntry === id) {
      this.setState({expandedEntry: null});
    } else {
      this.setState({expandedEntry: id});
    }
  }

  render() {
    return (

        <SearchkitProvider searchkit={searchkit}>
          <Layout>

            <TopBar>
              <SearchBox
              autofocus={true}
              searchOnChange={true}
              placeholder="Search a build ID, eg: 201706*"
              queryFields={["build.id"]}/>
            </TopBar>

            <LayoutBody>
              <SideBar>
                <RefinementListFilter field="target.version"
                            title="Version"
                            id="versions"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            orderDirection="desc"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All versions"}}/>
                <RefinementListFilter field="target.platform"
                            title="Platform"
                            id="platform"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All platforms"}}/>
                <RefinementListFilter field="target.channel"
                            title="Channel"
                            id="channel"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All channels"}}/>
                <RefinementListFilter field="target.locale"
                            title="Locale"
                            id="locale"
                            size={10}
                            operator="OR"
                            orderKey="_term"
                            listComponent={ItemCheckboxList}
                            translations={{"All":"All locales"}}/>
              </SideBar>

              <LayoutResults>

                <ActionBar>
                  <ActionBarRow>
                    <HitsStats/>
                    <SortingSelector options={[
                      {label: "Published on", field:"download.date", order: "desc", defaultOption: true},
                      {label: "Build date", field:"build.date", order: "desc"}
                    ]}/>
                  </ActionBarRow>

                  <ActionBarRow>
                    <SelectedFilters/>
                    <ResetFilters/>
                  </ActionBarRow>

                  <MenuFilter field="source.product"
                              title="Product"
                              id="products"
                              listComponent={Tabs}
                              translations={{"All":"All products"}}/>
                </ActionBar>

                <Hits hitsPerPage={30} listComponent={HitsTable(this.toggleExpand.bind(this), this.state.expandedEntry)}/>
                <NoHits translations={{
                  "NoHits.NoResultsFound":"No release found were found for {query}",
                  "NoHits.DidYouMean":"Search for {suggestion}",
                  "NoHits.SearchWithoutFilters":"Search for {query} without filters"}} suggestionsField="target.version"/>

                <Pagination showNumbers={true}/>

               </LayoutResults>
            </LayoutBody>
          </Layout>
        </SearchkitProvider>

    );
  }
}

export default App;
<|endoftext|>


<commit_before>// Basic test case
var Botkit = require('botkit');

var controller = Botkit.slackbot({
  debug: true
});

// connect the bot to a stream of messages
controller.spawn({
  token: process.env.SLACK_TOKEN,
}).startRTM()

// give the bot something to listen for.
controller.hears('throw the dice',['direct_message','direct_mention','mention'],function(bot,message) {

  var names = ["Josh", "Keshav", "Chris", "Will", "KC", "Jarom", "Christian"];
  shuffle(names);
  bot.reply(message,names.join('\n'));

});

// Fisher–Yates shuffle - thanks stack overflow
// http://stackoverflow.com/a/6274398/3221576
function shuffle(array) {
  var counter = array.length;

  // While there are elements in the array
  while (counter > 0) {
    // Pick a random index
    var index = Math.floor(Math.random() * counter);

    // Decrease counter by 1
    counter--;

    // And swap the last element with it
    var temp = array[counter];
    array[counter] = array[index];
    array[index] = temp;
  }

  return array;
}
<commit_msg>added addison and alphabetized<commit_after>// Basic test case
var Botkit = require('botkit');

var controller = Botkit.slackbot({
  debug: true
});

// connect the bot to a stream of messages
controller.spawn({
  token: process.env.SLACK_TOKEN,
}).startRTM()

// give the bot something to listen for.
controller.hears('throw the dice',['direct_message','direct_mention','mention'],function(bot,message) {

  var names = ["Addison", "Christian", "Chris", "Jarom", "Josh", "KC", "Keshav", "Will"];
  shuffle(names);
  bot.reply(message,names.join('\n'));

});

// Fisher–Yates shuffle - thanks stack overflow
// http://stackoverflow.com/a/6274398/3221576
function shuffle(array) {
  var counter = array.length;

  // While there are elements in the array
  while (counter > 0) {
    // Pick a random index
    var index = Math.floor(Math.random() * counter);

    // Decrease counter by 1
    counter--;

    // And swap the last element with it
    var temp = array[counter];
    array[counter] = array[index];
    array[index] = temp;
  }

  return array;
}
<|endoftext|>