<commit_before>/**
 * @typedef {Object} TestResult
 * @property {Boolean} failed - whether or not test failed
 * @property {String} name - name of test
 * @property {Boolean} passed - whether or not test passed
 * @property {Number} runDuration - run duration in milliseconds
 * @property {Boolean} skipped - whether or not test was skipped
 */

/**
 * Get duration in human friendly format
 * @param {Number} value - duration in milliseconds
 * @returns {String} human friendly duration
 */
function getHumanReadableDuration (value) {
  if (value < 1000) {
    return value + ' ms'
  }

  // Convert from milliseconds to seconds
  value = value / 1000

  if (value < 60) {
    return value + ' s'
  }

  // Convert from seconds to minutes
  value = value / 60

  if (value < 60) {
    return value + ' min'
  }

  // Convert from minutes to hours
  value = value / 60

  return value + ' hr'
}

/**
 * Sort tests by duration
 * @param {TestResult} a - first test
 * @param {TestResult} b - second test
 * @returns {Number} number indicating sort order
 */
function testSorter (a, b) {
  return a.runDuration - b.runDuration
}

/**
 * Write out individual test result
 * @param {TestResult} test - test to write out result of
 */
function testWriter (test, verbose) {
  // Other properties that may be useful: logs, error, launcherId, items
  var humanFriendlyDuration = getHumanReadableDuration(test.runDuration)
  this.out.write('[' + humanFriendlyDuration + '] ' + test.name + '\n')

  if (verbose) {
    if (test.logs && test.logs.length !== 0) {
      this.out.write('\tLogs:\n')

      test.logs.forEach((log) => {
        this.out.write('\t\t' + log + '\n')
      })
    }

    if (test.error) {
      var e = test.error
      this.out.write('\n\tError: ' + e.message + '\n')

      if (e.stack) {
        this.out.write('\n\t\t' + e.stack.toString().replace(/\n/g, '\n\t\t') + '\n\n')
      }
    }
  }
}

/**
 * Write passed tests
 */
function writePassedTests () {
  if (this.passedTests.length !== 0) {
    this.out.write('PASSED TESTS\n\n')

    this.passedTests
      .sort(testSorter)
      .forEach(testWriter.bind(this))

    this.out.write('\n')
  }
}

/**
 * Write out summary of test run
 * @param {String} humanReadableDuration - human readable test run duration
 */
function writeSummary (humanReadableDuration) {
  var passed = this.pass
  var skipped = this.skipped
  var total = this.total
  var failed = total - skipped - passed

  this.out.write(
    'ran ' + total + ' tests in ' + humanReadableDuration + ' [' + passed +
    ' passed / ' + failed + ' failed / ' + skipped + ' skipped]\n\n'
  )
}

function Reporter (silent, out) {
  // Set options
  this.out = out || process.stdout
  this.silent = silent

  // Set test arrays
  this.failedTests = []
  this.passedTests = []

  // Set counters
  this.pass = 0
  this.skipped = 0
  this.total = 0

  // Other stuff
  this.endTime = null
  this.id = 1
  this.stoppedOnError = null
  this.startTime = new Date()
}

Reporter.prototype = {
  finish: function () {
    if (this.silent) {
      return
    }

    this.endTime = new Date()

    var duration = Math.round(this.endTime - this.startTime)
    var humanReadableDuration = getHumanReadableDuration(duration)

    if (this.failedTests.length === 0) {
      writeSummary.call(this, humanReadableDuration)
      writePassedTests.call(this)
    } else {
      this.out.write('\n')
    }

    writeSummary.call(this, humanReadableDuration)
  },

  report: function (prefix, data) {
    if (data.skipped) {
      this.skipped++
    } else if (data.passed) {
      this.pass++
      this.passedTests.push(data)
    } else {
      this.out.write(this.failedTests.length === 0 ? 'FAILED TESTS\n\n' : '\n')
      this.failedTests.push(data)
      testWriter.call(this, data, true)
    }

    this.total++
  }
}

module.exports = Reporter
<commit_msg>Fix lint error<commit_after>/**
 * @typedef {Object} TestResult
 * @property {Boolean} failed - whether or not test failed
 * @property {String} name - name of test
 * @property {Boolean} passed - whether or not test passed
 * @property {Number} runDuration - run duration in milliseconds
 * @property {Boolean} skipped - whether or not test was skipped
 */

/**
 * Get duration in human friendly format
 * @param {Number} value - duration in milliseconds
 * @returns {String} human friendly duration
 */
function getHumanReadableDuration (value) {
  if (value < 1000) {
    return value + ' ms'
  }

  // Convert from milliseconds to seconds
  value = value / 1000

  if (value < 60) {
    return value + ' s'
  }

  // Convert from seconds to minutes
  value = value / 60

  if (value < 60) {
    return value + ' min'
  }

  // Convert from minutes to hours
  value = value / 60

  return value + ' hr'
}

/**
 * Sort tests by duration
 * @param {TestResult} a - first test
 * @param {TestResult} b - second test
 * @returns {Number} number indicating sort order
 */
function testSorter (a, b) {
  return a.runDuration - b.runDuration
}

/**
 * Write out individual test result
 * @param {TestResult} test - test to write out result of
 * @param {Boolean} verbose - whether or not to show additional error information
 */
function testWriter (test, verbose) {
  // Other properties that may be useful: logs, error, launcherId, items
  var humanFriendlyDuration = getHumanReadableDuration(test.runDuration)
  this.out.write('[' + humanFriendlyDuration + '] ' + test.name + '\n')

  if (verbose) {
    if (test.logs && test.logs.length !== 0) {
      this.out.write('\tLogs:\n')

      test.logs.forEach((log) => {
        this.out.write('\t\t' + log + '\n')
      })
    }

    if (test.error) {
      var e = test.error
      this.out.write('\n\tError: ' + e.message + '\n')

      if (e.stack) {
        this.out.write('\n\t\t' + e.stack.toString().replace(/\n/g, '\n\t\t') + '\n\n')
      }
    }
  }
}

/**
 * Write passed tests
 */
function writePassedTests () {
  if (this.passedTests.length !== 0) {
    this.out.write('PASSED TESTS\n\n')

    this.passedTests
      .sort(testSorter)
      .forEach(testWriter.bind(this))

    this.out.write('\n')
  }
}

/**
 * Write out summary of test run
 * @param {String} humanReadableDuration - human readable test run duration
 */
function writeSummary (humanReadableDuration) {
  var passed = this.pass
  var skipped = this.skipped
  var total = this.total
  var failed = total - skipped - passed

  this.out.write(
    'ran ' + total + ' tests in ' + humanReadableDuration + ' [' + passed +
    ' passed / ' + failed + ' failed / ' + skipped + ' skipped]\n\n'
  )
}

function Reporter (silent, out) {
  // Set options
  this.out = out || process.stdout
  this.silent = silent

  // Set test arrays
  this.failedTests = []
  this.passedTests = []

  // Set counters
  this.pass = 0
  this.skipped = 0
  this.total = 0

  // Other stuff
  this.endTime = null
  this.id = 1
  this.stoppedOnError = null
  this.startTime = new Date()
}

Reporter.prototype = {
  finish: function () {
    if (this.silent) {
      return
    }

    this.endTime = new Date()

    var duration = Math.round(this.endTime - this.startTime)
    var humanReadableDuration = getHumanReadableDuration(duration)

    if (this.failedTests.length === 0) {
      writeSummary.call(this, humanReadableDuration)
      writePassedTests.call(this)
    } else {
      this.out.write('\n')
    }

    writeSummary.call(this, humanReadableDuration)
  },

  report: function (prefix, data) {
    if (data.skipped) {
      this.skipped++
    } else if (data.passed) {
      this.pass++
      this.passedTests.push(data)
    } else {
      this.out.write(this.failedTests.length === 0 ? 'FAILED TESTS\n\n' : '\n')
      this.failedTests.push(data)
      testWriter.call(this, data, true)
    }

    this.total++
  }
}

module.exports = Reporter
<|endoftext|>


<commit_before>var database = require('./database');

var collection;
var db = database.createDB('sync', function(err, _collection) {
    if (err) {
        console.log('Errors while loading collection: ');
        console.log(err);
        console.log('Attempting to create collection...');
        database.createCollection('session', function(err, col) {
            if (err) {
                console.log('Error!');
                console.log(err);
            } else {
                console.log('Success!');
                collection = col;
            }
        });
    } else collection = _collection;
});

exports.version = function(data, emit) {
    emit({type: 'version', data: {name: 'TouchLay Sync', version: '0.0.1'}});
};

exports.findById = function(data, emit) {
    if (!collection) {
        emit({type: 'result', data: {}});
    }

    database.findOneById(collection, req.params.id, function(err, item) {
        emit({type: 'result', data: item});
    });
};

exports.findAll = function(data, emit) {
    if (!collection) {
        emit({type: 'results', data: []});
    }

    var result = {};
    collection.find().toArray(function(err, items) {
        emit({type: 'results', data: items});
    });
};

exports.create = function(data, emit) {
    if (data.data) {
        collection.insert({data: data.data}, {safe: true}, function(err, records) {
            if (err) {
                console.log('Errors while inserting document: ' + JSON.stringify(err));
                emit({type: 'message', data: {success: false, errors: err, message: 'Failed to create new session.'}});
            } else {
                console.log('Inserted record: ' + JSON.stringify(records[0]));
                emit({type: 'message', data: {id: records[0]._id, success: true, message: 'Successfully created new session.'}});
            }
        });
        return;
    }

    emit({type: 'message', data: {success: false, message: 'No data.'}});
};

exports.update = function(data, emit) {
    if (!data.id) {
        emit({type: 'message', data: {success: false, message: 'No ID.'}});
    }

    if (data.data) {
        collection.update({_id: database.ObjectID(data.id)}, {data: data.data}, {safe: true}, function(err) {
            if (err) {
                console.log('Errors while updating document: ' + JSON.stringify(err));
                emit({type: 'message', data: {success: false, errors: err, message: 'Failed to update session (does it exist?).'}});
            } else {
                console.log('Updated record "' + data.id + '".');
                emit({type: 'message', data: {id: data.id, success: true, message: 'Successfully updated session.'}});
            }
        });
        return;
    }

    emit({type: 'message', data: {success: false, message: 'No data.'}});
};

