<commit_before>var App = Ember.Application.create({
    LOG_TRANSITIONS: true
});

App.Router.map(function() {
    this.resource('projects', function() {
        this.resource('project', { path: '/:project_id' });
    });

});

var layersStore = Ember.Object.create({
  loaded: []
});

// Controllers

App.ProjectsIndexController = Ember.ArrayController.extend({
    sortProperties: ['name'],

    //newProject: '',

    actions : {

        createProject: function() {

            time = (new Date()).toTimeString();

            var project = this.store.createRecord('project', {
                name: time,
            });

            var self = this;

            var onSuccess = function(project) {

                var newProject = DS.PromiseObject.create({
                    promise: App.Project.store.fetch('project', { name: time })
                });

                newProject.then(function() {
                    console.log(newProject)
                    self.transitionToRoute('project', newProject.get('content.content.0.id'));
                });
            };
            project.save().then(onSuccess);

        },

        //saveProject: function() {
        //    console.log(this.get('newProject'));
        //    var project = this.store.createRecord('project', {
        //        name: this.get('newProject'),
        //        status: 'UNSAVED'
        //    });
        //    project.save();
        //
        //},

        deleteProject: function(project) {
            console.log(project);
            this.store.find('project', project).then(function (project) {
                project.destroyRecord();
            });

        }
    }

});

App.ProjectController = Ember.ObjectController.extend({
    showLayers: function() {

      var layers = this.get("model.layer_ids.content.content")
      var added_layers = [];
      $(layers).each(function(){
        added_layers.push(this.id)
      })
      layersStore.set("loaded",added_layers)

      return this.get('model.layer_ids')

    }.property('model.layer_ids.@each'),

    // Empty property for the input filed so we can clear it later.
    projectName: '',

    thisProject: function() {}.property(),

    getLayers: function(){
        loaded_layers = this.get("model.layer_ids").content.content.length;
        var i = this.incrementProperty('i'),
            c = loadCount.get("count");

        if(i !== c ){
          this.get("model").reload();
        }

        loadCount.set("count",i);

    }.property("model"),

    savedStatus: function() {
        //console.log(this);
    }.property(),

    actions: {
        reload: function() {
          this.get('model').reload().then(function(model) {
            // do something with the reloaded model
            console.log(model.layer_ids);
          });
        },

        updateProject: function() {
            var project = this.get('model')
            project.set('name', this.get('projectName'))
            project.set('saved', true);

            // perserve this so we can clear the projectName field after save.
            var controller = this;
            project.save().then(function(project){
                // Clear the projectName filed.
                controller.set('projectName', '');
            });
        },
    }
});

App.AddLayerModalController = Ember.ArrayController.extend({
   sortProperties: ['layer_type', 'name'],
});

// Routers

App.IndexRoute = Ember.Route.extend({});

App.AddLayerModalRoute = Ember.Route.extend({
    model: function() {
        // return this.store.find('layer');
    },
});

App.ProjectsIndexRoute = Ember.Route.extend({
    model: function() {
        return this.store.find('project');
    },

})

App.ProjectRoute = Ember.Route.extend({

    model: function(params) {
        var project = this.store.find('project',  params.project_id);
        return project;
    },

    actions: {
        addLayer: function(layer, model) {
            var layerID = layer.get('id');
            var _this = this;
            var projectID = _this.get('controller.model.id');
            var projectlayer = this.store.createRecord('projectlayer', {
                project_id: projectID,
                layer_id: layerID
            });
            projectlayer.save().then(function(){
              _this.get("controller.model").reload();
            });
        },

        removeLayer: function(layer, project) {
            var layerID = layer.get('id');
            var layerClass = layer.get('layer');
            var _this = this;
            var project = project || this.get("controller.model.id");

            var projectLayer = DS.PromiseObject.create({
                promise: this.store.find('projectlayer', { layer_id: layerID, project_id: project })
            });

            projectLayer.then(function() {
                var projectLayerID = projectLayer.get('content.content.0.id');
                    console.log(projectLayer);

                App.Projectlayer.store.find('projectlayer', projectLayerID).then(function(projectlayer){
                    projectlayer.destroyRecord().then(function(){
                        _this.get("controller.model").reload();
                    });
                });

            });

            $("."+layerClass).fadeOut( 500, function() {
                $(this).remove();
            });

        },

        // Modal
        showModal: function(name) {
            var content = this.store.find('layer');
            this.controllerFor(name).set('content', content);
            this.render(name, {
                into: 'application',
                outlet: 'modal'
            });
        },
        removeModal: function() {
            this.disconnectOutlet({
                outlet: 'modal',
                parentView: 'application'
            });
        }
    },

});

var loadCount = Ember.Object.create({
  count: 0
});

App.Map = Ember.Object.extend();
var store = App.Map.create();

// Views

// Components

App.BaseMapComponent = Ember.Component.extend({
    didInsertElement: function() {

        var map = L.map('map', {
            center: [33.7489954,-84.3879824],
            zoom: 14,
            zoomControl:false
        });

        var osm = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors Georgia State University and Emory University',
        }).addTo(map).setZIndex(0);

        var MapQuestOpen_Aerial = L.tileLayer('http://oatile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg', {
            attribution: 'Tiles Courtesy of MapQuest — Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency contributors Georgia State University and Emory University',
            subdomains: '1234'
        });

        var toner = L.tileLayer('http://d.tile.stamen.com/toner/{z}/{x}/{y}.png', {
          attribution: '© Stamen Toner Map contributors Georgia State University and Emory University',
        });

        var baseMaps = {
            "Street": osm,
            "Satellite": MapQuestOpen_Aerial,
            "Toner": toner
        };

        L.control.zoom({ position: 'topright' }).addTo(map);
        L.control.layers(baseMaps).addTo(map);

        store.set('map', map);
        // save map instance
        this.controller.set('map', map);
    },
});

App.OpacitySliderComponent = Ember.Component.extend({
    opacityslider: function() {

                var layer = DS.PromiseObject.create({
                    promise: App.Layer.store.find('layer', this.layerID)
                });

                layer.then(function() {

                    var layerName = layer.get('layer');
                    // console.log(layerName)
                    var slider = $("input.slider, input ."+layerName).slider({
                        //precision: 2,
                        value: 10,
                        reversed: true
                    });

                });
    }.property(),

    actions: {
        opacityChange: function() {
            var layerName = this.layer
            // console.log("opacity layer name:"+layerName)
            var value = $("input."+layerName).val();
            //if(isNaN(value)) {
            //    var value = $("input."+layerName).val();
            //}
            // console.log("value of opacity slider:"+value)
            var opacity = value / 10;
            // console.log("opacity:"+opacity);
            $("div."+layerName+",img."+layerName).css({'opacity': opacity});
        }
    }
});

App.AddRemoveLayerButtonComponent = Ember.Component.extend({
    layerAdded: function(layer){
      return false
    }.property(),
    actions: {
        buttonAddLayer: function(layer) {
          this.toggleProperty("layerAdded");
          this.set('action','addLayer');
          this.sendAction('action', this.get('param'));
        },
        buttonRemoveLayer: function(layer) {
          this.toggleProperty("layerAdded")
          this.set('action','removeLayer');
          this.sendAction('action', this.get('param'));
        },
    }
});

Ember.Handlebars.helper('is_active', function(layer) {
    var loaded_layers = layersStore.get("loaded"),
        this_layer = this.get("param.id");

    if (loaded_layers.indexOf(this_layer) > -1){
      this.set("layerAdded",true)
      return
    }
    this.set("layerAdded",false)
    return
});

App.RemoveLayerButtonComponent = Ember.Component.extend({
    actions: {
        removeLayer: function() {
            this.sendAction('action', this.get('param'));
        }
    }
});

App.ListAddedLayersComponent = Ember.Component.extend({

    model: function() {
        return this.store.find('project');
    },

});

App.MyModalComponent = Ember.Component.extend({
    actions: {
        ok: function() {
            this.$('.modal').modal('hide');
            this.sendAction('ok');
        }
    },
    show: function() {
        this.$('.modal').modal().on('hidden.bs.modal', function() {
            this.sendAction('close');
        }.bind(this));
    }.on('didInsertElement')
});

App.MapLayersComponent = Ember.Component.extend({
    mappedLayers: function() {

        var mappedLayer = DS.PromiseObject.create({
            promise: App.Layer.store.find('layer', this.layerID)
        });

        mappedLayer.then(function() {

            var slug = mappedLayer.get('layer');
            var map = store.get('map');

            instution = mappedLayer.get('institution');

            switch(mappedLayer.get('layer_type')) {
                case 'planningatlanta':

                    var tile = L.tileLayer('http://static.library.gsu.edu/ATLmaps/tiles/' + mappedLayer.get('layer') + '/{z}/{x}/{y}.png', {
                        layer: mappedLayer.get('layer'),
                        tms: true,
                        minZoom: 13,
                        maxZoom: 19,
                        //attribution: 'GSU'
                    }).addTo(map).bringToFront().getContainer();

                    $(tile).addClass(slug);

                    break;

                case 'wms':

                    var wmsLayer = L.tileLayer.wms(instution.geoserver + mappedLayer.get('url') + '/wms', {
                        layers: mappedLayer.get('url')+':'+mappedLayer.get('layer'),
                        format: 'image/png',
                        CRS: 'EPSG:900913',
                        transparent: true
                    }).addTo(map).bringToFront().getContainer();

                    $(wmsLayer).addClass(slug);

                    break;

                case 'geojson':
                    var slug = mappedLayer.get('layer')
                    function viewData(feature, layer) {
                        var popupContent = "
"+feature.properties.name+"
"+
                        "
"+feature.properties.description+"
"+
                        ""+
                        "Photo Credit: "+feature.properties.image.credit+"";
                        layer.bindPopup(popupContent);

                    }
                    function setIcon(url, class_name){
                      return iconObj = L.icon({
                                            iconUrl: url,
                                            //iconSize: [50, 65],
                                            iconAnchor: [16, 37],
                                            popupAnchor: [0, -28],
                                            className: class_name
                                          });
                    }

                    if(mappedLayer.get('url')){
                      var points = new L.GeoJSON.AJAX(mappedLayer.get('url'), {
                          pointToLayer: function (feature, latlng) {
                            // console.log("slug",slug);
                            var marker = L.marker(latlng, {icon: setIcon("images/marker2.png", slug)});
                            return marker
                          },
                          onEachFeature: viewData,
                      }).addTo(map);
                      break;
                    }
            }

            shuffle.init();
        });
        //return mappedLayer
    }.property(),

    actions: {

    }
});

