<commit_before>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.pipeline.stage.deployStage', [
  require('../../../../serverGroup/serverGroup.read.service.js'),
  require('../../../../serverGroup/configure/common/serverGroupCommandBuilder.js'),
  require('../../../../cloudProvider/cloudProvider.registry.js'),
])
  .config(function (pipelineConfigProvider) {
    pipelineConfigProvider.registerStage({
      label: 'Deploy',
      description: 'Deploys the previously baked or found image',
      key: 'deploy',
      templateUrl: require('./deployStage.html'),
      executionDetailsUrl: require('./deployExecutionDetails.html'),
      controller: 'DeployStageCtrl',
      controllerAs: 'deployStageCtrl',
      defaultTimeoutMs: 60 * 60 * 1000, // 60 minutes
      validators: [
        {
          type: 'stageBeforeType',
          stageTypes: ['bake', 'findAmi', 'findImage'],
          message: 'You must have a Bake or Find Image stage before any deploy stage.'
        },
      ],
    });
  })
  .controller('DeployStageCtrl', function ($scope, $uibModal, stage, namingService, providerSelectionService,
                                           cloudProviderRegistry, serverGroupCommandBuilder, serverGroupTransformer) {
    $scope.stage = stage;

    function initializeCommand() {
      // TODO: We can probably remove this once we've migrated everyone over to multi-cluster deploy stages.
      // This is the lazy way to get us there without explicitly editing all the existing pipelines
      $scope.stage.clusters = $scope.stage.clusters || [];
      if ($scope.stage.cluster) {
        $scope.stage.cluster.account = $scope.stage.account;
        $scope.stage.clusters = [$scope.stage.cluster];

        delete $scope.stage.cluster;
        delete $scope.stage.account;
      }
    }

    this.getRegion = function(cluster) {
      if (cluster.region) {
        return cluster.region;
      }
      var availabilityZones = cluster.availabilityZones;
      if (availabilityZones) {
        var regions = Object.keys(availabilityZones);
        if (regions && regions.length) {
          return regions[0];
        }
      }
      return 'n/a';
    };

    this.getClusterName = function(cluster) {
      return namingService.getClusterName(cluster.application, cluster.stack, cluster.freeFormDetails);
    };

    this.addCluster = function() {
      providerSelectionService.selectProvider($scope.application).then(function(selectedProvider) {
        let config = cloudProviderRegistry.getValue(selectedProvider, 'serverGroup');
        $uibModal.open({
          templateUrl: config.cloneServerGroupTemplateUrl,
          controller: `${config.cloneServerGroupController} as ctrl`,
          resolve: {
            title: function () {
              return 'Configure Deployment Cluster';
            },
            application: function () {
              return $scope.application;
            },
            serverGroupCommand: function () {
              return serverGroupCommandBuilder.buildNewServerGroupCommandForPipeline(selectedProvider);
            },
          }
        }).result.then(function(command) {
            // If we don't set the provider, the serverGroupTransformer won't know which provider to delegate to.
            command.provider = selectedProvider;
            var stageCluster = serverGroupTransformer.convertServerGroupCommandToDeployConfiguration(command);
            delete stageCluster.credentials;
            $scope.stage.clusters.push(stageCluster);
          });
      });
    };

    this.editCluster = function(cluster, index) {
      cluster.provider = cluster.providerType || 'aws';
      let providerConfig = cloudProviderRegistry.getProvider(cluster.provider);
      return $uibModal.open({
        templateUrl: providerConfig.serverGroup.cloneServerGroupTemplateUrl,
        controller: `${providerConfig.serverGroup.cloneServerGroupController} as ctrl`,
        resolve: {
          title: function () {
            return 'Configure Deployment Cluster';
          },
          application: function () {
            return $scope.application;
          },
          serverGroupCommand: function () {
            return serverGroupCommandBuilder.buildServerGroupCommandFromPipeline($scope.application, cluster);
          },
        }
      }).result.then(function(command) {
          var stageCluster = serverGroupTransformer.convertServerGroupCommandToDeployConfiguration(command);
          delete stageCluster.credentials;
          $scope.stage.clusters[index] = stageCluster;
        });
    };

    this.copyCluster = function(index) {
      $scope.stage.clusters.push(angular.copy($scope.stage.clusters[index]));
    };

    this.removeCluster = function(index) {
      $scope.stage.clusters.splice(index, 1);
    };

    initializeCommand();

  }).name;
<commit_msg>check cloudProvider and providerType fields before defaulting to aws<commit_after>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.pipeline.stage.deployStage', [
  require('../../../../serverGroup/serverGroup.read.service.js'),
  require('../../../../serverGroup/configure/common/serverGroupCommandBuilder.js'),
  require('../../../../cloudProvider/cloudProvider.registry.js'),
])
  .config(function (pipelineConfigProvider) {
    pipelineConfigProvider.registerStage({
      label: 'Deploy',
      description: 'Deploys the previously baked or found image',
      key: 'deploy',
      templateUrl: require('./deployStage.html'),
      executionDetailsUrl: require('./deployExecutionDetails.html'),
      controller: 'DeployStageCtrl',
      controllerAs: 'deployStageCtrl',
      defaultTimeoutMs: 60 * 60 * 1000, // 60 minutes
      validators: [
        {
          type: 'stageBeforeType',
          stageTypes: ['bake', 'findAmi', 'findImage'],
          message: 'You must have a Bake or Find Image stage before any deploy stage.'
        },
      ],
    });
  })
  .controller('DeployStageCtrl', function ($scope, $uibModal, stage, namingService, providerSelectionService,
                                           cloudProviderRegistry, serverGroupCommandBuilder, serverGroupTransformer) {
    $scope.stage = stage;

    function initializeCommand() {
      // TODO: We can probably remove this once we've migrated everyone over to multi-cluster deploy stages.
      // This is the lazy way to get us there without explicitly editing all the existing pipelines
      $scope.stage.clusters = $scope.stage.clusters || [];
      if ($scope.stage.cluster) {
        $scope.stage.cluster.account = $scope.stage.account;
        $scope.stage.clusters = [$scope.stage.cluster];

        delete $scope.stage.cluster;
        delete $scope.stage.account;
      }
    }

    this.getRegion = function(cluster) {
      if (cluster.region) {
        return cluster.region;
      }
      var availabilityZones = cluster.availabilityZones;
      if (availabilityZones) {
        var regions = Object.keys(availabilityZones);
        if (regions && regions.length) {
          return regions[0];
        }
      }
      return 'n/a';
    };

    this.getClusterName = function(cluster) {
      return namingService.getClusterName(cluster.application, cluster.stack, cluster.freeFormDetails);
    };

    this.addCluster = function() {
      providerSelectionService.selectProvider($scope.application).then(function(selectedProvider) {
        let config = cloudProviderRegistry.getValue(selectedProvider, 'serverGroup');
        $uibModal.open({
          templateUrl: config.cloneServerGroupTemplateUrl,
          controller: `${config.cloneServerGroupController} as ctrl`,
          resolve: {
            title: function () {
              return 'Configure Deployment Cluster';
            },
            application: function () {
              return $scope.application;
            },
            serverGroupCommand: function () {
              return serverGroupCommandBuilder.buildNewServerGroupCommandForPipeline(selectedProvider);
            },
          }
        }).result.then(function(command) {
            // If we don't set the provider, the serverGroupTransformer won't know which provider to delegate to.
            command.provider = selectedProvider;
            var stageCluster = serverGroupTransformer.convertServerGroupCommandToDeployConfiguration(command);
            delete stageCluster.credentials;
            $scope.stage.clusters.push(stageCluster);
          });
      });
    };

    this.editCluster = function(cluster, index) {
      cluster.provider = cluster.cloudProvider || cluster.providerType || 'aws';
      let providerConfig = cloudProviderRegistry.getProvider(cluster.provider);
      return $uibModal.open({
        templateUrl: providerConfig.serverGroup.cloneServerGroupTemplateUrl,
        controller: `${providerConfig.serverGroup.cloneServerGroupController} as ctrl`,
        resolve: {
          title: function () {
            return 'Configure Deployment Cluster';
          },
          application: function () {
            return $scope.application;
          },
          serverGroupCommand: function () {
            return serverGroupCommandBuilder.buildServerGroupCommandFromPipeline($scope.application, cluster);
          },
        }
      }).result.then(function(command) {
          var stageCluster = serverGroupTransformer.convertServerGroupCommandToDeployConfiguration(command);
          delete stageCluster.credentials;
          $scope.stage.clusters[index] = stageCluster;
        });
    };

    this.copyCluster = function(index) {
      $scope.stage.clusters.push(angular.copy($scope.stage.clusters[index]));
    };

    this.removeCluster = function(index) {
      $scope.stage.clusters.splice(index, 1);
    };

    initializeCommand();

  }).name;
<|endoftext|>


<commit_before>import React from "react"

class Modal extends React.Component {

	static defaultProps = {
		modalOn : false,
		bgColor : '#FAFAFA',
		mode : 'default'
	}

	static propTypes = {
		modalOn : React.PropTypes.bool.isRequired,
		bgColor : React.PropTypes.string,
		mode : React.PropTypes.string
	}

	constructor(props) {
		super(props);
		this.state = {
			modalOpen : this.props.modalOn,
			bgColor : this.props.bgColor,
			mode : this.props.mode
		};
	}