exports.destroy = function(data, emit) {
    if (!data.id) {
        emit({type: 'message', data: {success: false, message: 'No ID.'}});
    }

    collection.remove({_id: database.ObjectID(data.id)}, {w: 1}, function(err, removedDocs) {
        if (err) {
            console.log('Errors while removing document: ' + JSON.stringify(err));
            emit({type: 'message', data: {success: false, errors: err, message: 'Failed to destroy session (does it exist?).'}});
        } else {
            console.log('Removed record "' + data.id + '".');
            emit({type: 'message', data: {id: data.id, success: true, message: 'Successfully destroyed session.'}});
        }
    });
};
<commit_msg>fixed findById<commit_after>var database = require('./database');

var collection;
var db = database.createDB('sync', function(err, _collection) {
    if (err) {
        console.log('Errors while loading collection: ');
        console.log(err);
        console.log('Attempting to create collection...');
        database.createCollection('session', function(err, col) {
            if (err) {
                console.log('Error!');
                console.log(err);
            } else {
                console.log('Success!');
                collection = col;
            }
        });
    } else collection = _collection;
});

exports.version = function(data, emit) {
    emit({type: 'version', data: {name: 'TouchLay Sync', version: '0.0.1'}});
};

exports.findById = function(data, emit) {
    if (!collection) {
        emit({type: 'result', data: {}});
    }

    database.findOneById(collection, data.id, function(err, item) {
        emit({type: 'result', data: item});
    });
};

exports.findAll = function(data, emit) {
    if (!collection) {
        emit({type: 'results', data: []});
    }

    var result = {};
    collection.find().toArray(function(err, items) {
        emit({type: 'results', data: items});
    });
};

exports.create = function(data, emit) {
    if (data.data) {
        collection.insert({data: data.data}, {safe: true}, function(err, records) {
            if (err) {
                console.log('Errors while inserting document: ' + JSON.stringify(err));
                emit({type: 'message', data: {success: false, errors: err, message: 'Failed to create new session.'}});
            } else {
                console.log('Inserted record: ' + JSON.stringify(records[0]));
                emit({type: 'message', data: {id: records[0]._id, success: true, message: 'Successfully created new session.'}});
            }
        });
        return;
    }

    emit({type: 'message', data: {success: false, message: 'No data.'}});
};

exports.update = function(data, emit) {
    if (!data.id) {
        emit({type: 'message', data: {success: false, message: 'No ID.'}});
    }

    if (data.data) {
        collection.update({_id: database.ObjectID(data.id)}, {data: data.data}, {safe: true}, function(err) {
            if (err) {
                console.log('Errors while updating document: ' + JSON.stringify(err));
                emit({type: 'message', data: {success: false, errors: err, message: 'Failed to update session (does it exist?).'}});
            } else {
                console.log('Updated record "' + data.id + '".');
                emit({type: 'message', data: {id: data.id, success: true, message: 'Successfully updated session.'}});
            }
        });
        return;
    }

    emit({type: 'message', data: {success: false, message: 'No data.'}});
};

exports.destroy = function(data, emit) {
    if (!data.id) {
        emit({type: 'message', data: {success: false, message: 'No ID.'}});
    }

    collection.remove({_id: database.ObjectID(data.id)}, {w: 1}, function(err, removedDocs) {
        if (err) {
            console.log('Errors while removing document: ' + JSON.stringify(err));
            emit({type: 'message', data: {success: false, errors: err, message: 'Failed to destroy session (does it exist?).'}});
        } else {
            console.log('Removed record "' + data.id + '".');
            emit({type: 'message', data: {id: data.id, success: true, message: 'Successfully destroyed session.'}});
        }
    });
};
<|endoftext|>


<commit_before>define([
    'underscore',
    'knockout',
    'moment',
    'views/search/base-filter',
    'arches',
    'bindings/datepicker',
    'bindings/chosen',
    'bindings/time-wheel'
],
function(_, ko, moment, BaseFilter, arches) {
    return BaseFilter.extend({
        initialize: function(options) {
            var self = this;
            this.name = 'Time Filter';
            this.filter = {
                fromDate: ko.observable(null),
                toDate: ko.observable(null),
                dateNodeId: ko.observable(null),
                inverted: ko.observable(false)
            }
            this.filter.fromDate.subscribe(function (fromDate) {
                var toDate = self.filter.toDate();
                if (fromDate && toDate && toDate < fromDate) {
                    self.filter.toDate(fromDate);
                }
            });
            this.filter.toDate.subscribe(function (toDate) {
                var fromDate = self.filter.fromDate();
                if (fromDate && toDate && fromDate > toDate) {
                    self.filter.fromDate(toDate);
                }
            })
            this.dateRangeType = ko.observable('custom');
            this.format = 'YYYY-MM-DD';
            this.showWheel = ko.observable(false);
            this.breadCrumb = ko.observable();
            this.selectedPeriod = ko.observable();
            this.wheelConfig = ko.observable();
            this.getTimeWheelConfig();
            this.selectedPeriod.subscribe(function (d) {
                if (d) {
                    var start = moment(0, 'YYYY').add(d.start, 'years').format(this.format);
                    var end = moment(0, 'YYYY').add(d.end, 'years').format(this.format);
                    self.dateRangeType('custom');
                    self.filter.fromDate(end);
                    self.filter.toDate(end);
                    self.filter.fromDate(start);
                }
            })

            this.dateRangeType.subscribe(function(value) {
                var today = moment();
                var from = today.format(this.format);
                var to = today.format(this.format);
                switch (value) {
                    case "today":
                        break;
                    case "last-7":
                        from = today.subtract(7, 'days').format(this.format);
                        break;
                    case "last-30":
                        from = today.subtract(30, 'days').format(this.format);
                        break;
                    case "this-week":
                        from = today.day(0).format(this.format);
                        to = today.day(6).format(this.format);
                        break;
                    case "this-month":
                        from = today.date(1).format(this.format);
                        to = moment().month(today.month()+1).date(0).format(this.format);
                        break;
                    case "this-quarter":
                        from = moment().date(1).quarter(today.quarter()).format(this.format);
                        to = moment().date(1).quarter(today.quarter()+1).format(this.format);
                        break;
                    case "this-year":
                        var first = today.dayOfYear(1);
                        from = first.format(this.format);
                        to = first.add(1, 'years').subtract(1, 'days').format(this.format);
                        break;
                    default:
                        return;
                }
                this.filter.toDate(to);
                this.filter.fromDate(from);
            }, this);

            this.filterChanged = ko.computed(function(){
                if(!!this.filter.fromDate() || !!this.filter.toDate()){
                    this.termFilter.addTag(this.name, this.name, this.filter.inverted);
                }
                return ko.toJSON(this.filter);
            }, this).extend({ deferred: true });

            BaseFilter.prototype.initialize.call(this, options);
        },

        getTimeWheelConfig: function(){
            var self = this;
            $.ajax({
                type: "GET",
                url: arches.urls.time_wheel_config,
                success: function(response) {
                    self.wheelConfig(response);
                },
                error: function(response) {
                    self.breadCrumb(response.responseText);
                }
            });
        },

        appendFilters: function(filterParams) {
            var filters_applied = !!this.filter.fromDate() || !!this.filter.toDate();
            if(filters_applied){
                filterParams.temporalFilter = ko.toJSON(this.filter);
            }
            return filters_applied;
        },

        restoreState: function(query) {
            var doQuery = false;
            if ('temporalFilter' in query) {
                query.temporalFilter = JSON.parse(query.temporalFilter);
                this.filter.inverted(!!query.temporalFilter.inverted);
                this.termFilter.addTag(this.name, this.name, this.filter.inverted);
                ['fromDate', 'toDate', 'dateNodeId'].forEach(function(key) {
                    if (key in query.temporalFilter) {
                        this.filter[key](query.temporalFilter[key]);
                    }
                }, this);
                doQuery = true;
            }
            return doQuery;
        },

        clear: function() {
            this.filter.fromDate(null);
            this.filter.toDate(null);
            this.filter.dateNodeId(null);
            this.filter.inverted(false);
            this.dateRangeType('custom');
            this.termFilter.removeTag(this.name);
            this.selectedPeriod(null);
            return;
        }
    });
});
<commit_msg>fixing time filter date formats re: #1492<commit_after>define([
    'underscore',
    'knockout',
    'moment',
    'views/search/base-filter',
    'arches',
    'bindings/datepicker',
    'bindings/chosen',
    'bindings/time-wheel'
],
function(_, ko, moment, BaseFilter, arches) {
    return BaseFilter.extend({
        initialize: function(options) {
            var self = this;
            this.name = 'Time Filter';
            this.filter = {
                fromDate: ko.observable(null),
                toDate: ko.observable(null),
                dateNodeId: ko.observable(null),
                inverted: ko.observable(false)
            }
            this.filter.fromDate.subscribe(function (fromDate) {
                var toDate = self.filter.toDate();
                if (fromDate && toDate && toDate < fromDate) {
                    self.filter.toDate(fromDate);
                }
            });
            this.filter.toDate.subscribe(function (toDate) {
                var fromDate = self.filter.fromDate();
                if (fromDate && toDate && fromDate > toDate) {
                    self.filter.fromDate(toDate);
                }
            })
            this.dateRangeType = ko.observable('custom');
            this.format = 'YYYY-MM-DD';
            this.showWheel = ko.observable(false);
            this.breadCrumb = ko.observable();
            this.selectedPeriod = ko.observable();
            this.wheelConfig = ko.observable();
            this.getTimeWheelConfig();
            this.selectedPeriod.subscribe(function (d) {
                if (d) {
                    var start = moment(0, 'YYYY').add(d.start, 'years').format(self.format);
                    var end = moment(0, 'YYYY').add(d.end, 'years').format(self.format);
                    self.dateRangeType('custom');
                    self.filter.fromDate(end);
                    self.filter.toDate(end);
                    self.filter.fromDate(start);
                }
            })

            this.dateRangeType.subscribe(function(value) {
                var today = moment();
                var from = today.format(this.format);
                var to = today.format(this.format);
                switch (value) {
                    case "today":
                        break;
                    case "last-7":
                        from = today.subtract(7, 'days').format(this.format);
                        break;
                    case "last-30":
                        from = today.subtract(30, 'days').format(this.format);
                        break;
                    case "this-week":
                        from = today.day(0).format(this.format);
                        to = today.day(6).format(this.format);
                        break;
                    case "this-month":
                        from = today.date(1).format(this.format);
                        to = moment().month(today.month()+1).date(0).format(this.format);
                        break;
                    case "this-quarter":
                        from = moment().date(1).quarter(today.quarter()).format(this.format);
                        to = moment().date(1).quarter(today.quarter()+1).format(this.format);
                        break;
                    case "this-year":
                        var first = today.dayOfYear(1);
                        from = first.format(this.format);
                        to = first.add(1, 'years').subtract(1, 'days').format(this.format);
                        break;
                    default:
                        return;
                }
                this.filter.toDate(to);
                this.filter.fromDate(from);
            }, this);

            this.filterChanged = ko.computed(function(){
                if(!!this.filter.fromDate() || !!this.filter.toDate()){
                    this.termFilter.addTag(this.name, this.name, this.filter.inverted);
                }
                return ko.toJSON(this.filter);
            }, this).extend({ deferred: true });

            BaseFilter.prototype.initialize.call(this, options);
        },

        getTimeWheelConfig: function(){
            var self = this;
            $.ajax({
                type: "GET",
                url: arches.urls.time_wheel_config,
                success: function(response) {
                    self.wheelConfig(response);
                },
                error: function(response) {
                    self.breadCrumb(response.responseText);
                }
            });
        },

        appendFilters: function(filterParams) {
            var filters_applied = !!this.filter.fromDate() || !!this.filter.toDate();
            if(filters_applied){
                filterParams.temporalFilter = ko.toJSON(this.filter);
            }
            return filters_applied;
        },

        restoreState: function(query) {
            var doQuery = false;
            if ('temporalFilter' in query) {
                query.temporalFilter = JSON.parse(query.temporalFilter);
                this.filter.inverted(!!query.temporalFilter.inverted);
                this.termFilter.addTag(this.name, this.name, this.filter.inverted);
                ['fromDate', 'toDate', 'dateNodeId'].forEach(function(key) {
                    if (key in query.temporalFilter) {
                        this.filter[key](query.temporalFilter[key]);
                    }
                }, this);
                doQuery = true;
            }
            return doQuery;
        },

        clear: function() {
            this.filter.fromDate(null);
            this.filter.toDate(null);
            this.filter.dateNodeId(null);
            this.filter.inverted(false);
            this.dateRangeType('custom');
            this.termFilter.removeTag(this.name);
            this.selectedPeriod(null);
            return;
        }
    });
});
<|endoftext|>