// Adapter

App.ApplicationAdapter = DS.RESTAdapter.extend({
    host: 'http://api.atlmaps-dev.com:7000',
    namespace: 'v1',
    suffix: '.json',
    buildURL: function(record, suffix) {
      var s = this._super(record, suffix);
      return s + this.get('suffix');
    }
});

App.Store = DS.Store.extend({
  adapter: App.ApplicationAdapter
});

// Models
App.Layer = DS.Model.extend({
    name: DS.attr('string'),
    slug: DS.attr('string'),
    keywords: DS.attr('string'),
    description: DS.attr('string'),
    url: DS.attr('string'),
    layer: DS.attr('string'),
    date: DS.attr('date'),
    layer_type: DS.attr('string'),
    zoomlevels: DS.attr('string'),
    minx: DS.attr('number'),
    miny: DS.attr('number'),
    maxx: DS.attr('number'),
    maxy: DS.attr('number'),
    project_ids: DS.hasMany('project', {async: true}),
    institution: DS.attr()
});

App.Project = DS.Model.extend({
    name: DS.attr('string'),
    description: DS.attr('string'),
    saved: DS.attr('boolean'),
    published: DS.attr('boolean'),
    //user: DS.attr('number'),
    layer_ids: DS.hasMany('layer', {async: true}),
})

App.Projectlayer = DS.Model.extend({
    layer_id: DS.attr(),
    project_id: DS.attr()
});

$(document).ready(function(){
  $.material.ripples(".btn, .navbar a");
  (function(){
  // init on shuffle items
    shuffle.init();
  })()

  // document events
  $(document).on('click','#hide-layer-options',function(){
    $(".layer-controls").animate({"left":"-100%"},500,"easeInQuint",function(){
      $("#show-layer-options").fadeIn(500);
    });
  })
  .on('click','#show-layer-options',function(){
    $(".layer-controls").animate({"left":"0%"},500,"easeOutQuint");
    $("#show-layer-options").fadeOut(500);
  })
  .on('click','.shuffle-items li.item',function(){
    shuffle.click(this);
  })

})
<commit_msg>Typo fix.<commit_after>var App = Ember.Application.create({
    LOG_TRANSITIONS: true
});

App.Router.map(function() {
    this.resource('projects', function() {
        this.resource('project', { path: '/:project_id' });
    });

});

var layersStore = Ember.Object.create({
  loaded: []
});

// Controllers

App.ProjectsIndexController = Ember.ArrayController.extend({
    sortProperties: ['name'],

    //newProject: '',

    actions : {

        createProject: function() {

            time = (new Date()).toTimeString();

            var project = this.store.createRecord('project', {
                name: time,
            });

            var self = this;

            var onSuccess = function(project) {

                var newProject = DS.PromiseObject.create({
                    promise: App.Project.store.fetch('project', { name: time })
                });

                newProject.then(function() {
                    console.log(newProject)
                    self.transitionToRoute('project', newProject.get('content.content.0.id'));
                });
            };
            project.save().then(onSuccess);

        },

        //saveProject: function() {
        //    console.log(this.get('newProject'));
        //    var project = this.store.createRecord('project', {
        //        name: this.get('newProject'),
        //        status: 'UNSAVED'
        //    });
        //    project.save();
        //
        //},

        deleteProject: function(project) {
            console.log(project);
            this.store.find('project', project).then(function (project) {
                project.destroyRecord();
            });

        }
    }

});

App.ProjectController = Ember.ObjectController.extend({
    showLayers: function() {

      var layers = this.get("model.layer_ids.content.content")
      var added_layers = [];
      $(layers).each(function(){
        added_layers.push(this.id)
      })
      layersStore.set("loaded",added_layers)

      return this.get('model.layer_ids')

    }.property('model.layer_ids.@each'),

    // Empty property for the input filed so we can clear it later.
    projectName: '',

    thisProject: function() {}.property(),

    getLayers: function(){
        loaded_layers = this.get("model.layer_ids").content.content.length;
        var i = this.incrementProperty('i'),
            c = loadCount.get("count");

        if(i !== c ){
          this.get("model").reload();
        }

        loadCount.set("count",i);

    }.property("model"),

    savedStatus: function() {
        //console.log(this);
    }.property(),

    actions: {
        reload: function() {
          this.get('model').reload().then(function(model) {
            // do something with the reloaded model
            console.log(model.layer_ids);
          });
        },

        updateProject: function() {
            var project = this.get('model')
            project.set('name', this.get('projectName'))
            project.set('saved', true);

            // perserve this so we can clear the projectName field after save.
            var controller = this;
            project.save().then(function(project){
                // Clear the projectName filed.
                controller.set('projectName', '');
            });
        },
    }
});

App.AddLayerModalController = Ember.ArrayController.extend({
   sortProperties: ['layer_type', 'name'],
});

// Routers

App.IndexRoute = Ember.Route.extend({});

App.AddLayerModalRoute = Ember.Route.extend({
    model: function() {
        // return this.store.find('layer');
    },
});

App.ProjectsIndexRoute = Ember.Route.extend({
    model: function() {
        return this.store.find('project');
    },

})

App.ProjectRoute = Ember.Route.extend({

    model: function(params) {
        var project = this.store.find('project',  params.project_id);
        return project;
    },

    actions: {
        addLayer: function(layer, model) {
            var layerID = layer.get('id');
            var _this = this;
            var projectID = _this.get('controller.model.id');
            var projectlayer = this.store.createRecord('projectlayer', {
                project_id: projectID,
                layer_id: layerID
            });
            projectlayer.save().then(function(){
              _this.get("controller.model").reload();
            });
        },

        removeLayer: function(layer, project) {
            var layerID = layer.get('id');
            var layerClass = layer.get('layer');
            var _this = this;
            var project = project || this.get("controller.model.id");

            var projectLayer = DS.PromiseObject.create({
                promise: this.store.find('projectlayer', { layer_id: layerID, project_id: project })
            });

            projectLayer.then(function() {
                var projectLayerID = projectLayer.get('content.content.0.id');
                    console.log(projectLayer);

                App.Projectlayer.store.find('projectlayer', projectLayerID).then(function(projectlayer){
                    projectlayer.destroyRecord().then(function(){
                        _this.get("controller.model").reload();
                    });
                });

            });

            $("."+layerClass).fadeOut( 500, function() {
                $(this).remove();
            });

        },

        // Modal
        showModal: function(name) {
            var content = this.store.find('layer');
            this.controllerFor(name).set('content', content);
            this.render(name, {
                into: 'application',
                outlet: 'modal'
            });
        },
        removeModal: function() {
            this.disconnectOutlet({
                outlet: 'modal',
                parentView: 'application'
            });
        }
    },

});

var loadCount = Ember.Object.create({
  count: 0
});

App.Map = Ember.Object.extend();
var store = App.Map.create();

// Views

// Components

App.BaseMapComponent = Ember.Component.extend({
    didInsertElement: function() {

        var map = L.map('map', {
            center: [33.7489954,-84.3879824],
            zoom: 14,
            zoomControl:false
        });

        var osm = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors Georgia State University and Emory University',
        }).addTo(map).setZIndex(0);

        var MapQuestOpen_Aerial = L.tileLayer('http://oatile{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg', {
            attribution: 'Tiles Courtesy of MapQuest — Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency contributors Georgia State University and Emory University',
            subdomains: '1234'
        });

        var toner = L.tileLayer('http://d.tile.stamen.com/toner/{z}/{x}/{y}.png', {
          attribution: '© Stamen Toner Map contributors Georgia State University and Emory University',
        });

        var baseMaps = {
            "Street": osm,
            "Satellite": MapQuestOpen_Aerial,
            "Toner": toner
        };

        L.control.zoom({ position: 'topright' }).addTo(map);
        L.control.layers(baseMaps).addTo(map);

        store.set('map', map);
        // save map instance
        this.controller.set('map', map);
    },
});

App.OpacitySliderComponent = Ember.Component.extend({
    opacityslider: function() {

                var layer = DS.PromiseObject.create({
                    promise: App.Layer.store.find('layer', this.layerID)
                });

                layer.then(function() {

                    var layerName = layer.get('layer');
                    // console.log(layerName)
                    var slider = $("input.slider, input ."+layerName).slider({
                        //precision: 2,
                        value: 10,
                        reversed: true
                    });

                });
    }.property(),

    actions: {
        opacityChange: function() {
            var layerName = this.layer
            // console.log("opacity layer name:"+layerName)
            var value = $("input."+layerName).val();
            //if(isNaN(value)) {
            //    var value = $("input."+layerName).val();
            //}
            // console.log("value of opacity slider:"+value)
            var opacity = value / 10;
            // console.log("opacity:"+opacity);
            $("div."+layerName+",img."+layerName).css({'opacity': opacity});
        }
    }
});

App.AddRemoveLayerButtonComponent = Ember.Component.extend({
    layerAdded: function(layer){
      return false
    }.property(),
    actions: {
        buttonAddLayer: function(layer) {
          this.toggleProperty("layerAdded");
          this.set('action','addLayer');
          this.sendAction('action', this.get('param'));
        },
        buttonRemoveLayer: function(layer) {
          this.toggleProperty("layerAdded")
          this.set('action','removeLayer');
          this.sendAction('action', this.get('param'));
        },
    }
});

Ember.Handlebars.helper('is_active', function(layer) {
    var loaded_layers = layersStore.get("loaded"),
        this_layer = this.get("param.id");

    if (loaded_layers.indexOf(this_layer) > -1){
      this.set("layerAdded",true)
      return
    }
    this.set("layerAdded",false)
    return
});

App.RemoveLayerButtonComponent = Ember.Component.extend({
    actions: {
        removeLayer: function() {
            this.sendAction('action', this.get('param'));
        }
    }
});

