<commit_before>/* Copyright (c) 2010, Sage Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Attatchment Manager
 */
define('Mobile/SalesLogix/AttachmentManager', [
    'Mobile/SalesLogix/FileManager',
    'dojo/_base/lang',
    'dojo/_base/declare',
    'dojo/string',
    'dojo/number',
    'Sage/Platform/Mobile/Convert'
], function(
    FileManager,
    lang,
    declare,
    string,
    dNumber,
    convert
) {
    return declare('Mobile.SalesLogix.AttachmentManager', null, {
        _fileManager: null,
        _entityContext: null,
        _uploadUrl: '',
        _baseUrl: '',
        _attachmentTemplate: false,
        serviceName: false,
        contractName: 'system',
        resourceKind: 'attachments',
        querySelect: null,
        queryInclude: null,
        _files: null,
        _fileDescriptions: null,
        _filesUploadedCount: 0,
        _fileCount: 0,
        _totalProgress: 0,
        _isUploading:false,
        constructor: function() {
            var service, oldContractName;
            this.querySelect = [];
            this.queryInclude = [];
            this._files = [];
            this._fileDescriptions = [];
            this._fileManager = new FileManager();
            service = App.getService(this.serviceName);
            oldContractName = service.getContractName();
            service.setContractName(this.contractName);
            this._baseUrl = service.getUri().toString();
            this._uploadUrl = this._baseUrl + '/attachments/file';
            service.setContractName(oldContractName);
        },
        createAttachments: function(files) {

        },
        createAttachment: function(file, mixin) {
            if (!mixin.hasOwnProperty('description')) {
                mixin['description'] = this._getDefaultDescription(file.name);
            }
            this._files.push(file);
            this._fileDescriptions.push({
                fileName:file.name,
                description: mixin['description']
            });
            this.uploadFiles();
        },
        _getDefaultDescription: function(filename) {
            return filename.replace(/\.[\w]*/, '');
        },
        getAttachmentTemplate: function(callback) {
            this.requestTemplate(
                function(template) {
                    this._attachmentTemplate = template;
                    this.uploadFiles();
                },
                this.onRequestTemplateFailure
            );
        },
        getAttachmentUrl: function(attachmentId) {
            var fileUrl = this._baseUrl + '/attachments(\'' + attachmentId + '\')/file';
            return fileUrl;
        },
        _getFileDescription: function(fileName) {
            var description = this._getDefaultDescription(fileName);
            for (var i = 0; i < this._fileDescriptions.length; i++) {
                if (fileName === this._fileDescriptions[i].fileName) {
                    description = this._fileDescriptions[i].description;
                }
            }
            if ((description === null)|| (description === '')) {
                description = this._getDefaultDescription(fileName);
            }
            return description;
        },
        _getAttachmentContextMixin: function(fileName) {
            var contextMixin;
            contextMixin = this._getAttachmentContext();
            return contextMixin;
        },
        _getAttachmentContext: function() {
            var contextView;
            var view;
            var entry;
            var contextData = {};
            var found;
            found = App.queryNavigationContext(function(o) {
                var context = (o.options && o.options.source) || o;
                if (/^(accounts|contacts|opportunities|tickets|leads|activities|history)$/.test(context.resourceKind) && context.key) {
                    return true;
                }
                return false;
            });
            contextView = (found && found.options && found.options.source) || found;
            if (contextView) {
                view = App.getView(contextView.id),
                entry = contextView.entry || (view && view.entry) || contextView;

                if (!entry || !entry['$key']) {
                    return {};
                }

                switch (contextView.resourceKind) {
                    case 'accounts':
                        contextData = { accountId: entry['$key'], accountName: entry['$descriptor'] };
                        break;
                    case 'contacts':
                        contextData = { contactId: entry['$key'], contactName: entry['$descriptor'], accountId: entry['AccountId'], accountName: entry['AccountName'] };
                        break;
                    case 'opportunities':
                        contextData = { opportunityId: entry['$key'], description: entry['$descriptor'], accountId: entry['AccountId'], accountName: entry['AccountName'] };
                        break;
                    case 'tickets':
                        contextData = { ticketId: entry['$key'], ticketNumber: entry['$descriptor'], accountId: entry['AccountId'], accountName: entry['AccountName'] };
                        break;
                    case 'leads':
                        contextData = { leadId: entry['$key'], accountName: entry['$descriptor'] };
                        break;
                    case 'activities':
                        contextData = { activityId: entry['$key'], contactId: entry['ContactId'], contactName: entry['ContactName'], accountId: entry['AccountId'], accountName: entry['AccountName'], opportunityId: entry['OpportunityId'], ticketId: entry['TicketId'], };
                        break;
                    case 'history':
                        contextData = { historyId: entry['$key'], contactId: entry['ContactId'], contactName: entry['ContactName'], accountId: entry['AccountId'], accountName: entry['AccountName'], opportunityId: entry['OpportunityId'], ticketId: entry['TicketId'], };
                        break;
                    default:
                        contextData = { entityId: entry['$key'], entityName: contextView.id, description: entry['$descriptor'] };
                        break;
                }
            }
            return contextData;
        },
        getService: function() {
            return App.getService(this.serviceName); /* if false is passed, the default service will be returned */
        },
        createTemplateRequest: function() {
            var request = new Sage.SData.Client.SDataTemplateResourceRequest(this.getService());
            request.setResourceKind(this.resourceKind);
            request.setContractName(this.contractName);
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Select, this.querySelect.join(','));
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Include, this.queryInclude.join(','));
            return request;
        },
        requestTemplate: function(onSucess, onFailure) {
            var request = this.createTemplateRequest();
            if (request)
                request.read({
                    success: onSucess,
                    failure: onFailure,
                    scope: this
                });
        },
        onRequestTemplateFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        onRequestTemplateSuccess: function(entry) {
            this.processTemplateEntry(entry);
        },
        createDataRequest: function(id) {
            var request = new Sage.SData.Client.SDataSingleResourceRequest(this.getService());
            request.setResourceKind(this.resourceKind);
            request.setContractName(this.contractName);
            request.setResourceSelector(string.substitute("'${0}'", [id]));

            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Select, this.querySelect.join(','));
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Include, this.queryInclude.join(','));
            request.setQueryArg('_includeFile', 'false');
            return request;
        },
        requestData: function(attachmnetId, onSucess, onFailure) {
            var request = this.createDataRequest(attachmnetId);
            if (request)
                request.read({
                    success: onSucess,
                    failure: onFailure,
                    scope: this
                });
        },
        onRequestTemplateFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        onRequestDataFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        uploadFiles: function() {
            this._isUploading = true;
            this._fileCount = this._files.length;
            while (this._files.length > 0) {
                var file = this._files.pop();
                this._fileManager.uploadFile(file,
                this._uploadUrl,
                this._updateProgress,
                this._onSuccessUpload,
                this._onFailedUpload,
                this);
            }
        },
        _onSuccessUpload: function(request) {
            //the id of the new attachment is buried in the Location response header...
            var url = request.getResponseHeader('Location');
            var re = /\'\w+\'/g;
            var matches = url.match(re);
            if (matches) {
                var id = matches[0].replace(/\'/g, '');
                //now that we have the id, we can fetch it using the SingleEntrySDataStore
                this.requestData(id, function(attachment) {
                    var mixin = this._getAttachmentContextMixin(attachment.fileName);
                    if (mixin) {
                        attachment.attachDate = convert.toIsoStringFromDate(new Date());
                        attachment.dataType = 'R';
                        attachment.description = this._getFileDescription(attachment.fileName);
                        attachment = lang.mixin(attachment, mixin);
                        var request = this.createDataRequest(id);
                        if (request){
                            request.update(attachment, {
                                success: this.onSuccessUpdate,
                                failure: this._onFailedUpdate,
                                scope: this
                            });
                        }
                    }
                },
                    this.onRequestDataFailure
                );

            }
            // this._filesUploadedCount = this._filesUploadedCount + 1;
            // this._updateProgress((this._fileCount < 1) ? 100 : (this._filesUploadedCount / this._fileCount) * 100);
        },
        _onFailedUpload: function(resp) {
            console.warn('Attachment failed to upload %o', resp);
        },
        _onFailedAdd: function(resp) {
            console.warn('Attachment failed to save %o', resp);
        },
        onSuccessUpdate: function(attachment) {
        },
        _onFailedUpdate: function(resp) {
            console.warn('Attachment failed to update %o', resp);
        },
        _updateProgress: function(curFileProgress) {
            //console.log('progress obj: %o', curFileProgress);
            var pct = this._totalProgress;
            //console.log('pct: ' + pct);
            if (curFileProgress && curFileProgress.lengthComputable) {
                var thisFilePercent = (curFileProgress.loaded / curFileProgress.total) * 100;
                pct += Math.round(thisFilePercent / this._fileCount);
            } else if (curFileProgress) {
                pct = curFileProgress;
            }
            this._totalProgress = pct;
            //console.log('now calculated pct: ' + pct);
            if (pct < 99) {
                // dialogs.showProgressBar({
                //     pct: pct,
                //     title: this.percentComplete
                // });
            } else {
                //  dialogs.closeProgressBar();
                this._resetCounts();

            }
        },
        _resetCounts: function() {
            this._fileCount = 0;
            this._filesUploadedCount = 0;
            this._isUploading = false;
            this._totalProgress = 0;
        },
        getAttachmentFile: function(attachmentId, responseType, onSuccsess) {
            var url = this.getAttachmentUrl(attachmentId);
            var fm = this._fileManager.getFile(url, responseType, onSuccsess);
        }
    });
});
<commit_msg>Fixing Attachement to contact and then account.<commit_after>/* Copyright (c) 2010, Sage Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Attatchment Manager
 */
