<commit_before>import {browserHistory} from 'react-router';

import * as ActionCreators from './action-creators';
import * as ActionTypes from './action-types';
import {request, response, fail, requiresAuth, isFeedRequest, isFeedResponse} from './action-helpers';
import {getPost} from '../services/api';
import {setToken, persistUser} from '../services/auth';
import {init} from '../services/realtime';
import {userParser} from '../utils';

//middleware for api requests
export const apiMiddleware = store => next => async (action) => {
  //ignore normal actions
  if (!action.apiRequest) {
    return next(action);
  }

  //dispatch request begin action
  //clean apiRequest to not get caught by this middleware
  var t = store.dispatch({...action, type: request(action.type), apiRequest: null});
  try {
    const apiResponse = await action.apiRequest(action.payload);
    const obj = await apiResponse.json();
    if (apiResponse.status === 200) {
      return store.dispatch({payload: obj, type: response(action.type), request: action.payload});
    } else {
      return store.dispatch({payload: obj, type: fail(action.type), request: action.payload, response: apiResponse});
    }
  } catch (e) {
    return store.dispatch(ActionCreators.serverError(e));
  }
};

export const authMiddleware = store => next => action => {

  //stop action propagation if it should be authed and user is not authed
  if (requiresAuth(action) && !store.getState().authenticated) {
    return;
  }

  if (action.type === ActionTypes.UNAUTHENTICATED) {
    setToken();
    persistUser();
    next(action);
    const pathname = (store.getState().routing.locationBeforeTransitions || {}).pathname;
    if (!pathname || pathname.indexOf('signin') !== -1 || pathname.indexOf('signup') !== -1) {
      return;
    }
    return browserHistory.push('/signin');
  }

  if (action.type === response(ActionTypes.SIGN_IN) ||
     action.type === response(ActionTypes.SIGN_UP) ) {
    setToken(action.payload.authToken);
    next(action);
    store.dispatch(ActionCreators.whoAmI());

    // Do not redirect to Home page if signed in at Bookmarklet
    const pathname = (store.getState().routing.locationBeforeTransitions || {}).pathname;
    if (pathname === '/bookmarklet') {
      return;
    }

    return browserHistory.push('/');
  }

  if (action.type === response(ActionTypes.WHO_AM_I) ||
     action.type === response(ActionTypes.UPDATE_USER) ) {
    persistUser(userParser(action.payload.users));
    return next(action);
  }

  return next(action);
};

export const searchMiddleware = store => next => action => {
  switch (action.type) {
    case response(ActionTypes.GET_SEARCH_RESULTS): {
      // Let's just remove irrelevant comments from the server payload
      // (all except for the first ones and the last ones)

      // 1. Remove pointers to those comments from payload.posts
      // and set proper omittedComments for each post
      let irrelevantCommentIds = [];
      if (action.payload.posts) {
        action.payload.posts.forEach((post) => {
          if (post.comments && post.comments.length > 3) {
            post.omittedComments = post.comments.length - 2;
            for (let i = 1; i < post.comments.length - 1; i++) {
              irrelevantCommentIds.push(post.comments[i]);
            }
            post.comments = [post.comments[0], post.comments[post.comments.length - 1]];
          }
        });
      }

      // 2. Remove the actual comments from payload.comments
      if (action.payload.comments) {
        action.payload.comments = action.payload.comments.filter(c => irrelevantCommentIds.indexOf(c.id) === -1);
      }
    }
  }

  return next(action);
};

export const likesLogicMiddleware = store => next => action => {
  switch (action.type) {
    case ActionTypes.SHOW_MORE_LIKES: {
      const postId = action.payload.postId;
      const post = store.getState().posts[postId];
      const isSync = (post.omittedLikes === 0);
      if (isSync) {
        return store.dispatch(ActionCreators.showMoreLikesSync(postId));
      } else {
        return store.dispatch(ActionCreators.showMoreLikesAsync(postId));
      }
    }
  }

  return next(action);
};

export const userPhotoLogicMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.UPDATE_USER_PICTURE)) {
    // Update data after userpic is updated
    store.dispatch(ActionCreators.whoAmI());
  }

  return next(action);
};

export const groupPictureLogicMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.UPDATE_GROUP_PICTURE)) {
    // Update data after group picture is updated
    store.dispatch(ActionCreators.getUserInfo(action.request.groupName));
  }

  return next(action);
};

export const redirectionMiddleware = store => next => action => {
  //go to home if single post has been removed
  if (action.type === response(ActionTypes.DELETE_POST) && store.getState().singlePostId) {
    return browserHistory.push('/');
  }

  if (action.type === response(ActionTypes.DEMOTE_GROUP_ADMIN) &&
      store.getState().user.id === action.request.user.id) {
    browserHistory.push(`/${action.request.groupName}/subscribers`);
  }

  return next(action);
};

export const requestsMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.WHO_AM_I)) {
    next(action);

    if (store.getState().user.pendingGroupRequests) {
      store.dispatch(ActionCreators.managedGroups());
    }

    return;
  }

  return next(action);
};

const maybeGetRespectivePost = async (store, postId, action) => {
  const state = store.getState();

  // If the post is in the store, just pass on the original action (comment:new or like:new)
  if (state.posts[postId]) {
    return store.dispatch(action);
  }

  // Otherwise, for the first page of home feed, try to retrieve the respective post
  const isHomeFeed = state.routing.locationBeforeTransitions.pathname === '/';
  const isFirstPage = !state.routing.locationBeforeTransitions.query.offset;
  if (isHomeFeed && isFirstPage) {
    const postResponse = await getPost({postId});
    const data = await postResponse.json();
    if (postResponse.status === 200) {
      return store.dispatch({...data, type: ActionTypes.REALTIME_POST_NEW, post: data.posts});
    }
  }

  return false;
};

const bindHandlers = store => ({
  'post:new': data => {
    const state = store.getState();

    const isFirstPage = !state.routing.locationBeforeTransitions.query.offset;

    if (isFirstPage) {

      const isHomeFeed = state.routing.locationBeforeTransitions.pathname === '/';
      const useRealtimePreference = state.user.frontendPreferences.realtimeActive;

      if (!isHomeFeed || (useRealtimePreference && isHomeFeed)) {
        return store.dispatch({...data, type: ActionTypes.REALTIME_POST_NEW, post: data.posts});
      }
    }
    return false;
  },
  'post:update': data => store.dispatch({...data, type: ActionTypes.REALTIME_POST_UPDATE, post: data.posts}),
  'post:destroy': data => store.dispatch({type: ActionTypes.REALTIME_POST_DESTROY, postId: data.meta.postId}),
  'post:hide': data => store.dispatch({type: ActionTypes.REALTIME_POST_HIDE, postId: data.meta.postId}),
  'post:unhide': data => store.dispatch({type: ActionTypes.REALTIME_POST_UNHIDE, postId: data.meta.postId}),
  'comment:new': data => maybeGetRespectivePost(store, data.comments.postId, {type: ActionTypes.REALTIME_COMMENT_NEW, comment: data.comments, users: data.users}),
  'comment:update': data => store.dispatch({...data, type: ActionTypes.REALTIME_COMMENT_UPDATE, comment: data.comments}),
  'comment:destroy': data => store.dispatch({type: ActionTypes.REALTIME_COMMENT_DESTROY, commentId: data.commentId, postId: data.postId}),
  'like:new': data => maybeGetRespectivePost(store, data.meta.postId, {type: ActionTypes.REALTIME_LIKE_NEW, postId: data.meta.postId, users:[data.users]}),
  'like:remove': data => store.dispatch({type: ActionTypes.REALTIME_LIKE_REMOVE, postId: data.meta.postId, userId: data.meta.userId}),
});

export const realtimeMiddleware = store => {
  const handlers = bindHandlers(store);
  let realtimeConnection;
  return next => action => {

    if (action.type === ActionTypes.UNAUTHENTICATED) {
      if (realtimeConnection) {
        realtimeConnection.disconnect();
        realtimeConnection = undefined;
      }
    }

    if (isFeedRequest(action) ||
      action.type === request(ActionTypes.GET_SINGLE_POST)) {
      if (realtimeConnection) {
        realtimeConnection.unsubscribe();
      }
    }

    if (isFeedResponse(action) && action.payload.timelines) {
      if (!realtimeConnection) {
        realtimeConnection = init(handlers);
      }
      realtimeConnection.subscribe({timeline:[action.payload.timelines.id]});
    }

    if (action.type === response(ActionTypes.GET_SINGLE_POST)) {
      if (!realtimeConnection) {
        realtimeConnection = init(handlers);
      }
      realtimeConnection.subscribe({post:[action.payload.posts.id]});
    }

    return next(action);
  };
};
<commit_msg>Add post visibility check on realtime comments and likes<commit_after>import {browserHistory} from 'react-router';