	componentWillReceiveProps(nextProps) {
		this.setState({
			modalOpen : nextProps.modalOn
		});
	}

	closeHandle() {
		this.setState({
			modalOpen : false
		});
	}

	render() {

		let styles = {
			wrap : {
				common : {
					position : "fixed",
					width : "100%",
					height : "100%",
					top : 0,
					left : 0,
					padding : 0,
					display : "flex",
					//alignItems : "center",
					justifyContent : "center",
					overflowY : "auto"
				},
				custom : {
					backgroundColor : this.state.mode==='default' ? `rgba(250,250,250,0.8)` : this.state.bgColor,
				},
				child : {
					width : "100%",

				}
			},
			btn : {
				common : {
					position : "fixed",
					borderRadius : 3,
					border : "1px solid #08c",
					fontSize : 16,
					color : "#08c",
					textAlign : "right",
					top : 10,
					right : 10,
					padding : 3
				}
			}
		};

		return(

				{this.state.modalOpen &&

{this.closeHandle()}} >Close

{this.props.children}

}

		);
	}
}

export default Modal;<commit_msg>bgcolor commenting<commit_after>import React from "react"

class Modal extends React.Component {

	static defaultProps = {
		modalOn : false,
		//bgColor : '#FAFAFA',
		mode : 'default'
	}

	static propTypes = {
		modalOn : React.PropTypes.bool.isRequired,
		//bgColor : React.PropTypes.string,
		mode : React.PropTypes.string
	}

	constructor(props) {
		super(props);
		this.state = {
			modalOpen : this.props.modalOn,
			//bgColor : this.props.bgColor,
			mode : this.props.mode
		};
	}

	componentWillReceiveProps(nextProps) {
		this.setState({
			modalOpen : nextProps.modalOn
		});
	}

	closeHandle() {
		this.setState({
			modalOpen : false
		});
	}

	render() {

		let styles = {
			wrap : {
				common : {
					position : "fixed",
					width : "100%",
					height : "100%",
					top : 0,
					left : 0,
					padding : 0,
					display : "flex",
					//alignItems : "center",
					justifyContent : "center",
					overflowY : "auto"
				},
				custom : {
					backgroundColor : this.state.mode==='default' ? `rgba(18,18,18,0.5)` : this.state.bgColor,
				},
				child : {
					width : "100%",

				}
			},
			btn : {
				common : {
					position : "fixed",
					borderRadius : 3,
					border : "1px solid #08c",
					fontSize : 16,
					color : "#08c",
					textAlign : "right",
					top : 10,
					right : 10,
					padding : 3
				}
			}
		};

		return(

				{this.state.modalOpen &&

{this.closeHandle()}} >Close

{this.props.children}

}

		);
	}
}

export default Modal;<|endoftext|>


<commit_before>/**
 @ngdoc service
 * @name umbraco.services.tourService
 *
 * @description
 * Added in Umbraco 7.8. Application-wide service for handling tours.
 */
