<commit_before>import 'regenerator-runtime/runtime';
import { makeExecutableSchema } from 'graphql-tools';
import { parse, execute } from 'graphql';

const getState = async ({ statesRepository, eventStore, readModel, aggregateIds }) => {
    const readModelName = readModel.name.toLowerCase();
    const isAggregateBased = Array.isArray(aggregateIds) && aggregateIds.length > 0;

    const stateName = isAggregateBased
        ? `${readModelName}\u200D${aggregateIds.sort().join('\u200D')}`
        : readModelName;

    const { eventHandlers, initialState } = readModel;

    if (!statesRepository[stateName]) {
        const eventTypes = Object.keys(eventHandlers);
        let state = initialState || {};
        let error = null;

        const result = !isAggregateBased
            ? eventStore.subscribeByEventType(eventTypes, (event) => {
                const handler = eventHandlers[event.type];
                if (!handler) return;

                try {
                    state = handler(state, event);
                } catch (err) {
                    error = err;
                }
            })
            : eventStore.subscribeByAggregateId(aggregateIds, (event) => {
                const handler = eventHandlers[event.type];
                if (!handler) return;

                try {
                    state = handler(state, event);
                } catch (err) {
                    error = err;
                }
            });

        statesRepository[stateName] = async () => {
            await result;
            if (error) throw error;
            return state;
        };
    }

    return await statesRepository[stateName]();
};

function extractAggregateIdsFromGqlQuery(parsedGqlQuery, gqlVariables) {
    const findAllAggregateIds = (queryObject, store = []) => {
        if (!queryObject || typeof queryObject !== 'object') return store;

        if (queryObject.kind === 'Field' && Array.isArray(queryObject.arguments)) {
            queryObject.arguments
                .filter(arg => arg.name && arg.name.value === 'aggregateId' && arg.value)
                .map(
                    arg =>
                        arg.value.kind === 'Variable' && arg.value.name && arg.value.name.value
                            ? gqlVariables[arg.value.name.value]
                            : arg.value.value
                )
                .forEach(value => store.push(value));
        }

        if (Object.getPrototypeOf(queryObject) === Object.prototype) {
            Object.keys(queryObject).forEach(key => findAllAggregateIds(queryObject[key], store));
        } else if (Array.isArray(queryObject)) {
            queryObject.forEach(part => findAllAggregateIds(part, store));
        }

        return store;
    };

    return findAllAggregateIds(parsedGqlQuery);
}

function getExecutor({ statesRepository, eventStore, readModel, getReadModel }) {
    const { gqlSchema, gqlResolvers, name } = readModel;
    const executableSchema =
        gqlSchema &&
        makeExecutableSchema({
            resolvers: gqlResolvers ? { Query: gqlResolvers } : {},
            typeDefs: gqlSchema
        });

    return async (gqlQuery, gqlVariables, getJwt) => {
        if (!gqlQuery) {
            return await getState({ statesRepository, eventStore, readModel });
        }

        if (!executableSchema) {
            throw new Error(`GraphQL schema for '${name}' read model is not found`);
        }

        const parsedGqlQuery = parse(gqlQuery);
        const aggregateIds = extractAggregateIdsFromGqlQuery(parsedGqlQuery, gqlVariables);
        const state = await getState({ statesRepository, eventStore, readModel, aggregateIds });

        const gqlResponse = await execute(
            executableSchema,
            parsedGqlQuery,
            state,
            { getJwt, getReadModel },
            gqlVariables
        );

        if (gqlResponse.errors) throw gqlResponse.errors;
        return gqlResponse.data;
    };
}