<commit_before>// @client-side

import ns from 'ima/namespace';
import AbstractRouter from 'ima/router/abstractRouter';

ns.namespace('ima.router');

/**
 * Names of the DOM events the router responds to.
 *
 * @const
 * @property EVENTS
 * @type {Object<string, string>}
 */
const EVENTS = Object.freeze({
	/**
	 * Name of the event produced when the user clicks the page using the
	 * mouse, or touches the page and the touch event is not stopped.
	 *
	 * @const
	 * @property
	 * @type {string}
	 */
	CLICK: 'click',

	/**
	 * Name of the event fired when the user navigates back in the history.
	 *
	 * @const
	 * @property EVENTS.POP_STATE
	 * @type {string}
	 */
	POP_STATE: 'popstate'
});

/**
 * Address bar content manipulation modes.
 *
 * @const
 * @property MODES
 * @type {Object<string, string>}
 */
const MODES = Object.freeze({
	/**
	 * Address bar manipulation mode in which the current URL in the address
	 * bar is being udpated using the session history management API.
	 *
	 * @const
	 * @property MODES.HISTORY
	 * @type {string}
	 */
	HISTORY: 'history',

	/**
	 * Address bar manipulation mode in which the current URL in the address
	 * bar is being udpated by modifying the {@code hash} part.
	 *
	 * @const
	 * @property MODES.HASH
	 * @type {string}
	 */
	HASH: 'hash'
});

/**
 * The number used as the index of the mouse left button in DOM
 * {@code MouseEvent}s.
 *
 * @const
 * @property MOUSE_LEFT_BUTTON
 * @type {number}
 */
const MOUSE_LEFT_BUTTON = 0;

/**
 * The client-side implementation of the {@codelink ima.router.Router}
 * interface.
 *
 * @class ClientRouter
 * @extends ima.router.AbstractRouter
 * @namespace ima.router
 * @module ima
 * @submodule ima.router
 */
export default class ClientRouter extends AbstractRouter {

	/**
	 * Initializes the client-side router.
	 *
	 * @constructor
	 * @method constructor
	 * @param {ima.page.manager.PageManager} pageManager The page manager
	 *        handling UI rendering, and transitions between pages if at the
	 *        client side.
	 * @param {ima.router.RouteFactory} factory Factory for routes.
	 * @param {ima.event.Dispatcher} dispatcher Dispatcher fires events to
	 *        app.
	 * @param {{ROUTE_NAMES: Object<string, string>, EVENTS: Object<string, string>}} ROUTER_CONSTANTS
	 *        The internal router constants. The {@code ROUTE_NAMES}
	 *        contains internal route names. The {@code EVENTS} contains name
	 *        of events which are fired with {@code ima.Event.Dispatcher}.
	 * @param {ima.window.Window} window The current global client-side
	 *        APIs provider.
	 */
	constructor(pageManager, factory, dispatcher, ROUTER_CONSTANTS, window) {
		super(pageManager, factory, dispatcher, ROUTER_CONSTANTS);

		/**
		 * Helper for accessing the native client-side APIs.
		 *
		 * @private
		 * @property _window
		 * @type {ima.window.Window}
		 */
		this._window = window;

		/**
		 * Current address bar manipulation mode, specified as one of the
		 * {@code MODES.*} constants..
		 *
		 * @private
		 * @property mode
		 * @type {string}
		 * @default null
		 */
		this._mode = null;
	}

	/**
	 * @inheritdoc
	 * @method init
	 */
	init(config) {
		super.init(config);
		this._mode = this._window.hasHistoryAPI() ? MODES.HISTORY : MODES.HASH;
		this._host = config.$Host || this._window.getHost();

		return this;
	}

	/**
	 * @inheritdoc
	 * @method getUrl
	 */
	getUrl() {
		return this._window.getUrl();
	}

	/**
	 * @inheritdoc
	 * @method getPath
	 */
	getPath() {
		return this._extractRoutePath(this._window.getPath());
	}

	/**
	 * @inheritdoc
	 * @method listen
	 */
	listen() {
		var nativeWindow = this._window.getWindow();

		this._setAddressBar(this.getUrl());
		let eventName = EVENTS.POP_STATE;
		this._window.bindEventListener(nativeWindow, eventName, (event) => {

			if (event.state) {
				this.route(this.getPath())
					.then(() => {
						var scroll = event.state.scroll;

						if (scroll) {
							this._pageManager.scrollTo(scroll.x, scroll.y);
						}
					});
			}
		});

		this._window.bindEventListener(nativeWindow, EVENTS.CLICK, (event) => {
			this._handleClick(event);
		});

		return this;
	}

	/**
	 * @inheritdoc
	 * @method redirect
	 */
	redirect(url = '', options = {}) {
		if (this._isSameDomain(url) && this._mode === MODES.HISTORY) {
			var path = url.replace(this.getDomain(), '');
			path = this._extractRoutePath(path);

			this._saveScrollHistory();
			this._setAddressBar(url);
			this.route(path, options);
		} else {
			this._window.redirect(url);
		}
	}

	/**
	 * @inheritdoc
	 * @method route
	 */
	route(path, options = {}) {
		return (
			super
				.route(path, options)
				.catch((error) => {
					return this.handleError({ error });
				})
				.catch((error) => {
					this._handleFatalError(error);
				})
		);
	}

	/**
	 * @inheritdoc
	 * @method handleError
	 */
	handleError(params, options = {}) {
		if ($Debug) {
			console.error(params.error);
		}

		if (this.isClientError(params.error)) {
			return this.handleNotFound(params, options);
		}

		if (this.isRedirection(params.error)) {
			options.httpStatus = params.error.getHttpStatus();
			this.redirect(params.error.getParams().url, options);
			return Promise.resolve({
				content: null,
				status: options.httpStatus,
				error: params.error
			});
		}

		return (
			super
				.handleError(params, options)
				.catch((error) => {
					this._handleFatalError(error);
				})
		);
	}

	/**
	 * @inheritdoc
	 * @method handleNotFound
	 */
	handleNotFound(params, options = {}) {
		return (
			super
				.handleNotFound(params, options)
				.catch((error) => {
					return this.handleError({ error });
				})
		);
	}

	/**
	 * Handle a fatal error application state. IMA handle fatal error when IMA
	 * handle error.
	 *
	 * @private
	 * @method _handleFatalError
	 * @param {Error} error
	 */
	_handleFatalError(error) {
		if ($IMA && typeof $IMA.fatalErrorHandler === 'function') {
			$IMA.fatalErrorHandler(error);
		} else {

			if ($Debug) {
				console.warn('You must implement $IMA.fatalErrorHandler in ' +
						'services.js');
			}
		}
	}

	/**
	 * Handles a click event. The method performs navigation to the target
	 * location of the anchor (if it has one).
	 *
	 * The navigation will be handled by the router if the protocol and domain
	 * of the anchor's target location (href) is the same as the current,
	 * otherwise the method results in a hard redirect.
	 *
	 * @private
	 * @method _handleClick
	 * @param {MouseEvent} event The click event.
	 */
	_handleClick(event) {
		var target = event.target || event.srcElement;
		var anchorElement = this._getAnchorElement(target);

		if (!anchorElement) {
			return;
		}

		var anchorHref = anchorElement.href;
		var isDefinedTargetHref = anchorHref !== undefined &&
				anchorHref !== null;
		var isSetTarget = anchorElement.getAttribute('target') !== null;
		var isLeftButton = event.button === MOUSE_LEFT_BUTTON;
		var isSameDomain = this._isSameDomain(anchorHref);
		var isHashLink = this._isHashLink(anchorHref);
		var isLinkPrevented = event.defaultPrevented;

		if (!isDefinedTargetHref ||
				isSetTarget ||
				!isLeftButton ||
				!isSameDomain ||
				isHashLink ||
				isLinkPrevented) {
			return;
		}

		this._window.preventDefault(event);
		this.redirect(anchorHref);
	}

