<commit_before>import React, { Component } from "react";

class APIPage extends Component {

  render() {
    return (

Install via npm

          npm install react-day-picker --save

Use as React component

{`import React from "react";
import DayPicker from "react-day-picker";

const modifiers = {
  "firstOfMonth": (day) => day.getDate() === 1,
  "disabled": (day) => day.getDay() === 0
}

class MyComponent extends React.Component {
  render() {
    return <DayPicker modifiers={modifiers} />;
  }
}
`}

          See all the examples.

Styling

          You need to provide your own CSS to style the component. You can
          use this
          file as starting point.

Props

                Prop

                Type

              Description

                  initialMonth

Date

The month to display in the calendar. Default is the current month.

                  numberOfMonths

Number

The number of months, starting from initialMonth.
                Default is 1.

                  modifiers

Object

                  An object of functions returning a boolean.
The key of the object is
                  the CSS modifier that will be added to the CSS class of the day's cell if the function returns true.
                  The first argument of the function is the day (type Date) represented in the cell.

                  By default, the calendar will use today and outside modifiers.

                  For example, the following object will add DayPicker-Day--firstOfMonth class
                  to the cells corresponding to the first day of the month,
                  and DayPicker-Day--disabled to each sunday.

{`const modifiers = {
  "firstOfMonth": (day) => day.getDate() === 1,
  "disabled": (day) => day.getDay() === 0
}`}

                  renderDay

Function

                  Returns the content of a day cell. By default, it renders the day's date:
                  (day) => day.getDate().

                  It can return React elements. For example, the following code will display the day and the name of the people
                  celebrating a birthday that day.

{`render() {
  function renderDay(day) {
    const birthdays = getBirthdaysForDay(day)
    return (

          { day.getDate() }

        {
          birthdays.map((birthday) =>

              { birthday.name }

        }

    )
  }
  return <DayPicker renderDay={renderDay} />;
}`}

                  enableOutsideDays

Boolean

                  Display the days outside the current month. Default is false.

                  canChangeMonth

Boolean

                  Enable the navigation between months. Default is true.

                  localeUtils

Object

                  Object of functions to format dates and to get the first
                  day of the week. Pass your own utils to support localization.

                  Must conform to the following protocol:

{`{
  formatMonthTitle(d: Date, locale: string): string
  formatWeekdayShort(dayIndex: Number, locale: string): string
  formatWeekdayLong(dayIndex: Number, locale: string): string
  getFirstDayOfWeek(locale: string): string
}
`}

                  By default the used locale is English (US). See also Localization with moment.js

                  locale

String

                  The locale passed to localeUtils functions.
                  Default is en.

                  onDayClick

Function

                  Event handler when the user clicks on a day cell. Example:

{`function onDayClick(e, day, modifiers) {
  console.log("Day %s has been clicked", day.toString());
}`}

                  onDayTouchTap

Function

                  Event handler when the user taps (or click) on a day cell. Requires react-tap-event-plugin. Example:

{`
import reactTapEvent from "react-tap-event-plugin";
reactTapEvent()

function onDayTouchTap(e, day, modifiers) {
  console.log("Day %s has been tapped", day.toString());
}`}

                  onDayMouseEnter

Function

                  Event handler when the mouse enters a day cell. Example:

{`function onDayMouseEnter(e, day, modifiers) {
    // do stuff, e.g. show a tooltip
}`}

                  onDayMouseLeave

Function

                  Event handler when the mouse leave a day cell. Example:

{`function onDayMouseLeave(e, day, modifiers) {
   // do things, e.g. hide a tooltip
}`}

                  onMonthChange

Function

                  Event handler when the month is changed, i.e. clicking the
                  navigation buttons or using the keyboard. Example:

{`function onMonthChange(e, day, modifiers) {
   // do magic, e.g. request a server for days availability
}`}

                  onCaptionClick

Function

                  Event handler when the user clicks on the caption in the header displaying the month. Example:

{`function onCaptionClick(e, currentMonth) {
  // Set daypicker to initial month
  const daypicker = this.refs.daypicker;
  daypicker.showMonth(daypicker.props.initialMonth);
}`}

                  className

String

                  Class names to add to the root node.

                  style

Object

                  A custom style object to add to the root node.

                  tabIndex

Number

                  The tab index for keyboard navigation. Default is 0.

Methods

                Name

              Description

                  showMonth(d: Date)

Shows the specified month.

                  showPreviousMonth()

Shows the previous month(s).

                  showNextMonth()

Shows the next month(s).

    );
  }

}

export default APIPage;
<commit_msg>Use ES6 syntax<commit_after>import React, { Component } from "react";

class APIPage extends Component {

  render() {
    return (

Install via npm

          npm install react-day-picker --save

Use as React component

{`var React = require("react");
var DayPicker = require("react-day-picker");

var modifiers = {
  "firstOfMonth": (day) => day.getDate() === 1,
  "disabled": (day) => day.getDay() === 0
}

var MyComponent = React.createComponent({
  render() {
    return <DayPicker modifiers={modifiers} />;
  }
})
`}

          See all the examples.

Styling

          You need to provide your own CSS to style the component. You can
          use this
          file as starting point.

Props

                Prop

                Type

              Description

                  initialMonth

Date

The month to display in the calendar. Default is the current month.

                  numberOfMonths

Number

The number of months, starting from initialMonth.
                Default is 1.

                  modifiers

Object

                  An object of functions returning a boolean.
The key of the object is
                  the CSS modifier that will be added to the CSS class of the day's cell if the function returns true.
                  The first argument of the function is the day (type Date) represented in the cell.

                  By default, the calendar will use today and outside modifiers.

                  For example, the following object will add DayPicker-Day--firstOfMonth class
                  to the cells corresponding to the first day of the month,
                  and DayPicker-Day--disabled to each sunday.

{`var modifiers = {
  "firstOfMonth": (day) => day.getDate() === 1,
  "disabled": (day) => day.getDay() === 0
}`}

                  renderDay

Function

                  Returns the content of a day cell. By default, it renders the day's date:
                  (day) => day.getDate().

                  It can return React elements. For example, the following code will display the day and the name of the people
                  celebrating a birthday that day.

{`render() {
  function renderDay(day) {
    var birthdays = getBirthdaysForDay(day)
    return (

          { day.getDate() }

        {
          birthdays.map((birthday) =>

              { birthday.name }

        }

    )
  }
  return <DayPicker renderDay={renderDay} />;
}`}

                  enableOutsideDays

Boolean

                  Display the days outside the current month. Default is false.

                  canChangeMonth

Boolean

                  Enable the navigation between months. Default is true.

                  localeUtils

Object

                  Object of functions to format dates and to get the first
                  day of the week. Pass your own utils to support localization.

                  Must conform to the following protocol:

{`{
  formatMonthTitle(d: Date, locale: string): string
  formatWeekdayShort(dayIndex: Number, locale: string): string
  formatWeekdayLong(dayIndex: Number, locale: string): string
  getFirstDayOfWeek(locale: string): string
}
`}

                  By default the used locale is English (US). See also Localization with moment.js

                  locale

String

                  The locale passed to localeUtils functions.
                  Default is en.

                  onDayClick

Function

                  Event handler when the user clicks on a day cell. Example:

{`function onDayClick(e, day, modifiers) {
  console.log("Day %s has been clicked", day.toString());
}`}

                  onDayTouchTap

Function

                  Event handler when the user taps (or click) on a day cell. Requires react-tap-event-plugin. Example:

{`
var reactTapEvent = require("react-tap-event-plugin");
reactTapEvent()

function onDayTouchTap(e, day, modifiers) {
  console.log("Day %s has been tapped", day.toString());
}`}

                  onDayMouseEnter

Function

                  Event handler when the mouse enters a day cell. Example:

{`function onDayMouseEnter(e, day, modifiers) {
    // do stuff, e.g. show a tooltip
}`}

                  onDayMouseLeave

Function

                  Event handler when the mouse leave a day cell. Example:

{`function onDayMouseLeave(e, day, modifiers) {
   // do things, e.g. hide a tooltip
}`}

                  onMonthChange

Function

                  Event handler when the month is changed, i.e. clicking the
                  navigation buttons or using the keyboard. Example:

{`function onMonthChange(e, day, modifiers) {
   // do magic, e.g. request a server for days availability
}`}

                  onCaptionClick

Function

                  Event handler when the user clicks on the caption in the header displaying the month. Example:

{`function onCaptionClick(e, currentMonth) {
  // Set daypicker to initial month
  var daypicker = this.refs.daypicker;
  daypicker.showMonth(daypicker.props.initialMonth);
}`}

                  className

String

                  Class names to add to the root node.

                  style

Object

                  A custom style object to add to the root node.

                  tabIndex

Number

                  The tab index for keyboard navigation. Default is 0.

Methods

                Name

              Description

                  showMonth(d: Date)

Shows the specified month.

                  showPreviousMonth()

Shows the previous month(s).

                  showNextMonth()

Shows the next month(s).

    );
  }

}