export default ({ eventStore, readModels }) => {
    const statesRepository = {};

    const getReadModel = async (modelName, aggregateIds) => {
        const readModel = readModels.find(
            model => modelName.toLowerCase() === model.name.toLowerCase()
        );
        if (readModel) {
            return await getState({ statesRepository, eventStore, readModel, aggregateIds });
        }
        return null;
    };

    const executors = readModels.reduce((result, readModel) => {
        result[readModel.name.toLowerCase()] = getExecutor({
            statesRepository,
            getReadModel,
            eventStore,
            readModel
        });
        return result;
    }, {});

    return async (readModelName, gqlQuery, gqlVariables, getJwt) => {
        const executor = executors[readModelName.toLowerCase()];

        if (executor === undefined) {
            throw new Error(`The '${readModelName}' read model is not found`);
        }

        return executor(gqlQuery, gqlVariables, getJwt);
    };
};
<commit_msg>can assign a false value to the initial state (#262)<commit_after>import 'regenerator-runtime/runtime';
import { makeExecutableSchema } from 'graphql-tools';
import { parse, execute } from 'graphql';

const getState = async ({ statesRepository, eventStore, readModel, aggregateIds }) => {
    const readModelName = readModel.name.toLowerCase();
    const isAggregateBased = Array.isArray(aggregateIds) && aggregateIds.length > 0;

    const stateName = isAggregateBased
        ? `${readModelName}\u200D${aggregateIds.sort().join('\u200D')}`
        : readModelName;

    const { eventHandlers, initialState } = readModel;

    if (!statesRepository[stateName]) {
        const eventTypes = Object.keys(eventHandlers);
        let state = initialState !== undefined ? initialState : {};

        let error = null;

        const result = !isAggregateBased
            ? eventStore.subscribeByEventType(eventTypes, (event) => {
                const handler = eventHandlers[event.type];
                if (!handler) return;

                try {
                    state = handler(state, event);
                } catch (err) {
                    error = err;
                }
            })
            : eventStore.subscribeByAggregateId(aggregateIds, (event) => {
                const handler = eventHandlers[event.type];
                if (!handler) return;

                try {
                    state = handler(state, event);
                } catch (err) {
                    error = err;
                }
            });

        statesRepository[stateName] = async () => {
            await result;
            if (error) throw error;
            return state;
        };
    }

    return await statesRepository[stateName]();
};

function extractAggregateIdsFromGqlQuery(parsedGqlQuery, gqlVariables) {
    const findAllAggregateIds = (queryObject, store = []) => {
        if (!queryObject || typeof queryObject !== 'object') return store;

        if (queryObject.kind === 'Field' && Array.isArray(queryObject.arguments)) {
            queryObject.arguments
                .filter(arg => arg.name && arg.name.value === 'aggregateId' && arg.value)
                .map(
                    arg =>
                        arg.value.kind === 'Variable' && arg.value.name && arg.value.name.value
                            ? gqlVariables[arg.value.name.value]
                            : arg.value.value
                )
                .forEach(value => store.push(value));
        }

        if (Object.getPrototypeOf(queryObject) === Object.prototype) {
            Object.keys(queryObject).forEach(key => findAllAggregateIds(queryObject[key], store));
        } else if (Array.isArray(queryObject)) {
            queryObject.forEach(part => findAllAggregateIds(part, store));
        }

        return store;
    };

    return findAllAggregateIds(parsedGqlQuery);
}

function getExecutor({ statesRepository, eventStore, readModel, getReadModel }) {
    const { gqlSchema, gqlResolvers, name } = readModel;
    const executableSchema =
        gqlSchema &&
        makeExecutableSchema({
            resolvers: gqlResolvers ? { Query: gqlResolvers } : {},
            typeDefs: gqlSchema
        });

    return async (gqlQuery, gqlVariables, getJwt) => {
        if (!gqlQuery) {
            return await getState({ statesRepository, eventStore, readModel });
        }

        if (!executableSchema) {
            throw new Error(`GraphQL schema for '${name}' read model is not found`);
        }

        const parsedGqlQuery = parse(gqlQuery);
        const aggregateIds = extractAggregateIdsFromGqlQuery(parsedGqlQuery, gqlVariables);
        const state = await getState({ statesRepository, eventStore, readModel, aggregateIds });

        const gqlResponse = await execute(
            executableSchema,
            parsedGqlQuery,
            state,
            { getJwt, getReadModel },
            gqlVariables
        );

        if (gqlResponse.errors) throw gqlResponse.errors;
        return gqlResponse.data;
    };
}

export default ({ eventStore, readModels }) => {
    const statesRepository = {};

    const getReadModel = async (modelName, aggregateIds) => {
        const readModel = readModels.find(
            model => modelName.toLowerCase() === model.name.toLowerCase()
        );
        if (readModel) {
            return await getState({ statesRepository, eventStore, readModel, aggregateIds });
        }
        return null;
    };

    const executors = readModels.reduce((result, readModel) => {
        result[readModel.name.toLowerCase()] = getExecutor({
            statesRepository,
            getReadModel,
            eventStore,
            readModel
        });
        return result;
    }, {});

    return async (readModelName, gqlQuery, gqlVariables, getJwt) => {
        const executor = executors[readModelName.toLowerCase()];

        if (executor === undefined) {
            throw new Error(`The '${readModelName}' read model is not found`);
        }

        return executor(gqlQuery, gqlVariables, getJwt);
    };
};
<|endoftext|>


<commit_before>"use strict";

function TexturePanel(parent, obj)
{
	Panel.call(this, parent, obj);

	var self = this;

	//Name
	this.form.addText("Name");
	this.name = new TextBox(this.form.element);
	this.name.size.set(190, 18);
	this.name.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "name", self.name.getText()));
		Editor.updateViewsGUI();
	});
	this.form.add(this.name);
	this.form.nextRow();

	//UUID
	if(Editor.settings.general.showUUID)
	{
		this.form.addText("UUID");
		this.uuid = this.form.addText("");
		this.form.nextRow();
	}

	//WrapS
	this.form.addText("Wrap Hor.");
	this.wrapS = new DropdownList(this.form.element);
	this.wrapS.size.set(120, 18);
	this.wrapS.addValue("Clamp to Edge", THREE.ClampToEdgeWrapping);
	this.wrapS.addValue("Repeat", THREE.RepeatWrapping);
	this.wrapS.addValue("Repeat Mirrored", THREE.MirroredRepeatWrapping);
	this.wrapS.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "wrapS", self.wrapS.getValue()));
		self.updatePreview();
	});
	this.form.add(this.wrapS);
	this.form.nextRow();

	//WrapT
	this.form.addText("Wrap Vert.");
	this.wrapT = new DropdownList(this.form.element);
	this.wrapT.size.set(120, 18);
	this.wrapT.addValue("Clamp to Edge", THREE.ClampToEdgeWrapping);
	this.wrapT.addValue("Repeat", THREE.RepeatWrapping);
	this.wrapT.addValue("Repeat Mirrored", THREE.MirroredRepeatWrapping);
	this.wrapT.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "wrapT", self.wrapT.getValue()));
		self.updatePreview();
	});
	this.form.add(this.wrapT);
	this.form.nextRow();

	//Repeat
	this.form.addText("Repeat");
	this.repeat = new CoordinatesBox(this.form.element);
	this.repeat.setMode(CoordinatesBox.VECTOR2);
	this.repeat.size.set(120, 18);
	this.repeat.setStep(0.01);
	this.repeat.setOnChange(function()
	{
		var value = self.repeat.getValue();
		self.obj.repeat.set(value.x, value.y);
		self.updatePreview();
	});
	this.form.add(this.repeat);
	this.form.nextRow();

	//Offset
	this.form.addText("Offset");
	this.offset = new CoordinatesBox(this.form.element);
	this.offset.setMode(CoordinatesBox.VECTOR2);
	this.offset.size.set(120, 18);
	this.offset.setStep(0.01);
	this.offset.setOnChange(function()
	{
		var value = self.offset.getValue();
		self.obj.offset.set(value.x, value.y);
		self.updatePreview();
	});
	this.form.add(this.offset);
	this.form.nextRow();

	//Center
	this.form.addText("Center");
	this.center = new CoordinatesBox(this.form.element);
	this.center.setMode(CoordinatesBox.VECTOR2);
	this.center.size.set(120, 18);
	this.center.setStep(0.01);
	this.center.setOnChange(function()
	{
		var value = self.center.getValue();
		self.obj.center.set(value.x, value.y);
		self.updatePreview();
	});
	this.form.add(this.center);
	this.form.nextRow();

	//Rotation
	this.form.addText("Rotation");
	this.rotation = new NumberBox(this.form.element);
	this.rotation.size.set(60, 18);
	this.rotation.setStep(0.1);
	this.rotation.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "rotation", self.rotation.getValue()));
		self.updatePreview();
	});
	this.form.add(this.rotation);
	this.form.nextRow();

	//Minification filter
	this.form.addText("Min. filter");
	this.minFilter = new DropdownList(this.form.element);
	this.minFilter.size.set(150, 18);
	this.minFilter.addValue("Nearest", THREE.NearestFilter);
	this.minFilter.addValue("Linear", THREE.LinearFilter);
	this.minFilter.addValue("MIP Nearest Nearest", THREE.NearestMipMapNearestFilter);
	this.minFilter.addValue("MIP Nearest Linear", THREE.NearestMipMapLinearFilter);
	this.minFilter.addValue("MIP Linear Nearest", THREE.LinearMipMapNearestFilter);
	this.minFilter.addValue("MIP Linear Linear", THREE.LinearMipMapLinearFilter);
	this.minFilter.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "minFilter", self.minFilter.getValue()));
		self.updatePreview();
	});
	this.form.add(this.minFilter);
	this.form.nextRow();

	//Magnification filter
	this.form.addText("Mag. filter");
	this.magFilter = new DropdownList(this.form.element);
	this.magFilter.size.set(150, 18);
	this.magFilter.addValue("Nearest", THREE.NearestFilter);
	this.magFilter.addValue("Linear", THREE.LinearFilter);
	this.magFilter.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "magFilter", self.magFilter.getValue()));
		self.updatePreview();
	});
	this.form.add(this.magFilter);
	this.form.nextRow();

	//Premultiply Alpha
	this.form.addText("Premul. Alpha");
	this.premultiplyAlpha = new CheckBox(this.form.element);
	this.premultiplyAlpha.size.set(15, 15);
	this.premultiplyAlpha.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "premultiplyAlpha", self.premultiplyAlpha.getValue()));
		self.updatePreview();
	});
	this.form.add(this.premultiplyAlpha);
	this.form.nextRow();

	//Flip Y
	this.form.addText("Flip Y");
	this.flipY = new CheckBox(this.form.element);
	this.flipY.size.set(15, 15);
	this.flipY.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "flipY", self.flipY.getValue()));
		self.updatePreview();
	});
	this.form.add(this.flipY);
	this.form.nextRow();
}

TexturePanel.prototype = Object.create(Panel.prototype);

//Update panel information
TexturePanel.prototype.updatePanel = function()
{
	this.name.setText(this.obj.name);

	if(this.uuid !== undefined)
	{
		this.uuid.setText(this.obj.uuid);
	}

	this.wrapT.setValue(this.obj.wrapT);
	this.wrapS.setValue(this.obj.wrapS);
	this.repeat.setValue(this.obj.repeat);
	this.offset.setValue(this.obj.offset);
	this.center.setValue(this.obj.center);
	this.rotation.setValue(this.obj.rotation);
	this.magFilter.setValue(this.obj.magFilter);
	this.minFilter.setValue(this.obj.minFilter);
	this.premultiplyAlpha.setValue(this.obj.premultiplyAlpha);
	this.flipY.setValue(this.obj.flipY);
};<commit_msg>Fix texture panel updatePreview<commit_after>"use strict";

