<commit_before>/* First thing is first need to call back to the sever to get the name and
picture url */
var loadProfile = function(){
    $.ajax({
        url: '/profile',
        dataType: 'json',
        success: function(profile) {
            $('div.lightbox').remove();
            $('#container p').html('Hi '+profile.name.givenName+', (test) thank you for your interest in sendmail.
This app is still in development, but will be done in about a month (because it\'s due for a class!). Feel free to come back then. None of your credentials have been saved in the meantime =)
');
            $('#container').append('');
            $('#container').append('
Click here to logout
');

            //TODO update stuff according to profile
        },
        error: function(xhr, status, error) {
            if (xhr.status === 409) { //content just isnt ready
                setTimeout(function(){ loadProfile(); }, 500);
            } else {
                var err = $('
');
                err.html(xhr.status+': There was an error fetching your profile.'+
                'Please refresh to try again. Sorry!');
                $('body').prepend(err);
            }
        }
    });
};
loadProfile();

$(document).ready(function(){
    /* Bind listeners here */
    $('#container').on('click', '#logout', function(){
        $.ajax({
            url: '/logout',
            success: function(){
                window.location.href = '/';
            },
            error: function(){
                var err = $('
');
                err.html(xhr.status+': There was an error logging you out.'+
                'Please refresh to try again / see if it worked anyways. Sorry!');
                $('body').prepend(err);
            }
        });
    });

});

<commit_msg>Minor edits<commit_after>/* First thing is first need to call back to the sever to get the name and
picture url */
var loadProfile = function(){
    $.ajax({
        url: '/profile',
        dataType: 'json',
        success: function(profile) {
            $('div.lightbox').remove();
            $('#container p').html('Hi '+profile.name.givenName+', thank you for your interest in SendMail.
This app is still in development, but will be finished in about a month (because it\'s due for a class!). Feel free to come back then. None of your credentials have been saved in the meantime =)
');
            $('#container').append('');
            $('#container').append('
Click here to logout
');

            //TODO update stuff according to profile
        },
        error: function(xhr, status, error) {
            if (xhr.status === 409) { //content just isnt ready
                setTimeout(function(){ loadProfile(); }, 500);
            } else {
                var err = $('
');
                err.html(xhr.status+': There was an error fetching your profile.'+
                'Please refresh to try again. Sorry!');
                $('body').prepend(err);
            }
        }
    });
};
loadProfile();

$(document).ready(function(){
    /* Bind listeners here */
    $('#container').on('click', '#logout', function(){
        $.ajax({
            url: '/logout',
            success: function(){
                window.location.href = '/';
            },
            error: function(){
                var err = $('
');
                err.html(xhr.status+': There was an error logging you out.'+
                'Please refresh to try again / see if it worked anyways. Sorry!');
                $('body').prepend(err);
            }
        });
    });

});

<|endoftext|>


<commit_before>angular.module('travel.services', [])

////////////////// Groups //////////////////////

.factory('Groups', function ($http) {
  // HTTP REQ FUNCTIONS
  var addParticipants = function(data) {
    return $http({
      method: 'POST',
      url: '/api/group/add',
      data: data
    });
  };
  var createGroup = function(data){
    return $http({
      method: 'POST',
      url: '/api/group',
      data: data
    })
    .then(function (resp) {
      return resp.data;
    });
  };
  var getUserGroups = function(userId){
    return $http({
      method: 'GET',
      url: '/api/group',
      data: { userId: userId }
    })
    .then(function(resp){
      return resp.data;
    });
  };

  // NOT HTTP REQ FUNCTIONS
  var selectGroup = function (groupInfo, _$rootScope_) {
    _$rootScope_.currentGroup = groupInfo;
    _$rootScope_.destinationPermalink = groupInfo.destination;
  };

  return {
    // HTTP REQ FUNCTIONS
    getUserGroups: getUserGroups,
    createGroup: createGroup,
    addParticipants: addParticipants,

    // NOT HTTP REQ FUNCTIONS
    selectGroup: selectGroup,
  };
})

////////////////// CITY //////////////////////

.factory('City', function ($http) {
  var getCity = function(destPermalink){
    return $http({
      method: 'GET',
      url: '/api/dest',
      params: { name: destPermalink }
    })
    .then(function(resp){
      return resp.data;
    });
  };

  return {
    getCity: getCity
  };
})

////////////////// UTIL //////////////////////

.factory('Util', function () {
  var transToPermalink = function (string) {
    // Leave commented-out to let the server throw errors for now
    // if (!string) return;

    return string.trim().replace(/\s+/g, '-').toLowerCase();
  };

  return {
    transToPermalink: transToPermalink
  };
})

////////////////// VENUES //////////////////////

.factory('Venues', function ($http) {

  ////////////////// PLACES TO EXPLORE //////////////////////

  var getVenues = function(query){
    return $http({
      method: 'GET',
      url: '/api/dest/venues',
      params: query
    })
    .then(function successCb (resp){
      return resp.data;
    }, function errCb (resp) {
      console.error(resp);
      return resp;
    });
  };

  ////////////////// FAVORITES //////////////////////

  var getRatings = function(query){
    return $http({
      method: 'GET',
      url: '/api/rating',
      params: query
    })
    .then(function(resp){
      return resp.data;
    });
  };

  var getUserFavorites = function (userId) {
    return $http({
      method: 'GET',
      url: '/api/fav/user',
      params: {userId: userId}
    })
    .then(function(resp) {
      console.log(resp.data);
      return resp.data;
    });
  };

  var addToUserFavorites = function (venue, userId) {
    return $http({
      method: 'POST',
      url: '/api/fav',
      data: data
    });
  };

  var addRating = function(data) {
    return $http({
      method: 'POST',
      url: '/api/rating',
      data: data
    });
  };

  ////////////////// GROUP FAVORITES - ADMIN ONLY //////////////////////

  var addtoItinerary = function(data) {
    return $http({
      method: 'POST',
      url: '/api/itin',
      data: data
    });
  };

  ////////////////// ITINERARY //////////////////////

  var getItinerary = function(query){
    return $http({
      method: 'GET',
      url: '/api/itin',
      params: {query: query}
    })
    .then(function(resp){
      return resp.data;
    });
  };

  return {
    getVenues: getVenues,
    getUserFavorites: getUserFavorites,
    addToUserFavorites: addToUserFavorites,
    addRating: addRating,
    getRatings: getRatings,
    getItinerary: getItinerary,
    addtoItinerary: addtoItinerary
  };

})

////////////////// TRANSFACTORY STORAGE //////////////////////

.factory('CurrentInfo', function ($http) {
  var destination = {
    name: null,
    basicInfo: null,
    venues: null
  };
  return {
    destination: destination
  };
})

// ////////////////// SESSION STORAGE //////////////////////

// .factory('SessionStorage', function ($http, $location, $window) {
//   var sessionExists = function () {
//     return !!$window.sessionStorage.getItem('knowhere');
//   };

//   return {
//     sessionExists: sessionExists
//   };
// });
<commit_msg>fixing jshint<commit_after>angular.module('travel.services', [])

////////////////// Groups //////////////////////

.factory('Groups', function ($http) {
  // HTTP REQ FUNCTIONS
  var addParticipants = function(data) {
    return $http({
      method: 'POST',
      url: '/api/group/add',
      data: data
    });
  };
  var createGroup = function(data){
    return $http({
      method: 'POST',
      url: '/api/group',
      data: data
    })
    .then(function (resp) {
      return resp.data;
    });
  };
  var getUserGroups = function(userId){
    return $http({
      method: 'GET',
      url: '/api/group',
      data: { userId: userId }
    })
    .then(function(resp){
      return resp.data;
    });
  };

  // NOT HTTP REQ FUNCTIONS
  var selectGroup = function (groupInfo, _$rootScope_) {
    _$rootScope_.currentGroup = groupInfo;
    _$rootScope_.destinationPermalink = groupInfo.destination;
  };

  return {
    // HTTP REQ FUNCTIONS
    getUserGroups: getUserGroups,
    createGroup: createGroup,
    addParticipants: addParticipants,

    // NOT HTTP REQ FUNCTIONS
    selectGroup: selectGroup,
  };
})

////////////////// CITY //////////////////////

.factory('City', function ($http) {
  var getCity = function(destPermalink){
    return $http({
      method: 'GET',
      url: '/api/dest',
      params: { name: destPermalink }
    })
    .then(function(resp){
      return resp.data;
    });
  };

  return {
    getCity: getCity
  };
})

////////////////// UTIL //////////////////////

.factory('Util', function () {
  var transToPermalink = function (string) {
    // Leave commented-out to let the server throw errors for now
    // if (!string) return;

    return string.trim().replace(/\s+/g, '-').toLowerCase();
  };

  return {
    transToPermalink: transToPermalink
  };
})

////////////////// VENUES //////////////////////

.factory('Venues', function ($http) {

  ////////////////// PLACES TO EXPLORE //////////////////////

  var getVenues = function(query){
    return $http({
      method: 'GET',
      url: '/api/dest/venues',
      params: query
    })
    .then(function successCb (resp){
      return resp.data;
    }, function errCb (resp) {
      console.error(resp);
      return resp;
    });
  };

  ////////////////// FAVORITES //////////////////////

  var getRatings = function(query){
    return $http({
      method: 'GET',
      url: '/api/rating',
      params: query
    })
    .then(function(resp){
      return resp.data;
    });
  };

  var getUserFavorites = function (userId) {
    return $http({
      method: 'GET',
      url: '/api/fav/user',
      params: {userId: userId}
    })
    .then(function(resp) {
      console.log(resp.data);
      return resp.data;
    });
  };

  var addToUserFavorites = function (venue, userId) {
    return $http({
      method: 'POST',
      url: '/api/fav',
      data: data
    });
  };

  var addRating = function(data) {
    return $http({
      method: 'POST',
      url: '/api/rating',
      data: data
    });
  };

  ////////////////// GROUP FAVORITES - ADMIN ONLY //////////////////////

  var addtoItinerary = function(data) {
    return $http({
      method: 'POST',
      url: '/api/itin',
      data: data
    });
  };

  ////////////////// ITINERARY //////////////////////

  var getItinerary = function(query){
    return $http({
      method: 'GET',
      url: '/api/itin',
      params: {query: query}
    })
    .then(function(resp){
      return resp.data;
    });
  };

  return {
    getVenues: getVenues,
    getUserFavorites: getUserFavorites,
    addToUserFavorites: addToUserFavorites,
    addRating: addRating,
    getRatings: getRatings,
    getItinerary: getItinerary,
    addtoItinerary: addtoItinerary
  };

})

////////////////// TRANSFACTORY STORAGE //////////////////////

.factory('CurrentInfo', function ($http) {
  var destination = {
    name: null,
    basicInfo: null,
    venues: null
  };
  return {
    destination: destination
  };
});

// ////////////////// SESSION STORAGE //////////////////////

// .factory('SessionStorage', function ($http, $location, $window) {
//   var sessionExists = function () {
//     return !!$window.sessionStorage.getItem('knowhere');
//   };

//   return {
//     sessionExists: sessionExists
//   };
// });
<|endoftext|>


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

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    items:[
        {
            xtype: 'panel',
            layout: 'anchor',
            border: true,
            fieldDefaults: {
                labelWidth: 40
            },
            defaultType: 'textfield',
            bodyPadding: 5,
            items: [
                {
                    fieldLabel: 'Query',
                    itemId: 'queryField',
                    anchor:'100%',
                    width: 700,
                    height: 100,
                    xtype: 'textarea',
                    value: '{\n'+
                            '    "$and": [ {"KanbanState": {"$gte":"In Dev"}}, {"KanbanState": {"$lt":"Accepted"}} ],\n'+
                            '    "__At": "current"\n'+
                            '}'
                },
                {
                    fieldLabel: 'Fields',
                    itemId: 'fieldsField',
                    anchor: '100%',
                    width: 700,
                    value: "ObjectID, KanbanState"
                },
                {
                    fieldLabel: 'Sort',
                    itemId: 'sortField',
                    anchor: '100%',
                    width: 700,
                    value: "{'ObjectID' : -1, '_ValidFrom': 1}"
                },
                {
                    fieldLabel: 'Page Size',
                    itemId: 'pageSizeField',
                    anchor: '100%',
                    width: 700,
                    value: '1000'
                }
            ],

            buttons: [
                {
                    xtype: 'rallybutton',
                    text: 'Chart It!',
                    itemId: 'chartButton'
                }
            ]
        },
        {
            xtype: 'panel',
            itemId: 'chartHolder',
            layout: 'fit',
            height: 400,
            margin: '0 0 200 0'
        }
    ],
    launch: function() {
        var button = this.down('#chartButton');
        button.on('click', this.chartClicked, this);
    },

    chartClicked: function(){

        var queryField = this.down('#queryField');
        var query = queryField.getValue();
        var selectedFields = this.down('#fieldsField').getValue();
        if(selectedFields){
            if(selectedFields === 'true'){
                selectedFields = true;
            }
            else{
                selectedFields = selectedFields.split(', ');
            }
        }

        var sort = this.down('#sortField').getValue();

        var pageSize = this.down('#pageSizeField').getValue();
        var parsedPageSize = parseInt(pageSize, 10);
        // don't allow empty or 0 pagesize
        pageSize = (parsedPageSize) ? parsedPageSize : 10;

        var callback = Ext.bind(this.processSnapshots, this);
        this.doSearch(query, selectedFields, sort, pageSize, callback);
    },

    createSortMap: function(csvFields){
        var fields = csvFields.split(', ');
        var sortMap = {};
        for(var field in fields){
            if(fields.hasOwnProperty(field)){
                sortMap[field] = 1;
            }
        }

        return sortMap;
    },

    doSearch: function(query, fields, sort, pageSize, callback){
        var workspace = this.context.getWorkspace().ObjectID;
        var queryUrl = 'https://rally1.rallydev.com/analytics/1.32/'+ workspace +
                        '/artifact/snapshot/query.js';
        var params = {
            find: query
        };

        if(fields){
            //TODO can't handle $slice expression
            params.fields = Ext.JSON.encode(fields);
        }

        if(sort){
            params.sort = sort;
        }

        if(pageSize){
            params.pagesize = pageSize;
        }

        Ext.Ajax.cors = true;
        Ext.Ajax.request({
            url: queryUrl,
            method: 'GET',
            params: params,
            withCredentials: true,
            success: function(response){
                var text = response.responseText;
                var json = Ext.JSON.decode(text);
                callback(json.Results);
            }
        });
    },

    processSnapshots: function(snapshots){
        var groupBySpec = {
        	groupBy: 'KanbanState',
        	aggregations: [
        		{
        			field: 'ObjectID',
        			f: '$count'
        		}
        	]
        };

        var groups = lumenize.groupBy(snapshots, groupBySpec);
        var rows = this.convertGroupingsToRows(groups);

        var snapshotStore = Ext.create('Ext.data.Store', {
            storeId:'snapshotStore',
            fields: ["KanbanState", "ObjectID_Count"],
            data: rows,
            proxy: {
                type: 'memory',
                reader: {
                    type: 'json',
                    root: 'rows'
                }
            }
        });

		var chart = {
			xtype : 'rallychart',
			id : 'chart',
			height: 400,
			series : [{
			  type : 'column',
			  dataIndex : 'ObjectID_Count',
			  name : 'Count',
			  visible : true
			}],
			store : snapshotStore,
			xField : 'KanbanState',
			chartConfig : {
			  chart : {
				marginRight : 130,
				marginBottom : 250,
				zoomType : 'x',
				animation : {
				  duration : 1500,
				  easing : 'swing'
				}
			  },
			  title : {
				text : 'Kanban State Counts',
				align: 'center'
			  },
			  xAxis : [{
				title : {
				  text : 'KanbanState',
				  margin : 40
				},
				labels : {
				  align: 'right',
				  rotation : 300
				}
			  }],
			  yAxis : {
				title : {
				  text : 'Count'
				},
				plotLines : [{
				  value : 0,
				  width : 1,
				  color : '#808080'
				}]
			  },
			  plotOptions : {
				series : {
				  animation : {
					duration : 3000,
					easing : 'swing'
				  }
				}
			  },
			  tooltip : {
				formatter : function() {
				  return this.x + ': ' + this.y;
				}
			  },
			  legend : {
				layout : 'vertical',
				align : 'right',
				verticalAlign : 'top',
				x : -10,
				y : 100,
				borderWidth : 0
			  }
			}
		  };

        var chartHolder = this.down('#chartHolder');
        chartHolder.removeAll(true);
        chartHolder.add(chart);
    },

    convertGroupingsToRows: function(groups){
    	var rows = [];

    	for(var group in groups){
    		if( groups.hasOwnProperty(group) ){
    			rows.push({
    				"KanbanState": group,
    				"ObjectID_Count": groups[group]['ObjectID_$count']
    			});
    		}
    	}

    	return { "rows": rows };
    },

    getFieldsFromSnapshots: function(snapshots){
        if(snapshots.length === 0){
            return [];
        }

        var snapshot = snapshots[0];
        var fields = [];
        for(var key in snapshot){
            if (snapshot.hasOwnProperty(key)){
                fields.push(key);
            }
        }

        return fields;
    },

    createColumnsForFields: function(fields){
        var columns = [];
        for(var i=0; i < fields.length; ++i){
            var col = {
                header: fields[i],
                dataIndex: fields[i]
            };

            if(fields[i] === 'Name'){
                col.flex = 1;
            }
            columns.push(col);
        }

        return columns;
    }
});<commit_msg>Made the bars red.<commit_after>var lumenize = require('./lumenize');

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    items:[
        {
            xtype: 'panel',
            layout: 'anchor',
            border: true,
            fieldDefaults: {
                labelWidth: 40
            },
            defaultType: 'textfield',
            bodyPadding: 5,
            items: [
                {
                    fieldLabel: 'Query',
                    itemId: 'queryField',
                    anchor:'100%',
                    width: 700,
                    height: 100,
                    xtype: 'textarea',
                    value: '{\n'+
                            '    "$and": [ {"KanbanState": {"$gte":"In Dev"}}, {"KanbanState": {"$lt":"Accepted"}} ],\n'+
                            '    "__At": "current"\n'+
                            '}'
                },
                {
                    fieldLabel: 'Fields',
                    itemId: 'fieldsField',
                    anchor: '100%',
                    width: 700,
                    value: "ObjectID, KanbanState"
                },
                {
                    fieldLabel: 'Sort',
                    itemId: 'sortField',
                    anchor: '100%',
                    width: 700,
                    value: "{'ObjectID' : -1, '_ValidFrom': 1}"
                },
                {
                    fieldLabel: 'Page Size',
                    itemId: 'pageSizeField',
                    anchor: '100%',
                    width: 700,
                    value: '1000'
                }
            ],

            buttons: [
                {
                    xtype: 'rallybutton',
                    text: 'Chart It!',
                    itemId: 'chartButton'
                }
            ]
        },
        {
            xtype: 'panel',
            itemId: 'chartHolder',
            layout: 'fit',
            height: 400,
            margin: '0 0 200 0'
        }
    ],
    launch: function() {
        var button = this.down('#chartButton');
        button.on('click', this.chartClicked, this);
    },

    chartClicked: function(){

        var queryField = this.down('#queryField');
        var query = queryField.getValue();
        var selectedFields = this.down('#fieldsField').getValue();
        if(selectedFields){
            if(selectedFields === 'true'){
                selectedFields = true;
            }
            else{
                selectedFields = selectedFields.split(', ');
            }
        }

        var sort = this.down('#sortField').getValue();

        var pageSize = this.down('#pageSizeField').getValue();
        var parsedPageSize = parseInt(pageSize, 10);
        // don't allow empty or 0 pagesize
        pageSize = (parsedPageSize) ? parsedPageSize : 10;

        var callback = Ext.bind(this.processSnapshots, this);
        this.doSearch(query, selectedFields, sort, pageSize, callback);
    },

    createSortMap: function(csvFields){
        var fields = csvFields.split(', ');
        var sortMap = {};
        for(var field in fields){
            if(fields.hasOwnProperty(field)){
                sortMap[field] = 1;
            }
        }

        return sortMap;
    },

    doSearch: function(query, fields, sort, pageSize, callback){
        var workspace = this.context.getWorkspace().ObjectID;
        var queryUrl = 'https://rally1.rallydev.com/analytics/1.32/'+ workspace +
                        '/artifact/snapshot/query.js';
        var params = {
            find: query
        };

        if(fields){
            //TODO can't handle $slice expression
            params.fields = Ext.JSON.encode(fields);
        }

        if(sort){
            params.sort = sort;
        }

        if(pageSize){
            params.pagesize = pageSize;
        }

        Ext.Ajax.cors = true;
        Ext.Ajax.request({
            url: queryUrl,
            method: 'GET',
            params: params,
            withCredentials: true,
            success: function(response){
                var text = response.responseText;
                var json = Ext.JSON.decode(text);
                callback(json.Results);
            }
        });
    },

    processSnapshots: function(snapshots){
        var groupBySpec = {
        	groupBy: 'KanbanState',
        	aggregations: [
        		{
        			field: 'ObjectID',
        			f: '$count'
        		}
        	]
        };

        var groups = lumenize.groupBy(snapshots, groupBySpec);
        var rows = this.convertGroupingsToRows(groups);

        var snapshotStore = Ext.create('Ext.data.Store', {
            storeId:'snapshotStore',
            fields: ["KanbanState", "ObjectID_Count"],
            data: rows,
            proxy: {
                type: 'memory',
                reader: {
                    type: 'json',
                    root: 'rows'
                }
            }
        });

		var chart = {
			xtype : 'rallychart',
			id : 'chart',
			height: 400,
			series : [{
			  type : 'column',
			  dataIndex : 'ObjectID_Count',
			  name : 'Count',
			  visible : true
			}],
			store : snapshotStore,
			xField : 'KanbanState',
			chartConfig : {
			  chart : {
				marginRight : 130,
				marginBottom : 250,
				zoomType : 'x',
				animation : {
				  duration : 1500,
				  easing : 'swing'
				}
			  },
			  title : {
				text : 'Kanban State Counts',
				align: 'center'
			  },
			  xAxis : [{
				title : {
				  text : 'KanbanState',
				  margin : 40
				},
				labels : {
				  align: 'right',
				  rotation : 300
				}
			  }],
			  yAxis : {
				title : {
				  text : 'Count'
				},
				plotLines : [{
				  value : 0,
				  width : 1,
				  color : '#808080'
				}]
			  },
			  plotOptions : {
				  column: {
					  color: '#F00'
				  },
				series : {
				  animation : {
					duration : 3000,
					easing : 'swing'
				  }
				}
			  },
			  tooltip : {
				formatter : function() {
				  return this.x + ': ' + this.y;
				}
			  },
			  legend : {
				layout : 'vertical',
				align : 'right',
				verticalAlign : 'top',
				x : -10,
				y : 100,
				borderWidth : 0
			  }
			}
		  };

        var chartHolder = this.down('#chartHolder');
        chartHolder.removeAll(true);
        chartHolder.add(chart);
    },

    convertGroupingsToRows: function(groups){
    	var rows = [];

    	for(var group in groups){
    		if( groups.hasOwnProperty(group) ){
    			rows.push({
    				"KanbanState": group,
    				"ObjectID_Count": groups[group]['ObjectID_$count']
    			});
    		}
    	}

    	return { "rows": rows };
    },

    getFieldsFromSnapshots: function(snapshots){
        if(snapshots.length === 0){
            return [];
        }

        var snapshot = snapshots[0];
        var fields = [];
        for(var key in snapshot){
            if (snapshot.hasOwnProperty(key)){
                fields.push(key);
            }
        }

        return fields;
    },

    createColumnsForFields: function(fields){
        var columns = [];
        for(var i=0; i < fields.length; ++i){
            var col = {
                header: fields[i],
                dataIndex: fields[i]
            };

            if(fields[i] === 'Name'){
                col.flex = 1;
            }
            columns.push(col);
        }

        return columns;
    }
});<|endoftext|>


<commit_before>Ext.define('IterationStatusHistory', {
    extend: 'Rally.app.TimeboxScopedApp',
    componentCls: 'app',
    scopeType: 'iteration',
    layout: {
      type: 'vbox',
      align: 'stretch'
    },

    snapshotIndex: 0,

    launch: function() {
      this.callParent(arguments);
      this.add({
        flex: 1,
        xtype: 'container',
        layout: {
          type: 'vbox',
          align: 'stretch'
        },
        items: [{
          xtype: 'container',
          width: 600,
          items: [{
            xtype: 'rallybutton',
            iconCls: 'icon-right',
            width: 32,
            margin: '10 0 10 10',
            cls: 'rly-small secondary',
            listeners: {
              click: this._play,
              scope: this
            }
          },{
            xtype: 'rallybutton',
            iconCls: 'icon-pause',
            width: 32,
            margin: '10 0 10 10',
            cls: 'rly-small secondary',
            listeners: {
              click: this._pause,
              scope: this
            }
          },{
            xtype: 'container',
            margin: '10',
            id: 'date-display'
          }]
        }, {
          xtype: 'container',
          itemId: 'chartContainer',
          height: 110
        }, {
          xtype: 'container',
          id: 'board-container',
          flex: 1,
          layout: 'fit',
          items: [{
            xtype: 'rallycardboard',
            id: 'card-board',
            attribute : 'ScheduleState',
            types: ['Defect', 'HierarchicalRequirement', 'TestSet', 'DefectSuite'],
            storeConfig : {
              autoLoad: false
            },
            columnConfig: {
              isMatchingRecord: function(record) {
                return record.get(this.attribute) === this.getValue();
              }
            },
            cardConfig: {
              fields: ['PlanEstimate']
            },
            rowConfig: {
              field: 'Expedite'
            }
          }]
        }]
      });
    },

    onScopeChange: function() {
      var iterationName = this.getContext().getTimeboxScope()
        .getRecord().get('Name');

      this._getIterationOIDs(iterationName)
        .then(this._getSnapshotData.bind(this));
    },

    _getIterationOIDs: function(iterationName) {
      var promise = Ext.create('Deft.Deferred');

      Ext.create('Rally.data.wsapi.Store', {
        autoLoad: true,
        limit: Infinity,
        fetch: ['StartDate', 'EndDate', 'ObjectID', 'PlannedVelocity'],
        model: 'Iteration',
        filters: [{
          property: 'Name',
          value: iterationName
        }],
        listeners: {
          load: function(store, data) {
            promise.resolve(data);
          }
        }
      });

      return promise;
    },

    _getSnapshotData: function(iterationRecords) {
      this.iterations = iterationRecords;
      var iteration = this.getContext().getTimeboxScope().getRecord();
      var startDate = iteration.get('StartDate');
      var endDate = iteration.get('EndDate');
      this.dateSeries = this._getDateSeries(startDate, endDate);
      var iterationOIDs = _.map(iterationRecords, function(iterationRecord) {
        return iterationRecord.getId();
      });

      Deft.Chain.parallel(_.map(this.dateSeries, function(date) {
        return function() {
          var promise = Ext.create('Deft.Deferred');

          Ext.create('Rally.data.lookback.SnapshotStore', {
            autoLoad: true,
            fetch: ['_TypeHierarchy', 'Name', 'ScheduleState', 'FormattedID', 'PlanEstimate', 'Owner', 'Blocked', 'Ready', 'BlockedReason', 'State', 'Expedite'],
            hydrate: ['ScheduleState', '_TypeHierarchy', 'Owner', 'State'],
            limit: Infinity,
            filters: [{
              property: '__At',
              value: Rally.util.DateTime.toIsoString(date)
            },{
              property: '_TypeHierarchy',
              operator: 'in',
              value: ['Defect', 'HierarchicalRequirement', 'TestSet', 'DefectSuite']
            },{
              property: 'Iteration',
              operator: 'in',
              value: iterationOIDs
            }],
            sorters: [{
              property: 'ObjectID',
              direction: 'ASC'
            }],
            listeners: {
              load: function(store, snapshots) {
                promise.resolve(snapshots);
              }
            }
          });

          return promise;
        };
      })).then((function(snapshotData) {
        var userOIDs = _.unique(_.compact(_.flatten(_.map(snapshotData, function(snapshots) {
          return _.map(snapshots, function(snapshot) {
            return snapshot.get('Owner');
          });
        }))));

        this._getUserNameMap(userOIDs).then((function(userNameMap) {
          _.each(snapshotData, function(snapshots) {
            _.each(snapshots, function(snapshot) {
              snapshot.set('_id', snapshot.get('ObjectID'));
              snapshot.set('_ref', '/' + _.last(snapshot.get('_TypeHierarchy')).toLowerCase() + '/' + snapshot.get('ObjectID'));
              if (snapshot.get('Owner')) {
                snapshot.set('Owner', {
                  _ref: '/user/' + snapshot.get('Owner'),
                  _refObjectName: userNameMap[snapshot.get('Owner')]
                });
              }
            });
          });

          this.snapshotData = snapshotData;
          this._showData(0);
        }).bind(this));
      }).bind(this));
    },

    _getUserNameMap: function(userOIDs) {
      var promise = Ext.create('Deft.Deferred');

      Ext.create('Rally.data.wsapi.Store', {
        autoLoad: true,
        limit: Infinity,
        model: 'User',
        fetch: ['DisplayName'],
        filters: Rally.data.QueryFilter.or(_.map(userOIDs, function(OID) {
          return {
            property: 'ObjectID',
            value: OID
          };
        })),
        listeners: {
          load: function(store, data) {
            var userNameMap = _.reduce(data, function(map, user) {
              map[user.get('ObjectID')] = user.get('_refObjectName');

              return map;
            }, {});

            promise.resolve(userNameMap);
          }
        }
      });

      return promise;
    },

    _getDateSeries: function(startDate, endDate) {
      var dates = [];
      var date = startDate;
      date.setHours(23, 59, 59);

      while(date <= endDate) {
        if (date.getDay() !== 0 && date.getDay() !== 6) {
          dates.push(date);
        }
        date = new Date(date.getTime() + (1000 * 60 * 60 * 24));
      }

      return dates;
    },

    _play: function() {
      if (this.snapshotIndex >= this.snapshotData.length) {
        this.snapshotIndex = 0;
      }

      this._showData(this.snapshotIndex);
      this.interval = setInterval((function() {
        this.snapshotIndex++;
        this._showData(this.snapshotIndex);
      }).bind(this), 3000);
    },

    _pause: function() {
      clearInterval(this.interval);
      delete this.interval;
    },

    _showData: function(index) {
      var snapshotData = this.snapshotData[index];
      if(snapshotData) {
        this._displayCurrentDate(this.dateSeries[index]);
        this._showCharts(snapshotData, index);
        this._showBoard(snapshotData, index !== 0);
      } else {
        this._pause();
      }
    },

    _displayCurrentDate: function(date) {
      var dateContainer = Ext.getCmp('date-display');
      var formattedDate = Rally.util.DateTime.format(date, 'l, M dd, Y');
      dateContainer.update(formattedDate);
    },

    _showCharts: function(data, index) {
      if(this.down('statsbanner')) {
        this.down('statsbanner').destroy();
      }
      this.down('#chartContainer').add({
        xtype: 'statsbanner',
        context: this.getContext(),
        iterations: this.iterations,
        snapshotData: data,
        day: index,
        totalDays: this.snapshotData.length
      });
    },

    _showBoard: function(data, flair) {
      var board = Ext.getCmp('card-board');
      var columnNames = _.pluck(board.columnDefinitions, 'value');
      var existingCardOIDs = _.map(board.columnDefinitions, function() {
        return [];
      });

      _.each(board.columnDefinitions, function(column, idx) {
        existingCardOIDs[idx] = _.map(column.getCards(), function(card) {
          return card.getRecord().get('ObjectID');
        });
        column.clearCards();
      });

      _.each(data, function(record) {
        var newCardIndex = columnNames.indexOf(record.get(board.attribute));
        board.addCard(record, flair && !_.contains(existingCardOIDs[newCardIndex], record.get('ObjectID')));
      });
    }
});
<commit_msg>change play/pause ordering<commit_after>Ext.define('IterationStatusHistory', {
    extend: 'Rally.app.TimeboxScopedApp',
    componentCls: 'app',
    scopeType: 'iteration',
    layout: {
      type: 'vbox',
      align: 'stretch'
    },

    snapshotIndex: 0,

    launch: function() {
      this.callParent(arguments);
      this.add({
        flex: 1,
        xtype: 'container',
        layout: {
          type: 'vbox',
          align: 'stretch'
        },
        items: [{
          xtype: 'container',
          width: 600,
          items: [{
            xtype: 'rallybutton',
            iconCls: 'icon-right',
            width: 32,
            margin: '10 0 10 10',
            cls: 'rly-small secondary',
            listeners: {
              click: this._play,
              scope: this
            }
          },{
            xtype: 'rallybutton',
            iconCls: 'icon-pause',
            width: 32,
            margin: '10 0 10 10',
            cls: 'rly-small secondary',
            listeners: {
              click: this._pause,
              scope: this
            }
          },{
            xtype: 'container',
            margin: '10',
            id: 'date-display'
          }]
        }, {
          xtype: 'container',
          itemId: 'chartContainer',
          height: 110
        }, {
          xtype: 'container',
          id: 'board-container',
          flex: 1,
          layout: 'fit',
          items: [{
            xtype: 'rallycardboard',
            id: 'card-board',
            attribute : 'ScheduleState',
            types: ['Defect', 'HierarchicalRequirement', 'TestSet', 'DefectSuite'],
            storeConfig : {
              autoLoad: false
            },
            columnConfig: {
              isMatchingRecord: function(record) {
                return record.get(this.attribute) === this.getValue();
              }
            },
            cardConfig: {
              fields: ['PlanEstimate']
            },
            rowConfig: {
              field: 'Expedite'
            }
          }]
        }]
      });
    },

    onScopeChange: function() {
      var iterationName = this.getContext().getTimeboxScope()
        .getRecord().get('Name');

      this._getIterationOIDs(iterationName)
        .then(this._getSnapshotData.bind(this));
    },

    _getIterationOIDs: function(iterationName) {
      var promise = Ext.create('Deft.Deferred');

      Ext.create('Rally.data.wsapi.Store', {
        autoLoad: true,
        limit: Infinity,
        fetch: ['StartDate', 'EndDate', 'ObjectID', 'PlannedVelocity'],
        model: 'Iteration',
        filters: [{
          property: 'Name',
          value: iterationName
        }],
        listeners: {
          load: function(store, data) {
            promise.resolve(data);
          }
        }
      });

      return promise;
    },

    _getSnapshotData: function(iterationRecords) {
      this.iterations = iterationRecords;
      var iteration = this.getContext().getTimeboxScope().getRecord();
      var startDate = iteration.get('StartDate');
      var endDate = iteration.get('EndDate');
      this.dateSeries = this._getDateSeries(startDate, endDate);
      var iterationOIDs = _.map(iterationRecords, function(iterationRecord) {
        return iterationRecord.getId();
      });

      Deft.Chain.parallel(_.map(this.dateSeries, function(date) {
        return function() {
          var promise = Ext.create('Deft.Deferred');

          Ext.create('Rally.data.lookback.SnapshotStore', {
            autoLoad: true,
            fetch: ['_TypeHierarchy', 'Name', 'ScheduleState', 'FormattedID', 'PlanEstimate', 'Owner', 'Blocked', 'Ready', 'BlockedReason', 'State', 'Expedite'],
            hydrate: ['ScheduleState', '_TypeHierarchy', 'Owner', 'State'],
            limit: Infinity,
            filters: [{
              property: '__At',
              value: Rally.util.DateTime.toIsoString(date)
            },{
              property: '_TypeHierarchy',
              operator: 'in',
              value: ['Defect', 'HierarchicalRequirement', 'TestSet', 'DefectSuite']
            },{
              property: 'Iteration',
              operator: 'in',
              value: iterationOIDs
            }],
            sorters: [{
              property: 'ObjectID',
              direction: 'ASC'
            }],
            listeners: {
              load: function(store, snapshots) {
                promise.resolve(snapshots);
              }
            }
          });

          return promise;
        };
      })).then((function(snapshotData) {
        var userOIDs = _.unique(_.compact(_.flatten(_.map(snapshotData, function(snapshots) {
          return _.map(snapshots, function(snapshot) {
            return snapshot.get('Owner');
          });
        }))));

        this._getUserNameMap(userOIDs).then((function(userNameMap) {
          _.each(snapshotData, function(snapshots) {
            _.each(snapshots, function(snapshot) {
              snapshot.set('_id', snapshot.get('ObjectID'));
              snapshot.set('_ref', '/' + _.last(snapshot.get('_TypeHierarchy')).toLowerCase() + '/' + snapshot.get('ObjectID'));
              if (snapshot.get('Owner')) {
                snapshot.set('Owner', {
                  _ref: '/user/' + snapshot.get('Owner'),
                  _refObjectName: userNameMap[snapshot.get('Owner')]
                });
              }
            });
          });

          this.snapshotData = snapshotData;
          this._showData(0);
        }).bind(this));
      }).bind(this));
    },

    _getUserNameMap: function(userOIDs) {
      var promise = Ext.create('Deft.Deferred');

      Ext.create('Rally.data.wsapi.Store', {
        autoLoad: true,
        limit: Infinity,
        model: 'User',
        fetch: ['DisplayName'],
        filters: Rally.data.QueryFilter.or(_.map(userOIDs, function(OID) {
          return {
            property: 'ObjectID',
            value: OID
          };
        })),
        listeners: {
          load: function(store, data) {
            var userNameMap = _.reduce(data, function(map, user) {
              map[user.get('ObjectID')] = user.get('_refObjectName');

              return map;
            }, {});

            promise.resolve(userNameMap);
          }
        }
      });

      return promise;
    },

    _getDateSeries: function(startDate, endDate) {
      var dates = [];
      var date = startDate;
      date.setHours(23, 59, 59);

      while(date <= endDate) {
        if (date.getDay() !== 0 && date.getDay() !== 6) {
          dates.push(date);
        }
        date = new Date(date.getTime() + (1000 * 60 * 60 * 24));
      }

      return dates;
    },

    _play: function() {
      if (this.snapshotIndex >= this.snapshotData.length) {
        this.snapshotIndex = 0;
      } else {
        this.snapshotIndex++;
      }

      this._showData(this.snapshotIndex);
      this.interval = setInterval((function() {
        this.snapshotIndex++;
        this._showData(this.snapshotIndex);
      }).bind(this), 3000);
    },

    _pause: function() {
      clearInterval(this.interval);
      delete this.interval;
    },

    _showData: function(index) {
      var snapshotData = this.snapshotData[index];
      if(snapshotData) {
        this._displayCurrentDate(this.dateSeries[index]);
        this._showCharts(snapshotData, index);
        this._showBoard(snapshotData, index !== 0);
      } else {
        this._pause();
      }
    },

    _displayCurrentDate: function(date) {
      var dateContainer = Ext.getCmp('date-display');
      var formattedDate = Rally.util.DateTime.format(date, 'l, M dd, Y');
      dateContainer.update(formattedDate);
    },

    _showCharts: function(data, index) {
      if(this.down('statsbanner')) {
        this.down('statsbanner').destroy();
      }
      this.down('#chartContainer').add({
        xtype: 'statsbanner',
        context: this.getContext(),
        iterations: this.iterations,
        snapshotData: data,
        day: index,
        totalDays: this.snapshotData.length
      });
    },

    _showBoard: function(data, flair) {
      var board = Ext.getCmp('card-board');
      var columnNames = _.pluck(board.columnDefinitions, 'value');
      var existingCardOIDs = _.map(board.columnDefinitions, function() {
        return [];
      });

      _.each(board.columnDefinitions, function(column, idx) {
        existingCardOIDs[idx] = _.map(column.getCards(), function(card) {
          return card.getRecord().get('ObjectID');
        });
        column.clearCards();
      });

      _.each(data, function(record) {
        var newCardIndex = columnNames.indexOf(record.get(board.attribute));
        board.addCard(record, flair && !_.contains(existingCardOIDs[newCardIndex], record.get('ObjectID')));
      });
    }
});
<|endoftext|>


<commit_before>Ext.define('Rally.ui.tree.DescriptionRichTextView', {
    extend: Ext.view.View,
    alias: 'widget.treedescriptionrichtextview',

    cls: 'description-richtextview',

    initComponent: function() {
        this.callParent(arguments);
        this._createTpl();

    },

    constructor: function(config) {
        this.mergeConfig(config);
        this.callParent(arguments);
    },

    _createTpl: function() {
        this.tpl = new Ext.XTemplate(
            '<tpl>',
                '
{[this.getDetails()]}
',
            '</tpl>'
        );

        this.tpl.self.addMembers({
            getDetails: Ext.bind(function(record) {
                return record.get('Description');
            }, this)
        });
    }
});

Ext.define('Rally.ui.tree.EditorsList', {
    extend: Ext.view.View,
    alias: 'widget.treeeditorslist',

    cls: 'description-richtextview',

    initComponent: function() {
        this.callParent(arguments);
        this._createTpl();

    },

    constructor: function(config) {
        this.mergeConfig(config);
        this.callParent(arguments);
    },

    _createTpl: function() {
        this.tpl = new Ext.XTemplate(
            '<tpl>',
                '
{[this.getDetails()]}
',
            '</tpl>'
        );

        this.tpl.self.addMembers({
            getDetails: Ext.bind(function(record) {
                return record.get('Description');
            }, this)
        });
    }
});

Ext.define( 'Rally.ui.tree.extendedTreeItem' , {
    alias: 'widget.extendedTreeItem',
    extend: 'Rally.ui.tree.TreeItem',
    config: {
        displayedFields: ['Name', 'Description', 'TeamMembers']
    },

    draw: function() {
        var me = this;

        if (this.content) {
            this.content.destroy();
        }

        var cls = 'treeItemContent';
        if (this.getSelectable()) {
            cls += ' selectable';
        }

        if (!this.expander) {
            this.expander = this.drawExpander();
        } else {
            this.toggleExpander();
        }

        this.insert(1, {

            xtype: 'container',
            itemId: 'treeItemContent',
            cls: cls,
            layout: {
                type: 'hbox'
            },
            items: [
                {
                    xtype: 'component',
                    renderTpl: this.getContentTpl(),
                    renderData: this.getRenderData(),
                    listeners: {
                        afterrender: function() {
                            this.setupListeners();
                            this.fireEvent('draw');
                        },
                        scope: this
                    }
                },
                {
                    xtype: 'container',
                    itemId: 'userInfoRecord',
                    layout: {
                        type: 'hbox'
                    },
                    style: {
                        marginLeft: '50px'
                    },
                    listeners: {
                        afterrender: function(cmp) {
                            var treeItem = me;

                            var record = me.getRecord();
                            record.getCollection('TeamMembers').load().then({
                                success: function(data) {
                                    _.each(data, function(member) {
                                        cmp.add(
                                            {   xtype: 'container',
                                                cls: 'rally-textfield-component',
//                                                itemId: 'teamMembersInfo',
                                                style: { marginLeft: '10px'},
                                                html: member.get('_refObjectName')
                                            }
                                        );
                                    });
                                }
                            });
                        }
                    }
                }
            ]
        });

    }
});

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    launch: function() {

        var app = this;
       var pt = Ext.create( 'Rally.ui.tree.ProjectTree', {
        config: {
            treeItemConfigForRecordFn:  function(record) {
                if (record.get('_type') === 'workspace'){
                    return { xtype: 'rallyplaintreeitem' };
                }
                else {
                    return {
                        xtype: 'extendedTreeItem',
                        selectable: true
                    };
                }
            },
            topLevelStoreConfig: {
                fetch: ['Name', 'Editors', 'State', 'Workspace'],
                filters: [{
                    property: 'State',
                    value: 'Open'
                }, {
                    property: 'Projects.State',
                    value: 'Open'
                }],
                sorters: [{
                    property: 'Name',
                    direction: 'ASC'
                }],
                context: function() { app._getContext(app); }
            },

            childItemsStoreConfigForParentRecordFn: function(record){

                var storeConfig = {
                    fetch: ['Name', 'Editors', 'Description', 'Children:summary[State]', 'State', 'Workspace', 'Owner'],
                    hydrate: [ 'Editors', 'Owner' ],
                    sorters: [{
                        property: 'Name',
                        direction: 'ASC'
                    }]
                };

                if(record.get('_type') === 'workspace'){
                    return Ext.apply(storeConfig, {
                        filters: [{
                            property: 'Parent',
                            value: 'null'
                        }],
                        context: {
                            workspace: record.get('_ref'),
                            project: null
                        }
                    });
                } else {
                    return Ext.apply(storeConfig, {
                        filters: [{
                            property: 'Parent',
                            value: record.get('_ref')
                        }],
                        context: {
                            workspace: record.get('Workspace')._ref,
                            project: null
                        }
                    });
                }
            }
        }
       });

       this.add(pt);
    }
});
<commit_msg>remove unused code<commit_after>Ext.define( 'Rally.ui.tree.extendedTreeItem' , {
    alias: 'widget.extendedTreeItem',
    extend: 'Rally.ui.tree.TreeItem',
    config: {
        displayedFields: ['Name', 'Description', 'TeamMembers']
    },

    draw: function() {
        var me = this;

        if (this.content) {
            this.content.destroy();
        }

        var cls = 'treeItemContent';
        if (this.getSelectable()) {
            cls += ' selectable';
        }

        if (!this.expander) {
            this.expander = this.drawExpander();
        } else {
            this.toggleExpander();
        }

        this.insert(1, {

            xtype: 'container',
            itemId: 'treeItemContent',
            cls: cls,
            layout: {
                type: 'hbox'
            },
            items: [
                {
                    xtype: 'component',
                    renderTpl: this.getContentTpl(),
                    renderData: this.getRenderData(),
                    listeners: {
                        afterrender: function() {
                            this.setupListeners();
                            this.fireEvent('draw');
                        },
                        scope: this
                    }
                },
                {
                    xtype: 'container',
                    itemId: 'userInfoRecord',
                    layout: {
                        type: 'hbox'
                    },
                    style: {
                        marginLeft: '50px'
                    },
                    listeners: {
                        afterrender: function(cmp) {
                            var treeItem = me;

                            var record = me.getRecord();
                            record.getCollection('TeamMembers').load().then({
                                success: function(data) {
                                    _.each(data, function(member) {
                                        cmp.add(
                                            {   xtype: 'container',
                                                cls: 'rally-textfield-component',
//                                                itemId: 'teamMembersInfo',
                                                style: { marginLeft: '10px'},
                                                html: member.get('_refObjectName')
                                            }
                                        );
                                    });
                                }
                            });
                        }
                    }
                }
            ]
        });

    }
});

Ext.define('CustomApp', {
    extend: 'Rally.app.App',
    componentCls: 'app',

    launch: function() {

        var app = this;
       var pt = Ext.create( 'Rally.ui.tree.ProjectTree', {
        config: {
            treeItemConfigForRecordFn:  function(record) {
                if (record.get('_type') === 'workspace'){
                    return { xtype: 'rallyplaintreeitem' };
                }
                else {
                    return {
                        xtype: 'extendedTreeItem',
                        selectable: true
                    };
                }
            },
            topLevelStoreConfig: {
                fetch: ['Name', 'Editors', 'State', 'Workspace'],
                filters: [{
                    property: 'State',
                    value: 'Open'
                }, {
                    property: 'Projects.State',
                    value: 'Open'
                }],
                sorters: [{
                    property: 'Name',
                    direction: 'ASC'
                }],
                context: function() { app._getContext(app); }
            },

            childItemsStoreConfigForParentRecordFn: function(record){

                var storeConfig = {
                    fetch: ['Name', 'Editors', 'Description', 'Children:summary[State]', 'State', 'Workspace', 'Owner'],
                    hydrate: [ 'Editors', 'Owner' ],
                    sorters: [{
                        property: 'Name',
                        direction: 'ASC'
                    }]
                };

                if(record.get('_type') === 'workspace'){
                    return Ext.apply(storeConfig, {
                        filters: [{
                            property: 'Parent',
                            value: 'null'
                        }],
                        context: {
                            workspace: record.get('_ref'),
                            project: null
                        }
                    });
                } else {
                    return Ext.apply(storeConfig, {
                        filters: [{
                            property: 'Parent',
                            value: record.get('_ref')
                        }],
                        context: {
                            workspace: record.get('Workspace')._ref,
                            project: null
                        }
                    });
                }
            }
        }
       });

       this.add(pt);
    }
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import Chooser from '../../shared/Chooser';
import Dropdown from '../../shared/Dropdown';

import TeamMemberRoleConstants from '../../../constants/TeamMemberRoleConstants';

export default class MemberRole extends React.PureComponent {
  static displayName = "Team.Pipelines.Role";

  static propTypes = {
    teamMember: PropTypes.shape({
      role: PropTypes.string.isRequired
    }).isRequired,
    onRoleChange: PropTypes.func.isRequired,
    savingNewRole: PropTypes.string
  };

  render() {
    const saving = this.props.savingNewRole;

    return (
      <Dropdown width={270}>

{this.label(this.props.teamMember.role)}

        <Chooser selected={this.props.teamMember.role} onSelect={this.props.onRoleChange}>
          <Chooser.SelectOption
            value={TeamMemberRoleConstants.MAINTAINER}
            saving={saving === TeamMemberRoleConstants.MAINTAINER}
            selected={this.props.teamMember.role === TeamMemberRoleConstants.MAINTAINER}
            label={this.label(TeamMemberRoleConstants.MAINTAINER)}
            description="Manage members and pipelines with unrestricted access"
          />
          <Chooser.SelectOption
            value={TeamMemberRoleConstants.MEMBER}
            saving={saving === TeamMemberRoleConstants.MEMBER}
            selected={this.props.teamMember.role === TeamMemberRoleConstants.MEMBER}
            label={this.label(TeamMemberRoleConstants.MEMBER)}
            description="Create and access pipelines based on each pipeline’s permissions"
          />
        </Chooser>
      </Dropdown>
    );
  }

  label(value) {
    switch (value) {
      case TeamMemberRoleConstants.MAINTAINER:
        return "Maintainer";
      case TeamMemberRoleConstants.MEMBER:
        return "Member";
    }
  }
}
<commit_msg>More desription copy tweaks for<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import Chooser from '../../shared/Chooser';
import Dropdown from '../../shared/Dropdown';

import TeamMemberRoleConstants from '../../../constants/TeamMemberRoleConstants';

export default class MemberRole extends React.PureComponent {
  static displayName = "Team.Pipelines.Role";

  static propTypes = {
    teamMember: PropTypes.shape({
      role: PropTypes.string.isRequired
    }).isRequired,
    onRoleChange: PropTypes.func.isRequired,
    savingNewRole: PropTypes.string
  };

  render() {
    const saving = this.props.savingNewRole;

    return (
      <Dropdown width={270}>

{this.label(this.props.teamMember.role)}

        <Chooser selected={this.props.teamMember.role} onSelect={this.props.onRoleChange}>
          <Chooser.SelectOption
            value={TeamMemberRoleConstants.MAINTAINER}
            saving={saving === TeamMemberRoleConstants.MAINTAINER}
            selected={this.props.teamMember.role === TeamMemberRoleConstants.MAINTAINER}
            label={this.label(TeamMemberRoleConstants.MAINTAINER)}
            description={Create and access pipelines.
Add and remove users.}
          />
          <Chooser.SelectOption
            value={TeamMemberRoleConstants.MEMBER}
            saving={saving === TeamMemberRoleConstants.MEMBER}
            selected={this.props.teamMember.role === TeamMemberRoleConstants.MEMBER}
            label={this.label(TeamMemberRoleConstants.MEMBER)}
            description="Create and access pipelines."
          />
        </Chooser>
      </Dropdown>
    );
  }

  label(value) {
    switch (value) {
      case TeamMemberRoleConstants.MAINTAINER:
        return "Maintainer";
      case TeamMemberRoleConstants.MEMBER:
        return "Member";
    }
  }
}
<|endoftext|>


<commit_before>/* global module, require */

module.exports = function(gulp, config) {

    'use strict';

    var requireDir = require('require-dir');
    var path = require('path');
    var _ = require('underscore');
    var fs = require('fs');
    var mkdirp = require('mkdirp');

    if (!config.paths.translations) {
        return;
    }

    // translate
    var translations = requireDir(path.resolve(config.paths.translations));
    var localesDir = path.resolve(config.paths.tmp + '/resources/locales');
    var chars = {
        '{{': '__',
        '}}': '__'
    };

    var pluralKeys = {
        zero: '_plural_0',
        one: '',
        two: '_plural_2',
        few: '_plural_3',
        many: '_plural',
        other: '_plural_indefinite'

    };

    var getParsedTerm = function(term, definition) {
        var pluralKey;
        var parsedTermKey;
        var splittedTerm = term.split('_');
        var parsedTerm = {
            key: term,
            value: ''
        };

        if (!_.has(pluralKeys, _.last(splittedTerm))){
            parsedTerm.value = definition;
            return parsedTerm;
        }

        pluralKey = pluralKeys[_.last(splittedTerm)];
        parsedTermKey = term.replace('_' + _.last(splittedTerm), '') + pluralKey;
        parsedTerm.key = parsedTermKey;
        parsedTerm.value = definition;

        return parsedTerm;
    };

    var replaceChars = function(term) {
        _.each(chars, function(value, key) {
            term = term.replace(new RegExp(key, 'g'), value);
        });

        term = term.trim();
        return term;
    };

    var parseLang = function(terms) {
        var parsedTerm;
        var parsedTerms = {};
        _.each(terms, function(term) {
            term.term = replaceChars(term.term);
            parsedTerm = getParsedTerm(term.term, term.definition);

            if (parsedTerms[parsedTerm.key]) {
                _.extend(parsedTerms[parsedTerm.key], parsedTerm.value);
            } else {
                parsedTerms[parsedTerm.key] = parsedTerm.value;
            }
        });
        return parsedTerms;
    };

    var initDirs = function() {
        mkdirp.sync(localesDir);
    };

    gulp.task('_translate', function() {
        var json;
        initDirs();
        _.each(translations, function(lang, name) {
            json = JSON.stringify(parseLang(lang));
            fs.writeFile(localesDir + '/' + name + '.json', json);
        });
    });

};
<commit_msg>Add translated routes<commit_after>/* global module, require */

module.exports = function(gulp, config) {

    'use strict';

    var requireDir = require('require-dir');
    var path = require('path');
    var _ = require('underscore');
    var fs = require('fs');
    var mkdirp = require('mkdirp');

    if (!config.paths.translations) {
        return;
    }

    // translate
    var translations = requireDir(path.resolve(config.paths.translations));
    var localesDir = path.resolve(config.paths.tmp + '/resources/locales');
    var projectConfig = requireDir(path.resolve(config.paths.app + '/resources/config'));
    var projectConfigDir = path.resolve(config.paths.tmp + '/resources/config');
    var chars = {
        '{{': '__',
        '}}': '__'
    };

    var pluralKeys = {
        zero: '_plural_0',
        one: '',
        two: '_plural_2',
        few: '_plural_3',
        many: '_plural',
        other: '_plural_indefinite'

    };

    var getParsedTerm = function(term, definition) {
        var pluralKey;
        var parsedTermKey;
        var splittedTerm = term.split('_');
        var parsedTerm = {
            key: term,
            value: ''
        };

        if (!_.has(pluralKeys, _.last(splittedTerm))) {
            parsedTerm.value = definition;
            return parsedTerm;
        }

        pluralKey = pluralKeys[_.last(splittedTerm)];
        parsedTermKey = term.replace('_' + _.last(splittedTerm), '') + pluralKey;
        parsedTerm.key = parsedTermKey;
        parsedTerm.value = definition;

        return parsedTerm;
    };

    var replaceChars = function(term) {
        _.each(chars, function(value, key) {
            term = term.replace(new RegExp(key, 'g'), value);
        });

        term = term.trim();
        return term;
    };

    var parseLang = function(terms) {
        var parsedTerm;
        var parsedTerms = {};
        _.each(terms, function(term) {
            term.term = replaceChars(term.term);
            parsedTerm = getParsedTerm(term.term, term.definition);

            if (parsedTerms[parsedTerm.key]) {
                _.extend(parsedTerms[parsedTerm.key], parsedTerm.value);
            } else {
                parsedTerms[parsedTerm.key] = parsedTerm.value;
            }
        });
        return parsedTerms;
    };

    var initDirs = function() {
        mkdirp.sync(localesDir);
        mkdirp.sync(projectConfigDir);
    };

    /**
     * Build a route path with a given structure
     * @method function
     * @param  {String} pathStruc
     * @param  {object} pathTermsObject
     * @return {String}
     * @example
     * var pathStruc = '/route_thematic/:thematicId/route_book/:bookId';
     * var pathTermsObject = {route_thematic: ['tematica', 'thematic'], route_book: ['libro', 'book']};
     * buildRoutePath(pathStruc, pathTermsObject)
     * ->
     * '/(tematica|thematic)/:thematicId/(libro|book)/:bookId'
     */
    var buildRoutePath = function(pathStruc, pathTermsObject) {
        var joinedRouteNames;

        _.each(pathTermsObject, function(routeNames, routeKey) {
            joinedRouteNames = '(' + routeNames.join('|') + ')';
            pathStruc = pathStruc.replace(routeKey, joinedRouteNames);
        });

        return pathStruc;
    };

    /**
     * Build a route object
     * @method function
     * @param  {object} langBundles
     * @param  {String} pathStruc
     * @return {object}             A route object
     * @example
     * buildRoute(langBundles, '/route_thematic/:thematicId/route_book/:bookId')
     * ->
     * {
        	route: '/(tematica|thematic)/:thematicId/(libro|book)/:bookId',
        	es: ['tematica', 'libro'],
        	en: ['libro', 'book']
        }
     */
    var createRoute = function(langBundles, pathStruc) {
        var route = {};
        var pathTerms = pathStruc.split('/');
        var pathTermsObject = {};

        _.each(langBundles, function(bundle, langName) {
            route[langName] = [];

            for (var i in pathTerms) {
                var term = pathTerms[i];
                var routeName = bundle[term];

                if (routeName) {
                    route[langName].push(routeName);

                    pathTermsObject[term] = pathTermsObject[term] || [];
                    pathTermsObject[term].push(routeName);
                }
            }

        });

        route.route = buildRoutePath(pathStruc, pathTermsObject);

        return route;
    };

    /**
     * Create a routes.js file
     * @method function
     * @param  {object} langBundles
     * @return {object}             routes object
     */
    var createRoutes = function(langBundles) {
        var routesStruc = projectConfig.config.routes;
        var routes = {};
        var js = 'window.app = window.app || {}; ';
        js = js + 'window.app.routes = window.app.routes || {}; ';

        if (!routesStruc) {
            return;
        }

        _.each(routesStruc, function(pathStruc, route) {
            routes[route] = createRoute(langBundles, pathStruc);
        });

        js = js + 'window.app.routes = ';
        js = js + JSON.stringify(routes) + ';';
        fs.writeFile(projectConfigDir + '/routes.js', js);

        return routes;
    };

    gulp.task('_translate', function() {
        var langBundles = {};
        var langBundle;
        var routes;
        var json;
        var js = 'window.app = window.app || {}; ';
        js = js + 'window.app.locales = window.app.locales || {}; ';

        initDirs();
        _.each(translations, function(lang, name) {
            langBundle = parseLang(lang);
            langBundles[name] = langBundle;

            json = JSON.stringify(langBundle);

            js = js + 'window.app.locales["' + name + '"] = ';
            js = js + json + ';';

            fs.writeFile(localesDir + '/' + name + '.json', json);
        });

        routes = createRoutes(langBundles);

        fs.writeFile(localesDir + '/locales.js', js);

    });

};
<|endoftext|>


<commit_before>/*
 * grunt-html-build
 * https://github.com/spatools/grunt-html-build
 * Copyright (c) 2013 SPA Tools
 * Code below is licensed under MIT License
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

module.exports = function (grunt) {
    //#region Global Properties

    var // Init
        _ = grunt.util._,
        EOL = grunt.util.linefeed,
        path = require('path'),
        beautifier = require('js-beautify'),
        beautify = {
            js: beautifier.js,
            css: beautifier.css,
            html: beautifier.html
        },

        // Tags Regular Expressions
        regexTagStartTemplate = "<!--\\s*%parseTag%:(\\w+)\\s*(inline)?\\s*(optional)?\\s*([^\\s]*)\\s*-->", // <!-- build:{type} [inline] [optional] {name} --> {} required [] optional
        regexTagEndTemplate = "<!--\\s*\\/%parseTag%\\s*-->", // <!-- /build -->
        regexTagStart = "",
        regexTagEnd = "",
        isFileRegex = /\.(\w+){2,4}$/;

    //#endregion

    //#region Private Methods

    function getBuildTags(content) {
        var lines = content.replace(/\r\n/g, '\n').split(/\n/),
            tag = false,
            tags = [],
            last;

        lines.forEach(function (l) {
            var tagStart = l.match(new RegExp(regexTagStart)),
                tagEnd = new RegExp(regexTagEnd).test(l);

            if (tagStart) {
                tag = true;
                last = { type: tagStart[1], inline: !!tagStart[2], optional: !!tagStart[3], name: tagStart[4], lines: [] };
                tags.push(last);
            }

            // switch back tag flag when endbuild
            if (tag && tagEnd) {
                last.lines.push(l);
                tag = false;
            }

            if (tag && last) {
                last.lines.push(l);
            }
        });

        return tags;
    }
    function validateBlockWithName(tag, params) {
        var src = params[tag.type + "s"],

            keys = tag.name.split("."),
            ln = keys.length;

        for (var i = 0; i < ln; i++) {
            src = src[keys[i]]; // Search target
        }

        if (src) {
            var opt = {},
                files = src;

            if (_.isObject(src)) {
                if (src.files) {
                    opt = _.omit(src, "files");
                    files = src.files;
                }
                else {
                    // if paths are named, just take values
                    files = _.values(src);
                }
            }

            return grunt.file.expand(opt, files);
        }
    }
    function validateBlockAlways(tag) {
        return true;
    }

    function setTagRegexes(parseTag) {
        regexTagStart = regexTagStartTemplate.replace(/%parseTag%/, function () { return parseTag });
        regexTagEnd = regexTagEndTemplate.replace(/%parseTag%/, function () { return parseTag });
    }

    //#endregion

    //#region Processors Methods

    function createTemplateData(options, extend) {
        return {
            data: extend ? _.extend({}, options.data, extend) : options.data
        };
    }
    function processTemplate(template, options, extend) {
        return grunt.template.process(template, createTemplateData(options, extend));
    }
    function processHtmlTagTemplate(options, extend, inline) {
        var template = templates[options.type + (inline ? "-inline" : "")];
        return processTemplate(template, options, extend);
    }

    function processHtmlTag(options) {
        if (options.inline) {
            var content = options.files.map(grunt.file.read).join(EOL);
            return processHtmlTagTemplate(options, { content: content }, true);
        }
        else {
            return options.files.map(function (f) {
                var url = options.relative ? path.relative(options.dest, f) : f;

                if (options.prefix) {
                    url = path.join(options.prefix, url);
                }

                url = url.replace(/\\/g, '/');

                return processHtmlTagTemplate(options, { src: url });
            }).join(EOL);
        }
    }

    //#endregion

    //#region Processors / Validators / Templates

    var
        templates = {
            'script': '<script type="text/javascript" src="<%= src %>"></script>',
            'script-inline': '<script type="text/javascript"><%= content %></script>',
            'style': '<link type="text/css" rel="stylesheet" href="<%= src %>" />',
            'style-inline': '<style><%= content %></style>'
        },
        validators = {
            script: validateBlockWithName,
            style: validateBlockWithName,
            section: validateBlockWithName,

            process: validateBlockAlways,
            remove: validateBlockAlways,

            //base method
            validate: function (tag, params) {
                return validators[tag.type](tag, params);
            }
        },
        processors = {
            script: processHtmlTag,
            style: processHtmlTag,
            section: function (options) {
                return options.files.map(grunt.file.read).join(EOL);
            },

            process: function (options) {
                return options.lines
                                .map(function (l) { return processTemplate(l, options); })
                                .join(EOL)
                                .replace(new RegExp(regexTagStart), "")
                                .replace(new RegExp(regexTagEnd), "");
            },
            remove: function (options) {
                return "";
            },

            //base method
            transform: function (options) {
                return processors[options.type](options);
            }
        };

    //#endregion

    grunt.registerMultiTask('htmlbuild', "Grunt HTML Builder - Replace scripts and styles, Removes debug parts, append html partials, Template options", function () {
        var config = grunt.config(),
            params = this.options({
                beautify: false,
                logOptionals: false,
                relative: true,
                scripts: {},
                styles: {},
                sections: {},
                data: {},
                parseTag: 'build'
            });

        setTagRegexes(params.parseTag);

        this.files.forEach(function (file) {
            var dest = file.dest || "",
                destPath, content, tags;

            file.src.forEach(function (src) {
                if (params.replace) {
                    destPath = src;
                }
                else if (isFileRegex.test(dest)) {
                    destPath = dest;
                }
                else {
                    destPath = path.join(dest, path.basename(src));
                }

                content = grunt.util.normalizelf(grunt.file.read(src).toString());
                tags = getBuildTags(content);

                tags.forEach(function (tag) {
                    var raw = tag.lines.join(EOL),
                        result = "",
                        tagFiles = validators.validate(tag, params);

                    if (tagFiles) {
                        var options = _.extend({}, tag, {
                            data: _.extend({}, config, params.data),
                            files: tagFiles,
                            dest: dest,
                            prefix: params.prefix,
                            relative: params.relative
                        });

                        result = processors.transform(options);
                    }
                    else if (tag.optional) {
                        if (params.logOptionals)
                            grunt.log.error().error("Tag with type: '" + tag.type + "' and name: '" + tag.name + "' is not configured in your Gruntfile.js but is set optional, deleting block !");
                    }
                    else {
                        grunt.fail.warn("Tag with type '" + tag.type + "' and name: '" + tag.name + "' is not configured in your Gruntfile.js !");
                    }

                    content = content.replace(raw, function () { return result });
                });

                if (params.beautify) {
                    content = beautify.html(content, _.isObject(params.beautify) ? params.beautify : {});
                }

                // write the contents to destination
                grunt.file.write(destPath, content);
                grunt.log.ok("File " + destPath + " created !");
            });
        });
    });
};
<commit_msg>Fix prefix's ability to contain //, as in https://<commit_after>/*
 * grunt-html-build
 * https://github.com/spatools/grunt-html-build
 * Copyright (c) 2013 SPA Tools
 * Code below is licensed under MIT License
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

module.exports = function (grunt) {
    //#region Global Properties

    var // Init
        _ = grunt.util._,
        EOL = grunt.util.linefeed,
        URL = require('url'),
        path = require('path'),
        beautifier = require('js-beautify'),
        beautify = {
            js: beautifier.js,
            css: beautifier.css,
            html: beautifier.html
        },

        // Tags Regular Expressions
        regexTagStartTemplate = "<!--\\s*%parseTag%:(\\w+)\\s*(inline)?\\s*(optional)?\\s*([^\\s]*)\\s*-->", // <!-- build:{type} [inline] [optional] {name} --> {} required [] optional
        regexTagEndTemplate = "<!--\\s*\\/%parseTag%\\s*-->", // <!-- /build -->
        regexTagStart = "",
        regexTagEnd = "",
        isFileRegex = /\.(\w+){2,4}$/;

    //#endregion

    //#region Private Methods

    function getBuildTags(content) {
        var lines = content.replace(/\r\n/g, '\n').split(/\n/),
            tag = false,
            tags = [],
            last;

        lines.forEach(function (l) {
            var tagStart = l.match(new RegExp(regexTagStart)),
                tagEnd = new RegExp(regexTagEnd).test(l);

            if (tagStart) {
                tag = true;
                last = { type: tagStart[1], inline: !!tagStart[2], optional: !!tagStart[3], name: tagStart[4], lines: [] };
                tags.push(last);
            }

            // switch back tag flag when endbuild
            if (tag && tagEnd) {
                last.lines.push(l);
                tag = false;
            }

            if (tag && last) {
                last.lines.push(l);
            }
        });

        return tags;
    }
    function validateBlockWithName(tag, params) {
        var src = params[tag.type + "s"],

            keys = tag.name.split("."),
            ln = keys.length;

        for (var i = 0; i < ln; i++) {
            src = src[keys[i]]; // Search target
        }

        if (src) {
            var opt = {},
                files = src;

            if (_.isObject(src)) {
                if (src.files) {
                    opt = _.omit(src, "files");
                    files = src.files;
                }
                else {
                    // if paths are named, just take values
                    files = _.values(src);
                }
            }

            return grunt.file.expand(opt, files);
        }
    }
    function validateBlockAlways(tag) {
        return true;
    }

    function setTagRegexes(parseTag) {
        regexTagStart = regexTagStartTemplate.replace(/%parseTag%/, function () { return parseTag });
        regexTagEnd = regexTagEndTemplate.replace(/%parseTag%/, function () { return parseTag });
    }

    //#endregion

    //#region Processors Methods

    function createTemplateData(options, extend) {
        return {
            data: extend ? _.extend({}, options.data, extend) : options.data
        };
    }
    function processTemplate(template, options, extend) {
        return grunt.template.process(template, createTemplateData(options, extend));
    }
    function processHtmlTagTemplate(options, extend, inline) {
        var template = templates[options.type + (inline ? "-inline" : "")];
        return processTemplate(template, options, extend);
    }

    function processHtmlTag(options) {
        if (options.inline) {
            var content = options.files.map(grunt.file.read).join(EOL);
            return processHtmlTagTemplate(options, { content: content }, true);
        }
        else {
            return options.files.map(function (f) {
                var url = options.relative ? path.relative(options.dest, f) : f;

                url = url.replace(/\\/g, '/');

                if (options.prefix) {
                    url = URL.resolve(options.prefix.replace(/\\/g, '/'), url);
                }

                return processHtmlTagTemplate(options, { src: url });
            }).join(EOL);
        }
    }

    //#endregion

    //#region Processors / Validators / Templates

    var
        templates = {
            'script': '<script type="text/javascript" src="<%= src %>"></script>',
            'script-inline': '<script type="text/javascript"><%= content %></script>',
            'style': '<link type="text/css" rel="stylesheet" href="<%= src %>" />',
            'style-inline': '<style><%= content %></style>'
        },
        validators = {
            script: validateBlockWithName,
            style: validateBlockWithName,
            section: validateBlockWithName,

            process: validateBlockAlways,
            remove: validateBlockAlways,

            //base method
            validate: function (tag, params) {
                return validators[tag.type](tag, params);
            }
        },
        processors = {
            script: processHtmlTag,
            style: processHtmlTag,
            section: function (options) {
                return options.files.map(grunt.file.read).join(EOL);
            },

            process: function (options) {
                return options.lines
                                .map(function (l) { return processTemplate(l, options); })
                                .join(EOL)
                                .replace(new RegExp(regexTagStart), "")
                                .replace(new RegExp(regexTagEnd), "");
            },
            remove: function (options) {
                return "";
            },

            //base method
            transform: function (options) {
                return processors[options.type](options);
            }
        };

    //#endregion

    grunt.registerMultiTask('htmlbuild', "Grunt HTML Builder - Replace scripts and styles, Removes debug parts, append html partials, Template options", function () {
        var config = grunt.config(),
            params = this.options({
                beautify: false,
                logOptionals: false,
                relative: true,
                scripts: {},
                styles: {},
                sections: {},
                data: {},
                parseTag: 'build'
            });

        setTagRegexes(params.parseTag);

        this.files.forEach(function (file) {
            var dest = file.dest || "",
                destPath, content, tags;

            file.src.forEach(function (src) {
                if (params.replace) {
                    destPath = src;
                }
                else if (isFileRegex.test(dest)) {
                    destPath = dest;
                }
                else {
                    destPath = path.join(dest, path.basename(src));
                }

                content = grunt.util.normalizelf(grunt.file.read(src).toString());
                tags = getBuildTags(content);

                tags.forEach(function (tag) {
                    var raw = tag.lines.join(EOL),
                        result = "",
                        tagFiles = validators.validate(tag, params);

                    if (tagFiles) {
                        var options = _.extend({}, tag, {
                            data: _.extend({}, config, params.data),
                            files: tagFiles,
                            dest: dest,
                            prefix: params.prefix,
                            relative: params.relative
                        });

                        result = processors.transform(options);
                    }
                    else if (tag.optional) {
                        if (params.logOptionals)
                            grunt.log.error().error("Tag with type: '" + tag.type + "' and name: '" + tag.name + "' is not configured in your Gruntfile.js but is set optional, deleting block !");
                    }
                    else {
                        grunt.fail.warn("Tag with type '" + tag.type + "' and name: '" + tag.name + "' is not configured in your Gruntfile.js !");
                    }

                    content = content.replace(raw, function () { return result });
                });

                if (params.beautify) {
                    content = beautify.html(content, _.isObject(params.beautify) ? params.beautify : {});
                }

                // write the contents to destination
                grunt.file.write(destPath, content);
                grunt.log.ok("File " + destPath + " created !");
            });
        });
    });
};
<|endoftext|>


<commit_before>/*
 * grunt-esri-slurp
 * https://github.com/steveoh/grunt-esri-slurp
 *
 * Copyright (c) 2014 steveoh
 * Licensed under the MIT license.
 */

'use strict';
var fs = require('fs'),
  path = require('path'),

  async = require('async'),
  beautify = require('js-beautify').js_beautify,
  beautify_css = require('js-beautify').css,
  mkdirp = require('mkdirp'),
  request = require('request'),
  S = require('string'),
  ProgressBar = require('progress'),

  unwind = require('./unwinder');

module.exports = function(grunt) {
  grunt.registerMultiTask('esri_slurp', 'download esri js api amd modules and create a package', function() {
    var options = this.options({
        version: null,
        beautify: false
      }),
      done = this.async();

    if (!options.version || !this.files[0].dest) {
      grunt.fail.warn('version option is required and the dest file property must be set on the target.');
    }

    var packageLocation = this.files[0].dest;

    packageLocation = S(packageLocation).ensureRight(path.sep).s;

    grunt.log.subhead('downloading esri version ' + options.version + ' modules');

    mkdirp.sync(packageLocation);

    var esriVersionBaseUrl = 'http://js.arcgis.com/' + options.version + 'amd/js/esri/';
    grunt.verbose.writeln('esri base url: ' + esriVersionBaseUrl);

    var esriModules = require('./esriModules-' + options.version);

    var bar = new ProgressBar('downloading [:bar] :percent :etas', {
      total: esriModules.length,
      stream: process.stdout,
      width: 30
    });

    async.eachLimit(esriModules, 20, function(file, callback) {
      var subPath = S(path.dirname(file)).ensureRight('/').s,
        fileFolder = path.join(packageLocation, subPath),
        fileName = path.basename(file),
        httpUrl = esriVersionBaseUrl + subPath + fileName;

      if (!fs.existsSync(fileFolder)) {
        mkdirp.sync(fileFolder);
      }

      request({
          uri: httpUrl,
          encoding: 'binary'
        },
        function(error, response, body) {
          if (body.length < 1) {
            bar.total = bar.total - 1;

            callback(error, body);

            return;
          }

          var newFile = path.join(packageLocation, file);

          var extension = path.extname(file);
          if (extension === '.js' || extension === '.css') {
            body = unwind(body);

            if (options.beautify) {
              if (extension === '.js') {
                body = beautify(body);
              } else if (extension = '.css') {
                body = beautify_css(body);
              }
            }
          }

          fs.writeFile(newFile, body, 'binary');

          bar.tick();

          callback(error, body);
        });
    }, function(err) {
      if (err) {
        grunt.fail.warn(err);
      }

      done();
    });
  });
};<commit_msg>updated activity text<commit_after>/*
 * grunt-esri-slurp
 * https://github.com/steveoh/grunt-esri-slurp
 *
 * Copyright (c) 2014 steveoh
 * Licensed under the MIT license.
 */

'use strict';
var fs = require('fs'),
  path = require('path'),

  async = require('async'),
  beautify = require('js-beautify').js_beautify,
  beautify_css = require('js-beautify').css,
  mkdirp = require('mkdirp'),
  os = require('os'),
  request = require('request'),
  S = require('string'),
  ProgressBar = require('progress'),

  unwind = require('./unwinder');

module.exports = function(grunt) {
  grunt.registerMultiTask('esri_slurp', 'download esri js api amd modules and create a package', function() {
    var options = this.options({
        version: null,
        beautify: false
      }),
      done = this.async();

    if (!options.version || !this.files[0].dest) {
      grunt.fail.warn('version option is required and the dest file property must be set on the target.');
    }

    var packageLocation = this.files[0].dest;

    packageLocation = S(packageLocation).ensureRight(path.sep).s;

    grunt.log.subhead('downloading and processing esri version ' + options.version + ' modules');

    mkdirp.sync(packageLocation);

    var esriVersionBaseUrl = 'http://js.arcgis.com/' + options.version + 'amd/js/esri/';
    grunt.verbose.writeln('esri base url: ' + esriVersionBaseUrl);

    var esriModules = require('./esriModules-' + options.version);

    var bar = new ProgressBar('[:bar] :percent remaining: :etas elapsed: :elapseds', {
      total: esriModules.length,
      stream: process.stdout,
      width: 30
    });

    async.eachLimit(esriModules, 20, function(file, callback) {
      var subPath = S(path.dirname(file)).ensureRight('/').s,
        fileFolder = path.join(packageLocation, subPath),
        fileName = path.basename(file),
        httpUrl = esriVersionBaseUrl + subPath + fileName;

      if (!fs.existsSync(fileFolder)) {
        mkdirp.sync(fileFolder);
      }

      request({
          uri: httpUrl,
          encoding: 'binary'
        },
        function(error, response, body) {
          if (body.length < 1) {
            bar.total = bar.total - 1;

            callback(error, body);

            return;
          }

          var newFile = path.join(packageLocation, file);

          var extension = path.extname(file);
          if (extension === '.js' || extension === '.css') {
            body = unwind(body);

            if (options.beautify) {
              if (extension === '.js') {
                body = beautify(body);
              } else if (extension = '.css') {
                body = beautify_css(body);
              }
            }
          }

          fs.writeFile(newFile, body, 'binary');

          bar.tick();

          callback(error, body);
        });
    }, function(err) {
      if (err) {
        grunt.fail.warn(err);
      }

      done();
    });
  });
};<|endoftext|>