App.ListAddedLayersComponent = Ember.Component.extend({

    model: function() {
        return this.store.find('project');
    },

});

App.MyModalComponent = Ember.Component.extend({
    actions: {
        ok: function() {
            this.$('.modal').modal('hide');
            this.sendAction('ok');
        }
    },
    show: function() {
        this.$('.modal').modal().on('hidden.bs.modal', function() {
            this.sendAction('close');
        }.bind(this));
    }.on('didInsertElement')
});

App.MapLayersComponent = Ember.Component.extend({
    mappedLayers: function() {

        var mappedLayer = DS.PromiseObject.create({
            promise: App.Layer.store.find('layer', this.layerID)
        });

        mappedLayer.then(function() {

            var slug = mappedLayer.get('layer');
            var map = store.get('map');

            institution = mappedLayer.get('institution');

            switch(mappedLayer.get('layer_type')) {
                case 'planningatlanta':

                    var tile = L.tileLayer('http://static.library.gsu.edu/ATLmaps/tiles/' + mappedLayer.get('layer') + '/{z}/{x}/{y}.png', {
                        layer: mappedLayer.get('layer'),
                        tms: true,
                        minZoom: 13,
                        maxZoom: 19,
                        //attribution: 'GSU'
                    }).addTo(map).bringToFront().getContainer();

                    $(tile).addClass(slug);

                    break;

                case 'wms':

                    var wmsLayer = L.tileLayer.wms(institution.geoserver + mappedLayer.get('url') + '/wms', {
                        layers: mappedLayer.get('url') + ':' + mappedLayer.get('layer'),
                        format: 'image/png',
                        CRS: 'EPSG:900913',
                        transparent: true
                    }).addTo(map).bringToFront().getContainer();

                    $(wmsLayer).addClass(slug);

                    break;

                case 'geojson':
                    var slug = mappedLayer.get('layer')
                    function viewData(feature, layer) {
                        var popupContent = "
"+feature.properties.name+"
"+
                        "
"+feature.properties.description+"
"+
                        ""+
                        "Photo Credit: "+feature.properties.image.credit+"";
                        layer.bindPopup(popupContent);

                    }
                    function setIcon(url, class_name){
                      return iconObj = L.icon({
                                            iconUrl: url,
                                            //iconSize: [50, 65],
                                            iconAnchor: [16, 37],
                                            popupAnchor: [0, -28],
                                            className: class_name
                                          });
                    }

                    if(mappedLayer.get('url')){
                      var points = new L.GeoJSON.AJAX(mappedLayer.get('url'), {
                          pointToLayer: function (feature, latlng) {
                            // console.log("slug",slug);
                            var marker = L.marker(latlng, {icon: setIcon("images/marker2.png", slug)});
                            return marker
                          },
                          onEachFeature: viewData,
                      }).addTo(map);
                      break;
                    }
            }

            shuffle.init();
        });
        //return mappedLayer
    }.property(),

    actions: {

    }
});

// Adapter

App.ApplicationAdapter = DS.RESTAdapter.extend({
    host: 'http://api.atlmaps-dev.com:7000',
    namespace: 'v1',
    suffix: '.json',
    buildURL: function(record, suffix) {
      var s = this._super(record, suffix);
      return s + this.get('suffix');
    }
});

App.Store = DS.Store.extend({
  adapter: App.ApplicationAdapter
});

// Models
App.Layer = DS.Model.extend({
    name: DS.attr('string'),
    slug: DS.attr('string'),
    keywords: DS.attr('string'),
    description: DS.attr('string'),
    url: DS.attr('string'),
    layer: DS.attr('string'),
    date: DS.attr('date'),
    layer_type: DS.attr('string'),
    zoomlevels: DS.attr('string'),
    minx: DS.attr('number'),
    miny: DS.attr('number'),
    maxx: DS.attr('number'),
    maxy: DS.attr('number'),
    project_ids: DS.hasMany('project', {async: true}),
    institution: DS.attr()
});

App.Project = DS.Model.extend({
    name: DS.attr('string'),
    description: DS.attr('string'),
    saved: DS.attr('boolean'),
    published: DS.attr('boolean'),
    //user: DS.attr('number'),
    layer_ids: DS.hasMany('layer', {async: true}),
})

App.Projectlayer = DS.Model.extend({
    layer_id: DS.attr(),
    project_id: DS.attr()
});

$(document).ready(function(){
  $.material.ripples(".btn, .navbar a");
  (function(){
  // init on shuffle items
    shuffle.init();
  })()

  // document events
  $(document).on('click','#hide-layer-options',function(){
    $(".layer-controls").animate({"left":"-100%"},500,"easeInQuint",function(){
      $("#show-layer-options").fadeIn(500);
    });
  })
  .on('click','#show-layer-options',function(){
    $(".layer-controls").animate({"left":"0%"},500,"easeOutQuint");
    $("#show-layer-options").fadeOut(500);
  })
  .on('click','.shuffle-items li.item',function(){
    shuffle.click(this);
  })

})
<|endoftext|>


<commit_before>import {isFunction} from '../helpers/util';
import { baseInterceptor, getQuery } from './baseInterceptor';
import { nativeXHR } from '../helpers/nativeServices';

export const name = 'XMLHttpRequest';
export const Reference = nativeXHR;

export const fakeService = config =>
  baseInterceptor(config, class fakeXMLHttpRequest {
    constructor(helpers) {
      this.xhr = new Reference();
      this.getHandler = helpers.getHandler;
      this.getParams = helpers.getParams;
      this._requestHeaders = {};

      setXhrState(this, this.xhr);
    }

    //TODO: Handle 'async', 'user', 'password'
    open(method, url, async, user, password) {
      this.method = method;
      this.url = url;
      this.xhr.open(method, url);
    }

    //TODO: Handle 'data' parameter
    //TODO: Support all handlers 'progress', 'loadstart', 'abort', 'error'
    send(data) {
      const handler = this.getHandler(this.url, this.method);
      const xhr = this.xhr;
      const onreadyCallback = this.onreadystatechange;
      const onloadCallback = this.onload;
      const successCallback = onreadyCallback || onloadCallback;

      if (handler && successCallback) {
        const params = this.getParams(this.url, this.method);
        const query = getQuery(this.url);
        const headers = this._requestHeaders;

        this.readyState = 4;
        this.status = 200; // @TODO (zzarcon): Support custom status codes
        //TODO: Pass 'body' to handler
        this.responseText = this.response = handler({params, query, headers});

        return successCallback();
      }

      //TODO: Automatically set all the properties
      xhr.onreadystatechange = () => {
        this.readyState = xhr.readyState;
        this.response = xhr.response;
        this.responseText = xhr.responseText;
        this.responseType = xhr.responseType;
        this.responseXML = xhr.responseXML;
        this.status = xhr.status;
        this.statusText = xhr.statusText;

        onreadyCallback && onreadyCallback.call(xhr);
      };

      xhr.onload = () => {
        onloadCallback && onloadCallback.call(xhr);
      };

      return xhr.send();
    }

    setRequestHeader(name, value) {
      this._requestHeaders[name] = value;

      this.xhr.setRequestHeader(name, value);
    }
  });

const setXhrState = (fakeInstance, xhr) => {
  for (let prop in xhr) {
    const value = xhr[prop];
    if (!fakeInstance[prop]) {
      fakeInstance[prop] = isFunction(value) ? value.bind(xhr) : value;
    }
  }
};<commit_msg>Make xhrInterceptor a little cleaner, move utils to helpers<commit_after>import { baseInterceptor, getQuery } from './baseInterceptor';
import { nativeXHR } from '../helpers/nativeServices';
import { extendWithBind } from '../helpers/util';

class XMLHttpRequestInterceptor {
  constructor(helpers) {
    this.xhr = new nativeXHR();
    this.getHandler = helpers.getHandler;
    this.getParams = helpers.getParams;
    this._requestHeaders = {};

    extendWithBind(this, this.xhr);
  }

  //TODO: Handle 'async', 'user', 'password'
  open(method, url, async, user, password) {
    this.method = method;
    this.url = url;
    this.xhr.open(method, url);
  }

  //TODO: Handle 'data' parameter
  //TODO: Support all handlers 'progress', 'loadstart', 'abort', 'error'
  send(data) {
    const handler = this.getHandler(this.url, this.method);
    const xhr = this.xhr;
    const onreadyCallback = this.onreadystatechange;
    const onloadCallback = this.onload;
    const successCallback = onreadyCallback || onloadCallback;

    if (handler && successCallback) {
      const params = this.getParams(this.url, this.method);
      const query = getQuery(this.url);
      const headers = this._requestHeaders;

      this.readyState = 4;
      this.status = 200; // @TODO (zzarcon): Support custom status codes
      //TODO: Pass 'body' to handler
      this.responseText = this.response = handler({params, query, headers});

      return successCallback();
    }

    //TODO: Automatically set all the properties
    xhr.onreadystatechange = () => {
      this.readyState = xhr.readyState;
      this.response = xhr.response;
      this.responseText = xhr.responseText;
      this.responseType = xhr.responseType;
      this.responseXML = xhr.responseXML;
      this.status = xhr.status;
      this.statusText = xhr.statusText;

      return onreadyCallback && onreadyCallback.call(xhr);
    };

    xhr.onload = () => {
      onloadCallback && onloadCallback.call(xhr);
    };

    return xhr.send();
  }

  setRequestHeader(name, value) {
    this._requestHeaders[name] = value;

    this.xhr.setRequestHeader(name, value);
  }
}

export const name = 'XMLHttpRequest';
export const Reference = nativeXHR;
export const fakeService = config =>
  baseInterceptor(config, XMLHttpRequestInterceptor);
<|endoftext|>