define('Mobile/SalesLogix/AttachmentManager', [
    'Mobile/SalesLogix/FileManager',
    'dojo/_base/lang',
    'dojo/_base/declare',
    'dojo/string',
    'dojo/number',
    'Sage/Platform/Mobile/Convert'
], function(
    FileManager,
    lang,
    declare,
    string,
    dNumber,
    convert
) {
    return declare('Mobile.SalesLogix.AttachmentManager', null, {
        _fileManager: null,
        _entityContext: null,
        _uploadUrl: '',
        _baseUrl: '',
        _attachmentTemplate: false,
        serviceName: false,
        contractName: 'system',
        resourceKind: 'attachments',
        querySelect: null,
        queryInclude: null,
        _files: null,
        _fileDescriptions: null,
        _filesUploadedCount: 0,
        _fileCount: 0,
        _totalProgress: 0,
        _isUploading:false,
        constructor: function() {
            var service, oldContractName;
            this.querySelect = [];
            this.queryInclude = [];
            this._files = [];
            this._fileDescriptions = [];
            this._fileManager = new FileManager();
            service = App.getService(this.serviceName);
            oldContractName = service.getContractName();
            service.setContractName(this.contractName);
            this._baseUrl = service.getUri().toString();
            this._uploadUrl = this._baseUrl + '/attachments/file';
            service.setContractName(oldContractName);
        },
        createAttachments: function(files) {

        },
        createAttachment: function(file, mixin) {
            if (!mixin.hasOwnProperty('description')) {
                mixin['description'] = this._getDefaultDescription(file.name);
            }
            this._files.push(file);
            this._fileDescriptions.push({
                fileName:file.name,
                description: mixin['description']
            });
            this.uploadFiles();
        },
        _getDefaultDescription: function(filename) {
            return filename.replace(/\.[\w]*/, '');
        },
        getAttachmentTemplate: function(callback) {
            this.requestTemplate(
                function(template) {
                    this._attachmentTemplate = template;
                    this.uploadFiles();
                },
                this.onRequestTemplateFailure
            );
        },
        getAttachmentUrl: function(attachmentId) {
            var fileUrl = this._baseUrl + '/attachments(\'' + attachmentId + '\')/file';
            return fileUrl;
        },
        _getFileDescription: function(fileName) {
            var description = this._getDefaultDescription(fileName);
            for (var i = 0; i < this._fileDescriptions.length; i++) {
                if (fileName === this._fileDescriptions[i].fileName) {
                    description = this._fileDescriptions[i].description;
                }
            }
            if ((description === null)|| (description === '')) {
                description = this._getDefaultDescription(fileName);
            }
            return description;
        },
        _getAttachmentContextMixin: function(fileName) {
            var contextMixin;
            contextMixin = this._getAttachmentContext();
            return contextMixin;
        },
        _getAttachmentContext: function() {
            var contextView;
            var view;
            var entry;
            var contextData = {};
            var found;
            found = App.queryNavigationContext(function(o) {
                var context = (o.options && o.options.source) || o;
                if (/^(accounts|contacts|opportunities|tickets|leads|activities|history)$/.test(context.resourceKind) && context.key) {
                    return true;
                }
                return false;
            });
            contextView = (found && found.options && found.options.source) || found;
            if (contextView) {
                view = App.getView(contextView.id),
                entry = contextView.entry || (view && view.entry) || contextView;

                if (!entry || !entry['$key']) {
                    return {};
                }

                switch (contextView.resourceKind) {
                    case 'accounts':
                        contextData = { accountId: entry['$key'], accountName: entry['$descriptor'] };
                        break;
                    case 'contacts':
                        contextData = { contactId: entry['$key'], contactName: entry['$descriptor'], accountId: entry['Account']['$key'], accountName: entry['Account']['AccountName'] };
                        break;
                    case 'opportunities':
                        contextData = { opportunityId: entry['$key'], description: entry['$descriptor'], accountId: entry['Account']['$key'], accountName: entry['Account']['AccountName'] };
                        break;
                    case 'tickets':
                        contextData = { ticketId: entry['$key'], ticketNumber: entry['$descriptor'], accountId: entry['Account']['$key'], accountName: entry['Account']['AccountName'] };
                        break;
                    case 'leads':
                        contextData = { leadId: entry['$key'], accountName: entry['$descriptor'] };
                        break;
                    case 'activities':
                        contextData = { activityId: entry['$key'], contactId: entry['ContactId'], contactName: entry['ContactName'], accountId: entry['AccountId'], accountName: entry['AccountName'], opportunityId: entry['OpportunityId'], ticketId: entry['TicketId'], };
                        break;
                    case 'history':
                        contextData = { historyId: entry['$key'], contactId: entry['ContactId'], contactName: entry['ContactName'], accountId: entry['AccountId'], accountName: entry['AccountName'], opportunityId: entry['OpportunityId'], ticketId: entry['TicketId'], };
                        break;
                    default:
                        contextData = { entityId: entry['$key'], entityName: contextView.id, description: entry['$descriptor'] };
                        break;
                }
            }
            return contextData;
        },
        getService: function() {
            return App.getService(this.serviceName); /* if false is passed, the default service will be returned */
        },
        createTemplateRequest: function() {
            var request = new Sage.SData.Client.SDataTemplateResourceRequest(this.getService());
            request.setResourceKind(this.resourceKind);
            request.setContractName(this.contractName);
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Select, this.querySelect.join(','));
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Include, this.queryInclude.join(','));
            return request;
        },
        requestTemplate: function(onSucess, onFailure) {
            var request = this.createTemplateRequest();
            if (request)
                request.read({
                    success: onSucess,
                    failure: onFailure,
                    scope: this
                });
        },
        onRequestTemplateFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        onRequestTemplateSuccess: function(entry) {
            this.processTemplateEntry(entry);
        },
        createDataRequest: function(id) {
            var request = new Sage.SData.Client.SDataSingleResourceRequest(this.getService());
            request.setResourceKind(this.resourceKind);
            request.setContractName(this.contractName);
            request.setResourceSelector(string.substitute("'${0}'", [id]));

            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Select, this.querySelect.join(','));
            request.setQueryArg(Sage.SData.Client.SDataUri.QueryArgNames.Include, this.queryInclude.join(','));
            request.setQueryArg('_includeFile', 'false');
            return request;
        },
        requestData: function(attachmnetId, onSucess, onFailure) {
            var request = this.createDataRequest(attachmnetId);
            if (request)
                request.read({
                    success: onSucess,
                    failure: onFailure,
                    scope: this
                });
        },
        onRequestTemplateFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        onRequestDataFailure: function(response, o) {
            // alert(string.substitute(this.requestErrorText, [response, o]));
            // ErrorManager.addError(response, o, this.options, 'failure');
        },
        uploadFiles: function() {
            this._isUploading = true;
            this._fileCount = this._files.length;
            while (this._files.length > 0) {
                var file = this._files.pop();
                this._fileManager.uploadFile(file,
                this._uploadUrl,
                this._updateProgress,
                this._onSuccessUpload,
                this._onFailedUpload,
                this);
            }
        },
        _onSuccessUpload: function(request) {
            //the id of the new attachment is buried in the Location response header...
            var url = request.getResponseHeader('Location');
            var re = /\'\w+\'/g;
            var matches = url.match(re);
            if (matches) {
                var id = matches[0].replace(/\'/g, '');
                //now that we have the id, we can fetch it using the SingleEntrySDataStore
                this.requestData(id, function(attachment) {
                    var mixin = this._getAttachmentContextMixin(attachment.fileName);
                    if (mixin) {
                        attachment.attachDate = convert.toIsoStringFromDate(new Date());
                        attachment.dataType = 'R';
                        attachment.description = this._getFileDescription(attachment.fileName);
                        attachment = lang.mixin(attachment, mixin);
                        var request = this.createDataRequest(id);
                        if (request){
                            request.update(attachment, {
                                success: this.onSuccessUpdate,
                                failure: this._onFailedUpdate,
                                scope: this
                            });
                        }
                    }
                },
                    this.onRequestDataFailure
                );

            }
            // this._filesUploadedCount = this._filesUploadedCount + 1;
            // this._updateProgress((this._fileCount < 1) ? 100 : (this._filesUploadedCount / this._fileCount) * 100);
        },
        _onFailedUpload: function(resp) {
            console.warn('Attachment failed to upload %o', resp);
        },
        _onFailedAdd: function(resp) {
            console.warn('Attachment failed to save %o', resp);
        },
        onSuccessUpdate: function(attachment) {
        },
        _onFailedUpdate: function(resp) {
            console.warn('Attachment failed to update %o', resp);
        },
        _updateProgress: function(curFileProgress) {
            //console.log('progress obj: %o', curFileProgress);
            var pct = this._totalProgress;
            //console.log('pct: ' + pct);
            if (curFileProgress && curFileProgress.lengthComputable) {
                var thisFilePercent = (curFileProgress.loaded / curFileProgress.total) * 100;
                pct += Math.round(thisFilePercent / this._fileCount);
            } else if (curFileProgress) {
                pct = curFileProgress;
            }
            this._totalProgress = pct;
            //console.log('now calculated pct: ' + pct);
            if (pct < 99) {
                // dialogs.showProgressBar({
                //     pct: pct,
                //     title: this.percentComplete
                // });
            } else {
                //  dialogs.closeProgressBar();
                this._resetCounts();

            }
        },
        _resetCounts: function() {
            this._fileCount = 0;
            this._filesUploadedCount = 0;
            this._isUploading = false;
            this._totalProgress = 0;
        },
        getAttachmentFile: function(attachmentId, responseType, onSuccsess) {
            var url = this.getAttachmentUrl(attachmentId);
            var fm = this._fileManager.getFile(url, responseType, onSuccsess);
        }
    });
});
<|endoftext|>


