<commit_before>define(['jquery', 'DoughBaseComponent'],
  function ($, DoughBaseComponent) {
    'use strict';

    var ChatPopup,
      defaultConfig = {
        scrollThrottle: 200,
        scrollLimit: 700,
        hiddenClass: 'mobile-webchat--hide'
      };

    ChatPopup = function ($el, config) {
      ChatPopup.baseConstructor.call(this, $el, config, defaultConfig);

      this.chatPopupBtn = $el;
      this.chatPopupIcon = $el.find('[data-dough-webchat-icon]');
      this.chatPopupClose = $el.find('[data-dough-webchat-close]');
      this.popupElements = $el.children().not('[data-dough-webchat-icon]');
      this.serviceSelect = $el.find('[data-dough-webchat-select]');
      this.whatsappBtn = $el.find('[data-dough-webchat-button-whatsapp]');
      this.webchatBtn = $el.find('[data-dough-webchat-button-webchat]');

    };

    /**
     * Inherit from base module, for shared methods and interface
     */
    DoughBaseComponent.extend(ChatPopup);

    ChatPopup.componentName = 'ChatPopup';

    ChatPopup.prototype._setupListeners = function () {
      var self = this;
      // on icon click open popup
      this.chatPopupIcon.click(function (event) {
        event.preventDefault();
        self._togglePopup();
        self._manageTransition(1);
      });
      // on X click close popup
      this.chatPopupClose.click(function (event) {
        event.preventDefault();
        self._togglePopup();
        self._manageTransition(0);
        self._setScrollLimits();
      });
      // on select change
      this.serviceSelect.change(function(event) {
        if(event.target.value === 'debt-and-borrowing' || event.target.value === 'pensions-and-retirement') {
          self.whatsappBtn.removeClass('is-hidden');
        } else {
          self.whatsappBtn.addClass('is-hidden');
        }
      });

      // on scroll hide
      $(window).scroll($.throttle(defaultConfig.scrollThrottle, function() {
        // past scroll limits
        if(self._hideChatPopup()) self.chatPopupBtn.addClass(defaultConfig.hiddenClass);
        // completely hide when contact panels are reached
        self._reachedContactPanels() ? self.chatPopupBtn.addClass('is-hidden') : self.chatPopupBtn.removeClass('is-hidden');
      }));
      // on left border click reveal popup
      this.chatPopupBtn.click(function(event){
        // left border x-axis offset
        if(event.offsetX < 20 && self.chatPopupBtn.hasClass(defaultConfig.hiddenClass)) {
          self.chatPopupBtn.removeClass(defaultConfig.hiddenClass);
          self._setScrollLimits();
        }
      });
    };

    ChatPopup.prototype._setScrollLimits = function () {
      this.scrollLimitTop = this._getScrollAmount() - defaultConfig.scrollLimit;
      this.scrollLimitBottom = this._getScrollAmount() + defaultConfig.scrollLimit;
      if(this.scrollLimitTop < 0) this.scrollLimitTop = 0;
      // define offset for bottom contact panels
      this.contactPanelsOffset = $('[data-dough-contact-panels]').offset().top - $(window).innerHeight();
    };

    ChatPopup.prototype._hideChatPopup = function () {
      if(!this.chatPopupBtn.hasClass(defaultConfig.hiddenClass) && this.chatPopupBtn.hasClass('mobile-webchat--closed')){
        return this._getScrollAmount() < this.scrollLimitTop ||  this._getScrollAmount() > this.scrollLimitBottom;
      }
    };

    ChatPopup.prototype._reachedContactPanels = function () {
      return $(window).scrollTop() > this.contactPanelsOffset && this.chatPopupBtn.hasClass(defaultConfig.hiddenClass);
    };

    ChatPopup.prototype._getScrollAmount = function() {
      return $(window).scrollTop();
    };

    ChatPopup.prototype._manageTransition = function (opacity) {
      var self = this;
      setTimeout(function () {
        $.each(self.popupElements, function (index, value) {
          value.style.opacity = opacity;
          value.style.filter = "alpha(opacity=" + opacity + "00)"; // IE fallback
        });
      }, 100);
    };

    ChatPopup.prototype._togglePopup = function () {
      this.chatPopupBtn.toggleClass('mobile-webchat--opened').toggleClass('mobile-webchat--closed');
    };

    /**
     * Public method imported in BackToTop.js to manage popup vertical position in article pages
     * @param {boolean} raised - set button raised state
     * @param {boolean} atSmallViewport - viewport width < 720px
     */
    ChatPopup.prototype._raisedChatPopup = function (raised, atSmallViewport) {
      var raisedPopup = raised && atSmallViewport;
      // check if conditions are met
      if (raisedPopup) {
        this.chatPopupBtn.addClass('mobile-webchat--raised')
      } else {
        this.chatPopupBtn.removeClass('mobile-webchat--raised')
      };
    }

    /**
     * @param {Promise} initialised
     */
    ChatPopup.prototype.init = function (initialised) {
      this._setScrollLimits();
      this._setupListeners();
      this._initialisedSuccess(initialised);
    };

    return ChatPopup;
  });
<commit_msg>10483 fix tests (#334)<commit_after>define(['jquery', 'DoughBaseComponent'],
  function($, DoughBaseComponent) {
    'use strict';

    var ChatPopup,
      defaultConfig = {
        scrollThrottle: 200,
        scrollLimit: 700,
        hiddenClass: 'mobile-webchat--hide'
      };

    ChatPopup = function($el, config) {
      ChatPopup.baseConstructor.call(this, $el, config, defaultConfig);

      this.chatPopupBtn = $el;
      this.chatPopupIcon = $el.find('[data-dough-webchat-icon]');
      this.chatPopupClose = $el.find('[data-dough-webchat-close]');
      this.popupElements = $el.children().not('[data-dough-webchat-icon]');
      this.serviceSelect = $el.find('[data-dough-webchat-select]');
      this.whatsappBtn = $el.find('[data-dough-webchat-button-whatsapp]');
      this.webchatBtn = $el.find('[data-dough-webchat-button-webchat]');

    };

    /**
     * Inherit from base module, for shared methods and interface
     */
    DoughBaseComponent.extend(ChatPopup);

    ChatPopup.componentName = 'ChatPopup';

    ChatPopup.prototype._setupListeners = function() {
      var self = this;
      // on icon click open popup
      this.chatPopupIcon.click(function(event) {
        event.preventDefault();
        self._togglePopup();
        self._manageTransition(1);
      });
      // on X click close popup
      this.chatPopupClose.click(function(event) {
        event.preventDefault();
        self._togglePopup();
        self._manageTransition(0);
        self._setScrollLimits();
      });
      // on select change
      this.serviceSelect.change(function(event) {
        if (event.target.value === 'debt-and-borrowing' || event.target.value === 'pensions-and-retirement') {
          self.whatsappBtn.removeClass('is-hidden');
        } else {
          self.whatsappBtn.addClass('is-hidden');
        }
      });

      // on scroll hide
      $(window).scroll($.throttle(defaultConfig.scrollThrottle, function() {
        // past scroll limits
        if (self._hideChatPopup()) {
          self.chatPopupBtn.addClass(defaultConfig.hiddenClass);
        }
        // completely hide when contact panels are reached
        self._reachedContactPanels() ? self.chatPopupBtn.addClass('is-hidden') : self.chatPopupBtn.removeClass('is-hidden');
      }));
      // on left border click reveal popup
      this.chatPopupBtn.click(function(event) {
        // left border x-axis offset
        if (event.offsetX < 20 && self.chatPopupBtn.hasClass(defaultConfig.hiddenClass)) {
          self.chatPopupBtn.removeClass(defaultConfig.hiddenClass);
          self._setScrollLimits();
        }
      });
    };

    ChatPopup.prototype._setScrollLimits = function() {
      this.scrollLimitTop = this._getScrollAmount() - defaultConfig.scrollLimit;
      this.scrollLimitBottom = this._getScrollAmount() + defaultConfig.scrollLimit;
      if (this.scrollLimitTop < 0) {
        this.scrollLimitTop = 0;
      }
      // define offset for bottom contact panels
      this.contactPanelsOffset = $('[data-dough-contact-panels]').offset().top - $(window).innerHeight();
    };

    ChatPopup.prototype._hideChatPopup = function() {
      if (!this.chatPopupBtn.hasClass(defaultConfig.hiddenClass) && this.chatPopupBtn.hasClass('mobile-webchat--closed')){
        return this._getScrollAmount() < this.scrollLimitTop ||  this._getScrollAmount() > this.scrollLimitBottom;
      }
    };

    ChatPopup.prototype._reachedContactPanels = function() {
      return $(window).scrollTop() > this.contactPanelsOffset && this.chatPopupBtn.hasClass(defaultConfig.hiddenClass);
    };

    ChatPopup.prototype._getScrollAmount = function() {
      return $(window).scrollTop();
    };

    ChatPopup.prototype._manageTransition = function(opacity) {
      var self = this;
      setTimeout(function() {
        $.each(self.popupElements, function(index, value) {
          value.style.opacity = opacity;
          value.style.filter = "alpha(opacity=" + opacity + "00)"; // IE fallback
        });
      }, 100);
    };

    ChatPopup.prototype._togglePopup = function() {
      this.chatPopupBtn.toggleClass('mobile-webchat--opened').toggleClass('mobile-webchat--closed');
    };

    /**
     * Public method imported in BackToTop.js to manage popup vertical position in article pages
     * @param {boolean} raised - set button raised state
     * @param {boolean} atSmallViewport - viewport width < 720px
     */
    ChatPopup.prototype._raisedChatPopup = function(raised, atSmallViewport) {
      var raisedPopup = raised && atSmallViewport;
      // check if conditions are met
      if (raisedPopup) {
        this.chatPopupBtn.addClass('mobile-webchat--raised')
      } else {
        this.chatPopupBtn.removeClass('mobile-webchat--raised')
      };
    }

    /**
     * @param {Promise} initialised
     */
    ChatPopup.prototype.init = function(initialised) {
      this._setScrollLimits();
      this._setupListeners();
      this._initialisedSuccess(initialised);
    };

    return ChatPopup;
  });