<commit_before>(function (factory) {
	// Packaging/modules magic dance
	var L;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet'], factory);
	}

	else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		module.exports = factory(L);
	}

	else {
		// Browser globals
		if (typeof window.L === 'undefined') {
			throw 'Leaflet must be loaded first';
		}
		factory(window.L);
	}
}(function (L) {
	'use strict';
	L.Control.OpenCageSearch = L.Control.extend({
		options: {
			showResultIcons: false,
			collapsed: true,
			expand: 'click',
			position: 'topright',
			placeholder: 'Search...',
			errorMessage: 'Nothing found.',
			key: '',
			limit: 5
		},

		_callbackId: 0,

		initialize: function (options) {
			L.Util.setOptions(this, options);
			if (!this.options.geocoder) {
				this.options.geocoder = new L.Control.OpenCageSearch.Geocoder(this.options);
			}
		},

		onAdd: function (map) {
			var className = 'leaflet-control-ocd-search';
			var container = L.DomUtil.create('div', className);
			var icon = L.DomUtil.create('div', 'leaflet-control-ocd-search-icon', container);
			var form = this._form = L.DomUtil.create('form', className + '-form', container);
			var input;

			this._map = map;
			this._container = container;
			input = this._input = L.DomUtil.create('input');
			input.type = 'text';
			input.placeholder = this.options.placeholder;

			L.DomEvent.addListener(input, 'keydown', this._keydown, this);

			this._errorElement = document.createElement('div');
			this._errorElement.className = className + '-form-no-error';
			this._errorElement.innerHTML = this.options.errorMessage;

			this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-ocd-search-alternatives-minimized');

			form.appendChild(input);
			form.appendChild(this._errorElement);
			container.appendChild(this._alts);

			L.DomEvent.addListener(form, 'submit', this._geocode, this);

			if (this.options.collapsed) {
				if (this.options.expand === 'click') {
					L.DomEvent.addListener(icon, 'click', function(e) {
						// TODO: touch
						if (e.button === 0 && e.detail !== 2) {
							this._toggle();
						}
					}, this);
				}

				else {
					L.DomEvent.addListener(icon, 'mouseover', this._expand, this);
					L.DomEvent.addListener(icon, 'mouseout', this._collapse, this);
					this._map.on('movestart', this._collapse, this);
				}
			}

			else {
				this._expand();
			}

			L.DomEvent.disableClickPropagation(container);

			return container;
		},

		_geocodeResult: function (results) {
			L.DomUtil.removeClass(this._container, 'leaflet-control-ocd-search-spinner');
			if (results.length === 1) {
				this._geocodeResultSelected(results[0]);
			}

			else if (results.length > 0) {
				this._alts.innerHTML = '';
				this._results = results;
				L.DomUtil.removeClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
				for (var i = 0; i < results.length; i++) {
					this._alts.appendChild(this._createAlt(results[i], i));
				}
			}

			else {
				L.DomUtil.addClass(this._errorElement, 'leaflet-control-ocd-search-error');
			}
		},

		markGeocode: function(result) {
			if (result.bounds) {
				this._map.fitBounds(result.bounds);
			} else {
				this._map.panTo(result.center);
			}

			if (this._geocodeMarker) {
				this._map.removeLayer(this._geocodeMarker);
			}

			this._geocodeMarker = new L.Marker(result.center)
				.bindPopup(result.name)
				.addTo(this._map)
				.openPopup();

			return this;
		},

		_geocode: function(event) {
			L.DomEvent.preventDefault(event);

			L.DomUtil.addClass(this._container, 'leaflet-control-ocd-search-spinner');
			this._clearResults();
			this.options.geocoder.geocode(this._input.value, this._geocodeResult, this);

			return false;
		},

		_geocodeResultSelected: function(result) {
			if (this.options.collapsed) {
				this._collapse();
			}

			else {
				this._clearResults();
			}

			this.markGeocode(result);
		},

		_toggle: function() {
			if (this._container.className.indexOf('leaflet-control-ocd-search-expanded') >= 0) {
				this._collapse();
			}

			else {
				this._expand();
			}
		},

		_expand: function () {
			L.DomUtil.addClass(this._container, 'leaflet-control-ocd-search-expanded');
			this._input.select();
		},

		_collapse: function () {
			this._container.className = this._container.className.replace(' leaflet-control-ocd-search-expanded', '');
			L.DomUtil.addClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-ocd-search-error');
		},

		_clearResults: function () {
			L.DomUtil.addClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
			this._selection = null;
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-ocd-search-error');
		},

		_createAlt: function(result, index) {
			var li = document.createElement('li');
			li.innerHTML = '' +
				(this.options.showResultIcons && result.icon ?
					'' :
					'') +
				result.name + '';
			L.DomEvent.addListener(li, 'click', function clickHandler() {
				this._geocodeResultSelected(result);
			}, this);

			return li;
		},

		_keydown: function(e) {
			var _this = this,
				select = function select(dir) {
					if (_this._selection) {
						L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-ocd-search-selected');
						_this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
					}

					if (!_this._selection) {
						_this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
					}

					if (_this._selection) {
						L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-ocd-search-selected');
					}
				};

			switch (e.keyCode) {
			// Up
			case 38:
				select(-1);
				L.DomEvent.preventDefault(e);
				break;
			// Up
			case 40:
				select(1);
				L.DomEvent.preventDefault(e);
				break;
			// Enter
			case 13:
				if (this._selection) {
					var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10);
					this._geocodeResultSelected(this._results[index]);
					this._clearResults();
					L.DomEvent.preventDefault(e);
				}
			}
			return true;
		}
	});

	L.Control.openCageSearch = function(id, options) {
		return new L.Control.OpenCageSearch(id, options);
	};

	L.Control.OpenCageSearch.callbackId = 0;
	L.Control.OpenCageSearch.jsonp = function(url, params, callback, context, jsonpParam) {
		var callbackId = '_ocd_geocoder_' + (L.Control.OpenCageSearch.callbackId++);

		params[jsonpParam || 'callback'] = callbackId;
		window[callbackId] = L.Util.bind(callback, context);
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = url + L.Util.getParamString(params);
		script.id = callbackId;
		document.getElementsByTagName('head')[0].appendChild(script);
	};

	L.Control.OpenCageSearch.Geocoder = L.Class.extend({
		options: {
			serviceUrl: 'https://api.opencagedata.com/geocode/v1/',
			geocodingQueryParams: {},
			reverseQueryParams: {},
			key: '',
			limit: 5
		},

		initialize: function(options) {
			L.Util.setOptions(this, options);
		},

		geocode: function(query, cb, context) {
			L.Control.OpenCageSearch.jsonp(this.options.serviceUrl + 'json/', L.extend({
				q: query,
				limit: this.options.limit,
				key: this.options.key
			}, this.options.geocodingQueryParams),
			function(data) {
				var results = [];
				for (var i=data.results.length - 1; i >= 0; i--) {
					results[i] = {
						name: data.results[i].formatted,
						center: L.latLng(data.results[i].geometry.lat, data.results[i].geometry.lng)
					};
					if (data.results[i].bounds) {
						results[i].bounds = L.latLngBounds(
							[data.results[i].bounds.southwest.lat, data.results[i].bounds.southwest.lng],
							[data.results[i].bounds.northeast.lat, data.results[i].bounds.northeast.lng]);
					}
				}
				cb.call(context, results);
			}, this, 'jsonp');
		},

		reverse: function(location, scale, cb, context) {
			this.geocode(location, cb, context);
		}
	});

	L.Control.OpenCageSearch.geocoder = function(options) {
		return new L.Control.OpenCageSearch.Geocoder(options);
	};

	return L.Control.OpenCageSearch;
}));
<commit_msg>Update L.Control.OpenCageSearch.js<commit_after>(function (factory) {
	// Packaging/modules magic dance
	var L;
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['leaflet'], factory);
	}

	else if (typeof module !== 'undefined') {
		// Node/CommonJS
		L = require('leaflet');
		module.exports = factory(L);
	}

	else {
		// Browser globals
		if (typeof window.L === 'undefined') {
			throw 'Leaflet must be loaded first';
		}
		factory(window.L);
	}
}(function (L) {
	'use strict';
	L.Control.OpenCageSearch = L.Control.extend({
		options: {
			showResultIcons: false,
			collapsed: true,
			expand: 'click',
			position: 'topright',
			placeholder: 'Search...',
			errorMessage: 'Nothing found.',
			key: '',
			limit: 5
		},

		_callbackId: 0,

		initialize: function (options) {
			L.Util.setOptions(this, options);
			if (!this.options.geocoder) {
				this.options.geocoder = new L.Control.OpenCageSearch.Geocoder(this.options);
			}
		},

		onAdd: function (map) {
			var className = 'leaflet-control-ocd-search';
			var container = L.DomUtil.create('div', className);
			var icon = L.DomUtil.create('div', 'leaflet-control-ocd-search-icon', container);
			var form = this._form = L.DomUtil.create('form', className + '-form', container);
			var input;

			this._map = map;
			this._container = container;
			input = this._input = L.DomUtil.create('input');
			input.type = 'text';
			input.placeholder = this.options.placeholder;

			L.DomEvent.addListener(input, 'keydown', this._keydown, this);

			this._errorElement = document.createElement('div');
			this._errorElement.className = className + '-form-no-error';
			this._errorElement.innerHTML = this.options.errorMessage;

			this._alts = L.DomUtil.create('ul', className + '-alternatives leaflet-control-ocd-search-alternatives-minimized');

			form.appendChild(input);
			form.appendChild(this._errorElement);
			container.appendChild(this._alts);

			L.DomEvent.addListener(form, 'submit', this._geocode, this);

			if (this.options.collapsed) {
				if (this.options.expand === 'click') {
					L.DomEvent.addListener(icon, 'click', function(e) {
						// TODO: touch
						if (e.button === 0 && e.detail !== 2) {
							this._toggle();
						}
					}, this);
				}

				else {
					L.DomEvent.addListener(icon, 'mouseover', this._expand, this);
					L.DomEvent.addListener(icon, 'mouseout', this._collapse, this);
					this._map.on('movestart', this._collapse, this);
				}
			}

			else {
				this._expand();
			}

			L.DomEvent.disableClickPropagation(container);

			return container;
		},

		_geocodeResult: function (results) {
			L.DomUtil.removeClass(this._container, 'leaflet-control-ocd-search-spinner');
			if (results.length === 1) {
				this._geocodeResultSelected(results[0]);
			}

			else if (results.length > 0) {
				this._alts.innerHTML = '';
				this._results = results;
				L.DomUtil.removeClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
				for (var i = 0; i < results.length; i++) {
					this._alts.appendChild(this._createAlt(results[i], i));
				}
			}

			else {
				L.DomUtil.addClass(this._errorElement, 'leaflet-control-ocd-search-error');
			}
		},

		markGeocode: function(result) {
			if (result.bounds) {
				this._map.fitBounds(result.bounds);
			} else {
				this._map.panTo(result.center);
			}

			return this;
		},

		_geocode: function(event) {
			L.DomEvent.preventDefault(event);

			L.DomUtil.addClass(this._container, 'leaflet-control-ocd-search-spinner');
			this._clearResults();
			this.options.geocoder.geocode(this._input.value, this._geocodeResult, this);

			return false;
		},

		_geocodeResultSelected: function(result) {
			if (this.options.collapsed) {
				this._collapse();
			}

			else {
				this._clearResults();
			}

			this.markGeocode(result);
		},

		_toggle: function() {
			if (this._container.className.indexOf('leaflet-control-ocd-search-expanded') >= 0) {
				this._collapse();
			}

			else {
				this._expand();
			}
		},

		_expand: function () {
			L.DomUtil.addClass(this._container, 'leaflet-control-ocd-search-expanded');
			this._input.select();
		},

		_collapse: function () {
			this._container.className = this._container.className.replace(' leaflet-control-ocd-search-expanded', '');
			L.DomUtil.addClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-ocd-search-error');
		},

		_clearResults: function () {
			L.DomUtil.addClass(this._alts, 'leaflet-control-ocd-search-alternatives-minimized');
			this._selection = null;
			L.DomUtil.removeClass(this._errorElement, 'leaflet-control-ocd-search-error');
		},

		_createAlt: function(result, index) {
			var li = document.createElement('li');
			li.innerHTML = '' +
				(this.options.showResultIcons && result.icon ?
					'' :
					'') +
				result.name + '';
			L.DomEvent.addListener(li, 'click', function clickHandler() {
				this._geocodeResultSelected(result);
			}, this);

			return li;
		},

		_keydown: function(e) {
			var _this = this,
				select = function select(dir) {
					if (_this._selection) {
						L.DomUtil.removeClass(_this._selection.firstChild, 'leaflet-control-ocd-search-selected');
						_this._selection = _this._selection[dir > 0 ? 'nextSibling' : 'previousSibling'];
					}

					if (!_this._selection) {
						_this._selection = _this._alts[dir > 0 ? 'firstChild' : 'lastChild'];
					}

					if (_this._selection) {
						L.DomUtil.addClass(_this._selection.firstChild, 'leaflet-control-ocd-search-selected');
					}
				};

			switch (e.keyCode) {
			// Up
			case 38:
				select(-1);
				L.DomEvent.preventDefault(e);
				break;
			// Up
			case 40:
				select(1);
				L.DomEvent.preventDefault(e);
				break;
			// Enter
			case 13:
				if (this._selection) {
					var index = parseInt(this._selection.firstChild.getAttribute('data-result-index'), 10);
					this._geocodeResultSelected(this._results[index]);
					this._clearResults();
					L.DomEvent.preventDefault(e);
				}
			}
			return true;
		}
	});

	L.Control.openCageSearch = function(id, options) {
		return new L.Control.OpenCageSearch(id, options);
	};

	L.Control.OpenCageSearch.callbackId = 0;
	L.Control.OpenCageSearch.jsonp = function(url, params, callback, context, jsonpParam) {
		var callbackId = '_ocd_geocoder_' + (L.Control.OpenCageSearch.callbackId++);

		params[jsonpParam || 'callback'] = callbackId;
		window[callbackId] = L.Util.bind(callback, context);
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = url + L.Util.getParamString(params);
		script.id = callbackId;
		document.getElementsByTagName('head')[0].appendChild(script);
	};

	L.Control.OpenCageSearch.Geocoder = L.Class.extend({
		options: {
			serviceUrl: 'https://api.opencagedata.com/geocode/v1/',
			geocodingQueryParams: {},
			reverseQueryParams: {},
			key: '',
			limit: 5
		},

		initialize: function(options) {
			L.Util.setOptions(this, options);
		},

		geocode: function(query, cb, context) {
			L.Control.OpenCageSearch.jsonp(this.options.serviceUrl + 'json/', L.extend({
				q: query,
				limit: this.options.limit,
				key: this.options.key
			}, this.options.geocodingQueryParams),
			function(data) {
				var results = [];
				for (var i=data.results.length - 1; i >= 0; i--) {
					results[i] = {
						name: data.results[i].formatted,
						center: L.latLng(data.results[i].geometry.lat, data.results[i].geometry.lng)
					};
					if (data.results[i].bounds) {
						results[i].bounds = L.latLngBounds(
							[data.results[i].bounds.southwest.lat, data.results[i].bounds.southwest.lng],
							[data.results[i].bounds.northeast.lat, data.results[i].bounds.northeast.lng]);
					}
				}
				cb.call(context, results);
			}, this, 'jsonp');
		},

		reverse: function(location, scale, cb, context) {
			this.geocode(location, cb, context);
		}
	});

	L.Control.OpenCageSearch.geocoder = function(options) {
		return new L.Control.OpenCageSearch.Geocoder(options);
	};

	return L.Control.OpenCageSearch;
}));
<|endoftext|>