export default APIPage;
<|endoftext|>


<commit_before>import 'core-js/es6/string';
import path from 'path';

const homeTmpl = './template/Home/index';
const contentTmpl = './template/Content/index';
const redirectTmpl = './template/Redirect';
const appShellTmpl = './template/AppShell';

function pickerGenerator(module) {
  const tester = new RegExp(`^docs/${module}`);
  return (markdownData) => {
    const { filename } = markdownData.meta;
    if (tester.test(filename)
        && !/\/demo$/.test(path.dirname(filename))) {
      return {
        meta: markdownData.meta,
      };
    }
    return null;
  };
}

module.exports = {
  lazyLoad(nodePath, nodeValue) {
    if (typeof nodeValue === 'string') {
      return true;
    }
    return nodePath.endsWith('/demo');
  },
  pick: {
    components(markdownData) {
      const { filename } = markdownData.meta;
      if (!/^components/.test(filename)
          || /[/\\]demo$/.test(path.dirname(filename))) {
        return null;
      }
      return {
        meta: markdownData.meta,
      };
    },
    changelog(markdownData) {
      if (/CHANGELOG/.test(markdownData.meta.filename)) {
        return {
          meta: markdownData.meta,
        };
      }
      return null;
    },
    'docs/pattern': pickerGenerator('pattern'),
    'docs/react': pickerGenerator('react'),
    'docs/resource': pickerGenerator('resource'),
    'docs/spec': pickerGenerator('spec'),
  },
  plugins: [
    'bisheng-plugin-description',
    'bisheng-plugin-toc?maxDepth=2&keepElem',
    'bisheng-plugin-antd',
    'bisheng-plugin-react?lang=__react',
  ],
  routes: {
    path: '/',
    component: './template/Layout/index',
    indexRoute: { component: homeTmpl },
    childRoutes: [{
      path: 'app-shell',
      component: appShellTmpl,
    }, {
      path: 'index-cn',
      component: homeTmpl,
    }, {
      path: 'docs/pattern/:children',
      component: redirectTmpl,
    }, {
      path: 'docs/react/:children',
      component: contentTmpl,
    }, {
      path: 'changelog',
      component: contentTmpl,
    }, {
      path: 'changelog-cn',
      component: contentTmpl,
    }, {
      path: 'components/:children/',
      component: contentTmpl,
    }, {
      path: 'docs/spec/feature',
      component: redirectTmpl,
    }, {
      path: 'docs/spec/feature-cn',
      component: redirectTmpl,
    }, {
      path: 'docs/spec/:children',
      component: contentTmpl,
    }, {
      path: 'docs/resource/:children',
      component: redirectTmpl,
    }],
  },
};
<commit_msg>:bug: fix npm start<commit_after>require('core-js/es6/string');
const path = require('path');

const homeTmpl = './template/Home/index';
const contentTmpl = './template/Content/index';
const redirectTmpl = './template/Redirect';
const appShellTmpl = './template/AppShell';

function pickerGenerator(module) {
  const tester = new RegExp(`^docs/${module}`);
  return (markdownData) => {
    const { filename } = markdownData.meta;
    if (tester.test(filename)
        && !/\/demo$/.test(path.dirname(filename))) {
      return {
        meta: markdownData.meta,
      };
    }
    return null;
  };
}

module.exports = {
  lazyLoad(nodePath, nodeValue) {
    if (typeof nodeValue === 'string') {
      return true;
    }
    return nodePath.endsWith('/demo');
  },
  pick: {
    components(markdownData) {
      const { filename } = markdownData.meta;
      if (!/^components/.test(filename)
          || /[/\\]demo$/.test(path.dirname(filename))) {
        return null;
      }
      return {
        meta: markdownData.meta,
      };
    },
    changelog(markdownData) {
      if (/CHANGELOG/.test(markdownData.meta.filename)) {
        return {
          meta: markdownData.meta,
        };
      }
      return null;
    },
    'docs/pattern': pickerGenerator('pattern'),
    'docs/react': pickerGenerator('react'),
    'docs/resource': pickerGenerator('resource'),
    'docs/spec': pickerGenerator('spec'),
  },
  plugins: [
    'bisheng-plugin-description',
    'bisheng-plugin-toc?maxDepth=2&keepElem',
    'bisheng-plugin-antd',
    'bisheng-plugin-react?lang=__react',
  ],
  routes: {
    path: '/',
    component: './template/Layout/index',
    indexRoute: { component: homeTmpl },
    childRoutes: [{
      path: 'app-shell',
      component: appShellTmpl,
    }, {
      path: 'index-cn',
      component: homeTmpl,
    }, {
      path: 'docs/pattern/:children',
      component: redirectTmpl,
    }, {
      path: 'docs/react/:children',
      component: contentTmpl,
    }, {
      path: 'changelog',
      component: contentTmpl,
    }, {
      path: 'changelog-cn',
      component: contentTmpl,
    }, {
      path: 'components/:children/',
      component: contentTmpl,
    }, {
      path: 'docs/spec/feature',
      component: redirectTmpl,
    }, {
      path: 'docs/spec/feature-cn',
      component: redirectTmpl,
    }, {
      path: 'docs/spec/:children',
      component: contentTmpl,
    }, {
      path: 'docs/resource/:children',
      component: redirectTmpl,
    }],
  },
};
<|endoftext|>