<|endoftext|>


<commit_before>module.exports = {

  updateInfo: function (req, res) {
    var result = {}
    var iTunesItemIdentifier = '1002185140'
    var forceUpdate = {
      type: 'force',
      title: 'A new version of the app is available',
      iTunesItemIdentifier
    }
    var suggestUpdate = {
      type: 'suggest',
      title: 'An update is available',
      iTunesItemIdentifier
    }

    /*
    Format for result:
    result = {
      type: 'force',  // can be 'force' or 'suggest'
      title: 'A new version of the app is available',
      message: 'You can go to the App Store now to update',
      iTunesItemIdentifier: '1002185140'
    }
    */
    switch (req.param('ios-version')) {
      case '2.0':
        result = Object.assign(
          suggestUpdate,
          { message: 'The version you are using is not longer up to date. Please go to the App Store to update.' }
        )
        break
      case '1.65':
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
        break
      case undefined:
        break
      default:
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
    }

    switch (req.param('android-version')) {
      case '2.0':
        result = Object.assign(
          suggestUpdate,
          { message: 'The version you are using is not longer up to date. Please go to the App Store to update.' }
        )
        break
      case '1.65':
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
        break
      case undefined:
        break
      default:
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
    }
    res.ok(result)
  }
}
<commit_msg>Comment out suggested updates, but leave for future development<commit_after>module.exports = {

  updateInfo: function (req, res) {
    var result = {}
    var iTunesItemIdentifier = '1002185140'
    var forceUpdate = {
      type: 'force',
      title: 'A new version of the app is available',
      iTunesItemIdentifier
    }
    var suggestUpdate = {
      type: 'suggest',
      title: 'An update is available',
      iTunesItemIdentifier
    }

    /*
    Format for result:
    result = {
      type: 'force',  // can be 'force' or 'suggest'
      title: 'A new version of the app is available',
      message: 'You can go to the App Store now to update',
      iTunesItemIdentifier: '1002185140'
    }
    */
    switch (req.param('ios-version')) {
      // case '2.0':
      //   result = Object.assign(
      //     suggestUpdate,
      //     { message: 'The version you are using is not longer up to date. Please go to the App Store to update.' }
      //   )
      //   break
      case '1.9':
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
        break
      case undefined:
        break
      default:
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
    }

    switch (req.param('android-version')) {
      // case '1.9':
      //   result = Object.assign(
      //     suggestUpdate,
      //     { message: 'The version you are using is not longer up to date. Please go to the App Store to update.' }
      //   )
      //   break
      case '1.9':
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
        break
      case undefined:
        break
      default:
        result = Object.assign(
          forceUpdate,
          { message: 'The version you are using is no longer compatible with the site. Please go to the App Store now to update' }
        )
    }
    res.ok(result)
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('mean.system')
.controller('IndexController', ['$scope', 'Global', function ($scope, Global) {
    $scope.global = Global;
}])
.controller('CreatureController', ['$scope', 'Global', 'socket', function ($scope, Global, socket) {
    $scope.global = Global;
	$scope.battleStartUsers = [];
	var username = window.user.username;

	/**
	 * Update users waiting for game
	 */
	socket.emit('start', username);
	socket.on('echo', function() {
		socket.emit('prev_connected', username);
	});
	socket.on('join', function (user) {
		console.log( 'join ' + user);
		if ($scope.battleStartUsers.indexOf(user) === -1)
		$scope.battleStartUsers.push(user);
	});
	socket.on('prev_connected', function (user) {
		console.log( 'prev_connected ' + user);
		if ($scope.battleStartUsers.indexOf(user) === -1)
		$scope.battleStartUsers.push(user);
	});

	$scope.initGame = function (user) {
		console.log((new Date()).toString());
		socket.emit('initGame', {user: user, room: (new Date()).toString()});
	};

	socket.on('initGame', function(data) {
		if (data.user === username) {
			window.gameConnection = data;
			socket.removeremoveAllListeners();
			data.user = username;
			socket.emit('joinGame', data);
		}
	});

	socket.on('gameConnection', function(data) {
		window.gameConnection = data;
		socket.removeremoveAllListeners();
		location.url('/battle');
	});

}]);
<commit_msg>Fix 2<commit_after>'use strict';

angular.module('mean.system')
.controller('IndexController', ['$scope', 'Global', function ($scope, Global) {
    $scope.global = Global;
}])
.controller('CreatureController', ['$scope', 'Global', 'socket', '$location', function ($scope, Global, socket, $location) {
    $scope.global = Global;
	$scope.battleStartUsers = [];
	var username = window.user.username;

	/**
	 * Update users waiting for game
	 */
	socket.emit('start', username);
	socket.on('echo', function() {
		socket.emit('prev_connected', username);
	});
	socket.on('join', function (user) {
		console.log( 'join ' + user);
		if ($scope.battleStartUsers.indexOf(user) === -1)
		$scope.battleStartUsers.push(user);
	});
	socket.on('prev_connected', function (user) {
		console.log( 'prev_connected ' + user);
		if ($scope.battleStartUsers.indexOf(user) === -1)
		$scope.battleStartUsers.push(user);
	});

	$scope.initGame = function (user) {
		console.log((new Date()).toString());
		socket.emit('initGame', {user: user, room: (new Date()).toString()});
	};

	socket.on('initGame', function(data) {
		if (data.user === username) {
			window.gameConnection = data;
			socket.removeAllListeners();
			data.user = username;
			socket.emit('joinGame', data);
		}
	});

	socket.on('gameConnection', function(data) {
		window.gameConnection = data;
		socket.removeAllListeners();
		$location.url('/battle');
	});

}]);
<|endoftext|>


<commit_before>//===========================================================================
//    Copyright 2014 Delving B.V.
//
//    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.
//===========================================================================

String.prototype.endsWith = function (suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

define(["angular"], function () {
    "use strict";

    var progressStates = {
        'state-preparing': "Preparing",
        'state-harvesting': "Harvesting",
        'state-collecting': "Collecting",
        'state-adopting': "Adopting",
        'state-generating': "Generating",
        'state-splitting': "Splitting",
        'state-collating': "Collating",
        'state-categorizing': "Categorizing",
        'state-processing': "Processing",
        'state-saving': "Saving",
        'state-skosifying': "Skosifying",
        'state-error': "Error"
    };

    /**
     * user is not a service, but stems from userResolve (Check ../user/dataset-list-services.js) object used by dashboard.routes.
     */
    var DatasetListCtrl = function ($rootScope, $scope, user, datasetListService, $location, $timeout) {
        if (user == null) $location.path("/");
        $scope.user = user;
        $scope.uploading = false;
        $scope.filteredDatasets = [];
        $scope.files = [];
        $scope.percent = null;
        $scope.dropSupported = false;
        $scope.newFileOpen = false;
        $scope.newDataset = {};
        $scope.specFilter = "";

        function checkNewEnabled() {
            if ($scope.newDataset.specTyped)
                $scope.newDataset.spec = $scope.newDataset.specTyped.trim().replace(/\W+/g, "-").replace(/[-]+/g, "-").toLowerCase();
            else
                $scope.newDataset.spec = "";
            $scope.newDataset.enabled = $scope.newDataset.spec.length && $scope.newDataset.character;
        }

        $scope.$watch("newDataset.specTyped", checkNewEnabled);
        $scope.$watch("newDataset.character", checkNewEnabled);

        function filterDatasets() {
            var filter = $scope.specFilter.trim();
            if (filter) {
                $scope.filteredDatasets = _.filter($scope.datasets, function (dataset) {
                    return dataset.datasetSpec.toLowerCase().indexOf(filter.toLowerCase()) >= 0;
                });
            }
            else {
                $scope.filteredDatasets = $scope.datasets;
            }
        }

        $scope.$watch("specFilter", filterDatasets);

        datasetListService.listPrefixes().then(function (prefixes) {
            $scope.characters = _.map(prefixes, function (prefix) {
                // for each prefix we should be able to accept a pre-mapped file
                return {
                    title: "Mapped to '" + prefix.toUpperCase() + "' format",
                    code: "character-mapped",
                    prefix: prefix
                };
            });
            if ($scope.characters.length == 1) {
                $scope.newDataset.character = $scope.characters[0];
            }
        });

        $scope.nonEmpty = function (obj) {
            return !_.isEmpty(obj)
        };

        $scope.isEmpty = function (obj) {
            return _.isEmpty(obj)
        };

        $scope.cancelNewFile = function () {
            $scope.newFileOpen = false;
        };

        $scope.setDropSupported = function () {
            $scope.dropSupported = true;
        };

        $scope.decorateDataset = function (dataset) {
            dataset.edit = angular.copy(dataset);
            dataset.apiMappings = user.narthexAPI + '/' + dataset.datasetSpec + '/mappings';
//            if (dataset.character) dataset.prefix = info.character.prefix;
//            split the states into date and time
            var stateVisible = false;
            _.forEach(
                [
                    'stateRaw', 'stateRawAnalyzed', 'stateSourced',
                    'stateMappable', 'stateProcessable', 'stateProcessed',
                    'stateAnalyzed', 'stateSaved'
                ],
                function (stateName) {
                    var time = dataset[stateName];
                    if (time) {
                        stateVisible = true;
                        var dt = time.split('T');
                        dataset[stateName] = {
                            d: dt[0],
                            t: dt[1].split('+')[0],
                            dt: dt
                        };
                    }
                }
            );
            if (!stateVisible) {
                dataset.empty = true;
            }
        };

        $scope.fetchDatasetList = function () {
            console.log('fetching list');
            $scope.specFilter = "";
            datasetListService.listDatasets().then(function (array) {
                // kill existing progress checkers
                if ($scope.datasets) _.forEach($scope.datasets, function (dataset) {
                    if (dataset.progressCheckerTimeout) {
                        $timeout.cancel(dataset.progressCheckerTimeout);
                        delete(dataset.progressCheckerTimeout);
                    }
                });
                _.forEach(array, $scope.decorateDataset);
                $scope.datasets = $scope.filteredDatasets = array;
            });
        };

        $scope.fetchDatasetList();

        $scope.createDataset = function () {
            datasetListService.create($scope.newDataset.spec, $scope.newDataset.character.code, $scope.newDataset.character.prefix).then(function () {
                $scope.cancelNewFile();
                $scope.newDataset.spec = undefined;
                $scope.fetchDatasetList();
            });
        };

    };

    DatasetListCtrl.$inject = [
        "$rootScope", "$scope", "user", "datasetListService", "$location", "$timeout"
    ];

    // these lists must match with DsInfo.scala

    var metadataFields = [
        "datasetName", "datasetDescription", "datasetAggregator", "datasetOwner", "datasetLanguage", "datasetRights"
    ];

    var harvestFields = [
        "harvestType", "harvestURL", "harvestDataset", "harvestPrefix", "harvestSearch"
    ];

    var harvestCronFields = [
        "harvestPreviousTime", "harvestDelay", "harvestDelayUnit", "harvestIncremental"
    ];

    var publishFields = [
        "publishOAIPMH", "publishIndex", "publishLOD"
    ];

    var categoriesFields = [
        "categoriesInclude"
    ];

    var DatasetEntryCtrl = function ($scope, datasetListService, $location, $timeout, $upload) {

        var ds = $scope.dataset;

        var baseUrl = $scope.user ? $scope.user.naveDomain : "http://unknown-nave-domain";
        $scope.searchLink = baseUrl + "/search?qf=delving_spec:" + ds.datasetSpec;
        $scope.apiLink = baseUrl + "/api/search/v1/?qf=delving_spec:" + ds.datasetSpec;
        // todo: note that edm is hardcoded here:
        $scope.oaiPmhLink = baseUrl + "/api/oai-pmh?verb=ListRecords&metadataPrefix=edm&set=" + ds.datasetSpec;
        $scope.apiPathErrors = $scope.user.narthexAPI + "/" + ds.datasetSpec + "/errors";

        function checkProgress() {
            datasetListService.datasetProgress(ds.datasetSpec).then(
                function (data) {
                    if (data.progressType == 'progress-idle') {
                        console.log(ds.datasetSpec + " is idle, stopping check");
                        ds.progress = undefined;
                        if (data.errorMessage) {
                            console.log(ds.datasetSpec + " has error message " + data.errorMessage);
                            ds.error = data.errorMessage;
                        }
                        if (ds.refreshAfter) {
                            delete ds.refreshAfter;
                            console.log(ds.datasetSpec + " refreshing after progress");
                            refreshInfo();
                        }
                        delete ds.progress;
                    }
                    else {
                        console.log(ds.datasetSpec + " is in progress");
                        ds.progress = {
                            state: data.progressState,
                            type: data.progressType,
                            count: parseInt(data.count)
                        };
                        createProgressMessage(ds.progress);
                        ds.progressCheckerTimeout = $timeout(checkProgress, 900 + Math.floor(Math.random() * 200));
                    }
                },
                function (problem) {
                    if (problem.status == 404) {
                        alert("Processing problem with " + ds.datasetSpec);
                    }
                    else {
                        alert("Network problem " + problem.status);
                    }
                }
            );
        }

        function refreshProgress() {
            console.log('refresh progress');
            datasetListService.datasetInfo(ds.datasetSpec).then(function (dataset) {
                if (ds.progressCheckerTimeout) $timeout.cancel(ds.progressCheckerTimeout);
                $scope.decorateDataset(dataset);
                $scope.dataset = dataset;
                dataset.refreshAfter = true;
                dataset.progressCheckerTimeout = $timeout(checkProgress, 1000);
            });
        }

        function refreshInfo() {
            console.log('refresh info');
            datasetListService.datasetInfo(ds.datasetSpec).then(function (dataset) {
                $scope.decorateDataset(dataset);
                $scope.dataset = dataset;
            });
        }

        $scope.leftTabOpen = "metadata";
        $scope.rightTabOpen = ds.harvestURL ? "harvest" : "drop";
        $scope.expanded = false;

        $scope.$watch("expanded", function (expanded) {
            if (expanded) {
                refreshInfo();
            }
            else {
                refreshProgress();
            }
        });

        if (!ds) return;

        ds.progressCheckerTimeout = $timeout(checkProgress, 1000 + Math.floor(Math.random() * 1000));

        $scope.$watch("dataset", function (newDs) {
            ds = newDs;
            setUnchanged()
        });

        function fileDropped($files, after) {
            //$files: an array of files selected, each file has name, size, and type.  Take the first only.
            if (!($files.length && !ds.uploading)) return;
            var onlyFile = $files[0];
            if (!(onlyFile.name.endsWith('.xml.gz') || onlyFile.name.endsWith('.xml') || onlyFile.name.endsWith('.sip.zip'))) {
                alert("Sorry, the file must end with '.xml.gz' or '.xml' or '.sip.zip'");
                return;
            }
            ds.uploading = true;
            $upload.upload({
                url: '/narthex/app/dataset/' + ds.datasetSpec + '/upload',
                file: onlyFile
            }).progress(
                function (evt) {
                    if (ds.uploading) ds.uploadPercent = parseInt(100.0 * evt.loaded / evt.total);
                }
            ).success(
                function () {
                    ds.uploading = false;
                    ds.uploadPercent = null;
                    if (after) after();
                }
            ).error(
                function (data, status, headers, config) {
                    ds.uploading = false;
                    ds.uploadPercent = null;
                    console.log("Failure during upload: data", data);
                    console.log("Failure during upload: status", status);
                    console.log("Failure during upload: headers", headers);
                    console.log("Failure during upload: config", config);
                    alert(data.problem);
                }
            );
        }

        $scope.receiveDropped = function ($files) {
            fileDropped($files, refreshProgress);
        };

        function createProgressMessage(p) {
            if (p.count == 0) p.count = 1;
            var pre = '';
            var post = '';
            var mid = p.count.toString();
            if (p.count > 3) {
                switch (p.type) {
                    case "progress-busy":
                        p.count = 100;
                        mid = "Busy..";
                        break;
                    case "progress-percent":
                        post = " %";
                        break;
                    case "progress-workers":
                        p.count = 100;
                        post = " workers";
                        break;
                    case "progress-pages":
                        p.count = p.count % 100;
                        post = " pages";
                        break;
                }
                if (p.count > 9) {
                    pre = progressStates[p.state] + " ";
                }
            }
            p.message = pre + mid + post;
        }

        function unchanged(fieldNameList) {
            var unchanged = true;
            _.forEach(fieldNameList, function (fieldName) {
                if (!angular.equals(ds[fieldName], ds.edit[fieldName])) {
//                    console.log("changed " + fieldName);
                    unchanged = false;
                }
            });
            return unchanged;
        }

        function setUnchanged() {
            $scope.unchangedMetadata = unchanged(metadataFields);
            $scope.unchangedPublish = unchanged(publishFields);
            $scope.unchangedHarvest = unchanged(harvestFields);
            $scope.unchangedHarvestCron = unchanged(harvestCronFields);
            $scope.unchangedCategories = unchanged(categoriesFields);
        }

        $scope.$watch("dataset.edit", setUnchanged, true);

        function setProperties(propertyList) {
            var payload = {propertyList: propertyList, values: {}};
            _.forEach(propertyList, function (propertyName) {
                payload.values[propertyName] = angular.copy(ds.edit[propertyName]);
            });
            datasetListService.setDatasetProperties(ds.datasetSpec, payload).then(refreshInfo);
        }

        $scope.setMetadata = function () {
            setProperties(metadataFields);
        };

        $scope.setPublish = function () {
            setProperties(publishFields);
        };

        $scope.setCategories = function () {
            setProperties(categoriesFields)
        };

        $scope.setHarvest = function () {
            setProperties(harvestFields);
        };

        $scope.setHarvestCron = function () {
            setProperties(harvestCronFields);
        };

        $scope.isLater = function (currState, nextState) {
            if (!nextState) return true;
            if (currState) return currState.dt > nextState.dt;
            return false;
        };

        $scope.showInvalidRecordsPage = function () {
            window.open($scope.apiPathErrors, "_blank")
        };

        $scope.goToDataset = function () {
            $location.path("/dataset/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.goToTerms = function () {
            $location.path("/terms/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.goToCategories = function () {
            $location.path("/categories/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.toggleDatasetProduction = function() {
            datasetListService.toggleDatasetProduction().then(function(data) {
                // todo: data.acceptanceOnly?
                refreshInfo()
            });
        };

        function command(command, areYouSure, after) {
            if (areYouSure && !confirm(areYouSure)) return;
            datasetListService.command(ds.datasetSpec, command).then(function (reply) {
                console.log(reply);
            }).then(function () {
                if (after) after();
            });
        }

        $scope.interruptProcessing = function () {
            command("interrupt", "Interrupt processing?", refreshProgress);
        };

        $scope.startGeneratingSip = function () {
            command("start generating sip", null, refreshProgress());
        };

        $scope.discardProcessed = function () {
            command("remove processed", "Discard processed data?", refreshInfo);
        };

        $scope.discardTree = function () {
            command("remove tree", "Discard analysis?", refreshInfo);
        };

        $scope.startProcessing = function () {
            command("start processing", null, refreshProgress);
        };

        $scope.startFirstHarvest = function () {
            command("start first harvest", "Erase existing data?", refreshProgress);
        };

        $scope.startRawAnalysis = function () {
            command("start raw analysis", null, refreshProgress);
        };

        $scope.startProcessedAnalysis = function () {
            command("start processed analysis", null, refreshProgress);
        };

        $scope.startSaving = function () {
            command("start saving", null, refreshProgress);
        };

        $scope.clearError = function () {
            command("clear error", null, refreshInfo());
        };

        $scope.deleteDataset = function () {
            command("delete", "Delete dataset?", $scope.fetchDatasetList);
        };

        function fetchSipFileList() {
            datasetListService.listSipFiles(ds.datasetSpec).then(function (data) {
                $scope.sipFiles = (data && data.list && data.list.length) ? data.list : undefined;
            });
        }

        fetchSipFileList();

        $scope.deleteSipZip = function () {
            datasetListService.deleteLatestSipFile(ds.datasetSpec).then(function () {
                fetchSipFileList();
            });
        };
    };

    DatasetEntryCtrl.$inject = ["$scope", "datasetListService", "$location", "$timeout", "$upload"];

    return {
        DatasetListCtrl: DatasetListCtrl,
        DatasetEntryCtrl: DatasetEntryCtrl
    };

});
<commit_msg>Maintain the latest expanded dataset in the search params for page refresh.<commit_after>//===========================================================================
//    Copyright 2014 Delving B.V.
//
//    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.
//===========================================================================

String.prototype.endsWith = function (suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

define(["angular"], function () {
    "use strict";

    var progressStates = {
        'state-preparing': "Preparing",
        'state-harvesting': "Harvesting",
        'state-collecting': "Collecting",
        'state-adopting': "Adopting",
        'state-generating': "Generating",
        'state-splitting': "Splitting",
        'state-collating': "Collating",
        'state-categorizing': "Categorizing",
        'state-processing': "Processing",
        'state-saving': "Saving",
        'state-skosifying': "Skosifying",
        'state-error': "Error"
    };

    /**
     * user is not a service, but stems from userResolve (Check ../user/dataset-list-services.js) object used by dashboard.routes.
     */
    var DatasetListCtrl = function ($rootScope, $scope, user, datasetListService, $location, $timeout) {
        if (user == null) $location.path("/");
        $scope.user = user;
        $scope.uploading = false;
        $scope.filteredDatasets = [];
        $scope.files = [];
        $scope.percent = null;
        $scope.dropSupported = false;
        $scope.newFileOpen = false;
        $scope.newDataset = {};
        $scope.specFilter = "";

        function checkNewEnabled() {
            if ($scope.newDataset.specTyped)
                $scope.newDataset.spec = $scope.newDataset.specTyped.trim().replace(/\W+/g, "-").replace(/[-]+/g, "-").toLowerCase();
            else
                $scope.newDataset.spec = "";
            $scope.newDataset.enabled = $scope.newDataset.spec.length && $scope.newDataset.character;
        }

        $scope.$watch("newDataset.specTyped", checkNewEnabled);
        $scope.$watch("newDataset.character", checkNewEnabled);

        function filterDatasets() {
            var filter = $scope.specFilter.trim();
            if (filter) {
                $scope.filteredDatasets = _.filter($scope.datasets, function (dataset) {
                    return dataset.datasetSpec.toLowerCase().indexOf(filter.toLowerCase()) >= 0;
                });
            }
            else {
                $scope.filteredDatasets = $scope.datasets;
            }
        }

        $scope.$watch("specFilter", filterDatasets);

        datasetListService.listPrefixes().then(function (prefixes) {
            $scope.characters = _.map(prefixes, function (prefix) {
                // for each prefix we should be able to accept a pre-mapped file
                return {
                    title: "Mapped to '" + prefix.toUpperCase() + "' format",
                    code: "character-mapped",
                    prefix: prefix
                };
            });
            if ($scope.characters.length == 1) {
                $scope.newDataset.character = $scope.characters[0];
            }
        });

        $scope.nonEmpty = function (obj) {
            return !_.isEmpty(obj)
        };

        $scope.isEmpty = function (obj) {
            return _.isEmpty(obj)
        };

        $scope.cancelNewFile = function () {
            $scope.newFileOpen = false;
        };

        $scope.setDropSupported = function () {
            $scope.dropSupported = true;
        };

        $scope.decorateDataset = function (dataset) {
            dataset.edit = angular.copy(dataset);
            dataset.apiMappings = user.narthexAPI + '/' + dataset.datasetSpec + '/mappings';
//            if (dataset.character) dataset.prefix = info.character.prefix;
//            split the states into date and time
            var stateVisible = false;
            _.forEach(
                [
                    'stateRaw', 'stateRawAnalyzed', 'stateSourced',
                    'stateMappable', 'stateProcessable', 'stateProcessed',
                    'stateAnalyzed', 'stateSaved'
                ],
                function (stateName) {
                    var time = dataset[stateName];
                    if (time) {
                        stateVisible = true;
                        var dt = time.split('T');
                        dataset[stateName] = {
                            d: dt[0],
                            t: dt[1].split('+')[0],
                            dt: dt
                        };
                    }
                }
            );
            if (!stateVisible) {
                dataset.empty = true;
            }
        };

        $scope.fetchDatasetList = function () {
            console.log('fetching list');
            $scope.specFilter = "";
            datasetListService.listDatasets().then(function (array) {
                // kill existing progress checkers
                if ($scope.datasets) _.forEach($scope.datasets, function (dataset) {
                    if (dataset.progressCheckerTimeout) {
                        $timeout.cancel(dataset.progressCheckerTimeout);
                        delete(dataset.progressCheckerTimeout);
                    }
                });
                _.forEach(array, $scope.decorateDataset);
                $scope.datasets = $scope.filteredDatasets = array;
            });
        };

        $scope.fetchDatasetList();

        $scope.createDataset = function () {
            datasetListService.create($scope.newDataset.spec, $scope.newDataset.character.code, $scope.newDataset.character.prefix).then(function () {
                $scope.cancelNewFile();
                $scope.newDataset.spec = undefined;
                $scope.fetchDatasetList();
            });
        };

    };

    DatasetListCtrl.$inject = [
        "$rootScope", "$scope", "user", "datasetListService", "$location", "$timeout"
    ];

    // these lists must match with DsInfo.scala

    var metadataFields = [
        "datasetName", "datasetDescription", "datasetAggregator", "datasetOwner", "datasetLanguage", "datasetRights"
    ];

    var harvestFields = [
        "harvestType", "harvestURL", "harvestDataset", "harvestPrefix", "harvestSearch"
    ];

    var harvestCronFields = [
        "harvestPreviousTime", "harvestDelay", "harvestDelayUnit", "harvestIncremental"
    ];

    var publishFields = [
        "publishOAIPMH", "publishIndex", "publishLOD"
    ];

    var categoriesFields = [
        "categoriesInclude"
    ];

    var DatasetEntryCtrl = function ($scope, datasetListService, $location, $timeout, $upload, $routeParams) {

        var ds = $scope.dataset;

        $scope.expanded = $routeParams.dataset == ds.datasetSpec;

        var baseUrl = $scope.user ? $scope.user.naveDomain : "http://unknown-nave-domain";
        $scope.searchLink = baseUrl + "/search?qf=delving_spec:" + ds.datasetSpec;
        $scope.apiLink = baseUrl + "/api/search/v1/?qf=delving_spec:" + ds.datasetSpec;
        // todo: note that edm is hardcoded here:
        $scope.oaiPmhLink = baseUrl + "/api/oai-pmh?verb=ListRecords&metadataPrefix=edm&set=" + ds.datasetSpec;
        $scope.apiPathErrors = $scope.user.narthexAPI + "/" + ds.datasetSpec + "/errors";

        function checkProgress() {
            datasetListService.datasetProgress(ds.datasetSpec).then(
                function (data) {
                    if (data.progressType == 'progress-idle') {
                        console.log(ds.datasetSpec + " is idle, stopping check");
                        ds.progress = undefined;
                        if (data.errorMessage) {
                            console.log(ds.datasetSpec + " has error message " + data.errorMessage);
                            ds.error = data.errorMessage;
                        }
                        if (ds.refreshAfter) {
                            delete ds.refreshAfter;
                            console.log(ds.datasetSpec + " refreshing after progress");
                            refreshInfo();
                        }
                        delete ds.progress;
                    }
                    else {
                        console.log(ds.datasetSpec + " is in progress");
                        ds.progress = {
                            state: data.progressState,
                            type: data.progressType,
                            count: parseInt(data.count)
                        };
                        createProgressMessage(ds.progress);
                        ds.progressCheckerTimeout = $timeout(checkProgress, 900 + Math.floor(Math.random() * 200));
                    }
                },
                function (problem) {
                    if (problem.status == 404) {
                        alert("Processing problem with " + ds.datasetSpec);
                    }
                    else {
                        alert("Network problem " + problem.status);
                    }
                }
            );
        }

        function refreshProgress() {
            console.log('refresh progress');
            datasetListService.datasetInfo(ds.datasetSpec).then(function (dataset) {
                if (ds.progressCheckerTimeout) $timeout.cancel(ds.progressCheckerTimeout);
                $scope.decorateDataset(dataset);
                $scope.dataset = dataset;
                dataset.refreshAfter = true;
                dataset.progressCheckerTimeout = $timeout(checkProgress, 1000);
            });
        }

        function refreshInfo() {
            console.log('refresh info');
            datasetListService.datasetInfo(ds.datasetSpec).then(function (dataset) {
                $scope.decorateDataset(dataset);
                $scope.dataset = dataset;
            });
        }

        $scope.leftTabOpen = "metadata";
        $scope.rightTabOpen = ds.harvestURL ? "harvest" : "drop";

        $scope.$watch("expanded", function (expanded) {
            if (expanded) {
                $location.search({dataset: ds.datasetSpec});
                refreshInfo();
            }
            else {
                refreshProgress();
            }
        });

        if (!ds) return;

        ds.progressCheckerTimeout = $timeout(checkProgress, 1000 + Math.floor(Math.random() * 1000));

        $scope.$watch("dataset", function (newDs) {
            ds = newDs;
            setUnchanged()
        });

        function fileDropped($files, after) {
            //$files: an array of files selected, each file has name, size, and type.  Take the first only.
            if (!($files.length && !ds.uploading)) return;
            var onlyFile = $files[0];
            if (!(onlyFile.name.endsWith('.xml.gz') || onlyFile.name.endsWith('.xml') || onlyFile.name.endsWith('.sip.zip'))) {
                alert("Sorry, the file must end with '.xml.gz' or '.xml' or '.sip.zip'");
                return;
            }
            ds.uploading = true;
            $upload.upload({
                url: '/narthex/app/dataset/' + ds.datasetSpec + '/upload',
                file: onlyFile
            }).progress(
                function (evt) {
                    if (ds.uploading) ds.uploadPercent = parseInt(100.0 * evt.loaded / evt.total);
                }
            ).success(
                function () {
                    ds.uploading = false;
                    ds.uploadPercent = null;
                    if (after) after();
                }
            ).error(
                function (data, status, headers, config) {
                    ds.uploading = false;
                    ds.uploadPercent = null;
                    console.log("Failure during upload: data", data);
                    console.log("Failure during upload: status", status);
                    console.log("Failure during upload: headers", headers);
                    console.log("Failure during upload: config", config);
                    alert(data.problem);
                }
            );
        }

        $scope.receiveDropped = function ($files) {
            fileDropped($files, refreshProgress);
        };

        function createProgressMessage(p) {
            if (p.count == 0) p.count = 1;
            var pre = '';
            var post = '';
            var mid = p.count.toString();
            if (p.count > 3) {
                switch (p.type) {
                    case "progress-busy":
                        p.count = 100;
                        mid = "Busy..";
                        break;
                    case "progress-percent":
                        post = " %";
                        break;
                    case "progress-workers":
                        p.count = 100;
                        post = " workers";
                        break;
                    case "progress-pages":
                        p.count = p.count % 100;
                        post = " pages";
                        break;
                }
                if (p.count > 9) {
                    pre = progressStates[p.state] + " ";
                }
            }
            p.message = pre + mid + post;
        }

        function unchanged(fieldNameList) {
            var unchanged = true;
            _.forEach(fieldNameList, function (fieldName) {
                if (!angular.equals(ds[fieldName], ds.edit[fieldName])) {
//                    console.log("changed " + fieldName);
                    unchanged = false;
                }
            });
            return unchanged;
        }

        function setUnchanged() {
            $scope.unchangedMetadata = unchanged(metadataFields);
            $scope.unchangedPublish = unchanged(publishFields);
            $scope.unchangedHarvest = unchanged(harvestFields);
            $scope.unchangedHarvestCron = unchanged(harvestCronFields);
            $scope.unchangedCategories = unchanged(categoriesFields);
        }

        $scope.$watch("dataset.edit", setUnchanged, true);

        function setProperties(propertyList) {
            var payload = {propertyList: propertyList, values: {}};
            _.forEach(propertyList, function (propertyName) {
                payload.values[propertyName] = angular.copy(ds.edit[propertyName]);
            });
            datasetListService.setDatasetProperties(ds.datasetSpec, payload).then(refreshInfo);
        }

        $scope.setMetadata = function () {
            setProperties(metadataFields);
        };

        $scope.setPublish = function () {
            setProperties(publishFields);
        };

        $scope.setCategories = function () {
            setProperties(categoriesFields)
        };

        $scope.setHarvest = function () {
            setProperties(harvestFields);
        };

        $scope.setHarvestCron = function () {
            setProperties(harvestCronFields);
        };

        $scope.isLater = function (currState, nextState) {
            if (!nextState) return true;
            if (currState) return currState.dt > nextState.dt;
            return false;
        };

        $scope.showInvalidRecordsPage = function () {
            window.open($scope.apiPathErrors, "_blank")
        };

        $scope.goToDataset = function () {
            $location.path("/dataset/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.goToTerms = function () {
            $location.path("/terms/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.goToCategories = function () {
            $location.path("/categories/" + ds.datasetSpec);
            $location.search({});
        };

        $scope.toggleDatasetProduction = function() {
            datasetListService.toggleDatasetProduction().then(function(data) {
                // todo: data.acceptanceOnly?
                refreshInfo()
            });
        };

        function command(command, areYouSure, after) {
            if (areYouSure && !confirm(areYouSure)) return;
            datasetListService.command(ds.datasetSpec, command).then(function (reply) {
                console.log(reply);
            }).then(function () {
                if (after) after();
            });
        }

        $scope.interruptProcessing = function () {
            command("interrupt", "Interrupt processing?", refreshProgress);
        };

        $scope.startGeneratingSip = function () {
            command("start generating sip", null, refreshProgress());
        };

        $scope.discardProcessed = function () {
            command("remove processed", "Discard processed data?", refreshInfo);
        };

        $scope.discardTree = function () {
            command("remove tree", "Discard analysis?", refreshInfo);
        };

        $scope.startProcessing = function () {
            command("start processing", null, refreshProgress);
        };

        $scope.startFirstHarvest = function () {
            command("start first harvest", "Erase existing data?", refreshProgress);
        };

        $scope.startRawAnalysis = function () {
            command("start raw analysis", null, refreshProgress);
        };

        $scope.startProcessedAnalysis = function () {
            command("start processed analysis", null, refreshProgress);
        };

        $scope.startSaving = function () {
            command("start saving", null, refreshProgress);
        };

        $scope.clearError = function () {
            command("clear error", null, refreshInfo());
        };

        $scope.deleteDataset = function () {
            command("delete", "Delete dataset?", $scope.fetchDatasetList);
        };

        function fetchSipFileList() {
            datasetListService.listSipFiles(ds.datasetSpec).then(function (data) {
                $scope.sipFiles = (data && data.list && data.list.length) ? data.list : undefined;
            });
        }

        fetchSipFileList();

        $scope.deleteSipZip = function () {
            datasetListService.deleteLatestSipFile(ds.datasetSpec).then(function () {
                fetchSipFileList();
            });
        };
    };

    DatasetEntryCtrl.$inject = ["$scope", "datasetListService", "$location", "$timeout", "$upload", "$routeParams"];

    return {
        DatasetListCtrl: DatasetListCtrl,
        DatasetEntryCtrl: DatasetEntryCtrl
    };

});
<|endoftext|>


<commit_before>/* global BABYLON */
import { loadPlayground, getPlaygroundId } from "./playground";
const canvas = document.getElementById("babylon-canvas"); // Get the canvas element

// Add your code here matching the playground format
const createScene = function (engine) {
    // Model by Mixamo

    engine.enableOfflineSupport = false;

    // This is really important to tell Babylon.js to use decomposeLerp and matrix interpolation
    BABYLON.Animation.AllowMatricesInterpolation = true;

    const scene = new BABYLON.Scene(engine);

    const camera = new BABYLON.ArcRotateCamera("camera1", Math.PI / 2, Math.PI / 4, 3, new BABYLON.Vector3(0, 1, 0), scene);
    camera.attachControl(canvas, true);

    camera.lowerRadiusLimit = 2;
    camera.upperRadiusLimit = 10;
    camera.wheelDeltaPercentage = 0.01;

    const light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
    light.intensity = 0.6;
    light.specular = BABYLON.Color3.Black();

    const light2 = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -0.5, -1.0), scene);
    light2.position = new BABYLON.Vector3(0, 5, 5);

    // Shadows
    const shadowGenerator = new BABYLON.ShadowGenerator(1024, light2);
    shadowGenerator.useBlurExponentialShadowMap = true;
    shadowGenerator.blurKernel = 32;

    engine.displayLoadingUI();

    BABYLON.SceneLoader.ImportMesh("", "./scenes/", "dummy3.babylon", scene, function (newMeshes, particleSystems, skeletons) {
        const skeleton = skeletons[0];

        shadowGenerator.addShadowCaster(scene.meshes[0], true);
        for (let index = 0; index < newMeshes.length; index++) {
            newMeshes[index].receiveShadows = false;
        }

        const helper = scene.createDefaultEnvironment({
            enableGroundShadow: true,
        });
        helper.setMainColor(BABYLON.Color3.Gray());
        helper.ground.position.y += 0.01;

        // ROBOT
        skeleton.animationPropertiesOverride = new BABYLON.AnimationPropertiesOverride();
        skeleton.animationPropertiesOverride.enableBlending = true;
        skeleton.animationPropertiesOverride.blendingSpeed = 0.05;
        skeleton.animationPropertiesOverride.loopMode = 1;

        const idleRange = skeleton.getAnimationRange("YBot_Idle");
        const walkRange = skeleton.getAnimationRange("YBot_Walk");
        const runRange = skeleton.getAnimationRange("YBot_Run");
        const leftRange = skeleton.getAnimationRange("YBot_LeftStrafeWalk");
        const rightRange = skeleton.getAnimationRange("YBot_RightStrafeWalk");

        // IDLE
        if (idleRange) scene.beginAnimation(skeleton, idleRange.from, idleRange.to, true);

        // UI
        const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
        const UiPanel = new BABYLON.GUI.StackPanel();
        UiPanel.width = "220px";
        UiPanel.fontSize = "14px";
        UiPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
        UiPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
        advancedTexture.addControl(UiPanel);
        // ..
        const button = BABYLON.GUI.Button.CreateSimpleButton("but1", "Play Idle");
        button.paddingTop = "10px";
        button.width = "100px";
        button.height = "50px";
        button.color = "white";
        button.background = "green";
        button.onPointerDownObservable.add(() => {
            if (idleRange) scene.beginAnimation(skeleton, idleRange.from, idleRange.to, true);
        });
        UiPanel.addControl(button);
        // ..
        let button1 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Play Walk");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (walkRange) scene.beginAnimation(skeleton, walkRange.from, walkRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but3", "Play Run");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (runRange) scene.beginAnimation(skeleton, runRange.from, runRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but4", "Play Left");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (leftRange) scene.beginAnimation(skeleton, leftRange.from, leftRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but5", "Play Right");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (rightRange) scene.beginAnimation(skeleton, rightRange.from, rightRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but6", "Play Blend");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (walkRange && leftRange) {
                scene.stopAnimation(skeleton);
                const walkAnim = scene.beginWeightedAnimation(skeleton, walkRange.from, walkRange.to, 0.5, true);
                const leftAnim = scene.beginWeightedAnimation(skeleton, leftRange.from, leftRange.to, 0.5, true);

                // Note: Sync Speed Ratio With Master Walk Animation
                walkAnim.syncWith(null);
                leftAnim.syncWith(walkAnim);
            }
        });
        UiPanel.addControl(button1);

        engine.hideLoadingUI();
    });

    return scene;
};
let engine;
let scene;
const runScene = async () => {
    const playgroundId = getPlaygroundId();
    if (engine) {
        engine.dispose();
        engine = undefined;
    }
    engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine
    if (playgroundId) {
        window.engine = engine;
        window.canvas = canvas;
        scene = await loadPlayground(playgroundId);
    } else {
        scene = createScene(engine); //Call the createScene function
    }

    // Register a render loop to repeatedly render the scene
    engine.runRenderLoop(function () {
        scene.render();
    });

    // Watch for browser/canvas resize events
    window.addEventListener("resize", function () {
        engine.resize();
    });
};

runScene();

window.addEventListener("hashchange", runScene);
<commit_msg>make the snapshot work correctly when deployed in tests<commit_after>/* global BABYLON */
import { loadPlayground, getPlaygroundId } from "./playground";
const canvas = document.getElementById("babylon-canvas"); // Get the canvas element

// Add your code here matching the playground format
const createScene = function (engine) {
    // Model by Mixamo

    engine.enableOfflineSupport = false;

    // This is really important to tell Babylon.js to use decomposeLerp and matrix interpolation
    BABYLON.Animation.AllowMatricesInterpolation = true;

    const scene = new BABYLON.Scene(engine);

    const camera = new BABYLON.ArcRotateCamera("camera1", Math.PI / 2, Math.PI / 4, 3, new BABYLON.Vector3(0, 1, 0), scene);
    camera.attachControl(canvas, true);

    camera.lowerRadiusLimit = 2;
    camera.upperRadiusLimit = 10;
    camera.wheelDeltaPercentage = 0.01;

    const light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
    light.intensity = 0.6;
    light.specular = BABYLON.Color3.Black();

    const light2 = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -0.5, -1.0), scene);
    light2.position = new BABYLON.Vector3(0, 5, 5);

    // Shadows
    const shadowGenerator = new BABYLON.ShadowGenerator(1024, light2);
    shadowGenerator.useBlurExponentialShadowMap = true;
    shadowGenerator.blurKernel = 32;

    engine.displayLoadingUI();

    BABYLON.SceneLoader.ImportMesh("", "https://playground.babylonjs.com/scenes/", "dummy3.babylon", scene, function (newMeshes, particleSystems, skeletons) {
        const skeleton = skeletons[0];

        shadowGenerator.addShadowCaster(scene.meshes[0], true);
        for (let index = 0; index < newMeshes.length; index++) {
            newMeshes[index].receiveShadows = false;
        }

        const helper = scene.createDefaultEnvironment({
            enableGroundShadow: true,
        });
        helper.setMainColor(BABYLON.Color3.Gray());
        helper.ground.position.y += 0.01;

        // ROBOT
        skeleton.animationPropertiesOverride = new BABYLON.AnimationPropertiesOverride();
        skeleton.animationPropertiesOverride.enableBlending = true;
        skeleton.animationPropertiesOverride.blendingSpeed = 0.05;
        skeleton.animationPropertiesOverride.loopMode = 1;

        const idleRange = skeleton.getAnimationRange("YBot_Idle");
        const walkRange = skeleton.getAnimationRange("YBot_Walk");
        const runRange = skeleton.getAnimationRange("YBot_Run");
        const leftRange = skeleton.getAnimationRange("YBot_LeftStrafeWalk");
        const rightRange = skeleton.getAnimationRange("YBot_RightStrafeWalk");

        // IDLE
        if (idleRange) scene.beginAnimation(skeleton, idleRange.from, idleRange.to, true);

        // UI
        const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
        const UiPanel = new BABYLON.GUI.StackPanel();
        UiPanel.width = "220px";
        UiPanel.fontSize = "14px";
        UiPanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
        UiPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
        advancedTexture.addControl(UiPanel);
        // ..
        const button = BABYLON.GUI.Button.CreateSimpleButton("but1", "Play Idle");
        button.paddingTop = "10px";
        button.width = "100px";
        button.height = "50px";
        button.color = "white";
        button.background = "green";
        button.onPointerDownObservable.add(() => {
            if (idleRange) scene.beginAnimation(skeleton, idleRange.from, idleRange.to, true);
        });
        UiPanel.addControl(button);
        // ..
        let button1 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Play Walk");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (walkRange) scene.beginAnimation(skeleton, walkRange.from, walkRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but3", "Play Run");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (runRange) scene.beginAnimation(skeleton, runRange.from, runRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but4", "Play Left");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (leftRange) scene.beginAnimation(skeleton, leftRange.from, leftRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but5", "Play Right");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (rightRange) scene.beginAnimation(skeleton, rightRange.from, rightRange.to, true);
        });
        UiPanel.addControl(button1);
        // ..
        button1 = BABYLON.GUI.Button.CreateSimpleButton("but6", "Play Blend");
        button1.paddingTop = "10px";
        button1.width = "100px";
        button1.height = "50px";
        button1.color = "white";
        button1.background = "green";
        button1.onPointerDownObservable.add(() => {
            if (walkRange && leftRange) {
                scene.stopAnimation(skeleton);
                const walkAnim = scene.beginWeightedAnimation(skeleton, walkRange.from, walkRange.to, 0.5, true);
                const leftAnim = scene.beginWeightedAnimation(skeleton, leftRange.from, leftRange.to, 0.5, true);

                // Note: Sync Speed Ratio With Master Walk Animation
                walkAnim.syncWith(null);
                leftAnim.syncWith(walkAnim);
            }
        });
        UiPanel.addControl(button1);

        engine.hideLoadingUI();
    });

    return scene;
};
let engine;
let scene;
const runScene = async () => {
    const playgroundId = getPlaygroundId();
    if (engine) {
        engine.dispose();
        engine = undefined;
    }
    engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine
    if (playgroundId) {
        window.engine = engine;
        window.canvas = canvas;
        scene = await loadPlayground(playgroundId);
    } else {
        scene = createScene(engine); //Call the createScene function
    }

    // Register a render loop to repeatedly render the scene
    engine.runRenderLoop(function () {
        scene.render();
    });

    // Watch for browser/canvas resize events
    window.addEventListener("resize", function () {
        engine.resize();
    });
};