<commit_before>function GetContext() {
  return document.getElementById("canvas").getContext("2d");
}

var radiusSupported = false;
var nextCount = 0;
var touchMap = {};
var pointMode = (window.location.hash == "#points");
var enableForce = false;
var drawTouchMajor = true;
var foundRotationAngle = false;
var scale = 1;

document.addEventListener("keyup", function(e) {
  switch(e.which) {
    // ESC
    case 27:
    var canvas = document.getElementById("canvas");
    canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
    break;

    // p
    case 80:
    pointMode = !pointMode;
    window.location.hash = pointMode ? "#points" : "";
    break;

    // f
    case 70:
    enableForce = !enableForce;
    break;

    // a
    case 65:
    drawTouchMajor = !drawTouchMajor;
    break;

    // enter
    case 13:
    if (document.documentElement.webkitRequestFullscreen) {
      if (document.webkitFullscreenElement)
        document.webkitCancelFullScreen();
      else
        document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
    }
  }

});

window.addEventListener("resize", function(e) {
    InitializeCanvas();
});

function drawTouches(touches, eventType) {
  var context = GetContext();
  for (var i = 0; i < touches.length; ++i) {
    var touch = touches[i];

    // Map the identifier to a small count (no-op on Chrome, but
    // important for mobile Safari).
    if (!(touch.identifier in touchMap)) {
      touchMap[touch.identifier] = nextCount;
      nextCount++;
    }

    // Polyfill non-standard properties
    if (!("radiusX" in touch) && "webkitRadiusX" in touch)
      touch.radiusX = touch.webkitRadiusX;
    if (!("radiusY" in touch) && "webkitRadiusY" in touch)
      touch.radiusY = touch.webkitRadiusY;
    if (!("rotationAngle" in touch) && "webkitRotationAngle" in touch)
      touch.rotationAngle = touch.webkitRotationAngle;
    if (!("force" in touch) && "webkitForce" in touch)
      touch.force = touch.webkitForce;

    var radiusX = getAdjustedRadius(touch.radiusX, touch.radiusY);
    var radiusY = getAdjustedRadius(touch.radiusY, touch.radiusX);
    var rotationAngle = getAdjustedRotationAngle(touch.rotationAngle);
    foundRotationAngle = foundRotationAngle || rotationAngle;

    // Try to avoid start/end ellipses overlapping exactly
    if (eventType == "touchend") {
      radiusX++;
      radiusY++;
    }

    context.save();
    context.translate(touch.pageX * scale, touch.pageY * scale);
    context.rotate(rotationAngle);
    context.scale(radiusY/radiusX, 1);
    context.beginPath();
    context.arc(0, 0, radiusX, 0, 2.0 * Math.PI, false);
    context.closePath();

    // Fill the ellipse on start/move
    if (eventType != "touchend") {
      var opacity = pointMode ? 1 : 0.1;

      var hue = (touchMap[touch.identifier] * 30) % 256;
      var lum = 40;
      if (enableForce && touch.force)
        lum = Math.round(touch.force / 0.4 * 50 + 20);
      context.fillStyle = "hsla(" + hue + ",100%," + lum + "%, " + opacity + ")";
      context.fill();
    }

    // Outline ellipse on start/end
    if (eventType != "touchmove") {
      context.strokeStyle = eventType == "touchstart" ? "black" : "grey";
      context.lineWidth = 2;
      context.stroke();
    }

    if (drawTouchMajor && foundRotationAngle) {
      context.strokeStyle = "#fff";
      context.lineWidth = 1;
      context.beginPath();
      if (radiusX >= radiusY) {
        context.moveTo(0, -radiusX);
        context.lineTo(0, radiusX);
      } else {
        // Note that this is also radiusX, because of the scaling above
        context.moveTo(-radiusX, 0);
        context.lineTo(radiusX, 0);
      }
      context.stroke();
    }

    context.restore();
  }
}

function getAdjustedRadius(radius, otherRadius) {
  if (pointMode)
    return 1;

  // Spec says to use 1 for unknown radius, can't differentiate between that
  // and real 1 pixel radius.
  var radiusUndefined = !radius || radius <= 1;
  var otherRadiusUndefined = !otherRadius || otherRadius <= 1;

  if (radiusUndefined) {
    radius = otherRadiusUndefined? 15 : otherRadius;
  }

  if (radius > 100) {
    console.error("Got large radius: " + radius);
    radius = 100;
  }

  return radius * scale;
}

function getAdjustedRotationAngle(angle) {
  return angle * Math.PI / 180;
}

function TouchHandler(event) {
  event.preventDefault();
  drawTouches(event.changedTouches,event.type);
}

var mousePressed = false;

function MouseHandler(event) {
  if (event.type == "mousedown" && event.button === 0) mousePressed = true;
  if (mousePressed && event.button === 0)
  {
    var fakeTouch = {
      identifier: 10,
      pageX : event.pageX,
      pageY : event.pageY
    };
    var eventType = event.type == "mousedown" ? "touchstart" :
      event.type == "mouseup" ? "touchend" : "touchmove";
    drawTouches([fakeTouch], eventType);
    event.preventDefault();

    if (event.type == "mouseup") mousePressed = false;
  }
}

function InitializeCanvas() {
  var elem = document.getElementById("canvas");

  var newscale = window.devicePixelRatio ? window.devicePixelRatio : 1;
  var newwidth = window.screen.width * newscale;
  var newheight = window.screen.height * newscale;

  if (elem.width != newwidth || elem.height != newheight || scale != newscale) {
    // resizing a canvas clears it, so do it only when it's dimensions have changed.
    scale = newscale;
    elem.width = newwidth;
    elem.height = newheight;
    elem.style.width = window.screen.width + "px";
    elem.style.height = window.screen.height + "px";
  }
}
<commit_msg>Update paint.js<commit_after>function GetContext() {
  return document.getElementById("canvas").getContext("2d");
}

var radiusSupported = false;
var nextCount = 0;
var touchMap = {};
var pointMode = (window.location.hash == "#points");
var enableForce = false;
var drawTouchMajor = true;
var foundRotationAngle = false;
var scale = 1;

document.addEventListener("keyup", function(e) {
  switch(e.which) {
    // ESC
    case 27:
    var canvas = document.getElementById("canvas");
    canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
    break;

    // p
    case 80:
    pointMode = !pointMode;
    window.location.hash = pointMode ? "#points" : "";
    break;

    // f
    case 70:
    enableForce = !enableForce;
    break;

    // a
    case 65:
    drawTouchMajor = !drawTouchMajor;
    break;

    // enter
    case 13:
    if (document.documentElement.webkitRequestFullscreen) {
      if (document.webkitFullscreenElement)
        document.webkitCancelFullScreen();
      else
        document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
    }
  }

});

window.addEventListener("resize", function(e) {
    InitializeCanvas();
});

function drawTouches(touches, eventType) {
  var context = GetContext();
  for (var i = 0; i < touches.length; ++i) {
    var touch = touches[i];

    // Map the identifier to a small count (no-op on Chrome, but
    // important for mobile Safari).
    if (!(touch.identifier in touchMap)) {
      touchMap[touch.identifier] = nextCount;
      nextCount++;
    }

    // Polyfill non-standard properties
    if (!("radiusX" in touch) && "webkitRadiusX" in touch)
      touch.radiusX = touch.webkitRadiusX;
    if (!("radiusY" in touch) && "webkitRadiusY" in touch)
      touch.radiusY = touch.webkitRadiusY;
    if (!("rotationAngle" in touch) && "webkitRotationAngle" in touch)
      touch.rotationAngle = touch.webkitRotationAngle;
    if (!("force" in touch) && "webkitForce" in touch)
      touch.force = touch.webkitForce;

    var radiusX = getAdjustedRadius(touch.radiusX, touch.radiusY);
    var radiusY = getAdjustedRadius(touch.radiusY, touch.radiusX);
    var rotationAngle = getAdjustedRotationAngle(touch.rotationAngle);
    foundRotationAngle = foundRotationAngle || rotationAngle;

    // Try to avoid start/end ellipses overlapping exactly
    if (eventType == "touchend") {
      radiusX++;
      radiusY++;
    }

    context.save();
    context.translate(touch.pageX * scale, touch.pageY * scale);
    context.rotate(rotationAngle);
    context.scale(1, radiusY/radiusX);
    context.beginPath();
    context.arc(0, 0, radiusX, 0, 2.0 * Math.PI, false);
    context.closePath();

    // Fill the ellipse on start/move
    if (eventType != "touchend") {
      var opacity = pointMode ? 1 : 0.1;

      var hue = (touchMap[touch.identifier] * 30) % 256;
      var lum = 40;
      if (enableForce && touch.force)
        lum = Math.round(touch.force / 0.4 * 50 + 20);
      context.fillStyle = "hsla(" + hue + ",100%," + lum + "%, " + opacity + ")";
      context.fill();
    }

    // Outline ellipse on start/end
    if (eventType != "touchmove") {
      context.strokeStyle = eventType == "touchstart" ? "black" : "grey";
      context.lineWidth = 2;
      context.stroke();
    }

    if (drawTouchMajor && foundRotationAngle) {
      context.strokeStyle = "#fff";
      context.lineWidth = 1;
      context.beginPath();
      if (radiusX >= radiusY) {
        context.moveTo(-radiusX, 0);
        context.lineTo(radiusX, 0);
      } else {
        // Note that this is also radiusX, because of the scaling above
        context.moveTo(0, -radiusX);
        context.lineTo(0, radiusX);
      }
      context.stroke();
    }

    context.restore();
  }
}