(function () {
    'use strict';

    function tourService(eventsService, currentUserResource, $q, tourResource) {

        var tours = [];
        var currentTour = null;

        /**
         * Registers all tours from the server and returns a promise
         */
        function registerAllTours() {
            tours = [];
            return tourResource.getTours().then(function(tourFiles) {
                angular.forEach(tourFiles, function (tourFile) {
                    angular.forEach(tourFile.tours, function(newTour) {
                        validateTour(newTour);
                        validateTourRegistration(newTour);
                        tours.push(newTour);
                    });
                });
                eventsService.emit("appState.tour.updatedTours", tours);
            });
        }

        /**
         * Method to return all of the tours as a new instance
         */
        function getTours() {
            return tours;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#startTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Raises an event to start a tour
         * @param {Object} tour The tour which should be started
         */
        function startTour(tour) {
            validateTour(tour);
            eventsService.emit("appState.tour.start", tour);
            currentTour = tour;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#endTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Raises an event to end the current tour
         */
        function endTour(tour) {
            eventsService.emit("appState.tour.end", tour);
            currentTour = null;
        }

        /**
         * Disables a tour for the user, raises an event and returns a promise
         * @param {any} tour
         */
        function disableTour(tour) {
            var deferred = $q.defer();
            tour.disabled = true;
            currentUserResource
                .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
                    function() {
                        eventsService.emit("appState.tour.end", tour);
                        currentTour = null;
                        deferred.resolve(tour);
                    });
            return deferred.promise;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#completeTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Completes a tour for the user, raises an event and returns a promise
         * @param {Object} tour The tour which should be completed
         */
        function completeTour(tour) {
            var deferred = $q.defer();
            tour.completed = true;
            currentUserResource
                .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
                    function() {
                        eventsService.emit("appState.tour.complete", tour);
                        currentTour = null;
                        deferred.resolve(tour);
                    });
            return deferred.promise;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getCurrentTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns the current tour
         * @returns {Object} Returns the current tour
         */
        function getCurrentTour() {
            // TODO: This should be reset if a new user logs in
            return currentTour;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getGroupedTours
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns a promise of grouped tours with the current user statuses
         * @returns {Array} All registered tours grouped by tour group
         */
        function getGroupedTours() {
            var deferred = $q.defer();
            var tours = getTours();
            setTourStatuses(tours).then(function() {
                var groupedTours = [];
                tours.forEach(function (item) {

                    if (item.contentType === null || item.contentType === '') {
                        var groupExists = false;
                        var newGroup = {
                            "group": "",
                            "tours": []
                        };

                        groupedTours.forEach(function (group) {
                            // extend existing group if it is already added
                            if (group.group === item.group) {
                                if (item.groupOrder) {
                                    group.groupOrder = item.groupOrder;
                                }
                                groupExists = true;

                            if(item.hidden === false){
                                group.tours.push(item);
                            }
                            }
                        });

                        // push new group to array if it doesn't exist
                        if (!groupExists) {
                            newGroup.group = item.group;
                            if (item.groupOrder) {
                                newGroup.groupOrder = item.groupOrder;
                            }

                        if(item.hidden === false){
                            newGroup.tours.push(item);
                            groupedTours.push(newGroup);
                        }
                    }

                });

                deferred.resolve(groupedTours);
            });
            return deferred.promise;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getTourByAlias
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns a promise of the tour found by alias with the current user statuses
         * @param {Object} tourAlias The tour alias of the tour which should be returned
         * @returns {Object} Tour object
         */
        function getTourByAlias(tourAlias) {
            var deferred = $q.defer();
            var tours = getTours();
            setTourStatuses(tours).then(function () {
                var tour = _.findWhere(tours, { alias: tourAlias });
                deferred.resolve(tour);
            });
            return deferred.promise;
        }

        /**
        * @ngdoc method
        * @name umbraco.services.tourService#getToursForDoctype
        * @methodOf umbraco.services.tourService
        *
        * @description
        * Returns a promise of the tours found by documenttype alias.
        * @param {Object} doctypeAlias The doctype alias for which  the tours which should be returned
        * @returns {Array} An array of tour objects for the doctype
        */
        function getToursForDoctype(doctypeAlias) {
            var deferred = $q.defer();
            tourResource.getToursForDoctype(doctypeAlias).then(function (tours) {
                deferred.resolve(tours);
            });
            return deferred.promise;
        }

        ///////////

        /**
         * Validates a tour object and makes sure it consists of the correct properties needed to start a tour
         * @param {any} tour
         */
        function validateTour(tour) {

            if (!tour) {
                throw "A tour is not specified";
            }

            if (!tour.alias) {
                throw "A tour alias is required";
            }

            if (!tour.steps) {
                throw "Tour " + tour.alias + " is missing tour steps";
            }

            if (tour.steps && tour.steps.length === 0) {
                throw "Tour " + tour.alias + " is missing tour steps";
            }

            if (tour.requiredSections.length === 0) {
                throw "Tour " + tour.alias + " is missing the required sections";
            }
        }

        /**
         * Validates a tour before it gets registered in the service
         * @param {any} tour
         */
        function validateTourRegistration(tour) {
            // check for existing tours with the same alias
            angular.forEach(tours, function (existingTour) {
                if (existingTour.alias === tour.alias) {
                    throw "A tour with the alias " + tour.alias + " is already registered";
                }
            });
        }

        /**
         * Based on the tours given, this will set each of the tour statuses (disabled/completed) based on what is stored against the current user
         * @param {any} tours
         */
        function setTourStatuses(tours) {

            var deferred = $q.defer();
            currentUserResource.getTours().then(function (storedTours) {

                angular.forEach(storedTours, function (storedTour) {
                    if (storedTour.completed === true) {
                        angular.forEach(tours, function (tour) {
                            if (storedTour.alias === tour.alias) {
                                tour.completed = true;
                            }
                        });
                    }
                    if (storedTour.disabled === true) {
                        angular.forEach(tours, function (tour) {
                            if (storedTour.alias === tour.alias) {
                                tour.disabled = true;
                            }
                        });
                    }
                });

                deferred.resolve(tours);
            });
            return deferred.promise;
        }

        var service = {
            registerAllTours: registerAllTours,
            startTour: startTour,
            endTour: endTour,
            disableTour: disableTour,
            completeTour: completeTour,
            getCurrentTour: getCurrentTour,
            getGroupedTours: getGroupedTours,
            getTourByAlias: getTourByAlias,
            getToursForDoctype : getToursForDoctype
        };

        return service;

    }

    angular.module("umbraco.services").factory("tourService", tourService);

})();
<commit_msg>Fix automatic merge gone wrong<commit_after>/**
 @ngdoc service
 * @name umbraco.services.tourService
 *
 * @description
 * Added in Umbraco 7.8. Application-wide service for handling tours.
 */
(function () {
    'use strict';

    function tourService(eventsService, currentUserResource, $q, tourResource) {

        var tours = [];
        var currentTour = null;

        /**
         * Registers all tours from the server and returns a promise
         */
        function registerAllTours() {
            tours = [];
            return tourResource.getTours().then(function(tourFiles) {
                angular.forEach(tourFiles, function (tourFile) {
                    angular.forEach(tourFile.tours, function(newTour) {
                        validateTour(newTour);
                        validateTourRegistration(newTour);
                        tours.push(newTour);
                    });
                });
                eventsService.emit("appState.tour.updatedTours", tours);
            });
        }

        /**
         * Method to return all of the tours as a new instance
         */
        function getTours() {
            return tours;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#startTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Raises an event to start a tour
         * @param {Object} tour The tour which should be started
         */
        function startTour(tour) {
            validateTour(tour);
            eventsService.emit("appState.tour.start", tour);
            currentTour = tour;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#endTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Raises an event to end the current tour
         */
        function endTour(tour) {
            eventsService.emit("appState.tour.end", tour);
            currentTour = null;
        }

        /**
         * Disables a tour for the user, raises an event and returns a promise
         * @param {any} tour
         */
        function disableTour(tour) {
            var deferred = $q.defer();
            tour.disabled = true;
            currentUserResource
                .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
                    function() {
                        eventsService.emit("appState.tour.end", tour);
                        currentTour = null;
                        deferred.resolve(tour);
                    });
            return deferred.promise;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#completeTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Completes a tour for the user, raises an event and returns a promise
         * @param {Object} tour The tour which should be completed
         */
        function completeTour(tour) {
            var deferred = $q.defer();
            tour.completed = true;
            currentUserResource
                .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
                    function() {
                        eventsService.emit("appState.tour.complete", tour);
                        currentTour = null;
                        deferred.resolve(tour);
                    });
            return deferred.promise;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getCurrentTour
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns the current tour
         * @returns {Object} Returns the current tour
         */
        function getCurrentTour() {
            // TODO: This should be reset if a new user logs in
            return currentTour;
        }

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getGroupedTours
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns a promise of grouped tours with the current user statuses
         * @returns {Array} All registered tours grouped by tour group
         */
        function getGroupedTours() {
            var deferred = $q.defer();
            var tours = getTours();
            setTourStatuses(tours).then(function() {
                var groupedTours = [];
                tours.forEach(function (item) {

                    if (item.contentType === null || item.contentType === '') {
                        var groupExists = false;
                        var newGroup = {
                            "group": "",
                            "tours": []
                        };

                        groupedTours.forEach(function (group) {
                            // extend existing group if it is already added
                            if (group.group === item.group) {
                                if (item.groupOrder) {
                                    group.groupOrder = item.groupOrder;
                                }
                                groupExists = true;

                            if(item.hidden === false){
                                group.tours.push(item);
                            }
                            }
                        });

                        // push new group to array if it doesn't exist
                        if (!groupExists) {
                            newGroup.group = item.group;
                            if (item.groupOrder) {
                                newGroup.groupOrder = item.groupOrder;
                            }

                        if(item.hidden === false){
                            newGroup.tours.push(item);
                            groupedTours.push(newGroup);
                        }
                    }

                }

                deferred.resolve(groupedTours);
            });
            return deferred.promise;
        });

        /**
         * @ngdoc method
         * @name umbraco.services.tourService#getTourByAlias
         * @methodOf umbraco.services.tourService
         *
         * @description
         * Returns a promise of the tour found by alias with the current user statuses
         * @param {Object} tourAlias The tour alias of the tour which should be returned
         * @returns {Object} Tour object
         */
        function getTourByAlias(tourAlias) {
            var deferred = $q.defer();
            var tours = getTours();
            setTourStatuses(tours).then(function () {
                var tour = _.findWhere(tours, { alias: tourAlias });
                deferred.resolve(tour);
            });
            return deferred.promise;
        }

        /**
        * @ngdoc method
        * @name umbraco.services.tourService#getToursForDoctype
        * @methodOf umbraco.services.tourService
        *
        * @description
        * Returns a promise of the tours found by documenttype alias.
        * @param {Object} doctypeAlias The doctype alias for which  the tours which should be returned
        * @returns {Array} An array of tour objects for the doctype
        */
        function getToursForDoctype(doctypeAlias) {
            var deferred = $q.defer();
            tourResource.getToursForDoctype(doctypeAlias).then(function (tours) {
                deferred.resolve(tours);
            });
            return deferred.promise;
        }

        ///////////

        /**
         * Validates a tour object and makes sure it consists of the correct properties needed to start a tour
         * @param {any} tour
         */
        function validateTour(tour) {

            if (!tour) {
                throw "A tour is not specified";
            }

            if (!tour.alias) {
                throw "A tour alias is required";
            }

            if (!tour.steps) {
                throw "Tour " + tour.alias + " is missing tour steps";
            }

            if (tour.steps && tour.steps.length === 0) {
                throw "Tour " + tour.alias + " is missing tour steps";
            }

            if (tour.requiredSections.length === 0) {
                throw "Tour " + tour.alias + " is missing the required sections";
            }
        }

        /**
         * Validates a tour before it gets registered in the service
         * @param {any} tour
         */
        function validateTourRegistration(tour) {
            // check for existing tours with the same alias
            angular.forEach(tours, function (existingTour) {
                if (existingTour.alias === tour.alias) {
                    throw "A tour with the alias " + tour.alias + " is already registered";
                }
            });
        }

        /**
         * Based on the tours given, this will set each of the tour statuses (disabled/completed) based on what is stored against the current user
         * @param {any} tours
         */
        function setTourStatuses(tours) {

            var deferred = $q.defer();
            currentUserResource.getTours().then(function (storedTours) {

                angular.forEach(storedTours, function (storedTour) {
                    if (storedTour.completed === true) {
                        angular.forEach(tours, function (tour) {
                            if (storedTour.alias === tour.alias) {
                                tour.completed = true;
                            }
                        });
                    }
                    if (storedTour.disabled === true) {
                        angular.forEach(tours, function (tour) {
                            if (storedTour.alias === tour.alias) {
                                tour.disabled = true;
                            }
                        });
                    }
                });

                deferred.resolve(tours);
            });
            return deferred.promise;
        }

        var service = {
            registerAllTours: registerAllTours,
            startTour: startTour,
            endTour: endTour,
            disableTour: disableTour,
            completeTour: completeTour,
            getCurrentTour: getCurrentTour,
            getGroupedTours: getGroupedTours,
            getTourByAlias: getTourByAlias,
            getToursForDoctype : getToursForDoctype
        };

        return service;

    }

    angular.module("umbraco.services").factory("tourService", tourService);

})();
<|endoftext|>


<commit_before>import angular from 'angular';
import template from './projects.html';
import dialogTemplate from './projects.dialog.html';

export const ProjectsComponent = {
    bindings: {},
    controller: class ProjectsComponent {
        constructor($scope, $mdDialog, $mdToast, ProjectsService, ResponseHandler, Validator) {
            'ngInject';
            this.$scope = $scope;
            this.$mdDialog = $mdDialog;
            this.$mdToast = $mdToast;
            this.ProjectsService = ProjectsService;
            this.ResponseHandler = ResponseHandler;
            this.Validator = Validator;
        }

        $onInit() {
            this.projects = [];
            this.getProjects(false);
        }

        getProjects(forceRefresh) {
            return this.ProjectsService.get(forceRefresh).then(projects => this.projects = projects);
        }

        addOrEdit(project = { id: null, name: '', status: true }, targetEvent, method) {
            this.isEditing = !!project.id;
            this.selectedProject = angular.copy(project);

            this.$mdDialog
                .show({
                    preserveScope: true,
                    scope: this.$scope,
                    targetEvent,
                    template: dialogTemplate
                })
                .then(project => {
                    project.name === project.name.trim();
                    if (!this.Validator.isUnique(this.projects, 'name', this.selectedProject, this.isEditing, true, 'proyecto')) {
                        this.selectedProject = null;
                        return;
                    }
                    if (!this.isEditing) {
                        delete project.id;
                        delete project.status;
                    }
                    this.ProjectsService[method](project).then(response => {
                        this.ResponseHandler.success(response);
                        this.getProjects();
                    });
                })
                .catch(() => {
                    this.selectedProject = null;
                });
        }

        /**
         * Validate if a project name is unique
         * @param {any} project
         * @return {boolean}
         */
        isUnique(project) {
            if (project.id) { // It is for an update
                return !this.projects.some(pro => pro.name === project.name && pro.id !== project.id);
            } else { // for an addition
                return !this.projects.some(pro => pro.name === project.name);
            }
        }
    },
    template
};<commit_msg>feat Deletes unnnecesary dependency injection<commit_after>import angular from 'angular';
import template from './projects.html';
import dialogTemplate from './projects.dialog.html';

export const ProjectsComponent = {
    bindings: {},
    controller: class ProjectsComponent {
        constructor($scope, $mdDialog, ProjectsService, ResponseHandler, Validator) {
            'ngInject';
            this.$scope = $scope;
            this.$mdDialog = $mdDialog;
            this.ProjectsService = ProjectsService;
            this.ResponseHandler = ResponseHandler;
            this.Validator = Validator;
        }

        $onInit() {
            this.projects = [];
            this.getProjects(false);
        }

        getProjects(forceRefresh) {
            return this.ProjectsService.get(forceRefresh).then(projects => this.projects = projects);
        }

        addOrEdit(project = { id: null, name: '', status: true }, targetEvent, method) {
            this.isEditing = !!project.id;
            this.selectedProject = angular.copy(project);

            this.$mdDialog
                .show({
                    preserveScope: true,
                    scope: this.$scope,
                    targetEvent,
                    template: dialogTemplate
                })
                .then(project => {
                    project.name === project.name.trim();
                    if (!this.Validator.isUnique(this.projects, 'name', this.selectedProject, this.isEditing, true, 'proyecto')) {
                        this.selectedProject = null;
                        return;
                    }
                    if (!this.isEditing) {
                        delete project.id;
                        delete project.status;
                    }
                    this.ProjectsService[method](project).then(response => {
                        this.ResponseHandler.success(response);
                        this.getProjects();
                    });
                })
                .catch(() => {
                    this.selectedProject = null;
                });
        }

        /**
         * Validate if a project name is unique
         * @param {any} project
         * @return {boolean}
         */
        isUnique(project) {
            if (project.id) { // It is for an update
                return !this.projects.some(pro => pro.name === project.name && pro.id !== project.id);
            } else { // for an addition
                return !this.projects.some(pro => pro.name === project.name);
            }
        }
    },
    template
};<|endoftext|>


<commit_before>exports.individu = {
    indemnites_journalieres_maternite: 'indJourMaternite',
    indemnites_journalieres_maladie: 'indJourMaladie',
    indemnites_journalieres_maladie_professionnelle: 'indJourMaladieProf',
    indemnites_journalieres_accident_travail: 'indJourAccidentDuTravail',
    indemnites_volontariat: 'indVolontariat',
    indemnites_chomage_partiel: 'indChomagePartiel',
    chonet: 'allocationsChomage',
    chobrut: {
        src: 'allocationsChomage',
        fn: function(value) {
            return value / (1 - (((0.062 + 0.005) * 0.9825) + 0.028));
        }
    },
    salnet: 'revenusSalarie',
    salbrut: {
        src: 'revenusSalarie',
        fn: function(value) { return value / 0.77; }
    },
    rstnet: 'pensionsRetraitesRentes',
    aah: 'aah',
    pensions_alimentaires_percues: 'pensionsAlimentaires',
    revenus_locatifs: 'revenusLocatifs',
    revenus_capital: 'revenusDuCapital',
    indemnites_stage: 'stage',
    revenus_stage_formation_pro: 'revenusStageFormationPro',
    allocation_securisation_professionnelle: 'allocationSecurisationPro',
    prime_forfaitaire_mensuelle_reprise_activite: 'primeRepriseActivite',
    dedommagement_victime_amiante: 'dedommagementAmiante',
    prestation_compensatoire: 'prestationCompensatoire',
    retraite_combattant: 'retraiteCombattant',
    pensions_invalidite: 'pensionsInvalidite',
    bourse_enseignement_sup: 'bourseEnseignementSup',
    bourse_recherche: 'bourseRecherche',
    gains_exceptionnels: 'gainsExceptionnels'
};

exports.famille = {
    aspa: 'aspa',
    aide_logement: 'allocationLogement'
};
<commit_msg>Retire les prestations simulées de l'input OpenFisca<commit_after>exports.individu = {
    indemnites_journalieres_maternite: 'indJourMaternite',
    indemnites_journalieres_maladie: 'indJourMaladie',
    indemnites_journalieres_maladie_professionnelle: 'indJourMaladieProf',
    indemnites_journalieres_accident_travail: 'indJourAccidentDuTravail',
    indemnites_volontariat: 'indVolontariat',
    indemnites_chomage_partiel: 'indChomagePartiel',
    chonet: 'allocationsChomage',
    chobrut: {
        src: 'allocationsChomage',
        fn: function(value) {
            return value / (1 - (((0.062 + 0.005) * 0.9825) + 0.028));
        }
    },
    salnet: 'revenusSalarie',
    salbrut: {
        src: 'revenusSalarie',
        fn: function(value) { return value / 0.77; }
    },
    rstnet: 'pensionsRetraitesRentes',
    aah: 'aah',
    pensions_alimentaires_percues: 'pensionsAlimentaires',
    revenus_locatifs: 'revenusLocatifs',
    revenus_capital: 'revenusDuCapital',
    indemnites_stage: 'stage',
    revenus_stage_formation_pro: 'revenusStageFormationPro',
    allocation_securisation_professionnelle: 'allocationSecurisationPro',
    prime_forfaitaire_mensuelle_reprise_activite: 'primeRepriseActivite',
    dedommagement_victime_amiante: 'dedommagementAmiante',
    prestation_compensatoire: 'prestationCompensatoire',
    retraite_combattant: 'retraiteCombattant',
    pensions_invalidite: 'pensionsInvalidite',
    bourse_enseignement_sup: 'bourseEnseignementSup',
    bourse_recherche: 'bourseRecherche',
    gains_exceptionnels: 'gainsExceptionnels'
};

exports.famille = {
    // aspa: 'aspa',
    // aide_logement: 'allocationLogement'
};
<|endoftext|>


<commit_before>/**
 * tab-content.js
 */

/* shared */
import {
  getType, isObjectNotEmpty, isString, logErr, setElementDataset,
  preventDefaultEvent, throwErr
} from './common.js';
import { getTab, updateTab } from './browser.js';
import { closeTabs, muteTabs } from './browser-tabs.js';
import { getSidebarTab, getSidebarTabId } from './util.js';
import {
  CLASS_TAB_AUDIO, CLASS_TAB_CLOSE, CLASS_TAB_CONTENT, CLASS_TAB_ICON,
  CLASS_TAB_TITLE, HIGHLIGHTED, IDENTIFIED, TAB_CLOSE, TAB_MUTE,
  TAB_MUTE_UNMUTE, TABS_CLOSE, TABS_MUTE, TABS_MUTE_UNMUTE, URL_AUDIO_MUTED,
  URL_AUDIO_PLAYING, URL_FAVICON_DEFAULT, URL_LOADING_THROBBER
} from './constant.js';

/* api */
const { i18n } = browser;

/* favicon */
export const favicon = new Map([
  [
    'https://abs.twimg.com/favicons/favicon.ico',
    '../img/twitter-logo-blue.svg'
  ],
  [
    'https://abs.twimg.com/icons/apple-touch-icon-192x192.png',
    '../img/twitter-logo-blue.svg'
  ],
  [
    'chrome://browser/skin/customize.svg',
    '../img/customize-favicon.svg'
  ],
  [
    'chrome://browser/skin/settings.svg',
    '../img/options-favicon.svg'
  ],
  [
    'chrome://mozapps/skin/extensions/extensionGeneric-16.svg',
    '../img/addons-favicon.svg'
  ],
  [
    'chrome://mozapps/skin/extensions/extension.svg',
    '../img/addons-favicon.svg'
  ]
]);

/* contextual identities icon name */
export const contextualIdentitiesIconName = new Set([
  'briefcase', 'cart', 'chill', 'dollar', 'fingerprint', 'food', 'fruit',
  'gift', 'pet', 'tree', 'vacation'
]);

/* contextual identities icon color */
export const contextualIdentitiesIconColor = new Set([
  'blue', 'purple', 'pink', 'red', 'orange', 'yellow', 'green',
  'turquoise'
]);

/**
 * tab icon fallback
 *
 * @param {object} evt - event
 * @returns {boolean} - false
 */
export const tabIconFallback = evt => {
  if (isObjectNotEmpty(evt)) {
    const { target, type } = evt;
    if (type === 'error' && target && isString(target.src)) {
      target.src = URL_FAVICON_DEFAULT;
    }
  }
  return false;
};

/**
 * add tab icon error listener
 *
 * @param {object} elm - img element
 * @returns {void}
 */
export const addTabIconErrorListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img') {
    elm.addEventListener('error', tabIconFallback);
  }
};

/**
 * set tab icon
 *
 * @param {object} elm - img element
 * @param {object} info - tab info
 * @returns {void}
 */
export const setTabIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { favIconUrl, status, title, url } = info;
    if (status === 'loading') {
      try {
        if (isString(title) && isString(url)) {
          const { href } = new URL(url);
          const connecting =
            href.replace(/\/$/, '').endsWith(title.replace(/\/$/, ''));
          if (connecting) {
            elm.dataset.connecting = url;
          } else if (elm.dataset.connecting) {
            const { stroke } = window.getComputedStyle(elm);
            elm.style.fill = stroke;
            elm.dataset.connecting = '';
          }
        } else {
          elm.dataset.connecting = url;
        }
      } catch (e) {
        logErr(e);
        elm.dataset.connecting = url;
      }
      elm.src = URL_LOADING_THROBBER;
    } else {
      elm.dataset.connecting = '';
      elm.style.fill = '';
      if (favIconUrl) {
        elm.src = favicon.get(favIconUrl) || favIconUrl;
      } else {
        elm.src = URL_FAVICON_DEFAULT;
      }
    }
  }
};

/* tab content */
/**
 * set tab content
 *
 * @param {object} tab - tab element
 * @param {object} tabsTab - tabs.Tab
 * @returns {void}
 */
export const setTabContent = async (tab, tabsTab) => {
  if (tab && tab.nodeType === Node.ELEMENT_NODE && isObjectNotEmpty(tabsTab)) {
    const { favIconUrl, status, title, url } = tabsTab;
    const tabContent = tab.querySelector(`.${CLASS_TAB_CONTENT}`);
    const tabTitle = tab.querySelector(`.${CLASS_TAB_TITLE}`);
    const tabIcon = tab.querySelector(`.${CLASS_TAB_ICON}`);
    tabContent.title = title;
    tabTitle.textContent = title;
    await setTabIcon(tabIcon, { favIconUrl, status, title, url });
    await setElementDataset(tab, 'tab', JSON.stringify(tabsTab));
  }
};

/* audio */
/**
 * handle clicked audio button
 *
 * @param {!object} evt - event
 * @returns {?Function} - muteTabs() / updateTab()
 */
export const handleClickedTabAudio = async evt => {
  const { target } = evt;
  const tab = getSidebarTab(target);
  const tabId = getSidebarTabId(tab);
  let func;
  if (Number.isInteger(tabId)) {
    const tabsTab = await getTab(tabId);
    const { mutedInfo: { muted } } = tabsTab;
    const { classList } = tab;
    if (classList.contains(HIGHLIGHTED)) {
      const selectedTabs = document.querySelectorAll(`.${HIGHLIGHTED}`);
      func = muteTabs(Array.from(selectedTabs), !muted);
    } else {
      func = updateTab(tabId, { muted: !muted });
    }
  }
  return func;
};

/**
 * handle tab audio onclick
 *
 * @param {!object} evt - Event
 * @returns {Function} - handleClickedTabAudio()
 */
export const tabAudioOnClick = evt =>
  handleClickedTabAudio(evt).catch(throwErr);

/**
 * add tab audio click event listener
 *
 * @param {object} elm - element
 * @returns {void}
 */
export const addTabAudioClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_AUDIO)) {
    elm.addEventListener('click', tabAudioOnClick);
  }
};