runScene();

window.addEventListener("hashchange", runScene);
<|endoftext|>


<commit_before>/* global angular */
;(function () {
  angular.module('resilienzManager')
    .provider('resilienzManagerDataProvider', function resilienzManagerDataProvider () {
      var restURL = '/'
      this.setURL = function (url) {
        restURL = url
      }
      this.$get = function ($http) {
        return {
          users: function () {
            return $http({
              method: 'GET', url: restURL + 'users/'
            })
          },
          actions: function () {
            return $http({
              method: 'GET', url: restURL + 'actions/'
            })
          },
          action: function (id) {
            return $http({
              method: 'GET', url: restURL + 'actions/' + id
            })
          },
          actionsForUser: function (id) {
            return $http({
              method: 'GET', url: restURL + 'actions/user/' + id
            })
          },
          categoriesFull: function () {
            return $http({
              method: 'GET', url: restURL + 'categories/full'
            })
          },
          getLayoutImagesByActionPage: function (actionid, page) {
            return $http({
              method: 'GET', url: restURL + 'actions/' + actionid + '/' + page + '/layout'
            })
          },
          getPositionImage: function (actionid, page, positionid) {
            return $http({
              method: 'GET', url: restURL + 'positions/' + actionid + '/' + page + '/' + positionid + '/image'
            })
          },
          createPage: function (actionid, category, page, id, removed) {
            return $http({
              method: 'PATCH', url: restURL + 'bookimages/' + actionid + '/' + category + '/' + page + '/' + id + '/' + (removed ? '1' : '0')
            })
          },
          imageRescale: function (name, data, cw, ch, width, height) {
            var sd = data
            sd.cw = cw
            sd.ch = ch
            sd.imageWidth = width
            sd.imageHeight = height
            return $http({
              method: 'PUT', url: restURL + 'bookimages/' + name + '/rescale', data: sd
            })
          },
          imageDelete: function (name) {
            return $http({
              method: 'DELETE', url: restURL + 'bookimages/' + name
            })
          },
          textSave: function (actionId, page, positionId, value) {
            return $http({
              method: 'PUT', url: restURL + 'booktext/save/' + actionId + '/' + page + '/' + positionId + '', data: value
            })
          },
          actionMakeFinal: function (id) {
            return $http({
              method: 'PUT', url: restURL + 'actions/' + id + '/finalize'
            })
          },
          createBook: function (id) {
            return $http({
              method: 'PUT', url: restURL + 'book/' + id
            })
          },
          switchToAction: function (userId, actionId) {
            return $http({
              method: 'PATCH', url: restURL + 'actions/' + userId + '/switch/' + actionId
            })
          },
          createAction: function (userId, comment) {
            return $http({
              method: 'POST', url: restURL + 'actions/' + userId, data: comment
            })
          },
          actionSaveLayout: function (id, page, layoutId) {
            return $http({
              method: 'PUT', url: restURL + 'actions/' + id + '/' + page + '/layout', data: layoutId
            })
          }
        }
      }
    })
}())
<commit_msg>correct body<commit_after>/* global angular */
;(function () {
  angular.module('resilienzManager')
    .provider('resilienzManagerDataProvider', function resilienzManagerDataProvider () {
      var restURL = '/'
      this.setURL = function (url) {
        restURL = url
      }
      this.$get = function ($http) {
        return {
          users: function () {
            return $http({
              method: 'GET', url: restURL + 'users/'
            })
          },
          actions: function () {
            return $http({
              method: 'GET', url: restURL + 'actions/'
            })
          },
          action: function (id) {
            return $http({
              method: 'GET', url: restURL + 'actions/' + id
            })
          },
          actionsForUser: function (id) {
            return $http({
              method: 'GET', url: restURL + 'actions/user/' + id
            })
          },
          categoriesFull: function () {
            return $http({
              method: 'GET', url: restURL + 'categories/full'
            })
          },
          getLayoutImagesByActionPage: function (actionid, page) {
            return $http({
              method: 'GET', url: restURL + 'actions/' + actionid + '/' + page + '/layout'
            })
          },
          getPositionImage: function (actionid, page, positionid) {
            return $http({
              method: 'GET', url: restURL + 'positions/' + actionid + '/' + page + '/' + positionid + '/image'
            })
          },
          createPage: function (actionid, category, page, id, removed) {
            return $http({
              method: 'PATCH', url: restURL + 'bookimages/' + actionid + '/' + category + '/' + page + '/' + id + '/' + (removed ? '1' : '0')
            })
          },
          imageRescale: function (name, data, cw, ch, width, height) {
            var sd = data
            sd.cw = cw
            sd.ch = ch
            sd.imageWidth = width
            sd.imageHeight = height
            return $http({
              method: 'PUT', url: restURL + 'bookimages/' + name + '/rescale', data: sd
            })
          },
          imageDelete: function (name) {
            return $http({
              method: 'DELETE', url: restURL + 'bookimages/' + name
            })
          },
          textSave: function (actionId, page, positionId, value) {
            return $http({
              method: 'PUT', url: restURL + 'booktext/save/' + actionId + '/' + page + '/' + positionId + '', data: value
            })
          },
          actionMakeFinal: function (id) {
            return $http({
              method: 'PUT', url: restURL + 'actions/' + id + '/finalize'
            })
          },
          createBook: function (id) {
            return $http({
              method: 'PUT', url: restURL + 'book/' + id
            })
          },
          switchToAction: function (userId, actionId) {
            return $http({
              method: 'PATCH', url: restURL + 'actions/' + userId + '/switch/' + actionId
            })
          },
          createAction: function (userId, comment) {
            return $http({
              method: 'POST', url: restURL + 'actions/' + userId, data: {comment: comment}
            })
          },
          actionSaveLayout: function (id, page, layoutId) {
            return $http({
              method: 'PUT', url: restURL + 'actions/' + id + '/' + page + '/layout', data: layoutId
            })
          }
        }
      }
    })
}())
<|endoftext|>