	/**
	 * The method determines whether an anchor element or a child of an anchor
	 * element has been clicked, and if it was, the method returns anchor
	 * element else null.
	 *
	 * @private
	 * @method _getAnchorElement
	 * @param {Node} target
	 * @return {?Node}
	 */
	_getAnchorElement(target) {
		var self = this;

		while (target && !hasReachedAnchor(target)) {
			target = target.parentNode;
		}

		function hasReachedAnchor(nodeElement) {
			return nodeElement.parentNode &&
					nodeElement !== self._window.getBody() &&
					nodeElement.href !== undefined &&
					nodeElement.href !== null;
		}

		return target;
	}

	/**
	 * Tests whether the provided target URL contains only an update of the
	 * hash fragment of the current URL.
	 *
	 * @private
	 * @method _isHashLink
	 * @param {string} targetUrl The target URL.
	 * @return {boolean} {@code true} if the navigation to target URL would
	 *         result only in updating the hash fragment of the current URL.
	 */
	_isHashLink(targetUrl) {
		if (targetUrl.indexOf('#') === -1) {
			return false;
		}

		var currentUrl = this._window.getUrl();
		var trimmedCurrentUrl = currentUrl.indexOf('#') === -1 ? currentUrl :
				currentUrl.substring(0, currentUrl.indexOf('#'));
		var trimmedTargetUrl = targetUrl.substring(0, targetUrl.indexOf('#'));

		return trimmedTargetUrl === trimmedCurrentUrl;
	}

	/**
	 * Sets the provided URL to the browser's address bar by pushing a new
	 * state to the history.
	 *
	 * The state object pushed to the history will be an object with the
	 * following structure: {@code {url: string}}. The {@code url} field will
	 * be set to the provided URL.
	 *
	 * @private
	 * @method _setAddressBar
	 * @param {string} url The URL.
	 */
	_setAddressBar(url) {
		var scroll = {
			x: 0,
			y: 0
		};
		var state = { url, scroll };

		this._window.pushState(state, null, url);
	}

	/**
	 * Save user's scroll state to history.
	 *
	 * Replace scroll values in current state for actual scroll values in
	 * document.
	 *
	 * @method _saveScrollHistory
	 */
	_saveScrollHistory() {
		var url = this.getUrl();
		var scroll = {
			x: this._window.getScrollX(),
			y: this._window.getScrollY()
		};
		var state = { url, scroll };

		this._window.replaceState(state, null, url);
	}

	/**
	 * Tests whether the the protocol and domain of the provided URL are the
	 * same as the current.
	 *
	 * @private
	 * @method _isSameDomain
	 * @param {string} [url=''] The URL.
	 * @return {boolean} {@code true} if the protocol and domain of the
	 *         provided URL are the same as the current.
	 */
	_isSameDomain(url = '') {
		return !!url.match(this.getBaseUrl());
	}
}

ns.ima.router.ClientRouter = ClientRouter;
<commit_msg>#! remove deprectecated preventDefault method<commit_after>// @client-side

import ns from 'ima/namespace';
import AbstractRouter from 'ima/router/abstractRouter';

ns.namespace('ima.router');

/**
 * Names of the DOM events the router responds to.
 *
 * @const
 * @property EVENTS
 * @type {Object<string, string>}
 */
const EVENTS = Object.freeze({
	/**
	 * Name of the event produced when the user clicks the page using the
	 * mouse, or touches the page and the touch event is not stopped.
	 *
	 * @const
	 * @property
	 * @type {string}
	 */
	CLICK: 'click',

	/**
	 * Name of the event fired when the user navigates back in the history.
	 *
	 * @const
	 * @property EVENTS.POP_STATE
	 * @type {string}
	 */
	POP_STATE: 'popstate'
});

/**
 * Address bar content manipulation modes.
 *
 * @const
 * @property MODES
 * @type {Object<string, string>}
 */
const MODES = Object.freeze({
	/**
	 * Address bar manipulation mode in which the current URL in the address
	 * bar is being udpated using the session history management API.
	 *
	 * @const
	 * @property MODES.HISTORY
	 * @type {string}
	 */
	HISTORY: 'history',

	/**
	 * Address bar manipulation mode in which the current URL in the address
	 * bar is being udpated by modifying the {@code hash} part.
	 *
	 * @const
	 * @property MODES.HASH
	 * @type {string}
	 */
	HASH: 'hash'
});

/**
 * The number used as the index of the mouse left button in DOM
 * {@code MouseEvent}s.
 *
 * @const
 * @property MOUSE_LEFT_BUTTON
 * @type {number}
 */
const MOUSE_LEFT_BUTTON = 0;

/**
 * The client-side implementation of the {@codelink ima.router.Router}
 * interface.
 *
 * @class ClientRouter
 * @extends ima.router.AbstractRouter
 * @namespace ima.router
 * @module ima
 * @submodule ima.router
 */
export default class ClientRouter extends AbstractRouter {

	/**
	 * Initializes the client-side router.
	 *
	 * @constructor
	 * @method constructor
	 * @param {ima.page.manager.PageManager} pageManager The page manager
	 *        handling UI rendering, and transitions between pages if at the
	 *        client side.
	 * @param {ima.router.RouteFactory} factory Factory for routes.
	 * @param {ima.event.Dispatcher} dispatcher Dispatcher fires events to
	 *        app.
	 * @param {{ROUTE_NAMES: Object<string, string>, EVENTS: Object<string, string>}} ROUTER_CONSTANTS
	 *        The internal router constants. The {@code ROUTE_NAMES}
	 *        contains internal route names. The {@code EVENTS} contains name
	 *        of events which are fired with {@code ima.Event.Dispatcher}.
	 * @param {ima.window.Window} window The current global client-side
	 *        APIs provider.
	 */
	constructor(pageManager, factory, dispatcher, ROUTER_CONSTANTS, window) {
		super(pageManager, factory, dispatcher, ROUTER_CONSTANTS);

		/**
		 * Helper for accessing the native client-side APIs.
		 *
		 * @private
		 * @property _window
		 * @type {ima.window.Window}
		 */
		this._window = window;

		/**
		 * Current address bar manipulation mode, specified as one of the
		 * {@code MODES.*} constants..
		 *
		 * @private
		 * @property mode
		 * @type {string}
		 * @default null
		 */
		this._mode = null;
	}

	/**
	 * @inheritdoc
	 * @method init
	 */
	init(config) {
		super.init(config);
		this._mode = this._window.hasHistoryAPI() ? MODES.HISTORY : MODES.HASH;
		this._host = config.$Host || this._window.getHost();

		return this;
	}

	/**
	 * @inheritdoc
	 * @method getUrl
	 */
	getUrl() {
		return this._window.getUrl();
	}

	/**
	 * @inheritdoc
	 * @method getPath
	 */
	getPath() {
		return this._extractRoutePath(this._window.getPath());
	}

	/**
	 * @inheritdoc
	 * @method listen
	 */
	listen() {
		var nativeWindow = this._window.getWindow();

		this._setAddressBar(this.getUrl());
		let eventName = EVENTS.POP_STATE;
		this._window.bindEventListener(nativeWindow, eventName, (event) => {

			if (event.state) {
				this.route(this.getPath())
					.then(() => {
						var scroll = event.state.scroll;

						if (scroll) {
							this._pageManager.scrollTo(scroll.x, scroll.y);
						}
					});
			}
		});

		this._window.bindEventListener(nativeWindow, EVENTS.CLICK, (event) => {
			this._handleClick(event);
		});

		return this;
	}

	/**
	 * @inheritdoc
	 * @method redirect
	 */
	redirect(url = '', options = {}) {
		if (this._isSameDomain(url) && this._mode === MODES.HISTORY) {
			var path = url.replace(this.getDomain(), '');
			path = this._extractRoutePath(path);

			this._saveScrollHistory();
			this._setAddressBar(url);
			this.route(path, options);
		} else {
			this._window.redirect(url);
		}
	}

	/**
	 * @inheritdoc
	 * @method route
	 */
	route(path, options = {}) {
		return (
			super
				.route(path, options)
				.catch((error) => {
					return this.handleError({ error });
				})
				.catch((error) => {
					this._handleFatalError(error);
				})
		);
	}

	/**
	 * @inheritdoc
	 * @method handleError
	 */
	handleError(params, options = {}) {
		if ($Debug) {
			console.error(params.error);
		}

		if (this.isClientError(params.error)) {
			return this.handleNotFound(params, options);
		}

		if (this.isRedirection(params.error)) {
			options.httpStatus = params.error.getHttpStatus();
			this.redirect(params.error.getParams().url, options);
			return Promise.resolve({
				content: null,
				status: options.httpStatus,
				error: params.error
			});
		}

		return (
			super
				.handleError(params, options)
				.catch((error) => {
					this._handleFatalError(error);
				})
		);
	}

	/**
	 * @inheritdoc
	 * @method handleNotFound
	 */
	handleNotFound(params, options = {}) {
		return (
			super
				.handleNotFound(params, options)
				.catch((error) => {
					return this.handleError({ error });
				})
		);
	}

	/**
	 * Handle a fatal error application state. IMA handle fatal error when IMA
	 * handle error.
	 *
	 * @private
	 * @method _handleFatalError
	 * @param {Error} error
	 */
	_handleFatalError(error) {
		if ($IMA && typeof $IMA.fatalErrorHandler === 'function') {
			$IMA.fatalErrorHandler(error);
		} else {

			if ($Debug) {
				console.warn('You must implement $IMA.fatalErrorHandler in ' +
						'services.js');
			}
		}
	}