/**
 * set tab audio
 *
 * @param {object} elm - element
 * @param {object} info - audio info
 * @returns {void}
 */
export const setTabAudio = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && isObjectNotEmpty(info)) {
    const { audible, muted, highlighted } = info;
    if (muted) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE_UNMUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE_UNMUTE}_tooltip`);
      }
    } else if (audible) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE}_tooltip`);
      }
    } else {
      elm.title = '';
    }
  }
};

/**
 * set tab audio icon
 *
 * @param {object} elm - element
 * @param {object} info - audio info
 * @returns {void}
 */
export const setTabAudioIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { audible, muted } = info;
    if (muted) {
      elm.alt = i18n.getMessage(`${TAB_MUTE_UNMUTE}`);
      elm.src = URL_AUDIO_MUTED;
    } else if (audible) {
      elm.alt = i18n.getMessage(`${TAB_MUTE}`);
      elm.src = URL_AUDIO_PLAYING;
    } else {
      elm.alt = '';
      elm.src = '';
    }
  }
};

/* close button */
/**
 * set close tab button tooltip
 *
 * @param {object} elm - element
 * @param {boolean} highlighted - highlighted
 * @returns {void}
 */
export const setCloseTab = async (elm, highlighted) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_CLOSE)) {
    if (highlighted) {
      elm.title = i18n.getMessage(`${TABS_CLOSE}_tooltip`);
    } else {
      elm.title = i18n.getMessage(`${TAB_CLOSE}_tooltip`);
    }
  }
};