<commit_before>import renderTag from 'discourse/lib/render-tag';

function formatTag(t) {
  return renderTag(t.id, {count: t.count});
}

export default Ember.TextField.extend({
  classNameBindings: [':tag-chooser'],
  attributeBindings: ['tabIndex', 'placeholderKey', 'categoryId'],

  _setupTags: function() {
    const tags = this.get('tags') || [];
    this.set('value', tags.join(", "));
  }.on('init'),

  _valueChanged: function() {
    const tags = this.get('value').split(',').map(v => v.trim()).reject(v => v.length === 0).uniq();
    this.set('tags', tags);
  }.observes('value'),

  _initializeTags: function() {
    const site = this.site,
          self = this,
          filterRegexp = new RegExp(this.site.tags_filter_regexp, "g");

    this.$().select2({
      tags: true,
      placeholder: I18n.t(this.get('placeholderKey') || 'tagging.choose_for_topic'),
      maximumInputLength: this.siteSettings.max_tag_length,
      maximumSelectionSize: this.siteSettings.max_tags_per_topic,
      initSelection(element, callback) {
        const data = [];

        function splitVal(string, separator) {
          var val, i, l;
          if (string === null || string.length < 1) return [];
          val = string.split(separator);
          for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
          return val;
        }

        $(splitVal(element.val(), ",")).each(function () {
          data.push({
            id: this,
            text: this
          });
        });

        callback(data);
      },
      createSearchChoice: function(term, data) {
        term = term.replace(filterRegexp, '').trim();

        // No empty terms, make sure the user has permission to create the tag
        if (!term.length || !site.get('can_create_tag')) { return; }

        if ($(data).filter(function() {
          return this.text.localeCompare(term) === 0;
        }).length === 0) {
          return { id: term, text: term };
        }
      },
      createSearchChoicePosition: function(list, item) {
        // Search term goes on the bottom
        list.push(item);
      },
      formatSelection: function (data) {
          return data ? renderTag(this.text(data)) : undefined;
      },
      formatSelectionCssClass: function(){
        return "discourse-tag-select2";
      },
      formatResult: formatTag,
      multiple: true,
      ajax: {
        quietMillis: 200,
        cache: true,
        url: Discourse.getURL("/tags/filter/search"),
        dataType: 'json',
        data: function (term) {
          return { q: term, limit: self.siteSettings.max_tag_search_results, filterForInput: true, categoryId: self.get('categoryId') };
        },
        results: function (data) {
          if (self.siteSettings.tags_sort_alphabetically) {
            data.results = data.results.sort(function(a,b) { return a.id > b.id; });
          }
          return data;
        }
      },
    });
  }.on('didInsertElement'),

  _destroyTags: function() {
    this.$().select2('destroy');
  }.on('willDestroyElement')

});
<commit_msg>tag-chooser input detects when bound tags list has changed<commit_after>import renderTag from 'discourse/lib/render-tag';