function getAdjustedRadius(radius, otherRadius) {
  if (pointMode)
    return 1;

  // Spec says to use 1 for unknown radius, can't differentiate between that
  // and real 1 pixel radius.
  var radiusUndefined = !radius || radius <= 1;
  var otherRadiusUndefined = !otherRadius || otherRadius <= 1;

  if (radiusUndefined) {
    radius = otherRadiusUndefined? 15 : otherRadius;
  }

  if (radius > 100) {
    console.error("Got large radius: " + radius);
    radius = 100;
  }

  return radius * scale;
}

function getAdjustedRotationAngle(angle) {
  return angle * Math.PI / 180;
}

function TouchHandler(event) {
  event.preventDefault();
  drawTouches(event.changedTouches,event.type);
}

var mousePressed = false;

function MouseHandler(event) {
  if (event.type == "mousedown" && event.button === 0) mousePressed = true;
  if (mousePressed && event.button === 0)
  {
    var fakeTouch = {
      identifier: 10,
      pageX : event.pageX,
      pageY : event.pageY
    };
    var eventType = event.type == "mousedown" ? "touchstart" :
      event.type == "mouseup" ? "touchend" : "touchmove";
    drawTouches([fakeTouch], eventType);
    event.preventDefault();

    if (event.type == "mouseup") mousePressed = false;
  }
}

function InitializeCanvas() {
  var elem = document.getElementById("canvas");

  var newscale = window.devicePixelRatio ? window.devicePixelRatio : 1;
  var newwidth = window.screen.width * newscale;
  var newheight = window.screen.height * newscale;

  if (elem.width != newwidth || elem.height != newheight || scale != newscale) {
    // resizing a canvas clears it, so do it only when it's dimensions have changed.
    scale = newscale;
    elem.width = newwidth;
    elem.height = newheight;
    elem.style.width = window.screen.width + "px";
    elem.style.height = window.screen.height + "px";
  }
}
<|endoftext|>


<commit_before>"use strict";
/**
 * Creating floating Panel-nodes which can be shown and hidden.
 *
 *
 * Copyright (c) 2014 ITSA - https://github.com/itsa
 * New BSD License - http://choosealicense.com/licenses/bsd-3-clause/
 *
 *
 * @module panel
 * @class Panel
 * @since 0.0.1
*/

require('js-ext/lib/object.js');
require('js-ext/lib/string.js');
require('polyfill');
require('./css/panel.css');

var NAME = '[panel]: ',
    PANEL_Z = 1000,
    MODAL_Z = 2000,
    PANEL_TOP = 999,
    MAX_WIDTH_FULL_BUTTONS = 150,
    createHashMap = require('js-ext/extra/hashmap.js').createMap;

