<commit_before>"use strict";
/**
 * @module opcua.address_space
 * @class AddressSpace
 */
require("requirish")._(module);
var assert = require("better-assert");
var _ = require("underscore");
var NodeClass = require("lib/datamodel/nodeclass").NodeClass;
var Argument = require("lib/datamodel/argument_list").Argument;
var DataValue = require("lib/datamodel/datavalue").DataValue;
var Variant = require("lib/datamodel/variant").Variant;
var DataType = require("lib/datamodel/variant").DataType;
var VariantArrayType = require("lib/datamodel/variant").VariantArrayType;
var StatusCodes = require("lib/datamodel/opcua_status_code").StatusCodes;
var browse_service = require("lib/services/browse_service");
var BrowseDirection = browse_service.BrowseDirection;

// Release 1.03 12 OPC Unified Architecture, Part 9
// Two-state state machines
// Most states defined in this standard are simple – i.e. they are either TRUE or FALSE. The
// TwoStateVariableType is introduced specifically for this use case. More complex states are
// modelled by using a StateMachineType defined in Part 5.
// The TwoStateVariableType is derived from the StateVariableType.
//
// Attribute        Value
// BrowseName       TwoStateVariableType
// DataType         LocalizedText
// ValueRank         -1 (-1 = Scalar)
// IsAbstract       False
//
// Subtype of the StateVariableType defined in Part 5.
// Note that a Reference to this subtype is not shown in the definition of the StateVariableType
//
// References      NodeClass BrowseName              DataType      TypeDefinition Modelling Rule
// HasProperty     Variable  Id                      Boolean       PropertyType   Mandatory
// HasProperty     Variable  TransitionTime          UtcTime       PropertyType   Optional
// HasProperty     Variable  EffectiveTransitionTime UtcTime       PropertyType   Optional
// HasProperty     Variable  TrueState               LocalizedText PropertyType   Optional
// HasProperty     Variable  FalseState              LocalizedText PropertyType   Optional
// HasTrueSubState StateMachine or
//                 TwoStateVariableType
//                                                  <StateIdentifier> Defined in Clause 5.4.2 Optional
// HasFalseSubState StateMachine or
//                  TwoStateVariableType
//                                                  <StateIdentifier> Defined in Clause 5.4.3 Optional

function _updateTransitionTime(node) {
    // TransitionTime specifies the time when the current state was entered.
    if (node.transitionTime) {
        node.transitionTime.setValueFromSource({dataType: DataType.DateTime, value: (new Date())})
    }
}

function _updateEffectiveTransitionTime(node,subStateNode) {
    if (node.effectiveTransitionTime) {
        //xx console.log("xxxx _updateEffectiveTransitionTime because subStateNode ",subStateNode.browseName.toString());
        node.effectiveTransitionTime.setValueFromSource({ dataType: DataType.DateTime,value: (new Date())})
    }
}
function _setup_TrueFalseSubStateRelation_detector(node) {

    node._old_add_backward_reference = node._add_backward_reference;
    node._add_backward_reference = function(reference) {

        // call old method
        node._old_add_backward_reference(reference);

        if ( ( reference.referenceType === "HasTrueSubState" ||  reference.referenceType === "HasFalseSubState" ) && reference.isForward) {

            var addressSpace = node.__address_space;
            // add event handle
            var subState = addressSpace.findNode(reference.nodeId);
            subState.on("value_changed",_updateEffectiveTransitionTime.bind(null,node,subState));

        }
    };

    // TODO : shall we care about overloading the remove_backward_reference method ?
}

function _install_effectiveTransitionTime_mechanism(node)
{

    // install change detection on sub State

    // this is useful to change the effective transitionTime
    // EffectiveTransitionTime specifies the time when the current state or one of its sub states was entered.
    // If, for example, a LevelAlarm is active and – while active – switches several times between High and
    // HighHigh, then the TransitionTime stays at the point in time where the Alarm became active whereas the
    // EffectiveTransitionTime changes with each shift of a sub state.
    if(node.effectiveTransitionTime) {

        // install "value_changed" event handler on SubState that are already defined
        var subStates = [].concat(node.getTrueSubStates(),node.getFalseSubStates());
        subStates.forEach(function(subState) {
            subState.on("value_changed",_updateEffectiveTransitionTime.bind(null,node,subState));
        });

        // some TrueSubState and FalseSubState relationship may be added later
        // so we need a mechanism to keep adding the "value_changed" event handle on subStates that
        // will be defined later.
        _setup_TrueFalseSubStateRelation_detector(node);
    }
}

function TwoStateVariable_setValue(boolValue) {

    var node = this;

    var dataValue = node.id.readValue();
    var oldValue = dataValue.value.value;
    if (dataValue.statusCode === StatusCodes.Good && boolValue === oldValue) {
        return; // nothing to do
    }
    //
    node.id.setValueFromSource(new Variant({dataType: DataType.Boolean, value: boolValue}));

    _updateTransitionTime(node);

    _updateEffectiveTransitionTime(node,node);

}

function _getEffectiveDisplayName(node) {
    var dataValue = node.id.readValue();
    if (dataValue.statusCode !== StatusCodes.Good) {
        return dataValue;
    }
    assert(dataValue.value.dataType === DataType.Boolean);
    var boolValue = dataValue.value.value;

    var humanReadableString = _getHumanReadableString(node);

    var subStateNodes;
    if (boolValue) {
        subStateNodes = node.findReferencesExAsObject("HasTrueSubState",BrowseDirection.Forward);
    } else {
        subStateNodes = node.findReferencesExAsObject("HasFalseSubState",BrowseDirection.Forward);
    }
    var states = subStateNodes.forEach(function(n) {
        // todo happen
    });

    return humanReadableString
}
function _getHumanReadableString(node) {

    var dataValue = node.id.readValue();
    if (dataValue.statusCode !== StatusCodes.Good) {
        return dataValue;
    }
    assert(dataValue.value.dataType === DataType.Boolean);
    var boolValue = dataValue.value.value;

    // The Value Attribute of a TwoStateVariable contains the current state as a human readable name.
    // The EnabledState for example, might contain the name “Enabled” when TRUE and “Disabled” when FALSE.

    var valueAsLocalizedText;

    if (boolValue) {
        var _trueState = (node._trueState) ? node._trueState: "TRUE";
        valueAsLocalizedText = { dataType: "LocalizedText", value: { text: _trueState}};

    } else {
        var _falseState = (node._falseState) ? node._falseState: "FALSE";
        valueAsLocalizedText = { dataType: "LocalizedText", value: { text: _falseState}};
    }
    dataValue = dataValue.clone();
    dataValue.value =new Variant(valueAsLocalizedText);
    return dataValue;

}

function _install_TwoStateVariable_machinery(node,options) {

    assert(node.typeDefinitionObj.browseName.toString() === "TwoStateVariableType");
    assert(node.dataTypeObj.browseName.toString() === "LocalizedText");
    assert(node.hasOwnProperty("valueRank") && (node.valueRank === -1 || node.valueRank === 0));

    options = options || {};

    // it should be possible to define a trueState and falseState LocalizedText even if the trueState or FalseState node
    // is not exposed. Therefore we need to store their value into dedicated variables.
    if (options.trueState) {
        assert(options.falseState);
        assert(typeof(options.trueState)=="string" );
        assert(typeof(options.falseState)=="string" );
        node._trueState  = options.trueState;
        node._falseState = options.falseState;
    }

    if (node.falseState) {
        assert(node.trueState);

        node.falseState.bindVariable({
            get: function() {
                var node = this;
                return new Variant({
                    dataType: DataType.LocalizedText,
                    value: node._falseState
                });
            }
        },true);

        node.trueState.bindVariable({
            get: function() {
                var node = this;
                return new Variant({
                    dataType: DataType.LocalizedText,
                    value: node._trueState
                });
            }
        },true);
    }

    assert(node.hasOwnProperty("id"));

    node.id.on("value_changed",function() {
        node._internal_set_dataValue(_getHumanReadableString(node));
    });
    node._internal_set_dataValue(_getHumanReadableString(node));

    // todo : also set the effectiveDisplayName if present

    // from spec Part 5
    // Release 1.03 OPC Unified Architecture, Part 5
    // EffectiveDisplayName contains a human readable name for the current state of the state
    // machine after taking the state of any SubStateMachines in account. There is no rule specified
    // for which state or sub-state should be used. It is up to the Server and will depend on the
    // semantics of the StateMachineType
    //
    // EffectiveDisplaName will be constructed by added the EnableState
    // and the State of the addTrue state
    if (node.effectiveDisplayName) {

        node.id.on("value_changed",function() {
            node.effectiveDisplayName._internal_set_dataValue(_getEffectiveDisplayName(node));
        });
        node.effectiveDisplayName._internal_set_dataValue(_getEffectiveDisplayName(node));

    }

    _install_effectiveTransitionTime_mechanism(node);

    node.setValue = TwoStateVariable_setValue;

}