<commit_before>(function(window)
{
    var Gitana = window.Gitana;

    Gitana.Stack = Gitana.AbstractPlatformObject.extend(
    /** @lends Gitana.Stack.prototype */
    {
        /**
         * @constructs
         * @augments Gitana.AbstractPlatformObject
         *
         * @class Stack
         *
         * @param {Gitana.Platform} platform
         * @param [Object] object json object (if no callback required for populating)
         */
        constructor: function(platform, object)
        {
            this.base(platform, object);

            this.objectType = "Gitana.Stack";
        },

        /**
         * @OVERRIDE
         */
        getUri: function()
        {
            return "/stacks/" + this.getId();
        },

        /**
         * @override
         */
        clone: function()
        {
            return this.getFactory().stack(this.getPlatform(), this.object);
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // TEAMABLE
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Reads a team.
         *
         * @param teamKey
         *
         * @chainable team
         */
        readTeam: function(teamKey)
        {
            var uriFunction = function()
            {
                return this.getUri() + "/teams/" + teamKey;
            };

            var chainable = this.getFactory().team(this.getPlatform(), this, teamKey);
            return this.chainGet(chainable, uriFunction);
        },

        /**
         * Lists teams.
         *
         * @chainable map of teams
         */
        listTeams: function()
        {
            var uriFunction = function()
            {
                return this.getUri() + "/teams";
            };

            var chainable = this.getFactory().teamMap(this.getCluster(), this);
            return this.chainGet(chainable, uriFunction);
        },

        /**
         * Creates a team.
         *
         * @param teamKey
         * @param object
         *
         * @chainable team
         */
        createTeam: function(teamKey, object)
        {
            if (!object)
            {
                object = {};
            }

            var uriFunction = function()
            {
                return this.getUri() + "/teams?key=" + teamKey;
            };

            var self = this;

            var chainable = this.getFactory().team(this.getPlatform(), this, teamKey);
            return this.chainPostResponse(chainable, uriFunction, {}, object).then(function() {
                this.subchain(self).readTeam(teamKey).then(function() {
                    Gitana.copyInto(chainable.object, this.object);
                });
            });
        },

        /**
         * Gets the owners team
         *
         * @chained team
         */
        readOwnersTeam: function()
        {
            return this.readTeam("owners");
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // END OF TEAMABLE
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // ATTACHMENTS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Hands back an attachments map.
         *
         * @chained attachment map
         *
         * @public
         */
        listAttachments: function()
        {
            var self = this;

            var attachmentMap = new Gitana.BinaryAttachmentMap(this);

            var result = this.subchain(attachmentMap);
            result.subchain().then(function() {

                var chain = this;

                self.getDriver().gitanaGet(self.getUri() + "/attachments", null, function(response) {

                    var map = {};
                    for (var i = 0; i < response.rows.length; i++)
                    {
                        map[response.rows[i]["_doc"]] = response.rows[i];
                    }
                    attachmentMap.handleMap(map);

                    chain.next();
                });

                return false;
            });

            return result;
        },

        /**
         * Picks off a single attachment
         *
         * @chained attachment
         *
         * @param attachmentId
         */
        attachment: function(attachmentId)
        {
            return this.listAttachments().select(attachmentId);
        },

        /**
         * Creates an attachment.
         *
         * When using this method from within the JS driver, it really only works for text-based content such
         * as JSON or text.
         *
         * @chained attachment
         *
         * @param attachmentId (use null or false for default attachment)
         * @param contentType
         * @param data
         */
        attach: function(attachmentId, contentType, data)
        {
            var self = this;

            // the thing we're handing back
            var result = this.subchain(new Gitana.BinaryAttachment(this, attachmentId));

            // preload some work onto a subchain
            result.subchain().then(function() {

                // upload the attachment
                var uploadUri = self.getUri() + "/attachments/" + attachmentId;
                this.chainUpload(this, uploadUri, null, contentType, data).then(function() {

                    // read back attachment information and plug onto result
                    this.subchain(self).listAttachments().select(attachmentId).then(function() {
                        result.handleAttachment(this.attachment);
                    });
                });
            });

            return result;
        },

        /**
         * Deletes an attachment.
         *
         * @param attachmentId
         */
        unattach: function(attachmentId)
        {
            return this.subchain().then(function() {

                this.chainDelete(this, this.getUri() + "/attachments/" + attachmentId).then(function() {

                    // TODO

                });
            });
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // LOGS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Queries for log entries.
         *
         * @chained log entry map
         *
         * @param {Object} query Query for finding log entries.
         * @param [Object] pagination pagination (optional)
         */
        queryLogEntries: function(query, pagination)
        {
            var self = this;
            var uriFunction = function()
            {
                return self.getUri() + "/logs/query";
            };

            if (!query)
            {
                query = {};
            }

            var chainable = this.getFactory().logEntryMap(this.getCluster());

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            return this.chainPost(chainable, uriFunction, params, query);
        },

        /**
         * Read a log entry.
         *
         * @chained log entry
         *
         * @param {String} jobId
         */
        readLogEntry: function(logEntryId)
        {
            var self = this;
            var uriFunction = function()
            {
                return self.getUri() + "/logs/" + logEntryId;
            };

            var chainable = this.getFactory().logEntry(this.getCluster());

            return this.chainGet(chainable, uriFunction);
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // STACK OPERATIONS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Assigns a data store to the stack
         *
         * @chained this
         *
         * @param {Gitana.DataStore} datastore a platform datastore
         * @param {String} key optional key
         */
        assignDataStore: function(datastore, key)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/assign";
            };

            var params = {
                "type": datastore.getType(),
                "id": datastore.getId()
            };

            if (key)
            {
                params["key"] = key;
            }

            return this.chainPostEmpty(this, uriFunction, params);
        },

        /**
         * Unassigns a data store from the stack
         *
         * @chained this
         *
         * @param {String} key optional key
         */
        unassignDataStore: function(key)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/unassign";
            };

            var params = {
                "key": key
            };

            return this.chainPostEmpty(this, uriFunction, params);

        },

        /**
         * Lists the data stores in this stack.
         *
         * @chained datastore map
         *
         * @param pagination
         */
        listDataStores: function(pagination)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores";
            };

            var chainable = this.getFactory().platformDataStoreMap(this.getPlatform());

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            return this.chainGet(chainable, uriFunction, params);
        },

        /**
         * Lists the data stores in this stack.
         *
         * @chained datastore map
         *
         * @param {Object} query
         * @param [Object] pagination pagination (optional)
         */
        queryDataStores: function(query, pagination)
        {
            var self = this;

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/query";
            };

            var chainable = this.getFactory().platformDataStoreMap(this.getPlatform());

            return this.chainPost(chainable, uriFunction, params, query);
        },

        /**
         * Checks whether a datastore exists for the given key on this stack.
         * This passes the result (true/false) to the chaining function.
         *
         * @chained this
         *
         * @param {String} key the datastore key
         * @param {Function} callback
         */
        existsDataStore: function(key, callback)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/check?key=" + key;
            };

            return this.chainPostResponse(this, uriFunction).then(function() {
                callback.call(this, this.response["exists"]);
            });
        }

    });

})(window);
<commit_msg>Made stack.assignDatastore method also takes a simple json object input which contains datastore type, id and optional key.<commit_after>(function(window)
{
    var Gitana = window.Gitana;

    Gitana.Stack = Gitana.AbstractPlatformObject.extend(
    /** @lends Gitana.Stack.prototype */
    {
        /**
         * @constructs
         * @augments Gitana.AbstractPlatformObject
         *
         * @class Stack
         *
         * @param {Gitana.Platform} platform
         * @param [Object] object json object (if no callback required for populating)
         */
        constructor: function(platform, object)
        {
            this.base(platform, object);

            this.objectType = "Gitana.Stack";
        },

        /**
         * @OVERRIDE
         */
        getUri: function()
        {
            return "/stacks/" + this.getId();
        },

        /**
         * @override
         */
        clone: function()
        {
            return this.getFactory().stack(this.getPlatform(), this.object);
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // TEAMABLE
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Reads a team.
         *
         * @param teamKey
         *
         * @chainable team
         */
        readTeam: function(teamKey)
        {
            var uriFunction = function()
            {
                return this.getUri() + "/teams/" + teamKey;
            };

            var chainable = this.getFactory().team(this.getPlatform(), this, teamKey);
            return this.chainGet(chainable, uriFunction);
        },

        /**
         * Lists teams.
         *
         * @chainable map of teams
         */
        listTeams: function()
        {
            var uriFunction = function()
            {
                return this.getUri() + "/teams";
            };

            var chainable = this.getFactory().teamMap(this.getCluster(), this);
            return this.chainGet(chainable, uriFunction);
        },

        /**
         * Creates a team.
         *
         * @param teamKey
         * @param object
         *
         * @chainable team
         */
        createTeam: function(teamKey, object)
        {
            if (!object)
            {
                object = {};
            }

            var uriFunction = function()
            {
                return this.getUri() + "/teams?key=" + teamKey;
            };

            var self = this;

            var chainable = this.getFactory().team(this.getPlatform(), this, teamKey);
            return this.chainPostResponse(chainable, uriFunction, {}, object).then(function() {
                this.subchain(self).readTeam(teamKey).then(function() {
                    Gitana.copyInto(chainable.object, this.object);
                });
            });
        },

        /**
         * Gets the owners team
         *
         * @chained team
         */
        readOwnersTeam: function()
        {
            return this.readTeam("owners");
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // END OF TEAMABLE
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // ATTACHMENTS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Hands back an attachments map.
         *
         * @chained attachment map
         *
         * @public
         */
        listAttachments: function()
        {
            var self = this;

            var attachmentMap = new Gitana.BinaryAttachmentMap(this);

            var result = this.subchain(attachmentMap);
            result.subchain().then(function() {

                var chain = this;

                self.getDriver().gitanaGet(self.getUri() + "/attachments", null, function(response) {

                    var map = {};
                    for (var i = 0; i < response.rows.length; i++)
                    {
                        map[response.rows[i]["_doc"]] = response.rows[i];
                    }
                    attachmentMap.handleMap(map);

                    chain.next();
                });

                return false;
            });

            return result;
        },

        /**
         * Picks off a single attachment
         *
         * @chained attachment
         *
         * @param attachmentId
         */
        attachment: function(attachmentId)
        {
            return this.listAttachments().select(attachmentId);
        },

        /**
         * Creates an attachment.
         *
         * When using this method from within the JS driver, it really only works for text-based content such
         * as JSON or text.
         *
         * @chained attachment
         *
         * @param attachmentId (use null or false for default attachment)
         * @param contentType
         * @param data
         */
        attach: function(attachmentId, contentType, data)
        {
            var self = this;

            // the thing we're handing back
            var result = this.subchain(new Gitana.BinaryAttachment(this, attachmentId));

            // preload some work onto a subchain
            result.subchain().then(function() {

                // upload the attachment
                var uploadUri = self.getUri() + "/attachments/" + attachmentId;
                this.chainUpload(this, uploadUri, null, contentType, data).then(function() {

                    // read back attachment information and plug onto result
                    this.subchain(self).listAttachments().select(attachmentId).then(function() {
                        result.handleAttachment(this.attachment);
                    });
                });
            });

            return result;
        },

        /**
         * Deletes an attachment.
         *
         * @param attachmentId
         */
        unattach: function(attachmentId)
        {
            return this.subchain().then(function() {

                this.chainDelete(this, this.getUri() + "/attachments/" + attachmentId).then(function() {

                    // TODO

                });
            });
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // LOGS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Queries for log entries.
         *
         * @chained log entry map
         *
         * @param {Object} query Query for finding log entries.
         * @param [Object] pagination pagination (optional)
         */
        queryLogEntries: function(query, pagination)
        {
            var self = this;
            var uriFunction = function()
            {
                return self.getUri() + "/logs/query";
            };

            if (!query)
            {
                query = {};
            }

            var chainable = this.getFactory().logEntryMap(this.getCluster());

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            return this.chainPost(chainable, uriFunction, params, query);
        },

        /**
         * Read a log entry.
         *
         * @chained log entry
         *
         * @param {String} jobId
         */
        readLogEntry: function(logEntryId)
        {
            var self = this;
            var uriFunction = function()
            {
                return self.getUri() + "/logs/" + logEntryId;
            };

            var chainable = this.getFactory().logEntry(this.getCluster());

            return this.chainGet(chainable, uriFunction);
        },

        //////////////////////////////////////////////////////////////////////////////////////////
        //
        // STACK OPERATIONS
        //
        //////////////////////////////////////////////////////////////////////////////////////////

        /**
         * Assigns a data store to the stack
         * It takes datastore and key (optional) as input or a json object than contains
         * datastore type, id and key (optional)
         *
         * @chained this
         *
         * @param {Gitana.DataStore} datastore a platform datastore
         * @param {String} key optional key
         */
        assignDataStore: function(datastore, key)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/assign";
            };

            var args = Gitana.makeArray(arguments);

            var params;

            if (args.length == 1)
            {
                var arg = args.shift();

                if (arg.getType && arg.getId)
                {
                    params = {
                        "type": arg.getType(),
                        "id": arg.getId()
                    };
                }
                else
                {
                    params = arg;
                }
            }
            else
            {
                datastore = args.shift();
                key = args.shift();
                params = {
                    "type": datastore.getType(),
                    "id": datastore.getId()
                };

                if (key)
                {
                    params["key"] = key;
                }
            }

            return this.chainPostEmpty(this, uriFunction, params);
        },

        /**
         * Unassigns a data store from the stack
         *
         * @chained this
         *
         * @param {String} key optional key
         */
        unassignDataStore: function(key)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/unassign";
            };

            var params = {
                "key": key
            };

            return this.chainPostEmpty(this, uriFunction, params);

        },

        /**
         * Lists the data stores in this stack.
         *
         * @chained datastore map
         *
         * @param pagination
         */
        listDataStores: function(pagination)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores";
            };

            var chainable = this.getFactory().platformDataStoreMap(this.getPlatform());

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            return this.chainGet(chainable, uriFunction, params);
        },

        /**
         * Lists the data stores in this stack.
         *
         * @chained datastore map
         *
         * @param {Object} query
         * @param [Object] pagination pagination (optional)
         */
        queryDataStores: function(query, pagination)
        {
            var self = this;

            // prepare params (with pagination)
            var params = {};
            if (pagination)
            {
                Gitana.copyInto(params, pagination);
            }

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/query";
            };

            var chainable = this.getFactory().platformDataStoreMap(this.getPlatform());

            return this.chainPost(chainable, uriFunction, params, query);
        },

        /**
         * Checks whether a datastore exists for the given key on this stack.
         * This passes the result (true/false) to the chaining function.
         *
         * @chained this
         *
         * @param {String} key the datastore key
         * @param {Function} callback
         */
        existsDataStore: function(key, callback)
        {
            var self = this;

            var uriFunction = function()
            {
                return self.getUri() + "/datastores/check?key=" + key;
            };

            return this.chainPostResponse(this, uriFunction).then(function() {
                callback.call(this, this.response["exists"]);
            });
        }

    });

})(window);
<|endoftext|>