function TexturePanel(parent, obj)
{
	Panel.call(this, parent, obj);

	var self = this;

	//Name
	this.form.addText("Name");
	this.name = new TextBox(this.form.element);
	this.name.size.set(190, 18);
	this.name.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "name", self.name.getText()));
		Editor.updateViewsGUI();
	});
	this.form.add(this.name);
	this.form.nextRow();

	//UUID
	if(Editor.settings.general.showUUID)
	{
		this.form.addText("UUID");
		this.uuid = this.form.addText("");
		this.form.nextRow();
	}

	//WrapS
	this.form.addText("Wrap Hor.");
	this.wrapS = new DropdownList(this.form.element);
	this.wrapS.size.set(120, 18);
	this.wrapS.addValue("Clamp to Edge", THREE.ClampToEdgeWrapping);
	this.wrapS.addValue("Repeat", THREE.RepeatWrapping);
	this.wrapS.addValue("Repeat Mirrored", THREE.MirroredRepeatWrapping);
	this.wrapS.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "wrapS", self.wrapS.getValue()));
	});
	this.form.add(this.wrapS);
	this.form.nextRow();

	//WrapT
	this.form.addText("Wrap Vert.");
	this.wrapT = new DropdownList(this.form.element);
	this.wrapT.size.set(120, 18);
	this.wrapT.addValue("Clamp to Edge", THREE.ClampToEdgeWrapping);
	this.wrapT.addValue("Repeat", THREE.RepeatWrapping);
	this.wrapT.addValue("Repeat Mirrored", THREE.MirroredRepeatWrapping);
	this.wrapT.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "wrapT", self.wrapT.getValue()));
	});
	this.form.add(this.wrapT);
	this.form.nextRow();

	//Repeat
	this.form.addText("Repeat");
	this.repeat = new CoordinatesBox(this.form.element);
	this.repeat.setMode(CoordinatesBox.VECTOR2);
	this.repeat.size.set(120, 18);
	this.repeat.setStep(0.01);
	this.repeat.setOnChange(function()
	{
		var value = self.repeat.getValue();
		self.obj.repeat.set(value.x, value.y);
	});
	this.form.add(this.repeat);
	this.form.nextRow();

	//Offset
	this.form.addText("Offset");
	this.offset = new CoordinatesBox(this.form.element);
	this.offset.setMode(CoordinatesBox.VECTOR2);
	this.offset.size.set(120, 18);
	this.offset.setStep(0.01);
	this.offset.setOnChange(function()
	{
		var value = self.offset.getValue();
		self.obj.offset.set(value.x, value.y);
	});
	this.form.add(this.offset);
	this.form.nextRow();

	//Center
	this.form.addText("Center");
	this.center = new CoordinatesBox(this.form.element);
	this.center.setMode(CoordinatesBox.VECTOR2);
	this.center.size.set(120, 18);
	this.center.setStep(0.01);
	this.center.setOnChange(function()
	{
		var value = self.center.getValue();
		self.obj.center.set(value.x, value.y);
	});
	this.form.add(this.center);
	this.form.nextRow();

	//Rotation
	this.form.addText("Rotation");
	this.rotation = new NumberBox(this.form.element);
	this.rotation.size.set(60, 18);
	this.rotation.setStep(0.1);
	this.rotation.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "rotation", self.rotation.getValue()));
	});
	this.form.add(this.rotation);
	this.form.nextRow();

	//Minification filter
	this.form.addText("Min. filter");
	this.minFilter = new DropdownList(this.form.element);
	this.minFilter.size.set(150, 18);
	this.minFilter.addValue("Nearest", THREE.NearestFilter);
	this.minFilter.addValue("Linear", THREE.LinearFilter);
	this.minFilter.addValue("MIP Nearest Nearest", THREE.NearestMipMapNearestFilter);
	this.minFilter.addValue("MIP Nearest Linear", THREE.NearestMipMapLinearFilter);
	this.minFilter.addValue("MIP Linear Nearest", THREE.LinearMipMapNearestFilter);
	this.minFilter.addValue("MIP Linear Linear", THREE.LinearMipMapLinearFilter);
	this.minFilter.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "minFilter", self.minFilter.getValue()));
	});
	this.form.add(this.minFilter);
	this.form.nextRow();

	//Magnification filter
	this.form.addText("Mag. filter");
	this.magFilter = new DropdownList(this.form.element);
	this.magFilter.size.set(150, 18);
	this.magFilter.addValue("Nearest", THREE.NearestFilter);
	this.magFilter.addValue("Linear", THREE.LinearFilter);
	this.magFilter.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "magFilter", self.magFilter.getValue()));
	});
	this.form.add(this.magFilter);
	this.form.nextRow();

	//Premultiply Alpha
	this.form.addText("Premul. Alpha");
	this.premultiplyAlpha = new CheckBox(this.form.element);
	this.premultiplyAlpha.size.set(15, 15);
	this.premultiplyAlpha.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "premultiplyAlpha", self.premultiplyAlpha.getValue()));
	});
	this.form.add(this.premultiplyAlpha);
	this.form.nextRow();

	//Flip Y
	this.form.addText("Flip Y");
	this.flipY = new CheckBox(this.form.element);
	this.flipY.size.set(15, 15);
	this.flipY.setOnChange(function()
	{
		Editor.history.add(new ChangeAction(self.obj, "flipY", self.flipY.getValue()));
	});
	this.form.add(this.flipY);
	this.form.nextRow();
}

TexturePanel.prototype = Object.create(Panel.prototype);

//Update panel information
TexturePanel.prototype.updatePanel = function()
{
	this.name.setText(this.obj.name);

	if(this.uuid !== undefined)
	{
		this.uuid.setText(this.obj.uuid);
	}

	this.wrapT.setValue(this.obj.wrapT);
	this.wrapS.setValue(this.obj.wrapS);
	this.repeat.setValue(this.obj.repeat);
	this.offset.setValue(this.obj.offset);
	this.center.setValue(this.obj.center);
	this.rotation.setValue(this.obj.rotation);
	this.magFilter.setValue(this.obj.magFilter);
	this.minFilter.setValue(this.obj.minFilter);
	this.premultiplyAlpha.setValue(this.obj.premultiplyAlpha);
	this.flipY.setValue(this.obj.flipY);
};<|endoftext|>