module.exports = function (window) {

    var DOCUMENT = window.document,
        LightMap = require('js-ext/extra/lightmap.js'),
        Panel, Event, setupEvents, DD, stackManager, insertModalLayer;

    window._ITSAmodules || Object.protectedProp(window, '_ITSAmodules', createHashMap());

/*jshint boss:true */
    if (Panel=window._ITSAmodules.Panel) {
/*jshint boss:false */
        return Panel; // Panel was already created
    }

    require('window-ext')(window);
    require('node-plugin')(window);
    require('focusmanager')(window);
    require('scrollable')(window);

    Event = require('event-mobile')(window);
    DD = require('drag')(window);
    DD.init(); // ITSA combines the Drag-module with drag-drop into ITSA.DD

    /*
     * Generates a modal-layer.
     *
     * @method insertModalLayer
     * @protected
     * @since 0.0.1
     */
    insertModalLayer = function() {
       DOCUMENT.body.addSystemElement('

', null, true);
    };

    insertModalLayer();

    /*
     * Sets up all events needed for Panel's to work well.
     *
     * @method setupEvents
     * @protected
     * @since 0.0.1
     */
    setupEvents = function() {
        Event.defineEvent('panel:buttonhide').defaultFn(function(e) {
            var model = e.model;
            model.visible = false;
            (typeof model.callback==='function') && model.callback(e.button);
        });
        Event.before('panel:buttonhide', function(e) {
            var model = e.model;
            if (typeof model.validate==='function') {
                model.validate(e) || e.preventDefault();
            }
        });
        Event.after('tap', function(e) {
            var buttonNode = e.target,
                panelNode = buttonNode.inside('[plugin-panel="true"]'),
                plugin = panelNode._plugin.panel,
                model = plugin.model;
            Event.emit(panelNode, 'panel:buttonhide', {button: buttonNode, plugin: plugin, model: model});
        }, '[plugin-panel="true"] >div[is="header"] button, [plugin-panel="true"] >div[is="footer"] button, [plugin-panel="true"] >button');
    };

    setupEvents();

    /*
     * An object with several method to control stacked panels.
     *
     * @property stackManager
     * @type Object
     * @protected
     * @since 0.0.1
     */
    stackManager = DOCUMENT.stackManager = {
        elements: new LightMap(),
        isOnTop: function(host) {
            return (this.topElement===host);
        },
        setOnTop: function(host) {
            this.topElement = host;
        },
        registerModal: function(host) {
            var instance = this;
            instance.elements.set(host, true);
            instance.showModalLayer(true);
        },
        unRegisterModal: function(host) {
            var instance = this;
            instance.elements.delete(host);
            instance.hasModalElements() || instance.showModalLayer(false);
        },
        hasModalElements: function() {
            return (this.elements.size()>0);
        },
        showModalLayer: function(show) {
            var modalLayer = DOCUMENT.getElement('body >div[is="system-node"].itsa-modal-layer', true);
            modalLayer.toggleClass('itsa-no-display', !show);
        }
    };

    /*
     * Creates a new Panel-node which is prepended to body.
     *
     * @for document
     * @method createPanel
     * @param data {Object} the panel plugin's `model`-object
     * @param [systemNode] {boolean} whether the created node should be a systemnode
     * @return {HTMLElement} the created panelNode
     * @since 0.0.1
     */
    DOCUMENT.createPanel = function(data, systemNode) {
        var panel;
        if (!Object.isObject(data)) {
            console.warn('document.createPanel should be invoked with an object as first argument.');
            return;
        }
        if (systemNode) {
            panel = DOCUMENT.body.addSystemElement('

');
        }
        else {
            panel = DOCUMENT.body.prepend('

');
        }
        panel.plug('panel', null, data);
        return panel;
    };

    window._ITSAmodules.Panel = Panel = DOCUMENT.definePlugin('panel', function() {
        var instance = this,
            model = instance.model,
            host = instance.host,
            allDivs, serverHeader, serverContent, serverFooter;

        if (host.getAttr('panel-rendered')==='true') {
            // serverside rendered --> we might need to catch header, content and footer
            // for they aren't set in the attributes
            allDivs = host.getAll('>div');
            serverHeader = allDivs[0] && allDivs[0].getHTML();
            serverContent = allDivs[1] && allDivs[1].getHTML();
            serverFooter = allDivs[2] && allDivs[2].getHTML();
            serverHeader && instance.defineWhenUndefined('header', serverHeader);
            serverContent && instance.defineWhenUndefined('content', serverContent);
            if (serverFooter) {
                instance.defineWhenUndefined('footer', serverFooter);
            }
        }
        instance._resizeHandler = Event.after('UI:resize', function() {
            var isMobileWidth = (window.getWidth()<=480);
            model.center && instance.centerPanel();
            host[((model.draggable && !isMobileWidth) ? '' : 'un')+'plug']('dd');
            instance.setPanelWidth(isMobileWidth);
        });
    }, {
        /*
         * All panel's attributes: these attributes will be read during initalization and updated during `sync`
         * In the dom, the attributenames are prepended with `pluginName-`. The property-values should be the property-types
         * that belong to the property, this way the attributes get right casted into model.
         *
         * @property attrs
         * @default {
         *    visible: 'boolean',
         *    onTopWhenShowed: 'boolean',
         *    headerCloseBtn: 'boolean',
         *    stack: 'number',
         *    left: 'number',
         *    top: 'number',
         *    center: 'boolean',
         *    minWidth: 'number',
         *    maxWidth: 'number',
         *    minHeight: 'number',
         *    maxHeight: 'number',
         *    modal: 'boolean',
         *    draggable: 'boolean',
         *    focusmanaged: 'boolean'
         * }
         * @type Object
         * @since 0.0.1
        */
        attrs: {
            visible: 'boolean',
            onTopWhenShowed: 'boolean',
            headerCloseBtn: 'boolean',
            stack: 'number',
            left: 'number',
            top: 'number',
            center: 'boolean',
            minWidth: 'number',
            maxWidth: 'number',
            minHeight: 'number',
            maxHeight: 'number',
            modal: 'boolean',
            draggable: 'boolean',
            focusmanaged: 'boolean'
        },
        /*
         * Any default values for attributes specified by `attrs`.
         *
         * @property defaults
         * @default {
         *    visible: false,
         *    onTopWhenShowed: true,
         *    stack: 1,
         *    center: true,
         *    modal: true,
         *    focusmanaged: true,
         *    headerCloseBtn: false
         * }
         * @type Object
         * @since 0.0.1
        */
        defaults: {
            visible: false,
            onTopWhenShowed: true,
            stack: 1,
            center: true,
            modal: true,
            focusmanaged: true,
            headerCloseBtn: false
        },
        /*
         * Renders the plugin. This method is invoked only once: at the end of initialization.
         * It should be used to render any nodes inside the host. Not all plugins need this.
         *
         * @method render
         * @since 0.0.1
         */
        render: function() {
            var instance = this,
                host = instance.host,
                newContent;
            host.setClass('itsa-hidden');
            newContent = '

'+
                         '

'+
                         '

' +
                         '<button class="panel-close pure-button">x</button>';
            host.setHTML(newContent);
        },
        /*
         * Syncs plugin.model's data with the host. Not its attributes: they will be synced automaticly.
         * Is invoked after every change of plugin.model's data.
         *
         * @method sync
         * @since 0.0.1
         */
        sync: function() {
            var instance = this,
                host = instance.host,
                model = instance.model,
                header = model.header,
                content = model.content,
                footer = model.footer,
                stack = model.stack,
                divs = host.getAll('>div'),
                headerNode = divs[0],
                contentNode = divs[1],
                footerNode = divs[2],
                isMobileWidth = (window.getWidth()<=480),
                buttonCloseNode = host.getElement('>button'),
                showHeaderCloseBtn = model.headerCloseBtn,
                zIndex, isOnTop;
            (header==='undefined') && (header=undefined);
            (footer==='undefined') && (footer=undefined);
            if (!footer || !footer.contains('button')) {
                showHeaderCloseBtn = true;
            }
            if (showHeaderCloseBtn && !header) {
                header = '';
            }
            (header!==undefined) && headerNode.setHTML(header || '');
            buttonCloseNode.toggleClass('itsa-no-display', !showHeaderCloseBtn);

            headerNode.toggleClass('itsa-hidden', (header===undefined));
            contentNode.setHTML(content || '');
            contentNode.plug('scroll');
            (footer!==undefined) && footerNode.setHTML(footer || '');
            footerNode.toggleClass('itsa-hidden', (footer===undefined));

            zIndex = (model.modal ? MODAL_Z : PANEL_Z);

            if (model.visible && model.modal) {
                stackManager.registerModal(host);
            }
            else {
                stackManager.unRegisterModal(host);
            }

            if (model.onTopWhenShowed && model.visible && host.hasClass('itsa-hidden')) {
                instance.showOnTop();
            }

            isOnTop = stackManager.isOnTop(host);
            zIndex += isOnTop ? PANEL_TOP : stack;

            host.setInlineStyle('z-index', zIndex);

            model.minWidth && host.setInlineStyle('minWidth', model.minWidth);
            model.minHeight && host.setInlineStyle('minHeight', model.minHeight);
            model.maxHeight && host.setInlineStyle('maxHeight', model.maxHeight);
            instance.setPanelWidth(isMobileWidth);

            if (model.center && (!model.draggable || ((instance._previousVisible!==true) && model.visible))) {
                instance.centerPanel();
            }
            else if (!model.center && !host.hasClass('dd-dragging')) {
                host.setInlineStyles([
                    {property: 'left', value: model.left+'px'},
                    {property: 'top', value: model.top+'px'}
                ]);
            }
            // we can plug/unplug multiple times --> node-plugin won't do anything when there are no changes
            host[((model.draggable && !isMobileWidth) ? '' : 'un')+'plug']('dd');
            host[(model.focusmanaged ? '' : 'un')+'plug']('fm');
            host.toggleClass('itsa-full-draggable', model.draggable && !header);
            if (model.draggable && header) {
                 host.hasAttr('dd-handle') || host.setAttr('dd-handle', '>div:first-child');
            }
            else {
                 host.hasAttr('dd-handle') && host.removeAttr('dd-handle');
            }

            host.toggleClass('itsa-hidden', !model.visible);
            // if there is a change of model.visible, the fire an event:
            if (instance._previousVisible!==model.visible) {
                Event.emit(host, 'panel:'+ (model.visible ? 'shown' : 'hidden'), {plugin: instance, model: model});
                instance._previousVisible = model.visible;
            }
            if (isOnTop && model.modal) {
                host.focus();
            }
        },
        /*
         * Centeres the panel on the screen.
         *
         * @method centerPanel
         * @since 0.0.1
         */
        centerPanel: function() {
            var instance = this,
                host = instance.host,
                model = instance.model;
            model.left = Math.round((window.getWidth()-host.width)/2);
            model.top = Math.round((window.getHeight()-host.height)/2);
            host.setInlineStyles([
                {property: 'left', value: model.left+'px'},
                {property: 'top', value: model.top+'px'}
            ]);
        },
        /*
         * Sets the style `maxWidth` and the attribute `expand-buttons`. These need to be set after width-changes of either the panel or the screen.
         *
         * @method setPanelWidth
         * @param isMobileWidth {Boolean} whether the current screen-width is `mobile-width`
         * @since 0.0.1
         */
        setPanelWidth: function(isMobileWidth) {
            var instance = this,
                host = instance.host,
                model = instance.model;
            if (isMobileWidth) {
                host.hasInlineStyle('maxWidth') && host.removeInlineStyle('maxWidth');
                host.setAttr('expand-buttons', 'true');
            }
            else {
                if (model.maxWidth) {
                    host.setInlineStyle('maxWidth', model.maxWidth);
                    if (host.width>MAX_WIDTH_FULL_BUTTONS) {
                        host.removeAttr('expand-buttons');
                    }
                    else {
                        host.setAttr('expand-buttons', 'true');
                    }
                }
                else {
                     host.removeAttr('expand-buttons');
                }
            }
        },
        /*
         * Maes this panel as the `top`-panel of the stack.
         *
         * @method showOnTop
         * @since 0.0.1
         */
        showOnTop: function() {
            stackManager.setOnTop(this.host);
        },
        /*
         * Cleansup the plugin. Is invoked whenever a plugin gets unplugged or its host gets removed from the dom.
         *
         * @method destroy
         * @since 0.0.1
         */
        destroy: function() {
            var instance = this,
                host = instance.host;
            instance._resizeHandler.detach();
            host.removeInlineStyle('z-index');
            host.unplug('dd');
            host.unplug('fm');
            host.removeClass(['itsa-hidden', 'itsa-full-draggable']);
            stackManager.unRegisterModal(host);
            host.empty();
        }
    });

    return Panel;
};<commit_msg>changed its-no-display into its-nodisplay<commit_after>"use strict";
/**
 * Creating floating Panel-nodes which can be shown and hidden.
 *
 *
 * Copyright (c) 2014 ITSA - https://github.com/itsa
 * New BSD License - http://choosealicense.com/licenses/bsd-3-clause/
 *
 *
 * @module panel
 * @class Panel
 * @since 0.0.1
*/

require('js-ext/lib/object.js');
require('js-ext/lib/string.js');
require('polyfill');
require('./css/panel.css');

var NAME = '[panel]: ',
    PANEL_Z = 1000,
    MODAL_Z = 2000,
    PANEL_TOP = 999,
    MAX_WIDTH_FULL_BUTTONS = 150,
    createHashMap = require('js-ext/extra/hashmap.js').createMap;

module.exports = function (window) {

    var DOCUMENT = window.document,
        LightMap = require('js-ext/extra/lightmap.js'),
        Panel, Event, setupEvents, DD, stackManager, insertModalLayer;

    window._ITSAmodules || Object.protectedProp(window, '_ITSAmodules', createHashMap());

/*jshint boss:true */
    if (Panel=window._ITSAmodules.Panel) {
/*jshint boss:false */
        return Panel; // Panel was already created
    }

    require('window-ext')(window);
    require('node-plugin')(window);
    require('focusmanager')(window);
    require('scrollable')(window);

    Event = require('event-mobile')(window);
    DD = require('drag')(window);
    DD.init(); // ITSA combines the Drag-module with drag-drop into ITSA.DD

    /*
     * Generates a modal-layer.
     *
     * @method insertModalLayer
     * @protected
     * @since 0.0.1
     */
    insertModalLayer = function() {
       DOCUMENT.body.addSystemElement('

', null, true);
    };

    insertModalLayer();

    /*
     * Sets up all events needed for Panel's to work well.
     *
     * @method setupEvents
     * @protected
     * @since 0.0.1
     */
    setupEvents = function() {
        Event.defineEvent('panel:buttonhide').defaultFn(function(e) {
            var model = e.model;
            model.visible = false;
            (typeof model.callback==='function') && model.callback(e.button);
        });
        Event.before('panel:buttonhide', function(e) {
            var model = e.model;
            if (typeof model.validate==='function') {
                model.validate(e) || e.preventDefault();
            }
        });
        Event.after('tap', function(e) {
            var buttonNode = e.target,
                panelNode = buttonNode.inside('[plugin-panel="true"]'),
                plugin = panelNode._plugin.panel,
                model = plugin.model;
            Event.emit(panelNode, 'panel:buttonhide', {button: buttonNode, plugin: plugin, model: model});
        }, '[plugin-panel="true"] >div[is="header"] button, [plugin-panel="true"] >div[is="footer"] button, [plugin-panel="true"] >button');
    };

    setupEvents();

    /*
     * An object with several method to control stacked panels.
     *
     * @property stackManager
     * @type Object
     * @protected
     * @since 0.0.1
     */
    stackManager = DOCUMENT.stackManager = {
        elements: new LightMap(),
        isOnTop: function(host) {
            return (this.topElement===host);
        },
        setOnTop: function(host) {
            this.topElement = host;
        },
        registerModal: function(host) {
            var instance = this;
            instance.elements.set(host, true);
            instance.showModalLayer(true);
        },
        unRegisterModal: function(host) {
            var instance = this;
            instance.elements.delete(host);
            instance.hasModalElements() || instance.showModalLayer(false);
        },
        hasModalElements: function() {
            return (this.elements.size()>0);
        },
        showModalLayer: function(show) {
            var modalLayer = DOCUMENT.getElement('body >div[is="system-node"].itsa-modal-layer', true);
            modalLayer.toggleClass('itsa-nodisplay', !show);
        }
    };

    /*
     * Creates a new Panel-node which is prepended to body.
     *
     * @for document
     * @method createPanel
     * @param data {Object} the panel plugin's `model`-object
     * @param [systemNode] {boolean} whether the created node should be a systemnode
     * @return {HTMLElement} the created panelNode
     * @since 0.0.1
     */
    DOCUMENT.createPanel = function(data, systemNode) {
        var panel;
        if (!Object.isObject(data)) {
            console.warn('document.createPanel should be invoked with an object as first argument.');
            return;
        }
        if (systemNode) {
            panel = DOCUMENT.body.addSystemElement('

');
        }
        else {
            panel = DOCUMENT.body.prepend('

');
        }
        panel.plug('panel', null, data);
        return panel;
    };

    window._ITSAmodules.Panel = Panel = DOCUMENT.definePlugin('panel', function() {
        var instance = this,
            model = instance.model,
            host = instance.host,
            allDivs, serverHeader, serverContent, serverFooter;

        if (host.getAttr('panel-rendered')==='true') {
            // serverside rendered --> we might need to catch header, content and footer
            // for they aren't set in the attributes
            allDivs = host.getAll('>div');
            serverHeader = allDivs[0] && allDivs[0].getHTML();
            serverContent = allDivs[1] && allDivs[1].getHTML();
            serverFooter = allDivs[2] && allDivs[2].getHTML();
            serverHeader && instance.defineWhenUndefined('header', serverHeader);
            serverContent && instance.defineWhenUndefined('content', serverContent);
            if (serverFooter) {
                instance.defineWhenUndefined('footer', serverFooter);
            }
        }
        instance._resizeHandler = Event.after('UI:resize', function() {
            var isMobileWidth = (window.getWidth()<=480);
            model.center && instance.centerPanel();
            host[((model.draggable && !isMobileWidth) ? '' : 'un')+'plug']('dd');
            instance.setPanelWidth(isMobileWidth);
        });
    }, {
        /*
         * All panel's attributes: these attributes will be read during initalization and updated during `sync`
         * In the dom, the attributenames are prepended with `pluginName-`. The property-values should be the property-types
         * that belong to the property, this way the attributes get right casted into model.
         *
         * @property attrs
         * @default {
         *    visible: 'boolean',
         *    onTopWhenShowed: 'boolean',
         *    headerCloseBtn: 'boolean',
         *    stack: 'number',
         *    left: 'number',
         *    top: 'number',
         *    center: 'boolean',
         *    minWidth: 'number',
         *    maxWidth: 'number',
         *    minHeight: 'number',
         *    maxHeight: 'number',
         *    modal: 'boolean',
         *    draggable: 'boolean',
         *    focusmanaged: 'boolean'
         * }
         * @type Object
         * @since 0.0.1
        */
        attrs: {
            visible: 'boolean',
            onTopWhenShowed: 'boolean',
            headerCloseBtn: 'boolean',
            stack: 'number',
            left: 'number',
            top: 'number',
            center: 'boolean',
            minWidth: 'number',
            maxWidth: 'number',
            minHeight: 'number',
            maxHeight: 'number',
            modal: 'boolean',
            draggable: 'boolean',
            focusmanaged: 'boolean'
        },
        /*
         * Any default values for attributes specified by `attrs`.
         *
         * @property defaults
         * @default {
         *    visible: false,
         *    onTopWhenShowed: true,
         *    stack: 1,
         *    center: true,
         *    modal: true,
         *    focusmanaged: true,
         *    headerCloseBtn: false
         * }
         * @type Object
         * @since 0.0.1
        */
        defaults: {
            visible: false,
            onTopWhenShowed: true,
            stack: 1,
            center: true,
            modal: true,
            focusmanaged: true,
            headerCloseBtn: false
        },
        /*
         * Renders the plugin. This method is invoked only once: at the end of initialization.
         * It should be used to render any nodes inside the host. Not all plugins need this.
         *
         * @method render
         * @since 0.0.1
         */
        render: function() {
            var instance = this,
                host = instance.host,
                newContent;
            host.setClass('itsa-hidden');
            newContent = '

'+
                         '

'+
                         '

' +
                         '<button class="panel-close pure-button">x</button>';
            host.setHTML(newContent);
        },
        /*
         * Syncs plugin.model's data with the host. Not its attributes: they will be synced automaticly.
         * Is invoked after every change of plugin.model's data.
         *
         * @method sync
         * @since 0.0.1
         */
        sync: function() {
            var instance = this,
                host = instance.host,
                model = instance.model,
                header = model.header,
                content = model.content,
                footer = model.footer,
                stack = model.stack,
                divs = host.getAll('>div'),
                headerNode = divs[0],
                contentNode = divs[1],
                footerNode = divs[2],
                isMobileWidth = (window.getWidth()<=480),
                buttonCloseNode = host.getElement('>button'),
                showHeaderCloseBtn = model.headerCloseBtn,
                zIndex, isOnTop;
            (header==='undefined') && (header=undefined);
            (footer==='undefined') && (footer=undefined);
            if (!footer || !footer.contains('button')) {
                showHeaderCloseBtn = true;
            }
            if (showHeaderCloseBtn && !header) {
                header = '';
            }
            (header!==undefined) && headerNode.setHTML(header || '');
            buttonCloseNode.toggleClass('itsa-nodisplay', !showHeaderCloseBtn);

            headerNode.toggleClass('itsa-hidden', (header===undefined));
            contentNode.setHTML(content || '');
            contentNode.plug('scroll');
            (footer!==undefined) && footerNode.setHTML(footer || '');
            footerNode.toggleClass('itsa-hidden', (footer===undefined));

            zIndex = (model.modal ? MODAL_Z : PANEL_Z);

            if (model.visible && model.modal) {
                stackManager.registerModal(host);
            }
            else {
                stackManager.unRegisterModal(host);
            }

            if (model.onTopWhenShowed && model.visible && host.hasClass('itsa-hidden')) {
                instance.showOnTop();
            }

            isOnTop = stackManager.isOnTop(host);
            zIndex += isOnTop ? PANEL_TOP : stack;

            host.setInlineStyle('z-index', zIndex);

            model.minWidth && host.setInlineStyle('minWidth', model.minWidth);
            model.minHeight && host.setInlineStyle('minHeight', model.minHeight);
            model.maxHeight && host.setInlineStyle('maxHeight', model.maxHeight);
            instance.setPanelWidth(isMobileWidth);

            if (model.center && (!model.draggable || ((instance._previousVisible!==true) && model.visible))) {
                instance.centerPanel();
            }
            else if (!model.center && !host.hasClass('dd-dragging')) {
                host.setInlineStyles([
                    {property: 'left', value: model.left+'px'},
                    {property: 'top', value: model.top+'px'}
                ]);
            }
            // we can plug/unplug multiple times --> node-plugin won't do anything when there are no changes
            host[((model.draggable && !isMobileWidth) ? '' : 'un')+'plug']('dd');
            host[(model.focusmanaged ? '' : 'un')+'plug']('fm');
            host.toggleClass('itsa-full-draggable', model.draggable && !header);
            if (model.draggable && header) {
                 host.hasAttr('dd-handle') || host.setAttr('dd-handle', '>div:first-child');
            }
            else {
                 host.hasAttr('dd-handle') && host.removeAttr('dd-handle');
            }

            host.toggleClass('itsa-hidden', !model.visible);
            // if there is a change of model.visible, the fire an event:
            if (instance._previousVisible!==model.visible) {
                Event.emit(host, 'panel:'+ (model.visible ? 'shown' : 'hidden'), {plugin: instance, model: model});
                instance._previousVisible = model.visible;
            }
            if (isOnTop && model.modal) {
                host.focus();
            }
        },
        /*
         * Centeres the panel on the screen.
         *
         * @method centerPanel
         * @since 0.0.1
         */
        centerPanel: function() {
            var instance = this,
                host = instance.host,
                model = instance.model;
            model.left = Math.round((window.getWidth()-host.width)/2);
            model.top = Math.round((window.getHeight()-host.height)/2);
            host.setInlineStyles([
                {property: 'left', value: model.left+'px'},
                {property: 'top', value: model.top+'px'}
            ]);
        },
        /*
         * Sets the style `maxWidth` and the attribute `expand-buttons`. These need to be set after width-changes of either the panel or the screen.
         *
         * @method setPanelWidth
         * @param isMobileWidth {Boolean} whether the current screen-width is `mobile-width`
         * @since 0.0.1
         */
        setPanelWidth: function(isMobileWidth) {
            var instance = this,
                host = instance.host,
                model = instance.model;
            if (isMobileWidth) {
                host.hasInlineStyle('maxWidth') && host.removeInlineStyle('maxWidth');
                host.setAttr('expand-buttons', 'true');
            }
            else {
                if (model.maxWidth) {
                    host.setInlineStyle('maxWidth', model.maxWidth);
                    if (host.width>MAX_WIDTH_FULL_BUTTONS) {
                        host.removeAttr('expand-buttons');
                    }
                    else {
                        host.setAttr('expand-buttons', 'true');
                    }
                }
                else {
                     host.removeAttr('expand-buttons');
                }
            }
        },
        /*
         * Maes this panel as the `top`-panel of the stack.
         *
         * @method showOnTop
         * @since 0.0.1
         */
        showOnTop: function() {
            stackManager.setOnTop(this.host);
        },
        /*
         * Cleansup the plugin. Is invoked whenever a plugin gets unplugged or its host gets removed from the dom.
         *
         * @method destroy
         * @since 0.0.1
         */
        destroy: function() {
            var instance = this,
                host = instance.host;
            instance._resizeHandler.detach();
            host.removeInlineStyle('z-index');
            host.unplug('dd');
            host.unplug('fm');
            host.removeClass(['itsa-hidden', 'itsa-full-draggable']);
            stackManager.unRegisterModal(host);
            host.empty();
        }
    });

    return Panel;
};<|endoftext|>


<commit_before>var Staccato = require('staccato')
var cadence = require('cadence')

module.exports = cadence(function (async, syslog, input, output) {
    var loop = async(function () {
        async(function () {
            input.read(async())
        }, function (line) {
            if (line == null) {
                return [ loop.break ]
            }
            output.write(JSON.stringify(syslog(line.toString())), async())
        })
    })()
})
<commit_msg>Append newline to serialized JSON.<commit_after>var Staccato = require('staccato')
var cadence = require('cadence')

module.exports = cadence(function (async, syslog, input, output) {
    var loop = async(function () {
        async(function () {
            input.read(async())
        }, function (line) {
            if (line == null) {
                return [ loop.break ]
            }
            output.write(JSON.stringify(syslog(line.toString())) + '\n', async())
        })
    })()
})
<|endoftext|>


<commit_before>const util = require('util')
const cp = require('child_process')
const fs = require('fs')
const path = require('path')
const { remote: { app } } = require('electron')

//const writeFile = util.promisify(fs.writeFile)

const TMP_FILE = `${app.getPath('userData')}/output.json`

/*async*/ function parse (filename) {
  return new Promise((resolve, reject) => {
    cp.exec(`rattletrap decode "${filename}" "${TMP_FILE}"`, function (error, stdout, stderr) {
      if (stderr) {
        reject(stderr)
      }

      const body = fs.readFileSync(path.resolve(TMP_FILE))

      resolve(JSON.parse(body))
    })
  })
  //const { stdout, stderr } = await exec(`${RT} decode ${filename} ${TMP_FILE}`)
}

function filter (tree) {
  return {
    playerStats: getPlayerStats(tree)
  }
}

function getPlayerStats (tree) {
  let players = tree.header.properties.value.PlayerStats.value.array_property

  players = players.map(player => {
    // TODO
    // const player = _.cloneDeep(player)

    player = getValues(player)
    player.Platform = player.Platform[player.Platform.length - 1]
    return player
  })

  return players
  //console.log(JSON.stringify(players, null, '\t'))
}

function getValues (o) {
  const mapped = {}

  o.keys.forEach(k => {
    const wrapped = o.value[k].value

    if (Object.keys(wrapped).length !== 1) {
      console.warn(`Expected a property to have one key, but it looks like:\n${JSON.stringify(wrapped)}`)
    }

    mapped[k] = wrapped[Object.keys(wrapped)[0]]
  })

  return mapped
}

const columns = [
  'Name', 'Team', /*'MVPs',*/ 'Pts', 'Goals', 'Assists', 'Saves', 'Shots'
]

const aliases = {
  Pts: 'Score'
}

function spreadsheet (games, paths, delimiter = '\t') {
  const headers = columns.map(column => {
    return `"${column}"`
  }).concat('Filename').join(delimiter)

  const players = games.map((playerStats, i) => {
    return playerStats.sort((a, b) => {
      return (a.Team - b.Team) || (b.Score - a.Score)
    }).map(player => {
      return columns.map(column => {
        let prop = aliases[column]
        if (typeof prop === 'undefined') {
          prop = column
        }
        /*if (typeof value === 'undefined') {
        value = ''
      }*/
        const value = typeof player[prop] === 'undefined' ? '' : player[prop]
        return `"${value}"`
      }).concat(paths[i]).join(delimiter)
    })
  })

  return [headers].concat(flatten(players)).join('\r\n')
}

const inputDirectory = process.argv[2]

module.exports = function (/*inputDirectory,*/inputFiles) {
  /*Promise.all(fs.readdirSync(path.resolve(inputDirectory))*/

  const paths = inputFiles
    .filter(filename => !!filename.match(/\.replay$/))
    .map(f => path.resolve(/*inputDirectory,*/process.cwd, f))

    // Serially parse each path and add the results to an array that this
    // promise resolves with.
    const resultsPromise = paths.reduce((memo, path) => {
      return memo.then(results => {
        return parse(path)
          .then(singleResult => {
            results.push(singleResult)
            return Promise.resolve(results)
          })
      })
    }, Promise.resolve([]))

  return resultsPromise
    .then(results => {
      const gameStats = results
        .map(filter)
        .map(f => f.playerStats)
      return spreadsheet(gameStats, paths)
    })

}

function flatten (arrays) {
  return arrays.reduce(
    ( acc, cur ) => acc.concat(cur),
    []
  );
}
<commit_msg>Use just the filename, not the full path<commit_after>const util = require('util')
const cp = require('child_process')
const fs = require('fs')
const path = require('path')
const { remote: { app } } = require('electron')

//const writeFile = util.promisify(fs.writeFile)

const TMP_FILE = `${app.getPath('userData')}/output.json`

/*async*/ function parse (filename) {
  return new Promise((resolve, reject) => {
    cp.exec(`rattletrap decode "${filename}" "${TMP_FILE}"`, function (error, stdout, stderr) {
      if (stderr) {
        reject(stderr)
      }

      const body = fs.readFileSync(path.resolve(TMP_FILE))

      resolve(JSON.parse(body))
    })
  })
  //const { stdout, stderr } = await exec(`${RT} decode ${filename} ${TMP_FILE}`)
}

function filter (tree) {
  return {
    playerStats: getPlayerStats(tree)
  }
}

function getPlayerStats (tree) {
  let players = tree.header.properties.value.PlayerStats.value.array_property

  players = players.map(player => {
    // TODO
    // const player = _.cloneDeep(player)

    player = getValues(player)
    player.Platform = player.Platform[player.Platform.length - 1]
    return player
  })

  return players
  //console.log(JSON.stringify(players, null, '\t'))
}

function getValues (o) {
  const mapped = {}

  o.keys.forEach(k => {
    const wrapped = o.value[k].value

    if (Object.keys(wrapped).length !== 1) {
      console.warn(`Expected a property to have one key, but it looks like:\n${JSON.stringify(wrapped)}`)
    }

    mapped[k] = wrapped[Object.keys(wrapped)[0]]
  })

  return mapped
}

const columns = [
  'Name', 'Team', /*'MVPs',*/ 'Pts', 'Goals', 'Assists', 'Saves', 'Shots'
]

const aliases = {
  Pts: 'Score'
}

function spreadsheet (games, paths, delimiter = '\t') {
  const headers = columns.map(column => {
    return `"${column}"`
  }).concat('"Filename"').join(delimiter)

  const players = games.map((playerStats, i) => {
    return playerStats.sort((a, b) => {
      return (a.Team - b.Team) || (b.Score - a.Score)
    }).map(player => {
      return columns.map(column => {
        let prop = aliases[column]
        if (typeof prop === 'undefined') {
          prop = column
        }
        /*if (typeof value === 'undefined') {
        value = ''
      }*/
        const value = typeof player[prop] === 'undefined' ? '' : player[prop]
        return `"${value}"`
      }).concat(`"${path.basename(paths[i])}"`).join(delimiter)
    })
  })

  return [headers].concat(flatten(players)).join('\r\n')
}

const inputDirectory = process.argv[2]

module.exports = function (/*inputDirectory,*/inputFiles) {
  /*Promise.all(fs.readdirSync(path.resolve(inputDirectory))*/

  const paths = inputFiles
    .filter(filename => !!filename.match(/\.replay$/))
    .map(f => path.resolve(/*inputDirectory,*/process.cwd, f))

    // Serially parse each path and add the results to an array that this
    // promise resolves with.
    const resultsPromise = paths.reduce((memo, path) => {
      return memo.then(results => {
        return parse(path)
          .then(singleResult => {
            results.push(singleResult)
            return Promise.resolve(results)
          })
      })
    }, Promise.resolve([]))

  return resultsPromise
    .then(results => {
      const gameStats = results
        .map(filter)
        .map(f => f.playerStats)
      return spreadsheet(gameStats, paths)
    })

}

function flatten (arrays) {
  return arrays.reduce(
    ( acc, cur ) => acc.concat(cur),
    []
  );
}
<|endoftext|>


<commit_before>var Router = Backbone.Router.extend({

	routes: {
		'' : 'home',
		'profile': 'profilePage',
		'art-list-temeraire': 'artListTemerairePage',
		'art-list-coquin': 'artListCoquinPage',
		'explanation': 'explanationPage',
		'artworkTemeraire': 'artworkTemerairePage',
		'artworkCoquin': 'artworkCoquinPage',

	},

	initialize: function() {
	  this.bind('route', this._pageView);
	},

	home:function() {
		home.render();
		appModel.set('nextRoute', 'profile');
		$('.timer').html('');
	},

	profilePage: function() {
		header.render();
		footer.render();
		var profile = new profileView();
		profile.render();

		appModel.set('startTimer', false);
		appModel.set('nextRoute', 'explanation');
	},

	artListTemerairePage: function() {
		var artListTemeraire = new artListTemeraireView();
		artListTemeraire.render();

		var startedTimer = appModel.get('startTimer');

		if (!startedTimer) {
			var timer = new timerView();
			timer.render();
			timer.startTimer();
			appModel.set('startTimer', true);
		}

		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');
	},

	artListCoquinPage: function() {
		var artListCoquin = new artListCoquinView();
		artListCoquin.render();

		var startedTimer = appModel.get('startTimer');

		if (!startedTimer) {
			var timer = new timerView();
			timer.render();
			timer.startTimer();
			appModel.set('startTimer', true);
		}

		appModel.set('headerTitle', 'coquin');
		appModel.set('headerColor', '9a4d9e');
	},

	explanationPage: function() {
		appModel.set('headerTitle', 'prototype');
		appModel.set('headerColor', '3e3e3e');
		appModel.set('startTimer', false);

		var explanation = new explanationView();
		explanation.render();
	},
	artworkTemerairePage: function() {
		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');

		var artworkTemeraire = new artworkTemeraireView();
		artworkTemeraire.render();

		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');
	},

	artworkCoquinPage: function() {
		appModel.set('headerTitle', 'Coquin');
		appModel.set('headerColor', 'ec462f');

		var artworkCoquin = new artworkCoquinView();
		artworkCoquin.render();

		appModel.set('headerTitle', 'coquin');
		appModel.set('headerColor', '9a4d9e');
	}

});<commit_msg>Fixed minor bugs with timer<commit_after>var Router = Backbone.Router.extend({

	routes: {
		'' : 'home',
		'profile': 'profilePage',
		'art-list-temeraire': 'artListTemerairePage',
		'art-list-coquin': 'artListCoquinPage',
		'explanation': 'explanationPage',
		'artworkTemeraire': 'artworkTemerairePage',
		'artworkCoquin': 'artworkCoquinPage',

	},

	initialize: function() {
	  this.bind('route', this._pageView);
	},

	home:function() {
		home.render();
		appModel.set('nextRoute', 'profile');
		$('.timer').html('');
	},

	profilePage: function() {
		header.render();
		footer.render();
		var profile = new profileView();
		profile.render();

		appModel.set('startTimer', false);
		appModel.set('nextRoute', 'explanation');
		$('.timer').html('');
	},

	artListTemerairePage: function() {
		var artListTemeraire = new artListTemeraireView();
		artListTemeraire.render();

		var startedTimer = appModel.get('startTimer');

		if (!startedTimer) {
			var timer = new timerView();
			timer.render();
			timer.startTimer();
			appModel.set('startTimer', true);
		}

		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');
	},

	artListCoquinPage: function() {
		var artListCoquin = new artListCoquinView();
		artListCoquin.render();

		var startedTimer = appModel.get('startTimer');

		if (!startedTimer) {
			var timer = new timerView();
			timer.render();
			timer.startTimer();
			appModel.set('startTimer', true);
		}

		appModel.set('headerTitle', 'coquin');
		appModel.set('headerColor', '9a4d9e');
	},

	explanationPage: function() {
		appModel.set('headerTitle', 'prototype');
		appModel.set('headerColor', '3e3e3e');
		appModel.set('startTimer', false);

		var explanation = new explanationView();
		explanation.render();
		$('.timer').html('');
	},
	artworkTemerairePage: function() {
		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');

		var artworkTemeraire = new artworkTemeraireView();
		artworkTemeraire.render();

		appModel.set('headerTitle', 'téméraire');
		appModel.set('headerColor', 'ec462f');
	},

	artworkCoquinPage: function() {
		appModel.set('headerTitle', 'Coquin');
		appModel.set('headerColor', 'ec462f');

		var artworkCoquin = new artworkCoquinView();
		artworkCoquin.render();

		appModel.set('headerTitle', 'coquin');
		appModel.set('headerColor', '9a4d9e');
	}

});<|endoftext|>


<commit_before>import { PureComponent, createElement } from 'react';
import { connect } from 'react-redux';
import Proptypes from 'prop-types';
import { withRouter } from 'react-router';
import isEmpty from 'lodash/isEmpty';
import { actions as modalMetadataActions } from 'components/modal-metadata';
import ownActions from './country-ndc-overview-actions';
import reducers, { initialState } from './country-ndc-overview-reducers';

import CountryNdcOverviewComponent from './country-ndc-overview-component';
import { getValuesGrouped } from './country-ndc-overview-selectors';

const actions = {
  ...modalMetadataActions,
  ...ownActions
};

const mapStateToProps = (state, { match }) => {
  const { iso } = match.params;
  const overviewData = state.countryNDCOverview.data;
  const countryData = overviewData ? overviewData[iso] : null;
  return {
    iso,
    values: getValuesGrouped(countryData),
    loading: state.countryNDCOverview.loading,
    sectors: countryData ? countryData.sectors : null,
    fetched: !isEmpty(countryData)
  };
};

class CountryNdcOverviewContainer extends PureComponent {
  componentWillMount() {
    const { match, loading, fetched, fetchCountryNdcOverviewData } = this.props;
    const { iso } = match.params;
    if (iso && !loading && !fetched) {
      fetchCountryNdcOverviewData(iso);
    }
  }

  handleInfoClick = () => {
    this.props.setModalMetadata({
      slugs: ['ndc_quantification_UNDP', 'ndc_quantification_WRI'],
      customTitle: 'Nationally Determined Contribution (NDC) Overview',
      open: true
    });
  };

  render() {
    return createElement(CountryNdcOverviewComponent, {
      ...this.props,
      handleInfoClick: this.handleInfoClick
    });
  }
}

CountryNdcOverviewContainer.propTypes = {
  match: Proptypes.object.isRequired,
  loading: Proptypes.bool,
  fetchCountryNdcOverviewData: Proptypes.func,
  fetched: Proptypes.bool,
  setModalMetadata: Proptypes.func.isRequired
};

export { actions, reducers, initialState };

export default withRouter(
  connect(mapStateToProps, actions)(CountryNdcOverviewContainer)
);
<commit_msg>Correct slugs for metadata<commit_after>import { PureComponent, createElement } from 'react';
import { connect } from 'react-redux';
import Proptypes from 'prop-types';
import { withRouter } from 'react-router';
import isEmpty from 'lodash/isEmpty';
import { actions as modalMetadataActions } from 'components/modal-metadata';
import ownActions from './country-ndc-overview-actions';
import reducers, { initialState } from './country-ndc-overview-reducers';

import CountryNdcOverviewComponent from './country-ndc-overview-component';
import { getValuesGrouped } from './country-ndc-overview-selectors';

const actions = {
  ...modalMetadataActions,
  ...ownActions
};

const mapStateToProps = (state, { match }) => {
  const { iso } = match.params;
  const overviewData = state.countryNDCOverview.data;
  const countryData = overviewData ? overviewData[iso] : null;
  return {
    iso,
    values: getValuesGrouped(countryData),
    loading: state.countryNDCOverview.loading,
    sectors: countryData ? countryData.sectors : null,
    fetched: !isEmpty(countryData)
  };
};

class CountryNdcOverviewContainer extends PureComponent {
  componentWillMount() {
    const { match, loading, fetched, fetchCountryNdcOverviewData } = this.props;
    const { iso } = match.params;
    if (iso && !loading && !fetched) {
      fetchCountryNdcOverviewData(iso);
    }
  }

  handleInfoClick = () => {
    this.props.setModalMetadata({
      slugs: ['ndc_cait', 'ndc_wb'],
      customTitle: 'Nationally Determined Contribution (NDC) Overview',
      open: true
    });
  };

  render() {
    return createElement(CountryNdcOverviewComponent, {
      ...this.props,
      handleInfoClick: this.handleInfoClick
    });
  }
}

CountryNdcOverviewContainer.propTypes = {
  match: Proptypes.object.isRequired,
  loading: Proptypes.bool,
  fetchCountryNdcOverviewData: Proptypes.func,
  fetched: Proptypes.bool,
  setModalMetadata: Proptypes.func.isRequired
};

export { actions, reducers, initialState };

export default withRouter(
  connect(mapStateToProps, actions)(CountryNdcOverviewContainer)
);
<|endoftext|>


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

// Initialize ridb client and get all facilities within 100 miles of Syracuse, NY that allow camping.
ridb.init('your-api-key');
ridb.facilities.getAll({latitude: 43.0469, longitude: -76.1444, radius: 100, activity: '9,109', limit: 1}, function(error, response){
        console.log(JSON.stringify(response));
});<commit_msg>Updated sample<commit_after>var ridb = require('./index');

// Initialize RIDB client.
var key = process.argv[2];
ridb.init(key);

// Get a list of facilities.
ridb.facilities.details(null, {limit: 3}, function(error, response) {
	if(!error) {
		console.log(JSON.stringify(response));
	}
});

// // Get the details of a specific facility.
ridb.facilities.details(234150, {}, function(error, response) {
	if(!error) {
		console.log(JSON.stringify(response));
	}
});

// // Get address details for a specific facility
ridb.facilities.addresses(234150, null, {}, function(error, response) {
	if(!error) {
		console.log(JSON.stringify(response));
	}
});

// Get a list of activities for a specific facility.
ridb.facilities.activities(234150, null, {}, function(error, response) {
	if(!error) {
		console.log(JSON.stringify(response));
	}
});<|endoftext|>