<commit_before>Posts = new Meteor.Collection("posts");
Meteor.autosubscribe(function () {
  Meteor.subscribe("directory");
  Meteor.subscribe("restrictiveUsers");
  Meteor.subscribe("posts");
});

Template.editor.rendered = function() {
  if (Meteor.user() !== null)
  {
    new Medium({
      element: document.getElementById('editor'),
      modifier: 'auto',
      placeholder: "",
      autofocus: false,
      autoHR: true,
      mode: 'rich',
      maxLength: -1,
      modifiers: {
          66: 'bold',
          73: 'italicize',
          85: 'underline',
          86: 'paste'
      },
      tags: {
          paragraph: 'p',
          outerLevel: ['pre','blockquote', 'figure', 'hr'],
          innerLevel: ['a', 'b', 'u', 'i', 'img', 'strong']
      },
      cssClasses: {
          editor: 'Medium',
          pasteHook: 'Medium-paste-hook',
          placeholder: 'Medium-placeholder'
      }
    });
    new Medium({
      element: document.getElementById('title'),
      mode: 'inline',
      maxLength: 25,
      placeholder: ''
    });
    if(typeof(Storage)!=="undefined")
    {
      if (localStorage.editor !== "" || localStorage.title !== "")
      {
        $('#title').html(localStorage.title);
        $('#editor').html(localStorage.editor);
      }
    }
    else
    {
    // Sorry! No web storage support..
    }
  }
};

Template.editor.isLoggedIn = function() {
  return (Meteor.user() !== null);
};

Template.editor.profileImage = function() {
  if (Meteor.user())
    return Meteor.user().services.twitter.profile_image_url;
};

Template.editor.events({
  'click button.minimal': function () {
    var title = $('#title').text();
    var content = $('#editor').html();
    Meteor.call("publishPost", title, content, function (data, err){
      console.log("waiting for callback");
      console.log(data);
      var author = Meteor.user().services.twitter.screenName;
      //clear localStorage
      //if they don't have it, there's nothing to be cleared because they suck
      if(typeof(Storage)!=="undefined")
      {
        localStorage.title = "";
        localStorage.editor = "";
      }
      Meteor.Router.to('/' + author + '/' + escape(title));
    });
  },

  'keyup' : function () {
    if(typeof(Storage)!=="undefined")
    {
      localStorage.title = $('#title').html();
      localStorage.editor = $('#editor').html();
    }
  }
});