<commit_before>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;

  var ProfileChart = window.shared.ProfileChart;
  var ProfileBarChart = window.shared.ProfileBarChart;
  var HighchartsWrapper = window.shared.HighchartsWrapper;

  var styles = {
    box: {
      border: '1px solid #ccc',
      padding:15,
      marginTop: 10,
      marginBottom: 10,
      width: '100%',
      backgroundColor: '#f2f2f2'
    },
    item: {
      paddingBottom: 10,
      width: 160
    },
    itemHead: {
      fontWeight: 'bold',
    },
    header: {
      display: 'flex',
      flexFlow: 'row',
      justifyContent: 'space-between'
    },
    desc: {
      fontWeight: 'bold',
      paddingTop: 30
    },
    title: {
      color: 'black',
      paddingBottom: 20,
      fontSize: 24
    },
    container: {
      width: '100%',
      marginTop: 50,
      marginLeft: 'auto',
      marginRight: 'auto',
      border: '1px solid #ccc',
      padding: '30px 30px 30px 30px',
      position: 'relative'
    },
    centerItem: {
      paddingBottom: 10,
      textAlign: 'center',
      width: 75
    },
    secHead: {
      display: 'flex',
      justifyContent: 'space-between',
      borderBottom: '1px solid #333',
      position: 'absolute',
      top: 30,
      left: 30,
      right: 30
    },
    navBar: {
      fontSize: 18
    },
    navTop: {
      textAlign: 'right',
      verticalAlign: 'text-top'
    }
  };

  var AttendanceDetails = window.shared.AttendanceDetails = React.createClass({
    displayName: 'AttendanceDetails',
    propTypes: {
      absences: React.PropTypes.array.isRequired,
      tardies: React.PropTypes.array.isRequired,
      disciplineIncidents: React.PropTypes.array.isRequired,
      student: React.PropTypes.object.isRequired,
      feed: React.PropTypes.object.isRequired
    },

    // TODO(KR) date, label
    plotLines: function() {
      return this.props.feed.services.active.map(function(activeService) {
        return {
          color: 'red',
          dashStyle: 'longdashdot', // Style of the plot line. Default to solid
          value: activeService.date_started,
          width: 2, // Width of the line
          label: {
            text: 'I am a label', // Content of the label.
            align: 'left' // Positioning of the label.
            // Default to center. x: +10 // Amount of pixels the label will be repositioned according to the alignment.
          }
        };
      });
    },

    render: function() {
      return dom.div({ className: 'AttendanceDetails' },
        this.renderNavBar(),
        this.renderDisciplineIncidents(),
        this.renderAbsences(),
        this.renderTardies(),
        this.renderIncidentHistory()
      );
    },

    renderNavBar: function() {
      return dom.div({ style: styles.navBar },
          dom.a({ style: styles.navBar, href: '#disciplineChart'}, 'Discipline Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#absences'}, 'Absences Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#tardies'}, 'Tardies Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#history'}, 'Incident History')
        );
    },

    renderHeader: function(title) {
      return dom.div({ style: styles.secHead },
        dom.h4({ style: styles.title }, title),
        dom.span({ style: styles.navTop }, dom.a({ href: '#' }, 'Back to top'))
      );
    },

    renderDisciplineIncidents: function() {
      return createEl(ProfileBarChart, {
        events: this.props.disciplineIncidents,
        titleText: 'Discipline Incidents',
        id: "disciplineChart",
        monthsBack: 48,
        tooltipTemplateString: "<%= moment.utc(e.occurred_at).format('MMMM Do, YYYY')%>",
        plotLines: this.plotLines()
      });
    },

    renderAbsences: function() {
      return createEl(ProfileBarChart, {
        events: this.props.absences,
        id: "absences",
        titleText: 'Absences',
        monthsBack: 48,
        plotLines: this.plotLines()
      });
    },

    renderTardies: function() {
      return createEl(ProfileBarChart, {
        events: this.props.tardies,
        id: "tardies",
        titleText: 'Tardies',
        monthsBack: 48,
        plotLines: this.plotLines()
      });
    },

    renderIncidents: function() {
      return dom.div({ style: {paddingTop: 60} }, this.props.disciplineIncidents.map(function(incident) {
        return dom.div({ style: styles.box, key: incident.id},
          dom.div({ style: styles.header },
            dom.div({ style: styles.item },
              dom.span({ style: styles.itemHead }, 'Date: '),
              dom.span({}, moment.utc(incident.occurred_at).format('MMM D, YYYY'))
              ),
            dom.div({ style: styles.centerItem },
              dom.span({ style: styles.itemHead }, 'Code: '),
              dom.span({}, incident.incident_code)
              ),
            dom.div({ style: styles.item },
              dom.span({ style: styles.itemHead }, 'Location: '),
              dom.span({}, incident.incident_location)
            )
          ),
          dom.div({}, dom.span({ style: styles.desc }, 'Description: ')),
          dom.div({}, incident.incident_description))

      }));
    },

    renderIncidentHistory: function() {
      return dom.div({ id: "history", style: styles.container },
        this.renderHeader('Incident History'),
        this.props.disciplineIncidents.length > 0
          ? this.renderIncidents()
          : dom.div({ style: {paddingTop: 60}}, 'No Incidents')
      );
    }
  });
})();
<commit_msg>Back out attendance_details changes<commit_after>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;

  var ProfileChart = window.shared.ProfileChart;
  var ProfileBarChart = window.shared.ProfileBarChart;
  var HighchartsWrapper = window.shared.HighchartsWrapper;

  var styles = {
    box: {
      border: '1px solid #ccc',
      padding:15,
      marginTop: 10,
      marginBottom: 10,
      width: '100%',
      backgroundColor: '#f2f2f2'
    },
    item: {
      paddingBottom: 10,
      width: 160
    },
    itemHead: {
      fontWeight: 'bold',
    },
    header: {
      display: 'flex',
      flexFlow: 'row',
      justifyContent: 'space-between'
    },
    desc: {
      fontWeight: 'bold',
      paddingTop: 30
    },
    title: {
      color: 'black',
      paddingBottom: 20,
      fontSize: 24
    },
    container: {
      width: '100%',
      marginTop: 50,
      marginLeft: 'auto',
      marginRight: 'auto',
      border: '1px solid #ccc',
      padding: '30px 30px 30px 30px',
      position: 'relative'
    },
    centerItem: {
      paddingBottom: 10,
      textAlign: 'center',
      width: 75
    },
    secHead: {
      display: 'flex',
      justifyContent: 'space-between',
      borderBottom: '1px solid #333',
      position: 'absolute',
      top: 30,
      left: 30,
      right: 30
    },
    navBar: {
      fontSize: 18
    },
    navTop: {
      textAlign: 'right',
      verticalAlign: 'text-top'
    }
  };

  var AttendanceDetails = window.shared.AttendanceDetails = React.createClass({
    displayName: 'AttendanceDetails',
    propTypes: {
      absences: React.PropTypes.array.isRequired,
      tardies: React.PropTypes.array.isRequired,
      disciplineIncidents: React.PropTypes.array.isRequired,
      student: React.PropTypes.object.isRequired
    },

    render: function() {
      return dom.div({ className: 'AttendanceDetails' },
        this.renderNavBar(),
        this.renderDisciplineIncidents(),
        this.renderAbsences(),
        this.renderTardies(),
        this.renderIncidentHistory()
      );
    },

    renderNavBar: function() {
      return dom.div({ style: styles.navBar },
          dom.a({ style: styles.navBar, href: '#disciplineChart'}, 'Discipline Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#absences'}, 'Absences Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#tardies'}, 'Tardies Chart'), ' | ',
          dom.a({ style: styles.navBar, href: '#history'}, 'Incident History')
        );
    },

    renderHeader: function(title) {
      return dom.div({ style: styles.secHead },
        dom.h4({ style: styles.title }, title),
        dom.span({ style: styles.navTop }, dom.a({ href: '#' }, 'Back to top'))
      );
    },

    renderDisciplineIncidents: function() {
      return createEl(ProfileBarChart, {
        events: this.props.disciplineIncidents,
        titleText: 'Discipline Incidents',
        id: "disciplineChart",
        monthsBack: 48,
        tooltipTemplateString: "<%= moment.utc(e.occurred_at).format('MMMM Do, YYYY')%>"
      });
    },

    renderAbsences: function() {
      return createEl(ProfileBarChart, {
        events: this.props.absences,
        id: "absences",
        titleText: 'Absences',
        monthsBack: 48
      });
    },

    renderTardies: function() {
      return createEl(ProfileBarChart, {
        events: this.props.tardies,
        id: "tardies",
        titleText: 'Tardies',
        monthsBack: 48
      });
    },

    renderIncidents: function() {
      return dom.div({ style: {paddingTop: 60} }, this.props.disciplineIncidents.map(function(incident) {
        return dom.div({ style: styles.box, key: incident.id},
          dom.div({ style: styles.header },
            dom.div({ style: styles.item },
              dom.span({ style: styles.itemHead }, 'Date: '),
              dom.span({}, moment.utc(incident.occurred_at).format('MMM D, YYYY'))
              ),
            dom.div({ style: styles.centerItem },
              dom.span({ style: styles.itemHead }, 'Code: '),
              dom.span({}, incident.incident_code)
              ),
            dom.div({ style: styles.item },
              dom.span({ style: styles.itemHead }, 'Location: '),
              dom.span({}, incident.incident_location)
            )
          ),
          dom.div({}, dom.span({ style: styles.desc }, 'Description: ')),
          dom.div({}, incident.incident_description))

      }));
    },

    renderIncidentHistory: function() {
      return dom.div({ id: "history", style: styles.container },
        this.renderHeader('Incident History'),
        this.props.disciplineIncidents.length > 0
          ? this.renderIncidents()
          : dom.div({ style: {paddingTop: 60}}, 'No Incidents')
      );
    },
  });
})();
<|endoftext|>


<commit_before>// Extensions

// keep this wrapper around the ones you use!
(function( undefined ){
	shoestring.fn.prevAll = function(){
		var ret = [],
			next;
		this.each(function( i ){
			while( this.previousElementSibling ){
				ret = ret.concat( this.previousElementSibling );
			}
		});
		return shoestring(ret);
	};
}());
<commit_msg>this makes prevAll not do an infinite loop in cases where it used to. If you miss that feature, try dividing by zero or whatever.<commit_after>// Extensions

// keep this wrapper around the ones you use!
(function( undefined ){
	shoestring.fn.prevAll = function(){
		var ret = [];
		this.each(function( i ){
			var self = this;
			while( self.previousElementSibling ){
				ret = ret.concat( self.previousElementSibling );
				self = self.previousElementSibling;
			}
		});
		return shoestring(ret);
	};
}());
<|endoftext|>


<commit_before>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FB_TEXT_LIMIT = 640;