import * as ActionCreators from './action-creators';
import * as ActionTypes from './action-types';
import {request, response, fail, requiresAuth, isFeedRequest, isFeedResponse} from './action-helpers';
import {getPost} from '../services/api';
import {setToken, persistUser} from '../services/auth';
import {init} from '../services/realtime';
import {userParser} from '../utils';

//middleware for api requests
export const apiMiddleware = store => next => async (action) => {
  //ignore normal actions
  if (!action.apiRequest) {
    return next(action);
  }

  //dispatch request begin action
  //clean apiRequest to not get caught by this middleware
  var t = store.dispatch({...action, type: request(action.type), apiRequest: null});
  try {
    const apiResponse = await action.apiRequest(action.payload);
    const obj = await apiResponse.json();
    if (apiResponse.status === 200) {
      return store.dispatch({payload: obj, type: response(action.type), request: action.payload});
    } else {
      return store.dispatch({payload: obj, type: fail(action.type), request: action.payload, response: apiResponse});
    }
  } catch (e) {
    return store.dispatch(ActionCreators.serverError(e));
  }
};

export const authMiddleware = store => next => action => {

  //stop action propagation if it should be authed and user is not authed
  if (requiresAuth(action) && !store.getState().authenticated) {
    return;
  }

  if (action.type === ActionTypes.UNAUTHENTICATED) {
    setToken();
    persistUser();
    next(action);
    const pathname = (store.getState().routing.locationBeforeTransitions || {}).pathname;
    if (!pathname || pathname.indexOf('signin') !== -1 || pathname.indexOf('signup') !== -1) {
      return;
    }
    return browserHistory.push('/signin');
  }

  if (action.type === response(ActionTypes.SIGN_IN) ||
     action.type === response(ActionTypes.SIGN_UP) ) {
    setToken(action.payload.authToken);
    next(action);
    store.dispatch(ActionCreators.whoAmI());

    // Do not redirect to Home page if signed in at Bookmarklet
    const pathname = (store.getState().routing.locationBeforeTransitions || {}).pathname;
    if (pathname === '/bookmarklet') {
      return;
    }

    return browserHistory.push('/');
  }

  if (action.type === response(ActionTypes.WHO_AM_I) ||
     action.type === response(ActionTypes.UPDATE_USER) ) {
    persistUser(userParser(action.payload.users));
    return next(action);
  }

  return next(action);
};

export const searchMiddleware = store => next => action => {
  switch (action.type) {
    case response(ActionTypes.GET_SEARCH_RESULTS): {
      // Let's just remove irrelevant comments from the server payload
      // (all except for the first ones and the last ones)

      // 1. Remove pointers to those comments from payload.posts
      // and set proper omittedComments for each post
      let irrelevantCommentIds = [];
      if (action.payload.posts) {
        action.payload.posts.forEach((post) => {
          if (post.comments && post.comments.length > 3) {
            post.omittedComments = post.comments.length - 2;
            for (let i = 1; i < post.comments.length - 1; i++) {
              irrelevantCommentIds.push(post.comments[i]);
            }
            post.comments = [post.comments[0], post.comments[post.comments.length - 1]];
          }
        });
      }

      // 2. Remove the actual comments from payload.comments
      if (action.payload.comments) {
        action.payload.comments = action.payload.comments.filter(c => irrelevantCommentIds.indexOf(c.id) === -1);
      }
    }
  }

  return next(action);
};

export const likesLogicMiddleware = store => next => action => {
  switch (action.type) {
    case ActionTypes.SHOW_MORE_LIKES: {
      const postId = action.payload.postId;
      const post = store.getState().posts[postId];
      const isSync = (post.omittedLikes === 0);
      if (isSync) {
        return store.dispatch(ActionCreators.showMoreLikesSync(postId));
      } else {
        return store.dispatch(ActionCreators.showMoreLikesAsync(postId));
      }
    }
  }

  return next(action);
};

export const userPhotoLogicMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.UPDATE_USER_PICTURE)) {
    // Update data after userpic is updated
    store.dispatch(ActionCreators.whoAmI());
  }

  return next(action);
};

export const groupPictureLogicMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.UPDATE_GROUP_PICTURE)) {
    // Update data after group picture is updated
    store.dispatch(ActionCreators.getUserInfo(action.request.groupName));
  }

  return next(action);
};

export const redirectionMiddleware = store => next => action => {
  //go to home if single post has been removed
  if (action.type === response(ActionTypes.DELETE_POST) && store.getState().singlePostId) {
    return browserHistory.push('/');
  }

  if (action.type === response(ActionTypes.DEMOTE_GROUP_ADMIN) &&
      store.getState().user.id === action.request.user.id) {
    browserHistory.push(`/${action.request.groupName}/subscribers`);
  }

  return next(action);
};

export const requestsMiddleware = store => next => action => {
  if (action.type === response(ActionTypes.WHO_AM_I)) {
    next(action);

    if (store.getState().user.pendingGroupRequests) {
      store.dispatch(ActionCreators.managedGroups());
    }

    return;
  }

  return next(action);
};

const maybeGetRespectivePost = async (store, postId, action) => {
  const state = store.getState();

  // If the post is in the store and it's visible, just pass on the original action (comment:new or like:new)
  if (state.posts[postId] && state.feedViewState.visibleEntries.indexOf(postId) > -1) {
    return store.dispatch(action);
  }

  // Otherwise, for the first page of home feed, try to retrieve the respective post
  const isHomeFeed = state.routing.locationBeforeTransitions.pathname === '/';
  const isFirstPage = !state.routing.locationBeforeTransitions.query.offset;
  if (isHomeFeed && isFirstPage) {
    const postResponse = await getPost({postId});
    const data = await postResponse.json();
    if (postResponse.status === 200) {
      return store.dispatch({...data, type: ActionTypes.REALTIME_POST_NEW, post: data.posts});
    }
  }

  return false;
};

const bindHandlers = store => ({
  'post:new': data => {
    const state = store.getState();

    const isFirstPage = !state.routing.locationBeforeTransitions.query.offset;

    if (isFirstPage) {

      const isHomeFeed = state.routing.locationBeforeTransitions.pathname === '/';
      const useRealtimePreference = state.user.frontendPreferences.realtimeActive;

      if (!isHomeFeed || (useRealtimePreference && isHomeFeed)) {
        return store.dispatch({...data, type: ActionTypes.REALTIME_POST_NEW, post: data.posts});
      }
    }
    return false;
  },
  'post:update': data => store.dispatch({...data, type: ActionTypes.REALTIME_POST_UPDATE, post: data.posts}),
  'post:destroy': data => store.dispatch({type: ActionTypes.REALTIME_POST_DESTROY, postId: data.meta.postId}),
  'post:hide': data => store.dispatch({type: ActionTypes.REALTIME_POST_HIDE, postId: data.meta.postId}),
  'post:unhide': data => store.dispatch({type: ActionTypes.REALTIME_POST_UNHIDE, postId: data.meta.postId}),
  'comment:new': data => maybeGetRespectivePost(store, data.comments.postId, {type: ActionTypes.REALTIME_COMMENT_NEW, comment: data.comments, users: data.users}),
  'comment:update': data => store.dispatch({...data, type: ActionTypes.REALTIME_COMMENT_UPDATE, comment: data.comments}),
  'comment:destroy': data => store.dispatch({type: ActionTypes.REALTIME_COMMENT_DESTROY, commentId: data.commentId, postId: data.postId}),
  'like:new': data => maybeGetRespectivePost(store, data.meta.postId, {type: ActionTypes.REALTIME_LIKE_NEW, postId: data.meta.postId, users:[data.users]}),
  'like:remove': data => store.dispatch({type: ActionTypes.REALTIME_LIKE_REMOVE, postId: data.meta.postId, userId: data.meta.userId}),
});

export const realtimeMiddleware = store => {
  const handlers = bindHandlers(store);
  let realtimeConnection;
  return next => action => {

    if (action.type === ActionTypes.UNAUTHENTICATED) {
      if (realtimeConnection) {
        realtimeConnection.disconnect();
        realtimeConnection = undefined;
      }
    }

    if (isFeedRequest(action) ||
      action.type === request(ActionTypes.GET_SINGLE_POST)) {
      if (realtimeConnection) {
        realtimeConnection.unsubscribe();
      }
    }

    if (isFeedResponse(action) && action.payload.timelines) {
      if (!realtimeConnection) {
        realtimeConnection = init(handlers);
      }
      realtimeConnection.subscribe({timeline:[action.payload.timelines.id]});
    }

    if (action.type === response(ActionTypes.GET_SINGLE_POST)) {
      if (!realtimeConnection) {
        realtimeConnection = init(handlers);
      }
      realtimeConnection.subscribe({post:[action.payload.posts.id]});
    }

    return next(action);
  };
};
<|endoftext|>


<commit_before>window.cls || (window.cls = {});