/**
 * handle clicked close button
 *
 * @param {object} evt - event
 * @returns {?Function} - closeTabs()
 */
export const handleClickedCloseButton = async evt => {
  const { target } = evt;
  const tab = getSidebarTab(target);
  let func;
  if (tab) {
    const { classList } = tab;
    if (classList.contains(HIGHLIGHTED)) {
      const selectedTabs = document.querySelectorAll(`.${HIGHLIGHTED}`);
      func = closeTabs(Array.from(selectedTabs));
    } else {
      func = closeTabs([tab]);
    }
  }
  return func || null;
};

/**
 * handle tab close button click
 *
 * @param {!object} evt - Event
 * @returns {Function} - handleClickedCloseButton()
 */
export const tabCloseOnClick = evt =>
  handleClickedCloseButton(evt).catch(throwErr);

/**
 * add tab close click listener
 *
 * @param {object} elm - element
 * @returns {void}
 */
export const addTabCloseClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_CLOSE)) {
    elm.addEventListener('mousedown', preventDefaultEvent);
    elm.addEventListener('click', tabCloseOnClick);
  }
};

/* contextual identities */
/**
 * set contextual identities icon
 *
 * @param {object} elm - element
 * @param {object} info - contextual identities info
 * @returns {void}
 */
export const setContextualIdentitiesIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { color, icon, name } = info;
    if (contextualIdentitiesIconColor.has(color) &&
        contextualIdentitiesIconName.has(icon) &&
        isString(name)) {
      elm.alt = name;
      elm.src = `../img/${icon}.svg#${color}`;
      elm.parentNode.classList.add(IDENTIFIED);
    }
  }
};

/* highlight */
/**
 * add hightlight class to tab
 *
 * @param {object} elm - element
 * @returns {Promise.<Array>} - results of each handler
 */
export const addHighlight = async elm => {
  const func = [];
  const tabId = getSidebarTabId(elm);
  if (Number.isInteger(tabId)) {
    const tab = await getTab(tabId);
    const { audible, mutedInfo: { muted } } = tab;
    const closeElm = elm.querySelector(`.${CLASS_TAB_CLOSE}`);
    const muteElm = elm.querySelector(`.${CLASS_TAB_AUDIO}`);
    elm.classList.add(HIGHLIGHTED);
    func.push(
      setCloseTab(closeElm, true),
      setTabAudio(muteElm, {
        audible,
        muted,
        highlighted: true
      })
    );
  }
  return Promise.all(func);
};

/**
 * add highlight class to tabs
 *
 * @param {Array} tabIds - array of tab ID
 * @returns {Promise.<Array>} - results of each handler
 */
export const addHighlightToTabs = async tabIds => {
  if (!Array.isArray(tabIds)) {
    throw new TypeError(`Expected Array but got ${getType(tabIds)}.`);
  }
  const func = [];
  for (const id of tabIds) {
    const item = document.querySelector(`[data-tab-id="${id}"]`);
    if (item) {
      func.push(addHighlight(item));
    }
  }
  return Promise.all(func);
};

/**
 * remove hightlight class from tab
 *
 * @param {object} elm - element
 * @returns {Promise.<Array>} - results of each handler
 */
export const removeHighlight = async elm => {
  const func = [];
  const tabId = getSidebarTabId(elm);
  if (Number.isInteger(tabId)) {
    const tab = await getTab(tabId);
    const { audible, mutedInfo: { muted } } = tab;
    const closeElm = elm.querySelector(`.${CLASS_TAB_CLOSE}`);
    const muteElm = elm.querySelector(`.${CLASS_TAB_AUDIO}`);
    elm.classList.remove(HIGHLIGHTED);
    func.push(
      setCloseTab(closeElm, false),
      setTabAudio(muteElm, {
        audible,
        muted,
        highlighted: false
      })
    );
  }
  return Promise.all(func);
};

/**
 * toggle highlight class of tab
 *
 * @param {object} elm - element
 * @returns {Function} - addHighlight() / removeHightlight()
 */
export const toggleHighlight = async elm => {
  let func;
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    if (elm.classList.contains(HIGHLIGHTED)) {
      func = removeHighlight(elm);
    } else {
      func = addHighlight(elm);
    }
  }
  return func;
};
<commit_msg>Update tab-content.js<commit_after>/**
 * tab-content.js
 */

/* shared */
import {
  getType, isObjectNotEmpty, isString, logErr, setElementDataset,
  preventDefaultEvent, throwErr
} from './common.js';
import { getTab, updateTab } from './browser.js';
import { closeTabs, muteTabs } from './browser-tabs.js';
import { getSidebarTab, getSidebarTabId } from './util.js';
import {
  CLASS_TAB_AUDIO, CLASS_TAB_CLOSE, CLASS_TAB_CONTENT, CLASS_TAB_ICON,
  CLASS_TAB_TITLE, HIGHLIGHTED, IDENTIFIED, TAB_CLOSE, TAB_MUTE,
  TAB_MUTE_UNMUTE, TABS_CLOSE, TABS_MUTE, TABS_MUTE_UNMUTE, URL_AUDIO_MUTED,
  URL_AUDIO_PLAYING, URL_FAVICON_DEFAULT, URL_LOADING_THROBBER
} from './constant.js';

/* api */
const { i18n } = browser;

/* favicon */
export const favicon = new Map([
  [
    'https://abs.twimg.com/favicons/favicon.ico',
    '../img/twitter-logo-blue.svg'
  ],
  [
    'https://abs.twimg.com/icons/apple-touch-icon-192x192.png',
    '../img/twitter-logo-blue.svg'
  ],
  [
    'chrome://browser/skin/customize.svg',
    '../img/customize-favicon.svg'
  ],
  [
    'chrome://browser/skin/settings.svg',
    '../img/options-favicon.svg'
  ],
  [
    'chrome://mozapps/skin/extensions/extensionGeneric-16.svg',
    '../img/addons-favicon.svg'
  ],
  [
    'chrome://mozapps/skin/extensions/extension.svg',
    '../img/addons-favicon.svg'
  ]
]);