<commit_before>app.factory("AuthService", function($rootScope) {
  var isAuthenticated = function() {
    console.log("check you");
    if ($rootScope.user){
      return true;
    } else {
      return false;
    }
  },
  saveLogin = function(user) {
    console.log("Saving ... ", user);
    $rootScope.user = user;
    return true;
  };

  return {
    isAuthenticated: isAuthenticated,
    saveLogin: saveLogin
  };
});<commit_msg>Fix state in scope #21<commit_after>app.factory("AuthService", function($rootScope) {
  var isAuthenticated = function() {
    console.log("check you");
    if ($rootScope.user){
      return true;
    } else {
      return false;
    }
  },
  saveLogin = function(user) {
    console.log("Saving ... ", user);
    $rootScope.user = user;
    return true;
  },
  getToken = function() {
    return $rootScope.user.token;
  };

  return {
    isAuthenticated: isAuthenticated,
    saveLogin: saveLogin
  };
});<|endoftext|>


<commit_before>import classNames from 'classnames';
import {Confirm, Dropdown} from 'reactjs-components';
import {Link} from 'react-router';
var React = require('react');
import {StoreMixin} from 'mesosphere-shared-reactjs';

import Cluster from '../utils/Cluster';
var EventTypes = require('../constants/EventTypes');
import Framework from '../structs/Framework';
import HealthBar from './HealthBar';
import Icon from './Icon';
var MarathonStore = require('../stores/MarathonStore');
import NestedServiceLinks from '../components/NestedServiceLinks';
import ServiceScaleFormModal from '../components/modals/ServiceScaleFormModal';
var ResourceTableUtil = require('../utils/ResourceTableUtil');
import ServiceActionItem from '../constants/ServiceActionItem';
var ServiceTableHeaderLabels = require('../constants/ServiceTableHeaderLabels');
import ServiceTableUtil from '../utils/ServiceTableUtil';
import ServiceTree from '../structs/ServiceTree';
import StringUtil from '../utils/StringUtil';
import {Table} from 'reactjs-components';
import TableUtil from '../utils/TableUtil';
var Units = require('../utils/Units');

const StatusMapping = {
  'Running': 'running-state'
};