	/**
	 * Handles a click event. The method performs navigation to the target
	 * location of the anchor (if it has one).
	 *
	 * The navigation will be handled by the router if the protocol and domain
	 * of the anchor's target location (href) is the same as the current,
	 * otherwise the method results in a hard redirect.
	 *
	 * @private
	 * @method _handleClick
	 * @param {MouseEvent} event The click event.
	 */
	_handleClick(event) {
		var target = event.target || event.srcElement;
		var anchorElement = this._getAnchorElement(target);

		if (!anchorElement) {
			return;
		}

		var anchorHref = anchorElement.href;
		var isDefinedTargetHref = anchorHref !== undefined &&
				anchorHref !== null;
		var isSetTarget = anchorElement.getAttribute('target') !== null;
		var isLeftButton = event.button === MOUSE_LEFT_BUTTON;
		var isSameDomain = this._isSameDomain(anchorHref);
		var isHashLink = this._isHashLink(anchorHref);
		var isLinkPrevented = event.defaultPrevented;

		if (!isDefinedTargetHref ||
				isSetTarget ||
				!isLeftButton ||
				!isSameDomain ||
				isHashLink ||
				isLinkPrevented) {
			return;
		}

		event.preventDefault();
		this.redirect(anchorHref);
	}

	/**
	 * The method determines whether an anchor element or a child of an anchor
	 * element has been clicked, and if it was, the method returns anchor
	 * element else null.
	 *
	 * @private
	 * @method _getAnchorElement
	 * @param {Node} target
	 * @return {?Node}
	 */
	_getAnchorElement(target) {
		var self = this;

		while (target && !hasReachedAnchor(target)) {
			target = target.parentNode;
		}

		function hasReachedAnchor(nodeElement) {
			return nodeElement.parentNode &&
					nodeElement !== self._window.getBody() &&
					nodeElement.href !== undefined &&
					nodeElement.href !== null;
		}

		return target;
	}

	/**
	 * Tests whether the provided target URL contains only an update of the
	 * hash fragment of the current URL.
	 *
	 * @private
	 * @method _isHashLink
	 * @param {string} targetUrl The target URL.
	 * @return {boolean} {@code true} if the navigation to target URL would
	 *         result only in updating the hash fragment of the current URL.
	 */
	_isHashLink(targetUrl) {
		if (targetUrl.indexOf('#') === -1) {
			return false;
		}

		var currentUrl = this._window.getUrl();
		var trimmedCurrentUrl = currentUrl.indexOf('#') === -1 ? currentUrl :
				currentUrl.substring(0, currentUrl.indexOf('#'));
		var trimmedTargetUrl = targetUrl.substring(0, targetUrl.indexOf('#'));

		return trimmedTargetUrl === trimmedCurrentUrl;
	}

	/**
	 * Sets the provided URL to the browser's address bar by pushing a new
	 * state to the history.
	 *
	 * The state object pushed to the history will be an object with the
	 * following structure: {@code {url: string}}. The {@code url} field will
	 * be set to the provided URL.
	 *
	 * @private
	 * @method _setAddressBar
	 * @param {string} url The URL.
	 */
	_setAddressBar(url) {
		var scroll = {
			x: 0,
			y: 0
		};
		var state = { url, scroll };

		this._window.pushState(state, null, url);
	}

	/**
	 * Save user's scroll state to history.
	 *
	 * Replace scroll values in current state for actual scroll values in
	 * document.
	 *
	 * @method _saveScrollHistory
	 */
	_saveScrollHistory() {
		var url = this.getUrl();
		var scroll = {
			x: this._window.getScrollX(),
			y: this._window.getScrollY()
		};
		var state = { url, scroll };

		this._window.replaceState(state, null, url);
	}

	/**
	 * Tests whether the the protocol and domain of the provided URL are the
	 * same as the current.
	 *
	 * @private
	 * @method _isSameDomain
	 * @param {string} [url=''] The URL.
	 * @return {boolean} {@code true} if the protocol and domain of the
	 *         provided URL are the same as the current.
	 */
	_isSameDomain(url = '') {
		return !!url.match(this.getBaseUrl());
	}
}

ns.ima.router.ClientRouter = ClientRouter;
<|endoftext|>


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

var mongodb = require('mongodb');
var dbClient = mongodb.MongoClient;
var ObjectId = mongodb.ObjectId;
var dbUrl = process.env.MONGODB_URI || 'mongodb://localhost/trand'

var request = require('request');
var _ = require('underscore');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');

router.use(bodyParser.json());
router.use(cookieParser());

router.get('/', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.find({email: req.currentUser.email}).toArray(function (err, results) {
        if (results.length>0) {
          results = results.reverse();
          res.json(results);
          db.close();
        } else {
          res.sendStatus(404);
          db.close();
        }
      })
    } else {
      res.sendStatus(404);
    }
  });
})

router.post('/new', function (req, res) {
  var items = req.body.combinations;
  var totalPrice = 0;
  var showed = _.where(items, {show: true});
  var totalPieces = showed.length;

  for (var i = 0; i < showed.length; i++) {
    totalPrice = totalPrice + showed[i].item.price;
  }

  var newComb = {
    email: req.currentUser.email,
    information: req.body.information,
    combinations: showed,
    price: totalPrice,
    pieces: totalPieces,
    date: new Date(),
  }

  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      if (typeof(req.body.information._id)==='undefined') {
        combinations.insert(newComb, function (err, results) {
          res.status(201).send(results.ops[0]._id);
          db.close();
        })
      } else {
        combinations.update({_id: ObjectId(req.body.information._id)}, {
          $set: {
            price: totalPrice,
            pieces: totalPieces,
            information: req.body.information,
            combinations: showed,
            date: new Date(),
          }
        }, function (err, results) {
          res.sendStatus(200);
          db.close();
        })
      }
    } else {
      res.sendStatus(404);
    }
  })
})

router.put('/update', function (req, res) {
  var updateComb = {
    _id: req.body.id,
    combinations: req.body.combinations,
  }
  var items = req.body.combinations;
  var totalPrice = 0;
  var showed = _.where(items, {show: true});
  var totalPieces = showed.length;

  for (var i = 0; i < showed.length; i++) {
    totalPrice = totalPrice + showed[i].item.price;
  }
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.update({_id: {id: req.body.id }}, {
        $set: {
          price: totalPrice,
          pieces: totalPieces,
          combinations: req.body.combinations,
          date: new Date(),
        }
      }, {
          upsert: true,
        }, function (err, results) {
        res.sendStatus(200);
        db.close();
      })
    } else {
      res.sendStatus(404);
    }
  })
})

router.post('/update-img', function (req, res) {
  var updateComb = {
    date: new Date(),
  }
  if (req.body.type === 'large') {
    updateComb.largeUrl = req.body.largeUrl;
  }
  if (req.body.type === 'thumb') {
    updateComb.thumbUrl = req.body.thumbUrl;
  }

  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.update({_id: ObjectId(req.body._id)}, {
        $set: updateComb }, {
          upsert: true,
        }, function (err, results) {
        res.sendStatus(200);
        db.close();
      })
    } else {
      res.sendStatus(404);
    }
  })
})

router.delete('/remove/:_id', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.remove({_id: ObjectId(req.params._id)}, function (err, result) {
        res.sendStatus(200);
        db.close;
      });
    } else {
      res.sendStatus(404);
    }
  })
});

router.delete('/remove-null/', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.remove({email: null }, function (err, result) {
        res.sendStatus(200);
        db.close;
      });
    } else {
      res.sendStatus(404);
    }
  })
});

module.exports = router;
<commit_msg>Change data order.<commit_after>var express = require('express');
var router = express.Router();

var mongodb = require('mongodb');
var dbClient = mongodb.MongoClient;
var ObjectId = mongodb.ObjectId;
var dbUrl = process.env.MONGODB_URI || 'mongodb://localhost/trand'

var request = require('request');
var _ = require('underscore');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');

router.use(bodyParser.json());
router.use(cookieParser());

router.get('/', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.find({email: req.currentUser.email}).toArray(function (err, results) {
        if (results.length>0) {
          res.json(results);
          db.close();
        } else {
          res.sendStatus(404);
          db.close();
        }
      })
    } else {
      res.sendStatus(404);
    }
  });
})

router.post('/new', function (req, res) {
  var items = req.body.combinations;
  var totalPrice = 0;
  var showed = _.where(items, {show: true});
  var totalPieces = showed.length;

  for (var i = 0; i < showed.length; i++) {
    totalPrice = totalPrice + showed[i].item.price;
  }

  var newComb = {
    email: req.currentUser.email,
    information: req.body.information,
    combinations: showed,
    price: totalPrice,
    pieces: totalPieces,
    date: new Date(),
  }

  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      if (typeof(req.body.information._id)==='undefined') {
        combinations.insert(newComb, function (err, results) {
          res.status(201).send(results.ops[0]._id);
          db.close();
        })
      } else {
        combinations.update({_id: ObjectId(req.body.information._id)}, {
          $set: {
            price: totalPrice,
            pieces: totalPieces,
            information: req.body.information,
            combinations: showed,
            date: new Date(),
          }
        }, function (err, results) {
          res.sendStatus(200);
          db.close();
        })
      }
    } else {
      res.sendStatus(404);
    }
  })
})

router.put('/update', function (req, res) {
  var updateComb = {
    _id: req.body.id,
    combinations: req.body.combinations,
  }
  var items = req.body.combinations;
  var totalPrice = 0;
  var showed = _.where(items, {show: true});
  var totalPieces = showed.length;

  for (var i = 0; i < showed.length; i++) {
    totalPrice = totalPrice + showed[i].item.price;
  }
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.update({_id: {id: req.body.id }}, {
        $set: {
          price: totalPrice,
          pieces: totalPieces,
          combinations: req.body.combinations,
          date: new Date(),
        }
      }, {
          upsert: true,
        }, function (err, results) {
        res.sendStatus(200);
        db.close();
      })
    } else {
      res.sendStatus(404);
    }
  })
})