/* contextual identities icon name */
export const contextualIdentitiesIconName = new Set([
  'briefcase', 'cart', 'chill', 'dollar', 'fence', 'fingerprint', 'food',
  'fruit', 'gift', 'pet', 'tree', 'vacation'
]);

/* contextual identities icon color */
export const contextualIdentitiesIconColor = new Set([
  'blue', 'green', 'orange', 'pink', 'purple', 'red', 'turquoise', 'yellow'
]);

/**
 * tab icon fallback
 *
 * @param {object} evt - event
 * @returns {boolean} - false
 */
export const tabIconFallback = evt => {
  if (isObjectNotEmpty(evt)) {
    const { target, type } = evt;
    if (type === 'error' && target && isString(target.src)) {
      target.src = URL_FAVICON_DEFAULT;
    }
  }
  return false;
};

/**
 * add tab icon error listener
 *
 * @param {object} elm - img element
 * @returns {void}
 */
export const addTabIconErrorListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img') {
    elm.addEventListener('error', tabIconFallback);
  }
};

/**
 * set tab icon
 *
 * @param {object} elm - img element
 * @param {object} info - tab info
 * @returns {void}
 */
export const setTabIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { favIconUrl, status, title, url } = info;
    if (status === 'loading') {
      try {
        if (isString(title) && isString(url)) {
          const { href } = new URL(url);
          const connecting =
            href.replace(/\/$/, '').endsWith(title.replace(/\/$/, ''));
          if (connecting) {
            elm.dataset.connecting = url;
          } else if (elm.dataset.connecting) {
            const { stroke } = window.getComputedStyle(elm);
            elm.style.fill = stroke;
            elm.dataset.connecting = '';
          }
        } else {
          elm.dataset.connecting = url;
        }
      } catch (e) {
        logErr(e);
        elm.dataset.connecting = url;
      }
      elm.src = URL_LOADING_THROBBER;
    } else {
      elm.dataset.connecting = '';
      elm.style.fill = '';
      if (favIconUrl) {
        elm.src = favicon.get(favIconUrl) || favIconUrl;
      } else {
        elm.src = URL_FAVICON_DEFAULT;
      }
    }
  }
};

/* tab content */
/**
 * set tab content
 *
 * @param {object} tab - tab element
 * @param {object} tabsTab - tabs.Tab
 * @returns {void}
 */
export const setTabContent = async (tab, tabsTab) => {
  if (tab && tab.nodeType === Node.ELEMENT_NODE && isObjectNotEmpty(tabsTab)) {
    const { favIconUrl, status, title, url } = tabsTab;
    const tabContent = tab.querySelector(`.${CLASS_TAB_CONTENT}`);
    const tabTitle = tab.querySelector(`.${CLASS_TAB_TITLE}`);
    const tabIcon = tab.querySelector(`.${CLASS_TAB_ICON}`);
    tabContent.title = title;
    tabTitle.textContent = title;
    await setTabIcon(tabIcon, { favIconUrl, status, title, url });
    await setElementDataset(tab, 'tab', JSON.stringify(tabsTab));
  }
};

/* audio */
/**
 * handle clicked audio button
 *
 * @param {!object} evt - event
 * @returns {?Function} - muteTabs() / updateTab()
 */
export const handleClickedTabAudio = async evt => {
  const { target } = evt;
  const tab = getSidebarTab(target);
  const tabId = getSidebarTabId(tab);
  let func;
  if (Number.isInteger(tabId)) {
    const tabsTab = await getTab(tabId);
    const { mutedInfo: { muted } } = tabsTab;
    const { classList } = tab;
    if (classList.contains(HIGHLIGHTED)) {
      const selectedTabs = document.querySelectorAll(`.${HIGHLIGHTED}`);
      func = muteTabs(Array.from(selectedTabs), !muted);
    } else {
      func = updateTab(tabId, { muted: !muted });
    }
  }
  return func;
};

/**
 * handle tab audio onclick
 *
 * @param {!object} evt - Event
 * @returns {Function} - handleClickedTabAudio()
 */
export const tabAudioOnClick = evt =>
  handleClickedTabAudio(evt).catch(throwErr);

/**
 * add tab audio click event listener
 *
 * @param {object} elm - element
 * @returns {void}
 */
export const addTabAudioClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_AUDIO)) {
    elm.addEventListener('click', tabAudioOnClick);
  }
};

/**
 * set tab audio
 *
 * @param {object} elm - element
 * @param {object} info - audio info
 * @returns {void}
 */
export const setTabAudio = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && isObjectNotEmpty(info)) {
    const { audible, muted, highlighted } = info;
    if (muted) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE_UNMUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE_UNMUTE}_tooltip`);
      }
    } else if (audible) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE}_tooltip`);
      }
    } else {
      elm.title = '';
    }
  }
};

/**
 * set tab audio icon
 *
 * @param {object} elm - element
 * @param {object} info - audio info
 * @returns {void}
 */
export const setTabAudioIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { audible, muted } = info;
    if (muted) {
      elm.alt = i18n.getMessage(`${TAB_MUTE_UNMUTE}`);
      elm.src = URL_AUDIO_MUTED;
    } else if (audible) {
      elm.alt = i18n.getMessage(`${TAB_MUTE}`);
      elm.src = URL_AUDIO_PLAYING;
    } else {
      elm.alt = '';
      elm.src = '';
    }
  }
};

/* close button */
/**
 * set close tab button tooltip
 *
 * @param {object} elm - element
 * @param {boolean} highlighted - highlighted
 * @returns {void}
 */
export const setCloseTab = async (elm, highlighted) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_CLOSE)) {
    if (highlighted) {
      elm.title = i18n.getMessage(`${TABS_CLOSE}_tooltip`);
    } else {
      elm.title = i18n.getMessage(`${TAB_CLOSE}_tooltip`);
    }
  }
};

/**
 * handle clicked close button
 *
 * @param {object} evt - event
 * @returns {?Function} - closeTabs()
 */
export const handleClickedCloseButton = async evt => {
  const { target } = evt;
  const tab = getSidebarTab(target);
  let func;
  if (tab) {
    const { classList } = tab;
    if (classList.contains(HIGHLIGHTED)) {
      const selectedTabs = document.querySelectorAll(`.${HIGHLIGHTED}`);
      func = closeTabs(Array.from(selectedTabs));
    } else {
      func = closeTabs([tab]);
    }
  }
  return func || null;
};

/**
 * handle tab close button click
 *
 * @param {!object} evt - Event
 * @returns {Function} - handleClickedCloseButton()
 */
export const tabCloseOnClick = evt =>
  handleClickedCloseButton(evt).catch(throwErr);

/**
 * add tab close click listener
 *
 * @param {object} elm - element
 * @returns {void}
 */
export const addTabCloseClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE &&
      elm.classList.contains(CLASS_TAB_CLOSE)) {
    elm.addEventListener('mousedown', preventDefaultEvent);
    elm.addEventListener('click', tabCloseOnClick);
  }
};

/* contextual identities */
/**
 * set contextual identities icon
 *
 * @param {object} elm - element
 * @param {object} info - contextual identities info
 * @returns {void}
 */
export const setContextualIdentitiesIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === 'img' &&
      isObjectNotEmpty(info)) {
    const { color, icon, name } = info;
    if (contextualIdentitiesIconColor.has(color) &&
        contextualIdentitiesIconName.has(icon) &&
        isString(name)) {
      elm.alt = name;
      elm.src = `../img/${icon}.svg#${color}`;
      elm.parentNode.classList.add(IDENTIFIED);
    }
  }
};

/* highlight */
/**
 * add hightlight class to tab
 *
 * @param {object} elm - element
 * @returns {Promise.<Array>} - results of each handler
 */
export const addHighlight = async elm => {
  const func = [];
  const tabId = getSidebarTabId(elm);
  if (Number.isInteger(tabId)) {
    const tab = await getTab(tabId);
    const { audible, mutedInfo: { muted } } = tab;
    const closeElm = elm.querySelector(`.${CLASS_TAB_CLOSE}`);
    const muteElm = elm.querySelector(`.${CLASS_TAB_AUDIO}`);
    elm.classList.add(HIGHLIGHTED);
    func.push(
      setCloseTab(closeElm, true),
      setTabAudio(muteElm, {
        audible,
        muted,
        highlighted: true
      })
    );
  }
  return Promise.all(func);
};

/**
 * add highlight class to tabs
 *
 * @param {Array} tabIds - array of tab ID
 * @returns {Promise.<Array>} - results of each handler
 */
export const addHighlightToTabs = async tabIds => {
  if (!Array.isArray(tabIds)) {
    throw new TypeError(`Expected Array but got ${getType(tabIds)}.`);
  }
  const func = [];
  for (const id of tabIds) {
    const item = document.querySelector(`[data-tab-id="${id}"]`);
    if (item) {
      func.push(addHighlight(item));
    }
  }
  return Promise.all(func);
};

/**
 * remove hightlight class from tab
 *
 * @param {object} elm - element
 * @returns {Promise.<Array>} - results of each handler
 */