window.cls.ListUnpacker = function(repl_service)
{

  this.unpack_list_alikes = function(msg, rt_id, callback)
  {
    const VALUE_LIST = 2, OBJECT_VALUE = 1, OBJECT_ID = 0;
    var value_list = msg[VALUE_LIST];
    var obj_ids = [];
    var call_list = [];
    var arg_list = [];
    for (var i = 0, obj_id, obj_id_str, value; value = value_list[i]; i++)
    {
      obj_id = value[OBJECT_VALUE] && value[OBJECT_VALUE][OBJECT_ID] || 0;
      obj_id_str = obj_id && "$_" + obj_id || "null";
      obj_ids.push(obj_id);
      call_list.push(obj_id_str);
      if (obj_id)
      {
        arg_list.push([obj_id_str, obj_id]);
      }
    };
    var tag = this._tagman.set_callback(this, this._handle_list_alikes_list,
                                        [msg, rt_id, obj_ids, callback]);
    var script = this._is_list_alike_to_string.replace("%s", call_list.join(','));
    var msg = [rt_id, 0, 0, script, arg_list];
    this._edservice.requestEval(tag, msg);
  }

  // Boolean(document.all) === false
  this._is_list_alike = function(list)
  {
    return list.map(function(item)
    {
      var _class = item === null ? "" : Object.prototype.toString.call(item);
      if (/(?:Array|Collection|List|Map)\]$/.test(_class))
      {
        return 2;
      }
      if (_class == "[object Object]" && typeof item.length == "number")
      {
        return 1;
      }
      return 0;
    }).join(',');
  };

  this._handle_list_alikes_list = function(status, msg, orig_msg,
                                           rt_id, obj_ids, callback)
  {
    const STATUS = 0, VALUE = 2;
    if (status || msg[STATUS] != "completed")
    {
      callback();
    }
    else
    {
      var log = msg[VALUE].split(',').map(Number);
      if (log.filter(Boolean).length)
      {
        var unpack = log.reduce(function(list, entry, index)
        {
          if (entry)
          {
            list.push(obj_ids[index]);
          }
          return list;
        }, []);
        var tag = this._tagman.set_callback(this, this._handle_unpacked_list,
                                            [orig_msg, rt_id, log, callback]);
        this._edservice.requestExamineObjects(tag, [rt_id, unpack]);
      }
      else
      {
        callback();
      }
    }
  }

  this._handle_unpacked_list = function(status, msg, orig_msg, rt_id, log, callback)
  {
    const OBJECT_CHAIN_LIST = 0, VALUE_LIST = 2, DF_INTERN_TYPE = 3;
    if (status || !msg[OBJECT_CHAIN_LIST])
    {
      opera.postError(ui_strings.DRAGONFLY_INFO_MESSAGE +
                      " ExamineObjects failed in _handle_unpacked_list in ListUnpacker");
    }
    else
    {
      var object_list =
        (msg[OBJECT_CHAIN_LIST]).map(this._examine_objects_to_value_list, this);
      var orig_value_list = orig_msg[VALUE_LIST];
      orig_msg[VALUE_LIST] = log.reduce(function(list, log_entry, index)
      {
        if (log_entry)
        {
          var unpack_header = orig_value_list[index];
          unpack_header[DF_INTERN_TYPE] = "unpack-header";
          list.push(unpack_header);
          list.push.apply(list, object_list.shift());
          list.push(["", null, 0, "unpack-footer"]);
        }
        else
        {
          list.push(orig_value_list[index]);
        }
        return list;
      }, []);
    }
    callback();
  }

  this._examine_objects_to_value_list = function(object_chain)
  {
    const
    // message ExamineObjects
    OBJECT_LIST = 0,
    // sub message ObjectInfo
    VALUE = 0, PROPERTY_LIST = 1,
    // sub message ObjectValue
    CLASS_NAME = 4,
    // sub message Property
    NAME = 0, PROPERTY_TYPE = 1, PROPERTY_VALUE = 2, OBJECT_VALUE = 3;

    var value_list = [];
    var object = object_chain[OBJECT_LIST] && object_chain[OBJECT_LIST][0];
    if (object && object[PROPERTY_LIST])
    {
      value_list = (object[PROPERTY_LIST]).reduce(function(list, prop)
      {
        if (prop[NAME].isdigit())
        {
          if (prop[PROPERTY_TYPE] == 'object')
          {
            list.push([null, prop[OBJECT_VALUE], parseInt(prop[NAME])]);
          }
          else
          {
            if (prop[PROPERTY_TYPE] == "string")
            {
              prop[PROPERTY_VALUE] = "\"" + prop[PROPERTY_VALUE] + "\"";
            }
            list.push([prop[PROPERTY_VALUE] || prop[PROPERTY_TYPE],
                      null, parseInt(prop[NAME])]);
          }
        }
        return list;
      }, []);
      value_list.sort(function(a, b)
      {
        return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
      });
    }
    return value_list;
  };

  this.init = function(repl_service)
  {
    this._repl_service = repl_service;
    this._tagman = window.tagManager;
    this._edservice = window.services["ecmascript-debugger"];
    this._is_list_alike_to_string = "(" +
                                    this._is_list_alike.toString() +
                                    ")([%s])";
  };

  this.init(repl_service);

};
<commit_msg>Separated callback in a error and success callback.<commit_after>window.cls || (window.cls = {});

window.cls.ListUnpacker = function()
{

  this.unpack_list_alikes = function(msg, rt_id, error_callback, success_callback)
  {
    const VALUE_LIST = 2, OBJECT_VALUE = 1, OBJECT_ID = 0;
    var value_list = msg[VALUE_LIST];
    var obj_ids = [];
    var call_list = [];
    var arg_list = [];
    for (var i = 0, obj_id, obj_id_str, value; value = value_list[i]; i++)
    {
      obj_id = value[OBJECT_VALUE] && value[OBJECT_VALUE][OBJECT_ID] || 0;
      obj_id_str = obj_id && "$_" + obj_id || "null";
      obj_ids.push(obj_id);
      call_list.push(obj_id_str);
      if (obj_id)
      {
        arg_list.push([obj_id_str, obj_id]);
      }
    };
    var tag = this._tagman.set_callback(this, this._handle_list_alikes_list,
                                        [msg, rt_id, obj_ids,
                                         error_callback, success_callback]);
    var script = this._is_list_alike_to_string.replace("%s", call_list.join(','));
    var msg = [rt_id, 0, 0, script, arg_list];
    this._edservice.requestEval(tag, msg);
  }

  // Boolean(document.all) === false
  this._is_list_alike = function(list)
  {
    return list.map(function(item)
    {
      var _class = item === null ? "" : Object.prototype.toString.call(item);
      if (/(?:Array|Collection|List|Map)\]$/.test(_class))
      {
        return 2;
      }
      if (_class == "[object Object]" && typeof item.length == "number")
      {
        return 1;
      }
      return 0;
    }).join(',');
  };

  this._handle_list_alikes_list = function(status, msg, orig_msg,
                                           rt_id, obj_ids,
                                           error_callback, success_callback)
  {
    const STATUS = 0, VALUE = 2;
    if (status || msg[STATUS] != "completed")
    {
      error_callback();
    }
    else
    {
      var log = msg[VALUE].split(',').map(Number);
      if (log.filter(Boolean).length)
      {
        var unpack = log.reduce(function(list, entry, index)
        {
          if (entry)
          {
            list.push(obj_ids[index]);
          }
          return list;
        }, []);
        var tag = this._tagman.set_callback(this, this._handle_unpacked_list,
                                            [orig_msg, rt_id, log,
                                             error_callback, success_callback]);
        this._edservice.requestExamineObjects(tag, [rt_id, unpack]);
      }
      else
      {
        error_callback();
      }
    }
  }

  this._handle_unpacked_list = function(status, msg, orig_msg, rt_id, log,
                                        error_callback, success_callback)
  {
    const OBJECT_CHAIN_LIST = 0, VALUE_LIST = 2, DF_INTERN_TYPE = 3;
    if (status || !msg[OBJECT_CHAIN_LIST])
    {
      opera.postError(ui_strings.DRAGONFLY_INFO_MESSAGE +
                      " ExamineObjects failed in _handle_unpacked_list in ListUnpacker");
      error_callback();
    }
    else
    {
      var object_list =
        (msg[OBJECT_CHAIN_LIST]).map(this._examine_objects_to_value_list, this);
      var orig_value_list = orig_msg[VALUE_LIST];
      orig_msg[VALUE_LIST] = log.reduce(function(list, log_entry, index)
      {
        if (log_entry)
        {
          var unpack_header = orig_value_list[index];
          unpack_header[DF_INTERN_TYPE] = "unpack-header";
          list.push(unpack_header);
          list.push.apply(list, object_list.shift());
          list.push(["", null, 0, "unpack-footer"]);
        }
        else
        {
          list.push(orig_value_list[index]);
        }
        return list;
      }, []);
      success_callback();
    }

  }

  this._examine_objects_to_value_list = function(object_chain)
  {
    const
    // message ExamineObjects
    OBJECT_LIST = 0,
    // sub message ObjectInfo
    VALUE = 0, PROPERTY_LIST = 1,
    // sub message ObjectValue
    CLASS_NAME = 4,
    // sub message Property
    NAME = 0, PROPERTY_TYPE = 1, PROPERTY_VALUE = 2, OBJECT_VALUE = 3;

    var value_list = [];
    var object = object_chain[OBJECT_LIST] && object_chain[OBJECT_LIST][0];
    if (object && object[PROPERTY_LIST])
    {
      value_list = (object[PROPERTY_LIST]).reduce(function(list, prop)
      {
        if (prop[NAME].isdigit())
        {
          if (prop[PROPERTY_TYPE] == 'object')
          {
            list.push([null, prop[OBJECT_VALUE], parseInt(prop[NAME])]);
          }
          else
          {
            if (prop[PROPERTY_TYPE] == "string")
            {
              prop[PROPERTY_VALUE] = "\"" + prop[PROPERTY_VALUE] + "\"";
            }
            list.push([prop[PROPERTY_VALUE] || prop[PROPERTY_TYPE],
                      null, parseInt(prop[NAME])]);
          }
        }
        return list;
      }, []);
      value_list.sort(function(a, b)
      {
        return a[2] < b[2] ? -1 : a[2] > b[2] ? 1 : 0;
      });
    }
    return value_list;
  };

  this.init = function()
  {
    this._tagman = window.tagManager;
    this._edservice = window.services["ecmascript-debugger"];
    this._is_list_alike_to_string =
      "(" + this._is_list_alike.toString() + ")([%s])";
  };

  this.init();

};
<|endoftext|>