Template.showPost.events({
  'click button.minimal.btnUpdate': function () {
    var id = Session.get("currentPostId");
    var content = $('#content').html();
    Meteor.call("updatePost", id, content, function (data, err){
      var author = Meteor.user().services.twitter.screenName;
      Meteor.Router.to('/' + author + '/' + escape(Session.get('currentPostTitle')));
    });
  },

  'click button.minimal.btnDelete': function () {
    var confirm = window.confirm("Are you sure you want to delete this post? This cannot be undone later.");
    if (confirm === true){
      Meteor.call("deletePost", Session.get('currentPostId'));
      Meteor.Router.to('/' + Meteor.user().services.twitter.screenName);
    }
  }
});

Template.showPost.rendered = function () {
  if (Meteor.user() !== null)
  {
    if (Meteor.user().services.twitter.screenName === Session.get('currentPostAuthor')){
      new Medium({
      element: document.getElementById('content'),
      modifier: 'auto',
      placeholder: "",
      autofocus: false,
      autoHR: true,
      mode: 'rich',
      maxLength: -1,
      modifiers: {
          66: 'bold',
          73: 'italicize',
          85: 'underline',
          86: 'paste'
      },
      tags: {
          paragraph: 'p',
          outerLevel: ['pre','blockquote', 'figure', 'hr'],
          innerLevel: ['a', 'b', 'u', 'i', 'img', 'strong']
      },
      cssClasses: {
          editor: 'Medium',
          pasteHook: 'Medium-paste-hook',
          placeholder: 'Medium-placeholder'
      }
    });
    }
  }
};

Template.showPost.isOwner = function() {
  if (Meteor.user() !== null)
  {
    return (Meteor.user().services.twitter.screenName === Session.get('currentPostAuthor'));
  }
  else
    return false;
};

Template.showPost.author = function() {
  return Session.get('currentPostAuthor');
};

Template.showPost.title = function() {
  return Session.get('currentPostTitle');
};

Template.showPost.screenName = function() {
  Session.set('currentPostScreenName', "loading...");
  Session.set('currentPostScreenName', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))}).name);
  return Session.get('currentPostScreenName');
};

Template.showPost.content = function() {
  Session.set('currentPostContent', "loading...");
  Session.set('currentPostContent', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))}).content);
  //we sneak the id of the post into the page, since we need it later. really has nothing to do with the author
  Session.set('currentPostId', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))})._id);
  return Session.get('currentPostContent');
};

Template.authorPage.author = function () {
  return Session.get('currentAuthorPage');
};

Template.authorPage.post = function() {
  return Posts.find({author: Session.get('currentAuthorPage')}, {sort: {time: -1}});
};<commit_msg>upped the number of title characters allowed<commit_after>Posts = new Meteor.Collection("posts");
Meteor.autosubscribe(function () {
  Meteor.subscribe("directory");
  Meteor.subscribe("restrictiveUsers");
  Meteor.subscribe("posts");
});

Template.editor.rendered = function() {
  if (Meteor.user() !== null)
  {
    new Medium({
      element: document.getElementById('editor'),
      modifier: 'auto',
      placeholder: "",
      autofocus: false,
      autoHR: true,
      mode: 'rich',
      maxLength: -1,
      modifiers: {
          66: 'bold',
          73: 'italicize',
          85: 'underline',
          86: 'paste'
      },
      tags: {
          paragraph: 'p',
          outerLevel: ['pre','blockquote', 'figure', 'hr'],
          innerLevel: ['a', 'b', 'u', 'i', 'img', 'strong']
      },
      cssClasses: {
          editor: 'Medium',
          pasteHook: 'Medium-paste-hook',
          placeholder: 'Medium-placeholder'
      }
    });
    new Medium({
      element: document.getElementById('title'),
      mode: 'inline',
      maxLength: 50,
      placeholder: ''
    });
    if(typeof(Storage)!=="undefined")
    {
      if (localStorage.editor !== "" || localStorage.title !== "")
      {
        $('#title').html(localStorage.title);
        $('#editor').html(localStorage.editor);
      }
    }
    else
    {
    // Sorry! No web storage support..
    }
  }
};

Template.editor.isLoggedIn = function() {
  return (Meteor.user() !== null);
};

Template.editor.profileImage = function() {
  if (Meteor.user())
    return Meteor.user().services.twitter.profile_image_url;
};

Template.editor.events({
  'click button.minimal': function () {
    var title = $('#title').text();
    var content = $('#editor').html();
    Meteor.call("publishPost", title, content, function (data, err){
      console.log("waiting for callback");
      console.log(data);
      var author = Meteor.user().services.twitter.screenName;
      //clear localStorage
      //if they don't have it, there's nothing to be cleared because they suck
      if(typeof(Storage)!=="undefined")
      {
        localStorage.title = "";
        localStorage.editor = "";
      }
      Meteor.Router.to('/' + author + '/' + escape(title));
    });
  },

  'keyup' : function () {
    if(typeof(Storage)!=="undefined")
    {
      localStorage.title = $('#title').html();
      localStorage.editor = $('#editor').html();
    }
  }
});

Template.showPost.events({
  'click button.minimal.btnUpdate': function () {
    var id = Session.get("currentPostId");
    var content = $('#content').html();
    Meteor.call("updatePost", id, content, function (data, err){
      var author = Meteor.user().services.twitter.screenName;
      Meteor.Router.to('/' + author + '/' + escape(Session.get('currentPostTitle')));
    });
  },

  'click button.minimal.btnDelete': function () {
    var confirm = window.confirm("Are you sure you want to delete this post? This cannot be undone later.");
    if (confirm === true){
      Meteor.call("deletePost", Session.get('currentPostId'));
      Meteor.Router.to('/' + Meteor.user().services.twitter.screenName);
    }
  }
});

Template.showPost.rendered = function () {
  if (Meteor.user() !== null)
  {
    if (Meteor.user().services.twitter.screenName === Session.get('currentPostAuthor')){
      new Medium({
      element: document.getElementById('content'),
      modifier: 'auto',
      placeholder: "",
      autofocus: false,
      autoHR: true,
      mode: 'rich',
      maxLength: -1,
      modifiers: {
          66: 'bold',
          73: 'italicize',
          85: 'underline',
          86: 'paste'
      },
      tags: {
          paragraph: 'p',
          outerLevel: ['pre','blockquote', 'figure', 'hr'],
          innerLevel: ['a', 'b', 'u', 'i', 'img', 'strong']
      },
      cssClasses: {
          editor: 'Medium',
          pasteHook: 'Medium-paste-hook',
          placeholder: 'Medium-placeholder'
      }
    });
    }
  }
};

Template.showPost.isOwner = function() {
  if (Meteor.user() !== null)
  {
    return (Meteor.user().services.twitter.screenName === Session.get('currentPostAuthor'));
  }
  else
    return false;
};

Template.showPost.author = function() {
  return Session.get('currentPostAuthor');
};

Template.showPost.title = function() {
  return Session.get('currentPostTitle');
};

Template.showPost.screenName = function() {
  Session.set('currentPostScreenName', "loading...");
  Session.set('currentPostScreenName', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))}).name);
  return Session.get('currentPostScreenName');
};

Template.showPost.content = function() {
  Session.set('currentPostContent', "loading...");
  Session.set('currentPostContent', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))}).content);
  //we sneak the id of the post into the page, since we need it later. really has nothing to do with the author
  Session.set('currentPostId', Posts.findOne({author: escape(Session.get('currentPostAuthor')), urlsafetitle: escape(Session.get('currentPostTitle'))})._id);
  return Session.get('currentPostContent');
};

Template.authorPage.author = function () {
  return Session.get('currentAuthorPage');
};

Template.authorPage.post = function() {
  return Posts.find({author: Session.get('currentAuthorPage')}, {sort: {time: -1}});
};<|endoftext|>


<commit_before>'use strict';

define(['projectWeb'], function() {

  console.log("ok?")

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

  rivalWarLayoutServiceModule.factory('rivalWarLayoutService', [
      '$translate',
      '$rootScope',
      'tmhDynamicLocale',
      'LOCALES',
      function($translate, $rootScope, tmhDynamicLocale, LOCALES) {

        // 다국어 처리부 시작.
        // VARS
        var localesObj = LOCALES.locales;

        // locales and locales display names
        var _LOCALES = Object.keys(localesObj);
        if (!_LOCALES || _LOCALES.length === 0) {
          console.error('There are no _LOCALES provided');
        }
        var _LOCALES_DISPLAY_NAMES = [];

        _LOCALES.forEach(function(locale) {
          _LOCALES_DISPLAY_NAMES.push(localesObj[locale]);
        });

        var currentLocale = $translate.proposedLanguage();

        // METHODS
        var checkLocaleIsValid = function(locale) {
          return _LOCALES.indexOf(locale) !== -1;
        };

        var setLocale = function(locale) {
          if (!checkLocaleIsValid(locale)) {
            console.error('Locale name "' + locale + '" is invalid');
            return;
          }
          startLoadingAnimation();
          currentLocale = locale;
          $translate.use(locale);
        };

        /**
         * Stop application loading animation when translations are loaded
         */
        var $html = angular.element('html');
        var LOADING_CLASS = 'app-loading';

        function startLoadingAnimation() {
          $html.addClass(LOADING_CLASS);
        }

        function stopLoadingAnimation() {
          $html.removeClass(LOADING_CLASS);
        }

        // EVENTS
        $rootScope.$on('$translateChangeSuccess', function(event, data) {
          document.documentElement.setAttribute('lang', data.language);// sets
          tmhDynamicLocale.set(data.language.toLowerCase().replace(/_/g, '-'));// load
        });

        $rootScope.$on('$localeChangeSuccess', function() {
          stopLoadingAnimation();
        });

        //다국어 처리부 끝

        //함수 시작.
        return {
          fire: function() {
            var $a = $('body a');

            $a.on('click', function (e) {
              var $this = $(this);
              if($this.attr('href') === "#") e.preventDefault();
            });

            $("#loading").remove();
            $(".requireLoadingText").remove();
            $.AdminLTE.layout.activate();

            $(".sidebar-menu li a").click(function() {
              $('li .active').removeClass('active');
              $(this).parent().addClass('active');
            });

          },// fire end

          //다국어 처리 함수
          getLocaleDisplayName: function() {
            return _LOCALES_DISPLAY_NAMES[0];
          },
          setLocaleByDisplayName: function(localeDisplayName) {
            setLocale(_LOCALES[_LOCALES_DISPLAY_NAMES
                    .indexOf(localeDisplayName)// get locale index
            ]);
          },
          getLocalesDisplayNames: function() {
            console.log('getLocalesDisplayNames :' + _LOCALES_DISPLAY_NAMES);
            return _LOCALES_DISPLAY_NAMES;
          }
        };// return end
      }]);// .define function end
});
<commit_msg>2016.12.10 사이드바 뷰 처리<commit_after>'use strict';

define(['projectWeb'], function() {

  console.log("ok?")

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

  rivalWarLayoutServiceModule.factory('rivalWarLayoutService', [
      '$translate',
      '$rootScope',
      'tmhDynamicLocale',
      'LOCALES',
      function($translate, $rootScope, tmhDynamicLocale, LOCALES) {

        // 다국어 처리부 시작.
        // VARS
        var localesObj = LOCALES.locales;

        // locales and locales display names
        var _LOCALES = Object.keys(localesObj);
        if (!_LOCALES || _LOCALES.length === 0) {
          console.error('There are no _LOCALES provided');
        }
        var _LOCALES_DISPLAY_NAMES = [];

        _LOCALES.forEach(function(locale) {
          _LOCALES_DISPLAY_NAMES.push(localesObj[locale]);
        });

        var currentLocale = $translate.proposedLanguage();

        // METHODS
        var checkLocaleIsValid = function(locale) {
          return _LOCALES.indexOf(locale) !== -1;
        };

        var setLocale = function(locale) {
          if (!checkLocaleIsValid(locale)) {
            console.error('Locale name "' + locale + '" is invalid');
            return;
          }
          startLoadingAnimation();
          currentLocale = locale;
          $translate.use(locale);
        };

        /**
         * Stop application loading animation when translations are loaded
         */
        var $html = angular.element('html');
        var LOADING_CLASS = 'app-loading';

        function startLoadingAnimation() {
          $html.addClass(LOADING_CLASS);
        }

        function stopLoadingAnimation() {
          $html.removeClass(LOADING_CLASS);
        }

        // EVENTS
        $rootScope.$on('$translateChangeSuccess', function(event, data) {
          document.documentElement.setAttribute('lang', data.language);// sets
          tmhDynamicLocale.set(data.language.toLowerCase().replace(/_/g, '-'));// load
        });

        $rootScope.$on('$localeChangeSuccess', function() {
          stopLoadingAnimation();
        });

        //다국어 처리부 끝

        //함수 시작.
        return {
          fire: function() {
            var $a = $('body a');

            $a.on('click', function (e) {
              var $this = $(this);
              if($this.attr('href') === "#") e.preventDefault();
            });

            $("#loading").remove();
            $(".requireLoadingText").remove();
            $.AdminLTE.layout.activate();

            $(".sidebar-menu li a").click(function() {
              $('li .active').removeClass('active');
              $(this).parent().addClass('active');
            });

          },// fire end

          //다국어 처리 함수
          getLocaleDisplayName: function() {
            return _LOCALES_DISPLAY_NAMES[0];
          },
          setLocaleByDisplayName: function(localeDisplayName) {
            setLocale(_LOCALES[_LOCALES_DISPLAY_NAMES
                    .indexOf(localeDisplayName)// get locale index
            ]);
          },
          getLocalesDisplayNames: function() {
            console.log('getLocalesDisplayNames :' + _LOCALES_DISPLAY_NAMES);
            return _LOCALES_DISPLAY_NAMES;
          },
          sideView : function(){
            $(window).on({
              resize: function(){
                var winWid = $(window).width(),
                    $body = $('body');

                if(winWid < 1024) $body.addClass('sidebar-collapse');
                else if (winWid >= 1025) $body.removeClass('sidebar-collapse');
              }
            }).trigger('resize');
          }
        };// return end
      }]);// .define function end
});
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var auth = require('./auth');
var series = require('../data/series');
var twitter = require('../data/twitter');
var db = require('../data/mdb');

var dataMin = 50;

router.get('/search', function(req, res){
  if(req.session.passport.user){
    console.log(JSON.stringify(req.session));
    var key = new auth.key().withUserAccess(
      req.session.passport.user.token,
      req.session.passport.user.tokenSecret
    );
  } else {
      res.json({err: "Not signed in"});
      res.end();
      return;
  }
  var term = req.query.q;
  var start = req.query.start;
  var end = req.query.end;
  if (!term){
    res.json({message: 'bad query'});
    res.end();
  }else{
    if (!start){
      start = Date.now();
    } else {
      start = Number(start);
    }

    if (!end){
      scale = 10*24*60*60*1000;
      end = start - scale;
    } else {
      end = Number(end);
    }

    series.getDaySamples(term, start, end, key)
    .then(function(series){
      res.json(JSON.stringify(series));
      res.end();
    })
    .fail(function(reason){
      res.json({err: reason.message});
      res.end();
    });
  }
});

router.get('/select', function(req, res){
  if(req.session.passport.user){
    console.log(JSON.stringify(req.session));
    var key = new auth.key().withUserAccess(
      req.session.passport.user.token,
      req.session.passport.user.tokenSecret
    );
  } else {
      res.json({err: "Not signed in"});
      res.end();
      return;
  }

  var term = req.query.term;
  var time = Number(req.query.start);
  if(!term || !time){
    res.json({err: 'bad query'});
    res.end();
    return;
  }

  new twitter(key).getSampleAtTime(term, time)
  .then(db.tweetsForSample)
  .then(function(tweets){
    res.json(tweets);
    res.end();
  });
});

module.exports = router;
<commit_msg>next tweets<commit_after>var express = require('express');
var router = express.Router();
var auth = require('./auth');
var series = require('../data/series');
var twitter = require('../data/twitter');
var db = require('../data/mdb');

var dataMin = 50;

router.get('/search', function(req, res){
  if(req.session.passport.user){
    console.log(JSON.stringify(req.session));
    var key = new auth.key().withUserAccess(
      req.session.passport.user.token,
      req.session.passport.user.tokenSecret
    );
  } else {
      res.json({err: "Not signed in"});
      res.end();
      return;
  }
  var term = req.query.q;
  var start = req.query.start;
  var end = req.query.end;
  if (!term){
    res.json({message: 'bad query'});
    res.end();
  }else{
    if (!start){
      start = Date.now();
    } else {
      start = Number(start);
    }

    if (!end){
      scale = 10*24*60*60*1000;
      end = start - scale;
    } else {
      end = Number(end);
    }

    series.getDaySamples(term, start, end, key)
    .then(function(series){
      res.json(JSON.stringify(series));
      res.end();
    })
    .fail(function(reason){
      res.json({err: reason.message});
      res.end();
    });
  }
});

router.get('/select', function(req, res){
  if(req.session.passport.user){
    console.log(JSON.stringify(req.session));
    var key = new auth.key().withUserAccess(
      req.session.passport.user.token,
      req.session.passport.user.tokenSecret
    );
  } else {
      res.json({err: "Not signed in"});
      res.end();
      return;
  }

  var term = req.query.term;
  var time = Number(req.query.start);
  if(!term || !time){
    res.json({err: 'bad query'});
    res.end();
    return;
  }

  new twitter(key).getSampleAtTime(term, time)
  .then(function(sample){
    req.session.minid = sample.minid;
    req.session.term = term;
    return Q(sample);
  })
  .then(db.tweetsForSample)
  .then(function(tweets){
    res.json(tweets);
    res.end();
  });
});

router.get('/next', function(req, res){
  if(req.session.passport.user){
    console.log(JSON.stringify(req.session));
    var key = new auth.key().withUserAccess(
      req.session.passport.user.token,
      req.session.passport.user.tokenSecret
    );
  } else {
    res.json({err: "Not signed in"});
    res.end();
    return;
  }

  if(!req.session.minid){
    res.json({err: "Who are you?"});
    res.end();
    return;
  }

  new twitter(key).getSampleFromId(req.session.term, req.session.minid)
    .then(function(sample){
      req.session.minid = sample.minid;
      return Q(sample);
    })
    .then(db.tweetsForSample)
    .then(function(tweets){
      res.json(tweets);
      res.end();
    });
});
module.exports = router;
<|endoftext|>


<commit_before>const express = require('express')
const router = express.Router()
const geartrack = require('geartrack')
const roundrobin = require('rr')
const cache = require('../services/cacheMiddleware')

// default cache time - 10 min
const CACHE_TIME = 10 * 60

// All this routes will be cached
// Error responses can manipulate cache time
router.use(cache(CACHE_TIME))

// All common providers, name, cssClass for color
let providers = {
  'sky': new Provider('Sky56', 'primary'),
  'correoses': new Provider('Correos ES', 'yellow'),
  'expresso24': new Provider('Expresso24', 'warning'),
  'singpost': new Provider('Singpost', 'danger'),
  'ctt': new Provider('CTT', 'primary'),
  'directlink': new Provider('Direct Link', 'yellow'),
  'trackchinapost': new Provider('Track China Post', 'danger'),
  'cainiao': new Provider('Cainiao', 'danger'),
  'yanwen': new Provider('Yanwen', 'success'),
  'cjah': new Provider('Cjah Tracking', 'success'),
  'postNL': new Provider('Post NL', 'warning'),
  'malaysiaPos': new Provider('Malasya Pos', 'danger'),
  'winit': new Provider('Winit', 'primary'),
  'panasia': new Provider('Panasia', 'info'),
  'pitneybowes': new Provider('Pitney Bowes', 'primary'),
  'dhl': new Provider('DHL', 'yellow'),
  'track24': new Provider('Track24', 'info'),
  'correos': new Provider('Correos Express Novo', 'danger'),
  'correosOld': new Provider('Correos Express Antigo', 'danger'),
  'mrw': new Provider('MRW', 'primary'),
  'ips': new Provider('IPS', 'yellow'),
}

/**
 * Adicional data
 */
router.get('/adicional', validateId, validatePostalCode, function (req, res) {
  let id = req.query.id, postalcode = req.query.postalcode

  //return processErrorResponse(new Error('DOWN - '), res, 'Adicional')

  geartrack.adicional.getInfo(id, postalcode, (err, adicionalEntity) => {
    if (err) {
      // sets the status code and the appropriate message
      return processErrorResponse(err, res, 'Adicional')
    }

    res.json(adicionalEntity)
  })
})

let proxys = []
if (process.env.GEARTRACK_PROXYS) {
  proxys = process.env.GEARTRACK_PROXYS.split(',').map(ip => ip.trim()).filter(ip => ip.length > 0)
}

/**
 * General providers that only need an id
 */
router.get('/:provider', validateId, function (req, res, next) {
  let id = req.query.id

  let providerObj = providers[req.params.provider]

  if (!providerObj) // no provider found
    return next()

  if (req.params.provider == 'track24' && proxys.length > 0) {
    let proxy = roundrobin(proxys)
    let proxyUrl = 'http://' + proxy + '/track24/ajax/tracking118.ajax.php'
    geartrack[req.params.provider].getInfoProxy(id, proxyUrl, providerCallback(res, providerObj))
  } else {
    geartrack[req.params.provider].getInfo(id, providerCallback(res, providerObj))
  }

})

function providerCallback (res, providerObj) {
  return (err, entity) => {
    if (err) {
      // sets the status code and the appropriate message
      return processErrorResponse(err, res, providerObj.name)
    }

    if (entity.constructor &&
      entity.constructor.name &&
      entity.constructor.name == 'SkyInfo' &&
      entity.messages &&
      entity.messages.length == 0 &&
      entity.status &&
      entity.status.length == 0) {
      // Sky has no info
      return processErrorResponse(new Error('DEFAULT - no info'), res, providerObj.name)
    }

    entity.provider = providerObj.name // name shown: 'Informação [provider]'
    entity.color = providerObj.cssClass // color of the background, may use bootstrap classes

    res.json(entity)
  }
}

/*
 |--------------------------------------------------------------------------
 | Process Error Response
 |--------------------------------------------------------------------------
 */
function processErrorResponse (err, res, provider) {
  let cacheSeconds = CACHE_TIME // default cache time
  let code = 400
  let message = ''

  let type = getErrorType(err.message)
  let bugsnag = res.app.get('bugsnag')

  switch (type) {
    case 'BUSY':
      message = 'O servidor está sobrecarregado, tenta novamente daqui a uns segundos.'
      cacheSeconds = 0 // prevent cache
      break
    case 'UNAVAILABLE':
      message = 'O servidor não está disponível de momento. Tenta mais tarde.'
      break
    case 'DOWN':
    case 'EMPTY':
      message = 'De momento este serviço está com problemas. Tenta mais tarde.'
      break
    case 'PARSER':
      if(bugsnag) bugsnag.notify(err) // send error to be analysed
      message = 'De momento estamos com dificuldade em aceder à informação deste servidor. Tenta mais tarde.'
      break
    case 'ACTION_REQUIRED':
      if(bugsnag) bugsnag.notify(err) // send error to be analysed
      cacheSeconds = 0 // prevent cache
      message = 'Este tracker requere um passo adicional no seu website. Depois de efetuares esse passo volta e atualiza a pagina para tentarmos de novo! :)'
      break
    default: // NO_DATA
      message = 'Ainda não existe informação disponível para este ID.'
      break
  }

  res.locals.expire = cacheSeconds
  return res.status(code).json({
    error: message,
    provider: provider
  })
}

function getErrorType (errorMessage) {
  let idx = errorMessage.indexOf(' - ')
  return errorMessage.substring(0, idx)
}

/*
 |--------------------------------------------------------------------------
 | Validation Middlewares
 |--------------------------------------------------------------------------
 */
function validateId (req, res, next) {
  let id = req.query.id

  if (!id) {
    res.status(400).json({error: 'ID must be passed in the query string!'})
    return
  }

  next()
}

function validatePostalCode (req, res, next) {
  let postalcode = req.query.postalcode

  if (!postalcode) {
    res.status(400).json({error: 'Postalcode must be passed in the query string!'})
    return
  }

  next()
}

/*
 |--------------------------------------------------------------------------
 | Utils
 |--------------------------------------------------------------------------
 */
function Provider (name, cssClass) {
  this.name = name
  this.cssClass = cssClass
}

function getRandomIntInclusive (min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)
  return Math.floor(Math.random() * (max - min + 1)) + min
}

module.exports = router
<commit_msg>:art: Notify when a service is with problems<commit_after>const express = require('express')
const router = express.Router()
const geartrack = require('geartrack')
const roundrobin = require('rr')
const cache = require('../services/cacheMiddleware')

// default cache time - 10 min
const CACHE_TIME = 10 * 60

// All this routes will be cached
// Error responses can manipulate cache time
router.use(cache(CACHE_TIME))

// All common providers, name, cssClass for color
let providers = {
  'sky': new Provider('Sky56', 'primary'),
  'correoses': new Provider('Correos ES', 'yellow'),
  'expresso24': new Provider('Expresso24', 'warning'),
  'singpost': new Provider('Singpost', 'danger'),
  'ctt': new Provider('CTT', 'primary'),
  'directlink': new Provider('Direct Link', 'yellow'),
  'trackchinapost': new Provider('Track China Post', 'danger'),
  'cainiao': new Provider('Cainiao', 'danger'),
  'yanwen': new Provider('Yanwen', 'success'),
  'cjah': new Provider('Cjah Tracking', 'success'),
  'postNL': new Provider('Post NL', 'warning'),
  'malaysiaPos': new Provider('Malasya Pos', 'danger'),
  'winit': new Provider('Winit', 'primary'),
  'panasia': new Provider('Panasia', 'info'),
  'pitneybowes': new Provider('Pitney Bowes', 'primary'),
  'dhl': new Provider('DHL', 'yellow'),
  'track24': new Provider('Track24', 'info'),
  'correos': new Provider('Correos Express Novo', 'danger'),
  'correosOld': new Provider('Correos Express Antigo', 'danger'),
  'mrw': new Provider('MRW', 'primary'),
  'ips': new Provider('IPS', 'yellow'),
}

/**
 * Adicional data
 */
router.get('/adicional', validateId, validatePostalCode, function (req, res) {
  let id = req.query.id, postalcode = req.query.postalcode

  //return processErrorResponse(new Error('DOWN - '), res, 'Adicional')

  geartrack.adicional.getInfo(id, postalcode, (err, adicionalEntity) => {
    if (err) {
      // sets the status code and the appropriate message
      return processErrorResponse(err, res, 'Adicional')
    }

    res.json(adicionalEntity)
  })
})

let proxys = []
if (process.env.GEARTRACK_PROXYS) {
  proxys = process.env.GEARTRACK_PROXYS.split(',').map(ip => ip.trim()).filter(ip => ip.length > 0)
}

/**
 * General providers that only need an id
 */
router.get('/:provider', validateId, function (req, res, next) {
  let id = req.query.id

  let providerObj = providers[req.params.provider]

  if (!providerObj) // no provider found
    return next()

  if (req.params.provider == 'track24' && proxys.length > 0) {
    let proxy = roundrobin(proxys)
    let proxyUrl = 'http://' + proxy + '/track24/ajax/tracking118.ajax.php'
    geartrack[req.params.provider].getInfoProxy(id, proxyUrl, providerCallback(res, providerObj))
  } else {
    geartrack[req.params.provider].getInfo(id, providerCallback(res, providerObj))
  }

})

function providerCallback (res, providerObj) {
  return (err, entity) => {
    if (err) {
      // sets the status code and the appropriate message
      return processErrorResponse(err, res, providerObj.name)
    }

    if (entity.constructor &&
      entity.constructor.name &&
      entity.constructor.name == 'SkyInfo' &&
      entity.messages &&
      entity.messages.length == 0 &&
      entity.status &&
      entity.status.length == 0) {
      // Sky has no info
      return processErrorResponse(new Error('DEFAULT - no info'), res, providerObj.name)
    }

    entity.provider = providerObj.name // name shown: 'Informação [provider]'
    entity.color = providerObj.cssClass // color of the background, may use bootstrap classes

    res.json(entity)
  }
}

/*
 |--------------------------------------------------------------------------
 | Process Error Response
 |--------------------------------------------------------------------------
 */
function processErrorResponse (err, res, provider) {
  let cacheSeconds = CACHE_TIME // default cache time
  let code = 400
  let message = ''

  let type = getErrorType(err.message)
  let bugsnag = res.app.get('bugsnag')

  switch (type) {
    case 'BUSY':
      message = 'O servidor está sobrecarregado, tenta novamente daqui a uns segundos.'
      cacheSeconds = 0 // prevent cache
      break
    case 'UNAVAILABLE':
      message = 'O servidor não está disponível de momento. Tenta mais tarde.'
      break
    case 'DOWN':
    case 'EMPTY':
      if(bugsnag) bugsnag.notify(err) // send error to be analysed
      message = 'De momento este serviço está com problemas. Tenta mais tarde.'
      break
    case 'PARSER':
      if(bugsnag) bugsnag.notify(err) // send error to be analysed
      message = 'De momento estamos com dificuldade em aceder à informação deste servidor. Tenta mais tarde.'
      break
    case 'ACTION_REQUIRED':
      if(bugsnag) bugsnag.notify(err) // send error to be analysed
      cacheSeconds = 0 // prevent cache
      message = 'Este tracker requere um passo adicional no seu website. Depois de efetuares esse passo volta e atualiza a pagina para tentarmos de novo! :)'
      break
    default: // NO_DATA
      message = 'Ainda não existe informação disponível para este ID.'
      break
  }

  res.locals.expire = cacheSeconds
  return res.status(code).json({
    error: message,
    provider: provider
  })
}

function getErrorType (errorMessage) {
  let idx = errorMessage.indexOf(' - ')
  return errorMessage.substring(0, idx)
}

/*
 |--------------------------------------------------------------------------
 | Validation Middlewares
 |--------------------------------------------------------------------------
 */
function validateId (req, res, next) {
  let id = req.query.id

  if (!id) {
    res.status(400).json({error: 'ID must be passed in the query string!'})
    return
  }

  next()
}

function validatePostalCode (req, res, next) {
  let postalcode = req.query.postalcode

  if (!postalcode) {
    res.status(400).json({error: 'Postalcode must be passed in the query string!'})
    return
  }

  next()
}

/*
 |--------------------------------------------------------------------------
 | Utils
 |--------------------------------------------------------------------------
 */
function Provider (name, cssClass) {
  this.name = name
  this.cssClass = cssClass
}

function getRandomIntInclusive (min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)
  return Math.floor(Math.random() * (max - min + 1)) + min
}

module.exports = router
<|endoftext|>