Skip to content

Instantly share code, notes, and snippets.

@mosson
Created January 21, 2016 11:16
Show Gist options
  • Save mosson/07bb8c311cc42d2a695f to your computer and use it in GitHub Desktop.
Save mosson/07bb8c311cc42d2a695f to your computer and use it in GitHub Desktop.
'use strict';
import _ from 'lodash';
import is from 'is_js';
import { parseIntOrNull } from 'services/NumberUtils';
class BaseModel {
static hasMany(name, targetClass, defaultID) {
/* eslint complexity: [0, 6] */
if (!this.prototype[`_get_${name}`]) {
this.prototype[`_get_${name}`] = function (v) {
return this[name];
};
}
if (!this.prototype[`_update_${name}`]) {
this.prototype[`_update_${name}`] = function (v) {
if (!this.state[name]) this.state[name] = {};
_.each(v, (props) => {
let id = props && props.id;
if (!id) return;
if (this.state[name][id]) {
this.state[name][id].update(props);
} else {
this.state[name][id] = new targetClass(props);
}
this.state[name][id]._updatedAt = new Date().getTime();
});
};
}
if (!this.prototype[`_destroy_${name}`]) {
this.prototype[`_destroy_${name}`] = function (v) {
if (!this.state[name]) return [];
_.each(v || [], (props) => {
let id = props && props.id;
if (!id) return;
if (this.state[name][id]) {
this.state[name][id].destroy(props);
if (props._destroyed) delete this.state[name][id];
}
});
};
}
if (!this.prototype[`_${name}_as_json`]) {
this.prototype[`_${name}_as_json`] = function () {
if (!this.state[name]) return [];
return _.map(this.state[name], (model) => {
return model.asJSON();
});
};
}
if (!(name in this.prototype)) {
Object.defineProperty(this.prototype, name, {
key : name,
enumerable : false,
configurable: true,
get : function () {
return _.values(this.state[name]);
}
});
}
}
static hasOne(name, targetClass, defaultID) {
if (!this.prototype[`_get_${name}`]) {
this.prototype[`_get_${name}`] = function (v) {
return this[name];
};
}
if (!this.prototype[`_update_${name}`]) {
this.prototype[`_update_${name}`] = function (v) {
if (this.state[name]) {
this.state[name].update(v);
} else {
this.state[name] = new targetClass(v);
}
this.state[name]._updatedAt = new Date().getTime();
};
}
if (!this.prototype[`_destroy_${name}`]) {
this.prototype[`_destroy_${name}`] = function (v) {
if (this.state[name]) {
this.state[name].destroy(v);
if (v._destroyed) delete this.state[name];
}
};
}
if (!this.prototype[`_${name}_as_json`]) {
this.prototype[`_${name}_as_json`] = function () {
if (this.state[name]) {
return this.state[name].asJSON();
}
};
}
if (!(name in this.prototype)) {
Object.defineProperty(this.prototype, name, {
key : name,
enumerable : false,
configurable: true,
get : function () {
return this.state[name] || new targetClass({id: defaultID});
}
});
}
}
static find(id) {
if (!this._instances) return null;
return this._instances[parseIntOrNull(id)];
}
static isEncode(value) {
return _.any([is.string, is.number, is.boolean, is.date, is.null, is.undefined], (m) => {
return m.call(is, value);
});
}
constructor(state) {
this.state = {};
this.update(state);
if (!this.constructor._instances) this.constructor._instances = {};
this.constructor._instances[this.id] = this;
}
update(state) {
_.each(state || {}, (value, key) => {
if (this[`_update_${key}`]) {
this[`_update_${key}`](value);
} else {
this.state[key] = value;
}
});
}
destroy(state) {
_.each(state || {}, (value, key) => {
if (this[`_destroy_${key}`]) {
this[`_destroy_${key}`](value);
}
});
}
toObject() {
return _.object(_.map(_.keys(this.state), (key) => {
if (this[`_get_${key}`]) {
return [key, this[`_get_${key}`]()];
} else {
return [key, this.state[key]];
}
}));
}
asJSON() {
let dict = _.map(this.state, (value, key) => {
if (this[`_${key}_as_json`]) {
return [key, this[`_${key}_as_json`]()];
} else {
if (BaseModel.isEncode(value))
return [key, value];
}
});
return _.object(_.compact(dict));
}
_update_id(v) {
this.state.id = parseIntOrNull(v);
}
get id() {
return (this.state || {}).id;
}
}
export default BaseModel;
@mosson
Copy link
Author