<commit_before>'use strict';

const join = require('path').join;
const ProfileRunner = require(join(__appRoot, 'src/profile-runner'));
const VERBOSITY = require(join(__appRoot, 'src/support/verbosity'));
const chalk = require('chalk');

class Reporter {
  /**
  * @param {TestRunner} testRunner The test runner
  * @param {number} verbosity The verbosity level
  */
  constructor(testRunner, verbosity) {
    this.verbosity = verbosity;
    testRunner.on(ProfileRunner.START, (profiles) => {
      console.info(`Executing ${profiles.length} profile${profiles.length === 1 ? '' : 's'}.\n`);
    });

    testRunner.on(ProfileRunner.END, (profiles) => {
      console.log(`Finished ${profiles.length} profiles.`);
    });

    testRunner.on(ProfileRunner.PROFILE_START, (profile) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.info(`${profile.description()}`);
      }
    });

    testRunner.on(ProfileRunner.PROFILE_END, (profile, result) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        const best = result.testResults
          .sort((a, b) => a.averageTime - b.averageTime)[0];
        console.info(chalk.green(`  Winner: "${best.func.description()}" (${best.averageTime.toFixed(3)}ms)\n`));
      }
    });

    testRunner.on(ProfileRunner.TEST_START, (profile, func) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.log(chalk.green(`  ${func.description()}`));
      }
    });

    testRunner.on(ProfileRunner.TEST_END, (profile, func, result) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.info(`    ${result.averageTime.toFixed(3)}ms`);
        console.info();
      }
    });

    testRunner.on(ProfileRunner.ERROR, (err) => {
      console.error(err.stack);
    });
  }
}

module.exports = Reporter;
<commit_msg>Fix naming<commit_after>'use strict';

const join = require('path').join;
const ProfileRunner = require(join(__appRoot, 'src/profile-runner'));
const VERBOSITY = require(join(__appRoot, 'src/support/verbosity'));
const chalk = require('chalk');

class Reporter {
  /**
  * @param {ProfileRunner} profileRunner The test runner
  * @param {number} verbosity The verbosity level
  */
  constructor(profileRunner, verbosity) {
    this.verbosity = verbosity;
    profileRunner.on(ProfileRunner.START, (profiles) => {
      console.info(`Executing ${profiles.length} profile${profiles.length === 1 ? '' : 's'}.\n`);
    });

    profileRunner.on(ProfileRunner.END, (profiles) => {
      console.log(`Finished ${profiles.length} profiles.`);
    });

    profileRunner.on(ProfileRunner.PROFILE_START, (profile) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.info(`${profile.description()}`);
      }
    });

    profileRunner.on(ProfileRunner.PROFILE_END, (profile, result) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        const best = result.testResults
          .sort((a, b) => a.averageTime - b.averageTime)[0];
        console.info(chalk.green(`  Winner: "${best.func.description()}" (${best.averageTime.toFixed(3)}ms)\n`));
      }
    });

    profileRunner.on(ProfileRunner.TEST_START, (profile, func) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.log(chalk.green(`  ${func.description()}`));
      }
    });

    profileRunner.on(ProfileRunner.TEST_END, (profile, func, result) => {
      if (this.verbosity >= VERBOSITY.NORMAL) {
        console.info(`    ${result.averageTime.toFixed(3)}ms`);
        console.info();
      }
    });

    profileRunner.on(ProfileRunner.ERROR, (err) => {
      console.error(err.stack);
    });
  }
}

module.exports = Reporter;
<|endoftext|>


<commit_before>/*!
 * QUnit CLI Boilerplate v1.3.0
 * Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
 * Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
 * Available under MIT license <http://mths.be/mit>
 */
;(function(window) {
  'use strict';

  /** Detect free variable `exports` */
  var freeExports = typeof exports == 'object' && exports;

  /** Detect free variable `global` and use it as `window` */
  var freeGlobal = typeof global == 'object' && global;
  if (freeGlobal.global === freeGlobal) {
    window = freeGlobal;
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Installs the CLI boilerplate additions on the given `context` object.
   *
   * @memberOf exports
   * @param {Object} context The context object.
   */
  function runInContext(context) {
    // exit early if no `context` is provided or if `QUnit` does not exist
    if (!context || !context.QUnit) {
      return;
    }

    /**
     * Schedules timer-based callbacks.
     *
     * @private
     * @param {Function|String} fn The function to call.
     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
     * @returns {Number} The the ID of the timeout.
     */
    function schedule(fn, delay, args, repeated) {
      // Rhino 1.7RC4 will error assigning `task` below
      // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
      var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
        'run': function() {
          fn.apply(context, args);
        }
      });
      // support non-functions
      if (typeof fn != 'function') {
        fn = (function(code) {
          code = String(code);
          return function() { eval(code); };
        }(fn));
      }
      // used by setInterval
      if (repeated) {
        timer.schedule(task, delay, delay);
      }
      // used by setTimeout
      else {
        timer.schedule(task, delay);
      }
      return counter;
    }

    /**
     * Clears the delay set by `setInterval` or `setTimeout`.
     *
     * @memberOf context
     * @param {Number} id The ID of the timeout to be cleared.
     */
    function clearTimer(id) {
      if (ids[id]) {
        ids[id].cancel();
        timer.purge();
        delete ids[id];
      }
    }

    /**
     * Executes a code snippet or function repeatedly, with a delay between each call.
     *
     * @memberOf context
     * @param {Function|String} fn The function to call or string to evaluate.
     * @oaram {Number} delay The number of milliseconds to delay each `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @returns {Number} The the ID of the timeout.
     */
    function setInterval(fn, delay) {
      return schedule(fn, delay, slice.call(arguments, 2), true);
    }

    /**
     * Executes a code snippet or a function after specified delay.
     *
     * @memberOf context
     * @param {Function|String} fn The function to call or string to evaluate.
     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @returns {Number} The the ID of the timeout.
     */
    function setTimeout(fn, delay) {
      return schedule(fn, delay, slice.call(arguments, 2));
    }

    /*------------------------------------------------------------------------*/

    /** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
    var console = context.console || (context.console = { 'log': context.print });

    /** Shorten `context.QUnit.QUnit` to `context.QUnit` */
    var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit;

    /** Used as a horizontal rule in console output */
    var hr = '----------------------------------------';

    /**
     * A logging callback triggered when all testing is completed.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`.
     */
    QUnit.done(function() {
      var ran;
      return function(details) {
        // stop `asyncTest()` from erroneously calling `done()` twice in
        // environments w/o timeouts
        if (ran) {
          return;
        }
        ran = true;

        console.log(hr);
        console.log('    PASS: ' + details.passed + '  FAIL: ' + details.failed + '  TOTAL: ' + details.total);
        console.log('    Finished in ' + details.runtime + ' milliseconds.');
        console.log(hr);

        // exit out of Narhwal, Rhino, or Ringo
        try {
          quit();
        } catch(e) { }

        // exit out of Node.js or PhantomJS
        try {
          var process = context.process || context.phantom;
          if (details.failed) {
            console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
            process.exit(1);
          } else {
            process.exit(0);
          }
        } catch(e) { }
      };
    }());

    /**
     * A logging callback triggered after every assertion.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`.
     */
    QUnit.log(function(details) {
      var expected = details.expected,
          result = details.result,
          type = typeof expected != 'undefined' ? 'EQ' : 'OK';

      var assertion = [
        result ? 'PASS' : 'FAIL',
        type,
        details.message || 'ok'
      ];

      if (!result && type == 'EQ') {
        assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
      }
      QUnit.config.testStats.assertions.push(assertion.join(' | '));
    });

    /**
     * A logging callback triggered at the start of every test module.
     *
     * @memberOf QUnit
     * @param {Object} details An object with property `name`.
     */
    QUnit.moduleStart(function(details) {
      console.log(hr);
      console.log(details.name);
      console.log(hr);
    });

    /**
     * Converts an object into a string representation.
     *
     * @memberOf QUnit
     * @type Function
     * @param {Object} object The object to stringify.
     * @returns {String} The result string.
     */
    QUnit.jsDump.parsers.object = (function() {
      var func = QUnit.jsDump.parsers.object;
      return function(object) {
        // fork to support Rhino's error objects
        if (typeof object.rhinoException == 'object') {
          return object.name +
            ' { message: "' + object.message +
            '", fileName: "' + object.fileName +
            '", lineNumber: ' + object.lineNumber + ' }';
        }
        return func(object);
      };
    }());

    /**
     * A logging callback triggered after a test is completed.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`.
     */
    QUnit.testDone(function(details) {
      var assertions = QUnit.config.testStats.assertions,
          testName = details.name;

      if (details.failed > 0) {
        console.log(' FAIL - '+ testName);
        assertions.forEach(function(value) {
          console.log('    ' + value);
        });
      }
      else {
        console.log(' PASS - ' + testName);
      }
      assertions.length = 0;
    });

    /**
     * An object used to hold information about the current running test.
     *
     * @memberOf QUnit.config
     * @type Object
     */
    QUnit.config.testStats = {

      /**
       * An array of test summaries (pipe separated).
       *
       * @memberOf QUnit.config.testStats
       * @type Array
       */
      'assertions': []
    };

    /*------------------------------------------------------------------------*/

    // Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
    // https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
    // http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
    try {
      var counter = 0,
          ids = {},
          slice = Array.prototype.slice,
          timer = new java.util.Timer;

      context.clearInterval =
      context.clearTimeout = clearTimer;
      context.setInterval = setInterval;
      context.setTimeout = setTimeout;
    } catch(e) { }

    // expose shortcuts
    // exclude `module` because some environments have it as a built-in object
    ('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
     'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
      context[methodName] = QUnit[methodName];
    });

    // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
    // Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
    QUnit.init();
  }

  /*--------------------------------------------------------------------------*/

  // expose QUnit CLIB
  if (freeExports) {
    freeExports.runInContext = runInContext;
  } else {
    runInContext(window);
  }
}(this));
<commit_msg>Avoid issues with Browserify.<commit_after>/*!
 * QUnit CLI Boilerplate v1.3.0
 * Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
 * Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
 * Available under MIT license <http://mths.be/mit>
 */