router.post('/update-img', function (req, res) {
  var updateComb = {
    date: new Date(),
  }
  if (req.body.type === 'large') {
    updateComb.largeUrl = req.body.largeUrl;
  }
  if (req.body.type === 'thumb') {
    updateComb.thumbUrl = req.body.thumbUrl;
  }

  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.update({_id: ObjectId(req.body._id)}, {
        $set: updateComb }, {
          upsert: true,
        }, function (err, results) {
        res.sendStatus(200);
        db.close();
      })
    } else {
      res.sendStatus(404);
    }
  })
})

router.delete('/remove/:_id', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.remove({_id: ObjectId(req.params._id)}, function (err, result) {
        res.sendStatus(200);
        db.close;
      });
    } else {
      res.sendStatus(404);
    }
  })
});

router.delete('/remove-null/', function (req, res) {
  dbClient.connect(dbUrl, function (err, db) {
    if (!err) {
      var combinations = db.collection('combinations');
      combinations.remove({email: null }, function (err, result) {
        res.sendStatus(200);
        db.close;
      });
    } else {
      res.sendStatus(404);
    }
  })
});

module.exports = router;
<|endoftext|>


<commit_before>/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 3.1.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        Mario Rothauer <office@foodcoopshop.com>
 * @copyright     Copyright (c) Mario Rothauer, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