export const removeHighlight = async elm => {
  const func = [];
  const tabId = getSidebarTabId(elm);
  if (Number.isInteger(tabId)) {
    const tab = await getTab(tabId);
    const { audible, mutedInfo: { muted } } = tab;
    const closeElm = elm.querySelector(`.${CLASS_TAB_CLOSE}`);
    const muteElm = elm.querySelector(`.${CLASS_TAB_AUDIO}`);
    elm.classList.remove(HIGHLIGHTED);
    func.push(
      setCloseTab(closeElm, false),
      setTabAudio(muteElm, {
        audible,
        muted,
        highlighted: false
      })
    );
  }
  return Promise.all(func);
};

/**
 * toggle highlight class of tab
 *
 * @param {object} elm - element
 * @returns {Function} - addHighlight() / removeHightlight()
 */
export const toggleHighlight = async elm => {
  let func;
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    if (elm.classList.contains(HIGHLIGHTED)) {
      func = removeHighlight(elm);
    } else {
      func = addHighlight(elm);
    }
  }
  return func;
};
<|endoftext|>


<commit_before>function getAbstract(html) { //get a text string representative of the document
	var removed = $("" + html + "").remove("div").remove("iframe").remove("script"); //strip out the interactive stuff - we just want a text string
	removed.children().each(function() { //flatten the dom into something usable
														 $(this)[0].insertAdjacentHTML("beforebegin", " " + $(this).html() + " ");
															$(this).remove();
														});
	removed = removed.html();
	var brTemplate = '
';
	var re = new RegExp(brTemplate, 'g');
	removed = removed.replace(re, '');
	var abstract = removed.substring(0, 150); //the length of the abstract to return
	if(abstract) {
		return abstract;
	} else {
		return "";
	}
}

var document_id = window.location.hash.replace("#", "");

var client = new Dropbox.Client({
	key: "DROPBOX_APP_KEY"
});

// Try to finish OAuth authorization.
client.authenticate({
	interactive: false
}, function (error) {
	if (error) {
		alert('Authentication error: ' + error);
	}
});

if (client.isAuthenticated()) {

	var datastoreManager = client.getDatastoreManager();
	datastoreManager.openDefaultDatastore(function (error, datastore) {
		if (error) {
			alert('Error opening default datastore: ' + error);
		}

		var documentTable = datastore.getTable('documents');

		documentTable.setResolutionRule('content', 'sum');

		if (document_id == "new") {
			var currentDocument = documentTable.insert({
				title: "Untitled Document",
				content: "",
				abstract: " ",
				created: new Date(),
				modified: new Date()
			});

		} else {
			var currentDocument = documentTable.get(document_id);
		}

		var savedContent = currentDocument.get("content");
		var savedTitle = currentDocument.get("title");

		$(".doc-name").val(currentDocument.get("title"));

		$("#document-editor").html(currentDocument.get("content"));

		setInterval(function () {

			if ($("#document-editor").html() != savedContent || $(".doc-name").val() != savedTitle) {

				if ($(".doc-name").val() != "") {
					var docTitle = $(".doc-name").val();
				} else {
					var docTitle = "Untitled Document";
				}
				console.log("syncing to dropbox");

				savedContent = $("#document-editor").html(); //in order for recordsChanged to work correctly, these need to update before the actual records
				savedTitle = $(".doc-name").val();

				currentDocument.set('title', docTitle);
				currentDocument.set("content", $("#document-editor").html());
				currentDocument.set("modified", new Date());
				currentDocument.set("abstract", getAbstract($("#document-editor").html()));
			} //end if savedcontent
		}, 4000);
	});

} else {
	window.location = "https://standaert.net/scratchpad";
}<commit_msg>better abstract generation<commit_after>function getAbstract(html) { //get a text string representative of the document
	var removed = $("" + html + "").remove("div").remove("iframe").remove("script"); //strip out the interactive stuff - we just want a text string
	removed = removed[0].textContent;
	var brTemplate = '
';
	var re = new RegExp(brTemplate, 'g');
	removed = removed.replace(re, '');
	var abstract = removed.substring(0, 175); //the length of the abstract to return
	if(abstract) {
		return abstract;
	} else {
		return "";
	}
}

var document_id = window.location.hash.replace("#", "");

var client = new Dropbox.Client({
	key: "DROPBOX_APP_KEY"
});

// Try to finish OAuth authorization.
client.authenticate({
	interactive: false
}, function (error) {
	if (error) {
		alert('Authentication error: ' + error);
	}
});

if (client.isAuthenticated()) {

	var datastoreManager = client.getDatastoreManager();
	datastoreManager.openDefaultDatastore(function (error, datastore) {
		if (error) {
			alert('Error opening default datastore: ' + error);
		}

		var documentTable = datastore.getTable('documents');

		documentTable.setResolutionRule('content', 'sum');

		if (document_id == "new") {
			var currentDocument = documentTable.insert({
				title: "Untitled Document",
				content: "",
				abstract: " ",
				created: new Date(),
				modified: new Date()
			});

		} else {
			var currentDocument = documentTable.get(document_id);
		}

		var savedContent = currentDocument.get("content");
		var savedTitle = currentDocument.get("title");

		$(".doc-name").val(currentDocument.get("title"));

		$("#document-editor").html(currentDocument.get("content"));

		setInterval(function () {

			if ($("#document-editor").html() != savedContent || $(".doc-name").val() != savedTitle) {

				if ($(".doc-name").val() != "") {
					var docTitle = $(".doc-name").val();
				} else {
					var docTitle = "Untitled Document";
				}
				console.log("syncing to dropbox");

				savedContent = $("#document-editor").html(); //in order for recordsChanged to work correctly, these need to update before the actual records
				savedTitle = $(".doc-name").val();

				currentDocument.set('title', docTitle);
				currentDocument.set("content", $("#document-editor").html());
				currentDocument.set("modified", new Date());
				currentDocument.set("abstract", getAbstract($("#document-editor").html()));
			} //end if savedcontent
		}, 4000);
	});

} else {
	window.location = "https://standaert.net/scratchpad";
}<|endoftext|>


<commit_before>/*

            _/    _/_/    _/_/_/_/_/                              _/
               _/    _/      _/      _/_/    _/    _/    _/_/_/  _/_/_/
          _/  _/  _/_/      _/    _/    _/  _/    _/  _/        _/    _/
         _/  _/    _/      _/    _/    _/  _/    _/  _/        _/    _/
        _/    _/_/  _/    _/      _/_/      _/_/_/    _/_/_/  _/    _/
       _/
    _/

    Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/>

    (c) 2012 by jQTouch project members.
    See LICENSE.txt for license.

    Author: Thomas Yip
*/

(function($) {
    function hide(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet');
        if (data.shown) {
            $(this).data('menusheet', {});
            var $source = data.source;
            $source.unbind('touchstart mousedown', data.closehandler);
            $source.one('webkitTransitionEnd', function() {
                $source.removeClass('passe transition in');
                $target.removeClass('passe out');
                !callback || callback.apply(this, arguments);
            });

            $source.addClass('passe transition in');
            $target.addClass('passe out').removeClass('current');
            $('#jqt').removeClass('menuopened');
        }
        return $target;
    }

    function show(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet') || {};
        if (!data.shown) {
            var $source = $('#jqt .current:not(.menusheet)');
            var closehandler = function() {
                $target.menusheet('hide');
                return false;
            };

            $source.one('webkitTransitionEnd', function() {
                $source.one('touchstart mousedown', closehandler);
                $source.removeClass('passe transition out');
                $target.removeClass('passe in');
                !callback || callback.apply(this, arguments);
            });

            data.shown = true;
            data.closehandler = closehandler;
            data.source = $source;
            $(this).data('menusheet', data);

            $source.addClass('passe transition out');
            $target.addClass('current in');
            $('#jqt').addClass('menuopened');
        }
        return $target;
    }

    var methods = {
        init: function(options) {
            $(this).addClass('menusheet');
            $(this).data({shown: false});
        },
        show: show,
        hide: hide
    };

    $.fn.menusheet = function(method) {
      if (methods[method]) {
          if ($(this).is('.menusheet')) {
              return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
          } else {
              var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.';
              console.warn(msg);
          }
      } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply(this, arguments);
      } else {
          $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
      }
    };

    if ($.jQTouch) {
        var scriptpath = $("script").last().attr("src").split('?')[0].split('/').slice(0, -1).join('/')+'/';
        var csspath = scriptpath + 'jqt.menusheet.css';

        var link = $('<link href="' + csspath + '" rel="stylesheet">');
        $('head').append($(link));

        $.jQTouch.addExtension(function MenuSheet(jQT) {
            jQT.addTapHandler({
                name: 'open-menusheet',
                isSupported: function(e, params) {
                    return params.$el.is('.menu');
                },
                fn: function(e, params) {
                    params.$el.removeClass('active');

                    var $target = $(params.hash);
                    $target.menusheet('show');

                    return false;
                }
            });
            jQT.addTapHandler({
                name: 'follow-menulink',
                isSupported: function(e, params) {
                    if ($('#jqt').hasClass('menuopened')) {
                        return params.$el.is('.menusheet a');
                    }
                    return false;
                },
                fn: function(e, params) {
                    params.$el.removeClass('active');

                    var $target = params.$el.closest('.menusheet');
                    $target.menusheet('hide', function() {
                        if (!params.$el.is('.dismiss')) {
                          params.$el.trigger('tap');
                        }
                    });
                    return false;
                }
            });
            return {};
        });
    } else {
    }
})($);
<commit_msg>Moved css loading to the front of the js file<commit_after>/*

            _/    _/_/    _/_/_/_/_/                              _/
               _/    _/      _/      _/_/    _/    _/    _/_/_/  _/_/_/
          _/  _/  _/_/      _/    _/    _/  _/    _/  _/        _/    _/
         _/  _/    _/      _/    _/    _/  _/    _/  _/        _/    _/
        _/    _/_/  _/    _/      _/_/      _/_/_/    _/_/_/  _/    _/
       _/
    _/

    Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/>

    (c) 2012 by jQTouch project members.
    See LICENSE.txt for license.

    Author: Thomas Yip
*/

(function($) {
    var src = $("head script").last().attr("src") || '';
    var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/';
    var csspath = scriptpath + 'jqt.menusheet.css';
    var link = $('<link href="' + csspath + '" rel="stylesheet">');
    $('head').append($(link));

    function hide(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet');
        if (data.shown) {
            $(this).data('menusheet', {});
            var $source = data.source;
            $source.unbind('touchstart mousedown', data.closehandler);
            $source.one('webkitTransitionEnd', function() {
                $source.removeClass('passe transition in');
                $target.removeClass('passe out');
                !callback || callback.apply(this, arguments);
            });

            $source.addClass('passe transition in');
            $target.addClass('passe out').removeClass('current');
            $('#jqt').removeClass('menuopened');
        }
        return $target;
    }

    function show(callback) {
        var $target = $(this);
        var data = $(this).data('menusheet') || {};
        if (!data.shown) {
            var $source = $('#jqt .current:not(.menusheet)');
            var closehandler = function() {
                $target.menusheet('hide');
                return false;
            };

            $source.one('webkitTransitionEnd', function() {
                $source.one('touchstart mousedown', closehandler);
                $source.removeClass('passe transition out');
                $target.removeClass('passe in');
                !callback || callback.apply(this, arguments);
            });

            data.shown = true;
            data.closehandler = closehandler;
            data.source = $source;
            $(this).data('menusheet', data);

            $source.addClass('passe transition out');
            $target.addClass('current in');
            $('#jqt').addClass('menuopened');
        }
        return $target;
    }

    var methods = {
        init: function(options) {
            $(this).addClass('menusheet');
            $(this).data({shown: false});
        },
        show: show,
        hide: hide
    };

    $.fn.menusheet = function(method) {
      if (methods[method]) {
          if ($(this).is('.menusheet')) {
              return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
          } else {
              var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.';
              console.warn(msg);
          }
      } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply(this, arguments);
      } else {
          $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
      }
    };

    if ($.jQTouch) {
        $.jQTouch.addExtension(function MenuSheet(jQT) {
            jQT.addTapHandler({
                name: 'open-menusheet',
                isSupported: function(e, params) {
                    return params.$el.is('.menu');
                },
                fn: function(e, params) {
                    params.$el.removeClass('active');

                    var $target = $(params.hash);
                    $target.menusheet('show');

                    return false;
                }
            });
            jQT.addTapHandler({
                name: 'follow-menulink',
                isSupported: function(e, params) {
                    if ($('#jqt').hasClass('menuopened')) {
                        return params.$el.is('.menusheet a');
                    }
                    return false;
                },
                fn: function(e, params) {
                    params.$el.removeClass('active');

                    var $target = params.$el.closest('.menusheet');
                    $target.menusheet('hide', function() {
                        if (!params.$el.is('.dismiss')) {
                          params.$el.trigger('tap');
                        }
                    });
                    return false;
                }
            });
            return {};
        });
    } else {
        console.error('Extension `jqt.menusheet` failed to load. jQT not found');
    }
})($);
<|endoftext|>


<commit_before>import { capture } from 'global/capture';
import { extend } from 'utils/object';
import Computation from './Computation';
import Model from './Model';
import { handleChange, mark } from 'shared/methodCallers';

export default class RootModel extends Model {
	constructor ( options ) {
		super( null, null );

		// TODO deprecate this
		this.changes = {};

		this.isRoot = true;
		this.root = this;
		this.ractive = options.ractive; // TODO sever this link

		this.value = options.data;
		this.adaptors = options.adapt;
		this.adapt();

		this.mappings = {};

		this.computationContext = options.ractive;
		this.computations = {};

		if ( options.computations ) {
			Object.keys( options.computations ).forEach( key => {
				const signature = options.computations[ key ];
				const computation = this.compute( key, signature );
				computation.init();
			});
		}
	}

	applyChanges () {
		this._changeHash = {};
		this.flush();

		return this._changeHash;
	}

	compute ( key, signature ) {
		const computation = new Computation( this, signature, key );
		this.computations[ key ] = computation;

		return computation;
	}

	get ( shouldCapture ) {
		if ( shouldCapture ) capture( this );
		let result = extend( {}, this.value );

		Object.keys( this.mappings ).forEach( key => {
			result[ key ] = this.mappings[ key ].value;
		});

		Object.keys( this.computations ).forEach( key => {
			if ( key[0] !== '@' ) { // exclude template expressions
				result[ key ] = this.computations[ key ].value;
			}
		});

		return result;
	}

	getKeypath () {
		return '';
	}

	has ( key ) {
		return ( key in this.mappings ) || ( key in this.computations ) || super.has( key );
	}

	joinKey ( key ) {
		return this.mappings.hasOwnProperty( key ) ? this.mappings[ key ] :
		       this.computations.hasOwnProperty( key ) ? this.computations[ key ] :
		       super.joinKey( key );
	}

	map ( localKey, origin ) {
		// TODO remapping
		this.mappings[ localKey ] = origin;
	}

	set ( value ) {
		// TODO wrapping root node is a baaaad idea. We should prevent this
		const wrapper = this.wrapper;
		if ( wrapper ) {
			const shouldTeardown = !wrapper.reset || wrapper.reset( value ) === false;

			if ( shouldTeardown ) {
				wrapper.teardown();
				this.wrapper = null;
				this.value = value;
				this.adapt();
			}
		} else {
			this.value = value;
			this.adapt();
		}

		this.deps.forEach( handleChange );
		this.children.forEach( mark );
		this.clearUnresolveds(); // TODO do we need to do this with primitive values? if not, what about e.g. unresolved `length` property of null -> string?
	}

	retrieve () {
		return this.value;
	}

	update () {
		// noop
	}

	updateFromBindings ( cascade ) {
		super.updateFromBindings( cascade );

		if ( cascade ) {
			// TODO computations as well?
			Object.keys( this.mappings ).forEach( key => {
				const model = this.mappings[ key ];
				model.updateFromBindings( cascade );
			});
		}
	}
}
<commit_msg>remove some unused code<commit_after>import { capture } from 'global/capture';
import { extend } from 'utils/object';
import Computation from './Computation';
import Model from './Model';
import { handleChange, mark } from 'shared/methodCallers';

export default class RootModel extends Model {
	constructor ( options ) {
		super( null, null );

		// TODO deprecate this
		this.changes = {};

		this.isRoot = true;
		this.root = this;
		this.ractive = options.ractive; // TODO sever this link

		this.value = options.data;
		this.adaptors = options.adapt;
		this.adapt();

		this.mappings = {};

		this.computationContext = options.ractive;
		this.computations = {};
	}

	applyChanges () {
		this._changeHash = {};
		this.flush();

		return this._changeHash;
	}

	compute ( key, signature ) {
		const computation = new Computation( this, signature, key );
		this.computations[ key ] = computation;

		return computation;
	}

	get ( shouldCapture ) {
		if ( shouldCapture ) capture( this );
		let result = extend( {}, this.value );

		Object.keys( this.mappings ).forEach( key => {
			result[ key ] = this.mappings[ key ].value;
		});

		Object.keys( this.computations ).forEach( key => {
			if ( key[0] !== '@' ) { // exclude template expressions
				result[ key ] = this.computations[ key ].value;
			}
		});

		return result;
	}

	getKeypath () {
		return '';
	}

	has ( key ) {
		return ( key in this.mappings ) || ( key in this.computations ) || super.has( key );
	}

	joinKey ( key ) {
		return this.mappings.hasOwnProperty( key ) ? this.mappings[ key ] :
		       this.computations.hasOwnProperty( key ) ? this.computations[ key ] :
		       super.joinKey( key );
	}

	map ( localKey, origin ) {
		// TODO remapping
		this.mappings[ localKey ] = origin;
	}

	set ( value ) {
		// TODO wrapping root node is a baaaad idea. We should prevent this
		const wrapper = this.wrapper;
		if ( wrapper ) {
			const shouldTeardown = !wrapper.reset || wrapper.reset( value ) === false;

			if ( shouldTeardown ) {
				wrapper.teardown();
				this.wrapper = null;
				this.value = value;
				this.adapt();
			}
		} else {
			this.value = value;
			this.adapt();
		}

		this.deps.forEach( handleChange );
		this.children.forEach( mark );
		this.clearUnresolveds(); // TODO do we need to do this with primitive values? if not, what about e.g. unresolved `length` property of null -> string?
	}

	retrieve () {
		return this.value;
	}

	update () {
		// noop
	}

	updateFromBindings ( cascade ) {
		super.updateFromBindings( cascade );

		if ( cascade ) {
			// TODO computations as well?
			Object.keys( this.mappings ).forEach( key => {
				const model = this.mappings[ key ];
				model.updateFromBindings( cascade );
			});
		}
	}
}
<|endoftext|>