exports.install = function (AddressSpace) {

    AddressSpace._install_TwoStateVariable_machinery = _install_TwoStateVariable_machinery;

    /**
     *
     * @method addTwoStateVariable
     *
     * @param options
     * @param options.browseName  {String}
     * @param [options.description {String}]
     * @param [options.modellingRule {String}]
     * @param [options.minimumSamplingInterval {Number} =0]
     * @param options.componentOf {Node|NodeId}
     * @param options.propertyOf {Node|NodeId}
     * @param options.trueState {String}
     * @param options.falseState {String}
     * @param [options.isTrueSubStateOf {NodeId}]
     * @param [options.isFalseSubStateOf {NodeId}]
     * @param [options.modellingRule]
     * @return {UAVariable}
     *
     * Optionals can be EffectiveDisplayName, TransitionTime, EffectiveTransitionTime
     */
    AddressSpace.prototype.addTwoStateVariable   = function (options) {

        assert(options.browseName," a browseName is required");
        var addressSpace = this;

        var twoStateVariableType = addressSpace.findVariableType("TwoStateVariableType");

        options.optionals = options.optionals || [];
        if (options.trueState) {
            options.optionals.push("TrueState");
        }
        if (options.falseState) {
            options.optionals.push("FalseState");
        }

        // we want event based change...
        options.minimumSamplingInterval = 0;

        var node = twoStateVariableType.instantiate({
            browseName:  options.browseName,

            nodeId: options.nodeId,

            description: options.description,

            organizedBy: options.organizedBy,
            componentOf: options.componentOf,
            propertyOf: options.propertyOf,

            modellingRule : options.modellingRule,

            minimumSamplingInterval: options.minimumSamplingInterval,
            optionals:   options.optionals
        });
        assert(node.dataTypeObj.browseName.toString()=== "LocalizedText");
        assert(node.minimumSamplingInterval === 0);

        if (options.trueState) {
            node._trueState = options.trueState;
            node.trueState.setValueFromSource({ dataType: "LocalizedText", value: { text : options.trueState }});
        }
        if (options.falseState) {
            node._falseState = options.falseState;
            node.falseState.setValueFromSource({ dataType: "LocalizedText", value: { text : options.falseState }});
        }

        node.id.setValueFromSource( {dataType: "Boolean", value: false} , StatusCodes.UncertainInitialValue);

        // handle isTrueSubStateOf
        if (options.isTrueSubStateOf) {
            node.addReference({ referenceType: "HasTrueSubState", isForward: false, nodeId: options.isTrueSubStateOf});
        }
        if (options.isFalseSubStateOf) {
            node.addReference({ referenceType: "HasFalseSubState", isForward: false, nodeId: options.isFalseSubStateOf});
        }

        _install_TwoStateVariable_machinery(node);

        return node;
    };
};

<commit_msg>add propertyOf options<commit_after>"use strict";
/**
 * @module opcua.address_space
 * @class AddressSpace
 */
require("requirish")._(module);
var assert = require("better-assert");
var _ = require("underscore");
var NodeClass = require("lib/datamodel/nodeclass").NodeClass;
var Argument = require("lib/datamodel/argument_list").Argument;
var DataValue = require("lib/datamodel/datavalue").DataValue;
var Variant = require("lib/datamodel/variant").Variant;
var DataType = require("lib/datamodel/variant").DataType;
var VariantArrayType = require("lib/datamodel/variant").VariantArrayType;
var StatusCodes = require("lib/datamodel/opcua_status_code").StatusCodes;
var browse_service = require("lib/services/browse_service");
var BrowseDirection = browse_service.BrowseDirection;

// Release 1.03 12 OPC Unified Architecture, Part 9
// Two-state state machines
// Most states defined in this standard are simple – i.e. they are either TRUE or FALSE. The
// TwoStateVariableType is introduced specifically for this use case. More complex states are
// modelled by using a StateMachineType defined in Part 5.
// The TwoStateVariableType is derived from the StateVariableType.
//
// Attribute        Value
// BrowseName       TwoStateVariableType
// DataType         LocalizedText
// ValueRank         -1 (-1 = Scalar)
// IsAbstract       False
//
// Subtype of the StateVariableType defined in Part 5.
// Note that a Reference to this subtype is not shown in the definition of the StateVariableType
//
// References      NodeClass BrowseName              DataType      TypeDefinition Modelling Rule
// HasProperty     Variable  Id                      Boolean       PropertyType   Mandatory
// HasProperty     Variable  TransitionTime          UtcTime       PropertyType   Optional
// HasProperty     Variable  EffectiveTransitionTime UtcTime       PropertyType   Optional
// HasProperty     Variable  TrueState               LocalizedText PropertyType   Optional
// HasProperty     Variable  FalseState              LocalizedText PropertyType   Optional
// HasTrueSubState StateMachine or
//                 TwoStateVariableType
//                                                  <StateIdentifier> Defined in Clause 5.4.2 Optional
// HasFalseSubState StateMachine or
//                  TwoStateVariableType
//                                                  <StateIdentifier> Defined in Clause 5.4.3 Optional

function _updateTransitionTime(node) {
    // TransitionTime specifies the time when the current state was entered.
    if (node.transitionTime) {
        node.transitionTime.setValueFromSource({dataType: DataType.DateTime, value: (new Date())})
    }
}

function _updateEffectiveTransitionTime(node,subStateNode) {
    if (node.effectiveTransitionTime) {
        //xx console.log("xxxx _updateEffectiveTransitionTime because subStateNode ",subStateNode.browseName.toString());
        node.effectiveTransitionTime.setValueFromSource({ dataType: DataType.DateTime,value: (new Date())})
    }
}
function _setup_TrueFalseSubStateRelation_detector(node) {

    node._old_add_backward_reference = node._add_backward_reference;
    node._add_backward_reference = function(reference) {

        // call old method
        node._old_add_backward_reference(reference);

        if ( ( reference.referenceType === "HasTrueSubState" ||  reference.referenceType === "HasFalseSubState" ) && reference.isForward) {

            var addressSpace = node.__address_space;
            // add event handle
            var subState = addressSpace.findNode(reference.nodeId);
            subState.on("value_changed",_updateEffectiveTransitionTime.bind(null,node,subState));

        }
    };

    // TODO : shall we care about overloading the remove_backward_reference method ?
}

function _install_effectiveTransitionTime_mechanism(node)
{

    // install change detection on sub State

    // this is useful to change the effective transitionTime
    // EffectiveTransitionTime specifies the time when the current state or one of its sub states was entered.
    // If, for example, a LevelAlarm is active and – while active – switches several times between High and
    // HighHigh, then the TransitionTime stays at the point in time where the Alarm became active whereas the
    // EffectiveTransitionTime changes with each shift of a sub state.
    if(node.effectiveTransitionTime) {

        // install "value_changed" event handler on SubState that are already defined
        var subStates = [].concat(node.getTrueSubStates(),node.getFalseSubStates());
        subStates.forEach(function(subState) {
            subState.on("value_changed",_updateEffectiveTransitionTime.bind(null,node,subState));
        });

        // some TrueSubState and FalseSubState relationship may be added later
        // so we need a mechanism to keep adding the "value_changed" event handle on subStates that
        // will be defined later.
        _setup_TrueFalseSubStateRelation_detector(node);
    }
}

function TwoStateVariable_setValue(boolValue) {

    var node = this;

    var dataValue = node.id.readValue();
    var oldValue = dataValue.value.value;
    if (dataValue.statusCode === StatusCodes.Good && boolValue === oldValue) {
        return; // nothing to do
    }
    //
    node.id.setValueFromSource(new Variant({dataType: DataType.Boolean, value: boolValue}));

    _updateTransitionTime(node);

    _updateEffectiveTransitionTime(node,node);

}

function _getEffectiveDisplayName(node) {
    var dataValue = node.id.readValue();
    if (dataValue.statusCode !== StatusCodes.Good) {
        return dataValue;
    }
    assert(dataValue.value.dataType === DataType.Boolean);
    var boolValue = dataValue.value.value;

    var humanReadableString = _getHumanReadableString(node);

    var subStateNodes;
    if (boolValue) {
        subStateNodes = node.findReferencesExAsObject("HasTrueSubState",BrowseDirection.Forward);
    } else {
        subStateNodes = node.findReferencesExAsObject("HasFalseSubState",BrowseDirection.Forward);
    }
    var states = subStateNodes.forEach(function(n) {
        // todo happen
    });

    return humanReadableString
}
function _getHumanReadableString(node) {

    var dataValue = node.id.readValue();
    if (dataValue.statusCode !== StatusCodes.Good) {
        return dataValue;
    }
    assert(dataValue.value.dataType === DataType.Boolean);
    var boolValue = dataValue.value.value;

    // The Value Attribute of a TwoStateVariable contains the current state as a human readable name.
    // The EnabledState for example, might contain the name “Enabled” when TRUE and “Disabled” when FALSE.

    var valueAsLocalizedText;

    if (boolValue) {
        var _trueState = (node._trueState) ? node._trueState: "TRUE";
        valueAsLocalizedText = { dataType: "LocalizedText", value: { text: _trueState}};

    } else {
        var _falseState = (node._falseState) ? node._falseState: "FALSE";
        valueAsLocalizedText = { dataType: "LocalizedText", value: { text: _falseState}};
    }
    dataValue = dataValue.clone();
    dataValue.value =new Variant(valueAsLocalizedText);
    return dataValue;

}

function _install_TwoStateVariable_machinery(node,options) {

    assert(node.typeDefinitionObj.browseName.toString() === "TwoStateVariableType");
    assert(node.dataTypeObj.browseName.toString() === "LocalizedText");
    assert(node.hasOwnProperty("valueRank") && (node.valueRank === -1 || node.valueRank === 0));

    options = options || {};

    // it should be possible to define a trueState and falseState LocalizedText even if the trueState or FalseState node
    // is not exposed. Therefore we need to store their value into dedicated variables.
    if (options.trueState) {
        assert(options.falseState);
        assert(typeof(options.trueState)=="string" );
        assert(typeof(options.falseState)=="string" );
        node._trueState  = options.trueState;
        node._falseState = options.falseState;
    }

    if (node.falseState) {
        assert(node.trueState);

        node.falseState.bindVariable({
            get: function() {
                var node = this;
                return new Variant({
                    dataType: DataType.LocalizedText,
                    value: node._falseState
                });
            }
        },true);

        node.trueState.bindVariable({
            get: function() {
                var node = this;
                return new Variant({
                    dataType: DataType.LocalizedText,
                    value: node._trueState
                });
            }
        },true);
    }

    assert(node.hasOwnProperty("id"));

    node.id.on("value_changed",function() {
        node._internal_set_dataValue(_getHumanReadableString(node));
    });
    node._internal_set_dataValue(_getHumanReadableString(node));

    // todo : also set the effectiveDisplayName if present

    // from spec Part 5
    // Release 1.03 OPC Unified Architecture, Part 5
    // EffectiveDisplayName contains a human readable name for the current state of the state
    // machine after taking the state of any SubStateMachines in account. There is no rule specified
    // for which state or sub-state should be used. It is up to the Server and will depend on the
    // semantics of the StateMachineType
    //
    // EffectiveDisplaName will be constructed by added the EnableState
    // and the State of the addTrue state
    if (node.effectiveDisplayName) {

        node.id.on("value_changed",function() {
            node.effectiveDisplayName._internal_set_dataValue(_getEffectiveDisplayName(node));
        });
        node.effectiveDisplayName._internal_set_dataValue(_getEffectiveDisplayName(node));

    }

    _install_effectiveTransitionTime_mechanism(node);

    node.setValue = TwoStateVariable_setValue;

}

exports.install = function (AddressSpace) {

    AddressSpace._install_TwoStateVariable_machinery = _install_TwoStateVariable_machinery;

    /**
     *
     * @method addTwoStateVariable
     *
     * @param options
     * @param options.browseName  {String}
     * @param [options.description {String}]
     * @param [options.modellingRule {String}]
     * @param [options.minimumSamplingInterval {Number} =0]
     * @param options.componentOf {Node|NodeId}
     * @param options.propertyOf {Node|NodeId}
     * @param options.trueState {String}
     * @param options.falseState {String}
     * @param [options.isTrueSubStateOf {NodeId}]
     * @param [options.isFalseSubStateOf {NodeId}]
     * @param [options.modellingRule]
     * @return {UAVariable}
     *
     * Optionals can be EffectiveDisplayName, TransitionTime, EffectiveTransitionTime
     */
    AddressSpace.prototype.addTwoStateVariable   = function (options) {

        assert(options.browseName," a browseName is required");
        var addressSpace = this;

        var twoStateVariableType = addressSpace.findVariableType("TwoStateVariableType");

        options.optionals = options.optionals || [];
        if (options.trueState) {
            options.optionals.push("TrueState");
        }
        if (options.falseState) {
            options.optionals.push("FalseState");
        }

        // we want event based change...
        options.minimumSamplingInterval = 0;

        var node = twoStateVariableType.instantiate({
            browseName:  options.browseName,

            nodeId: options.nodeId,

            description: options.description,

            organizedBy: options.organizedBy,
            componentOf: options.componentOf,
            //xx propertyOf: options.propertyOf,

            modellingRule : options.modellingRule,

            minimumSamplingInterval: options.minimumSamplingInterval,
            optionals:   options.optionals
        });
        assert(node.dataTypeObj.browseName.toString()=== "LocalizedText");
        assert(node.minimumSamplingInterval === 0);

        if (options.trueState) {
            node._trueState = options.trueState;
            node.trueState.setValueFromSource({ dataType: "LocalizedText", value: { text : options.trueState }});
        }
        if (options.falseState) {
            node._falseState = options.falseState;
            node.falseState.setValueFromSource({ dataType: "LocalizedText", value: { text : options.falseState }});
        }

        node.id.setValueFromSource( {dataType: "Boolean", value: false} , StatusCodes.UncertainInitialValue);

        // handle isTrueSubStateOf
        if (options.isTrueSubStateOf) {
            node.addReference({ referenceType: "HasTrueSubState", isForward: false, nodeId: options.isTrueSubStateOf});
        }
        if (options.isFalseSubStateOf) {
            node.addReference({ referenceType: "HasFalseSubState", isForward: false, nodeId: options.isFalseSubStateOf});
        }

        _install_TwoStateVariable_machinery(node);

        return node;
    };
};

<|endoftext|>


<commit_before>'use strict';

const router = require('koa-router')();
const { renderToStaticMarkup } = require('react-dom/server');

const getCardsController = require('./controllers/cards/get-cards.js');
const createCardController = require('./controllers/cards/create.js');
const deleteCardController = require('./controllers/cards/delete.js');

const getTransactionsController = require('./controllers/transactions/get.js');
const createTransactionsController = require('./controllers/transactions/create.js');

const createPayController = require('./controllers/pay/create.js');

const errorController = require('./controllers/error.js');
const indexView = require('./views/index.server.js');

const DATA = {
  user: {
    login: 'samuel_johnson',
    name: 'Samuel Johnson',
  },
};

router.get('/', (ctx) => {
  const indexViewHtml = renderToStaticMarkup(indexView(DATA));

  ctx.body = indexViewHtml;
});

router.get('/cards/', getCardsController);
router.post('/cards/', createCardController);
router.delete('/cards/:id', deleteCardController);

router.get('/cards/:id/transactions/', getTransactionsController);
router.post('/cards/:id/transactions/', createTransactionsController);

router.post('/cards/:id/pay', createPayController);

router.all('/error', errorController);

module.exports = router;
<commit_msg>Switch to renderToStaticNodeStream<commit_after>'use strict';

const router = require('koa-router')();
const { renderToStaticNodeStream } = require('react-dom/server');

const getCardsController = require('./controllers/cards/get-cards.js');
const createCardController = require('./controllers/cards/create.js');
const deleteCardController = require('./controllers/cards/delete.js');

const getTransactionsController = require('./controllers/transactions/get.js');
const createTransactionsController = require('./controllers/transactions/create.js');

const createPayController = require('./controllers/pay/create.js');

const errorController = require('./controllers/error.js');
const indexView = require('./views/index.server.js');

const DATA = {
  user: {
    login: 'samuel_johnson',
    name: 'Samuel Johnson',
  },
};

router.get('/', (ctx) => {
  ctx.type = 'html';
  ctx.body = renderToStaticNodeStream(indexView(DATA));
});

router.get('/cards/', getCardsController);
router.post('/cards/', createCardController);
router.delete('/cards/:id', deleteCardController);

router.get('/cards/:id/transactions/', getTransactionsController);
router.post('/cards/:id/transactions/', createTransactionsController);

router.post('/cards/:id/pay', createPayController);

router.all('/error', errorController);

module.exports = router;
<|endoftext|>


<commit_before>/* global $, google, Roundware */
const ROUNDWARE_SERVER_URL = 'https://prod.roundware.com/api/2';

//const ROUNDWARE_SERVER_URL = 'https://simw.roundware.com/api/2';
//const ROUNDWARE_DEFAULT_PROJECT_ID = 9;
//const ROUNDWARE_INITIAL_LATITUDE=39.22101;
//const ROUNDWARE_INITIAL_LONGITUDE=-85.897893;

//const ROUNDWARE_DEFAULT_PROJECT_ID = 10;
//const ROUNDWARE_INITIAL_LATITUDE = 42.337060559285234;
//const ROUNDWARE_INITIAL_LONGITUDE = -71.09792028045655;

//const ROUNDWARE_DEFAULT_PROJECT_ID = 1;
//const ROUNDWARE_INITIAL_LATITUDE = 41.0408653367726;
//const ROUNDWARE_INITIAL_LONGITUDE = -73.22926793670655;

const ROUNDWARE_DEFAULT_PROJECT_ID = 27;
const ROUNDWARE_INITIAL_LATITUDE = 34.02233;
const ROUNDWARE_INITIAL_LONGITUDE = -118.286364;

function mapSpeakers(map,roundware) {
  const speakers = roundware.speakers();

  $.each(speakers,function (i, item) {
    map.data.addGeoJson({
      "type": "Feature",
      "geometry": item.shape,
      "properties": {
        "speaker_id": item.id,
        "title": "outer"
      }
    });

    map.data.addGeoJson({
      "type": "Feature",
      "geometry": item.attenuation_border,
      "properties": {
        "speaker_id": item.id,
        "title": "inner"
      }
    });

    map.data.setStyle(function(feature) {
      if (feature.getProperty('name') == "outer") {
        return {
          fillColor: '#aaaaaa',
          fillOpacity: .5,
          strokeWeight: 1,
          strokeOpacity: .5
        };
      }
      else if (feature.getProperty('name') == "inner") {
        return {
          fillColor: '#555555',
          fillOpacity: 0,
          strokeWeight: 1,
          strokeOpacity: .2
        };
      }
    });
  });
}

function mapAssets(map,roundware) {
  const assets = roundware.assets();
  const assetMarkers = [];

  $.each(assets, function (i, item) {
    var marker_img = new google.maps.MarkerImage('https://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png');
    var point = new google.maps.LatLng(item.latitude, item.longitude);
    // var tag_ids = item.tag_ids.toString();
    // console.log('tag_ids = ' + tag_ids);

    var marker = new google.maps.Marker({
      position: point,
      map: map,
      icon: marker_img
    });

    marker.id = item.id;
    marker.rw_tags = [];

    if (item.tag_ids) {
      marker.rw_tags = item.tag_ids;
    }

    // display asset shape if exists
    if (item.shape) {
      marker.shape = new google.maps.Data();
      marker.shape.addGeoJson({
        "type": "Feature",
        "geometry": item.shape,
        "properties": {
          "asset_id": item.id,
          "name": "assetRange"
        }
      });

      marker.shape.setStyle(function(feature) {
        if (feature.getProperty('name') == "assetRange") {
          return {
            fillColor: '#6292CF',
            fillOpacity: .25,
            strokeWeight: 1,
            strokeOpacity: .8,
            strokeColor: '#6292CF'
          };
        }
      });
    } else {
      // if no asset shape, display default circle range
      const circle = {
        strokeColor: '#6292CF',
        strokeOpacity: 0.8,
        strokeWeight: 1,
        fillColor: '#6292CF',
        fillOpacity: 0.25,
        map: map,
        center: new google.maps.LatLng(item.latitude, item.longitude),
        radius: roundware._project.recordingRadius
      };

      marker.circle = new google.maps.Circle(circle);
    }

    assetMarkers.push(marker);
  });

  return assetMarkers;
}

function showHideMarkers(map,assetMarkers) {
  $.each(assetMarkers,function(i,item) {
    // if any item tags are not included in selected tags, hide marker, otherwise show it
    let selectedListenTagIds = $("#uiListenDisplay input:checked").map(function() {
      return Number(this.value);
    }).get();
    var is_visible = true;

    $.each(item.rw_tags, function(j, tag_id) {
      // if tag_id isn't selected, set to false and return
      if (!(selectedListenTagIds.includes(tag_id))) {
        is_visible = false;
        return;
      }
    });

    item.setVisible(is_visible);

    if (item.circle) {
      item.circle.setVisible(is_visible);
    }
    if (item.shape) {
      if (is_visible) {
        item.shape.setMap(map);
      } else if (!is_visible) {
        item.shape.setMap(null);
      }
    }
  });
}

// This function is intended to be invoked by the google API callback; see index.html
/* eslint-disable-next-line no-unused-vars */
function initDemo() {
  const googleMapsCenter = {
    lat: ROUNDWARE_INITIAL_LATITUDE,
    lng: ROUNDWARE_INITIAL_LONGITUDE
  };

  const listenerLocation = {
    latitude: ROUNDWARE_INITIAL_LATITUDE,
    longitude: ROUNDWARE_INITIAL_LONGITUDE
  };

  const listenMapEl = document.getElementById('mixMap');
  const playPauseBtn = document.getElementById('playPauseBtn');

  const map = new google.maps.Map(listenMapEl,{
    zoom: 18,
    center: googleMapsCenter
  });

  const listener = new google.maps.Marker({
    position: googleMapsCenter,
    map,
    draggable: true
  });

  const roundware = new Roundware(window,{
    serverUrl: ROUNDWARE_SERVER_URL,
    projectId: ROUNDWARE_DEFAULT_PROJECT_ID,
    geoListenEnabled: true,
    speakerFilters: { activeyn: true },
    assetFilters:   { submitted: true, media_type: "audio" },
    listenerLocation
  });

  roundware.
    connect().
    then(() => {
      mapSpeakers(map,roundware);

      const assetMarkers = mapAssets(map,roundware);
      showHideMarkers(assetMarkers);

      const mixer = roundware.activateMixer();

      google.maps.event.addListener(listener, "dragend",() => {
        const position = listener.getPosition();
        map.setCenter(position);

        const latitude = position.lat();
        const longitude = position.lng();

        roundware.updateLocation({ latitude, longitude });
      });

      playPauseBtn.addEventListener('click',() => {
        const isPlaying = mixer.toggle();
        playPauseBtn.textContent = isPlaying ? 'Pause' : 'Play';
      });

      playPauseBtn.disabled = false;
    }).
    catch(err => console.log('Roundware connection error',err));
}
<commit_msg>add info windows so we can check right assets playing<commit_after>/* global $, google, Roundware */
const ROUNDWARE_SERVER_URL = 'https://prod.roundware.com/api/2';

//const ROUNDWARE_SERVER_URL = 'https://simw.roundware.com/api/2';
//const ROUNDWARE_DEFAULT_PROJECT_ID = 9;
//const ROUNDWARE_INITIAL_LATITUDE=39.22101;
//const ROUNDWARE_INITIAL_LONGITUDE=-85.897893;

//const ROUNDWARE_DEFAULT_PROJECT_ID = 10;
//const ROUNDWARE_INITIAL_LATITUDE = 42.337060559285234;
//const ROUNDWARE_INITIAL_LONGITUDE = -71.09792028045655;

//const ROUNDWARE_DEFAULT_PROJECT_ID = 1;
//const ROUNDWARE_INITIAL_LATITUDE = 41.0408653367726;
//const ROUNDWARE_INITIAL_LONGITUDE = -73.22926793670655;

const ROUNDWARE_DEFAULT_PROJECT_ID = 27;
const ROUNDWARE_INITIAL_LATITUDE = 34.02233;
const ROUNDWARE_INITIAL_LONGITUDE = -118.286364;

function mapSpeakers(map,roundware) {
  const speakers = roundware.speakers();

  $.each(speakers,function (i, item) {
    map.data.addGeoJson({
      "type": "Feature",
      "geometry": item.shape,
      "properties": {
        "speaker_id": item.id,
        "title": "outer"
      }
    });

    map.data.addGeoJson({
      "type": "Feature",
      "geometry": item.attenuation_border,
      "properties": {
        "speaker_id": item.id,
        "title": "inner"
      }
    });

    map.data.setStyle(function(feature) {
      if (feature.getProperty('name') == "outer") {
        return {
          fillColor: '#aaaaaa',
          fillOpacity: .5,
          strokeWeight: 1,
          strokeOpacity: .5
        };
      }
      else if (feature.getProperty('name') == "inner") {
        return {
          fillColor: '#555555',
          fillOpacity: 0,
          strokeWeight: 1,
          strokeOpacity: .2
        };
      }
    });
  });
}

const MARKER_IMG_SRC = 'https://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png';

function mapAssets(map,roundware) {
  const assets = roundware.assets();
  const assetMarkers = [];
  const markerImg = new google.maps.MarkerImage(MARKER_IMG_SRC);

  $.each(assets, function (i, item) {
    const point = new google.maps.LatLng(item.latitude,item.longitude);
    // var tag_ids = item.tag_ids.toString();
    // console.log('tag_ids = ' + tag_ids);

    const marker = new google.maps.Marker({
      position: point,
      map: map,
      icon: markerImg
    });

    marker.id = item.id;
    marker.rw_tags = [];

    if (item.tag_ids) {
      marker.rw_tags = item.tag_ids;
    }

    const content = `
Asset ${item.id}

                     ${item.file}

Volume	${item.volume}

Created	${item.created.slice(0,19)}

Weight	${item.weight}

Tags	${item.tag_ids}

`;

    const infoWindow = new google.maps.InfoWindow({ content });

    marker.addListener('click', function() {
      infoWindow.open(map,marker);
    });

    // display asset shape if exists
    if (item.shape) {
      marker.shape = new google.maps.Data();
      marker.shape.addGeoJson({
        "type": "Feature",
        "geometry": item.shape,
        "properties": {
          "asset_id": item.id,
          "name": "assetRange"
        }
      });

      marker.shape.setStyle(function(feature) {
        if (feature.getProperty('name') == "assetRange") {
          return {
            fillColor: '#6292CF',
            fillOpacity: .25,
            strokeWeight: 1,
            strokeOpacity: .8,
            strokeColor: '#6292CF'
          };
        }
      });
    } else {
      // if no asset shape, display default circle range
      const circle = {
        strokeColor: '#6292CF',
        strokeOpacity: 0.8,
        strokeWeight: 1,
        fillColor: '#6292CF',
        fillOpacity: 0.25,
        map: map,
        center: new google.maps.LatLng(item.latitude, item.longitude),
        radius: roundware._project.recordingRadius
      };

      marker.circle = new google.maps.Circle(circle);
    }

    assetMarkers.push(marker);
  });

  return assetMarkers;
}

function showHideMarkers(map,assetMarkers) {
  $.each(assetMarkers,function(i,item) {
    // if any item tags are not included in selected tags, hide marker, otherwise show it
    let selectedListenTagIds = $("#uiListenDisplay input:checked").map(function() {
      return Number(this.value);
    }).get();
    var is_visible = true;

    $.each(item.rw_tags, function(j, tag_id) {
      // if tag_id isn't selected, set to false and return
      if (!(selectedListenTagIds.includes(tag_id))) {
        is_visible = false;
        return;
      }
    });

    item.setVisible(is_visible);

    if (item.circle) {
      item.circle.setVisible(is_visible);
    }
    if (item.shape) {
      if (is_visible) {
        item.shape.setMap(map);
      } else if (!is_visible) {
        item.shape.setMap(null);
      }
    }
  });
}

// This function is intended to be invoked by the google API callback; see index.html
/* eslint-disable-next-line no-unused-vars */
function initDemo() {
  const googleMapsCenter = {
    lat: ROUNDWARE_INITIAL_LATITUDE,
    lng: ROUNDWARE_INITIAL_LONGITUDE
  };

  const listenerLocation = {
    latitude: ROUNDWARE_INITIAL_LATITUDE,
    longitude: ROUNDWARE_INITIAL_LONGITUDE
  };

  const listenMapEl = document.getElementById('mixMap');
  const playPauseBtn = document.getElementById('playPauseBtn');

  const map = new google.maps.Map(listenMapEl,{
    zoom: 18,
    center: googleMapsCenter
  });

  const listener = new google.maps.Marker({
    position: googleMapsCenter,
    map,
    draggable: true
  });

  const roundware = new Roundware(window,{
    serverUrl: ROUNDWARE_SERVER_URL,
    projectId: ROUNDWARE_DEFAULT_PROJECT_ID,
    geoListenEnabled: true,
    speakerFilters: { activeyn: true },
    assetFilters:   { submitted: true, media_type: "audio" },
    listenerLocation
  });

  roundware.
    connect().
    then(() => {
      mapSpeakers(map,roundware);

      const assetMarkers = mapAssets(map,roundware);
      showHideMarkers(assetMarkers);

      const mixer = roundware.activateMixer();

      google.maps.event.addListener(listener, "dragend",() => {
        const position = listener.getPosition();
        map.setCenter(position);

        const latitude = position.lat();
        const longitude = position.lng();

        roundware.updateLocation({ latitude, longitude });
      });

      playPauseBtn.addEventListener('click',() => {
        const isPlaying = mixer.toggle();
        playPauseBtn.textContent = isPlaying ? 'Pause' : 'Play';
      });

      playPauseBtn.disabled = false;
    }).
    catch(err => console.log('Roundware connection error',err));
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------
 * OpenERP web_graph
 *---------------------------------------------------------*/

openerp.web_graph = function (instance) {

var _lt = instance.web._lt;

// removed ``undefined`` values
var filter_values = function (o) {
    var out = {};
    for (var k in o) {
        if (!o.hasOwnProperty(k) || o[k] === undefined) { continue; }
        out[k] = o[k];
    }
    return out;
};

instance.web.views.add('graph', 'instance.web_graph.GraphView');
instance.web_graph.GraphView = instance.web.View.extend({
    template: "GraphView",
    display_name: _lt('Graph'),
    view_type: "graph",

    init: function(parent, dataset, view_id, options) {
        var self = this;
        this._super(parent);
        this.set_default_options(options);
        this.dataset = dataset;
        this.view_id = view_id;

        this.mode = "bar";          // line, bar, area, pie, radar
        this.orientation = false;    // true: horizontal, false: vertical
        this.stacked = true;

        this.spreadsheet = false;   // Display data grid, allows copy to CSV
        this.forcehtml = false;
        this.legend = "top";        // top, inside, no

        this.domain = [];
        this.context = {};
        this.group_by = [];

        this.graph = null;
        this.on('view_loaded', self, self.load_graph);
    },
    destroy: function () {
        if (this.graph) {
            this.graph.destroy();
        }
        this._super();
    },

    load_graph: function(fields_view_get) {
        // TODO: move  to load_view and document
        var self = this;
        this.fields_view = fields_view_get;
        this.$el.addClass(this.fields_view.arch.attrs['class']);

        this.mode = this.fields_view.arch.attrs.type || 'bar';
        this.orientation = this.fields_view.arch.attrs.orientation == 'horizontal';

        var width = this.$el.parent().width();
        this.$el.css("width", width);
        this.container = this.$el.find("#editor-render-body").css({
            width: width,
            height: Math.min(500, width * 0.8)
        })[0];

        var graph_render = this.proxy('graph_render');
        this.$el.on('click', '.oe_graph_options a', function (evt) {
            var $el = $(evt.target);

            self.graph_render({data: filter_values({
                mode: $el.data('mode'),
                legend: $el.data('legend'),
                orientation: $el.data('orientation'),
                stacked: $el.data('stacked')
            })});
        });

        this.$el.find("#graph_show_data").click(function () {
            self.spreadsheet = ! self.spreadsheet;
            self.graph_render();
        });
        this.$el.find("#graph_switch").click(function () {
            if (self.mode != 'radar') {
                self.orientation = ! self.orientation;
            }
            self.graph_render();
        });

        this.$el.find("#graph_download").click(function () {
            if (self.legend == "top") { self.legend = "inside"; }
            self.forcehtml = true;

            self.graph_get_data().then(function (result) {
                self.graph_render_all(result).download.saveImage('png');
            }).always(function () {
                self.forcehtml = false;
            });
        });
        this.trigger('graph_view_loaded', fields_view_get);
    },

    get_format: function (options) {
        options = options || {};
        var legend = {
            show: this.legend != 'no',
        };

        switch (this.legend) {
        case 'top':
            legend.noColumns = 4;
            legend.container = this.$el.find("div.graph_header_legend")[0];
            break;
        case 'inside':
            legend.position = 'nw';
            legend.backgroundColor = '#D2E8FF';
            break;
        }

        return _.extend({
            legend: legend,
            mouse: {
                track: true,
                relative: true
            },
            spreadsheet : {
                show: this.spreadsheet,
                initialTab: "data"
            },
            HtmlText : (options.xaxis && options.xaxis.labelsAngle) ? false : !this.forcehtml,
        }, options);
    },

    make_graph: function (mode, container, data) {
        if (mode === 'area') { mode = 'line'; }
        return Flotr.draw(
            container, data.data,
            this.get_format(this['options_' + mode](data)));
    },

    options_bar: function (data) {
        var min = _(data.data).chain()
            .map(function (record) {
                if (record.data.length > 0){
	                return _.min(record.data, function (item) {
	                    return item[1];
	                })[1];
                }
            }).min().value();
        return {
            bars : {
                show : true,
                stacked : this.stacked,
                horizontal : this.orientation,
                barWidth : 0.7,
                lineWidth : 1
            },
            grid : {
                verticalLines : this.orientation,
                horizontalLines : !this.orientation,
                outline : "sw",
            },
            yaxis : {
                ticks: this.orientation ? data.ticks : false,
                min: !this.orientation ? (min < 0 ? min : 0) : null
            },
            xaxis : {
                labelsAngle: 45,
                ticks: this.orientation ? false : data.ticks,
                min: this.orientation ? (min < 0 ? min : 0) : null
            }
        };
    },

    options_pie: function (data) {
        return {
            pie : {
                show: true
            },
            grid : {
                verticalLines : false,
                horizontalLines : false,
                outline : "",
            },
            xaxis :  {showLabels: false},
            yaxis :  {showLabels: false},
        };
    },

    options_radar: function (data) {
        return {
            radar : {
                show : true,
                stacked : this.stacked
            },
            grid : {
                circular : true,
                minorHorizontalLines : true
            },
            xaxis : {
                ticks: data.ticks
            },
        };
    },

    options_line: function (data) {
        return {
            lines : {
                show : true,
                stacked : this.stacked
            },
            grid : {
                verticalLines : this.orientation,
                horizontalLines : !this.orientation,
                outline : "sw",
            },
            yaxis : {
                ticks: this.orientation ? data.ticks : false
            },
            xaxis : {
                labelsAngle: 45,
                ticks: this.orientation ? false : data.ticks
            }
        };
    },

    graph_get_data: function () {
        var model = this.dataset.model,
            domain = new instance.web.CompoundDomain(this.domain || []),
            context = new instance.web.CompoundContext(this.context || {}),
            group_by = this.group_by || [],
            view_id = this.view_id  || false,
            mode = this.mode || 'bar',
            orientation = this.orientation || false,
            stacked = this.stacked || false;

        var obj = new instance.web.Model(model);
        var view_get;
        var fields;
        var result = [];
        var ticks = {};

        return obj.call("fields_view_get", [view_id, 'graph']).pipe(function(tmp) {
            view_get = tmp;
            fields = view_get['fields'];
            var toload = _.select(group_by, function(x) { return fields[x] === undefined });
            if (toload.length >= 1)
                return obj.call("fields_get", [toload, context]);
            else
                return $.when([]);
        }).pipe(function (fields_to_add) {
            _.extend(fields, fields_to_add);

            var tree = $($.parseXML(view_get['arch']));

            var pos = 0;
            var xaxis = group_by || [];
            var yaxis = [];
            tree.find("field").each(function() {
                var field = $(this);
                if (! field.attr("name"))
                    return;
                if ((group_by.length == 0) && ((! pos) || field.attr('group'))) {
                    xaxis.push(field.attr('name'));
                }
                if (pos && ! field.attr('group')) {
                    yaxis.push(field.attr('name'));
                }
                pos += 1;
            });

            if (xaxis.length === 0)
                throw new Error("No field for the X axis!");
            if (yaxis.length === 0)
                throw new Error("No field for the Y axis!");

            // Convert a field's data into a displayable string

            function _convert_key(field, data) {
                if (fields[field]['type'] === 'many2one')
                    data = data && data[0];
                return data;
            }

            function _convert(field, data, tick) {
                tick = tick === undefined ? true : false;
                if (fields[field]['type'] === 'many2one') {
                    data = data && data[1];
                } else if ((fields[field]['type'] === 'selection') && (fields[field]['selection'] instanceof Array)) {
                    var d = {};
                    _.each(fields[field]['selection'], function(el) {
                        d[el[0]] = el[1];
                    });
                    data = d[data];
                }
                if (tick) {
                    if (ticks[data] === undefined)
                        ticks[data] = _.size(ticks);
                    return ticks[data];
                }
                return data || 0;
            }

            function _orientation(x, y) {
                if (! orientation)
                    return [x, y]
                return [y, x]
            }

            if (mode === "pie") {
                return obj.call("read_group", [domain, yaxis.concat([xaxis[0]]), [xaxis[0]]], {context: context}).pipe(function(res) {
                    _.each(res, function(record) {
                        result.push({
                            'data': [[_convert(xaxis[0], record[xaxis[0]]), record[yaxis[0]]]],
                            'label': _convert(xaxis[0], record[xaxis[0]], false)
                        });
                    });
                });
            } else if ((! stacked) || (xaxis.length < 2)) {
                var defs = [];
                _.each(xaxis, function(x) {
                    defs.push(obj.call("read_group", [domain, yaxis.concat([x]), [x]], {context: context}).pipe(function(res) {
                        return [x, res];
                    }));
                });
                return $.when.apply($, defs).pipe(function() {
                    _.each(_.toArray(arguments), function(res) {
                        var x = res[0];
                        res = res[1];
                        result.push({
                            'data': _.map(res, function(record) {
                                return _orientation(_convert(x, record[x]), record[yaxis[0]] || 0);
                            }),
                            'label': fields[x]['string']
                        });
                    });
                });
            } else {
                xaxis.reverse();
                return obj.call("read_group", [domain, yaxis.concat(xaxis.slice(0, 1)), xaxis.slice(0, 1)], {context: context}).pipe(function(axis) {
                    var defs = [];
                    _.each(axis, function(x) {
                        var key = x[xaxis[0]]
                        defs.push(obj.call("read_group", [domain+[(xaxis[0],'=',_convert_key(xaxis[0], key))], yaxis.concat(xaxis.slice(1, 2)), xaxis.slice(1, 2)],
                                {context: context}).pipe(function(res) {
                            return [x, key, res];
                        }));
                    });
                    return $.when.apply($, defs).pipe(function(res) {
                        var x = res[0];
                        var key = res[1];
                        res = res[2];
                        result.push({
                            'data': _.map(res, function(record) {
                                return _orientation(_convert(xaxis[1], record[xaxis[1]]), record[yaxis[0]] || 0);
                            }),
                            'label': _convert(xaxis[0], key, false)
                        })
                    });
                });
            }
        }).pipe(function() {
            var res = {
                'data': result,
                'ticks': _.map(ticks, function(el, key) { return [el, key] })
            };
            return res;
        });
    },

    // Render the graph and update menu styles
    graph_render: function (options) {
        options = options || {};
        _.extend(this, options.data);

        return this.graph_get_data()
            .then(this.proxy('graph_render_all'));
    },

    graph_render_all: function (data) {
        var i;
        if (this.mode=='area') {
            for (i=0; i<data.data.length; i++) {
                data.data[i].lines = {fill: true}
            }
        }
        if (this.graph) {
            this.graph.destroy();
        }

        // Render the graph
        this.$el.find(".graph_header_legend").children().remove();
        this.graph = this.make_graph(this.mode, this.container, data);

        // Update styles of menus

        this.$el.find("a").removeClass("active");

        var $active = this.$el.find('a[data-mode=' + this.mode + ']');
        if ($active.length > 1) {
            $active = $active.filter('[data-stacked=' + this.stacked + ']');
        }
        $active = $active.add(
            this.$el.find('a:not([data-mode])[data-legend=' + this.legend + ']'));

        $active.addClass('active');

        if (this.spreadsheet) {
            this.$el.find("#graph_show_data").addClass("active");
        }
        return this.graph;
    },

    // render the graph using the domain, context and group_by
    // calls the 'graph_data_get' python controller to process all data
    // TODO: check is group_by should better be in the context
    do_search: function(domain, context, group_by) {
        this.domain = domain;
        this.context = context;
        this.group_by = group_by;

        this.graph_render();
    },

    do_show: function() {
        this.do_push_state({});
        return this._super();
    },
});
};
<commit_msg>fixed problem with some other bar chart<commit_after>/*---------------------------------------------------------
 * OpenERP web_graph
 *---------------------------------------------------------*/

openerp.web_graph = function (instance) {

var _lt = instance.web._lt;

// removed ``undefined`` values
var filter_values = function (o) {
    var out = {};
    for (var k in o) {
        if (!o.hasOwnProperty(k) || o[k] === undefined) { continue; }
        out[k] = o[k];
    }
    return out;
};

instance.web.views.add('graph', 'instance.web_graph.GraphView');
instance.web_graph.GraphView = instance.web.View.extend({
    template: "GraphView",
    display_name: _lt('Graph'),
    view_type: "graph",

    init: function(parent, dataset, view_id, options) {
        var self = this;
        this._super(parent);
        this.set_default_options(options);
        this.dataset = dataset;
        this.view_id = view_id;

        this.mode = "bar";          // line, bar, area, pie, radar
        this.orientation = false;    // true: horizontal, false: vertical
        this.stacked = true;

        this.spreadsheet = false;   // Display data grid, allows copy to CSV
        this.forcehtml = false;
        this.legend = "top";        // top, inside, no

        this.domain = [];
        this.context = {};
        this.group_by = [];

        this.graph = null;
        this.on('view_loaded', self, self.load_graph);
    },
    destroy: function () {
        if (this.graph) {
            this.graph.destroy();
        }
        this._super();
    },

    load_graph: function(fields_view_get) {
        // TODO: move  to load_view and document
        var self = this;
        this.fields_view = fields_view_get;
        this.$el.addClass(this.fields_view.arch.attrs['class']);

        this.mode = this.fields_view.arch.attrs.type || 'bar';
        this.orientation = this.fields_view.arch.attrs.orientation == 'horizontal';

        var width = this.$el.parent().width();
        this.$el.css("width", width);
        this.container = this.$el.find("#editor-render-body").css({
            width: width,
            height: Math.min(500, width * 0.8)
        })[0];

        var graph_render = this.proxy('graph_render');
        this.$el.on('click', '.oe_graph_options a', function (evt) {
            var $el = $(evt.target);

            self.graph_render({data: filter_values({
                mode: $el.data('mode'),
                legend: $el.data('legend'),
                orientation: $el.data('orientation'),
                stacked: $el.data('stacked')
            })});
        });

        this.$el.find("#graph_show_data").click(function () {
            self.spreadsheet = ! self.spreadsheet;
            self.graph_render();
        });
        this.$el.find("#graph_switch").click(function () {
            if (self.mode != 'radar') {
                self.orientation = ! self.orientation;
            }
            self.graph_render();
        });

        this.$el.find("#graph_download").click(function () {
            if (self.legend == "top") { self.legend = "inside"; }
            self.forcehtml = true;

            self.graph_get_data().then(function (result) {
                self.graph_render_all(result).download.saveImage('png');
            }).always(function () {
                self.forcehtml = false;
            });
        });
        this.trigger('graph_view_loaded', fields_view_get);
    },

    get_format: function (options) {
        options = options || {};
        var legend = {
            show: this.legend != 'no',
        };

        switch (this.legend) {
        case 'top':
            legend.noColumns = 4;
            legend.container = this.$el.find("div.graph_header_legend")[0];
            break;
        case 'inside':
            legend.position = 'nw';
            legend.backgroundColor = '#D2E8FF';
            break;
        }

        return _.extend({
            legend: legend,
            mouse: {
                track: true,
                relative: true
            },
            spreadsheet : {
                show: this.spreadsheet,
                initialTab: "data"
            },
            HtmlText : (options.xaxis && options.xaxis.labelsAngle) ? false : !this.forcehtml,
        }, options);
    },

    make_graph: function (mode, container, data) {
        if (mode === 'area') { mode = 'line'; }
        return Flotr.draw(
            container, data.data,
            this.get_format(this['options_' + mode](data)));
    },

    options_bar: function (data) {
        var min = _(data.data).chain()
            .map(function (record) {
                if (record.data.length > 0){
	                return _.min(record.data, function (item) {
	                    return item[1];
	                })[1];
                }
            }).min().value();
        return {
            bars : {
                show : true,
                stacked : this.stacked,
                horizontal : this.orientation,
                barWidth : 0.7,
                lineWidth : 1
            },
            grid : {
                verticalLines : this.orientation,
                horizontalLines : !this.orientation,
                outline : "sw",
            },
            yaxis : {
                ticks: this.orientation ? data.ticks : false,
                min: !this.orientation ? (min < 0 ? min : 0) : null
            },
            xaxis : {
                labelsAngle: 45,
                ticks: this.orientation ? false : data.ticks,
                min: this.orientation ? (min < 0 ? min : 0) : null
            }
        };
    },

    options_pie: function (data) {
        return {
            pie : {
                show: true
            },
            grid : {
                verticalLines : false,
                horizontalLines : false,
                outline : "",
            },
            xaxis :  {showLabels: false},
            yaxis :  {showLabels: false},
        };
    },

    options_radar: function (data) {
        return {
            radar : {
                show : true,
                stacked : this.stacked
            },
            grid : {
                circular : true,
                minorHorizontalLines : true
            },
            xaxis : {
                ticks: data.ticks
            },
        };
    },

    options_line: function (data) {
        return {
            lines : {
                show : true,
                stacked : this.stacked
            },
            grid : {
                verticalLines : this.orientation,
                horizontalLines : !this.orientation,
                outline : "sw",
            },
            yaxis : {
                ticks: this.orientation ? data.ticks : false
            },
            xaxis : {
                labelsAngle: 45,
                ticks: this.orientation ? false : data.ticks
            }
        };
    },

    graph_get_data: function () {
        var model = this.dataset.model,
            domain = new instance.web.CompoundDomain(this.domain || []),
            context = new instance.web.CompoundContext(this.context || {}),
            group_by = this.group_by || [],
            view_id = this.view_id  || false,
            mode = this.mode || 'bar',
            orientation = this.orientation || false,
            stacked = this.stacked || false;

        var obj = new instance.web.Model(model);
        var view_get;
        var fields;
        var result = [];
        var ticks = {};

        return obj.call("fields_view_get", [view_id, 'graph']).pipe(function(tmp) {
            view_get = tmp;
            fields = view_get['fields'];
            var toload = _.select(group_by, function(x) { return fields[x] === undefined });
            if (toload.length >= 1)
                return obj.call("fields_get", [toload, context]);
            else
                return $.when([]);
        }).pipe(function (fields_to_add) {
            _.extend(fields, fields_to_add);

            var tree = $($.parseXML(view_get['arch']));

            var pos = 0;
            var xaxis = group_by || [];
            var yaxis = [];
            tree.find("field").each(function() {
                var field = $(this);
                if (! field.attr("name"))
                    return;
                if ((group_by.length == 0) && ((! pos) || field.attr('group'))) {
                    xaxis.push(field.attr('name'));
                }
                if (pos && ! field.attr('group')) {
                    yaxis.push(field.attr('name'));
                }
                pos += 1;
            });

            if (xaxis.length === 0)
                throw new Error("No field for the X axis!");
            if (yaxis.length === 0)
                throw new Error("No field for the Y axis!");

            // Convert a field's data into a displayable string

            function _convert_key(field, data) {
                if (fields[field]['type'] === 'many2one')
                    data = data && data[0];
                return data;
            }

            function _convert(field, data, tick) {
                tick = tick === undefined ? true : false;
                if (fields[field]['type'] === 'many2one') {
                    data = data && data[1];
                } else if ((fields[field]['type'] === 'selection') && (fields[field]['selection'] instanceof Array)) {
                    var d = {};
                    _.each(fields[field]['selection'], function(el) {
                        d[el[0]] = el[1];
                    });
                    data = d[data];
                }
                if (tick) {
                    if (ticks[data] === undefined)
                        ticks[data] = _.size(ticks);
                    return ticks[data];
                }
                return data || 0;
            }

            function _orientation(x, y) {
                if (! orientation)
                    return [x, y]
                return [y, x]
            }

            if (mode === "pie") {
                return obj.call("read_group", [domain, yaxis.concat([xaxis[0]]), [xaxis[0]]], {context: context}).pipe(function(res) {
                    _.each(res, function(record) {
                        result.push({
                            'data': [[_convert(xaxis[0], record[xaxis[0]]), record[yaxis[0]]]],
                            'label': _convert(xaxis[0], record[xaxis[0]], false)
                        });
                    });
                });
            } else if ((! stacked) || (xaxis.length < 2)) {
                var defs = [];
                _.each(xaxis, function(x) {
                    defs.push(obj.call("read_group", [domain, yaxis.concat([x]), [x]], {context: context}).pipe(function(res) {
                        return [x, res];
                    }));
                });
                return $.when.apply($, defs).pipe(function() {
                    _.each(_.toArray(arguments), function(res) {
                        var x = res[0];
                        res = res[1];
                        result.push({
                            'data': _.map(res, function(record) {
                                return _orientation(_convert(x, record[x]), record[yaxis[0]] || 0);
                            }),
                            'label': fields[x]['string']
                        });
                    });
                });
            } else {
                xaxis.reverse();
                return obj.call("read_group", [domain, yaxis.concat(xaxis.slice(0, 1)), xaxis.slice(0, 1)], {context: context}).pipe(function(axis) {
                    var defs = [];
                    _.each(axis, function(x) {
                        var key = x[xaxis[0]]
                        defs.push(obj.call("read_group", [new instance.web.CompoundDomain(domain, [[xaxis[0], '=' ,_convert_key(xaxis[0], key)]]),
                                yaxis.concat(xaxis.slice(1, 2)), xaxis.slice(1, 2)], {context: context}).pipe(function(res) {
                            return [x, key, res];
                        }));
                    });
                    return $.when.apply($, defs).pipe(function(res) {
                        var x = res[0];
                        var key = res[1];
                        res = res[2];
                        result.push({
                            'data': _.map(res, function(record) {
                                return _orientation(_convert(xaxis[1], record[xaxis[1]]), record[yaxis[0]] || 0);
                            }),
                            'label': _convert(xaxis[0], key, false)
                        })
                    });
                });
            }
        }).pipe(function() {
            var res = {
                'data': result,
                'ticks': _.map(ticks, function(el, key) { return [el, key] })
            };
            return res;
        });
    },

    // Render the graph and update menu styles
    graph_render: function (options) {
        options = options || {};
        _.extend(this, options.data);

        return this.graph_get_data()
            .then(this.proxy('graph_render_all'));
    },

    graph_render_all: function (data) {
        var i;
        if (this.mode=='area') {
            for (i=0; i<data.data.length; i++) {
                data.data[i].lines = {fill: true}
            }
        }
        if (this.graph) {
            this.graph.destroy();
        }

        // Render the graph
        this.$el.find(".graph_header_legend").children().remove();
        this.graph = this.make_graph(this.mode, this.container, data);

        // Update styles of menus

        this.$el.find("a").removeClass("active");

        var $active = this.$el.find('a[data-mode=' + this.mode + ']');
        if ($active.length > 1) {
            $active = $active.filter('[data-stacked=' + this.stacked + ']');
        }
        $active = $active.add(
            this.$el.find('a:not([data-mode])[data-legend=' + this.legend + ']'));

        $active.addClass('active');

        if (this.spreadsheet) {
            this.$el.find("#graph_show_data").addClass("active");
        }
        return this.graph;
    },

    // render the graph using the domain, context and group_by
    // calls the 'graph_data_get' python controller to process all data
    // TODO: check is group_by should better be in the context
    do_search: function(domain, context, group_by) {
        this.domain = domain;
        this.context = context;
        this.group_by = group_by;

        this.graph_render();
    },

    do_show: function() {
        this.do_push_state({});
        return this._super();
    },
});
};
<|endoftext|>


<commit_before>!function(a){var b="fu_popover",c=7,d={arrowShow:!0,autoHide:!1,autoHideDelay:2500,content:"",delay:{show:0,hide:0},dismissable:!1,placement:"bottom",themeName:"default",title:"",trigger:"click",width:"150px"},e=function(e,f){return this.element=a(e),this.popoverId=b+"_"+c++,this.options=a.extend({},d,f),this.options.autoHideDelay=void 0===this.options.autoHideDelay?0:this.options.autoHideDelay,this.options.delay.show=void 0===this.options.delay.show?0:this.options.delay.show,this.options.delay.hide=void 0===this.options.delay.hide?0:this.options.delay.hide,this.setStyles(),this.init(),this.initTriggers(),this};e.prototype.setStyles=function(){if("default"===this.options.themeName)if(a("#fu_popover_styles_default").length);else{var b=".fu_popover_"+this.options.themeName+" {position: absolute;background: #fff;border: 1px solid rgba(0, 0, 0, 0.2);border-radius: 6px;z-index: 1060;-webkit-background-clip: padding-box;background-clip: padding-box;border: 1px solid #cccccc;border: 1px solid rgba(0, 0, 0, 0.2);border-radius: 6px;-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);}";b+=".fu_popover_header_"+this.options.themeName+"{margin: 0;padding: 8px 14px;font-size: 14px;text-align: center;background-color: #f7f7f7;border-bottom: 1px solid #ebebeb;border-radius: 5px 5px 0 0;}.fu_popover_content_"+this.options.themeName+"{padding: 9px 14px;}",b+=".fu_popover_"+this.options.themeName+":after, .fu_popover_"+this.options.themeName+':before {border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none;}.fu_popover_'+this.options.themeName+":after {border-color: rgba(255, 255, 255, 0);border-width: 10px;}.fu_popover_"+this.options.themeName+":before {border-color: rgba(0, 0, 0, 0);border-width: 11px;}",b+=".arrow_top_"+this.options.themeName+":after{left: 50%;bottom: 100%;border-bottom-color: #fff;margin-left: -10px;}.arrow_top_"+this.options.themeName+":before{left: 50%;bottom: 100%;border-bottom-color: rgba(0, 0, 0, 0.2);margin-left: -11px;}",b+=".arrow_bottom_"+this.options.themeName+":after{left: 50%;top: 100%;border-top-color: #fff;margin-left: -10px;}.arrow_bottom_"+this.options.themeName+":before{left: 50%;top: 100%;border-top-color: rgba(0, 0, 0, 0.2);margin-left: -11px;}",b+=".arrow_left_"+this.options.themeName+":after{right: 100%;top: 50%;border-right-color: #fff;margin-top: -10px;}.arrow_left_"+this.options.themeName+":before{right: 100%;top: 50%;border-right-color: rgba(0, 0, 0, 0.2);margin-top: -11px;}",b+=".arrow_right_"+this.options.themeName+":after{left: 100%;top: 50%;border-left-color: #fff;margin-top: -10px;}.arrow_right_"+this.options.themeName+":before{left: 100%;top: 50%;border-left-color: rgba(0, 0, 0, 0.2);margin-top: -11px;}",a("").appendTo("head"),b=".fu_progress{overflow: hidden;height: 20px;margin-bottom: 10px;background-color: #f5f5f5;border-radius: 4px;-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);}",b+=".fu_progress_bar{float: left;width: 0%;height: 100%;font-size: 12px;line-height: 20px;color: #ffffff;text-align: center;background-color: #337ab7;-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-transition: width 0.6s ease;-o-transition: width 0.6s ease;transition: width 0.6s ease;}",a("").appendTo("head")}},e.prototype.init=function(){var a="";this.options.title.length>0&&(a='
'+this.options.title+"
");var c='
'+a+'
'+this.options.content+"

";this.options.dismissable===!0?this.initDismissableEvent():"",this.htmlStr=c},e.prototype.getArrowClass=function(){return"top"===this.options.placement?"arrow_bottom_"+this.options.themeName:"bottom"===this.options.placement?"arrow_top_"+this.options.themeName:"left"===this.options.placement?"arrow_right_"+this.options.themeName:"right"===this.options.placement?"arrow_left_"+this.options.themeName:""},e.prototype.initDismissableEvent=function(){var b=this.popoverId,c=this.options.delay.hide,d=this.element;a(document).mouseup(function(e){var f=a(d),g=a("#"+b);f.is(e.target)||0!==f.has(e.target).length||g.is(e.target)||0!==g.has(e.target).length||a("#"+b).hide(c)})},e.prototype.initTriggers=function(){var a=this.options.trigger.split(" ");a=jQuery.unique(a);for(var b=0;b<a.length;b++)"click"===a[b]?this.initClickTrigger():"hover"===a[b]?this.initHoverTrigger():"focus"===a[b]?this.initFocusTrigger():""},e.prototype.initClickTrigger=function(){var b=this.element;a("body").on("click","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.initHoverTrigger=function(){var b=this.element;a("body").on("mouseenter","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.initFocusTrigger=function(){var b=this.element;a("body").on("focus","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.display=function(b){var c=this.popoverId;if("show"===b){var d=this.options.delay.show,e=this.options.arrowShow;if(a("#"+c).length||a("body").append(this.htmlStr),setTimeout(function(){e||(a("#"+c).attr("class",""),a("#"+c).addClass("fu_popover_"+this.options.themeName)),a("#"+c).show()},d),this.setPopupPosition(),this.options.autoHide===!0){var f=this.options.autoHideDelay;f=0==f?2500:f,setTimeout(function(){a("#"+c).hide()},f)}}else"hide"===b?a("#"+c).hide(this.options.delay.hide):"destroy"===b&&(a("#"+c).remove(),a(this.element).removeData("fu_popover"),this.destroyTriggers())},e.prototype.getOffset=function(a){for(var b=navigator.userAgent.toLowerCase().indexOf("firefox")==-1,c=0,d=0;a;)c+=a.offsetLeft-a.scrollLeft+(b?a.clientLeft:0),d+=a.offsetTop-a.scrollTop+(b?a.clientTop:0),a=a.offsetParent;return{left:c+window.scrollX,top:d+window.scrollY}},e.prototype.setPopupPosition=function(){a("#"+this.popoverId).css({width:this.options.width});var j,k,b=this.getOffset(this.element[0]),d=(a("#"+this.popoverId).position(),a(this.element).outerWidth()),e=a(this.element).outerHeight(),f=b.left,g=b.top,h=a("#"+this.popoverId).outerWidth(),i=a("#"+this.popoverId).outerHeight();if("bottom"===this.options.placement||"top"===this.options.placement){var l=d/2,m=h/2;k="bottom"===this.options.placement?g+e+14:g-i-10;var n=f+l;j=n-m}else if("left"===this.options.placement||"right"===this.options.placement){var l=e/2,m=i/2;j="left"===this.options.placement?f-h-10:f+d+14;var o=g+l;k=o-m}a("#"+this.popoverId).css({left:j+"px",top:k+"px"})},e.prototype.destroyTriggers=function(){var b=this.options.trigger.split(" ");b=jQuery.unique(b);for(var c=0;c<b.length;c++)a("body").off("click","#"+this.element[0].id,function(){}),a("body").off("mouseenter","#"+this.element[0].id,function(){}),a("body").off("focus","#"+this.element[0].id,function(){})},a.fn.fu_popover=function(c){if("string"==typeof c){var d=a(this).data(b);if(jQuery.isEmptyObject(d))return this;d.display(c)}else if(!a.data(this,b)){var f=new e(this,c);return a("#"+f.element[0].id).data(b,f),a.data(this,b,f),this}}}(jQuery);
<commit_msg>offset calculaton bug for firefox fixed.<commit_after>!function(a){var b="fu_popover",c=7,d={arrowShow:!0,autoHide:!1,autoHideDelay:2500,content:"",delay:{show:0,hide:0},dismissable:!1,placement:"bottom",themeName:"default",title:"",trigger:"click",width:"150px"},e=function(e,f){return this.element=a(e),this.popoverId=b+"_"+c++,this.options=a.extend({},d,f),this.options.autoHideDelay=void 0===this.options.autoHideDelay?0:this.options.autoHideDelay,this.options.delay.show=void 0===this.options.delay.show?0:this.options.delay.show,this.options.delay.hide=void 0===this.options.delay.hide?0:this.options.delay.hide,this.setStyles(),this.init(),this.initTriggers(),this};e.prototype.setStyles=function(){if("default"===this.options.themeName)if(a("#fu_popover_styles_default").length);else{var b=".fu_popover_"+this.options.themeName+" {position: absolute;background: #fff;border: 1px solid rgba(0, 0, 0, 0.2);border-radius: 6px;z-index: 1060;-webkit-background-clip: padding-box;background-clip: padding-box;border: 1px solid #cccccc;border: 1px solid rgba(0, 0, 0, 0.2);border-radius: 6px;-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);}";b+=".fu_popover_header_"+this.options.themeName+"{margin: 0;padding: 8px 14px;font-size: 14px;text-align: center;background-color: #f7f7f7;border-bottom: 1px solid #ebebeb;border-radius: 5px 5px 0 0;}.fu_popover_content_"+this.options.themeName+"{padding: 9px 14px;}",b+=".fu_popover_"+this.options.themeName+":after, .fu_popover_"+this.options.themeName+':before {border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none;}.fu_popover_'+this.options.themeName+":after {border-color: rgba(255, 255, 255, 0);border-width: 10px;}.fu_popover_"+this.options.themeName+":before {border-color: rgba(0, 0, 0, 0);border-width: 11px;}",b+=".arrow_top_"+this.options.themeName+":after{left: 50%;bottom: 100%;border-bottom-color: #fff;margin-left: -10px;}.arrow_top_"+this.options.themeName+":before{left: 50%;bottom: 100%;border-bottom-color: rgba(0, 0, 0, 0.2);margin-left: -11px;}",b+=".arrow_bottom_"+this.options.themeName+":after{left: 50%;top: 100%;border-top-color: #fff;margin-left: -10px;}.arrow_bottom_"+this.options.themeName+":before{left: 50%;top: 100%;border-top-color: rgba(0, 0, 0, 0.2);margin-left: -11px;}",b+=".arrow_left_"+this.options.themeName+":after{right: 100%;top: 50%;border-right-color: #fff;margin-top: -10px;}.arrow_left_"+this.options.themeName+":before{right: 100%;top: 50%;border-right-color: rgba(0, 0, 0, 0.2);margin-top: -11px;}",b+=".arrow_right_"+this.options.themeName+":after{left: 100%;top: 50%;border-left-color: #fff;margin-top: -10px;}.arrow_right_"+this.options.themeName+":before{left: 100%;top: 50%;border-left-color: rgba(0, 0, 0, 0.2);margin-top: -11px;}",a("").appendTo("head"),b=".fu_progress{overflow: hidden;height: 20px;margin-bottom: 10px;background-color: #f5f5f5;border-radius: 4px;-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);}",b+=".fu_progress_bar{float: left;width: 0%;height: 100%;font-size: 12px;line-height: 20px;color: #ffffff;text-align: center;background-color: #337ab7;-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-transition: width 0.6s ease;-o-transition: width 0.6s ease;transition: width 0.6s ease;}",a("").appendTo("head")}},e.prototype.init=function(){var a="";this.options.title.length>0&&(a='
'+this.options.title+"
");var c='
'+a+'
'+this.options.content+"

";this.options.dismissable===!0?this.initDismissableEvent():"",this.htmlStr=c},e.prototype.getArrowClass=function(){return"top"===this.options.placement?"arrow_bottom_"+this.options.themeName:"bottom"===this.options.placement?"arrow_top_"+this.options.themeName:"left"===this.options.placement?"arrow_right_"+this.options.themeName:"right"===this.options.placement?"arrow_left_"+this.options.themeName:""},e.prototype.initDismissableEvent=function(){var b=this.popoverId,c=this.options.delay.hide,d=this.element;a(document).mouseup(function(e){var f=a(d),g=a("#"+b);f.is(e.target)||0!==f.has(e.target).length||g.is(e.target)||0!==g.has(e.target).length||a("#"+b).hide(c)})},e.prototype.initTriggers=function(){var a=this.options.trigger.split(" ");a=jQuery.unique(a);for(var b=0;b<a.length;b++)"click"===a[b]?this.initClickTrigger():"hover"===a[b]?this.initHoverTrigger():"focus"===a[b]?this.initFocusTrigger():""},e.prototype.initClickTrigger=function(){var b=this.element;a("body").on("click","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.initHoverTrigger=function(){var b=this.element;a("body").on("mouseenter","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.initFocusTrigger=function(){var b=this.element;a("body").on("focus","#"+this.element[0].id,function(){a(b).fu_popover("show")})},e.prototype.display=function(b){var c=this.popoverId;if("show"===b){var d=this.options.delay.show,e=this.options.arrowShow;if(a("#"+c).length||a("body").append(this.htmlStr),setTimeout(function(){e||(a("#"+c).attr("class",""),a("#"+c).addClass("fu_popover_"+this.options.themeName)),a("#"+c).show()},d),this.setPopupPosition(),this.options.autoHide===!0){var f=this.options.autoHideDelay;f=0==f?2500:f,setTimeout(function(){a("#"+c).hide()},f)}}else"hide"===b?a("#"+c).hide(this.options.delay.hide):"destroy"===b&&(a("#"+c).remove(),a(this.element).removeData("fu_popover"),this.destroyTriggers())},e.prototype.getOffsetSum=function(a){for(var b=0,c=0;a;)b+=parseInt(a.offsetTop),c+=parseInt(a.offsetLeft),a=a.offsetParent;return{top:b,left:c}},e.prototype.getOffsetRect=function(a){var b=a.getBoundingClientRect(),c=document.body,d=document.documentElement,e=window.pageYOffset||d.scrollTop||c.scrollTop,f=window.pageXOffset||d.scrollLeft||c.scrollLeft,g=d.clientTop||c.clientTop||0,h=d.clientLeft||c.clientLeft||0,i=b.top+e-g,j=b.left+f-h;return{top:Math.round(i),left:Math.round(j)}},e.prototype.getOffset=function(a){return a.getBoundingClientRect?this.getOffsetRect(a):this.getOffsetSum(a)},e.prototype.setPopupPosition=function(){a("#"+this.popoverId).css({width:this.options.width});var j,k,b=this.getOffset(this.element[0]),d=(a("#"+this.popoverId).position(),a(this.element).outerWidth()),e=a(this.element).outerHeight(),f=b.left,g=b.top,h=a("#"+this.popoverId).outerWidth(),i=a("#"+this.popoverId).outerHeight();if("bottom"===this.options.placement||"top"===this.options.placement){var l=d/2,m=h/2;k="bottom"===this.options.placement?g+e+14:g-i-10;var n=f+l;j=n-m}else if("left"===this.options.placement||"right"===this.options.placement){var l=e/2,m=i/2;j="left"===this.options.placement?f-h-10:f+d+14;var o=g+l;k=o-m}a("#"+this.popoverId).css({left:j+"px",top:k+"px"})},e.prototype.destroyTriggers=function(){var b=this.options.trigger.split(" ");b=jQuery.unique(b);for(var c=0;c<b.length;c++)a("body").off("click","#"+this.element[0].id,function(){}),a("body").off("mouseenter","#"+this.element[0].id,function(){}),a("body").off("focus","#"+this.element[0].id,function(){})},a.fn.fu_popover=function(c){if("string"==typeof c){var d=a(this).data(b);if(jQuery.isEmptyObject(d))return this;d.display(c)}else if(!a.data(this,b)){var f=new e(this,c);return a("#"+f.element[0].id).data(b,f),a.data(this,b,f),this}}}(jQuery);
<|endoftext|>


<commit_before>import Link from 'next/link'

const MediumPost = (props) => (

{props.snippet}

        {props.timestamp}
        {props.likes}

)

export default MediumPost<commit_msg>Fix medium post slider<commit_after>import Link from 'next/link'

const MediumPost = (props) => (

{props.snippet}

        {props.timestamp}
        {props.likes}

)

export default MediumPost<|endoftext|>


<commit_before>/**
 * @file Nashorn host adapter
 * @since 0.2.4
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfBootImplByHost*/ // Boot host specific implementation per host
/*global _gpfJavaHostImpl*/ // Common implementation for Java hosts
/*#endif*/

_gpfBootImplByHost[_GPF_HOST.NASHORN] = _gpfJavaHostImpl;
<commit_msg>Removes _gpfBootImplByHost<commit_after>/**
 * @file Nashorn host adapter
 * @since 0.2.4
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_HOST*/ // Host types
/*global _gpfHost*/ // Host type
/*global _gpfHostJava*/ // Common implementation for Java hosts
/*#endif*/

if (_GPF_HOST.NASHORN === _gpfHost) {

    _gpfHostJava();

}
<|endoftext|>