const FACEBOOK_LOCATION = "FACEBOOK_LOCATION";
const FACEBOOK_WELCOME = "FACEBOOK_WELCOME";

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

        async.eachSeries(splittedText, (textPart, callback) => {
            this.sendFBMessage(sender, {text: textPart})
                .then(() => callback())
                .catch(err => callback(err));
        });
    }

    //which webhook event
    getEventText(event) {
        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                console.log('event.message = true');
				return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                console.log('event.message.text = true');
				return event.message.text;
            }
        }

        if (event.postback && event.postback.payload) {
			console.log('event.postback && event.postback.payload = true');
            return event.postback.payload;
        }
		if (event.message.url) {
			console.log('event.message.url = true');
            return event.postback.payload;
        }
		console.log('return null');
        return null;

    }

    getFacebookEvent(event) {
        if (event.postback && event.postback.payload) {

            let payload = event.postback.payload;

            switch (payload) {
                case FACEBOOK_WELCOME:
                    return {name: FACEBOOK_WELCOME};

                case FACEBOOK_LOCATION:
                    return {name: FACEBOOK_LOCATION, data: event.postback.data}
            }
        }

        return null;
    }

    processFacebookEvent(event) {
        const sender = event.sender.id.toString();
        const eventObject = this.getFacebookEvent(event);

        if (eventObject) {

            // Handle a text message from this sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            let apiaiRequest = this.apiAiService.eventRequest(eventObject,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });
            this.doApiAiRequest(apiaiRequest, sender);
        }
    }

    processMessageEvent(event) {
        const sender = event.sender.id.toString();
        const text = this.getEventText(event);

        if (text) {

            // Handle a text message from this sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            this.doApiAiRequest(apiaiRequest, sender);
        }
    }

    doApiAiRequest(apiaiRequest, sender) {
        apiaiRequest.on('response', (response) => {
            if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                let responseMessages = response.result.fulfillment.messages;

                if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                    let facebookResponseData = responseData.facebook;
                    this.doDataResponse(sender, facebookResponseData);
                } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                    this.doRichContentResponse(sender, responseMessages);
                }
                else if (this.isDefined(responseText)) {
                    this.doTextResponse(sender, responseText);
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }

    splitResponse(str) {
        if (str.length <= FB_TEXT_LIMIT) {
            return [str];
        }

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

    chunkString(s, len) {
        let curr = len, prev = 0;

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let currReverse = curr;
                do {
                    if (s.substring(currReverse - 1, currReverse) == ' ') {
                        output.push(s.substring(prev, currReverse));
                        prev = currReverse;
                        curr = currReverse + len;
                        break;
                    }
                    currReverse--;
                } while (currReverse > prev)
            }
        }
        output.push(s.substr(prev));
        return output;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    message: messageData
                }
            }, (error, response) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    sender_action: action
                }
            }, (error, response) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    doSubscribeRequest() {
        request({
                method: 'POST',
                uri: `https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=${FB_PAGE_ACCESS_TOKEN}`
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription: ', error);
                } else {
                    console.log('Subscription result: ', response.body);
                }
            });
    }

    configureGetStartedEvent() {
        request({
                method: 'POST',
                uri: `https://graph.facebook.com/v2.6/me/thread_settings?access_token=${FB_PAGE_ACCESS_TOKEN}`,
                json: {
                    setting_type: "call_to_actions",
                    thread_state: "new_thread",
                    call_to_actions: [
                        {
                            payload: FACEBOOK_WELCOME
                        }
                    ]
                }
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription', error);
                } else {
                    console.log('Subscription result', response.body);
                }
            });
    }

    isDefined(obj) {
        if (typeof obj == 'undefined') {
            return false;
        }

        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] === FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        if (event.message && !event.message.is_echo) {

                            if (event.message.attachments) {
                                let locations = event.message.attachments.filter(a => a.type === "location");

                                // delete all locations from original message
                                event.message.attachments = event.message.attachments.filter(a => a.type !== "location");

                                if (locations.length > 0) {
                                    locations.forEach(l => {
                                        let locationEvent = {
                                            sender: event.sender,
                                            postback: {
                                                payload: "FACEBOOK_LOCATION",
                                                data: l.payload.coordinates
                                            }
                                        };

                                        facebookBot.processFacebookEvent(locationEvent);
                                    });
                                }
                            }

                            facebookBot.processMessageEvent(event);
                        } else if (event.postback && event.postback.payload) {
                            if (event.postback.payload === "FACEBOOK_WELCOME") {
                                facebookBot.processFacebookEvent(event);
                            } else {
                                facebookBot.processMessageEvent(event);
                            }
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

facebookBot.doSubscribeRequest();
<commit_msg>040817457<commit_after>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FB_TEXT_LIMIT = 640;

const FACEBOOK_LOCATION = "FACEBOOK_LOCATION";
const FACEBOOK_WELCOME = "FACEBOOK_WELCOME";

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

        async.eachSeries(splittedText, (textPart, callback) => {
            this.sendFBMessage(sender, {text: textPart})
                .then(() => callback())
                .catch(err => callback(err));
        });
    }

    //which webhook event
    getEventText(event) {
        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                console.log('event.message = true');
				return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                console.log('event.message.text = true');
				return event.message.text;
            }
        }

        if (event.postback && event.postback.payload) {
			console.log('event.postback && event.postback.payload = true');
            return event.postback.payload;
        }
		if (event.message.image) {
			console.log('event.message.image = true');
            return null;
        }
		console.log('return null');
        return null;

    }

    getFacebookEvent(event) {
        if (event.postback && event.postback.payload) {

            let payload = event.postback.payload;

            switch (payload) {
                case FACEBOOK_WELCOME:
                    return {name: FACEBOOK_WELCOME};

                case FACEBOOK_LOCATION:
                    return {name: FACEBOOK_LOCATION, data: event.postback.data}
            }
        }

        return null;
    }

    processFacebookEvent(event) {
        const sender = event.sender.id.toString();
        const eventObject = this.getFacebookEvent(event);

        if (eventObject) {

            // Handle a text message from this sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            let apiaiRequest = this.apiAiService.eventRequest(eventObject,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });
            this.doApiAiRequest(apiaiRequest, sender);
        }
    }

    processMessageEvent(event) {
        const sender = event.sender.id.toString();
        const text = this.getEventText(event);

        if (text) {

            // Handle a text message from this sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            this.doApiAiRequest(apiaiRequest, sender);
        }
    }

    doApiAiRequest(apiaiRequest, sender) {
        apiaiRequest.on('response', (response) => {
            if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                let responseMessages = response.result.fulfillment.messages;

                if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                    let facebookResponseData = responseData.facebook;
                    this.doDataResponse(sender, facebookResponseData);
                } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                    this.doRichContentResponse(sender, responseMessages);
                }
                else if (this.isDefined(responseText)) {
                    this.doTextResponse(sender, responseText);
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }

    splitResponse(str) {
        if (str.length <= FB_TEXT_LIMIT) {
            return [str];
        }

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

    chunkString(s, len) {
        let curr = len, prev = 0;

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let currReverse = curr;
                do {
                    if (s.substring(currReverse - 1, currReverse) == ' ') {
                        output.push(s.substring(prev, currReverse));
                        prev = currReverse;
                        curr = currReverse + len;
                        break;
                    }
                    currReverse--;
                } while (currReverse > prev)
            }
        }
        output.push(s.substr(prev));
        return output;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    message: messageData
                }
            }, (error, response) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            request({
                url: 'https://graph.facebook.com/v2.6/me/messages',
                qs: {access_token: FB_PAGE_ACCESS_TOKEN},
                method: 'POST',
                json: {
                    recipient: {id: sender},
                    sender_action: action
                }
            }, (error, response) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    doSubscribeRequest() {
        request({
                method: 'POST',
                uri: `https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=${FB_PAGE_ACCESS_TOKEN}`
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription: ', error);
                } else {
                    console.log('Subscription result: ', response.body);
                }
            });
    }

    configureGetStartedEvent() {
        request({
                method: 'POST',
                uri: `https://graph.facebook.com/v2.6/me/thread_settings?access_token=${FB_PAGE_ACCESS_TOKEN}`,
                json: {
                    setting_type: "call_to_actions",
                    thread_state: "new_thread",
                    call_to_actions: [
                        {
                            payload: FACEBOOK_WELCOME
                        }
                    ]
                }
            },
            (error, response, body) => {
                if (error) {
                    console.error('Error while subscription', error);
                } else {
                    console.log('Subscription result', response.body);
                }
            });
    }

    isDefined(obj) {
        if (typeof obj == 'undefined') {
            return false;
        }

        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] === FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        if (event.message && !event.message.is_echo) {

                            if (event.message.attachments) {
                                let locations = event.message.attachments.filter(a => a.type === "location");

                                // delete all locations from original message
                                event.message.attachments = event.message.attachments.filter(a => a.type !== "location");

                                if (locations.length > 0) {
                                    locations.forEach(l => {
                                        let locationEvent = {
                                            sender: event.sender,
                                            postback: {
                                                payload: "FACEBOOK_LOCATION",
                                                data: l.payload.coordinates
                                            }
                                        };

                                        facebookBot.processFacebookEvent(locationEvent);
                                    });
                                }
                            }

                            facebookBot.processMessageEvent(event);
                        } else if (event.postback && event.postback.payload) {
                            if (event.postback.payload === "FACEBOOK_WELCOME") {
                                facebookBot.processFacebookEvent(event);
                            } else {
                                facebookBot.processMessageEvent(event);
                            }
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

facebookBot.doSubscribeRequest();
<|endoftext|>


<commit_before>/**common -- iServer**/
import './common/iServer/AddressMatchServiceSpec.js';
import './common/iServer/AggQueryBuilderParameterSpec.js';
import './common/iServer/AggregationParameterSpec.js';
import './common/iServer/AreaSolarRadiationParametersSpec.js';
import './common/iServer/BufferAnalystServiceSpec.js';
import './common/iServer/BufferDistanceSpec.js';
import './common/iServer/BufferSettingSpec.js';
import './common/iServer/BurstPipelineAnalystServiceSpec.js';
import './common/iServer/ChartQueryFilterParameterSpec.js';
import './common/iServer/ChartQueryParametersSpec.js';
import './common/iServer/ClipParameterSpec.js';
import './common/iServer/ComputeWeightMatrixServiceSpec.js';
import './common/iServer/DensityAnalystServiceSpec.js';
import './common/iServer/EditFeaturesServiceSpec.js';
import './common/iServer/FacilityAnalystStreamParametersSpec.js';
import './common/iServer/FacilityAnalystUpstream3DParametersSpec.js';
import './common/iServer/FieldStatisticServiceSpec.js';
import './common/iServer/FilterAggParameterSpec.js';
import './common/iServer/FindClosestFacilitiesServiceSpec.js';
import './common/iServer/FindLocationServiceSpec.js';
import './common/iServer/FindMTSPPathsServiceSpec.js';
import './common/iServer/FindPathServiceSpec.js';
import './common/iServer/FindServiceAreasServiceSpec.js';
import './common/iServer/FindTSPPathsServiceSpec.js';
import './common/iServer/GenerateSpatialDataServiceSpec.js';
import './common/iServer/GeoBoundingBoxQueryBuilderParameterSpec.js';
import './common/iServer/GeoHashGridAggParameterSpec.js';
import './common/iServer/GeometryBatchAnalystServiceSpec.js';
import './common/iServer/GeoRelationAnalystServiceSpec.js';
import './common/iServer/GetFeaturesByBoundsServiceSpec.js';
import './common/iServer/GetFeaturesByBufferServiceSpec.js';
import './common/iServer/GetFeaturesByGeometryServiceSpec.js';
import './common/iServer/GetFeaturesByIDsServiceSpec.js';
import './common/iServer/GetFeaturesBySQLServiceSpec.js';
import './common/iServer/GetFieldsServiceSpec.js';
import './common/iServer/GetGridCellInfosServiceSpec.js';
import './common/iServer/GetLayersInfoServiceSpec.js';
import './common/iServer/GridSpec.js';
import './common/iServer/ImageSpec.js';
import './common/iServer/InterpolationAnalystServiceSpec.js';
import './common/iServer/LabelImageCellSpec.js';
import './common/iServer/LabelMixedStyleSpec.js';
import './common/iServer/LinkItemSpec.js';
import './common/iServer/MapServiceSpec.js';
import './common/iServer/MathExpressionAnalysisServiceSpec.js';
import './common/iServer/MeasureServiceSpec.js';
import './common/iServer/OverlapDisplayedOptionsSpec.js';
import './common/iServer/OverlayAnalystServiceSpec.js';
import './common/iServer/QueryByBoundsServiceSpec.js';
import './common/iServer/QueryByDistanceServiceSpec.js';
import './common/iServer/QueryByGeometryServiceSpec.js';
import './common/iServer/QueryBySQLServiceSpec.js';
import './common/iServer/QueryServiceSpec.js';
import './common/iServer/RouteCalculateMeasureServiceSpec.js';
import './common/iServer/RouteLocatorServiceSpec.js';
import './common/iServer/RouteSpec.js';
import './common/iServer/ServerGeometrySpec.js';
import './common/iServer/SetLayerInfoServiceSpec.js';
import './common/iServer/SetLayersInfoServiceSpec.js';
import './common/iServer/SetLayerStatusServiceSpec.js';
import './common/iServer/StopQueryServiceSpec.js';
import './common/iServer/SummaryAttributesJobsParameterSpec.js';
import './common/iServer/SurfaceAnalystServiceSpec.js';
import './common/iServer/TerrainCurvatureCalculationServiceSpec.js';
import './common/iServer/ThemeDotDensitySpec.js';
import './common/iServer/ThemeGridRangeSpec.js';
import './common/iServer/ThemeGridUniqueSpec.js';
import './common/iServer/ThemeLabelUniqueItemSpec.js';
import './common/iServer/ThemeRangeSpec.js';
import './common/iServer/ThemeServiceSpec.js';
import './common/iServer/ThiessenAnalystServiceSpec.js';
import './common/iServer/TilesetsServiceSpec.js';
import './common/iServer/TransferLineSpec.js';
import './common/iServer/TransferPathServiceSpec.js';
import './common/iServer/TransferSolutionServiceSpec.js';
import './common/iServer/UpdateEdgeWeightServiceSpec.js';
import './common/iServer/UpdateTurnNodeWeightServiceSpec.js';
// import './common/iServer/AreaSolarRadiationServiceSpec.js';       //iclient8注释掉
// import './common/iServer/ChartFeatureInfoSpecsServiceSpec.js';    //iclient8注释掉,海图测试LayerServices相关的类，等待服务端支持后添加
// import './common/iServer/ChartQueryServiceSpec.js';
// import './common/iServer/FacilityAnalystSinks3DServiceSpec.js';   //三维网络分析Facility系列的测试全部被iClient8注释掉
// import './common/iServer/FacilityAnalystSources3DServiceSpec.js';
// import './common/iServer/FacilityAnalystStreamServiceSpec.js';
// import './common/iServer/FacilityAnalystTracedown3DServiceSpec.js';
// import './common/iServer/FacilityAnalystTraceup3DServiceSpec.js';
// import './common/iServer/FacilityAnalystUpstream3DServiceSpec.js';

/**common -- control**/
import './common/control/TimeControlBaseSpec.js';
import './common/control/TimeFlowControlSpec.js';

/**common -- format**/
import './common/format/GeoJSONSpec.js';
import './common/format/JSONSpec.js';
import './common/format/WKTSpec.js';

/**common -- style**/
import './common/style/CartoCSSSpec.js';

/**common -- security**/
import './common/security/KeyServiceParameterSpec.js';
import './common/security/SecurityManagerSpec.js';

/**common -- commontypes**/
import './common/commontypes/BaseTypesSpec.js';
import './common/commontypes/BoundsSpec.js';
import './common/commontypes/DateSpec.js';
import './common/commontypes/LonLatSpec.js';
import './common/commontypes/PixelSpec.js';
import './common/commontypes/VectorSpec.js';
import './common/commontypes/UtilSpec.js';
import './common/commontypes/geometry/CollectionSpec.js';
import './common/commontypes/geometry/GeoTextSpec.js';
import './common/commontypes/geometry/LineStringSpec.js';
import './common/commontypes/geometry/LinearRingSpec.js';

/**common -- overlay**/
import './common/overlay/feature/ShapeFactorySpec.js';
import './common/overlay/levelRenderer/AreaSpec.js';
import './common/overlay/levelRenderer/ClipSpec.js';
import './common/overlay/levelRenderer/AnimationSpec.js';
import './common/overlay/levelRenderer/ColorSpec.js';
import './common/overlay/levelRenderer/ComputeBoundingBoxSpec';
import './common/overlay/levelRenderer/CurveSpec.js';
import './common/overlay/levelRenderer/EasingSpec.js';
import './common/overlay/levelRenderer/GroupSpec.js';
import './common/overlay/levelRenderer/LevelRendererSpec.js';
import './common/overlay/levelRenderer/MatrixSpec.js';
import './common/overlay/levelRenderer/PainterSpec.js';
import './common/overlay/levelRenderer/RenderSpec.js';
import './common/overlay/levelRenderer/ShapeSepc.js';
import './common/overlay/levelRenderer/SmicBrokenLineSpec.js';
import './common/overlay/levelRenderer/SmicCircleSpec.js';
import './common/overlay/levelRenderer/SmicEllipseSpec';
import './common/overlay/levelRenderer/SmicImageSpec.js';
import './common/overlay/levelRenderer/SmicIsogonSpec.js';
import './common/overlay/levelRenderer/SmicPointSpec.js';
import './common/overlay/levelRenderer/SmicPolygonSpec.js';
import './common/overlay/levelRenderer/SmicRectangleSpec.js';
import './common/overlay/levelRenderer/SmicRingSpec.js';
import './common/overlay/levelRenderer/SmicSectorSpec.js';
import './common/overlay/levelRenderer/SmicStarSpec.js';
import './common/overlay/levelRenderer/SmicTextSpec.js';
import './common/overlay/levelRenderer/StorageSpec.js';
import './common/overlay/levelRenderer/TransformableSpec.js';
import './common/overlay/levelRenderer/UtilSpec.js';
import './common/overlay/levelRenderer/VectorSpec.js';
import './common/overlay/GraphSpec';

/**common -- online**/
import './common/online/OnlineDataSpec.js';
import './common/online/OnlineSpec.js';
import './common/online/OnlineQueryDatasParameterSpec';

/**common -- iManager**/
import './common/iManager/iManagerCreateNodeParamSpec.js';

/**common -- iPortal**/
import './common/iPortal/iPortalQueryParamSpec.js';
// import './common/iPortal/iPortalUserSpec.js';
// import './common/iPortal/iPortalShareEntitySpec.js';
// import './common/iPortal/iPortalShareParamSpec.js';
// import './common/iPortal/iPortalResourceSpec.js';
// import './common/iPortal/iPortalQueryResultSpec.js';
// import './common/iPortal/iPortalSpec.js';
// import './common/iPortal/iPortalAddResourceParamSpec';
// import './common/iPortal/iPortalRegisterServiceParamSpec';
// import './common/iPortal/iPortalAddDataParamSpec.js';
// import './common/iPortal/iPortalDataMetaInfoParamSpec.js';
// import './common/iPortal/iPortalDataStoreInfoParamSpec.js';
// import './common/iPortal/iPortalDataConnectionInfoParamSpec.js';

/**common -- thirdparty**/
import './common/thirdparty/elasticsearch/ElasticSearchSpec.js';

/**common -- component**/
import './common/components/templates/IndexTabsPageContainerSpec.js';
import './common/components/templates/NavTabsPageSpec.js';
// import './common/components/templates/CommonContainerSpec.js';
import './common/components/chart/ChartModelSpec.js';
import './common/components/chart/ChartViewModelSpec';
import './common/components/chart/ChartViewSpec';

import './common/util/FetchRequestSpec';

<commit_msg>Update test-main-common.js<commit_after>/**common -- iServer**/
import './common/iServer/AddressMatchServiceSpec.js';
import './common/iServer/AggQueryBuilderParameterSpec.js';
import './common/iServer/AggregationParameterSpec.js';
import './common/iServer/AreaSolarRadiationParametersSpec.js';
import './common/iServer/BufferAnalystServiceSpec.js';
import './common/iServer/BufferDistanceSpec.js';
import './common/iServer/BufferSettingSpec.js';
import './common/iServer/BurstPipelineAnalystServiceSpec.js';
import './common/iServer/ChartQueryFilterParameterSpec.js';
import './common/iServer/ChartQueryParametersSpec.js';
import './common/iServer/ClipParameterSpec.js';
import './common/iServer/ComputeWeightMatrixServiceSpec.js';
import './common/iServer/DensityAnalystServiceSpec.js';
import './common/iServer/EditFeaturesServiceSpec.js';
import './common/iServer/FacilityAnalystStreamParametersSpec.js';
import './common/iServer/FacilityAnalystUpstream3DParametersSpec.js';
import './common/iServer/FieldStatisticServiceSpec.js';
import './common/iServer/FilterAggParameterSpec.js';
import './common/iServer/FindClosestFacilitiesServiceSpec.js';
import './common/iServer/FindLocationServiceSpec.js';
import './common/iServer/FindMTSPPathsServiceSpec.js';
import './common/iServer/FindPathServiceSpec.js';
import './common/iServer/FindServiceAreasServiceSpec.js';
import './common/iServer/FindTSPPathsServiceSpec.js';
import './common/iServer/GenerateSpatialDataServiceSpec.js';
import './common/iServer/GeoBoundingBoxQueryBuilderParameterSpec.js';
import './common/iServer/GeoHashGridAggParameterSpec.js';
import './common/iServer/GeometryBatchAnalystServiceSpec.js';
import './common/iServer/GeoRelationAnalystServiceSpec.js';
import './common/iServer/GetFeaturesByBoundsServiceSpec.js';
import './common/iServer/GetFeaturesByBufferServiceSpec.js';
import './common/iServer/GetFeaturesByGeometryServiceSpec.js';
import './common/iServer/GetFeaturesByIDsServiceSpec.js';
import './common/iServer/GetFeaturesBySQLServiceSpec.js';
import './common/iServer/GetFieldsServiceSpec.js';
import './common/iServer/GetGridCellInfosServiceSpec.js';
import './common/iServer/GetLayersInfoServiceSpec.js';
import './common/iServer/GridSpec.js';
import './common/iServer/ImageSpec.js';
import './common/iServer/InterpolationAnalystServiceSpec.js';
import './common/iServer/LabelImageCellSpec.js';
import './common/iServer/LabelMixedStyleSpec.js';
import './common/iServer/LinkItemSpec.js';
import './common/iServer/MapServiceSpec.js';
import './common/iServer/MathExpressionAnalysisServiceSpec.js';
import './common/iServer/MeasureServiceSpec.js';
import './common/iServer/OverlapDisplayedOptionsSpec.js';
import './common/iServer/OverlayAnalystServiceSpec.js';
import './common/iServer/QueryByBoundsServiceSpec.js';
import './common/iServer/QueryByDistanceServiceSpec.js';
import './common/iServer/QueryByGeometryServiceSpec.js';
import './common/iServer/QueryBySQLServiceSpec.js';
import './common/iServer/QueryServiceSpec.js';
import './common/iServer/RouteCalculateMeasureServiceSpec.js';
import './common/iServer/RouteLocatorServiceSpec.js';
import './common/iServer/RouteSpec.js';
import './common/iServer/ServerGeometrySpec.js';
import './common/iServer/SetLayerInfoServiceSpec.js';
import './common/iServer/SetLayersInfoServiceSpec.js';
import './common/iServer/SetLayerStatusServiceSpec.js';
import './common/iServer/StopQueryServiceSpec.js';
import './common/iServer/SummaryAttributesJobsParameterSpec.js';
import './common/iServer/SurfaceAnalystServiceSpec.js';
import './common/iServer/TerrainCurvatureCalculationServiceSpec.js';
import './common/iServer/ThemeDotDensitySpec.js';
import './common/iServer/ThemeGridRangeSpec.js';
import './common/iServer/ThemeGridUniqueSpec.js';
import './common/iServer/ThemeLabelUniqueItemSpec.js';
import './common/iServer/ThemeRangeSpec.js';
import './common/iServer/ThemeServiceSpec.js';
import './common/iServer/ThiessenAnalystServiceSpec.js';
import './common/iServer/TilesetsServiceSpec.js';
import './common/iServer/TransferLineSpec.js';
import './common/iServer/TransferPathServiceSpec.js';
import './common/iServer/TransferSolutionServiceSpec.js';
import './common/iServer/UpdateEdgeWeightServiceSpec.js';
import './common/iServer/UpdateTurnNodeWeightServiceSpec.js';
// import './common/iServer/AreaSolarRadiationServiceSpec.js';       //iclient8注释掉
// import './common/iServer/ChartFeatureInfoSpecsServiceSpec.js';    //iclient8注释掉,海图测试LayerServices相关的类，等待服务端支持后添加
// import './common/iServer/ChartQueryServiceSpec.js';
// import './common/iServer/FacilityAnalystSinks3DServiceSpec.js';   //三维网络分析Facility系列的测试全部被iClient8注释掉
// import './common/iServer/FacilityAnalystSources3DServiceSpec.js';
// import './common/iServer/FacilityAnalystStreamServiceSpec.js';
// import './common/iServer/FacilityAnalystTracedown3DServiceSpec.js';
// import './common/iServer/FacilityAnalystTraceup3DServiceSpec.js';
// import './common/iServer/FacilityAnalystUpstream3DServiceSpec.js';

/**common -- control**/
import './common/control/TimeControlBaseSpec.js';
import './common/control/TimeFlowControlSpec.js';

/**common -- format**/
import './common/format/GeoJSONSpec.js';
import './common/format/JSONSpec.js';
import './common/format/WKTSpec.js';

/**common -- style**/
import './common/style/CartoCSSSpec.js';

/**common -- security**/
import './common/security/KeyServiceParameterSpec.js';
import './common/security/SecurityManagerSpec.js';

/**common -- commontypes**/
import './common/commontypes/BaseTypesSpec.js';
import './common/commontypes/BoundsSpec.js';
import './common/commontypes/DateSpec.js';
import './common/commontypes/LonLatSpec.js';
import './common/commontypes/PixelSpec.js';
import './common/commontypes/VectorSpec.js';
import './common/commontypes/UtilSpec.js';
import './common/commontypes/geometry/CollectionSpec.js';
import './common/commontypes/geometry/GeoTextSpec.js';
import './common/commontypes/geometry/LineStringSpec.js';
import './common/commontypes/geometry/LinearRingSpec.js';

/**common -- overlay**/
import './common/overlay/feature/ShapeFactorySpec.js';
import './common/overlay/levelRenderer/AreaSpec.js';
import './common/overlay/levelRenderer/ClipSpec.js';
import './common/overlay/levelRenderer/AnimationSpec.js';
import './common/overlay/levelRenderer/ColorSpec.js';
import './common/overlay/levelRenderer/ComputeBoundingBoxSpec';
import './common/overlay/levelRenderer/CurveSpec.js';
import './common/overlay/levelRenderer/EasingSpec.js';
import './common/overlay/levelRenderer/GroupSpec.js';
import './common/overlay/levelRenderer/LevelRendererSpec.js';
import './common/overlay/levelRenderer/MatrixSpec.js';
import './common/overlay/levelRenderer/PainterSpec.js';
import './common/overlay/levelRenderer/RenderSpec.js';
import './common/overlay/levelRenderer/ShapeSepc.js';
import './common/overlay/levelRenderer/SmicBrokenLineSpec.js';
import './common/overlay/levelRenderer/SmicCircleSpec.js';
import './common/overlay/levelRenderer/SmicEllipseSpec';
import './common/overlay/levelRenderer/SmicImageSpec.js';
import './common/overlay/levelRenderer/SmicIsogonSpec.js';
import './common/overlay/levelRenderer/SmicPointSpec.js';
import './common/overlay/levelRenderer/SmicPolygonSpec.js';
import './common/overlay/levelRenderer/SmicRectangleSpec.js';
import './common/overlay/levelRenderer/SmicRingSpec.js';
import './common/overlay/levelRenderer/SmicSectorSpec.js';
import './common/overlay/levelRenderer/SmicStarSpec.js';
import './common/overlay/levelRenderer/SmicTextSpec.js';
import './common/overlay/levelRenderer/StorageSpec.js';
import './common/overlay/levelRenderer/TransformableSpec.js';
import './common/overlay/levelRenderer/UtilSpec.js';
import './common/overlay/levelRenderer/VectorSpec.js';
import './common/overlay/GraphSpec';

/**common -- online**/
import './common/online/OnlineDataSpec.js';
import './common/online/OnlineSpec.js';
import './common/online/OnlineQueryDatasParameterSpec';

/**common -- iManager**/
import './common/iManager/iManagerCreateNodeParamSpec.js';

/**common -- iPortal**/
import './common/iPortal/iPortalQueryParamSpec.js';
// import './common/iPortal/iPortalUserSpec.js';
// import './common/iPortal/iPortalShareEntitySpec.js';
// import './common/iPortal/iPortalShareParamSpec.js';
// import './common/iPortal/iPortalResourceSpec.js';
// import './common/iPortal/iPortalQueryResultSpec.js';
// import './common/iPortal/iPortalSpec.js';
// import './common/iPortal/iPortalAddResourceParamSpec';
// import './common/iPortal/iPortalRegisterServiceParamSpec';
// import './common/iPortal/iPortalAddDataParamSpec.js';
// import './common/iPortal/iPortalDataMetaInfoParamSpec.js';
// import './common/iPortal/iPortalDataStoreInfoParamSpec.js';
// import './common/iPortal/iPortalDataConnectionInfoParamSpec.js';

/**common -- thirdparty**/
import './common/thirdparty/elasticsearch/ElasticSearchSpec.js';

/**common -- component**/
import './common/components/templates/IndexTabsPageContainerSpec.js';
import './common/components/templates/NavTabsPageSpec.js';
import './common/components/templates/CommonContainerSpec.js';
import './common/components/chart/ChartModelSpec.js';
import './common/components/chart/ChartViewModelSpec';
import './common/components/chart/ChartViewSpec';

import './common/util/FetchRequestSpec';

<|endoftext|>


<commit_before>/* ----------
require
---------- */
var domselect = require('dom-select');

/* ----------
config object
global shared variables
---------- */
module.exports = {

	/* ----------
	vars
	@path, {string}
	site base URL, for AJAX requests
	---------- */
	PATH: 'http://baptistebriel.github.io',
	BASE: '/biggie/',

	/* ----------
	DOM nodes
	$node, {HTML element}
	global shared elements
	---------- */
	$body: document.body,
	$view: domselect('#js-view')

}<commit_msg>Update config.js<commit_after>/* ----------
require
---------- */
var domselect = require('dom-select');

/* ----------
config object
global shared variables
---------- */
module.exports = {

	/* ----------
	vars
	@path, {string}
	site base URL, for AJAX requests
	---------- */
	PATH: 'http://baptistebriel.github.io',
	BASE: '/',

	/* ----------
	DOM nodes
	$node, {HTML element}
	global shared elements
	---------- */
	$body: document.body,
	$view: domselect('#js-view')

}
<|endoftext|>


<commit_before>'use strict';

const { urlRoot } = window;
const supportedProtocols = [
  'bitcoin',
  'bitcoincash',
  'bitcoinsv',
  'ethereum',
  'litecoin',
  'ripple',
  'stellar',
  'eos',
  'dogecoin',
  'dash',
];

function isValidScheme(url) {
  if (!url) return false;
  return supportedProtocols.some((network) => url.startsWith(`${network}:`));
}

function decode(url) {
  url = url || '';
  const address = url.split('?')[0].split(':').pop();
  const data = { address };
  let match;
  match = url.match(/amount=([0-9.]+)/);
  if (match && match[1]) {
    data.value = match[1];
  }
  match = url.match(/dt=(\d+)/);
  if (match && match[1]) {
    data.tag = match[1];
  }
  return data;
}

function registerProtocolHandler(network) {
  if (!process.env.BUILD_PLATFORM === 'web') return;
  if (!navigator.registerProtocolHandler) return;
  if (!supportedProtocols.includes(network)) return;
  try {
    navigator.registerProtocolHandler(network, `${urlRoot}wallet/?coin=${network}&bip21=%s`, 'Coin Wallet');
    // eslint-disable-next-line
  } catch (e) {}
}

module.exports = {
  isValidScheme,
  decode,
  registerProtocolHandler,
};
<commit_msg>fix(app): protocol handler<commit_after>'use strict';

const { urlRoot } = window;
const supportedProtocols = [
  'bitcoin',
  'bitcoincash',
  'bitcoinsv',
  'ethereum',
  'litecoin',
  'ripple',
  'stellar',
  'eos',
  'dogecoin',
  'dash',
];

function isValidScheme(url) {
  if (!url) return false;
  return supportedProtocols.some((network) => url.startsWith(`${network}:`));
}

function decode(url) {
  url = url || '';
  const address = url.split('?')[0].split(':').pop();
  const data = { address };
  let match;
  match = url.match(/amount=([0-9.]+)/);
  if (match && match[1]) {
    data.value = match[1];
  }
  match = url.match(/dt=(\d+)/);
  if (match && match[1]) {
    data.tag = match[1];
  }
  return data;
}

function registerProtocolHandler(network) {
  if (process.env.BUILD_PLATFORM !== 'web') return;
  if (!navigator.registerProtocolHandler) return;
  if (!supportedProtocols.includes(network)) return;
  try {
    navigator.registerProtocolHandler(network, `${urlRoot}wallet/?coin=${network}&bip21=%s`, 'Coin Wallet');
    // eslint-disable-next-line
  } catch (e) {}
}

module.exports = {
  isValidScheme,
  decode,
  registerProtocolHandler,
};
<|endoftext|>


<commit_before>/* eslint no-console: "off" */

var express = require('express');
var bodyParser = require('body-parser');
var logger = require('morgan');
var passport = require('passport');
var path = require('path');

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

var app = express();
var history = require('connect-history-api-fallback');
var env = process.env.NODE_ENV || 'development';
var port = process.env.PORT || 3000;

app.use(history({
  // verbose: true
}));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

if (env === 'development') {
  app.use(logger('dev'));
  app.use(function (req, res, next) {
    setTimeout(function () {
      next();
    }, 500);
  });
}

if (env === 'production') {
  app.use(express.static(path.join(__dirname, '../node_modules/mbu-frontend/dist')));
}

app.use(function (req, res, next) {
  if (env === 'development') {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
  }

  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

// Passport configuration
app.use(passport.initialize());
require('./config/passport')(passport);

app.use('/api', require('./routes/index'));
app.use('/api', require('./routes/users'));
app.use('/api', require('./routes/forgot'));
app.use('/api/events', require('./routes/events'));
app.use('/api/badges', require('./routes/badges'));
app.use('/api/scouts', require('./routes/scouts'));

app.use(function (req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

if (!module.parent) {
  models.sequelize.sync().then(function () {
    app.listen(port, function () {
      console.log('MBU src listening on port', port);
    });
  });
}

module.exports = app;
<commit_msg>Morgan logger for http<commit_after>/* eslint no-console: "off" */

var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var passport = require('passport');
var path = require('path');

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

var app = express();
var history = require('connect-history-api-fallback');
var env = process.env.NODE_ENV || 'development';
var port = process.env.PORT || 3000;
var morganFormat = ':method :url :status :res[content-length] - :response-time ms';

app.use(history({
  // verbose: true
}));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

if (env === 'development') {
  app.use(morgan(morganFormat));
  app.use(function (req, res, next) {
    setTimeout(function () {
      next();
    }, 500);
  });
}

if (env === 'production') {
  app.use(morgan(morganFormat));
  app.use(express.static(path.join(__dirname, '../node_modules/mbu-frontend/dist')));
}

app.use(function (req, res, next) {
  if (env === 'development') {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
  }

  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

// Passport configuration
app.use(passport.initialize());
require('./config/passport')(passport);

app.use('/api', require('./routes/index'));
app.use('/api', require('./routes/users'));
app.use('/api', require('./routes/forgot'));
app.use('/api/events', require('./routes/events'));
app.use('/api/badges', require('./routes/badges'));
app.use('/api/scouts', require('./routes/scouts'));

app.use(function (req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

if (!module.parent) {
  models.sequelize.sync().then(function () {
    app.listen(port, function () {
      console.log('MBU src listening on port', port);
    });
  });
}

module.exports = app;
<|endoftext|>