;(function(window) {
  'use strict';

  /** Detect free variable `exports` */
  var freeExports = typeof exports == 'object' && exports;

  /** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */
  var freeGlobal = typeof global == 'object' && global;
  if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
    window = freeGlobal;
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Installs the CLI boilerplate additions on the given `context` object.
   *
   * @memberOf exports
   * @param {Object} context The context object.
   */
  function runInContext(context) {
    // exit early if no `context` is provided or if `QUnit` does not exist
    if (!context || !context.QUnit) {
      return;
    }

    /**
     * Schedules timer-based callbacks.
     *
     * @private
     * @param {Function|String} fn The function to call.
     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
     * @returns {Number} The the ID of the timeout.
     */
    function schedule(fn, delay, args, repeated) {
      // Rhino 1.7RC4 will error assigning `task` below
      // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
      var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
        'run': function() {
          fn.apply(context, args);
        }
      });
      // support non-functions
      if (typeof fn != 'function') {
        fn = (function(code) {
          code = String(code);
          return function() { eval(code); };
        }(fn));
      }
      // used by setInterval
      if (repeated) {
        timer.schedule(task, delay, delay);
      }
      // used by setTimeout
      else {
        timer.schedule(task, delay);
      }
      return counter;
    }

    /**
     * Clears the delay set by `setInterval` or `setTimeout`.
     *
     * @memberOf context
     * @param {Number} id The ID of the timeout to be cleared.
     */
    function clearTimer(id) {
      if (ids[id]) {
        ids[id].cancel();
        timer.purge();
        delete ids[id];
      }
    }

    /**
     * Executes a code snippet or function repeatedly, with a delay between each call.
     *
     * @memberOf context
     * @param {Function|String} fn The function to call or string to evaluate.
     * @oaram {Number} delay The number of milliseconds to delay each `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @returns {Number} The the ID of the timeout.
     */
    function setInterval(fn, delay) {
      return schedule(fn, delay, slice.call(arguments, 2), true);
    }

    /**
     * Executes a code snippet or a function after specified delay.
     *
     * @memberOf context
     * @param {Function|String} fn The function to call or string to evaluate.
     * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
     * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
     * @returns {Number} The the ID of the timeout.
     */
    function setTimeout(fn, delay) {
      return schedule(fn, delay, slice.call(arguments, 2));
    }

    /*------------------------------------------------------------------------*/

    /** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
    var console = context.console || (context.console = { 'log': context.print });

    /** Shorten `context.QUnit.QUnit` to `context.QUnit` */
    var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit;

    /** Used as a horizontal rule in console output */
    var hr = '----------------------------------------';

    /**
     * A logging callback triggered when all testing is completed.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`.
     */
    QUnit.done(function() {
      var ran;
      return function(details) {
        // stop `asyncTest()` from erroneously calling `done()` twice in
        // environments w/o timeouts
        if (ran) {
          return;
        }
        ran = true;

        console.log(hr);
        console.log('    PASS: ' + details.passed + '  FAIL: ' + details.failed + '  TOTAL: ' + details.total);
        console.log('    Finished in ' + details.runtime + ' milliseconds.');
        console.log(hr);

        // exit out of Narhwal, Rhino, or Ringo
        try {
          quit();
        } catch(e) { }

        // exit out of Node.js or PhantomJS
        try {
          var process = context.process || context.phantom;
          if (details.failed) {
            console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
            process.exit(1);
          } else {
            process.exit(0);
          }
        } catch(e) { }
      };
    }());

    /**
     * A logging callback triggered after every assertion.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`.
     */
    QUnit.log(function(details) {
      var expected = details.expected,
          result = details.result,
          type = typeof expected != 'undefined' ? 'EQ' : 'OK';

      var assertion = [
        result ? 'PASS' : 'FAIL',
        type,
        details.message || 'ok'
      ];

      if (!result && type == 'EQ') {
        assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
      }
      QUnit.config.testStats.assertions.push(assertion.join(' | '));
    });

    /**
     * A logging callback triggered at the start of every test module.
     *
     * @memberOf QUnit
     * @param {Object} details An object with property `name`.
     */
    QUnit.moduleStart(function(details) {
      console.log(hr);
      console.log(details.name);
      console.log(hr);
    });

    /**
     * Converts an object into a string representation.
     *
     * @memberOf QUnit
     * @type Function
     * @param {Object} object The object to stringify.
     * @returns {String} The result string.
     */
    QUnit.jsDump.parsers.object = (function() {
      var func = QUnit.jsDump.parsers.object;
      return function(object) {
        // fork to support Rhino's error objects
        if (typeof object.rhinoException == 'object') {
          return object.name +
            ' { message: "' + object.message +
            '", fileName: "' + object.fileName +
            '", lineNumber: ' + object.lineNumber + ' }';
        }
        return func(object);
      };
    }());

    /**
     * A logging callback triggered after a test is completed.
     *
     * @memberOf QUnit
     * @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`.
     */
    QUnit.testDone(function(details) {
      var assertions = QUnit.config.testStats.assertions,
          testName = details.name;

      if (details.failed > 0) {
        console.log(' FAIL - '+ testName);
        assertions.forEach(function(value) {
          console.log('    ' + value);
        });
      }
      else {
        console.log(' PASS - ' + testName);
      }
      assertions.length = 0;
    });

    /**
     * An object used to hold information about the current running test.
     *
     * @memberOf QUnit.config
     * @type Object
     */
    QUnit.config.testStats = {

      /**
       * An array of test summaries (pipe separated).
       *
       * @memberOf QUnit.config.testStats
       * @type Array
       */
      'assertions': []
    };

    /*------------------------------------------------------------------------*/

    // Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
    // https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
    // http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
    try {
      var counter = 0,
          ids = {},
          slice = Array.prototype.slice,
          timer = new java.util.Timer;

      context.clearInterval =
      context.clearTimeout = clearTimer;
      context.setInterval = setInterval;
      context.setTimeout = setTimeout;
    } catch(e) { }

    // expose shortcuts
    // exclude `module` because some environments have it as a built-in object
    ('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
     'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
      context[methodName] = QUnit[methodName];
    });

    // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
    // Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
    QUnit.init();
  }

  /*--------------------------------------------------------------------------*/

  // expose QUnit CLIB
  if (freeExports) {
    freeExports.runInContext = runInContext;
  } else {
    runInContext(window);
  }
}(this));
<|endoftext|>


<commit_before>import React from "react";
import {qnfetch, apiURL} from "assets/utils/request";
import moment from "moment";
import AppBar from "material-ui/AppBar";
import {List, ListItem} from "material-ui/List";
import ContentDrafts from "material-ui/svg-icons/content/drafts";
import ContentAdd from "material-ui/svg-icons/content/add";
import FloatingActionButton from "material-ui/FloatingActionButton";
import FlatButton from "material-ui/FlatButton";
import Dialog from "material-ui/Dialog";
import TextField from "material-ui/TextField";
import "./home.less";

class Home extends React.Component {
  constructor () {
    super();
    this.state = {
      isFetching: false,
      list: [],
      nextURL: '',
      dialogOpen: false
    }
  }

  componentWillMount () {
    this.fetchData();
  }

  componentDidMount () {
    let that = this;

    this.refs['list'].addEventListener('touchmove', function (e) {
      e.stopPropagation()
      var clientH = document.documentElement.clientHeight
      var scrollTop = document.body.scrollTop
      var scrollH = document.body.scrollHeight

      // 防止重复拉取
      if (that.state.isFetching) {
        return;
      }

      if (clientH + scrollTop >= scrollH) {
        if (that.state.nextURL) {

          that.setState({
            ...that.state,
            isFetching:true
          })

          qnfetch(that.state.nextURL)
            .then(res => res.json())
            .then(data => {
              const list = data.results;
              that.setState({
                ...that.state,
                list: [...that.state.list,...list],
                nextURL: data.next,
                isFetching:false
              })
            })
            .catch(err => console.log(err))
        }
      }
    }, false)
  }

  fetchData = () => {
    let that = this;
    qnfetch(apiURL.Get_Message_list)
      .then(res => res.json())
      .then(data => {
        const list = data.results;
        const nextURL = data.next;
        that.setState({list, nextURL})
      })
      .catch(err => console.log(err))

  }

  handleOpen = () => {
    this.setState({
      ...this.state,
      dialogOpen: true
    })
  }
  handleClose = () => {
    this.setState({
      ...this.state,
      dialogOpen: false
    })
  }

  handleSend = () => {
    const content = document.getElementById('contentText').value;
    const params = {content}

    qnfetch(apiURL.Post_Message, params, 'POST')
      .then(res => res.json())
      .then(data => {
        this.setState({
          ...this.state,
          list: this.state.list.push(data),
          dialogOpen: false
        })
      })
      .catch(err => console.log(err))
  }

  render () {
    const list = this.state.list || [];

    const actions = [
      <FlatButton
        label="取消"
        primary={true}
        onTouchTap={this.handleClose}
      />,
      <FlatButton
        label="发送"
        primary={true}
        keyboardFocused={true}
        onTouchTap={this.handleSend}
      />,
    ];

    return (

          <AppBar
            title="POST MAN"
            iconClassNameRight="muidocs-icon-navigation-expand-more"
          />

          <List>
            {list.length > 0 && list.map((i, index) =>
              <ListItem primaryText={i.content} secondaryText={i.time && moment.unix(i.time).fromNow()}
                        leftIcon={<ContentDrafts />} key={index}/>
            )}
          </List>

        <FloatingActionButton secondary={true} className="floating-button" onTouchTap={this.handleOpen}>
          <ContentAdd />
        </FloatingActionButton>

        <Dialog
          actions={actions}
          modal={false}
          open={this.state.dialogOpen}
          onRequestClose={this.handleClose}
        >
          <TextField
            hintText="尽情吐槽吧"
            floatingLabelText="你的留言"
            multiLine={true}
            rows={2}
            id="contentText"
          />
        </Dialog>

    )
  }
}
;

export default Home
<commit_msg>留言bug解决<commit_after>import React from "react";
import {qnfetch, apiURL} from "assets/utils/request";
import moment from "moment";
import AppBar from "material-ui/AppBar";
import {List, ListItem} from "material-ui/List";
import ContentDrafts from "material-ui/svg-icons/content/drafts";
import ContentAdd from "material-ui/svg-icons/content/add";
import FloatingActionButton from "material-ui/FloatingActionButton";
import FlatButton from "material-ui/FlatButton";
import Dialog from "material-ui/Dialog";
import TextField from "material-ui/TextField";
import "./home.less";

class Home extends React.Component {
  constructor () {
    super();
    this.state = {
      isFetching: false,
      list: [],
      nextURL: '',
      dialogOpen: false
    }
  }

  componentWillMount () {
    this.fetchData();
  }

  componentDidMount () {
    let that = this;

    this.refs['list'].addEventListener('touchmove', function (e) {
      e.stopPropagation()
      var clientH = document.documentElement.clientHeight
      var scrollTop = document.body.scrollTop
      var scrollH = document.body.scrollHeight

      // 防止重复拉取
      if (that.state.isFetching) {
        return;
      }

      if (clientH + scrollTop >= scrollH) {
        if (that.state.nextURL) {

          that.setState({
            ...that.state,
            isFetching:true
          })

          qnfetch(that.state.nextURL)
            .then(res => res.json())
            .then(data => {
              const list = data.results;
              that.setState({
                ...that.state,
                list: [...that.state.list,...list],
                nextURL: data.next,
                isFetching:false
              })
            })
            .catch(err => console.log(err))
        }
      }
    }, false)
  }

  fetchData = () => {
    let that = this;
    qnfetch(apiURL.Get_Message_list)
      .then(res => res.json())
      .then(data => {
        const list = data.results;
        const nextURL = data.next;
        that.setState({list, nextURL})
      })
      .catch(err => console.log(err))

  }

  handleOpen = () => {
    this.setState({
      ...this.state,
      dialogOpen: true
    })
  }
  handleClose = () => {
    this.setState({
      ...this.state,
      dialogOpen: false
    })
  }

  handleSend = () => {
    const content = document.getElementById('contentText').value
    const params = {content}
    const that = this
    qnfetch(apiURL.Post_Message, params, 'POST')
      .then(res => res.json())
      .then(data => {
        that.setState({
          ...that.state,
          list: [data, ...that.state.list],
          dialogOpen: false
        })
      })
      .catch(err => console.log(err))
  }

  render () {
    const list = this.state.list || [];

    const actions = [
      <FlatButton
        label="取消"
        primary={true}
        onTouchTap={this.handleClose}
      />,
      <FlatButton
        label="发送"
        primary={true}
        keyboardFocused={true}
        onTouchTap={this.handleSend}
      />,
    ];

    return (

          <AppBar
            title="POST MAN"
            iconClassNameRight="muidocs-icon-navigation-expand-more"
          />

          <List>
            {list.length > 0 && list.map((i, index) =>
              <ListItem primaryText={i.content} secondaryText={moment.unix(i.time).fromNow()}
                        leftIcon={<ContentDrafts />} key={index}/>
            )}
          </List>

        <FloatingActionButton secondary={true} className="floating-button" onTouchTap={this.handleOpen}>
          <ContentAdd />
        </FloatingActionButton>

        <Dialog
          actions={actions}
          modal={false}
          open={this.state.dialogOpen}
          onRequestClose={this.handleClose}
        >
          <TextField
            hintText="尽情吐槽吧"
            floatingLabelText="你的留言"
            multiLine={true}
            rows={2}
            id="contentText"
          />
        </Dialog>

    )
  }
}
;

export default Home
<|endoftext|>


<commit_before>/**
 * Created by paulparsons on 1/27/15.
 */

(function() {

	var angularChromosomeVis = angular.module('angularChromosomeVis', []);

	/**
	 * service that retrieves DAS model
	 */
	angularChromosomeVis.factory('dasLoader', function() {
		return {
			loadModel: function (segment, assembly) {
				return JSDAS.Simple.getClient("http://www.ensembl.org/das/Homo_sapiens.GRCh" + assembly + ".karyotype");
			}
		}
	});

	/**
	 * service that maintains an array of selectors. can be injected into any controller, directive, etc.
	 */
	angularChromosomeVis.factory('chrSelectors', ['$rootScope', function($rootScope) {
		"use strict";
		var selectors = []; //holds a list of all selectors that are input by the user

		return {
			getSelectors: function () {
				return selectors;
			},
			addSelector: function (selector) {
				selectors.push(selector);
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
			},
			deleteSelector: function (selector) {
				selectors = _.without(selectors, selector);
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
			},
			deleteAll: function () {
				selectors = [];
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
				$rootScope.$broadcast('selectors:deleted');
			}
		};
	}])

	angularChromosomeVis.directive('chromosome', ['dasLoader', 'chrSelectors', function(dasLoader, chrSelectors) {

		function link(scope, element, attr) {

			var dasModel;
			scope.selectors = { list: [] }; //holds selector objects

			var CHR1_BP_END = 248956422,
				STALK_MAG_PC = 0.8,
				PADDING = 30,
				LABEL_PADDING = 24,
				AXIS_SPACING = 4,
				STALK_SPACING = 3;

			var target = d3.select(element[0]).append('svg');
			target.attr('id', scope.id + 'svg'); //take id from the scope
			target.attr({width: '100%'});

			if (scope.axis) {
				target.attr({height: scope.height + (2 * PADDING)});
			} else {
				target.attr({height: scope.height + PADDING});
			}
			dasLoader.loadModel(scope.chr, scope.assembly)
				.features({segment: scope.chr}, function (res) {
					//success response
					if (res.GFF.SEGMENT.length > 0) {
						dasModel = {
							id: res.GFF.SEGMENT[0].id,
							start: res.GFF.SEGMENT[0].start,
							stop: res.GFF.SEGMENT[0].stop,
							bands: res.GFF.SEGMENT[0].FEATURE
						};
					} else {
						console.log("JSDAS results empty for segment");
					}

					if (typeof dasModel.err === 'undefined') {

						var rangeTo;

						if (scope.width === 'inherit') {
							var svgWidth = target[0][0].width.baseVal.value;
							rangeTo = scope.relSize ? ((+dasModel.stop / CHR1_BP_END) * svgWidth) - PADDING : svgWidth - PADDING;
						}
						else {
							rangeTo = scope.relSize ? ((+dasModel.stop / CHR1_BP_END) * scope.width) - PADDING : scope.width - PADDING;
						}

						var xscale = d3.scale.linear()
							.domain([dasModel.start, dasModel.stop])
							.range([0, rangeTo]);

						var band = target.selectAll("chromosome" + " g")
							.data(dasModel.bands)
							.enter().append("g");

						band.append("title")
							.text(function(m) {return m.id; });

						band.append('rect')
							.attr('class', function (m) {
								return m.TYPE.id.replace(':', ' ');
							})
							.attr('height', function (m) {
								return (m.TYPE.id === "band:stalk") ? (scope.height * STALK_MAG_PC) : scope.height;
							})
							.attr('width', function (m) {
								return xscale(+m.END.textContent) - xscale(+m.START.textContent);
							})
							.attr('x', function (m) {
								return xscale(m.START.textContent);
							})
							.attr('y', function (m) {
								return (m.TYPE.id === "band:stalk") ? (PADDING + STALK_SPACING) : PADDING;
							});

						var label = target.append("text")
							.attr("class", "band-lbl")
							.attr("y", LABEL_PADDING);

						band.on("mouseover", function (m) {
							label.text(m.id)
								.attr('x', (xscale(m.START.textContent)));
						});

						band.on("mouseout", function (m) {
							label.text(''); //empty the label
						});

						band.on("click", function (m) {
							var start = +m.START.textContent,
								end = +m.END.textContent;

							if (scope.mode === 'multi' || (scope.mode === "single" && scope.selectors.list.length == 0)) {
								var newSel = newSelector(scope, xscale, start, end, (PADDING - AXIS_SPACING)).draw(); //create new selector and draw it
								addSelector(newSel);//add new selector to local scope
								chrSelectors.addSelector(newSel); //add new location to the service
							}
						});

						if (scope.axis) {
							var bpAxis = d3.svg.axis()
								.scale(xscale)
								.tickFormat(d3.format('s'))
								.orient("bottom");

							target.append('g')
								.attr('class', 'bp-axis')
								.attr('transform', 'translate(0,' + (scope.height + PADDING + AXIS_SPACING) + ")")
								.call(bpAxis);
						}
					}

				}, function (err) {
					//error response handler
					console.log("Error from DAS loader: " + err);
				});

			function addSelector(sel) {
				"use strict";
				scope.$apply(function() {
					scope.selectors.list.push(sel);
				})
			}

			//when all selectors have been deleted from outside
			scope.$on('selectors:deleted', function(event) {
				angular.forEach (scope.selectors.list, function(sel) {
					"use strict";
					sel.delete();
				});
				scope.selectors.list = []; //delete locally
			});

			scope.delSelector = function(sel) {
				"use strict";
				sel.delete();
				scope.selectors.list = _.without(scope.selectors.list, sel) //delete locally
				chrSelectors.deleteSelector(sel); //delete from the service
			}

			function newSelector(scope, xscale, start, end, yshift) {
				return new Selector({
					scope: scope,
					xscale: xscale,
					y: yshift,
					target: '#' + scope.id + 'svg'
				}).init(start, end);
			};
		}

		/**
		 * selector object for chromosome. uses D3 brush
		 * @param opt - options for the selector
		 * @constructor
		 */
		function Selector (opt) {

			var self = this,
				_selector,
				_initialized;

			var AXIS_SPACING = 4;

			var options = (function () {
				return _.extend({}, {
					//DEFAULT OPTIONS
					height: 20,
					y:9
				}, opt || {});
			}());

			this.delete = function () {
				_selector.remove();
				_initialized = false;
			};

			function triggerSelectionChange () {
				var ext = self.brush.extent();
				self.start = Math.round(ext[0]);
				self.end = Math.round(ext[1]);
			}

			//initialize the selector
			this.init = function (start, end) {
				self.brush = d3.svg.brush()
					.x(options.xscale)
					.extent([start, end]);

				self.start = Math.round(start);
				self.end = Math.round(end);

				self.brush.on("brush", function () {
					triggerSelectionChange();
					options.scope.$apply();
				});

				//uncomment to use
				//self.brush.on("brushend", function () {
				//	//do something here on brush end
				//});

				_selector = d3.select(options.target).append("g")
					.classed('selector', true)
					.attr('transform',"translate(0,"+ options.y +")")
					.call(self.brush);

				_selector.selectAll('rect')
					.attr('height', options.height + (AXIS_SPACING * 2));

				_initialized = true;
				return self;
			};

			this.draw = function () {
				if (!_initialized) self.init();
				_selector.select('.background').remove();
				_selector.call(self.brush);
				return self;
			};

			this.move = function (to, from) {
				self.brush.extent([to, from]);
				var selector = d3.select(options.target + ' .selector');
				selector.call(self.brush);
				return self;
			};

		};

		return {
			link: link,
			restrict: 'AE',
			scope: {
				chr: '@',
				relSize: '=',
				assembly: '=',
				width: '@',
				height: '=',
				axis: '=',
				mode: '@',
				id: '@'
			}
		}
	}]);

})();<commit_msg>add scope defaults<commit_after>/**
 * Created by paulparsons on 1/27/15.
 */