var ServicesTable = React.createClass({

  displayName: 'ServicesTable',

  defaultProps: {
    isFiltered: false
  },

  propTypes: {
    isFiltered: React.PropTypes.bool,
    services: React.PropTypes.array.isRequired
  },

  mixins: [StoreMixin],

  getDefaultProps: function () {
    return {
      services: []
    };
  },

  getInitialState: function () {
    return {
      disabledDialog: null,
      errorMsg: null,
      serviceActionDialog: null,
      serviceToChange: null
    };
  },

  componentWillMount: function () {
    this.store_listeners = [
      {
        name: 'marathon',
        events: [
          'serviceDeleteError',
          'serviceDeleteSuccess',
          'serviceEditError',
          'serviceEditSuccess',
          'groupDeleteError',
          'groupDeleteSuccess',
          'groupEditError',
          'groupEditSuccess'
        ]
      }
    ];
  },

  componentDidMount: function () {
    MarathonStore.addChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  componentWillUnmount: function () {
    MarathonStore.removeChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  onMarathonStoreServiceDeleteSuccess: function () {
    this.closeDialog();
    this.context.router.transitionTo('services-page');
  },

  onMarathonStoreServiceDeleteError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreServiceEditSuccess: function () {
    this.closeDialog();
  },

  onMarathonStoreServiceEditError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreGroupDeleteSuccess: function () {
    this.closeDialog();
    this.context.router.transitionTo('services-page');
  },

  onMarathonStoreGroupDeleteError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreGroupEditSuccess: function () {
    this.closeDialog();
  },

  onMarathonStoreGroupEditError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  getOpenInNewWindowLink(service) {
    if (!(service instanceof Framework) || !service.getWebURL()) {
      return null;
    }

    return (

        <Icon
          color="white"
          className="icon-margin-left icon-margin-left-wide"
          family="mini"
          id="open-external"
          size="mini" />

    );
  },

  onAcceptDestroyConfirmDialog: function () {
    let service = this.state.serviceToChange;
    let isGroup = service instanceof ServiceTree;

    this.setState({disabledDialog: ServiceActionItem.DESTROY}, () => {
      let serviceID = service.getId();

      if (isGroup) {
        MarathonStore.deleteGroup(serviceID);
      } else {
        MarathonStore.deleteService(serviceID);
      }
    });
  },

  onAcceptSuspendConfirmDialog: function () {
    let service = this.state.serviceToChange;
    let isGroup = service instanceof ServiceTree;

    this.setState({disabledDialog: ServiceActionItem.SUSPEND}, () => {
      let serviceID = service.getId();

      if (isGroup) {
        MarathonStore.editGroup({
          id: serviceID,
          scaleBy: 0
        });
      } else {
        MarathonStore.editService({
          id: serviceID,
          instances: 0
        });
      }
    });
  },

  onMarathonAppsChange: function () {
    this.forceUpdate();
  },

  onActionsItemSelection: function (service, actionItem) {
    this.setState({
      serviceToChange: service,
      serviceActionDialog: actionItem.id
    });
  },

  closeDialog: function () {
    this.setState({
      disabledDialog: null,
      errorMsg: null,
      serviceActionDialog: null,
      serviceToChange: null
    });
  },

  getErrorMessage: function () {
    let {errorMsg} = this.state;
    if (!errorMsg) {
      return null;
    }
    return (

{errorMsg}

    );
  },

  getDestroyConfirmDialog: function () {
    const {state} = this;
    let service = state.serviceToChange;

    let message = (

Destroy Service

Are you sure you want to destroy {service && service.getId()}? This action is irreversible.

        {this.getErrorMessage()}

    );

    return  (
      <Confirm children={message}
        disabled={state.disabledDialog === ServiceActionItem.DESTROY}
        open={state.serviceActionDialog === ServiceActionItem.DESTROY}
        onClose={this.closeDialog}
        leftButtonText="Cancel"
        leftButtonCallback={this.closeDialog}
        rightButtonText="Destroy Service"
        rightButtonClassName="button button-danger"
        rightButtonCallback={this.onAcceptDestroyConfirmDialog} />
    );
  },

  getSuspendConfirmDialog: function () {
    let service = this.state.serviceToChange;
    const {state} = this;

    let message = (

Suspend Service

Are you sure you want to suspend {service && service.getId()} by scaling to 0 instances?

        {this.getErrorMessage()}

    );

    return  (
      <Confirm children={message}
        disabled={state.disabledDialog === ServiceActionItem.SUSPEND}
        open={state.serviceActionDialog === ServiceActionItem.SUSPEND}
        onClose={this.closeDialog}
        leftButtonText="Cancel"
        leftButtonCallback={this.closeDialog}
        rightButtonText="Suspend Service"
        rightButtonClassName="button button-primary"
        rightButtonCallback={this.onAcceptSuspendConfirmDialog} />
    );
  },

  getServiceScaleFormModal: function () {
    if (!this.state.serviceToChange) {
      return null;
    }

    return (
      <ServiceScaleFormModal
        open={this.state.serviceActionDialog === ServiceActionItem.SCALE}
        service={this.state.serviceToChange}
        onClose={this.closeDialog} />
    );
  },

  getServiceLink: function (service) {
    const id = encodeURIComponent(service.getId());

    if (this.props.isFiltered) {
      return (
        <NestedServiceLinks
          serviceID={id}
          className="service-breadcrumb"
          majorLinkClassName="service-breadcrumb-service-id"
          minorLinkWrapperClassName="service-breadcrumb-crumb" />
      );
    }

    return (
      <Link to="services-detail"
        className="headline table-cell-value flex-box flex-box-col"
        params={{id}}>

          {service.getName()}

      </Link>
    );
  },

  getImage: function (service) {
    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      return (
        <Icon
          className="icon-margin-right"
          color="grey"
          id="folder"
          size="small"
          family="small" />
      );
    }

    // Get service image/icon
    return (

    );
  },

  renderHeadline: function (prop, service) {
    const id = encodeURIComponent(service.getId());

    return (

        <Link to="services-detail"
          className="table-cell-icon"
          params={{id}}>
          {this.getImage(service)}
        </Link>
        {this.getServiceLink(service)}
        {this.getOpenInNewWindowLink(service)}

    );
  },

  renderServiceActions: function (prop, service) {
    let isGroup = service instanceof ServiceTree;
    let instancesCount = service.getInstancesCount();
    let scaleText = 'Scale';
    if (isGroup) {
      scaleText = 'Scale By';
    }

    const dropdownItems = [
      {
        className: 'hidden',
        id: ServiceActionItem.MORE,
        html: '',
        selectedHtml: (
          <Icon
            family="mini"
            id="gear"
            size="mini"
            className="icon-alert icon-margin-right"
            color="white" />
        )
      },
      {
        className: classNames({
          hidden: isGroup && instancesCount === 0
        }),
        id: ServiceActionItem.SCALE,
        html: scaleText
      },
      {
        className: classNames({
          hidden: instancesCount === 0
        }),
        id: ServiceActionItem.SUSPEND,
        html: 'Suspend'
      },
      {
        id: ServiceActionItem.DESTROY,
        html: Destroy
      }
    ];

    return (
      <Dropdown
        key="actions-dropdown"
        buttonClassName="button button-mini dropdown-toggle button-link button-inverse table-display-on-row-hover"
        dropdownMenuClassName="dropdown-menu"
        dropdownMenuListClassName="dropdown-menu-list"
        dropdownMenuListItemClassName="clickable"
        wrapperClassName="dropdown anchor-right flush-bottom"
        items={dropdownItems}
        persistentID={ServiceActionItem.MORE}
        onItemSelection={this.onActionsItemSelection.bind(this, service)}
        transition={true}
        transitionName="dropdown-menu" />
    );
  },

  renderStatus: function (prop, service) {
    let instanceCount = service.getInstancesCount();
    let serviceId = service.getId();
    let serviceStatus = service.getStatus();
    let serviceStatusClassSet = StatusMapping[serviceStatus] || '';
    let taskSummary = service.getTasksSummary();
    let {tasksRunning} = taskSummary;

    let conciseOverview = ` (${tasksRunning}/${instanceCount})`;
    let verboseOverview = ` (${tasksRunning} ${StringUtil.pluralize('Task', tasksRunning)})`;
    if (tasksRunning !== instanceCount) {
      verboseOverview = ` (${tasksRunning} of ${instanceCount} Tasks)`;
    }

    return (

          <HealthBar
            key={serviceId}
            tasksSummary={taskSummary}
            instancesCount={instanceCount} />

          {serviceStatus}
          {verboseOverview}
          {conciseOverview}

    );
  },

  renderStats: function (prop, service) {
    return (

        {Units.formatResource(prop, service.getResources()[prop])}

    );
  },

  renderStatsHeading: function (prop, sortBy, row) {
    let isHeader = row == null;

    return classNames('flush-left text-align-right hidden-mini hidden-small', {
      'highlight': prop === sortBy.prop,
      'clickable': isHeader
    });
  },

  getColumns: function () {
    let className = ResourceTableUtil.getClassName;
    let heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);
    let {isFiltered} = this.props;

    return [
      {
        className: function () {
          return classNames([
            className.apply(this, arguments),
            {'table-cell-short': isFiltered}
          ]);
        },
        headerClassName: className,
        prop: 'name',
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'serviceActions',
        render: this.renderServiceActions,
        sortable: false,
        heading: function () { return null; }
      },
      {
        className,
        headerClassName: className,
        prop: 'status',
        helpText: 'At-a-glance overview of the global application or group state',
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'cpus',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'mem',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'disk',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      }
    ];
  },

  getColGroup: function () {
    return (
      <colgroup>
        <col />
        <col style={{width: '40px'}} />
        <col className="status-bar-column"/>
        <col className="hidden-mini hidden-small" style={{width: '85px'}} />
        <col className="hidden-mini hidden-small" style={{width: '75px'}} />
        <col className="hidden-mini hidden-small" style={{width: '85px'}} />
      </colgroup>
    );
  },

  render: function () {
    return (

        {this.getDestroyConfirmDialog()}
        {this.getServiceScaleFormModal()}
        {this.getSuspendConfirmDialog()}

    );
  }
});

module.exports = ServicesTable;
<commit_msg>Change item text to group if group<commit_after>import classNames from 'classnames';
import {Confirm, Dropdown, Table} from 'reactjs-components';
import {Link} from 'react-router';
var React = require('react');
import {StoreMixin} from 'mesosphere-shared-reactjs';

import Cluster from '../utils/Cluster';
var EventTypes = require('../constants/EventTypes');
import Framework from '../structs/Framework';
import HealthBar from './HealthBar';
import Icon from './Icon';
var MarathonStore = require('../stores/MarathonStore');
import NestedServiceLinks from '../components/NestedServiceLinks';
import ServiceScaleFormModal from '../components/modals/ServiceScaleFormModal';
var ResourceTableUtil = require('../utils/ResourceTableUtil');
import ServiceActionItem from '../constants/ServiceActionItem';
var ServiceTableHeaderLabels = require('../constants/ServiceTableHeaderLabels');
import ServiceTableUtil from '../utils/ServiceTableUtil';
import ServiceTree from '../structs/ServiceTree';
import StringUtil from '../utils/StringUtil';
import TableUtil from '../utils/TableUtil';
var Units = require('../utils/Units');

const StatusMapping = {
  'Running': 'running-state'
};

var ServicesTable = React.createClass({

  displayName: 'ServicesTable',

  defaultProps: {
    isFiltered: false
  },

  propTypes: {
    isFiltered: React.PropTypes.bool,
    services: React.PropTypes.array.isRequired
  },

  mixins: [StoreMixin],

  getDefaultProps: function () {
    return {
      services: []
    };
  },

  getInitialState: function () {
    return {
      disabledDialog: null,
      errorMsg: null,
      serviceActionDialog: null,
      serviceToChange: null
    };
  },

  componentWillMount: function () {
    this.store_listeners = [
      {
        name: 'marathon',
        events: [
          'serviceDeleteError',
          'serviceDeleteSuccess',
          'serviceEditError',
          'serviceEditSuccess',
          'groupDeleteError',
          'groupDeleteSuccess',
          'groupEditError',
          'groupEditSuccess'
        ]
      }
    ];
  },

  componentDidMount: function () {
    MarathonStore.addChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  componentWillUnmount: function () {
    MarathonStore.removeChangeListener(
      EventTypes.MARATHON_APPS_CHANGE,
      this.onMarathonAppsChange
    );
  },

  onMarathonStoreServiceDeleteSuccess: function () {
    this.closeDialog();
    this.context.router.transitionTo('services-page');
  },

  onMarathonStoreServiceDeleteError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreServiceEditSuccess: function () {
    this.closeDialog();
  },

  onMarathonStoreServiceEditError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreGroupDeleteSuccess: function () {
    this.closeDialog();
    this.context.router.transitionTo('services-page');
  },

  onMarathonStoreGroupDeleteError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  onMarathonStoreGroupEditSuccess: function () {
    this.closeDialog();
  },

  onMarathonStoreGroupEditError: function ({message:errorMsg}) {
    this.setState({
      disabledDialog: null,
      errorMsg
    });
  },

  getOpenInNewWindowLink(service) {
    if (!(service instanceof Framework) || !service.getWebURL()) {
      return null;
    }

    return (

        <Icon
          color="white"
          className="icon-margin-left icon-margin-left-wide"
          family="mini"
          id="open-external"
          size="mini" />

    );
  },

  onAcceptDestroyConfirmDialog: function () {
    let service = this.state.serviceToChange;
    let isGroup = service instanceof ServiceTree;

    this.setState({disabledDialog: ServiceActionItem.DESTROY}, () => {
      let serviceID = service.getId();

      if (isGroup) {
        MarathonStore.deleteGroup(serviceID);
      } else {
        MarathonStore.deleteService(serviceID);
      }
    });
  },

  onAcceptSuspendConfirmDialog: function () {
    let service = this.state.serviceToChange;
    let isGroup = service instanceof ServiceTree;

    this.setState({disabledDialog: ServiceActionItem.SUSPEND}, () => {
      let serviceID = service.getId();

      if (isGroup) {
        MarathonStore.editGroup({
          id: serviceID,
          scaleBy: 0
        });
      } else {
        MarathonStore.editService({
          id: serviceID,
          instances: 0
        });
      }
    });
  },

  onMarathonAppsChange: function () {
    this.forceUpdate();
  },

  onActionsItemSelection: function (service, actionItem) {
    this.setState({
      serviceToChange: service,
      serviceActionDialog: actionItem.id
    });
  },

  closeDialog: function () {
    this.setState({
      disabledDialog: null,
      errorMsg: null,
      serviceActionDialog: null,
      serviceToChange: null
    });
  },

  getErrorMessage: function () {
    let {errorMsg} = this.state;
    if (!errorMsg) {
      return null;
    }
    return (

{errorMsg}

    );
  },

  getDestroyConfirmDialog: function () {
    const {state} = this;
    let service = state.serviceToChange;
    let itemText = 'Service';
    if (service instanceof ServiceTree) {
      itemText = 'Group';
    }

    let message = (

Destroy {itemText}

Are you sure you want to destroy {service && service.getId()}? This action is irreversible.

        {this.getErrorMessage()}

    );

    return (
      <Confirm children={message}
        disabled={state.disabledDialog === ServiceActionItem.DESTROY}
        open={state.serviceActionDialog === ServiceActionItem.DESTROY}
        onClose={this.closeDialog}
        leftButtonText="Cancel"
        leftButtonCallback={this.closeDialog}
        rightButtonText="Destroy Service"
        rightButtonClassName="button button-danger"
        rightButtonCallback={this.onAcceptDestroyConfirmDialog} />
    );
  },

  getSuspendConfirmDialog: function () {
    let service = this.state.serviceToChange;
    const {state} = this;
    let itemText = 'Service';
    if (service instanceof ServiceTree) {
      itemText = 'Group';
    }

    let message = (

Suspend {itemText}

Are you sure you want to suspend {service && service.getId()} by scaling to 0 instances?

        {this.getErrorMessage()}

    );

    return (
      <Confirm children={message}
        disabled={state.disabledDialog === ServiceActionItem.SUSPEND}
        open={state.serviceActionDialog === ServiceActionItem.SUSPEND}
        onClose={this.closeDialog}
        leftButtonText="Cancel"
        leftButtonCallback={this.closeDialog}
        rightButtonText="Suspend Service"
        rightButtonClassName="button button-primary"
        rightButtonCallback={this.onAcceptSuspendConfirmDialog} />
    );
  },

  getServiceScaleFormModal: function () {
    if (!this.state.serviceToChange) {
      return null;
    }

    return (
      <ServiceScaleFormModal
        open={this.state.serviceActionDialog === ServiceActionItem.SCALE}
        service={this.state.serviceToChange}
        onClose={this.closeDialog} />
    );
  },

  getServiceLink: function (service) {
    const id = encodeURIComponent(service.getId());

    if (this.props.isFiltered) {
      return (
        <NestedServiceLinks
          serviceID={id}
          className="service-breadcrumb"
          majorLinkClassName="service-breadcrumb-service-id"
          minorLinkWrapperClassName="service-breadcrumb-crumb" />
      );
    }

    return (
      <Link to="services-detail"
        className="headline table-cell-value flex-box flex-box-col"
        params={{id}}>

          {service.getName()}

      </Link>
    );
  },

  getImage: function (service) {
    if (service instanceof ServiceTree) {
      // Get serviceTree image/icon
      return (
        <Icon
          className="icon-margin-right"
          color="grey"
          id="folder"
          size="small"
          family="small" />
      );
    }

    // Get service image/icon
    return (

    );
  },

  renderHeadline: function (prop, service) {
    const id = encodeURIComponent(service.getId());

    return (

        <Link to="services-detail"
          className="table-cell-icon"
          params={{id}}>
          {this.getImage(service)}
        </Link>
        {this.getServiceLink(service)}
        {this.getOpenInNewWindowLink(service)}

    );
  },

  renderServiceActions: function (prop, service) {
    let isGroup = service instanceof ServiceTree;
    let instancesCount = service.getInstancesCount();
    let scaleText = 'Scale';
    if (isGroup) {
      scaleText = 'Scale By';
    }

    const dropdownItems = [
      {
        className: 'hidden',
        id: ServiceActionItem.MORE,
        html: '',
        selectedHtml: (
          <Icon
            family="mini"
            id="gear"
            size="mini"
            className="icon-alert icon-margin-right"
            color="white" />
        )
      },
      {
        className: classNames({
          hidden: isGroup && instancesCount === 0
        }),
        id: ServiceActionItem.SCALE,
        html: scaleText
      },
      {
        className: classNames({
          hidden: instancesCount === 0
        }),
        id: ServiceActionItem.SUSPEND,
        html: 'Suspend'
      },
      {
        id: ServiceActionItem.DESTROY,
        html: Destroy
      }
    ];

    return (
      <Dropdown
        key="actions-dropdown"
        buttonClassName="button button-mini dropdown-toggle button-link button-inverse table-display-on-row-hover"
        dropdownMenuClassName="dropdown-menu"
        dropdownMenuListClassName="dropdown-menu-list"
        dropdownMenuListItemClassName="clickable"
        wrapperClassName="dropdown anchor-right flush-bottom"
        items={dropdownItems}
        persistentID={ServiceActionItem.MORE}
        onItemSelection={this.onActionsItemSelection.bind(this, service)}
        transition={true}
        transitionName="dropdown-menu" />
    );
  },

  renderStatus: function (prop, service) {
    let instanceCount = service.getInstancesCount();
    let serviceId = service.getId();
    let serviceStatus = service.getStatus();
    let serviceStatusClassSet = StatusMapping[serviceStatus] || '';
    let taskSummary = service.getTasksSummary();
    let {tasksRunning} = taskSummary;

    let conciseOverview = ` (${tasksRunning}/${instanceCount})`;
    let verboseOverview = ` (${tasksRunning} ${StringUtil.pluralize('Task', tasksRunning)})`;
    if (tasksRunning !== instanceCount) {
      verboseOverview = ` (${tasksRunning} of ${instanceCount} Tasks)`;
    }

    return (

          <HealthBar
            key={serviceId}
            tasksSummary={taskSummary}
            instancesCount={instanceCount} />

          {serviceStatus}
          {verboseOverview}
          {conciseOverview}

    );
  },

  renderStats: function (prop, service) {
    return (

        {Units.formatResource(prop, service.getResources()[prop])}

    );
  },

  renderStatsHeading: function (prop, sortBy, row) {
    let isHeader = row == null;

    return classNames('flush-left text-align-right hidden-mini hidden-small', {
      'highlight': prop === sortBy.prop,
      'clickable': isHeader
    });
  },

  getColumns: function () {
    let className = ResourceTableUtil.getClassName;
    let heading = ResourceTableUtil.renderHeading(ServiceTableHeaderLabels);
    let {isFiltered} = this.props;

    return [
      {
        className: function () {
          return classNames([
            className.apply(this, arguments),
            {'table-cell-short': isFiltered}
          ]);
        },
        headerClassName: className,
        prop: 'name',
        render: this.renderHeadline,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className,
        headerClassName: className,
        prop: 'serviceActions',
        render: this.renderServiceActions,
        sortable: false,
        heading: function () { return null; }
      },
      {
        className,
        headerClassName: className,
        prop: 'status',
        helpText: 'At-a-glance overview of the global application or group state',
        render: this.renderStatus,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'cpus',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'mem',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      },
      {
        className: this.renderStatsHeading,
        headerClassName: this.renderStatsHeading,
        prop: 'disk',
        render: this.renderStats,
        sortable: true,
        sortFunction: ServiceTableUtil.propCompareFunctionFactory,
        heading
      }
    ];
  },

  getColGroup: function () {
    return (
      <colgroup>
        <col />
        <col style={{width: '40px'}} />
        <col className="status-bar-column"/>
        <col className="hidden-mini hidden-small" style={{width: '85px'}} />
        <col className="hidden-mini hidden-small" style={{width: '75px'}} />
        <col className="hidden-mini hidden-small" style={{width: '85px'}} />
      </colgroup>
    );
  },

  render: function () {
    return (

        {this.getDestroyConfirmDialog()}
        {this.getServiceScaleFormModal()}
        {this.getSuspendConfirmDialog()}

    );
  }
});

module.exports = ServicesTable;
<|endoftext|>


<commit_before>import sampleCombine from 'xstream/extra/sampleCombine'
import isolate from '@cycle/isolate'
import { i,p, div, br, label, input, code, table, tr, td, b, h2, button, textarea, a } from '@cycle/dom';
import { clone, equals } from 'ramda';
import xs from 'xstream';
import { logThis, log } from '../utils/logger'
import { ENTER_KEYCODE } from '../utils/keycodes.js'
import { SignatureCheck } from '../components/SignatureCheck'
import dropRepeats from 'xstream/extra/dropRepeats'

function SignatureForm(sources) {

	console.log('Starting component: SignatureForm...');

	const state$ = sources.onion.state$//.debug(console.log)
	const domSource$ = sources.DOM;
	const props$ = sources.props;

	// Check Signature subcomponent, via isolation
	const signatureCheckSink = isolate(SignatureCheck, 'query')(sources)
	const signatureCheckDom$ = signatureCheckSink.DOM;
	const signatureCheckHTTP$ = signatureCheckSink.HTTP;
	const signatureCheckReducer$ = signatureCheckSink.onion;

	// Valid query?
	const validated$ = state$.map(state => state.validated)

	const vdom$ = xs.combine(state$, signatureCheckDom$, validated$)
					.map(
						([state, checkdom, validated]) => {
							const query = state.query
							return div(
									[
										 div('.row  .green .darken-2 .white-text', {style : {padding: '20px 10px 10px 10px'}}, [
											// label('Query: '),
											div('.Default .waves-effect .col .s1', [
												i('.large  .center-align .material-icons .green-text', {style: {fontSize: '45px', fontColor: 'gray'}}, 'search'),
											]),
											// textarea('.Query .col s11 .materialize-textarea', {style: {fontSize: '20px'} , props: {type: 'text', value: query.trim()}, value: query.trim()}),
											input('.Query .col s10', {style: {fontSize: '20px'} , props: {type: 'text', value: query}, value: query}),
											// div('.row', [
												// div('.col .s1'),
											(validated)
											? div('.SignatureCheck .waves-effect .col .s1 .right-align', [
												i('.large .material-icons', {style: {fontSize: '45px', fontColor: 'grey'}}, ['play_arrow'])])
											: div('.SignatureCheck .col .s1 .right-align', [
												i('.large .material-icons  .green-text', {style: {fontSize: '45px', fontColor: 'grey'}}, 'play_arrow')])
											// ])
										]),
										(!validated) ? checkdom : div()
									])
	});

	// Update in query, or simply ENTER
	const newQuery$ = xs.merge(
				// state$.map(state => state.query),
				domSource$.select('.Query').events('input').map(ev => ev.target.value)
			).debug(console.log)

	// Updated state is propagated and picked up by the necessary components
	const click$ = domSource$.select('.SignatureCheck').events('click')
    const enter$ = domSource$.select('.Query').events('keydown').filter(({keyCode, ctrlKey}) => keyCode === ENTER_KEYCODE && ctrlKey === false) ;
	const update$ = xs.merge(click$, enter$)//.debug(log)

	// Set a default signature for demo purposes
	const setDefault$ = sources.DOM.select('.Default').events('click')
	const setDefaultReducer$ = setDefault$.map(events => prevState => {
		let newState = clone(prevState)
		newState.query = 'ENSG00000012048 -WRONG HSPA1A DNAJB1 DDIT4 -TSEN2'
		newState.validated = false
		return newState
	})

	// Takes care of initialization
	const defaultReducer$ = xs.of(function defaultReducer(prevState) {
		console.log('Signatureform -- defaultReducer')
        if (typeof prevState === 'undefined') {
			// console.log('prevState not exists')
			return {
				query : '', //ENSG00000012048 -WRONG HSPA1A DNAJB1 DDIT4 -TSEN2',
				validated : false
			}
        } else {
			// console.log('prevState exists')
			let newState = clone(prevState)
			// newState.validated = false
            return newState;
        }
    });

	// Update the state when input changes
	const queryReducer$ = newQuery$.map(query => prevState => {
		console.log('Signatureform -- queryReducer')
		let newState = clone(prevState)
		// console.log(newState)
		newState.query = query
		return newState
	})

	// invalidates the query when input changes
	const invalidateReducer$ = newQuery$.map(query => prevState => {
		console.log('Signatureform -- invalidateReducer')
		let newState = clone(prevState)
		newState.validated = false
		return newState
	})

	// Validates the state when validated from check
	const validateReducer$ = signatureCheckSink.validated
		.map(signal => prevState => {
			console.log('Signatureform -- validateReducer')
			let newState = clone(prevState)
			newState.validated = true
			return newState
		})

	// When update is clicked, update the query. Onionify does the rest
	const childReducer$ = signatureCheckSink.onion

	// When GO clicked or enter -> send updated 'value' to sink
	// Maybe catch when no valid query?
	const query$ = update$
		.compose(sampleCombine(state$))
		.map(([update, state]) => state.query)
		// .startWith(null).debug(log)

  return {
    	DOM: vdom$,
		onion: xs.merge(
			defaultReducer$,
			setDefaultReducer$,
			queryReducer$,
			invalidateReducer$,
			childReducer$,
			validateReducer$,
			),
		HTTP: signatureCheckHTTP$,
		query: query$.debug(q => console.log('!!! QUERY FIRED !!! ' + q))//.compose(dropRepeats(equals))

  };

}

export { SignatureForm };<commit_msg>Improved alignment<commit_after>import sampleCombine from 'xstream/extra/sampleCombine'
import isolate from '@cycle/isolate'
import { i,p, div, br, label, input, code, table, tr, td, b, h2, button, textarea, a } from '@cycle/dom';
import { clone, equals } from 'ramda';
import xs from 'xstream';
import { logThis, log } from '../utils/logger'
import { ENTER_KEYCODE } from '../utils/keycodes.js'
import { SignatureCheck } from '../components/SignatureCheck'
import dropRepeats from 'xstream/extra/dropRepeats'

function SignatureForm(sources) {

	console.log('Starting component: SignatureForm...');

	const state$ = sources.onion.state$//.debug(console.log)
	const domSource$ = sources.DOM;
	const props$ = sources.props;

	// Check Signature subcomponent, via isolation
	const signatureCheckSink = isolate(SignatureCheck, 'query')(sources)
	const signatureCheckDom$ = signatureCheckSink.DOM;
	const signatureCheckHTTP$ = signatureCheckSink.HTTP;
	const signatureCheckReducer$ = signatureCheckSink.onion;

	// Valid query?
	const validated$ = state$.map(state => state.validated)

	const vdom$ = xs.combine(state$, signatureCheckDom$, validated$)
					.map(
						([state, checkdom, validated]) => {
							const query = state.query
							return div(
								[
									div('.row  .green .darken-2 .white-text', {style : {padding: '20px 10px 10px 10px'}}, [
									// label('Query: '),
										div('.Default .waves-effect .col .s1', [
											i('.large  .center-align .material-icons .green-text', {style: {fontSize: '45px', fontColor: 'gray'}}, 'search'),
										]),
										// textarea('.Query .col .s10 .materialize-textarea', {style: {fontSize: '20px'} , props: {type: 'text', value: query.trim()}, value: query.trim()}),
										input('.Query .col s10', {style: {fontSize: '20px'} , props: {type: 'text', value: query}, value: query}),
										// div('.row', [
											// div('.col .s1'),
										(validated)
										? div('.SignatureCheck .waves-effect .col .s1 .center-align', [
											i('.large .material-icons', {style: {fontSize: '45px', fontColor: 'grey'}}, ['play_arrow'])])
										: div('.SignatureCheck .col .s1 .center-align', [
											i('.large .material-icons .green-text', {style: {fontSize: '45px', fontColor: 'grey'}}, 'play_arrow')])
										// ])
									]),
									(!validated) ? checkdom : div()
								])
	});

	// Update in query, or simply ENTER
	const newQuery$ = xs.merge(
				// state$.map(state => state.query),
				domSource$.select('.Query').events('input').map(ev => ev.target.value)
			).debug(console.log)

	// Updated state is propagated and picked up by the necessary components
	const click$ = domSource$.select('.SignatureCheck').events('click')
    const enter$ = domSource$.select('.Query').events('keydown').filter(({keyCode, ctrlKey}) => keyCode === ENTER_KEYCODE && ctrlKey === false) ;
	const update$ = xs.merge(click$, enter$)//.debug(log)

	// Set a default signature for demo purposes
	const setDefault$ = sources.DOM.select('.Default').events('click')
	const setDefaultReducer$ = setDefault$.map(events => prevState => {
		let newState = clone(prevState)
		newState.query = 'ENSG00000012048 -WRONG HSPA1A DNAJB1 DDIT4 -TSEN2'
		newState.validated = false
		return newState
	})

	// Takes care of initialization
	const defaultReducer$ = xs.of(function defaultReducer(prevState) {
		console.log('Signatureform -- defaultReducer')
        if (typeof prevState === 'undefined') {
			// console.log('prevState not exists')
			return {
				query : '', //ENSG00000012048 -WRONG HSPA1A DNAJB1 DDIT4 -TSEN2',
				validated : false
			}
        } else {
			// console.log('prevState exists')
			let newState = clone(prevState)
			// newState.validated = false
            return newState;
        }
    });

	// Update the state when input changes
	const queryReducer$ = newQuery$.map(query => prevState => {
		console.log('Signatureform -- queryReducer')
		let newState = clone(prevState)
		// console.log(newState)
		newState.query = query
		return newState
	})

	// invalidates the query when input changes
	const invalidateReducer$ = newQuery$.map(query => prevState => {
		console.log('Signatureform -- invalidateReducer')
		let newState = clone(prevState)
		newState.validated = false
		return newState
	})

	// Validates the state when validated from check
	const validateReducer$ = signatureCheckSink.validated
		.map(signal => prevState => {
			console.log('Signatureform -- validateReducer')
			let newState = clone(prevState)
			newState.validated = true
			return newState
		})

	// When update is clicked, update the query. Onionify does the rest
	const childReducer$ = signatureCheckSink.onion

	// When GO clicked or enter -> send updated 'value' to sink
	// Maybe catch when no valid query?
	const query$ = update$
		.compose(sampleCombine(state$))
		.map(([update, state]) => state.query)
		// .startWith(null).debug(log)

  return {
    	DOM: vdom$,
		onion: xs.merge(
			defaultReducer$,
			setDefaultReducer$,
			queryReducer$,
			invalidateReducer$,
			childReducer$,
			validateReducer$,
			),
		HTTP: signatureCheckHTTP$,
		query: query$.debug(q => console.log('!!! QUERY FIRED !!! ' + q))//.compose(dropRepeats(equals))

  };

}

export { SignatureForm };<|endoftext|>