function formatTag(t) {
  return renderTag(t.id, {count: t.count});
}

export default Ember.TextField.extend({
  classNameBindings: [':tag-chooser'],
  attributeBindings: ['tabIndex', 'placeholderKey', 'categoryId'],

  _setupTags: function() {
    const tags = this.get('tags') || [];
    this.set('value', tags.join(", "));
  }.on('init'),

  _valueChanged: function() {
    const tags = this.get('value').split(',').map(v => v.trim()).reject(v => v.length === 0).uniq();
    this.set('tags', tags);
  }.observes('value'),

  _tagsChanged: function() {
    const $tagChooser = this.$(),
          val = this.get('value');

    if ($tagChooser && val !== this.get('tags')) {
      if (this.get('tags')) {
        const data = this.get('tags').map((t) => {return {id: t, text: t};});
        $tagChooser.select2('data', data);
      } else {
        $tagChooser.select2('data', []);
      }
    }
  }.observes('tags'),

  _initializeTags: function() {
    const site = this.site,
          self = this,
          filterRegexp = new RegExp(this.site.tags_filter_regexp, "g");

    this.$().select2({
      tags: true,
      placeholder: I18n.t(this.get('placeholderKey') || 'tagging.choose_for_topic'),
      maximumInputLength: this.siteSettings.max_tag_length,
      maximumSelectionSize: self.get('unlimitedTagCount') ? null : this.siteSettings.max_tags_per_topic,
      initSelection(element, callback) {
        const data = [];

        function splitVal(string, separator) {
          var val, i, l;
          if (string === null || string.length < 1) return [];
          val = string.split(separator);
          for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
          return val;
        }

        $(splitVal(element.val(), ",")).each(function () {
          data.push({
            id: this,
            text: this
          });
        });

        callback(data);
      },
      createSearchChoice: function(term, data) {
        term = term.replace(filterRegexp, '').trim();

        // No empty terms, make sure the user has permission to create the tag
        if (!term.length || !site.get('can_create_tag')) { return; }

        if ($(data).filter(function() {
          return this.text.localeCompare(term) === 0;
        }).length === 0) {
          return { id: term, text: term };
        }
      },
      createSearchChoicePosition: function(list, item) {
        // Search term goes on the bottom
        list.push(item);
      },
      formatSelection: function (data) {
          return data ? renderTag(this.text(data)) : undefined;
      },
      formatSelectionCssClass: function(){
        return "discourse-tag-select2";
      },
      formatResult: formatTag,
      multiple: true,
      ajax: {
        quietMillis: 200,
        cache: true,
        url: Discourse.getURL("/tags/filter/search"),
        dataType: 'json',
        data: function (term) {
          const d = { q: term, limit: self.siteSettings.max_tag_search_results, categoryId: self.get('categoryId') };
          if (!self.get('everyTag')) {
            d.filterForInput = true;
          }
          return d;
        },
        results: function (data) {
          if (self.siteSettings.tags_sort_alphabetically) {
            data.results = data.results.sort(function(a,b) { return a.id > b.id; });
          }
          return data;
        }
      },
    });
  }.on('didInsertElement'),

  _destroyTags: function() {
    this.$().select2('destroy');
  }.on('willDestroyElement')

});
<|endoftext|>