(function() {

	var angularChromosomeVis = angular.module('angularChromosomeVis', []);

	/**
	 * service that retrieves DAS model
	 */
	angularChromosomeVis.factory('dasLoader', function() {
		return {
			loadModel: function (segment, assembly) {
				return JSDAS.Simple.getClient("http://www.ensembl.org/das/Homo_sapiens.GRCh" + assembly + ".karyotype");
			}
		}
	});

	/**
	 * service that maintains an array of selectors. can be injected into any controller, directive, etc.
	 */
	angularChromosomeVis.factory('chrSelectors', ['$rootScope', function($rootScope) {
		"use strict";
		var selectors = []; //holds a list of all selectors that are input by the user

		return {
			getSelectors: function () {
				return selectors;
			},
			addSelector: function (selector) {
				selectors.push(selector);
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
			},
			deleteSelector: function (selector) {
				selectors = _.without(selectors, selector);
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
			},
			deleteAll: function () {
				selectors = [];
				$rootScope.$broadcast('selectors:updated', selectors); //notify listeners and provide the new selectors array
				$rootScope.$broadcast('selectors:deleted');
			}
		};
	}])

	angularChromosomeVis.directive('chromosome', ['dasLoader', 'chrSelectors', function(dasLoader, chrSelectors) {

		function link(scope, element, attr) {

			//set default scope values if not provided
			scope.relSize = angular.isDefined(scope.relSize) ? scope.relSize : true;
			scope.assembly = angular.isDefined(scope.assembly) ? scope.assembly : 37;
			scope.height = angular.isDefined(scope.height) ? scope.height : 20;
			scope.axis = angular.isDefined(scope.axis) ? scope.axis : true;
			scope.mode = angular.isDefined(scope.mode) ? scope.mode : "multi";

			var dasModel;
			scope.selectors = { list: [] }; //holds selector objects

			var CHR1_BP_END = 248956422,
				STALK_MAG_PC = 0.8,
				PADDING = 30,
				LABEL_PADDING = 24,
				AXIS_SPACING = 4,
				STALK_SPACING = 3;

			var target = d3.select(element[0]).append('svg');
			target.attr('id', scope.id + 'svg'); //take id from the scope
			target.attr({width: '100%'});

			if (scope.axis) {
				target.attr({height: scope.height + (2 * PADDING)});
			} else {
				target.attr({height: scope.height + PADDING});
			}
			dasLoader.loadModel(scope.chr, scope.assembly)
				.features({segment: scope.chr}, function (res) {
					//success response
					if (res.GFF.SEGMENT.length > 0) {
						dasModel = {
							id: res.GFF.SEGMENT[0].id,
							start: res.GFF.SEGMENT[0].start,
							stop: res.GFF.SEGMENT[0].stop,
							bands: res.GFF.SEGMENT[0].FEATURE
						};
					} else {
						console.log("JSDAS results empty for segment");
					}

					if (typeof dasModel.err === 'undefined') {

						var rangeTo;

						if (scope.width === 'inherit') {
							var svgWidth = target[0][0].width.baseVal.value;
							rangeTo = scope.relSize ? ((+dasModel.stop / CHR1_BP_END) * svgWidth) - PADDING : svgWidth - PADDING;
						}
						else {
							rangeTo = scope.relSize ? ((+dasModel.stop / CHR1_BP_END) * scope.width) - PADDING : scope.width - PADDING;
						}

						var xscale = d3.scale.linear()
							.domain([dasModel.start, dasModel.stop])
							.range([0, rangeTo]);

						var band = target.selectAll("chromosome" + " g")
							.data(dasModel.bands)
							.enter().append("g");

						band.append("title")
							.text(function(m) {return m.id; });

						band.append('rect')
							.attr('class', function (m) {
								return m.TYPE.id.replace(':', ' ');
							})
							.attr('height', function (m) {
								return (m.TYPE.id === "band:stalk") ? (scope.height * STALK_MAG_PC) : scope.height;
							})
							.attr('width', function (m) {
								return xscale(+m.END.textContent) - xscale(+m.START.textContent);
							})
							.attr('x', function (m) {
								return xscale(m.START.textContent);
							})
							.attr('y', function (m) {
								return (m.TYPE.id === "band:stalk") ? (PADDING + STALK_SPACING) : PADDING;
							});

						var label = target.append("text")
							.attr("class", "band-lbl")
							.attr("y", LABEL_PADDING);

						band.on("mouseover", function (m) {
							label.text(m.id)
								.attr('x', (xscale(m.START.textContent)));
						});

						band.on("mouseout", function (m) {
							label.text(''); //empty the label
						});

						band.on("click", function (m) {
							var start = +m.START.textContent,
								end = +m.END.textContent;

							if (scope.mode === 'multi' || (scope.mode === "single" && scope.selectors.list.length == 0)) {
								var newSel = newSelector(scope, xscale, start, end, (PADDING - AXIS_SPACING)).draw(); //create new selector and draw it
								addSelector(newSel);//add new selector to local scope
								chrSelectors.addSelector(newSel); //add new location to the service
							}
						});

						if (scope.axis) {
							var bpAxis = d3.svg.axis()
								.scale(xscale)
								.tickFormat(d3.format('s'))
								.orient("bottom");

							target.append('g')
								.attr('class', 'bp-axis')
								.attr('transform', 'translate(0,' + (scope.height + PADDING + AXIS_SPACING) + ")")
								.call(bpAxis);
						}
					}

				}, function (err) {
					//error response handler
					console.log("Error from DAS loader: " + err);
				});

			function addSelector(sel) {
				"use strict";
				scope.$apply(function() {
					scope.selectors.list.push(sel);
				})
			}

			//when all selectors have been deleted from outside
			scope.$on('selectors:deleted', function(event) {
				angular.forEach (scope.selectors.list, function(sel) {
					"use strict";
					sel.delete();
				});
				scope.selectors.list = []; //delete locally
			});

			scope.delSelector = function(sel) {
				"use strict";
				sel.delete();
				scope.selectors.list = _.without(scope.selectors.list, sel) //delete locally
				chrSelectors.deleteSelector(sel); //delete from the service
			}

			function newSelector(scope, xscale, start, end, yshift) {
				return new Selector({
					scope: scope,
					xscale: xscale,
					y: yshift,
					target: '#' + scope.id + 'svg'
				}).init(start, end);
			};
		}

		/**
		 * selector object for chromosome. uses D3 brush
		 * @param opt - options for the selector
		 * @constructor
		 */
		function Selector (opt) {

			var self = this,
				_selector,
				_initialized;

			var AXIS_SPACING = 4;

			var options = (function () {
				return _.extend({}, {
					//DEFAULT OPTIONS
					height: 20,
					y:9
				}, opt || {});
			}());

			this.delete = function () {
				_selector.remove();
				_initialized = false;
			};

			function triggerSelectionChange () {
				var ext = self.brush.extent();
				self.start = Math.round(ext[0]);
				self.end = Math.round(ext[1]);
			}

			//initialize the selector
			this.init = function (start, end) {
				self.brush = d3.svg.brush()
					.x(options.xscale)
					.extent([start, end]);

				self.start = Math.round(start);
				self.end = Math.round(end);

				self.brush.on("brush", function () {
					triggerSelectionChange();
					options.scope.$apply();
				});

				//uncomment to use
				//self.brush.on("brushend", function () {
				//	//do something here on brush end
				//});

				_selector = d3.select(options.target).append("g")
					.classed('selector', true)
					.attr('transform',"translate(0,"+ options.y +")")
					.call(self.brush);

				_selector.selectAll('rect')
					.attr('height', options.height + (AXIS_SPACING * 2));

				_initialized = true;
				return self;
			};

			this.draw = function () {
				if (!_initialized) self.init();
				_selector.select('.background').remove();
				_selector.call(self.brush);
				return self;
			};

			this.move = function (to, from) {
				self.brush.extent([to, from]);
				var selector = d3.select(options.target + ' .selector');
				selector.call(self.brush);
				return self;
			};

		};

		return {
			link: link,
			restrict: 'AE',
			scope: {
				chr: '@',
				relSize: '=?',
				assembly: '=?',
				width: '@',
				height: '=?',
				axis: '=?',
				mode: '@',
				id: '@'
			}
		}
	}]);

})();<|endoftext|>


<commit_before>angular.module('apiClient').
	factory('apiClient', function() {

	  	return {
	  		/*
	  		urls: {
	  			auth: 			'http://127.0.0.1:5000/auth',
	  			user: 			'http://127.0.0.1:5000/user',
	  			mjs: 			'http://127.0.0.1:5000/mjs',
	  			wizard_search: 	'http://127.0.0.1:5000/wsearch',
	  			item: 			'http://127.0.0.1:5000/item',
	  			suggest: 		'http://127.0.0.1:5000/suggest',
	  			ftrees_search:	'http://127.0.0.1:5000/fsearch',
	  			ftrees_get: 	'http://127.0.0.1:5000/get_ftree_url',
	  			upload: 		'http://127.0.0.1:5000/upload'
	  		}
	  		*/
	  		urls: {
	  			auth: 			'http://bhsapi.ezdr.net/auth',
	  			user: 			'http://bhsapi.ezdr.net/user',
	  			mjs: 			'http://bhsapi.ezdr.net/mjs',
	  			wizard_search: 	'http://bhsapi.ezdr.net/wsearch',
	  			item: 			'http://bhsapi.ezdr.net/item',
	  			suggest: 		'http://bhsapi.ezdr.net/suggest',
	  			ftrees_search:	'http://bhsapi.ezdr.net/fsearch',
	  			ftrees_get: 	'http://bhsapi.ezdr.net/get_ftree_url',
	  			upload: 		'http://bhsapi.ezdr.net/upload'
	  		}
	  	};
	});
<commit_msg>swith to new production API<commit_after>angular.module('apiClient').
	factory('apiClient', function() {

	  	return {

	  		// urls: {
	  		// 	auth: 			'http://127.0.0.1:5000/auth',
	  		// 	user: 			'http://127.0.0.1:5000/user',
	  		// 	mjs: 			'http://127.0.0.1:5000/mjs',
	  		// 	wizard_search: 	'http://127.0.0.1:5000/wsearch',
	  		// 	item: 			'http://127.0.0.1:5000/item',
	  		// 	suggest: 		'http://127.0.0.1:5000/suggest',
	  		// 	ftrees_search:	'http://127.0.0.1:5000/fsearch',
	  		// 	ftrees_get: 	'http://127.0.0.1:5000/get_ftree_url',
	  		// 	upload: 		'http://127.0.0.1:5000/upload'
	  		// }

	  		urls: {
	  			auth: 			'http://api.myjewishidentity.org/auth',
	  			user: 			'http://api.myjewishidentity.org/user',
	  			mjs: 			'http://api.myjewishidentity.org/mjs',
	  			wizard_search: 	'http://api.myjewishidentity.org/wsearch',
	  			item: 			'http://api.myjewishidentity.org/item',
	  			suggest: 		'http://api.myjewishidentity.org/suggest',
	  			ftrees_search:	'http://api.myjewishidentity.org/fsearch',
	  			ftrees_get: 	'http://api.myjewishidentity.org/get_ftree_url',
	  			upload: 		'http://api.myjewishidentity.org/upload'
	  		}
	  	};
	});
<|endoftext|>