foodcoopshop.ModalProductNameEdit = {

    init : function() {

        var modalSelector = '#modal-product-name-edit';

        $('a.product-name-edit-button').on('click', function () {
            foodcoopshop.ModalProductNameEdit.getOpenHandler($(this), modalSelector);
        });

    },

    getHtml : function() {
        var html = '' + foodcoopshop.LocalizedJs.dialogProduct.Name + '
';
            html += '<input type="text" name="dialogName" id="dialogName" value="" />' + foodcoopshop.LocalizedJs.dialogProduct.ProductRenameInfoText + '
';
            html += '
';
            html += '
'
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.Unit + ' ' + foodcoopshop.LocalizedJs.dialogProduct.UnitDescriptionExample + '
';
                html += '<input type="text" name="dialogUnity" id="dialogUnity" value="" />
';
                html += '' + foodcoopshop.LocalizedJs.admin.EnterApproximateWeightInPriceDialog + '';
                html += '
';
            html += '
';
            html += '
';
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.DescriptionShort + '
';
                html += '<textarea class="ckeditor" name="dialogDescriptionShort" id="dialogDescriptionShort"></textarea>';
                html += '
';
            html += '
';
            html += '
';
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.DescriptionLong + '
';
                html += '
';
                    html += '<input type="checkbox" name="dialogIsDeclarationOk" id="dialogIsDeclarationOk" />' + foodcoopshop.LocalizedJs.dialogProduct.ProductDeclarationOK + ' ' + foodcoopshop.LocalizedJs.dialogProduct.Help + '
';
                    html += '<textarea class="ckeditor" name="dialogDescription" id="dialogDescription"></textarea>';
                html += '
';
            html += '
';
            html += '<input type="hidden" name="dialogProductId" id="dialogProductId" value="" />';
        return html;
    },

    getCloseHandler : function(modalSelector) {
        $(modalSelector).remove();
    },

    getSuccessHandler : function(modalSelector) {

        foodcoopshop.Helper.ajaxCall(
            '/admin/products/editName/',
            {
                productId: $('#dialogProductId').val(),
                name: $('#dialogName').val(),
                unity: $('#dialogUnity').val(),
                descriptionShort: CKEDITOR.instances['dialogDescriptionShort'].getData().trim(),
                description: CKEDITOR.instances['dialogDescription'].getData().trim(),
                isDeclarationOk: $('#dialogIsDeclarationOk:checked').length > 0 ? 1 : 0
            },
            {
                onOk: function (data) {
                    document.location.reload();
                },
                onError: function (data) {
                    foodcoopshop.Modal.appendFlashMessage(modalSelector, data.msg);
                    foodcoopshop.Modal.resetButtons(modalSelector);
                }
            }
        );
    },

    getOpenHandler : function(button, modalSelector) {

        foodcoopshop.Modal.appendModalToDom(
            modalSelector,
            foodcoopshop.LocalizedJs.dialogProduct.ChangeNameAndDescription,
            foodcoopshop.ModalProductNameEdit.getHtml()
        );

        foodcoopshop.Modal.bindSuccessButton(modalSelector, function() {
            foodcoopshop.ModalProductNameEdit.getSuccessHandler(modalSelector);
        });

        $(modalSelector).on('hidden.bs.modal', function (e) {
            foodcoopshop.ModalProductNameEdit.getCloseHandler(modalSelector);
        });

        $(modalSelector).modal();

        foodcoopshop.Helper.initCkeditor('dialogDescriptionShort');

        var row = button.closest('tr');
        var nameCell = row.find('td.cell-name');
        $(modalSelector + ' #dialogName').val(foodcoopshop.Admin.decodeEntities(nameCell.find('span.name-for-dialog .product-name').html()));
        $(modalSelector + ' #dialogIsDeclarationOk').prop('checked', row.find('span.is-declaration-ok-wrapper').data('is-declaration-ok'));
        var unityElement = nameCell.find('span.unity-for-dialog');
        var unity = '';
        if (unityElement.length > 0) {
            unity = foodcoopshop.Admin.decodeEntities(unityElement.html());
        }
        $(modalSelector + ' #dialogUnity').val(unity);
        CKEDITOR.instances['dialogDescriptionShort'].setData(nameCell.find('span.description-short-for-dialog').html());
        $(modalSelector + ' #dialogProductId').val(row.find('td.cell-id').html());

        var manufacturerId = row.data('manufacturerId');
        foodcoopshop.Helper.ajaxCall(
            '/admin/manufacturers/setElFinderUploadPath/' + manufacturerId,
            {},
            {
                onOk: function (data) {
                    foodcoopshop.Helper.initCkeditorSmallWithUpload('dialogDescription');
                    CKEDITOR.instances['dialogDescription'].setData(nameCell.find('span.description-for-dialog').html());
                },
                onError: function (data) {
                    foodcoopshop.Modal.appendFlashMessage(modalSelector, data.msg);
                    foodcoopshop.Modal.resetButtons(modalSelector);
                }
            }
        );

        // hide unity field if product has attributes
        if (button.closest('tr').next().hasClass('sub-row')) {
            $(modalSelector + ' .dialog-unity-wrapper').hide();
            $(modalSelector + ' #dialogLabelUnity').html(foodcoopshop.LocalizedJs.admin.Weight + '
' + '' + foodcoopshop.LocalizedJs.admin.EnterApproximateWeightInPriceDialog + '');
        }

        $(modalSelector + ' #dialogName').focus();

    }

};<commit_msg>remove tooltipster<commit_after>/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 3.1.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        Mario Rothauer <office@foodcoopshop.com>
 * @copyright     Copyright (c) Mario Rothauer, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
foodcoopshop.ModalProductNameEdit = {

    init : function() {

        var modalSelector = '#modal-product-name-edit';

        $('a.product-name-edit-button').on('click', function () {
            foodcoopshop.ModalProductNameEdit.getOpenHandler($(this), modalSelector);
        });

    },

    getHtml : function() {
        var html = '' + foodcoopshop.LocalizedJs.dialogProduct.Name + '
';
            html += '<input type="text" name="dialogName" id="dialogName" value="" />' + foodcoopshop.LocalizedJs.dialogProduct.ProductRenameInfoText + '
';
            html += '
';
            html += '
'
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.Unit + ' ' + foodcoopshop.LocalizedJs.dialogProduct.UnitDescriptionExample + '
';
                html += '<input type="text" name="dialogUnity" id="dialogUnity" value="" />
';
                html += '' + foodcoopshop.LocalizedJs.admin.EnterApproximateWeightInPriceDialog + '';
                html += '
';
            html += '
';
            html += '
';
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.DescriptionShort + '
';
                html += '<textarea class="ckeditor" name="dialogDescriptionShort" id="dialogDescriptionShort"></textarea>';
                html += '
';
            html += '
';
            html += '
';
                html += '' + foodcoopshop.LocalizedJs.dialogProduct.DescriptionLong + '
';
                html += '
';
                    html += '<input type="checkbox" name="dialogIsDeclarationOk" id="dialogIsDeclarationOk" />' + foodcoopshop.LocalizedJs.dialogProduct.ProductDeclarationOK + ' ' + foodcoopshop.LocalizedJs.dialogProduct.Help + '
';
                    html += '<textarea class="ckeditor" name="dialogDescription" id="dialogDescription"></textarea>';
                html += '
';
            html += '
';
            html += '<input type="hidden" name="dialogProductId" id="dialogProductId" value="" />';
        return html;
    },

    getCloseHandler : function(modalSelector) {
        $(modalSelector).remove();
    },

    getSuccessHandler : function(modalSelector) {

        foodcoopshop.Helper.ajaxCall(
            '/admin/products/editName/',
            {
                productId: $('#dialogProductId').val(),
                name: $('#dialogName').val(),
                unity: $('#dialogUnity').val(),
                descriptionShort: CKEDITOR.instances['dialogDescriptionShort'].getData().trim(),
                description: CKEDITOR.instances['dialogDescription'].getData().trim(),
                isDeclarationOk: $('#dialogIsDeclarationOk:checked').length > 0 ? 1 : 0
            },
            {
                onOk: function (data) {
                    document.location.reload();
                },
                onError: function (data) {
                    foodcoopshop.Modal.appendFlashMessage(modalSelector, data.msg);
                    foodcoopshop.Modal.resetButtons(modalSelector);
                }
            }
        );
    },

    getOpenHandler : function(button, modalSelector) {

        foodcoopshop.Modal.appendModalToDom(
            modalSelector,
            foodcoopshop.LocalizedJs.dialogProduct.ChangeNameAndDescription,
            foodcoopshop.ModalProductNameEdit.getHtml()
        );

        foodcoopshop.Modal.bindSuccessButton(modalSelector, function() {
            foodcoopshop.ModalProductNameEdit.getSuccessHandler(modalSelector);
        });

        $(modalSelector).on('hidden.bs.modal', function (e) {
            foodcoopshop.ModalProductNameEdit.getCloseHandler(modalSelector);
        });

        foodcoopshop.Modal.removeTooltipster();

        $(modalSelector).modal();

        foodcoopshop.Helper.initCkeditor('dialogDescriptionShort');

        var row = button.closest('tr');
        var nameCell = row.find('td.cell-name');
        $(modalSelector + ' #dialogName').val(foodcoopshop.Admin.decodeEntities(nameCell.find('span.name-for-dialog .product-name').html()));
        $(modalSelector + ' #dialogIsDeclarationOk').prop('checked', row.find('span.is-declaration-ok-wrapper').data('is-declaration-ok'));
        var unityElement = nameCell.find('span.unity-for-dialog');
        var unity = '';
        if (unityElement.length > 0) {
            unity = foodcoopshop.Admin.decodeEntities(unityElement.html());
        }
        $(modalSelector + ' #dialogUnity').val(unity);
        CKEDITOR.instances['dialogDescriptionShort'].setData(nameCell.find('span.description-short-for-dialog').html());
        $(modalSelector + ' #dialogProductId').val(row.find('td.cell-id').html());

        var manufacturerId = row.data('manufacturerId');
        foodcoopshop.Helper.ajaxCall(
            '/admin/manufacturers/setElFinderUploadPath/' + manufacturerId,
            {},
            {
                onOk: function (data) {
                    foodcoopshop.Helper.initCkeditorSmallWithUpload('dialogDescription');
                    CKEDITOR.instances['dialogDescription'].setData(nameCell.find('span.description-for-dialog').html());
                },
                onError: function (data) {
                    foodcoopshop.Modal.appendFlashMessage(modalSelector, data.msg);
                    foodcoopshop.Modal.resetButtons(modalSelector);
                }
            }
        );

        // hide unity field if product has attributes
        if (button.closest('tr').next().hasClass('sub-row')) {
            $(modalSelector + ' .dialog-unity-wrapper').hide();
            $(modalSelector + ' #dialogLabelUnity').html(foodcoopshop.LocalizedJs.admin.Weight + '
' + '' + foodcoopshop.LocalizedJs.admin.EnterApproximateWeightInPriceDialog + '');
        }

        $(modalSelector + ' #dialogName').focus();

    }

};<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import cookies from './config/cookies';
import {
  getApiUrl,
  getPublishProjectUrl
} from './screens/App/shared/utils/urlUtil';

const GET_PROJECTS_URL = getApiUrl('projects');
const GET_PROJECT_URL = getApiUrl('project');

/*
 * USER
 */

export const USER_FETCH_START = 'USER_FETCH_START'
function requestUser () {
  return {
    type: USER_FETCH_START
  }
}

export const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'
function fetchUserSuccess(result) {
  return {
    type: USER_FETCH_SUCCESS,
    result
  }
}

export const USER_FETCH_ERROR = 'USER_FETCH_ERROR'
function fetchUserError(error) {
  return {
    type: USER_FETCH_ERROR,
    error
  }
}

export function fetchUser() {
  return dispatch => {
    dispatch(requestUser())

    return fetch('https://api.github.com/user', {
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        }
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(fetchUserSuccess(json)))
  }
}

/*
 * GISTS
 */

export const GISTS_FETCH_START = 'GISTS_FETCH_START'
function requestGists () {
 return {
   type: GISTS_FETCH_START
 }
}

export const GISTS_FETCH_SUCCESS = 'GISTS_FETCH_SUCCESS'
function fetchGistsSuccess(result) {
 return {
   type: GISTS_FETCH_SUCCESS,
   result
 }
}

export const GISTS_FETCH_ERROR = 'GISTS_FETCH_ERROR'
function fetchGistsError(error) {
 return {
   type: GISTS_FETCH_ERROR,
   error
 }
}

export function fetchGists() {
 return dispatch => {
   dispatch(requestGists());
   return fetch('https://api.github.com/gists', {
       headers: {
         'Authorization': 'token ' + cookies.token,
         'Accept': 'application/vnd.github.v3'
       }
     })
     .then(req => req.json(), err => console.error(err))
     .then(json => dispatch(fetchGistsSuccess(json)));
 }
}

/*
 * PROJECTS
 */

export const PROJECTS_FETCH_START = 'PROJECTS_FETCH_START'
function requestProjects () {
 return {
   type: PROJECTS_FETCH_START
 }
}

export const PROJECTS_FETCH_SUCCESS = 'PROJECTS_FETCH_SUCCESS'
function fetchProjectsSuccess(result) {
 return {
   type: PROJECTS_FETCH_SUCCESS,
   result
 }
}

export const PROJECTS_FETCH_ERROR = 'PROJECTS_FETCH_ERROR'
function fetchProjectsError(error) {
 return {
   type: PROJECTS_FETCH_ERROR,
   error
 }
}

export function fetchProjects() {
  return dispatch => {
    dispatch(requestProjects());
    return fetch(GET_PROJECTS_URL, {
      headers: {
        'Authorization': 'token ' + cookies.token
      },
      credentials: 'include'
    })
    .then(req => req.json(), err => console.error(err))
    .then(json => dispatch(fetchProjectsSuccess(json)));
  }
}

/*
* PROJECT
*/

export const PROJECT_FETCH_START = 'PROJECT_FETCH_START'
function requestProject (id) {
 return {
   type: PROJECT_FETCH_START,
   id
 }
}

export const PROJECT_FETCH_SUCCESS = 'PROJECT_FETCH_SUCCESS'
function fetchProjectSuccess(result) {
 return {
   type: PROJECT_FETCH_SUCCESS,
   result
 }
}

export const PROJECT_FETCH_ERROR = 'PROJECT_FETCH_ERROR'
function fetchProjectError(error) {
 return {
   type: PROJECT_FETCH_ERROR,
   error
 }
}

export function fetchProject({ gistId, username }) {
 return dispatch => {
   dispatch(requestProject(gistId))

   return fetch(GET_PROJECT_URL + username + '/' + gistId, {
       headers: {
         'Authorization': 'token ' + cookies.token
       }
     })
     .then(res => res.json(), err => console.error(err))
     .then(json => dispatch(fetchProjectSuccess(json)));
 }
}

export function publishProject (project) {
  console.log(project);
  return (dispatch) => {
    dispatch({type: 'PUBLISH_PROJECT_REQUEST'});

    return fetch(getPublishProjectUrl(), {
      method: 'POST',
      headers: {
        'Authorization': 'token ' + cookies.token,
        'Content-Type': 'application/json; charset=utf-8'
      },
      credentials: 'include',
      body: JSON.stringify(project)
    })
    .then(res => res.json(), err => dispatch({type: 'PUBLISH_PROJECT_ERROR', error: err}))
    .then(json => dispatch({type: 'PUBLISH_PROJECT_SUCCESS', result: json}));
  }
}

/*
* CREATE GIST
*/

export const REQUEST_CREATE_GIST = 'REQUEST_CREATE_GIST'
function requestCreateGist () {
 return {
   type: REQUEST_CREATE_GIST
 }
}

export const RECEIVE_CREATE_GIST = 'RECEIVE_CREATE_GIST'
function receiveCreateGist (result) {
 return {
   type: RECEIVE_CREATE_GIST,
   result
 }
}

export const ERROR_CREATE_GIST = 'ERROR_CREATE_GIST'
function errorCreateGist (error) {
 return {
   type: ERROR_CREATE_GIST,
   error
 }
}

export function createGist(files) {
  return dispatch => {
    dispatch(requestCreateGist())

    return fetch('https://api.github.com/gists', {
        method: 'POST',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        },
        body: JSON.stringify({files})
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(receiveCreateGist(json)))
  }
}

/*
* FILES
*/

export const SAVE_FILE = 'SAVE_FILE'
function saveFileStart (id, file) {
  return {
    type: SAVE_FILE,
    id,
    file
  }
}

export const SAVE_FILE_SUCCESS = 'SAVE_FILE_SUCCESS'
function saveFileSuccess(result) {
  return {
    type: SAVE_FILE_SUCCESS,
    result
  }
}

export const SAVE_FILE_ERROR = 'SAVE_FILE_ERROR'
function saveFileError(error) {
  return {
    type: SAVE_FILE_ERROR,
    error
  }
}

export function saveFile(username, project, file) {
  return dispatch => {
    dispatch(saveFileStart(project.id, file))

    return fetch(GET_PROJECT_URL + username + '/' + project.id, {
        method: 'POST',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Content-Type': 'application/json; charset=utf-8'
        },
        body: JSON.stringify({
          isRepo: project.isRepo,
          file
        })
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(saveFileSuccess(json)))
  }
}

export function saveGistDescription(id, description) {
  return dispatch => {
    return fetch('https://api.github.com/gists/' + id, {
        method: 'PATCH',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        },
        body: JSON.stringify({description})
      })
  }
}

export const ADD_FILE = 'ADD_FILE'
export function addFile (filename) {
  return {
    type: ADD_FILE,
    filename
  }
}

export const OPEN_FILE = 'OPEN_FILE'
export function openFile (filename) {
  return {
    type: OPEN_FILE,
    filename
  }
}

/*
* FILES
*/

export const REQUEST_UPLOAD_FILES = 'REQUEST_UPLOAD_FILES'
function requestUploadFiles () {
 return {
   type: REQUEST_UPLOAD_FILES
 }
}

export const RECEIVE_UPLOAD_FILES = 'RECEIVE_UPLOAD_FILES'
function receiveUploadFiles (result) {
 return {
   type: RECEIVE_UPLOAD_FILES,
   result
 }
}

export const ERROR_UPLOAD_FILES = 'ERROR_UPLOAD_FILES'
function errorUploadFiles (error) {
 return {
   type: ERROR_UPLOAD_FILES,
   error
 }
}

export function uploadFiles(username, files) {
  return dispatch => {
    dispatch(requestUploadFiles())

    var data = new FormData()
    data.append('username', username)
    files.forEach((file, index) => data.append('file' + index, file))
    return fetch('/add_image', {
      method: 'POST',
      body: data
    })
    .then(req => req.json(), err => console.error(err))
    .then(json => dispatch(receiveUploadFiles(json)))
  }
}

export const REQUEST_USER_IMAGES = 'REQUEST_USER_IMAGES'
function requestUserImages () {
 return {
   type: REQUEST_USER_IMAGES
 }
}

export const RECEIVE_USER_IMAGES = 'RECEIVE_USER_IMAGES'
function receiveUserImages (result) {
 return {
   type: RECEIVE_USER_IMAGES,
   result
 }
}

export const ERROR_USER_IMAGES = 'ERROR_USER_IMAGES'
function errorUserImages (error) {
 return {
   type: ERROR_USER_IMAGES,
   error
 }
}

export function getUserImages(username) {
  return dispatch => {
    dispatch(requestUserImages())

    return fetch('/images/' + username)
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(receiveUserImages(json)))
  }
}