mosson commented Jan 21, 2016

class Survey extends BaseModel {
  get updated_at() {
    return this.state.updated_at;
  }

  get created_at() {
    return this.state.created_at;
  }

  get name() {
    return this.state.name;
  }

  get color() {
    return this.state.color || Constant.COLOR.GLACIER;
  }

  get status() {
    return this.state.status || Constant.STATUS.EDIT;
  }

  get completed_panels_count() {
    return this.state.completed_panels_count;
  }

  get is_public() {
    return !!this.state.is_public;
  }

  get result_url() {
    return this.state.result_url;
  }

  get password() {
    return this.state.password;
  }

  get is_public_preview() {
    return !!this.state.is_public_preview;
  }

  get preview_url() {
    return this.state.preview_url;
  }

  get preview_password() {
    return this.state.preview_password;
  }

  get is_gift() {
    return this.state.is_gift;
  }

  get gift_code() {
    return this.state.gift_code;
  }

  get _isOver() {
    return this.state._isOver;
  }
}

Survey.hasMany('collectors', Collector);
Survey.hasMany('segments', Segment);
Survey.hasOne('summary', Summary);
Survey.hasOne('collector', Collector);
Survey.hasOne('statistic', Statistic);

@mosson
Copy link
Author

mosson commented Jan 21, 2016

'use strict';

import _ from 'lodash';
import is from 'is_js';
import assign from 'object-assign';

import moment from 'moment';

import Dispatcher from 'dispatchers/common/Dispatcher';
import Constant from 'constants/surveys/AppConstants';

import BaseModel from 'models/BaseModel';
import User from 'models/User';
import Account from 'models/Account';
import Message from 'models/Message';
import Notification from 'models/Notification';
import Survey from 'models/Survey';

import AbstractStore from 'stores/AbstractStore';

class AppProxy extends BaseModel {
  get surveys() {
    return _.values(this.state.surveys).sort((a, b) => {
      return moment(b.created_at).toDate() < moment(a.created_at).toDate();
    });
  }

  get _isLegacy() {
    return this.state._isLegacy;
  }

  get _isNotification() {
    return this.state._isNotification;
  }

  get _filterColor() {
    return this.state._filterColor;
  }

  get _isSearch() {
    return this.state._isSearch;
  }

  get _isList() {
    return this.state._isList;
  }

  get _isColorEditor() {
    return this.state._isColorEditor;
  }

  get _isCreateModal() {
    return this.state._isCreateModal;
  }

  get _surveysOffset() {
    return this.state._surveysOffset || 0;
  }

  get _isSurveyQuerying() {
    return this.state._isSurveyQuerying;
  }

  get _isMoreSurveys() {
    if (this.state._isMoreSurveys === undefined) {
      return true;
    } else {
      return this.state._isMoreSurveys;
    }
  }

  get _q() {
    return this.state._q;
  }
}

AppProxy.hasOne('user', User);
AppProxy.hasOne('account', Account);
AppProxy.hasOne('survey', Survey);
AppProxy.hasMany('messages', Message);
AppProxy.hasMany('notifications', Notification);
AppProxy.hasMany('surveys', Survey);

class AppStore extends AbstractStore {
  constructor(key) {
    super(key);
    this._state = new AppProxy();
  }

  registration() {
    return {
      [Constant.ACTIONS.UPDATE]      : this.update.bind(this),
      [Constant.ACTIONS.DESTROY]     : this.destroy.bind(this),
      [Constant.ACTIONS.CHANGE_QUERY]: this.changeQuery.bind(this)
    };
  }

  trigger() {
    this.emit(Constant.EVENTS.CHANGED);
  }

  update(payload) {
    this._state.update(payload.data);
    this.trigger();
  }

  destroy(payload) {
    this._state.destroy(payload.data);
    this.trigger();
  }

  changeQuery(payload) {
    this._state.destroy({
      surveys: _.map(this._state.surveys, (survey) => {
        return {
          id        : survey.id,
          _destroyed: true
        };
      })
    });

    this._state.update(assign(payload.data, {_isMoreSurveys: true, _surveysOffset: 0}));
    this.trigger();
  }

  get state() {
    return this._state.toObject();
  }
}

export default AppStore;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment