<commit_before>$(document).ready(function() {
    renderContainer(template_data);
    startHandlers();
    $('#summary').scrollToFixed();
});

function renderContainer(data) {
    dust.render('container', template_data,

    function(err, out) {
        if (err) {
            console.log(err);
        }
        $('.container').html(out);
    });
}

function resetButton() {
    $('#btn-reset').on('click', function(event) {
        for (var i = 0; i < template_data.slots.length; i++) {
            resetSlot(template_data.slots[i].id_prefix);
        }
        updatePrimaryStats();
        updateOffensiveDefensiveStats();
    });
};

function resetSlot(slotId) {
    $('#' + slotId + '-ql').val('10.0');
    $('#' + slotId + '-glyph-ql').val('10.0');
    $('#' + slotId + '-primary-glyph').val('none');
    $('#' + slotId + '-secondary-glyph').val('none');
    $('#' + slotId + '-primary-glyph-dist-btn0').trigger('click');
    $('#' + slotId + '-secondary-glyph-dist-btn0').trigger('click');
};

function addAllRoleListenerToButton(role) {
  $('#btn-all-'+role).on('click', function(event) {
        for (var i = 0; i < template_data.slots.length; i++) {
            setRole(template_data.slots[i].id_prefix, role);
        }
        updatePrimaryStats();
        updateOffensiveDefensiveStats();
    });
};

function setRole(slotId, role) {
    $('#'+slotId+'-role').val(role);
};

function startHandlers() {
    for (var i = 0; i < template_data.slots.length; i++) {
        var buttonHandler = new ButtonHandler(template_data.slots[i].id_prefix);
        buttonHandler.initiate();
        var selectHandler = new SelectHandler(template_data.slots[i].id_prefix);
        selectHandler.initiate();
    }
    resetButton();
    addAllRoleListenerToButton('dps');
    addAllRoleListenerToButton('healer');
    addAllRoleListenerToButton('tank');
}

function updatePrimaryStats() {
    sumHitPoints = 0;
    sumAttackRating = 0;
    sumHealRating = 0;
    for (var i = 0; i < template_data.slots.length; i++) {
        var role = $('#' + template_data.slots[i].id_prefix + '-role option:selected').attr('value');
        var ql = $('#' + template_data.slots[i].id_prefix + '-ql option:selected').attr('value');
        if (role == 'dps') {
            sumAttackRating += custom_gear_data[template_data.slots[i].group].heal_dps['ql' + (ql)].rating;
        } else if (role == 'healer') {
            sumHealRating += custom_gear_data[template_data.slots[i].group].heal_dps['ql' + (ql)].rating;
        } else if (role == 'tank') {
            sumHitPoints += custom_gear_data[template_data.slots[i].group].tank['ql' + (ql)].hitpoints;
        }
    }
    $('#stat-hitpoints').text(sumHitPoints);
    $('#stat-attack-rating').text(sumAttackRating);
    $('#stat-heal-rating').text(sumHealRating);
}

function updateOffensiveDefensiveStats() {
    sums = {
        'critical-rating': 0,
        'critical-power': 0,
        'penetration-rating': 0,
        'hit-rating': 0,
        'block-rating': 0,
        'defense-rating': 0,
        'evade-rating': 0,
        'physical-protection': 0,
        'magical-protection': 0
    };
    for (var i = 0; i < template_data.slots.length; i++) {
        var glyphQl = $('#' + template_data.slots[i].id_prefix + '-glyph-ql option:selected').attr('value');
        var primaryGlyph = $('#' + template_data.slots[i].id_prefix + '-primary-glyph option:selected').attr('value');
        var secondaryGlyph = $('#' + template_data.slots[i].id_prefix + '-secondary-glyph option:selected').attr('value');

        if (primaryGlyph != "none" || secondaryGlyph != "none") {
            var primaryDist = $('#' + template_data.slots[i].id_prefix + '-primary-glyph-dist > button.btn.active')[0].innerHTML;
            var secondaryDist = $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-dist > button.btn.active')[0].innerHTML;

            if (primaryDist != null || secondaryDist != null) {
                var primaryValue = 0;
                var secondaryValue = 0;
                if (primaryGlyph != "none") {
                    primaryValue = glyph_data.stat[primaryGlyph].ql[glyphQl].slot[template_data.slots[i].group].dist[primaryDist];
                    sums[primaryGlyph] += primaryValue;
                    $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('+' + primaryValue);
                } else {
                    $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('0');
                }
                if (secondaryGlyph != "none") {
                    secondaryValue = glyph_data.stat[secondaryGlyph].ql[glyphQl].slot[template_data.slots[i].group].dist[secondaryDist];
                    sums[secondaryGlyph] += secondaryValue;
                    $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('+' + secondaryValue);
                } else {
                    $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('0');
                }

            }
        } else {
            $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('0');
            $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('0');
        }
    }
    console.log(sums);
    for (var stat in sums) {
        if (sums.hasOwnProperty(stat)) {
            if (sums[stat] > 0) {
                $('#stat-' + stat).html('+' + sums[stat]);
            } else {
                $('#stat-' + stat).html("0");
            }
        }
    }
};

function SelectHandler(slotId) {
    var slotId = slotId;
    var self = this;

    this.initiate = function() {
        self.addListenersToRoleSelect(slotId);
        self.addListenersToQlSelect(slotId, '');
        self.addListenersToGlyphSelect(slotId, 'glyph-ql');
        self.addListenersToGlyphSelect(slotId, 'primary-glyph');
        self.addListenersToGlyphSelect(slotId, 'secondary-glyph');
    };

    this.addListenersToRoleSelect = function(id_prefix) {
        $('#' + id_prefix + '-role').change(function() {
            updatePrimaryStats();
        });
    };

    this.addListenersToQlSelect = function(id_prefix, id_suffix) {
        $('#' + id_prefix + id_suffix + '-ql').change(function() {
            updatePrimaryStats();
        });
    };

    this.addListenersToGlyphSelect = function(id_prefix, id_suffix) {
        $('#' + id_prefix + '-' + id_suffix).change(function() {
            updateOffensiveDefensiveStats();
        });
    };
}

function ButtonHandler(slotId) {
    var slotId = slotId;
    var self = this;

    this.initiate = function() {
        this.addListenersToGlyphDistButtons(slotId, 'primary-glyph');
        this.addListenersToGlyphDistButtons(slotId, 'secondary-glyph');
    };

    this.addListenersToGlyphDistButtons = function(id_prefix, glyph) {
        self.onlyActiveButton('#' + slotId + '-primary-glyph-dist-btn0');
        self.onlyActiveButton('#' + slotId + '-secondary-glyph-dist-btn0');
        buttons = $('#' + id_prefix + '-' + glyph + '-dist > button.btn').on('click', function(event) {
            self.onlyActiveButton('#' + this.id);
            self.balanceGlyphDist(this, glyph);
            updateOffensiveDefensiveStats();
        });
    };

    this.balanceGlyphDist = function(button, glyph) {
        otherActiveButton = $('#' + slotId + '-' + self.getInverseGlyphStat(glyph) + '-dist > button.btn.active');
        self.balanceGlyphDistOverflow(button, otherActiveButton[0]);
    }

    this.balanceGlyphDistOverflow = function(clickedButton, otherButton) {
        if (otherButton != null) {
            clickedDist = parseInt(clickedButton.innerHTML);
            otherDist = parseInt(otherButton.innerHTML);
            sumBothDist = clickedDist + otherDist;
            if ((sumBothDist) > 4) {
                otherDistLoweredByOne = otherButton.id.substring(0, otherButton.id.length - 1) + (otherDist - (sumBothDist - 4));
                self.onlyActiveButton('#' + otherDistLoweredByOne);
            }
        }
    }

    this.onlyActiveButton = function(id) {
        $(id).siblings().removeClass('active');
        $(id).siblings().removeClass('btn-success');
        $(id).addClass('active');
        $(id).addClass('btn-success');
    };

    this.getInverseGlyphStat = function(glyph) {
        return glyph == 'primary-glyph' ? 'secondary-glyph' : 'primary-glyph';
    }
}<commit_msg>Fixed bug resetting, now also resets role<commit_after>$(document).ready(function() {
    renderContainer(template_data);
    startHandlers();
    $('#summary').scrollToFixed();
});

function renderContainer(data) {
    dust.render('container', template_data,

    function(err, out) {
        if (err) {
            console.log(err);
        }
        $('.container').html(out);
    });
}

function resetButton() {
    $('#btn-reset').on('click', function(event) {
        for (var i = 0; i < template_data.slots.length; i++) {
            resetSlot(template_data.slots[i].id_prefix);
        }
        updatePrimaryStats();
        updateOffensiveDefensiveStats();
    });
};

function resetSlot(slotId) {
    $('#' + slotId + '-ql').val('10.0');
    $('#' + slotId + '-role').val('none');
    $('#' + slotId + '-glyph-ql').val('10.0');
    $('#' + slotId + '-primary-glyph').val('none');
    $('#' + slotId + '-secondary-glyph').val('none');
    $('#' + slotId + '-primary-glyph-dist-btn0').trigger('click');
    $('#' + slotId + '-secondary-glyph-dist-btn0').trigger('click');
};

function addAllRoleListenerToButton(role) {
  $('#btn-all-'+role).on('click', function(event) {
        for (var i = 0; i < template_data.slots.length; i++) {
            setRole(template_data.slots[i].id_prefix, role);
        }
        updatePrimaryStats();
        updateOffensiveDefensiveStats();
    });
};

function setRole(slotId, role) {
    $('#'+slotId+'-role').val(role);
};

function startHandlers() {
    for (var i = 0; i < template_data.slots.length; i++) {
        var buttonHandler = new ButtonHandler(template_data.slots[i].id_prefix);
        buttonHandler.initiate();
        var selectHandler = new SelectHandler(template_data.slots[i].id_prefix);
        selectHandler.initiate();
    }
    resetButton();
    addAllRoleListenerToButton('dps');
    addAllRoleListenerToButton('healer');
    addAllRoleListenerToButton('tank');
}

function updatePrimaryStats() {
    sumHitPoints = 0;
    sumAttackRating = 0;
    sumHealRating = 0;
    for (var i = 0; i < template_data.slots.length; i++) {
        var role = $('#' + template_data.slots[i].id_prefix + '-role option:selected').attr('value');
        var ql = $('#' + template_data.slots[i].id_prefix + '-ql option:selected').attr('value');
        if (role == 'dps') {
            sumAttackRating += custom_gear_data[template_data.slots[i].group].heal_dps['ql' + (ql)].rating;
        } else if (role == 'healer') {
            sumHealRating += custom_gear_data[template_data.slots[i].group].heal_dps['ql' + (ql)].rating;
        } else if (role == 'tank') {
            sumHitPoints += custom_gear_data[template_data.slots[i].group].tank['ql' + (ql)].hitpoints;
        }
    }
    $('#stat-hitpoints').text(sumHitPoints);
    $('#stat-attack-rating').text(sumAttackRating);
    $('#stat-heal-rating').text(sumHealRating);
}

function updateOffensiveDefensiveStats() {
    sums = {
        'critical-rating': 0,
        'critical-power': 0,
        'penetration-rating': 0,
        'hit-rating': 0,
        'block-rating': 0,
        'defense-rating': 0,
        'evade-rating': 0,
        'physical-protection': 0,
        'magical-protection': 0
    };
    for (var i = 0; i < template_data.slots.length; i++) {
        var glyphQl = $('#' + template_data.slots[i].id_prefix + '-glyph-ql option:selected').attr('value');
        var primaryGlyph = $('#' + template_data.slots[i].id_prefix + '-primary-glyph option:selected').attr('value');
        var secondaryGlyph = $('#' + template_data.slots[i].id_prefix + '-secondary-glyph option:selected').attr('value');

        if (primaryGlyph != "none" || secondaryGlyph != "none") {
            var primaryDist = $('#' + template_data.slots[i].id_prefix + '-primary-glyph-dist > button.btn.active')[0].innerHTML;
            var secondaryDist = $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-dist > button.btn.active')[0].innerHTML;

            if (primaryDist != null || secondaryDist != null) {
                var primaryValue = 0;
                var secondaryValue = 0;
                if (primaryGlyph != "none") {
                    primaryValue = glyph_data.stat[primaryGlyph].ql[glyphQl].slot[template_data.slots[i].group].dist[primaryDist];
                    sums[primaryGlyph] += primaryValue;
                    $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('+' + primaryValue);
                } else {
                    $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('0');
                }
                if (secondaryGlyph != "none") {
                    secondaryValue = glyph_data.stat[secondaryGlyph].ql[glyphQl].slot[template_data.slots[i].group].dist[secondaryDist];
                    sums[secondaryGlyph] += secondaryValue;
                    $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('+' + secondaryValue);
                } else {
                    $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('0');
                }

            }
        } else {
            $('#' + template_data.slots[i].id_prefix + '-primary-glyph-value').html('0');
            $('#' + template_data.slots[i].id_prefix + '-secondary-glyph-value').html('0');
        }
    }
    console.log(sums);
    for (var stat in sums) {
        if (sums.hasOwnProperty(stat)) {
            if (sums[stat] > 0) {
                $('#stat-' + stat).html('+' + sums[stat]);
            } else {
                $('#stat-' + stat).html("0");
            }
        }
    }
};

function SelectHandler(slotId) {
    var slotId = slotId;
    var self = this;

    this.initiate = function() {
        self.addListenersToRoleSelect(slotId);
        self.addListenersToQlSelect(slotId, '');
        self.addListenersToGlyphSelect(slotId, 'glyph-ql');
        self.addListenersToGlyphSelect(slotId, 'primary-glyph');
        self.addListenersToGlyphSelect(slotId, 'secondary-glyph');
    };

    this.addListenersToRoleSelect = function(id_prefix) {
        $('#' + id_prefix + '-role').change(function() {
            updatePrimaryStats();
        });
    };

    this.addListenersToQlSelect = function(id_prefix, id_suffix) {
        $('#' + id_prefix + id_suffix + '-ql').change(function() {
            updatePrimaryStats();
        });
    };

    this.addListenersToGlyphSelect = function(id_prefix, id_suffix) {
        $('#' + id_prefix + '-' + id_suffix).change(function() {
            updateOffensiveDefensiveStats();
        });
    };
}

function ButtonHandler(slotId) {
    var slotId = slotId;
    var self = this;

    this.initiate = function() {
        this.addListenersToGlyphDistButtons(slotId, 'primary-glyph');
        this.addListenersToGlyphDistButtons(slotId, 'secondary-glyph');
    };

    this.addListenersToGlyphDistButtons = function(id_prefix, glyph) {
        self.onlyActiveButton('#' + slotId + '-primary-glyph-dist-btn0');
        self.onlyActiveButton('#' + slotId + '-secondary-glyph-dist-btn0');
        buttons = $('#' + id_prefix + '-' + glyph + '-dist > button.btn').on('click', function(event) {
            self.onlyActiveButton('#' + this.id);
            self.balanceGlyphDist(this, glyph);
            updateOffensiveDefensiveStats();
        });
    };

    this.balanceGlyphDist = function(button, glyph) {
        otherActiveButton = $('#' + slotId + '-' + self.getInverseGlyphStat(glyph) + '-dist > button.btn.active');
        self.balanceGlyphDistOverflow(button, otherActiveButton[0]);
    }

    this.balanceGlyphDistOverflow = function(clickedButton, otherButton) {
        if (otherButton != null) {
            clickedDist = parseInt(clickedButton.innerHTML);
            otherDist = parseInt(otherButton.innerHTML);
            sumBothDist = clickedDist + otherDist;
            if ((sumBothDist) > 4) {
                otherDistLoweredByOne = otherButton.id.substring(0, otherButton.id.length - 1) + (otherDist - (sumBothDist - 4));
                self.onlyActiveButton('#' + otherDistLoweredByOne);
            }
        }
    }

    this.onlyActiveButton = function(id) {
        $(id).siblings().removeClass('active');
        $(id).siblings().removeClass('btn-success');
        $(id).addClass('active');
        $(id).addClass('btn-success');
    };

    this.getInverseGlyphStat = function(glyph) {
        return glyph == 'primary-glyph' ? 'secondary-glyph' : 'primary-glyph';
    }
}<|endoftext|>


<commit_before>var forms = [];
var updatedForms = [];

function setFormUpdated(formIdx, fieldName) {
    return function () {
        if (!updatedForms[formIdx].includes(fieldName))
            updatedForms[formIdx].push(fieldName);
    }
}

function confirmNotSavingChanges(formIdx) {
    return function (e) {
        var updatedFields = [];
        for (var i = 0, formsLen = updatedForms.length; i < formsLen; i++) {
            var formUpdated = (updatedForms[i].length > 0);
            if (formUpdated && i != formIdx)
                updatedFields = updatedFields.concat(updatedForms[i]);
        }
        if (updatedFields.length > 0) {
            if (!confirm('You have not yet saved your changes to ' +
                updatedFields.join(', ') +
                '. You will lose them if you proceed with the current action. Do you wish to proceed?')) {
                e.preventDefault();
                e.stopPropagation();
                return false;
            } else
                return true;
        }
        return true;
    }
}

function setWarningOnNavigate() {
    forms = document.getElementsByTagName("form");
    for (var i = 0, formsLen = forms.length; i < formsLen; i++) {
        var form = forms[i];
        updatedForms[i] = [];
        var fields = form.querySelectorAll('input[type="text"],textarea');
        for (var j = 0, fieldsLen = fields.length; j < fieldsLen; j++) {
            var field = fields[j];
            field.addEventListener('input', setFormUpdated(i, field.name));
        }
        form.addEventListener('submit', confirmNotSavingChanges(i));
    }
    links = document.getElementsByTagName("a");
    for (var i = 0, formsLen = forms.length; i < formsLen; i++) {
        var link = links[i];
        link.addEventListener('click', confirmNotSavingChanges(-1));
    }
}
<commit_msg>minify js file<commit_after>var forms=[],updatedForms=[];function setFormUpdated(e,t){return function(){updatedForms[e].includes(t)||updatedForms[e].push(t)}}function confirmNotSavingChanges(r){return function(e){for(var t=[],n=0,o=updatedForms.length;n<o;n++){0<updatedForms[n].length&&n!=r&&(t=t.concat(updatedForms[n]))}return!(0<t.length)||(!!confirm("You have not yet saved your changes to "+t.join(", ")+". You will lose them if you proceed with the current action. Do you wish to proceed?")||(e.preventDefault(),e.stopPropagation(),!1))}}function setWarningOnNavigate(){for(var e=0,t=(forms=document.getElementsByTagName("form")).length;e<t;e++){var n=forms[e];updatedForms[e]=[];for(var o=n.querySelectorAll('input[type="text"],textarea'),r=0,a=o.length;r<a;r++){var s=o[r];s.addEventListener("input",setFormUpdated(e,s.name))}n.addEventListener("submit",confirmNotSavingChanges(e))}links=document.getElementsByTagName("a");for(e=0,t=forms.length;e<t;e++){links[e].addEventListener("click",confirmNotSavingChanges(-1))}}<|endoftext|>


<commit_before>/**
 * Created by ksinger on 19.02.2016.
 */

import  won from '../won-es6.js';
import { actionTypes, actionCreators, getConnectionRelatedData } from './actions.js';

import Immutable from 'immutable';

import {
    clone,
    jsonld2simpleFormat,
    getIn,
} from '../utils.js';

import {
    fetchDataForOwnedNeeds
} from '../won-message-utils.js';

import {
    makeParams,
    resetParams,
} from '../configRouting.js';

export function successfulCloseNeed(event) {
    return (dispatch, getState) => {
        console.log("got response for DEACTIVATE: " + event.getMessageType());
        //TODO maybe refactor these response message handling
        if (getState().getIn(['messages', 'waitingForAnswer', event.getIsRemoteResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            //dispatch(actionCreators.connections__denied(event));
        }
    }
}
export function failedCloseNeed(event) {
    return (dispatch, getState) => {
        const needUri = event.getReceiverNeed();
        /*
        * TODO not sure if it's necessary to invalidate
        * the cache here as the previous action will just have
        * been an optimistic update of the state. Invalidation
        * should happen in the action that causes the interaction
        * with the server.
        */
        won.invalidateCacheForNeed(needUri) // mark need and it's connection container dirty
            .then(() =>
                won.getConnectionUrisOfNeed(needUri)
            ).then(connectionUris =>
                Promise.all(
                    connectionUris.map(cnctUri =>
                        won.invalidateCacheForNewMessage(cnctUri, needUri) // mark connections dirty
                    )
                )
            ).then(() =>
                // as the need and it's connections have been marked dirty
                // they will be reloaded on this action.
                fetchDataForOwnedNeeds([needUri])
                //fetchAllAccessibleAndRelevantData([needUri])
            ).then(allThatData =>
                dispatch({
                    type: actionTypes.messages.closeNeed.failed,
                    payload: allThatData
                })
            );
    }
}

        /*
         hasReceiverNeed: "https://192.168.124.53:8443/won/resource/need/1741189480636743700"
         hasSenderNeed: "https://192.168.124.53:8443/won/resource/need/1741189480636743700"
         has....Connection
         event.uri

         won.WONMSG.hasReceiverNeed = won.WONMSG.baseUri + "hasReceiverNeed";
         won.WONMSG.hasReceiverNeedCompacted = won.WONMSG.prefix + ":hasReceiverNeed";
         won.WONMSG.hasReceiver = won.WONMSG.baseUri + "hasReceiver"; // connection if connection event
         won.WONMSG.hasReceiverCompacted = won.WONMSG.prefix + ":hasReceiver";
         won.WONMSG.hasReceiverNode = won.WONMSG.baseUri + "hasReceiverNode";
         won.WONMSG.hasReceiverNodeCompacted = won.WONMSG.prefix + ":hasReceiverNode";
         won.WONMSG.hasSenderNeed = won.WONMSG.baseUri + "hasSenderNeed";
         won.WONMSG.hasSenderNeedCompacted = won.WONMSG.prefix + ":hasSenderNeed";
         won.WONMSG.hasSender = won.WONMSG.baseUri + "hasSender";
         won.WONMSG.hasSenderCompacted = won.WONMSG.prefix + ":hasSender";
         won.WONMSG.hasSenderNode = won.WONMSG.baseUri + "hasSenderNode";
         won.WONMSG.hasSenderNodeCompacted = won.WONMSG.prefix + ":hasSenderNode";
         */

export function successfulCloseConnection(event) {
    return (dispatch, getState) => {
        const state = getState();
        console.log("got response for CLOSE: " + event.getMessageType());
        let eventUri = null;
        let receiverUri = null;
        let isRemoteResponse = false;
        //TODO maybe refactor these response message handling
        if (state.getIn(['messages', 'waitingForAnswer', event.getIsResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            eventUri = event.getIsResponseTo();
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            });
        } else if (state.getIn(['messages', 'waitingForAnswer', event.getIsRemoteResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            eventUri = event.getIsRemoteResponseTo();
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            });
        } else {
            //when a connection is closed by the node (e.g. when you close/deactivate a need all its corresponding connections will be closed)
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            })
        }
    }
}

//TODO move redirect elsewhere (e.g. to click-handler) then remove
export function successfulOpen(event){
    return (dispatch, getState) => {
        const state = getState();
        dispatch({
            type: actionTypes.messages.open.successOwn,
            payload: {
                event,
            }
        });

        dispatch(actionCreators.router__stateGoAbs("post", {
            postUri: event.getReceiverNeed(),
            connectionType: won.WON.Connected,
            connectionUri: event.getReceiver(),
        }));
    }
}

export function successfulCreate(event) {
    return (dispatch) => {
        //const state = getState();
        console.log("got response for CREATE: " + event.getMessageType());
        //TODO: if negative, use alternative need URI and send again
        //fetch need data and store in local RDF store
        //get URI of newly created need from message

        //load the data into the local rdf store and publish NeedCreatedEvent when done
        var needURI = event.getReceiverNeed();

        won.getNeed(needURI)
            .then((need) => {
                console.log("Dispatching action " + won.EVENT.NEED_CREATED);
                dispatch(actionCreators.needs__createSuccessful({
                    publishEventUri: event.getIsResponseTo(),
                    needUri: event.getSenderNeed(),
                    need: need,
                }));
            });
    }
}

export function openMessageReceived(event) {
    return dispatch => {
        won.invalidateCacheForNewMessage(event.getReceiver())
        .then(() =>
                getConnectionData(event))
        .then(data => {
                dispatch({
                    type: actionTypes.messages.openMessageReceived,
                    payload: data
                })
            }
        )
    }
}

export function connectMessageReceived(event) {
    return (dispatch, getState) => {

        const ownConnectionUri = event.getReceiver();
        const ownNeedUri = event.getReceiverNeed();
        const theirNeedUri = event.getSenderNeed();

        const state = getState();
        let connectionP;
        if(state.getIn(['connections', ownConnectionUri])) {
            // already in state. invalidate the version in the rdf-store.
            connectionP = Promise.resolve(state.getIn(['connections', ownConnectionUri]))
            won.invalidateCacheForNewConnection(ownConnectionUri, ownNeedUri);
        } else {
            // need to fetch
            connectionP = won
                .getConnectionWithEventUris(ownConnectionUri, { requesterWebId: ownNeedUri })
                .then(cnct => Immutable.fromJS(cnct));
        }

        Promise.all([
            connectionP,
            won.getNeed(theirNeedUri),
            won.getNeed(ownNeedUri), //uses ownNeed (but does not need connections uris to be loaded) in connectMessageReceived
        ])
        .then(([connection, theirNeed, ownNeed]) => {
            dispatch({
                type: actionTypes.messages.connectMessageReceived,
                payload: {
                    updatedConnection: ownConnectionUri,
                    connection: connection.set('hasConnectionState', won.WON.RequestReceived),
                    ownNeedUri: ownNeedUri,
                    ownNeed: ownNeed,
                    remoteNeed: theirNeed,
                    receivedEvent: event.getMessageUri(), // the more relevant event. used for unread-counter.
                    message: event,
                }
            });
        });

    }
}

/**
 * @deprecated due to the reason given in the TODO.
 * TODO this function indirectly fetches the entire
 * connection again! It should be enough to just
 * use the two events we get in most cases and make
 * the reducers correspondingly smarter.
 * @param eventOnRemote
 * @param eventOnOwn
 * @return {*}
 */
function getConnectionData(event) {
    return won
        .getConnectionWithOwnAndRemoteNeed(event.getReceiverNeed(),event.getSenderNeed())
        .then(connectionData =>
            getConnectionRelatedData(
                event.getReceiverNeed(),
                event.getSenderNeed(),
                connectionData.uri
            )
            .then(data => {
                if(data.events.filter(e => e.uri === event.getMessageUri()).length === 0) {
                    //
                    /*
                     * if data.events doesn't contain the arguments-events,
                     * add them. they might not be contained in the events-list
                     * due to a race condition, i.e. if data hasn't been
                     * stored on the node when the query resolves.
                     */
                    const eventOnOwn_ = clone(event.getFramedMessageResourceForState());
                    eventOnOwn_.hasCorrespondingRemoteMessage = clone(event.getFramedRemoteMessageResourceForState());
                    data.events.push( eventOnOwn_ );
                }

                data.receivedEvent = event.getMessageUri();
                data.updatedConnection = connectionData.uri;
                data.message = event;

                return data

            })
        )
}

export function needMessageReceived(event) {
    return (dispatch, getState) => {
        //first check if we really have the 'own' need in the state - otherwise we'll ignore the hint
        const need = getState().getIn(['needs', event.getReceiverNeed()]);
        if (!need) {
            console.log("ignoring needMessage for a need that is not ours:", event.getReceiverNeed());
        }
        dispatch({
            type: actionTypes.messages.needMessageReceived,
            payload: {
                needUri: event.getReceiverNeed(),
                needTitle: need.get("title"),
                message: event.getTextMessage(),
            }
        });
    }

}

export function hintMessageReceived(event) {
    return (dispatch, getState) => {

        //first check if we really have the 'own' need in the state - otherwise we'll ignore the hint
        if (!getState().getIn(['needs', event.getReceiverNeed()])) {
            console.log("ignoring hint for a need that is not ours:", event.getReceiverNeed());
        }

        //event.eventType = won.messageType2EventType[event.hasMessageType]; TODO needed?
        won.invalidateCacheForNewConnection(event.getReceiver(), event.getReceiverNeed())
            .then(() => {
                let needUri = event.getReceiverNeed();
                let match = {}
                //TODO: why do add the matchscore and counterpart when we don't use the event?

                event.matchScore = event.getMatchScore();
                event.matchCounterpartURI = event.getMatchCounterpart();

                console.log('going to crawl connection related data');//deletme

                getConnectionRelatedData(needUri, event.getMatchCounterpart(), event.getReceiver())
                .then(data => {
                        data.receivedEvent = event.getMessageUri();
                        data.updatedConnection = event.getReceiver();
                        dispatch({
                            type: actionTypes.messages.hintMessageReceived,
                            payload: data
                        });
                    }
                );

                // /add some properties to the eventData so as to make them easily accessible to consumers
                //of the hint event
                // below is commented as it seems to cause to hint event data loaded/displayed
                //if (eventData.matchCounterpartURI != null) {
                //    //load the data of the need the hint is about, if required
                //    //linkedDataService.ensureLoaded(eventData.uri);
                //    linkedDataService.ensureLoaded(eventData.matchCounterpartURI);
                //}

                console.log("handling hint message")
            });
    }
}

<commit_msg>Avoid hint for inactive needs Check the state of the need before sending hint. issue #1271 (cherry picked from commit e394948)<commit_after>/**
 * Created by ksinger on 19.02.2016.
 */

import  won from '../won-es6.js';
import { actionTypes, actionCreators, getConnectionRelatedData } from './actions.js';

import Immutable from 'immutable';

import {
    clone,
    jsonld2simpleFormat,
    getIn,
} from '../utils.js';

import {
    fetchDataForOwnedNeeds
} from '../won-message-utils.js';

import {
    makeParams,
    resetParams,
} from '../configRouting.js';

export function successfulCloseNeed(event) {
    return (dispatch, getState) => {
        console.log("got response for DEACTIVATE: " + event.getMessageType());
        //TODO maybe refactor these response message handling
        if (getState().getIn(['messages', 'waitingForAnswer', event.getIsRemoteResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            //dispatch(actionCreators.connections__denied(event));
        }
    }
}
export function failedCloseNeed(event) {
    return (dispatch, getState) => {
        const needUri = event.getReceiverNeed();
        /*
        * TODO not sure if it's necessary to invalidate
        * the cache here as the previous action will just have
        * been an optimistic update of the state. Invalidation
        * should happen in the action that causes the interaction
        * with the server.
        */
        won.invalidateCacheForNeed(needUri) // mark need and it's connection container dirty
            .then(() =>
                won.getConnectionUrisOfNeed(needUri)
            ).then(connectionUris =>
                Promise.all(
                    connectionUris.map(cnctUri =>
                        won.invalidateCacheForNewMessage(cnctUri, needUri) // mark connections dirty
                    )
                )
            ).then(() =>
                // as the need and it's connections have been marked dirty
                // they will be reloaded on this action.
                fetchDataForOwnedNeeds([needUri])
                //fetchAllAccessibleAndRelevantData([needUri])
            ).then(allThatData =>
                dispatch({
                    type: actionTypes.messages.closeNeed.failed,
                    payload: allThatData
                })
            );
    }
}

        /*
         hasReceiverNeed: "https://192.168.124.53:8443/won/resource/need/1741189480636743700"
         hasSenderNeed: "https://192.168.124.53:8443/won/resource/need/1741189480636743700"
         has....Connection
         event.uri

         won.WONMSG.hasReceiverNeed = won.WONMSG.baseUri + "hasReceiverNeed";
         won.WONMSG.hasReceiverNeedCompacted = won.WONMSG.prefix + ":hasReceiverNeed";
         won.WONMSG.hasReceiver = won.WONMSG.baseUri + "hasReceiver"; // connection if connection event
         won.WONMSG.hasReceiverCompacted = won.WONMSG.prefix + ":hasReceiver";
         won.WONMSG.hasReceiverNode = won.WONMSG.baseUri + "hasReceiverNode";
         won.WONMSG.hasReceiverNodeCompacted = won.WONMSG.prefix + ":hasReceiverNode";
         won.WONMSG.hasSenderNeed = won.WONMSG.baseUri + "hasSenderNeed";
         won.WONMSG.hasSenderNeedCompacted = won.WONMSG.prefix + ":hasSenderNeed";
         won.WONMSG.hasSender = won.WONMSG.baseUri + "hasSender";
         won.WONMSG.hasSenderCompacted = won.WONMSG.prefix + ":hasSender";
         won.WONMSG.hasSenderNode = won.WONMSG.baseUri + "hasSenderNode";
         won.WONMSG.hasSenderNodeCompacted = won.WONMSG.prefix + ":hasSenderNode";
         */

export function successfulCloseConnection(event) {
    return (dispatch, getState) => {
        const state = getState();
        console.log("got response for CLOSE: " + event.getMessageType());
        let eventUri = null;
        let receiverUri = null;
        let isRemoteResponse = false;
        //TODO maybe refactor these response message handling
        if (state.getIn(['messages', 'waitingForAnswer', event.getIsResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            eventUri = event.getIsResponseTo();
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            });
        } else if (state.getIn(['messages', 'waitingForAnswer', event.getIsRemoteResponseTo()])) {
            console.log("messages waitingForAnswer", event.getMessageUri());
            eventUri = event.getIsRemoteResponseTo();
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            });
        } else {
            //when a connection is closed by the node (e.g. when you close/deactivate a need all its corresponding connections will be closed)
            dispatch({
                type: actionTypes.messages.close.success,
                payload: event
            })
        }
    }
}

//TODO move redirect elsewhere (e.g. to click-handler) then remove
export function successfulOpen(event){
    return (dispatch, getState) => {
        const state = getState();
        dispatch({
            type: actionTypes.messages.open.successOwn,
            payload: {
                event,
            }
        });

        dispatch(actionCreators.router__stateGoAbs("post", {
            postUri: event.getReceiverNeed(),
            connectionType: won.WON.Connected,
            connectionUri: event.getReceiver(),
        }));
    }
}

export function successfulCreate(event) {
    return (dispatch) => {
        //const state = getState();
        console.log("got response for CREATE: " + event.getMessageType());
        //TODO: if negative, use alternative need URI and send again
        //fetch need data and store in local RDF store
        //get URI of newly created need from message

        //load the data into the local rdf store and publish NeedCreatedEvent when done
        var needURI = event.getReceiverNeed();

        won.getNeed(needURI)
            .then((need) => {
                console.log("Dispatching action " + won.EVENT.NEED_CREATED);
                dispatch(actionCreators.needs__createSuccessful({
                    publishEventUri: event.getIsResponseTo(),
                    needUri: event.getSenderNeed(),
                    need: need,
                }));
            });
    }
}

export function openMessageReceived(event) {
    return dispatch => {
        won.invalidateCacheForNewMessage(event.getReceiver())
        .then(() =>
                getConnectionData(event))
        .then(data => {
                dispatch({
                    type: actionTypes.messages.openMessageReceived,
                    payload: data
                })
            }
        )
    }
}

export function connectMessageReceived(event) {
    return (dispatch, getState) => {

        const ownConnectionUri = event.getReceiver();
        const ownNeedUri = event.getReceiverNeed();
        const theirNeedUri = event.getSenderNeed();

        const state = getState();
        let connectionP;
        if(state.getIn(['connections', ownConnectionUri])) {
            // already in state. invalidate the version in the rdf-store.
            connectionP = Promise.resolve(state.getIn(['connections', ownConnectionUri]))
            won.invalidateCacheForNewConnection(ownConnectionUri, ownNeedUri);
        } else {
            // need to fetch
            connectionP = won
                .getConnectionWithEventUris(ownConnectionUri, { requesterWebId: ownNeedUri })
                .then(cnct => Immutable.fromJS(cnct));
        }

        Promise.all([
            connectionP,
            won.getNeed(theirNeedUri),
            won.getNeed(ownNeedUri), //uses ownNeed (but does not need connections uris to be loaded) in connectMessageReceived
        ])
        .then(([connection, theirNeed, ownNeed]) => {
            dispatch({
                type: actionTypes.messages.connectMessageReceived,
                payload: {
                    updatedConnection: ownConnectionUri,
                    connection: connection.set('hasConnectionState', won.WON.RequestReceived),
                    ownNeedUri: ownNeedUri,
                    ownNeed: ownNeed,
                    remoteNeed: theirNeed,
                    receivedEvent: event.getMessageUri(), // the more relevant event. used for unread-counter.
                    message: event,
                }
            });
        });

    }
}

/**
 * @deprecated due to the reason given in the TODO.
 * TODO this function indirectly fetches the entire
 * connection again! It should be enough to just
 * use the two events we get in most cases and make
 * the reducers correspondingly smarter.
 * @param eventOnRemote
 * @param eventOnOwn
 * @return {*}
 */
function getConnectionData(event) {
    return won
        .getConnectionWithOwnAndRemoteNeed(event.getReceiverNeed(),event.getSenderNeed())
        .then(connectionData =>
            getConnectionRelatedData(
                event.getReceiverNeed(),
                event.getSenderNeed(),
                connectionData.uri
            )
            .then(data => {
                if(data.events.filter(e => e.uri === event.getMessageUri()).length === 0) {
                    //
                    /*
                     * if data.events doesn't contain the arguments-events,
                     * add them. they might not be contained in the events-list
                     * due to a race condition, i.e. if data hasn't been
                     * stored on the node when the query resolves.
                     */
                    const eventOnOwn_ = clone(event.getFramedMessageResourceForState());
                    eventOnOwn_.hasCorrespondingRemoteMessage = clone(event.getFramedRemoteMessageResourceForState());
                    data.events.push( eventOnOwn_ );
                }

                data.receivedEvent = event.getMessageUri();
                data.updatedConnection = connectionData.uri;
                data.message = event;

                return data

            })
        )
}

export function needMessageReceived(event) {
    return (dispatch, getState) => {
        //first check if we really have the 'own' need in the state - otherwise we'll ignore the hint
        const need = getState().getIn(['needs', event.getReceiverNeed()]);
        if (!need) {
            console.log("ignoring needMessage for a need that is not ours:", event.getReceiverNeed());
        }
        dispatch({
            type: actionTypes.messages.needMessageReceived,
            payload: {
                needUri: event.getReceiverNeed(),
                needTitle: need.get("title"),
                message: event.getTextMessage(),
            }
        });
    }

}

export function hintMessageReceived(event) {
    return (dispatch, getState) => {

        //first check if we really have the 'own' need in the state - otherwise we'll ignore the hint
        if (!getState().getIn(['needs', event.getReceiverNeed()])) {
            console.log("ignoring hint for a need that is not ours:", event.getReceiverNeed());
        } else {
            //check the state of the need and ignore hint if it is inactive
            const needState = getState().getIn(['needs', event.getReceiverNeed(), 'state']);
            if (needState == won.WON.ActiveCompacted) {
                //event.eventType = won.messageType2EventType[event.hasMessageType]; TODO needed?
                won.invalidateCacheForNewConnection(event.getReceiver(), event.getReceiverNeed())
                    .then(() => {
                        let needUri = event.getReceiverNeed();
                        let match = {}
                        //TODO: why do add the matchscore and counterpart when we don't use the event?

                        event.matchScore = event.getMatchScore();
                        event.matchCounterpartURI = event.getMatchCounterpart();

                        console.log('going to crawl connection related data');//deletme

                        getConnectionRelatedData(needUri, event.getMatchCounterpart(), event.getReceiver())
                            .then(data => {
                                    data.receivedEvent = event.getMessageUri();
                                    data.updatedConnection = event.getReceiver();
                                    dispatch({
                                        type: actionTypes.messages.hintMessageReceived,
                                        payload: data
                                    });
                                }
                            );

                        // /add some properties to the eventData so as to make them easily accessible to consumers
                        //of the hint event
                        // below is commented as it seems to cause to hint event data loaded/displayed
                        //if (eventData.matchCounterpartURI != null) {
                        //    //load the data of the need the hint is about, if required
                        //    //linkedDataService.ensureLoaded(eventData.uri);
                        //    linkedDataService.ensureLoaded(eventData.matchCounterpartURI);
                        //}

                        console.log("handling hint message")
                    });
            } else {
                console.log("ignoring hint for a  closed need:", event.getReceiverNeed());
            }
        }
    }
}

<|endoftext|>


<commit_before>/**
 * BlogService to handle blog posts
 *
 * @module BlogService
 */

/**
 * Find Blog posts for the current site and if set of the page.
 *
 * @param {string} host - The current host on the current request to get the site config
 * @param {string} page - The page identifier the blog post is saved on
 * @param {BlockDBCallback} callback - The callback that handles the database response.
 *
 * @alias module:BlogService.find
 * @alias module:BlogService.findAll
 */
var find = function (host, page, callback) {
  MultisiteService.getCurrentSiteConfig(host, function (err, config) {
    if(err) return callback(err, null, {code: 500, error: err}, config);
    var query = {
      where: {
        site: config.name
      }
    };
    if(page !== null && UtilityService.isDefined(page)) query.where.page = page;
    Blog.find(query).exec(function found(err, found) {
      if (err) return callback("Internal Server Error", {code: 500, error: err}, found, config);
      if (UtilityService.isUndefined(found) || !UtilityService.isArray(found)) return callback("Not Found", {code: 404}, found, config);
      return callback(null, found, {code: 200}, config);
    });
  });
}

/**
 * Find one blog post for the current site and with id
 *
 * @param {string} host - The current host on the current request to get the site config
 * @param {number} id - The id of the blog post to find
 * @param {BlockDBCallback} callback - The callback that handles the database response.
 *
 * @alias module:BlogService.findOne
 */
var findOne = function (host, id, callback) {
  MultisiteService.getCurrentSiteConfig(host, function (err, config) {
    if(err) return callback(err, null, {code: 500, error: err});
    var query = {
      where: {
        site: config.name
      }
    };
    if(id !== null && UtilityService.isUndefined(id)) query.where.id = id;
    Blog.findOne(query).exec(function (err, result) {
      if (err) return callback("Internal Server Error", result, {code: 500, error: err}, config);
      if (UtilityService.isUndefined(result)) return callback("Not Found", result, {code: 404}, config);
      return callback(null, result, {code: 200}, config);
    });
  });
}

/**
 * The Callback that handle the find results of blog posts
 * @callback {(number|string)} BlockDBCallback
 * @param {?string} err - Error message string, if no error err is null
 * @param {object|array} result - The Database result, can be an array of results or one result
 * @param {object} status - The request state, contains the HTTP-Statuscode as code
 * @param {object} config - The current site config
 */

/**
 * Find an attachment in post with post-id and attachmentUploadedAs string
 * @param {string} host - The current host on the current request to get the site config
 * @param {number} id - The id of the blog post to find the attachment in
 * @param {string} attachmentUploadedAs - The uploadedAs string of the attachment to find
 * @param {BlockFindAttachmentCallback} callback - The callback that handles the result.
 *
 * @alias module:BlogService.findAttachmentInPost
 */
var findAttachmentInPost = function (host, id, attachmentUploadedAs, callback) {
  var found = false;
  findOne(host, id, function (err, result, status, config) {
    sails.log.debug("[BlogService.findAttachmentInPost]", err, status, result);
    if(err || status.code !== 200 || !UtilityService.isArray(result.attachments)) return callback(err, status, found);
    for (var i = 0; i < result.attachments.length && !found; i++) {
      if(result.attachments[i].uploadedAs === attachmentUploadedAs) {
        found = true;
        return callback(null, i, result.attachments[i], status, config);
      }
    };
    return callback(null, -1, null, status, config);
  });
}

/**
 * The Callback to handles the result of found (or not found) attachment
 * @callback BlockFindAttachmentCallback
 * @param {?string} err - Error message string, if no error err is null
 * @param {(object|object[])} index - The index of the attachment, if no attachment was found, index is -1
 * @param {object} status - Statuscode of the findOne result
 * @param {object} config - The current site config
 */

/**
 * public functions
 */
module.exports = {
  find: find,
  findAll: find, // alias
  findOne: findOne,
  findAttachmentInPost: findAttachmentInPost,
}<commit_msg>sort blog posts by create date<commit_after>/**
 * BlogService to handle blog posts
 *
 * @module BlogService
 */

/**
 * Find Blog posts for the current site and if set of the page.
 *
 * @param {string} host - The current host on the current request to get the site config
 * @param {string} page - The page identifier the blog post is saved on
 * @param {BlockDBCallback} callback - The callback that handles the database response.
 *
 * @alias module:BlogService.find
 * @alias module:BlogService.findAll
 */
var find = function (host, page, callback) {
  MultisiteService.getCurrentSiteConfig(host, function (err, config) {
    if(err) return callback(err, null, {code: 500, error: err}, config);
    var query = {
      where: {
        site: config.name
      },
      sort: 'createdAt DESC'
    };
    if(page !== null && UtilityService.isDefined(page)) query.where.page = page;
    Blog.find(query).exec(function found(err, found) {
      if (err) return callback("Internal Server Error", {code: 500, error: err}, found, config);
      if (UtilityService.isUndefined(found) || !UtilityService.isArray(found)) return callback("Not Found", {code: 404}, found, config);
      return callback(null, found, {code: 200}, config);
    });
  });
}

/**
 * Find one blog post for the current site and with id
 *
 * @param {string} host - The current host on the current request to get the site config
 * @param {number} id - The id of the blog post to find
 * @param {BlockDBCallback} callback - The callback that handles the database response.
 *
 * @alias module:BlogService.findOne
 */
var findOne = function (host, id, callback) {
  MultisiteService.getCurrentSiteConfig(host, function (err, config) {
    if(err) return callback(err, null, {code: 500, error: err});
    var query = {
      where: {
        site: config.name
      }
    };
    if(id !== null && UtilityService.isUndefined(id)) query.where.id = id;
    Blog.findOne(query).exec(function (err, result) {
      if (err) return callback("Internal Server Error", result, {code: 500, error: err}, config);
      if (UtilityService.isUndefined(result)) return callback("Not Found", result, {code: 404}, config);
      return callback(null, result, {code: 200}, config);
    });
  });
}

/**
 * The Callback that handle the find results of blog posts
 * @callback {(number|string)} BlockDBCallback
 * @param {?string} err - Error message string, if no error err is null
 * @param {object|array} result - The Database result, can be an array of results or one result
 * @param {object} status - The request state, contains the HTTP-Statuscode as code
 * @param {object} config - The current site config
 */

/**
 * Find an attachment in post with post-id and attachmentUploadedAs string
 * @param {string} host - The current host on the current request to get the site config
 * @param {number} id - The id of the blog post to find the attachment in
 * @param {string} attachmentUploadedAs - The uploadedAs string of the attachment to find
 * @param {BlockFindAttachmentCallback} callback - The callback that handles the result.
 *
 * @alias module:BlogService.findAttachmentInPost
 */
var findAttachmentInPost = function (host, id, attachmentUploadedAs, callback) {
  var found = false;
  findOne(host, id, function (err, result, status, config) {
    sails.log.debug("[BlogService.findAttachmentInPost]", err, status, result);
    if(err || status.code !== 200 || !UtilityService.isArray(result.attachments)) return callback(err, status, found);
    for (var i = 0; i < result.attachments.length && !found; i++) {
      if(result.attachments[i].uploadedAs === attachmentUploadedAs) {
        found = true;
        return callback(null, i, result.attachments[i], status, config);
      }
    };
    return callback(null, -1, null, status, config);
  });
}

/**
 * The Callback to handles the result of found (or not found) attachment
 * @callback BlockFindAttachmentCallback
 * @param {?string} err - Error message string, if no error err is null
 * @param {(object|object[])} index - The index of the attachment, if no attachment was found, index is -1
 * @param {object} status - Statuscode of the findOne result
 * @param {object} config - The current site config
 */

/**
 * public functions
 */
module.exports = {
  find: find,
  findAll: find, // alias
  findOne: findOne,
  findAttachmentInPost: findAttachmentInPost,
}<|endoftext|>


<commit_before>module.exports = {
  extends: ['anvilabs'],
  plugins: ['typescript'],
  parser: 'typescript-eslint-parser',
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.js', '.ts', '.json'],
      },
    },
    'import/extensions': ['.js', '.ts'],
  },
  rules: {
    'no-undef': 'off', // conflicts with typescript
    'no-unused-vars': 'off', // conflicts with typescript
    'no-useless-constructor': 'off', // conflicts with typescript
    'spaced-comment': [
      'error',
      'always',
      {
        line: {
          exceptions: ['-', '+'],
          markers: ['=', '!', '/'], // space here to support sprockets directives
        },
        block: {
          exceptions: ['-', '+'],
          markers: ['=', '!'], // space here to support sprockets directives
          balanced: true,
        },
      },
    ],
    strict: 'off', // conflicts with typescript
    // https://github.com/benmosher/eslint-plugin-import
    'import/extensions': [
      'error',
      'always',
      {
        js: 'never',
        ts: 'never',
      },
    ],
    'import/no-named-as-default-member': 'off', // conflicts with typescript
    'import/no-named-as-default': 'off', // conflicts with typescript
    // https://github.com/not-an-aardvark/eslint-plugin-prettier
    'prettier/prettier': [
      'error',
      {
        useTabs: false,
        printWidth: 80,
        tabWidth: 2,
        singleQuote: true,
        trailingComma: 'all',
        bracketSpacing: false,
        jsxBracketSameLine: false,
        parser: 'typescript',
        semi: true,
      },
    ],
    // https://github.com/nzakas/eslint-plugin-typescript
    'typescript/adjacent-overload-signatures': 'error',
    'typescript/class-name-casing': 'error',
    'typescript/explicit-member-accessibility': 'error',
    'typescript/interface-name-prefix': 'error',
    'typescript/member-delimiter-style': 'off',
    'typescript/member-ordering': 'error',
    'typescript/no-angle-bracket-type-assertion': 'error',
    'typescript/no-empty-interface': 'error',
    'typescript/no-explicit-any': 'error',
    'typescript/no-namespace': ['error', {allowDefinitionFiles: true}],
    'typescript/no-parameter-properties': 'off',
    'typescript/no-triple-slash-reference': 'error',
    'typescript/no-type-alias': 'off',
    'typescript/no-unused-vars': 'error',
    'typescript/no-use-before-define': [
      'error',
      {functions: true, classes: true, variables: true},
    ],
    'typescript/prefer-namespace-keyword': 'error',
    'typescript/type-annotation-spacing': 'off',
  },
};
<commit_msg>fix(typescript): stop automatically extending the base config<commit_after>module.exports = {
  plugins: ['typescript'],
  parser: 'typescript-eslint-parser',
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.js', '.ts', '.json'],
      },
    },
    'import/extensions': ['.js', '.ts'],
  },
  rules: {
    'no-undef': 'off', // conflicts with typescript
    'no-unused-vars': 'off', // conflicts with typescript
    'no-useless-constructor': 'off', // conflicts with typescript
    'spaced-comment': [
      'error',
      'always',
      {
        line: {
          exceptions: ['-', '+'],
          markers: ['=', '!', '/'], // space here to support sprockets directives
        },
        block: {
          exceptions: ['-', '+'],
          markers: ['=', '!'], // space here to support sprockets directives
          balanced: true,
        },
      },
    ],
    strict: 'off', // conflicts with typescript
    // https://github.com/benmosher/eslint-plugin-import
    'import/extensions': [
      'error',
      'always',
      {
        js: 'never',
        ts: 'never',
      },
    ],
    'import/no-named-as-default-member': 'off', // conflicts with typescript
    'import/no-named-as-default': 'off', // conflicts with typescript
    // https://github.com/not-an-aardvark/eslint-plugin-prettier
    'prettier/prettier': [
      'error',
      {
        useTabs: false,
        printWidth: 80,
        tabWidth: 2,
        singleQuote: true,
        trailingComma: 'all',
        bracketSpacing: false,
        jsxBracketSameLine: false,
        parser: 'typescript',
        semi: true,
      },
    ],
    // https://github.com/nzakas/eslint-plugin-typescript
    'typescript/adjacent-overload-signatures': 'error',
    'typescript/class-name-casing': 'error',
    'typescript/explicit-member-accessibility': 'error',
    'typescript/interface-name-prefix': 'error',
    'typescript/member-delimiter-style': 'off',
    'typescript/member-ordering': 'error',
    'typescript/no-angle-bracket-type-assertion': 'error',
    'typescript/no-empty-interface': 'error',
    'typescript/no-explicit-any': 'error',
    'typescript/no-namespace': ['error', {allowDefinitionFiles: true}],
    'typescript/no-parameter-properties': 'off',
    'typescript/no-triple-slash-reference': 'error',
    'typescript/no-type-alias': 'off',
    'typescript/no-unused-vars': 'error',
    'typescript/no-use-before-define': [
      'error',
      {functions: true, classes: true, variables: true},
    ],
    'typescript/prefer-namespace-keyword': 'error',
    'typescript/type-annotation-spacing': 'off',
  },
};
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.controller:TasksCtrl
 * @description
 * # TasksCtrl
 * Controller of the Pear2Pear
 */
angular.module('Pear2Pear')
  .constant("Modernizr", Modernizr)
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/communities/:community_id/tasks', {
        templateUrl: 'views/tasks/index.html',
        controller: 'TasksCtrl'
      }).
      when('/communities/:community_id/tasks/new', {
        templateUrl: 'views/tasks/new.html',
        controller: 'TasksCtrl'
      }).
      when('/tasks/:id', {
        templateUrl: 'views/tasks/edit.html',
        controller:'TasksCtrl'
      });
  }])
  .controller('TasksCtrl', ['$scope', '$location', '$routeParams', 'Modernizr', '$filter', function($scope, $location, $routeParams, Modernizr, $filter){

    $scope.tasks =
      [
        {
          id: "1",
          name: "Task1",
          description: "Description1",
          completed: true,
          assignees: [
            {
              name: "Antonio"
            },
            {
              name: "Pablo"
            },
            {
              name: "Samer"
            },
            {
              name: "Juan"
            },
          ]
        },
        {
          id:"2",
          name: "Task2",
          completed: false,
          description: "Description2",
          assignees: [
          ]
        }
      ];

    $scope.toggleCompleted = function(task){
      task.completed = !task.completed;
    };

   //TODO backend

    $scope.task =  {
      id: "1",
      name: "Task1",
      description: "Description1",
      community_id: 1,
      completed: true,
      assignees: [
        {
          name: "Antonio"
        },
        {
          name: "Pablo"
        },
        {
          name: "Samer"
        },
        {
          name: "Juan"
        }
      ],
      deadlineDate : new Date(),
      reminders: [
        {
          id: "reminder1",
          date : new Date() //.parse("November 1, 2014 10:15 AM")
        },
        {
          id: "reminder2",
          date : new Date()//.parse("November 12, 2014 11:15 PM")
        }
      ]
    };

    var communityId = function() {
      return $routeParams.community_id || $scope.task && $scope.task.community_id;
    };

    var getCommunity = function() {
      //TODO backend
      if (communityId()) {
        return {
          id: $routeParams.community_id,
          name: "UCM P2Pvalue",
          users: [
            {
              name: "Antonio"
            },
            {
              name: "Pablo"
            },
            {
              name: "Samer"
            },
            {
              name: "Juan"
            },
            {
              name: "Jorge"
            },
            {
              name: "Laura"
            }
          ]
        };
      }
    };

    $scope.reminders = $scope.task.reminders;

    if ($scope.reminders[0]) {
      $scope.reminders[0].date.setFullYear(2014);
      $scope.reminders[0].date.setMonth(9);
      $scope.reminders[0].date.setDate(8);
      $scope.reminders[0].date.setHours(9);
      $scope.reminders[0].date.setMinutes(30);
      $scope.reminders[0].date.setSeconds(0);
      $scope.reminders[0].date.setMilliseconds(0);
      //this array has the reminders as retrieved from server so when they changes the reminder of the phone can be updated.

      var oldReminders = {};
      for (var i = 0; i < $scope.reminders.length; i += 1){
        oldReminders[$scope.reminders[i].id]= new Date();
        oldReminders[$scope.reminders[i].id].setTime($scope.reminders[i].date.getTime());
      }
    }

    $scope.isApp = function(){
      return window.location.search.search("cordova") > 0;
    };

    //TODO call this function on save form
    $scope.save = function(){
      // TODO save other stuff
      // saving reminders in phone
      for(var i = 0; i < $scope.reminders.length; i += 1){
        var r = $scope.reminders[i];
        if (r.date.getTime() !== oldReminders[r.id].getTime()){
          var oldDate = new Date();
          oldDate.setTime(oldReminders[r.id].getTime());
          //FIXME delete event not working
          $scope.deleteReminder(oldDate, $scope.getTask().name);
          $scope.addReminder(r.date, $scope.getTask().name);
        }
      }
      // TODO save also reminders
      $scope.index();
    };

    $scope.addReminder = function(date, title){
      var dateWnd = new window.Date();
      dateWnd.setTime(date.getTime());
  	var success = function(message) {
  	};
  	var error = function(message) {
  	  alert('Error: ' + JSON.stringify(message));
  	};

  	var calOptions = window.plugins.calendar.getCalendarOptions(); // grab the defaults
  	calOptions.firstReminderMinutes = 0;
      var comment = 'pear2pear reminder';
  	window.plugins.calendar.createEventWithOptions(title , "", comment,
                                                     dateWnd, dateWnd, calOptions, success, error);

    };

    $scope.deleteReminder = function(date, title){
      var success = function(message) {
      };
  	var error = function(message) {
  	  alert("Error: " + message);
  	};
  	var dateWnd = new window.Date();
      dateWnd.setTime(date.getTime());
  	window.plugins.calendar.deleteEvent(title, null, null, dateWnd, dateWnd,
  				                        success, error);

    };

    $scope.getReminders = function(taskId, userId){
      return $scope.reminders;
    };

    $scope.community = getCommunity();

    $scope.index = function() {
      $location.path('communities/' + communityId()  + '/tasks');
    };

    $scope.new = function(){
      $location.path('communities/' + communityId() + '/tasks/new');
    };

    $scope.edit = function(task){
      $location.path('tasks/' + task.id);
    };

    $scope.community_index = function() {
      $location.path('communities');
    };

    $scope.assigSelect = {
      assignees: $scope.community.users
    };

    $scope.supportsDateInput = Modernizr.inputtypes.date;
    $scope.supportsTimeInput = Modernizr.inputtypes.time;

    $scope.openDate = function($event) {
      $event.preventDefault();
      $event.stopPropagation();

      $scope.opened = true;
    };

    $scope.dateOptions = {};

  }])

  .directive(
    'dateInput',
        function(dateFilter) {
          return {
            require: 'ngModel',
            template: '<input type="date"></input>',
            replace: true,
            link: function(scope, elm, attrs, ngModelCtrl) {
              ngModelCtrl.$formatters.unshift(function (modelValue) {
                return dateFilter(modelValue, 'yyyy-MM-dd');
              });

              ngModelCtrl.$parsers.unshift(function(viewValue) {
                var newDate = ngModelCtrl.$modelValue;
                newDate.setDate(viewValue.getDate());
                newDate.setMonth(viewValue.getMonth());
                newDate.setYear(viewValue.getYear());
                return new Date(viewValue);
              });
            }
          };
        })
  .directive(
    'timeInput',
    function(dateFilter) {
      return {
        require: 'ngModel',
        template: '<input type="time"></input>',
        replace: true,
        link: function(scope, elm, attrs, ngModelCtrl) {
          ngModelCtrl.$formatters.unshift(function (modelValue) {
            return dateFilter(modelValue, 'HH:mm');
          });

          ngModelCtrl.$parsers.unshift(function(viewValue) {
            var newDate = ngModelCtrl.$modelValue;
            var newTime = new Date().parse(viewValue);
            newDate.setHours(newTime.getHours());
            newDate.setMinutes(newTime.getMinutes());
            newDate.setSeconds(0);
            return newDate;
          });
        }
      };
    })

 .config(function(uiSelectConfig) {
    uiSelectConfig.theme = 'select2';
  });
<commit_msg>add empty reminder at the end and fix date time native pickers bug<commit_after>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.controller:TasksCtrl
 * @description
 * # TasksCtrl
 * Controller of the Pear2Pear
 */
angular.module('Pear2Pear')
  .constant("Modernizr", Modernizr)
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/communities/:community_id/tasks', {
        templateUrl: 'views/tasks/index.html',
        controller: 'TasksCtrl'
      }).
      when('/communities/:community_id/tasks/new', {
        templateUrl: 'views/tasks/new.html',
        controller: 'TasksCtrl'
      }).
      when('/tasks/:id', {
        templateUrl: 'views/tasks/edit.html',
        controller:'TasksCtrl'
      });
  }])
  .controller('TasksCtrl', ['$scope', '$location', '$routeParams', 'Modernizr', '$filter', function($scope, $location, $routeParams, Modernizr, $filter){

    $scope.tasks =
      [
        {
          id: "1",
          name: "Task1",
          description: "Description1",
          completed: true,
          assignees: [
            {
              name: "Antonio"
            },
            {
              name: "Pablo"
            },
            {
              name: "Samer"
            },
            {
              name: "Juan"
            },
          ]
        },
        {
          id:"2",
          name: "Task2",
          completed: false,
          description: "Description2",
          assignees: [
          ]
        }
      ];

    $scope.toggleCompleted = function(task){
      task.completed = !task.completed;
    };

   //TODO backend

    $scope.task =  {
      id: "1",
      name: "Task1",
      description: "Description1",
      community_id: 1,
      completed: true,
      assignees: [
        {
          name: "Antonio"
        },
        {
          name: "Pablo"
        },
        {
          name: "Samer"
        },
        {
          name: "Juan"
        }
      ],
      deadlineDate : new Date(),
      reminders: [
        {
          id: "reminder1",
          date : new Date() //.parse("November 1, 2014 10:15 AM")
        },
        {
          id: "reminder2",
          date : new Date()//.parse("November 12, 2014 11:15 PM")
        }
      ]
    };

    var communityId = function() {
      return $routeParams.community_id || $scope.task && $scope.task.community_id;
    };

    var getCommunity = function() {
      //TODO backend
      if (communityId()) {
        return {
          id: $routeParams.community_id,
          name: "UCM P2Pvalue",
          users: [
            {
              name: "Antonio"
            },
            {
              name: "Pablo"
            },
            {
              name: "Samer"
            },
            {
              name: "Juan"
            },
            {
              name: "Jorge"
            },
            {
              name: "Laura"
            }
          ]
        };
      }
    };

    $scope.reminders = $scope.task.reminders;
    $scope.$watch('reminders', function () {
      var i = $scope.reminders.length - 1;
      if ($scope.reminders[i].date)
        $scope.reminders.push({id: 'newId' + i, date : null});
    },true);

    //TODO erase empty
    if ($scope.reminders[0]) {
      $scope.reminders[0].date.setFullYear(2014);
      $scope.reminders[0].date.setMonth(9);
      $scope.reminders[0].date.setDate(8);
      $scope.reminders[0].date.setHours(9);
      $scope.reminders[0].date.setMinutes(30);
      $scope.reminders[0].date.setSeconds(0);
      $scope.reminders[0].date.setMilliseconds(0);
      //this array has the reminders as retrieved from server so when they changes the reminder of the phone can be updated.

      var oldReminders = {};
      for (var i = 0; i < $scope.reminders.length; i += 1){
        if ($scope.reminders[i].date){
          oldReminders[$scope.reminders[i].id]= new Date();
          oldReminders[$scope.reminders[i].id].setTime($scope.reminders[i].date.getTime());
        }
      }
    }

    $scope.isApp = function(){
      return window.location.search.search("cordova") > 0;
    };

    //TODO call this function on save form
    $scope.save = function(){
      // TODO save other stuff
      // saving reminders in phone
      for(var i = 0; i < $scope.reminders.length; i += 1){
        var r = $scope.reminders[i];
        if (r.date.getTime() !== oldReminders[r.id].getTime()){
          var oldDate = new Date();
          oldDate.setTime(oldReminders[r.id].getTime());
          //FIXME delete event not working
          $scope.deleteReminder(oldDate, $scope.getTask().name);
          $scope.addReminder(r.date, $scope.getTask().name);
        }
      }
      // TODO save also reminders
      $scope.index();
    };

    $scope.addReminder = function(date, title){
      var dateWnd = new window.Date();
      dateWnd.setTime(date.getTime());
  	var success = function(message) {
  	};
  	var error = function(message) {
  	  alert('Error: ' + JSON.stringify(message));
  	};

  	var calOptions = window.plugins.calendar.getCalendarOptions(); // grab the defaults
  	calOptions.firstReminderMinutes = 0;
      var comment = 'pear2pear reminder';
  	window.plugins.calendar.createEventWithOptions(title , "", comment,
                                                     dateWnd, dateWnd, calOptions, success, error);

    };

    $scope.deleteReminder = function(date, title){
      var success = function(message) {
      };
  	var error = function(message) {
  	  alert("Error: " + message);
  	};
  	var dateWnd = new window.Date();
      dateWnd.setTime(date.getTime());
  	window.plugins.calendar.deleteEvent(title, null, null, dateWnd, dateWnd,
  				                        success, error);

    };

    $scope.getReminders = function(taskId, userId){
      return $scope.reminders;
    };

    $scope.community = getCommunity();

    $scope.index = function() {
      $location.path('communities/' + communityId()  + '/tasks');
    };

    $scope.new = function(){
      $location.path('communities/' + communityId() + '/tasks/new');
    };

    $scope.edit = function(task){
      $location.path('tasks/' + task.id);
    };

    $scope.community_index = function() {
      $location.path('communities');
    };

    $scope.assigSelect = {
      assignees: $scope.community.users
    };

    $scope.supportsDateInput = Modernizr.inputtypes.date;
    $scope.supportsTimeInput = Modernizr.inputtypes.time;

    $scope.openDate = function($event) {
      $event.preventDefault();
      $event.stopPropagation();

      $scope.opened = true;
    };

    $scope.dateOptions = {};

  }])

  .directive(
    'dateInput',
        function(dateFilter) {
          return {
            require: 'ngModel',
            template: '<input type="date"></input>',
            replace: true,
            link: function(scope, elm, attrs, ngModelCtrl) {
              ngModelCtrl.$formatters.unshift(function (modelValue) {
                return dateFilter(modelValue, 'yyyy-MM-dd');
              });

              ngModelCtrl.$parsers.unshift(function(viewValue) {
                return new Date(viewValue);
              });
            }
          };
        })
  .directive(
    'timeInput',
    function(dateFilter) {
      return {
        require: 'ngModel',
        template: '<input type="time"></input>',
        replace: true,
        link: function(scope, elm, attrs, ngModelCtrl) {
          ngModelCtrl.$formatters.unshift(function (modelValue) {
            return dateFilter(modelValue, 'HH:mm');
          });

          ngModelCtrl.$parsers.unshift(function(viewValue) {
            var newDate = new Date();
            if (ngModelCtrl.$modelValue){
              newDate.setTime(ngModelCtrl.$modelValue.getTime());
            }
            newDate.setHours(viewValue.split(':')[0]);
            newDate.setMinutes(viewValue.split(':')[1]);
            newDate.setSeconds(0);
            return newDate;
          });
        }
      };
    })

 .config(function(uiSelectConfig) {
    uiSelectConfig.theme = 'select2';
  });
<|endoftext|>


<commit_before>/*
 *
 * jquery-formatmoney - v0.0.1
 *
 * jQuery plugin to format data entry in the input text or the text display in the form of money.
 *
 * Made by Troy Young
 *
 */
 (function ($) {
 	"use strict";
 	if (!$.broswer) {
 		$.broswer = {};
 		$.broswer.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
 		$.broswer.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
 		$.broswer.opera = /opera/.test(navigator.userAgent.toLowerCase());
 		$.broswer.msie = /msie/.test(navigator.userAgent.toLowerCase());
 	}

 	var FormatMoney = {
 		init: function(options) {
 			options = $.extend({
	 			prefix: "",
				thousands: ",",
	 			decimal: ".",
	 			precision: 2,
	 			allowZero: false,
	 			allowNegative: false
	 		}, options);
 			return this.each(function() {
 				var $that = $(this),
 					isInputNode = $that.is('input[type="text"]'),
 					isNegative = false;

 				// common method to format the value.
 				function format(value) {
 					var plainValue = value.replace(options.prefix, ''),
 						virtualValue = value.replace(/\D/g, ''),
 						decimalPos = plainValue.indexOf(options.decimal),
 						integerPart,
 						decimalPart,
 						newValue;

 					if(options.allowNegative) {
 						isNegative = /-/.test(value);
 					}

 					if(isNegative) {
 						decimalPos = decimalPos - 1;
 					}

 					if(decimalPos > -1) {
 						integerPart = virtualValue.slice(0, decimalPos);
 						if (integerPart === '') {
 							integerPart = '0';
 							decimalPart = virtualValue;
 						} else {
 							decimalPart = virtualValue.slice(decimalPos + 1, virtualValue.length);
 						}
 					} else {
 						integerPart = virtualValue;
 						decimalPart = '';
 					}

					// construct the new value

					// construct the integer part
					newValue = (isNegative ? '-' : '') + integerPart + options.decimal;

					// construct the decimal part
					if(options.precision > 0) {
						decimalPart = decimalPart.slice(0, options.precision);

						if(decimalPart.length < options.precision) {
							decimalPart = decimalPart + new Array(options.precision - decimalPart.length + 1).join(0);
						}

						newValue += decimalPart;
 					}

 					return setSymbol(newValue);
 				}

 				function setSymbol(value) {
 					return options.prefix + value;
 				}

 				// if the node is a plain text node, just format it.
 				// but if the node is an input node, it should be binded events.
 				if(isInputNode) {

 				} else {
 					$that.text(format($that.text()));
 				}

 			});
 		}
 	};

 	// jQuery plugin extension
 	$.fn.formatmoney = function (options) {
 		return FormatMoney.init.call(this, options);
 	};

 })(window.jQuery || window.Zepto);<commit_msg>delete the banner from original source code.<commit_after>(function ($) {
 	"use strict";
 	if (!$.broswer) {
 		$.broswer = {};
 		$.broswer.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
 		$.broswer.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
 		$.broswer.opera = /opera/.test(navigator.userAgent.toLowerCase());
 		$.broswer.msie = /msie/.test(navigator.userAgent.toLowerCase());
 	}

 	var FormatMoney = {
 		init: function(options) {
 			options = $.extend({
	 			prefix: "",
				thousands: ",",
	 			decimal: ".",
	 			precision: 2,
	 			allowZero: false,
	 			allowNegative: false
	 		}, options);
 			return this.each(function() {
 				var $that = $(this),
 					isInputNode = $that.is('input[type="text"]'),
 					isNegative = false;

 				// common method to format the value.
 				function format(value) {
 					var plainValue = value.replace(options.prefix, ''),
 						virtualValue = value.replace(/\D/g, ''),
 						decimalPos = plainValue.indexOf(options.decimal),
 						integerPart,
 						decimalPart,
 						newValue;

 					if(options.allowNegative) {
 						isNegative = /-/.test(value);
 					}

 					if(isNegative) {
 						decimalPos = decimalPos - 1;
 					}

 					if(decimalPos > -1) {
 						integerPart = virtualValue.slice(0, decimalPos);
 						if (integerPart === '') {
 							integerPart = '0';
 							decimalPart = virtualValue;
 						} else {
 							decimalPart = virtualValue.slice(decimalPos + 1, virtualValue.length);
 						}
 					} else {
 						integerPart = virtualValue;
 						decimalPart = '';
 					}

					// construct the new value

					// construct the integer part
					newValue = (isNegative ? '-' : '') + integerPart + options.decimal;

					// construct the decimal part
					if(options.precision > 0) {
						decimalPart = decimalPart.slice(0, options.precision);

						if(decimalPart.length < options.precision) {
							decimalPart = decimalPart + new Array(options.precision - decimalPart.length + 1).join(0);
						}

						newValue += decimalPart;
 					}

 					return setSymbol(newValue);
 				}

 				function setSymbol(value) {
 					return options.prefix + value;
 				}

 				// if the node is a plain text node, just format it.
 				// but if the node is an input node, it should be binded events.
 				if(isInputNode) {

 				} else {
 					$that.text(format($that.text()));
 				}

 			});
 		}
 	};

 	// jQuery plugin extension
 	$.fn.formatmoney = function (options) {
 		return FormatMoney.init.call(this, options);
 	};

 })(window.jQuery || window.Zepto);<|endoftext|>


<commit_before>class ExperimentsService {
    /*@ngInject*/
    constructor(projectsAPI) {
        this.projectsAPI = projectsAPI;
    }

    getAllForProject(projectID) {
        return this.projectsAPI(projectID).one('experiments').getList();
    }

    createForProject(projectID, experiment) {
        return this.projectsAPI(projectID).one('experiments').customPOST(experiment);
    }

    updateForProject(projectID, experimentID, what) {
        return this.projectsAPI(projectID).one('experiments', experimentID).customPUT(what);
    }

    getForProject(projectID, experimentID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).customGET();
    }

    createTask(projectID, experimentID, experimentTask) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks').customPOST(experimentTask);
    }

    updateTask(projectID, experimentID, taskID, task) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks', taskID).customPUT(task);
    }

    addTemplateToTask(projectID, experimentID, taskID, templateID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks', taskID)
            .one('template', templateID).customPOST({});
    }

    deleteTask(projectID, experimentID, taskID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('task', taskID).customDELETE();
    }
}

angular.module('materialscommons').service('experimentsService', ExperimentsService);
<commit_msg>Add updateTaskTemplateProperties method.<commit_after>class ExperimentsService {
    /*@ngInject*/
    constructor(projectsAPI) {
        this.projectsAPI = projectsAPI;
    }

    getAllForProject(projectID) {
        return this.projectsAPI(projectID).one('experiments').getList();
    }

    createForProject(projectID, experiment) {
        return this.projectsAPI(projectID).one('experiments').customPOST(experiment);
    }

    updateForProject(projectID, experimentID, what) {
        return this.projectsAPI(projectID).one('experiments', experimentID).customPUT(what);
    }

    getForProject(projectID, experimentID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).customGET();
    }

    createTask(projectID, experimentID, experimentTask) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks').customPOST(experimentTask);
    }

    updateTask(projectID, experimentID, taskID, task) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks', taskID).customPUT(task);
    }

    addTemplateToTask(projectID, experimentID, taskID, templateID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks', taskID)
            .one('template', templateID).customPOST({});
    }

    updateTaskTemplateProperties(projectID, experimentID, taskID, updateArgs) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('tasks', taskID)
            .one('template').customPUT(updateArgs);
    }

    deleteTask(projectID, experimentID, taskID) {
        return this.projectsAPI(projectID).one('experiments', experimentID).one('task', taskID).customDELETE();
    }
}

angular.module('materialscommons').service('experimentsService', ExperimentsService);
<|endoftext|>


<commit_before>var Slave = function(vid, canv, coords, dims) {
	this.video = vid;
	this.canvas = canv;
	this.ctx = canv.getContext('2d');
	this.coords = coords;
	this.dims = dims;
	// this.scaleFactor; << might need this later
	this.transforms;
	this.vf; 				// videoframe object
	this.init = function(id) {
		this.transforms = new Transforms(this);
		this.vf = VideoFrame({
			    id : 'video_' + id,
			    frameRate: FrameRates.web,
				callback: function(response, format) {
					console.log('callback response: ' + response);
				}
			});
	}
	var Transforms = function(slave) {
		slave.video.addEventListener('play', function() {
			slave.transforms.draw();
		},false);

		this.draw = function() {
			//if(v.paused || v.ended) return false;
			slave.ctx.drawImage(slave.video,coords.x,coords.y,dims.width,dims.height);
			setTimeout(slave.transforms.draw,20);
		}

		this.redraw = function(){
			// Clear the entire canvas
			// * var p1 = slave.ctx.transformedPoint(0,0);
			// * var p2 = slave.ctx.transformedPoint(slave.dimensions.cw,slave.dimensions.ch);
			//ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
			// * slave.ctx.fillStyle = 'rgb(0,0,0)';
			// * slave.ctx.fillRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
			// Alternatively:
			// ctx.save();
			// ctx.setTransform(1,0,0,1,0,0);
			// ctx.clearRect(0,0,canvas.width,canvas.height);
			// ctx.restore();
			//slave.transforms.refit();
			slave.ctx.drawImage(slave.video,coords.x,coords.y,dims.width,dims.height);
		}

		/* UNCOMMENT IF ALLOWING ZOOM INTO A SINGLE SLAVE

		var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
		this.savedTransforms = [];
		this.xform = svg.createSVGMatrix();

		var save = slave.ctx.save;
		slave.ctx.save = function(){
			this.savedTransforms.push(this.xform.translate(0,0));
			return save.call(slave.ctx);
		};

		this.restore = function(){
			var restore = slave.ctx.restore;
			this.xform = savedTransforms.pop();
			return restore.call(slave.ctx);
		};

		this.scale = function(sx,sy){
			var scale = slave.ctx.scale;
			this.xform = this.xform.scaleNonUniform(sx,sy);
			return scale.call(slave.ctx,sx,sy);
		};

		this.rotate = function(radians){
			var rotate = slave.ctx.rotate;
			this.xform = this.xform.rotate(radians*180/Math.PI);
			return rotate.call(slave.ctx,radians);
		};

		this.translate = function(dx,dy){
			var translate = slave.ctx.translate;
			this.xform = this.xform.translate(dx,dy);
			return translate.call(slave.ctx,dx,dy);
		};

		this.transform = function(a,b,c,d,e,f){
			var transform = slave.ctx.transform;
			var m2 = svg.createSVGMatrix();
			m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
			this.xform = this.xform.multiply(m2);
			return transform.call(slave.ctx,a,b,c,d,e,f);
		};

		this.setTransform = function(a,b,c,d,e,f){
			var setTransform = slave.ctx.setTransform;
			this.xform.a = a;
			this.xform.b = b;
			this.xform.c = c;
			this.xform.d = d;
			this.xform.e = e;
			this.xform.f = f;
			return setTransform.call(slave.ctx,a,b,c,d,e,f);
		};

		var pt  = svg.createSVGPoint();
		slave.ctx.transformedPoint = function(x,y){
			pt.x=x; pt.y=y;
			return pt.matrixTransform(slave.transforms.xform.inverse());
		}

		// Checks if the viewport borders intersect with the canvas borders
		// If it intersects, then scale/translate back the canvas accordingly to fit the viewport.
		this.refit = function() {
			var tx = slave.transforms.xform.e;
			var ty = slave.transforms.xform.f;
			var s = slave.transforms.xform.a;
			if (s < 1 || s > slave.zoom.maxZoom) {
				this.scale(1/s, 1/s);
			}
			if (tx > 0 ) {
				this.translate(-tx/s,0);
			}
			if (ty > 0) {
				this.translate(0,-ty/s);
			}
			if (tx+slave.dimensions.cw*s < slave.dimensions.cw) {
				var dx = (slave.dimensions.cw - tx-slave.dimensions.cw*s)/s;
				this.translate(dx, 0);
			}
			if (ty+slave.dimensions.ch*s < slave.dimensions.ch) {
				var dy = (slave.dimensions.ch - ty-slave.dimensions.ch*s)/s;
				this.translate(0, dy);
			}
		}

		this.outerTranslate = function(dragStart) {
			var pt = slave.ctx.transformedPoint(slave.last.x,slave.last.y);
			var dx = pt.x-dragStart.x;
			var dy = pt.y-dragStart.y;
			var tx = slave.transforms.xform.e;
			var ty = slave.transforms.xform.f;
			var flag = 0;
			var s = slave.transforms.xform.a;

			if (tx+dx <= 0 && tx+slave.dimensions.cw*s+dx > slave.dimensions.cw) {
				this.translate(dx,0);
				flag = 1;
			}
			if (ty+dy <= 0 && ty+slave.dimensions.ch*s+dy > slave.dimensions.ch) {
				this.translate(0,dy);
				flag = 1;
			}
			// if (flag = 0) {
			//ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
			//}
			this.redraw();
		} */
	}
}
<commit_msg>improves efficiency of draw function<commit_after>var Slave = function(vid, canv, coords, dims) {
	this.video = vid;
	this.canvas = canv;
	this.ctx = canv.getContext('2d');
	this.coords = coords;
	this.dims = dims;
	// this.scaleFactor; << might need this later
	this.transforms;
	this.vf; 				// videoframe object
	this.init = function(id) {
		this.transforms = new Transforms(this);
		this.vf = VideoFrame({
			    id : 'video_' + id,
			    frameRate: FrameRates.web,
				callback: function(response, format) {
					console.log('callback response: ' + response);
				}
			});
	}
	var Transforms = function(slave) {
		slave.video.addEventListener('play', function() {
			slave.transforms.draw();
		},false);

		this.draw = function() {
			if (!slave.video.paused) { 	//if(v.paused || v.ended) return false;
				slave.ctx.drawImage(slave.video,coords.x,coords.y,dims.width,dims.height);
			}
			requestAnimationFrame(slave.transforms.draw)
			//setTimeout(slave.transforms.draw,20);
		}

		this.redraw = function(){
			// Clear the entire canvas
			// * var p1 = slave.ctx.transformedPoint(0,0);
			// * var p2 = slave.ctx.transformedPoint(slave.dimensions.cw,slave.dimensions.ch);
			//ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
			// * slave.ctx.fillStyle = 'rgb(0,0,0)';
			// * slave.ctx.fillRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
			// Alternatively:
			// ctx.save();
			// ctx.setTransform(1,0,0,1,0,0);
			// ctx.clearRect(0,0,canvas.width,canvas.height);
			// ctx.restore();
			//slave.transforms.refit();
			slave.ctx.drawImage(slave.video,coords.x,coords.y,dims.width,dims.height);
		}

		/* UNCOMMENT IF ALLOWING ZOOM INTO A SINGLE SLAVE

		var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
		this.savedTransforms = [];
		this.xform = svg.createSVGMatrix();

		var save = slave.ctx.save;
		slave.ctx.save = function(){
			this.savedTransforms.push(this.xform.translate(0,0));
			return save.call(slave.ctx);
		};

		this.restore = function(){
			var restore = slave.ctx.restore;
			this.xform = savedTransforms.pop();
			return restore.call(slave.ctx);
		};

		this.scale = function(sx,sy){
			var scale = slave.ctx.scale;
			this.xform = this.xform.scaleNonUniform(sx,sy);
			return scale.call(slave.ctx,sx,sy);
		};

		this.rotate = function(radians){
			var rotate = slave.ctx.rotate;
			this.xform = this.xform.rotate(radians*180/Math.PI);
			return rotate.call(slave.ctx,radians);
		};

		this.translate = function(dx,dy){
			var translate = slave.ctx.translate;
			this.xform = this.xform.translate(dx,dy);
			return translate.call(slave.ctx,dx,dy);
		};

		this.transform = function(a,b,c,d,e,f){
			var transform = slave.ctx.transform;
			var m2 = svg.createSVGMatrix();
			m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
			this.xform = this.xform.multiply(m2);
			return transform.call(slave.ctx,a,b,c,d,e,f);
		};

		this.setTransform = function(a,b,c,d,e,f){
			var setTransform = slave.ctx.setTransform;
			this.xform.a = a;
			this.xform.b = b;
			this.xform.c = c;
			this.xform.d = d;
			this.xform.e = e;
			this.xform.f = f;
			return setTransform.call(slave.ctx,a,b,c,d,e,f);
		};

		var pt  = svg.createSVGPoint();
		slave.ctx.transformedPoint = function(x,y){
			pt.x=x; pt.y=y;
			return pt.matrixTransform(slave.transforms.xform.inverse());
		}

		// Checks if the viewport borders intersect with the canvas borders
		// If it intersects, then scale/translate back the canvas accordingly to fit the viewport.
		this.refit = function() {
			var tx = slave.transforms.xform.e;
			var ty = slave.transforms.xform.f;
			var s = slave.transforms.xform.a;
			if (s < 1 || s > slave.zoom.maxZoom) {
				this.scale(1/s, 1/s);
			}
			if (tx > 0 ) {
				this.translate(-tx/s,0);
			}
			if (ty > 0) {
				this.translate(0,-ty/s);
			}
			if (tx+slave.dimensions.cw*s < slave.dimensions.cw) {
				var dx = (slave.dimensions.cw - tx-slave.dimensions.cw*s)/s;
				this.translate(dx, 0);
			}
			if (ty+slave.dimensions.ch*s < slave.dimensions.ch) {
				var dy = (slave.dimensions.ch - ty-slave.dimensions.ch*s)/s;
				this.translate(0, dy);
			}
		}

		this.outerTranslate = function(dragStart) {
			var pt = slave.ctx.transformedPoint(slave.last.x,slave.last.y);
			var dx = pt.x-dragStart.x;
			var dy = pt.y-dragStart.y;
			var tx = slave.transforms.xform.e;
			var ty = slave.transforms.xform.f;
			var flag = 0;
			var s = slave.transforms.xform.a;

			if (tx+dx <= 0 && tx+slave.dimensions.cw*s+dx > slave.dimensions.cw) {
				this.translate(dx,0);
				flag = 1;
			}
			if (ty+dy <= 0 && ty+slave.dimensions.ch*s+dy > slave.dimensions.ch) {
				this.translate(0,dy);
				flag = 1;
			}
			// if (flag = 0) {
			//ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
			//}
			this.redraw();
		} */
	}
}
<|endoftext|>