/*
* PREVIEW TYPE
*/

export const SET_PREVIEW_TYPE = 'SET_PREVIEW_TYPE'
export function setPreviewType (previewType) {
 return {
   type: SET_PREVIEW_TYPE,
   previewType
 }
}
<commit_msg>Remove errant log<commit_after>import fetch from 'isomorphic-fetch';
import cookies from './config/cookies';
import {
  getApiUrl,
  getPublishProjectUrl
} from './screens/App/shared/utils/urlUtil';

const GET_PROJECTS_URL = getApiUrl('projects');
const GET_PROJECT_URL = getApiUrl('project');

/*
 * USER
 */

export const USER_FETCH_START = 'USER_FETCH_START'
function requestUser () {
  return {
    type: USER_FETCH_START
  }
}

export const USER_FETCH_SUCCESS = 'USER_FETCH_SUCCESS'
function fetchUserSuccess(result) {
  return {
    type: USER_FETCH_SUCCESS,
    result
  }
}

export const USER_FETCH_ERROR = 'USER_FETCH_ERROR'
function fetchUserError(error) {
  return {
    type: USER_FETCH_ERROR,
    error
  }
}

export function fetchUser() {
  return dispatch => {
    dispatch(requestUser())

    return fetch('https://api.github.com/user', {
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        }
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(fetchUserSuccess(json)))
  }
}

/*
 * GISTS
 */

export const GISTS_FETCH_START = 'GISTS_FETCH_START'
function requestGists () {
 return {
   type: GISTS_FETCH_START
 }
}

export const GISTS_FETCH_SUCCESS = 'GISTS_FETCH_SUCCESS'
function fetchGistsSuccess(result) {
 return {
   type: GISTS_FETCH_SUCCESS,
   result
 }
}

export const GISTS_FETCH_ERROR = 'GISTS_FETCH_ERROR'
function fetchGistsError(error) {
 return {
   type: GISTS_FETCH_ERROR,
   error
 }
}

export function fetchGists() {
 return dispatch => {
   dispatch(requestGists());
   return fetch('https://api.github.com/gists', {
       headers: {
         'Authorization': 'token ' + cookies.token,
         'Accept': 'application/vnd.github.v3'
       }
     })
     .then(req => req.json(), err => console.error(err))
     .then(json => dispatch(fetchGistsSuccess(json)));
 }
}

/*
 * PROJECTS
 */

export const PROJECTS_FETCH_START = 'PROJECTS_FETCH_START'
function requestProjects () {
 return {
   type: PROJECTS_FETCH_START
 }
}

export const PROJECTS_FETCH_SUCCESS = 'PROJECTS_FETCH_SUCCESS'
function fetchProjectsSuccess(result) {
 return {
   type: PROJECTS_FETCH_SUCCESS,
   result
 }
}

export const PROJECTS_FETCH_ERROR = 'PROJECTS_FETCH_ERROR'
function fetchProjectsError(error) {
 return {
   type: PROJECTS_FETCH_ERROR,
   error
 }
}

export function fetchProjects() {
  return dispatch => {
    dispatch(requestProjects());
    return fetch(GET_PROJECTS_URL, {
      headers: {
        'Authorization': 'token ' + cookies.token
      },
      credentials: 'include'
    })
    .then(req => req.json(), err => console.error(err))
    .then(json => dispatch(fetchProjectsSuccess(json)));
  }
}

/*
* PROJECT
*/

export const PROJECT_FETCH_START = 'PROJECT_FETCH_START'
function requestProject (id) {
 return {
   type: PROJECT_FETCH_START,
   id
 }
}

export const PROJECT_FETCH_SUCCESS = 'PROJECT_FETCH_SUCCESS'
function fetchProjectSuccess(result) {
 return {
   type: PROJECT_FETCH_SUCCESS,
   result
 }
}

export const PROJECT_FETCH_ERROR = 'PROJECT_FETCH_ERROR'
function fetchProjectError(error) {
 return {
   type: PROJECT_FETCH_ERROR,
   error
 }
}

export function fetchProject({ gistId, username }) {
 return dispatch => {
   dispatch(requestProject(gistId))

   return fetch(GET_PROJECT_URL + username + '/' + gistId, {
       headers: {
         'Authorization': 'token ' + cookies.token
       }
     })
     .then(res => res.json(), err => console.error(err))
     .then(json => dispatch(fetchProjectSuccess(json)));
 }
}

export function publishProject (project) {
  return (dispatch) => {
    dispatch({type: 'PUBLISH_PROJECT_REQUEST'});

    return fetch(getPublishProjectUrl(), {
      method: 'POST',
      headers: {
        'Authorization': 'token ' + cookies.token,
        'Content-Type': 'application/json; charset=utf-8'
      },
      credentials: 'include',
      body: JSON.stringify(project)
    })
    .then(res => res.json(), err => dispatch({type: 'PUBLISH_PROJECT_ERROR', error: err}))
    .then(json => dispatch({type: 'PUBLISH_PROJECT_SUCCESS', result: json}));
  }
}

/*
* CREATE GIST
*/

export const REQUEST_CREATE_GIST = 'REQUEST_CREATE_GIST'
function requestCreateGist () {
 return {
   type: REQUEST_CREATE_GIST
 }
}

export const RECEIVE_CREATE_GIST = 'RECEIVE_CREATE_GIST'
function receiveCreateGist (result) {
 return {
   type: RECEIVE_CREATE_GIST,
   result
 }
}

export const ERROR_CREATE_GIST = 'ERROR_CREATE_GIST'
function errorCreateGist (error) {
 return {
   type: ERROR_CREATE_GIST,
   error
 }
}

export function createGist(files) {
  return dispatch => {
    dispatch(requestCreateGist())

    return fetch('https://api.github.com/gists', {
        method: 'POST',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        },
        body: JSON.stringify({files})
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(receiveCreateGist(json)))
  }
}

/*
* FILES
*/

export const SAVE_FILE = 'SAVE_FILE'
function saveFileStart (id, file) {
  return {
    type: SAVE_FILE,
    id,
    file
  }
}

export const SAVE_FILE_SUCCESS = 'SAVE_FILE_SUCCESS'
function saveFileSuccess(result) {
  return {
    type: SAVE_FILE_SUCCESS,
    result
  }
}

export const SAVE_FILE_ERROR = 'SAVE_FILE_ERROR'
function saveFileError(error) {
  return {
    type: SAVE_FILE_ERROR,
    error
  }
}

export function saveFile(username, project, file) {
  return dispatch => {
    dispatch(saveFileStart(project.id, file))

    return fetch(GET_PROJECT_URL + username + '/' + project.id, {
        method: 'POST',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Content-Type': 'application/json; charset=utf-8'
        },
        body: JSON.stringify({
          isRepo: project.isRepo,
          file
        })
      })
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(saveFileSuccess(json)))
  }
}

export function saveGistDescription(id, description) {
  return dispatch => {
    return fetch('https://api.github.com/gists/' + id, {
        method: 'PATCH',
        headers: {
          'Authorization': 'token ' + cookies.token,
          'Accept': 'application/vnd.github.v3'
        },
        body: JSON.stringify({description})
      })
  }
}

export const ADD_FILE = 'ADD_FILE'
export function addFile (filename) {
  return {
    type: ADD_FILE,
    filename
  }
}

export const OPEN_FILE = 'OPEN_FILE'
export function openFile (filename) {
  return {
    type: OPEN_FILE,
    filename
  }
}

/*
* FILES
*/

export const REQUEST_UPLOAD_FILES = 'REQUEST_UPLOAD_FILES'
function requestUploadFiles () {
 return {
   type: REQUEST_UPLOAD_FILES
 }
}

export const RECEIVE_UPLOAD_FILES = 'RECEIVE_UPLOAD_FILES'
function receiveUploadFiles (result) {
 return {
   type: RECEIVE_UPLOAD_FILES,
   result
 }
}

export const ERROR_UPLOAD_FILES = 'ERROR_UPLOAD_FILES'
function errorUploadFiles (error) {
 return {
   type: ERROR_UPLOAD_FILES,
   error
 }
}

export function uploadFiles(username, files) {
  return dispatch => {
    dispatch(requestUploadFiles())

    var data = new FormData()
    data.append('username', username)
    files.forEach((file, index) => data.append('file' + index, file))
    return fetch('/add_image', {
      method: 'POST',
      body: data
    })
    .then(req => req.json(), err => console.error(err))
    .then(json => dispatch(receiveUploadFiles(json)))
  }
}

export const REQUEST_USER_IMAGES = 'REQUEST_USER_IMAGES'
function requestUserImages () {
 return {
   type: REQUEST_USER_IMAGES
 }
}

export const RECEIVE_USER_IMAGES = 'RECEIVE_USER_IMAGES'
function receiveUserImages (result) {
 return {
   type: RECEIVE_USER_IMAGES,
   result
 }
}

export const ERROR_USER_IMAGES = 'ERROR_USER_IMAGES'
function errorUserImages (error) {
 return {
   type: ERROR_USER_IMAGES,
   error
 }
}

export function getUserImages(username) {
  return dispatch => {
    dispatch(requestUserImages())

    return fetch('/images/' + username)
      .then(req => req.json(), err => console.error(err))
      .then(json => dispatch(receiveUserImages(json)))
  }
}

/*
* PREVIEW TYPE
*/

export const SET_PREVIEW_TYPE = 'SET_PREVIEW_TYPE'
export function setPreviewType (previewType) {
 return {
   type: SET_PREVIEW_TYPE,
   previewType
 }
}
<|endoftext|>