mirror of https://github.com/portainer/portainer
				
				
				
			refactor(global): service separation #552
							parent
							
								
									0abe8883d1
								
							
						
					
					
						commit
						fe0bf77bbb
					
				
							
								
								
									
										27
									
								
								app/app.js
								
								
								
								
							
							
						
						
									
										27
									
								
								app/app.js
								
								
								
								
							| 
						 | 
				
			
			@ -1,5 +1,8 @@
 | 
			
		|||
angular.module('portainer.filters', []);
 | 
			
		||||
angular.module('portainer.rest', ['ngResource']);
 | 
			
		||||
angular.module('portainer.services', []);
 | 
			
		||||
angular.module('portainer.helpers', []);
 | 
			
		||||
angular.module('portainer', [
 | 
			
		||||
  'portainer.templates',
 | 
			
		||||
  'ui.bootstrap',
 | 
			
		||||
  'ui.router',
 | 
			
		||||
  'ui.select',
 | 
			
		||||
| 
						 | 
				
			
			@ -9,9 +12,11 @@ angular.module('portainer', [
 | 
			
		|||
  'angularUtils.directives.dirPagination',
 | 
			
		||||
  'LocalStorageModule',
 | 
			
		||||
  'angular-jwt',
 | 
			
		||||
  'portainer.services',
 | 
			
		||||
  'portainer.helpers',
 | 
			
		||||
  'portainer.templates',
 | 
			
		||||
  'portainer.filters',
 | 
			
		||||
  'portainer.rest',
 | 
			
		||||
  'portainer.helpers',
 | 
			
		||||
  'portainer.services',
 | 
			
		||||
  'auth',
 | 
			
		||||
  'dashboard',
 | 
			
		||||
  'container',
 | 
			
		||||
| 
						 | 
				
			
			@ -19,29 +24,29 @@ angular.module('portainer', [
 | 
			
		|||
  'containerLogs',
 | 
			
		||||
  'containers',
 | 
			
		||||
  'createContainer',
 | 
			
		||||
  'createNetwork',
 | 
			
		||||
  'createService',
 | 
			
		||||
  'createVolume',
 | 
			
		||||
  'docker',
 | 
			
		||||
  'endpoint',
 | 
			
		||||
  'endpointInit',
 | 
			
		||||
  'endpoints',
 | 
			
		||||
  'events',
 | 
			
		||||
  'images',
 | 
			
		||||
  'image',
 | 
			
		||||
  'images',
 | 
			
		||||
  'main',
 | 
			
		||||
  'network',
 | 
			
		||||
  'networks',
 | 
			
		||||
  'node',
 | 
			
		||||
  'service',
 | 
			
		||||
  'services',
 | 
			
		||||
  'settings',
 | 
			
		||||
  'sidebar',
 | 
			
		||||
  'createService',
 | 
			
		||||
  'stats',
 | 
			
		||||
  'swarm',
 | 
			
		||||
  'network',
 | 
			
		||||
  'networks',
 | 
			
		||||
  'node',
 | 
			
		||||
  'createNetwork',
 | 
			
		||||
  'task',
 | 
			
		||||
  'templates',
 | 
			
		||||
  'volumes',
 | 
			
		||||
  'createVolume'])
 | 
			
		||||
  'volumes'])
 | 
			
		||||
  .config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 'localStorageServiceProvider', 'jwtOptionsProvider', function ($stateProvider, $urlRouterProvider, $httpProvider, localStorageServiceProvider, jwtOptionsProvider) {
 | 
			
		||||
    'use strict';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('ContainerHelper', [function ContainerHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    hideContainers: function(containers, containersToHideLabels) {
 | 
			
		||||
      return containers.filter(function (container) {
 | 
			
		||||
        var filterContainer = false;
 | 
			
		||||
        containersToHideLabels.forEach(function(label, index) {
 | 
			
		||||
          if (_.has(container.Labels, label.name) &&
 | 
			
		||||
          container.Labels[label.name] === label.value) {
 | 
			
		||||
            filterContainer = true;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        if (!filterContainer) {
 | 
			
		||||
          return container;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('ImageHelper', [function ImageHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    createImageConfigForCommit: function(imageName, registry) {
 | 
			
		||||
      var imageNameAndTag = imageName.split(':');
 | 
			
		||||
      var image = imageNameAndTag[0];
 | 
			
		||||
      if (registry) {
 | 
			
		||||
        image = registry + '/' + imageNameAndTag[0];
 | 
			
		||||
      }
 | 
			
		||||
      var imageConfig = {
 | 
			
		||||
        repo: image,
 | 
			
		||||
        tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest'
 | 
			
		||||
      };
 | 
			
		||||
      return imageConfig;
 | 
			
		||||
    },
 | 
			
		||||
    createImageConfigForContainer: function (imageName, registry) {
 | 
			
		||||
      var imageNameAndTag = imageName.split(':');
 | 
			
		||||
      var image = imageNameAndTag[0];
 | 
			
		||||
      if (registry) {
 | 
			
		||||
        image = registry + '/' + imageNameAndTag[0];
 | 
			
		||||
      }
 | 
			
		||||
      var imageConfig = {
 | 
			
		||||
        fromImage: image,
 | 
			
		||||
        tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest'
 | 
			
		||||
      };
 | 
			
		||||
      return imageConfig;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('InfoHelper', [function InfoHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    determineEndpointMode: function(info) {
 | 
			
		||||
      var mode = {
 | 
			
		||||
        provider: '',
 | 
			
		||||
        role: ''
 | 
			
		||||
      };
 | 
			
		||||
      if (_.startsWith(info.ServerVersion, 'swarm')) {
 | 
			
		||||
        mode.provider = "DOCKER_SWARM";
 | 
			
		||||
        if (info.SystemStatus[0][1] === 'primary') {
 | 
			
		||||
          mode.role = "PRIMARY";
 | 
			
		||||
        } else {
 | 
			
		||||
          mode.role = "REPLICA";
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        if (!info.Swarm || _.isEmpty(info.Swarm.NodeID)) {
 | 
			
		||||
          mode.provider = "DOCKER_STANDALONE";
 | 
			
		||||
        } else {
 | 
			
		||||
          mode.provider = "DOCKER_SWARM_MODE";
 | 
			
		||||
          if (info.Swarm.ControlAvailable) {
 | 
			
		||||
            mode.role = "MANAGER";
 | 
			
		||||
          } else {
 | 
			
		||||
            mode.role = "WORKER";
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return mode;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('LabelHelper', [function LabelHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    fromLabelHashToKeyValue: function(labels) {
 | 
			
		||||
      if (labels) {
 | 
			
		||||
        return Object.keys(labels).map(function(key) {
 | 
			
		||||
          return {key: key, value: labels[key], originalKey: key, originalValue: labels[key], added: true};
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return [];
 | 
			
		||||
    },
 | 
			
		||||
    fromKeyValueToLabelHash: function(labelKV) {
 | 
			
		||||
      var labels = {};
 | 
			
		||||
      if (labelKV) {
 | 
			
		||||
        labelKV.forEach(function(label) {
 | 
			
		||||
          labels[label.key] = label.value;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return labels;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('NodeHelper', [function NodeHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    nodeToConfig: function(node) {
 | 
			
		||||
      return {
 | 
			
		||||
        Name: node.Spec.Name,
 | 
			
		||||
        Role: node.Spec.Role,
 | 
			
		||||
        Labels: node.Spec.Labels,
 | 
			
		||||
        Availability: node.Spec.Availability
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('ServiceHelper', [function ServiceHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    serviceToConfig: function(service) {
 | 
			
		||||
      return {
 | 
			
		||||
        Name: service.Spec.Name,
 | 
			
		||||
        Labels: service.Spec.Labels,
 | 
			
		||||
        TaskTemplate: service.Spec.TaskTemplate,
 | 
			
		||||
        Mode: service.Spec.Mode,
 | 
			
		||||
        UpdateConfig: service.Spec.UpdateConfig,
 | 
			
		||||
        Networks: service.Spec.Networks,
 | 
			
		||||
        EndpointSpec: service.Spec.EndpointSpec
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
angular.module('portainer.helpers')
 | 
			
		||||
.factory('TemplateHelper', [function TemplateHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    getPortBindings: function(ports) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      ports.forEach(function (port) {
 | 
			
		||||
        var portAndProtocol = _.split(port, '/');
 | 
			
		||||
        var binding = {
 | 
			
		||||
          containerPort: portAndProtocol[0],
 | 
			
		||||
          protocol: portAndProtocol[1]
 | 
			
		||||
        };
 | 
			
		||||
        bindings.push(binding);
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    },
 | 
			
		||||
    //Not used atm, may prove useful later
 | 
			
		||||
    getVolumeBindings: function(volumes) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      volumes.forEach(function (volume) {
 | 
			
		||||
        bindings.push({ containerPath: volume });
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    },
 | 
			
		||||
    //Not used atm, may prove useful later
 | 
			
		||||
    getEnvBindings: function(env) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      env.forEach(function (envvar) {
 | 
			
		||||
        var binding = {
 | 
			
		||||
          name: envvar.name
 | 
			
		||||
        };
 | 
			
		||||
        if (envvar.set) {
 | 
			
		||||
          binding.value = envvar.set;
 | 
			
		||||
        }
 | 
			
		||||
        bindings.push(binding);
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
function ContainerViewModel(data) {
 | 
			
		||||
  this.Id = data.Id;
 | 
			
		||||
  this.Status = data.Status;
 | 
			
		||||
  this.State = data.State;
 | 
			
		||||
  this.Names = data.Names;
 | 
			
		||||
  // Unavailable in Docker < 1.10
 | 
			
		||||
  if (data.NetworkSettings && !_.isEmpty(data.NetworkSettings.Networks)) {
 | 
			
		||||
    this.IP = data.NetworkSettings.Networks[Object.keys(data.NetworkSettings.Networks)[0]].IPAddress;
 | 
			
		||||
  }
 | 
			
		||||
  this.Image = data.Image;
 | 
			
		||||
  this.Command = data.Command;
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.Ports = [];
 | 
			
		||||
  for (var i = 0; i < data.Ports.length; ++i) {
 | 
			
		||||
    var p = data.Ports[i];
 | 
			
		||||
    if (p.PublicPort) {
 | 
			
		||||
      this.Ports.push({ host: p.IP, private: p.PrivatePort, public: p.PublicPort });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,120 @@
 | 
			
		|||
function createEventDetails(event) {
 | 
			
		||||
  var eventAttr = event.Actor.Attributes;
 | 
			
		||||
  var details = '';
 | 
			
		||||
  switch (event.Type) {
 | 
			
		||||
    case 'container':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'stop':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' stopped';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'start':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' started';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'kill':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' killed';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'die':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' exited with status code ' + eventAttr.exitCode;
 | 
			
		||||
      break;
 | 
			
		||||
      case 'commit':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' committed';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'restart':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' restarted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'pause':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' paused';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'unpause':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' unpaused';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'attach':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' attached';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      if (event.Action.indexOf('exec_create') === 0) {
 | 
			
		||||
        details = 'Exec instance created';
 | 
			
		||||
      } else if (event.Action.indexOf('exec_start') === 0) {
 | 
			
		||||
        details = 'Exec instance started';
 | 
			
		||||
      } else {
 | 
			
		||||
        details = 'Unsupported event';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'image':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'delete':
 | 
			
		||||
      details = 'Image deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'tag':
 | 
			
		||||
      details = 'New tag created for ' + eventAttr.name;
 | 
			
		||||
      break;
 | 
			
		||||
      case 'untag':
 | 
			
		||||
      details = 'Image untagged';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'pull':
 | 
			
		||||
      details = 'Image ' + event.Actor.ID + ' pulled';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'network':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Network ' + eventAttr.name + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Network ' + eventAttr.name + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'connect':
 | 
			
		||||
      details = 'Container connected to ' + eventAttr.name + ' network';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'disconnect':
 | 
			
		||||
      details = 'Container disconnected from ' + eventAttr.name + ' network';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'volume':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'mount':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' mounted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'unmount':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' unmounted';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    default:
 | 
			
		||||
    details = 'Unsupported event';
 | 
			
		||||
  }
 | 
			
		||||
  return details;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function EventViewModel(data) {
 | 
			
		||||
  // Type, Action, Actor unavailable in Docker < 1.10
 | 
			
		||||
  this.Time = data.time;
 | 
			
		||||
  if (data.Type) {
 | 
			
		||||
    this.Type = data.Type;
 | 
			
		||||
    this.Details = createEventDetails(data);
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Type = data.status;
 | 
			
		||||
    this.Details = data.from;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
function ImageViewModel(data) {
 | 
			
		||||
  this.Id = data.Id;
 | 
			
		||||
  this.Tag = data.Tag;
 | 
			
		||||
  this.Repository = data.Repository;
 | 
			
		||||
  this.Created = data.Created;
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.RepoTags = data.RepoTags;
 | 
			
		||||
  this.VirtualSize = data.VirtualSize;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
function NodeViewModel(data) {
 | 
			
		||||
  this.Model = data;
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Version = data.Version.Index;
 | 
			
		||||
  this.Name = data.Spec.Name;
 | 
			
		||||
  this.Role = data.Spec.Role;
 | 
			
		||||
  this.CreatedAt = data.CreatedAt;
 | 
			
		||||
  this.UpdatedAt = data.UpdatedAt;
 | 
			
		||||
  this.Availability = data.Spec.Availability;
 | 
			
		||||
 | 
			
		||||
  var labels = data.Spec.Labels;
 | 
			
		||||
  if (labels) {
 | 
			
		||||
    this.Labels = Object.keys(labels).map(function(key) {
 | 
			
		||||
      return { key: key, value: labels[key], originalKey: key, originalValue: labels[key], added: true };
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Labels = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this.Hostname = data.Description.Hostname;
 | 
			
		||||
  this.PlatformArchitecture = data.Description.Platform.Architecture;
 | 
			
		||||
  this.PlatformOS = data.Description.Platform.OS;
 | 
			
		||||
  this.CPUs = data.Description.Resources.NanoCPUs;
 | 
			
		||||
  this.Memory = data.Description.Resources.MemoryBytes;
 | 
			
		||||
  this.EngineVersion = data.Description.Engine.EngineVersion;
 | 
			
		||||
  this.EngineLabels = data.Description.Engine.Labels;
 | 
			
		||||
  this.Plugins = data.Description.Engine.Plugins;
 | 
			
		||||
  this.Status = data.Status.State;
 | 
			
		||||
 | 
			
		||||
  if (data.ManagerStatus) {
 | 
			
		||||
    this.Leader = data.ManagerStatus.Leader;
 | 
			
		||||
    this.Reachability = data.ManagerStatus.Reachability;
 | 
			
		||||
    this.ManagerAddr = data.ManagerStatus.Addr;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
function ServiceViewModel(data) {
 | 
			
		||||
  this.Model = data;
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Name = data.Spec.Name;
 | 
			
		||||
  this.Image = data.Spec.TaskTemplate.ContainerSpec.Image;
 | 
			
		||||
  this.Version = data.Version.Index;
 | 
			
		||||
  if (data.Spec.Mode.Replicated) {
 | 
			
		||||
    this.Mode = 'replicated' ;
 | 
			
		||||
    this.Replicas = data.Spec.Mode.Replicated.Replicas;
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Mode = 'global';
 | 
			
		||||
  }
 | 
			
		||||
  this.Labels = data.Spec.Labels;
 | 
			
		||||
  if (data.Spec.TaskTemplate.ContainerSpec) {
 | 
			
		||||
    this.ContainerLabels = data.Spec.TaskTemplate.ContainerSpec.Labels;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Spec.TaskTemplate.ContainerSpec.Env) {
 | 
			
		||||
    this.Env = data.Spec.TaskTemplate.ContainerSpec.Env;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Endpoint.Ports) {
 | 
			
		||||
    this.Ports = data.Endpoint.Ports;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Spec.UpdateConfig) {
 | 
			
		||||
    this.UpdateParallelism = (typeof data.Spec.UpdateConfig.Parallelism !== undefined) ? data.Spec.UpdateConfig.Parallelism || 0 : 1;
 | 
			
		||||
    this.UpdateDelay = data.Spec.UpdateConfig.Delay || 0;
 | 
			
		||||
    this.UpdateFailureAction = data.Spec.UpdateConfig.FailureAction || 'pause';
 | 
			
		||||
  } else {
 | 
			
		||||
    this.UpdateParallelism = 1;
 | 
			
		||||
    this.UpdateDelay = 0;
 | 
			
		||||
    this.UpdateFailureAction = 'pause';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.Scale = false;
 | 
			
		||||
  this.EditName = false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
function TaskViewModel(data, node_data) {
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Created = data.CreatedAt;
 | 
			
		||||
  this.Updated = data.UpdatedAt;
 | 
			
		||||
  this.Slot = data.Slot;
 | 
			
		||||
  this.Status = data.Status.State;
 | 
			
		||||
  this.Image = data.Spec.ContainerSpec ? data.Spec.ContainerSpec.Image : '';
 | 
			
		||||
  if (node_data) {
 | 
			
		||||
    for (var i = 0; i < node_data.length; ++i) {
 | 
			
		||||
      if (data.NodeID === node_data[i].ID) {
 | 
			
		||||
        this.Node = node_data[i].Description.Hostname;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Auth', ['$resource', 'AUTH_ENDPOINT', function AuthFactory($resource, AUTH_ENDPOINT) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(AUTH_ENDPOINT, {}, {
 | 
			
		||||
    login: {
 | 
			
		||||
      method: 'POST'
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Config', ['$resource', 'CONFIG_ENDPOINT', function ConfigFactory($resource, CONFIG_ENDPOINT) {
 | 
			
		||||
  return $resource(CONFIG_ENDPOINT).get();
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Container', ['$resource', 'Settings', function ContainerFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/containers/:id/:action', {
 | 
			
		||||
    name: '@name'
 | 
			
		||||
  }, {
 | 
			
		||||
    query: {method: 'GET', params: {all: 0, action: 'json', filters: '@filters' }, isArray: true},
 | 
			
		||||
    get: {method: 'GET', params: {action: 'json'}},
 | 
			
		||||
    stop: {method: 'POST', params: {id: '@id', t: 5, action: 'stop'}},
 | 
			
		||||
    restart: {method: 'POST', params: {id: '@id', t: 5, action: 'restart'}},
 | 
			
		||||
    kill: {method: 'POST', params: {id: '@id', action: 'kill'}},
 | 
			
		||||
    pause: {method: 'POST', params: {id: '@id', action: 'pause'}},
 | 
			
		||||
    unpause: {method: 'POST', params: {id: '@id', action: 'unpause'}},
 | 
			
		||||
    changes: {method: 'GET', params: {action: 'changes'}, isArray: true},
 | 
			
		||||
    stats: {method: 'GET', params: {id: '@id', stream: false, action: 'stats'}, timeout: 5000},
 | 
			
		||||
    start: {
 | 
			
		||||
      method: 'POST', params: {id: '@id', action: 'start'},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    },
 | 
			
		||||
    create: {
 | 
			
		||||
      method: 'POST', params: {action: 'create'},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    },
 | 
			
		||||
    remove: {
 | 
			
		||||
      method: 'DELETE', params: {id: '@id', v: 0},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    },
 | 
			
		||||
    rename: {
 | 
			
		||||
      method: 'POST', params: {id: '@id', action: 'rename', name: '@name'},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    },
 | 
			
		||||
    exec: {
 | 
			
		||||
      method: 'POST', params: {id: '@id', action: 'exec'},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('ContainerCommit', ['$resource', 'Settings', function ContainerCommitFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/commit', {}, {
 | 
			
		||||
    commit: {method: 'POST', params: {container: '@id', repo: '@repo', tag: '@tag'}}
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('ContainerLogs', ['$http', 'Settings', function ContainerLogsFactory($http, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    get: function (id, params, callback) {
 | 
			
		||||
      $http({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: Settings.url + '/containers/' + id + '/logs',
 | 
			
		||||
        params: {
 | 
			
		||||
          'stdout': params.stdout || 0,
 | 
			
		||||
          'stderr': params.stderr || 0,
 | 
			
		||||
          'timestamps': params.timestamps || 0,
 | 
			
		||||
          'tail': params.tail || 'all'
 | 
			
		||||
        }
 | 
			
		||||
      }).success(callback).error(function (data, status, headers, config) {
 | 
			
		||||
        console.log(error, data);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('ContainerTop', ['$http', 'Settings', function ($http, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    get: function (id, params, callback, errorCallback) {
 | 
			
		||||
      $http({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: Settings.url + '/containers/' + id + '/top',
 | 
			
		||||
        params: {
 | 
			
		||||
          ps_args: params.ps_args
 | 
			
		||||
        }
 | 
			
		||||
      }).success(callback);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Endpoints', ['$resource', 'ENDPOINTS_ENDPOINT', function EndpointsFactory($resource, ENDPOINTS_ENDPOINT) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(ENDPOINTS_ENDPOINT + '/:id/:action', {}, {
 | 
			
		||||
    create: { method: 'POST' },
 | 
			
		||||
    query: { method: 'GET', isArray: true },
 | 
			
		||||
    get: { method: 'GET', params: { id: '@id' } },
 | 
			
		||||
    update: { method: 'PUT', params: { id: '@id' } },
 | 
			
		||||
    remove: { method: 'DELETE', params: { id: '@id'} },
 | 
			
		||||
    getActiveEndpoint: { method: 'GET', params: { id: '0' } },
 | 
			
		||||
    setActiveEndpoint: { method: 'POST', params: { id: '@id', action: 'active' } }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Events', ['$resource', 'Settings', function EventFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/events', {}, {
 | 
			
		||||
    query: {
 | 
			
		||||
      method: 'GET', params: {since: '@since', until: '@until'},
 | 
			
		||||
      isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Exec', ['$resource', 'Settings', function ExecFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/exec/:id/:action', {}, {
 | 
			
		||||
    resize: {
 | 
			
		||||
      method: 'POST', params: {id: '@id', action: 'resize', h: '@height', w: '@width'},
 | 
			
		||||
      transformResponse: genericHandler
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Image', ['$resource', 'Settings', function ImageFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/images/:id/:action', {}, {
 | 
			
		||||
    query: {method: 'GET', params: {all: 0, action: 'json'}, isArray: true},
 | 
			
		||||
    get: {method: 'GET', params: {action: 'json'}},
 | 
			
		||||
    search: {method: 'GET', params: {action: 'search'}},
 | 
			
		||||
    history: {method: 'GET', params: {action: 'history'}, isArray: true},
 | 
			
		||||
    insert: {method: 'POST', params: {id: '@id', action: 'insert'}},
 | 
			
		||||
    tag: {method: 'POST', params: {id: '@id', action: 'tag', force: 0, repo: '@repo', tag: '@tag'}},
 | 
			
		||||
    inspect: {method: 'GET', params: {id: '@id', action: 'json'}},
 | 
			
		||||
    push: {
 | 
			
		||||
      method: 'POST', params: {action: 'push', id: '@tag'},
 | 
			
		||||
      isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
    },
 | 
			
		||||
    create: {
 | 
			
		||||
      method: 'POST', params: {action: 'create', fromImage: '@fromImage', tag: '@tag'},
 | 
			
		||||
      isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
    },
 | 
			
		||||
    remove: {
 | 
			
		||||
      method: 'DELETE', params: {id: '@id'},
 | 
			
		||||
      isArray: true, transformResponse: deleteImageHandler
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Info', ['$resource', 'Settings', function InfoFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/info', {});
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Network', ['$resource', 'Settings', function NetworkFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/networks/:id/:action', {id: '@id'}, {
 | 
			
		||||
    query: {method: 'GET', isArray: true},
 | 
			
		||||
    get: {method: 'GET'},
 | 
			
		||||
    create: {method: 'POST', params: {action: 'create'}, transformResponse: genericHandler},
 | 
			
		||||
    remove: { method: 'DELETE', transformResponse: genericHandler },
 | 
			
		||||
    connect: {method: 'POST', params: {action: 'connect'}},
 | 
			
		||||
    disconnect: {method: 'POST', params: {action: 'disconnect'}}
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Node', ['$resource', 'Settings', function NodeFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/nodes/:id/:action', {}, {
 | 
			
		||||
    query: {method: 'GET', isArray: true},
 | 
			
		||||
    get: {method: 'GET', params: {id: '@id'}},
 | 
			
		||||
    update: { method: 'POST', params: {id: '@id', action: 'update', version: '@version'} },
 | 
			
		||||
    remove: { method: 'DELETE', params: {id: '@id'} }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Service', ['$resource', 'Settings', function ServiceFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/services/:id/:action', {}, {
 | 
			
		||||
    get: { method: 'GET', params: {id: '@id'} },
 | 
			
		||||
    query: { method: 'GET', isArray: true },
 | 
			
		||||
    create: { method: 'POST', params: {action: 'create'} },
 | 
			
		||||
    update: { method: 'POST', params: {id: '@id', action: 'update', version: '@version'} },
 | 
			
		||||
    remove: { method: 'DELETE', params: {id: '@id'} }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Swarm', ['$resource', 'Settings', function SwarmFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/swarm', {}, {
 | 
			
		||||
    get: {method: 'GET'}
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Task', ['$resource', 'Settings', function TaskFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/tasks/:id', {}, {
 | 
			
		||||
    get: { method: 'GET', params: {id: '@id'} },
 | 
			
		||||
    query: { method: 'GET', isArray: true, params: {filters: '@filters'} }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Templates', ['$resource', 'TEMPLATES_ENDPOINT', function TemplatesFactory($resource, TEMPLATES_ENDPOINT) {
 | 
			
		||||
  return $resource(TEMPLATES_ENDPOINT, {}, {
 | 
			
		||||
    get: {method: 'GET', isArray: true}
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Users', ['$resource', 'USERS_ENDPOINT', function UsersFactory($resource, USERS_ENDPOINT) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(USERS_ENDPOINT + '/:username/:action', {}, {
 | 
			
		||||
    create: { method: 'POST' },
 | 
			
		||||
    get: { method: 'GET', params: { username: '@username' } },
 | 
			
		||||
    update: { method: 'PUT', params: { username: '@username' } },
 | 
			
		||||
    checkPassword: { method: 'POST', params: { username: '@username', action: 'passwd' } },
 | 
			
		||||
    checkAdminUser: { method: 'GET', params: { username: 'admin', action: 'check' } },
 | 
			
		||||
    initAdminUser: { method: 'POST', params: { username: 'admin', action: 'init' } }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Version', ['$resource', 'Settings', function VersionFactory($resource, Settings) {
 | 
			
		||||
    'use strict';
 | 
			
		||||
    return $resource(Settings.url + '/version', {});
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
angular.module('portainer.rest')
 | 
			
		||||
.factory('Volume', ['$resource', 'Settings', function VolumeFactory($resource, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return $resource(Settings.url + '/volumes/:name/:action', {name: '@name'}, {
 | 
			
		||||
    query: {method: 'GET'},
 | 
			
		||||
    get: {method: 'GET'},
 | 
			
		||||
    create: {method: 'POST', params: {action: 'create'}, transformResponse: genericHandler},
 | 
			
		||||
    remove: {
 | 
			
		||||
      method: 'DELETE', transformResponse: genericHandler
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('Authentication', ['$q', '$rootScope', 'Auth', 'jwtHelper', 'LocalStorage', 'StateManager', function AuthenticationFactory($q, $rootScope, Auth, jwtHelper, LocalStorage, StateManager) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    init: function() {
 | 
			
		||||
      var jwt = LocalStorage.getJWT();
 | 
			
		||||
      if (jwt) {
 | 
			
		||||
        var tokenPayload = jwtHelper.decodeToken(jwt);
 | 
			
		||||
        $rootScope.username = tokenPayload.username;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    login: function(username, password) {
 | 
			
		||||
      return $q(function (resolve, reject) {
 | 
			
		||||
        Auth.login({username: username, password: password}).$promise
 | 
			
		||||
        .then(function(data) {
 | 
			
		||||
          LocalStorage.storeJWT(data.jwt);
 | 
			
		||||
          $rootScope.username = username;
 | 
			
		||||
          resolve();
 | 
			
		||||
        }, function() {
 | 
			
		||||
          reject();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    logout: function() {
 | 
			
		||||
      StateManager.clean();
 | 
			
		||||
      LocalStorage.clean();
 | 
			
		||||
    },
 | 
			
		||||
    isAuthenticated: function() {
 | 
			
		||||
      var jwt = LocalStorage.getJWT();
 | 
			
		||||
      return jwt && !jwtHelper.isTokenExpired(jwt);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,84 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('EndpointService', ['$q', 'Endpoints', 'FileUploadService', function EndpointServiceFactory($q, Endpoints, FileUploadService) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    getActive: function() {
 | 
			
		||||
      return Endpoints.getActiveEndpoint().$promise;
 | 
			
		||||
    },
 | 
			
		||||
    setActive: function(endpointID) {
 | 
			
		||||
      return Endpoints.setActiveEndpoint({id: endpointID}).$promise;
 | 
			
		||||
    },
 | 
			
		||||
    endpoint: function(endpointID) {
 | 
			
		||||
      return Endpoints.get({id: endpointID}).$promise;
 | 
			
		||||
    },
 | 
			
		||||
    endpoints: function() {
 | 
			
		||||
      return Endpoints.query({}).$promise;
 | 
			
		||||
    },
 | 
			
		||||
    updateEndpoint: function(ID, name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, type) {
 | 
			
		||||
      var endpoint = {
 | 
			
		||||
        id: ID,
 | 
			
		||||
        Name: name,
 | 
			
		||||
        URL: type === 'local' ? ("unix://" + URL) : ("tcp://" + URL),
 | 
			
		||||
        TLS: TLS
 | 
			
		||||
      };
 | 
			
		||||
      var deferred = $q.defer();
 | 
			
		||||
      Endpoints.update({}, endpoint, function success(data) {
 | 
			
		||||
        FileUploadService.uploadTLSFilesForEndpoint(ID, TLSCAFile, TLSCertFile, TLSKeyFile).then(function success(data) {
 | 
			
		||||
          deferred.notify({upload: false});
 | 
			
		||||
          deferred.resolve(data);
 | 
			
		||||
        }, function error(err) {
 | 
			
		||||
          deferred.notify({upload: false});
 | 
			
		||||
          deferred.reject({msg: 'Unable to upload TLS certs', err: err});
 | 
			
		||||
        });
 | 
			
		||||
      }, function error(err) {
 | 
			
		||||
        deferred.reject({msg: 'Unable to update endpoint', err: err});
 | 
			
		||||
      });
 | 
			
		||||
      return deferred.promise;
 | 
			
		||||
    },
 | 
			
		||||
    deleteEndpoint: function(endpointID) {
 | 
			
		||||
      return Endpoints.remove({id: endpointID}).$promise;
 | 
			
		||||
    },
 | 
			
		||||
    createLocalEndpoint: function(name, URL, TLS, active) {
 | 
			
		||||
      var endpoint = {
 | 
			
		||||
        Name: "local",
 | 
			
		||||
        URL: "unix:///var/run/docker.sock",
 | 
			
		||||
        TLS: false
 | 
			
		||||
      };
 | 
			
		||||
      return Endpoints.create({active: active}, endpoint).$promise;
 | 
			
		||||
    },
 | 
			
		||||
    createRemoteEndpoint: function(name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, active) {
 | 
			
		||||
      var endpoint = {
 | 
			
		||||
        Name: name,
 | 
			
		||||
        URL: 'tcp://' + URL,
 | 
			
		||||
        TLS: TLS
 | 
			
		||||
      };
 | 
			
		||||
      var deferred = $q.defer();
 | 
			
		||||
      Endpoints.create({active: active}, endpoint, function success(data) {
 | 
			
		||||
        var endpointID = data.Id;
 | 
			
		||||
        if (TLS) {
 | 
			
		||||
          deferred.notify({upload: true});
 | 
			
		||||
          FileUploadService.uploadTLSFilesForEndpoint(endpointID, TLSCAFile, TLSCertFile, TLSKeyFile).then(function success(data) {
 | 
			
		||||
            deferred.notify({upload: false});
 | 
			
		||||
            if (active) {
 | 
			
		||||
              Endpoints.setActiveEndpoint({}, {id: endpointID}, function success(data) {
 | 
			
		||||
                deferred.resolve(data);
 | 
			
		||||
              }, function error(err) {
 | 
			
		||||
                deferred.reject({msg: 'Unable to create endpoint', err: err});
 | 
			
		||||
              });
 | 
			
		||||
            } else {
 | 
			
		||||
              deferred.resolve(data);
 | 
			
		||||
            }
 | 
			
		||||
          }, function error(err) {
 | 
			
		||||
            deferred.notify({upload: false});
 | 
			
		||||
            deferred.reject({msg: 'Unable to upload TLS certs', err: err});
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          deferred.resolve(data);
 | 
			
		||||
        }
 | 
			
		||||
      }, function error(err) {
 | 
			
		||||
        deferred.reject({msg: 'Unable to create endpoint', err: err});
 | 
			
		||||
      });
 | 
			
		||||
      return deferred.promise;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('FileUploadService', ['$q', 'Upload', function FileUploadFactory($q, Upload) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  function uploadFile(url, file) {
 | 
			
		||||
    var deferred = $q.defer();
 | 
			
		||||
    Upload.upload({
 | 
			
		||||
      url: url,
 | 
			
		||||
      data: { file: file }
 | 
			
		||||
    }).then(function success(data) {
 | 
			
		||||
      deferred.resolve(data);
 | 
			
		||||
    }, function error(e) {
 | 
			
		||||
      deferred.reject(e);
 | 
			
		||||
    }, function progress(evt) {
 | 
			
		||||
    });
 | 
			
		||||
    return deferred.promise;
 | 
			
		||||
  }
 | 
			
		||||
  return {
 | 
			
		||||
    uploadTLSFilesForEndpoint: function(endpointID, TLSCAFile, TLSCertFile, TLSKeyFile) {
 | 
			
		||||
      var deferred = $q.defer();
 | 
			
		||||
      var queue = [];
 | 
			
		||||
 | 
			
		||||
      if (TLSCAFile !== null) {
 | 
			
		||||
        var uploadTLSCA = uploadFile('api/upload/tls/' + endpointID + '/ca', TLSCAFile);
 | 
			
		||||
        queue.push(uploadTLSCA);
 | 
			
		||||
      }
 | 
			
		||||
      if (TLSCertFile !== null) {
 | 
			
		||||
        var uploadTLSCert = uploadFile('api/upload/tls/' + endpointID + '/cert', TLSCertFile);
 | 
			
		||||
        queue.push(uploadTLSCert);
 | 
			
		||||
      }
 | 
			
		||||
      if (TLSKeyFile !== null) {
 | 
			
		||||
        var uploadTLSKey = uploadFile('api/upload/tls/' + endpointID + '/key', TLSKeyFile);
 | 
			
		||||
        queue.push(uploadTLSKey);
 | 
			
		||||
      }
 | 
			
		||||
      $q.all(queue).then(function (data) {
 | 
			
		||||
        deferred.resolve(data);
 | 
			
		||||
      }, function (err) {
 | 
			
		||||
        deferred.reject(err);
 | 
			
		||||
      }, function update(evt) {
 | 
			
		||||
        deferred.notify(evt);
 | 
			
		||||
      });
 | 
			
		||||
      return deferred.promise;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('LineChart', ['Settings', function LineChartFactory(Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    build: function (id, data, getkey) {
 | 
			
		||||
      var chart = new Chart($(id).get(0).getContext("2d"));
 | 
			
		||||
      var map = {};
 | 
			
		||||
 | 
			
		||||
      for (var i = 0; i < data.length; i++) {
 | 
			
		||||
        var c = data[i];
 | 
			
		||||
        var key = getkey(c);
 | 
			
		||||
 | 
			
		||||
        var count = map[key];
 | 
			
		||||
        if (count === undefined) {
 | 
			
		||||
          count = 0;
 | 
			
		||||
        }
 | 
			
		||||
        count += 1;
 | 
			
		||||
        map[key] = count;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var labels = [];
 | 
			
		||||
      data = [];
 | 
			
		||||
      var keys = Object.keys(map);
 | 
			
		||||
      var max = 1;
 | 
			
		||||
 | 
			
		||||
      for (i = keys.length - 1; i > -1; i--) {
 | 
			
		||||
        var k = keys[i];
 | 
			
		||||
        labels.push(k);
 | 
			
		||||
        data.push(map[k]);
 | 
			
		||||
        if (map[k] > max) {
 | 
			
		||||
          max = map[k];
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      var steps = Math.min(max, 10);
 | 
			
		||||
      var dataset = {
 | 
			
		||||
        fillColor: "rgba(151,187,205,0.5)",
 | 
			
		||||
        strokeColor: "rgba(151,187,205,1)",
 | 
			
		||||
        pointColor: "rgba(151,187,205,1)",
 | 
			
		||||
        pointStrokeColor: "#fff",
 | 
			
		||||
        data: data
 | 
			
		||||
      };
 | 
			
		||||
      chart.Line({
 | 
			
		||||
        labels: labels,
 | 
			
		||||
        datasets: [dataset]
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        scaleStepWidth: Math.ceil(max / steps),
 | 
			
		||||
        pointDotRadius: 1,
 | 
			
		||||
        scaleIntegersOnly: true,
 | 
			
		||||
        scaleOverride: true,
 | 
			
		||||
        scaleSteps: steps
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('LocalStorage', ['localStorageService', function LocalStorageFactory(localStorageService) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    storeEndpointState: function(state) {
 | 
			
		||||
      localStorageService.set('ENDPOINT_STATE', state);
 | 
			
		||||
    },
 | 
			
		||||
    getEndpointState: function() {
 | 
			
		||||
      return localStorageService.get('ENDPOINT_STATE');
 | 
			
		||||
    },
 | 
			
		||||
    storeJWT: function(jwt) {
 | 
			
		||||
      localStorageService.set('JWT', jwt);
 | 
			
		||||
    },
 | 
			
		||||
    getJWT: function() {
 | 
			
		||||
      return localStorageService.get('JWT');
 | 
			
		||||
    },
 | 
			
		||||
    deleteJWT: function() {
 | 
			
		||||
      localStorageService.remove('JWT');
 | 
			
		||||
    },
 | 
			
		||||
    storePaginationCount: function(key, count) {
 | 
			
		||||
      localStorageService.cookie.set('pagination_' + key, count);
 | 
			
		||||
    },
 | 
			
		||||
    getPaginationCount: function(key) {
 | 
			
		||||
      return localStorageService.cookie.get('pagination_' + key);
 | 
			
		||||
    },
 | 
			
		||||
    clean: function() {
 | 
			
		||||
      localStorageService.clearAll();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('Messages', ['$sanitize', function MessagesFactory($sanitize) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    send: function (title, text) {
 | 
			
		||||
      $.gritter.add({
 | 
			
		||||
        title: $sanitize(title),
 | 
			
		||||
        text: $sanitize(text),
 | 
			
		||||
        time: 2000,
 | 
			
		||||
        before_open: function () {
 | 
			
		||||
          if ($('.gritter-item-wrapper').length === 3) {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    error: function (title, e, fallbackText) {
 | 
			
		||||
      var msg = fallbackText;
 | 
			
		||||
      if (e.data && e.data.message) {
 | 
			
		||||
        msg = e.data.message;
 | 
			
		||||
      } else if (e.message) {
 | 
			
		||||
        msg = e.message;
 | 
			
		||||
      } else if (e.data && e.data.length > 0 && e.data[0].message) {
 | 
			
		||||
        msg = e.data[0].message;
 | 
			
		||||
      }
 | 
			
		||||
      $.gritter.add({
 | 
			
		||||
        title: $sanitize(title),
 | 
			
		||||
        text: $sanitize(msg),
 | 
			
		||||
        time: 10000,
 | 
			
		||||
        before_open: function () {
 | 
			
		||||
          if ($('.gritter-item-wrapper').length === 4) {
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('Pagination', ['LocalStorage', 'Settings', function PaginationFactory(LocalStorage, Settings) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    getPaginationCount: function(key) {
 | 
			
		||||
      var storedCount = LocalStorage.getPaginationCount(key);
 | 
			
		||||
      var paginationCount = Settings.pagination_count;
 | 
			
		||||
      if (storedCount !== null) {
 | 
			
		||||
        paginationCount = storedCount;
 | 
			
		||||
      }
 | 
			
		||||
      return '' + paginationCount;
 | 
			
		||||
    },
 | 
			
		||||
    setPaginationCount: function(key, count) {
 | 
			
		||||
      LocalStorage.storePaginationCount(key, count);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', 'PAGINATION_MAX_ITEMS', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION, PAGINATION_MAX_ITEMS) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  var url = DOCKER_ENDPOINT;
 | 
			
		||||
  if (DOCKER_PORT) {
 | 
			
		||||
    url = url + DOCKER_PORT + '\\' + DOCKER_PORT;
 | 
			
		||||
  }
 | 
			
		||||
  var firstLoad = (localStorage.getItem('firstLoad') || 'true') === 'true';
 | 
			
		||||
  return {
 | 
			
		||||
    displayAll: true,
 | 
			
		||||
    endpoint: DOCKER_ENDPOINT,
 | 
			
		||||
    uiVersion: UI_VERSION,
 | 
			
		||||
    url: url,
 | 
			
		||||
    firstLoad: firstLoad,
 | 
			
		||||
    pagination_count: PAGINATION_MAX_ITEMS
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
angular.module('portainer.services')
 | 
			
		||||
.factory('StateManager', ['$q', 'Info', 'InfoHelper', 'Version', 'LocalStorage', function StateManagerFactory($q, Info, InfoHelper, Version, LocalStorage) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
 | 
			
		||||
  var state = {
 | 
			
		||||
    loading: true,
 | 
			
		||||
    application: {},
 | 
			
		||||
    endpoint: {}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    init: function() {
 | 
			
		||||
      var endpointState = LocalStorage.getEndpointState();
 | 
			
		||||
      if (endpointState) {
 | 
			
		||||
        state.endpoint = endpointState;
 | 
			
		||||
      }
 | 
			
		||||
      state.loading = false;
 | 
			
		||||
    },
 | 
			
		||||
    clean: function() {
 | 
			
		||||
      state.endpoint = {};
 | 
			
		||||
    },
 | 
			
		||||
    updateEndpointState: function(loading) {
 | 
			
		||||
      var deferred = $q.defer();
 | 
			
		||||
      if (loading) {
 | 
			
		||||
        state.loading = true;
 | 
			
		||||
      }
 | 
			
		||||
      $q.all([Info.get({}).$promise, Version.get({}).$promise])
 | 
			
		||||
      .then(function success(data) {
 | 
			
		||||
        var endpointMode = InfoHelper.determineEndpointMode(data[0]);
 | 
			
		||||
        var endpointAPIVersion = parseFloat(data[1].ApiVersion);
 | 
			
		||||
        state.endpoint.mode = endpointMode;
 | 
			
		||||
        state.endpoint.apiVersion = endpointAPIVersion;
 | 
			
		||||
        LocalStorage.storeEndpointState(state.endpoint);
 | 
			
		||||
        state.loading = false;
 | 
			
		||||
        deferred.resolve();
 | 
			
		||||
      }, function error(err) {
 | 
			
		||||
        state.loading = false;
 | 
			
		||||
        deferred.reject({msg: 'Unable to connect to the Docker endpoint', err: err});
 | 
			
		||||
      });
 | 
			
		||||
      return deferred.promise;
 | 
			
		||||
    },
 | 
			
		||||
    getState: function() {
 | 
			
		||||
      return state;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,170 +0,0 @@
 | 
			
		|||
angular.module('portainer.helpers', [])
 | 
			
		||||
.factory('InfoHelper', [function InfoHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    determineEndpointMode: function(info) {
 | 
			
		||||
      var mode = {
 | 
			
		||||
        provider: '',
 | 
			
		||||
        role: ''
 | 
			
		||||
      };
 | 
			
		||||
      if (_.startsWith(info.ServerVersion, 'swarm')) {
 | 
			
		||||
        mode.provider = "DOCKER_SWARM";
 | 
			
		||||
        if (info.SystemStatus[0][1] === 'primary') {
 | 
			
		||||
          mode.role = "PRIMARY";
 | 
			
		||||
        } else {
 | 
			
		||||
          mode.role = "REPLICA";
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        if (!info.Swarm || _.isEmpty(info.Swarm.NodeID)) {
 | 
			
		||||
          mode.provider = "DOCKER_STANDALONE";
 | 
			
		||||
        } else {
 | 
			
		||||
          mode.provider = "DOCKER_SWARM_MODE";
 | 
			
		||||
          if (info.Swarm.ControlAvailable) {
 | 
			
		||||
            mode.role = "MANAGER";
 | 
			
		||||
          } else {
 | 
			
		||||
            mode.role = "WORKER";
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return mode;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])      
 | 
			
		||||
.factory('LabelHelper', [function LabelHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    fromLabelHashToKeyValue: function(labels) {
 | 
			
		||||
      if (labels) {
 | 
			
		||||
        return Object.keys(labels).map(function(key) {
 | 
			
		||||
          return {key: key, value: labels[key], originalKey: key, originalValue: labels[key], added: true};
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return [];
 | 
			
		||||
    },
 | 
			
		||||
    fromKeyValueToLabelHash: function(labelKV) {
 | 
			
		||||
      var labels = {};
 | 
			
		||||
      if (labelKV) {
 | 
			
		||||
        labelKV.forEach(function(label) {
 | 
			
		||||
          labels[label.key] = label.value;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return labels;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])
 | 
			
		||||
.factory('ImageHelper', [function ImageHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    createImageConfigForCommit: function(imageName, registry) {
 | 
			
		||||
      var imageNameAndTag = imageName.split(':');
 | 
			
		||||
      var image = imageNameAndTag[0];
 | 
			
		||||
      if (registry) {
 | 
			
		||||
        image = registry + '/' + imageNameAndTag[0];
 | 
			
		||||
      }
 | 
			
		||||
      var imageConfig = {
 | 
			
		||||
        repo: image,
 | 
			
		||||
        tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest'
 | 
			
		||||
      };
 | 
			
		||||
      return imageConfig;
 | 
			
		||||
    },
 | 
			
		||||
    createImageConfigForContainer: function (imageName, registry) {
 | 
			
		||||
      var imageNameAndTag = imageName.split(':');
 | 
			
		||||
      var image = imageNameAndTag[0];
 | 
			
		||||
      if (registry) {
 | 
			
		||||
        image = registry + '/' + imageNameAndTag[0];
 | 
			
		||||
      }
 | 
			
		||||
      var imageConfig = {
 | 
			
		||||
        fromImage: image,
 | 
			
		||||
        tag: imageNameAndTag[1] ? imageNameAndTag[1] : 'latest'
 | 
			
		||||
      };
 | 
			
		||||
      return imageConfig;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])
 | 
			
		||||
.factory('ContainerHelper', [function ContainerHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    hideContainers: function(containers, containersToHideLabels) {
 | 
			
		||||
      return containers.filter(function (container) {
 | 
			
		||||
        var filterContainer = false;
 | 
			
		||||
        containersToHideLabels.forEach(function(label, index) {
 | 
			
		||||
          if (_.has(container.Labels, label.name) &&
 | 
			
		||||
          container.Labels[label.name] === label.value) {
 | 
			
		||||
            filterContainer = true;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        if (!filterContainer) {
 | 
			
		||||
          return container;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])
 | 
			
		||||
.factory('ServiceHelper', [function ServiceHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    serviceToConfig: function(service) {
 | 
			
		||||
      return {
 | 
			
		||||
        Name: service.Spec.Name,
 | 
			
		||||
        Labels: service.Spec.Labels,
 | 
			
		||||
        TaskTemplate: service.Spec.TaskTemplate,
 | 
			
		||||
        Mode: service.Spec.Mode,
 | 
			
		||||
        UpdateConfig: service.Spec.UpdateConfig,
 | 
			
		||||
        Networks: service.Spec.Networks,
 | 
			
		||||
        EndpointSpec: service.Spec.EndpointSpec
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])
 | 
			
		||||
.factory('NodeHelper', [function NodeHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    nodeToConfig: function(node) {
 | 
			
		||||
      return {
 | 
			
		||||
        Name: node.Spec.Name,
 | 
			
		||||
        Role: node.Spec.Role,
 | 
			
		||||
        Labels: node.Spec.Labels,
 | 
			
		||||
        Availability: node.Spec.Availability
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}])
 | 
			
		||||
.factory('TemplateHelper', [function TemplateHelperFactory() {
 | 
			
		||||
  'use strict';
 | 
			
		||||
  return {
 | 
			
		||||
    getPortBindings: function(ports) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      ports.forEach(function (port) {
 | 
			
		||||
        var portAndProtocol = _.split(port, '/');
 | 
			
		||||
        var binding = {
 | 
			
		||||
          containerPort: portAndProtocol[0],
 | 
			
		||||
          protocol: portAndProtocol[1]
 | 
			
		||||
        };
 | 
			
		||||
        bindings.push(binding);
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    },
 | 
			
		||||
    //Not used atm, may prove useful later
 | 
			
		||||
    getVolumeBindings: function(volumes) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      volumes.forEach(function (volume) {
 | 
			
		||||
        bindings.push({ containerPath: volume });
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    },
 | 
			
		||||
    //Not used atm, may prove useful later
 | 
			
		||||
    getEnvBindings: function(env) {
 | 
			
		||||
      var bindings = [];
 | 
			
		||||
      env.forEach(function (envvar) {
 | 
			
		||||
        var binding = {
 | 
			
		||||
          name: envvar.name
 | 
			
		||||
        };
 | 
			
		||||
        if (envvar.set) {
 | 
			
		||||
          binding.value = envvar.set;
 | 
			
		||||
        }
 | 
			
		||||
        bindings.push(binding);
 | 
			
		||||
      });
 | 
			
		||||
      return bindings;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}]);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,594 +0,0 @@
 | 
			
		|||
angular.module('portainer.services', ['ngResource', 'ngSanitize'])
 | 
			
		||||
    .factory('Container', ['$resource', 'Settings', function ContainerFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // Resource for interacting with the docker containers
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-1-containers
 | 
			
		||||
        return $resource(Settings.url + '/containers/:id/:action', {
 | 
			
		||||
            name: '@name'
 | 
			
		||||
        }, {
 | 
			
		||||
            query: {method: 'GET', params: {all: 0, action: 'json', filters: '@filters' }, isArray: true},
 | 
			
		||||
            get: {method: 'GET', params: {action: 'json'}},
 | 
			
		||||
            stop: {method: 'POST', params: {id: '@id', t: 5, action: 'stop'}},
 | 
			
		||||
            restart: {method: 'POST', params: {id: '@id', t: 5, action: 'restart'}},
 | 
			
		||||
            kill: {method: 'POST', params: {id: '@id', action: 'kill'}},
 | 
			
		||||
            pause: {method: 'POST', params: {id: '@id', action: 'pause'}},
 | 
			
		||||
            unpause: {method: 'POST', params: {id: '@id', action: 'unpause'}},
 | 
			
		||||
            changes: {method: 'GET', params: {action: 'changes'}, isArray: true},
 | 
			
		||||
            stats: {method: 'GET', params: {id: '@id', stream: false, action: 'stats'}, timeout: 5000},
 | 
			
		||||
            start: {
 | 
			
		||||
              method: 'POST', params: {id: '@id', action: 'start'},
 | 
			
		||||
              transformResponse: genericHandler
 | 
			
		||||
            },
 | 
			
		||||
            create: {
 | 
			
		||||
              method: 'POST', params: {action: 'create'},
 | 
			
		||||
              transformResponse: genericHandler
 | 
			
		||||
            },
 | 
			
		||||
            remove: {
 | 
			
		||||
              method: 'DELETE', params: {id: '@id', v: 0},
 | 
			
		||||
              transformResponse: genericHandler
 | 
			
		||||
            },
 | 
			
		||||
            rename: {
 | 
			
		||||
              method: 'POST', params: {id: '@id', action: 'rename', name: '@name'},
 | 
			
		||||
              transformResponse: genericHandler
 | 
			
		||||
            },
 | 
			
		||||
            exec: {
 | 
			
		||||
              method: 'POST', params: {id: '@id', action: 'exec'},
 | 
			
		||||
              transformResponse: genericHandler
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Service', ['$resource', 'Settings', function ServiceFactory($resource, Settings) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      // https://docs.docker.com/engine/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/3-9-services
 | 
			
		||||
      return $resource(Settings.url + '/services/:id/:action', {}, {
 | 
			
		||||
        get: { method: 'GET', params: {id: '@id'} },
 | 
			
		||||
        query: { method: 'GET', isArray: true },
 | 
			
		||||
        create: { method: 'POST', params: {action: 'create'} },
 | 
			
		||||
        update: { method: 'POST', params: {id: '@id', action: 'update', version: '@version'} },
 | 
			
		||||
        remove: { method: 'DELETE', params: {id: '@id'} }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Task', ['$resource', 'Settings', function TaskFactory($resource, Settings) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      // https://docs.docker.com/engine/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/3-9-services
 | 
			
		||||
      return $resource(Settings.url + '/tasks/:id', {}, {
 | 
			
		||||
        get: { method: 'GET', params: {id: '@id'} },
 | 
			
		||||
        query: { method: 'GET', isArray: true, params: {filters: '@filters'} }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Exec', ['$resource', 'Settings', function ExecFactory($resource, Settings) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      // https://docs.docker.com/engine/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/exec-resize
 | 
			
		||||
      return $resource(Settings.url + '/exec/:id/:action', {}, {
 | 
			
		||||
        resize: {
 | 
			
		||||
          method: 'POST', params: {id: '@id', action: 'resize', h: '@height', w: '@width'},
 | 
			
		||||
          transformResponse: genericHandler
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('ContainerCommit', ['$resource', '$http', 'Settings', function ContainerCommitFactory($resource, $http, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#create-a-new-image-from-a-container-s-changes
 | 
			
		||||
        return $resource(Settings.url + '/commit', {}, {
 | 
			
		||||
          commit: {method: 'POST', params: {container: '@id', repo: '@repo', tag: '@tag'}}
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('ContainerLogs', ['$resource', '$http', 'Settings', function ContainerLogsFactory($resource, $http, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#get-container-logs
 | 
			
		||||
        return {
 | 
			
		||||
            get: function (id, params, callback) {
 | 
			
		||||
                $http({
 | 
			
		||||
                    method: 'GET',
 | 
			
		||||
                    url: Settings.url + '/containers/' + id + '/logs',
 | 
			
		||||
                    params: {
 | 
			
		||||
                        'stdout': params.stdout || 0,
 | 
			
		||||
                        'stderr': params.stderr || 0,
 | 
			
		||||
                        'timestamps': params.timestamps || 0,
 | 
			
		||||
                        'tail': params.tail || 'all'
 | 
			
		||||
                    }
 | 
			
		||||
                }).success(callback).error(function (data, status, headers, config) {
 | 
			
		||||
                    console.log(error, data);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('ContainerTop', ['$http', 'Settings', function ($http, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#list-processes-running-inside-a-container
 | 
			
		||||
        return {
 | 
			
		||||
            get: function (id, params, callback, errorCallback) {
 | 
			
		||||
                $http({
 | 
			
		||||
                    method: 'GET',
 | 
			
		||||
                    url: Settings.url + '/containers/' + id + '/top',
 | 
			
		||||
                    params: {
 | 
			
		||||
                        ps_args: params.ps_args
 | 
			
		||||
                    }
 | 
			
		||||
                }).success(callback);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Image', ['$resource', 'Settings', function ImageFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-2-images
 | 
			
		||||
        return $resource(Settings.url + '/images/:id/:action', {}, {
 | 
			
		||||
            query: {method: 'GET', params: {all: 0, action: 'json'}, isArray: true},
 | 
			
		||||
            get: {method: 'GET', params: {action: 'json'}},
 | 
			
		||||
            search: {method: 'GET', params: {action: 'search'}},
 | 
			
		||||
            history: {method: 'GET', params: {action: 'history'}, isArray: true},
 | 
			
		||||
            insert: {method: 'POST', params: {id: '@id', action: 'insert'}},
 | 
			
		||||
            tag: {method: 'POST', params: {id: '@id', action: 'tag', force: 0, repo: '@repo', tag: '@tag'}},
 | 
			
		||||
            inspect: {method: 'GET', params: {id: '@id', action: 'json'}},
 | 
			
		||||
            push: {
 | 
			
		||||
                method: 'POST', params: {action: 'push', id: '@tag'},
 | 
			
		||||
                isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
            },
 | 
			
		||||
            create: {
 | 
			
		||||
                method: 'POST', params: {action: 'create', fromImage: '@fromImage', tag: '@tag'},
 | 
			
		||||
                isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
            },
 | 
			
		||||
            remove: {
 | 
			
		||||
              method: 'DELETE', params: {id: '@id'},
 | 
			
		||||
              isArray: true, transformResponse: deleteImageHandler
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Events', ['$resource', 'Settings', function EventFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/monitor-docker-s-events
 | 
			
		||||
        return $resource(Settings.url + '/events', {}, {
 | 
			
		||||
            query: {
 | 
			
		||||
              method: 'GET', params: {since: '@since', until: '@until'},
 | 
			
		||||
              isArray: true, transformResponse: jsonObjectsToArrayHandler
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Version', ['$resource', 'Settings', function VersionFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#show-the-docker-version-information
 | 
			
		||||
        return $resource(Settings.url + '/version', {}, {
 | 
			
		||||
            get: {method: 'GET'}
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Node', ['$resource', 'Settings', function NodeFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // https://docs.docker.com/engine/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/3-7-nodes
 | 
			
		||||
        return $resource(Settings.url + '/nodes/:id/:action', {}, {
 | 
			
		||||
          query: {method: 'GET', isArray: true},
 | 
			
		||||
          get: {method: 'GET', params: {id: '@id'}},
 | 
			
		||||
          update: { method: 'POST', params: {id: '@id', action: 'update', version: '@version'} },
 | 
			
		||||
          remove: { method: 'DELETE', params: {id: '@id'} }
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Swarm', ['$resource', 'Settings', function SwarmFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // https://docs.docker.com/engine/reference/api/docker_remote_api_<%= remoteApiVersion %>/#/3-8-swarm
 | 
			
		||||
        return $resource(Settings.url + '/swarm', {}, {
 | 
			
		||||
            get: {method: 'GET'}
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Info', ['$resource', 'Settings', function InfoFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#display-system-wide-information
 | 
			
		||||
        return $resource(Settings.url + '/info', {}, {
 | 
			
		||||
            get: {method: 'GET'}
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Network', ['$resource', 'Settings', function NetworkFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-5-networks
 | 
			
		||||
        return $resource(Settings.url + '/networks/:id/:action', {id: '@id'}, {
 | 
			
		||||
            query: {method: 'GET', isArray: true},
 | 
			
		||||
            get: {method: 'GET'},
 | 
			
		||||
            create: {method: 'POST', params: {action: 'create'}, transformResponse: genericHandler},
 | 
			
		||||
            remove: { method: 'DELETE', transformResponse: genericHandler },
 | 
			
		||||
            connect: {method: 'POST', params: {action: 'connect'}},
 | 
			
		||||
            disconnect: {method: 'POST', params: {action: 'disconnect'}}
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Volume', ['$resource', 'Settings', function VolumeFactory($resource, Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        // http://docs.docker.com/reference/api/docker_remote_api_<%= remoteApiVersion %>/#2-5-networks
 | 
			
		||||
        return $resource(Settings.url + '/volumes/:name/:action', {name: '@name'}, {
 | 
			
		||||
          query: {method: 'GET'},
 | 
			
		||||
          get: {method: 'GET'},
 | 
			
		||||
          create: {method: 'POST', params: {action: 'create'}, transformResponse: genericHandler},
 | 
			
		||||
          remove: {
 | 
			
		||||
            method: 'DELETE', transformResponse: genericHandler
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Config', ['$resource', 'CONFIG_ENDPOINT', function ConfigFactory($resource, CONFIG_ENDPOINT) {
 | 
			
		||||
      return $resource(CONFIG_ENDPOINT).get();
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Templates', ['$resource', 'TEMPLATES_ENDPOINT', function TemplatesFactory($resource, TEMPLATES_ENDPOINT) {
 | 
			
		||||
      return $resource(TEMPLATES_ENDPOINT, {}, {
 | 
			
		||||
        get: {method: 'GET', isArray: true}
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Settings', ['DOCKER_ENDPOINT', 'DOCKER_PORT', 'UI_VERSION', 'PAGINATION_MAX_ITEMS', function SettingsFactory(DOCKER_ENDPOINT, DOCKER_PORT, UI_VERSION, PAGINATION_MAX_ITEMS) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        var url = DOCKER_ENDPOINT;
 | 
			
		||||
        if (DOCKER_PORT) {
 | 
			
		||||
            url = url + DOCKER_PORT + '\\' + DOCKER_PORT;
 | 
			
		||||
        }
 | 
			
		||||
        var firstLoad = (localStorage.getItem('firstLoad') || 'true') === 'true';
 | 
			
		||||
        return {
 | 
			
		||||
          displayAll: true,
 | 
			
		||||
          endpoint: DOCKER_ENDPOINT,
 | 
			
		||||
          uiVersion: UI_VERSION,
 | 
			
		||||
          url: url,
 | 
			
		||||
          firstLoad: firstLoad,
 | 
			
		||||
          pagination_count: PAGINATION_MAX_ITEMS
 | 
			
		||||
        };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Auth', ['$resource', 'AUTH_ENDPOINT', function AuthFactory($resource, AUTH_ENDPOINT) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return $resource(AUTH_ENDPOINT, {}, {
 | 
			
		||||
        login: {
 | 
			
		||||
          method: 'POST'
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Users', ['$resource', 'USERS_ENDPOINT', function UsersFactory($resource, USERS_ENDPOINT) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return $resource(USERS_ENDPOINT + '/:username/:action', {}, {
 | 
			
		||||
        create: { method: 'POST' },
 | 
			
		||||
        get: { method: 'GET', params: { username: '@username' } },
 | 
			
		||||
        update: { method: 'PUT', params: { username: '@username' } },
 | 
			
		||||
        checkPassword: { method: 'POST', params: { username: '@username', action: 'passwd' } },
 | 
			
		||||
        checkAdminUser: { method: 'GET', params: { username: 'admin', action: 'check' } },
 | 
			
		||||
        initAdminUser: { method: 'POST', params: { username: 'admin', action: 'init' } }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Authentication', ['$q', '$rootScope', 'Auth', 'jwtHelper', 'LocalStorage', 'StateManager', function AuthenticationFactory($q, $rootScope, Auth, jwtHelper, LocalStorage, StateManager) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return {
 | 
			
		||||
        init: function() {
 | 
			
		||||
          var jwt = LocalStorage.getJWT();
 | 
			
		||||
          if (jwt) {
 | 
			
		||||
            var tokenPayload = jwtHelper.decodeToken(jwt);
 | 
			
		||||
            $rootScope.username = tokenPayload.username;
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        login: function(username, password) {
 | 
			
		||||
          return $q(function (resolve, reject) {
 | 
			
		||||
            Auth.login({username: username, password: password}).$promise
 | 
			
		||||
            .then(function(data) {
 | 
			
		||||
              LocalStorage.storeJWT(data.jwt);
 | 
			
		||||
              $rootScope.username = username;
 | 
			
		||||
              resolve();
 | 
			
		||||
            }, function() {
 | 
			
		||||
              reject();
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        },
 | 
			
		||||
        logout: function() {
 | 
			
		||||
          StateManager.clean();
 | 
			
		||||
          LocalStorage.clean();
 | 
			
		||||
        },
 | 
			
		||||
        isAuthenticated: function() {
 | 
			
		||||
          var jwt = LocalStorage.getJWT();
 | 
			
		||||
          return jwt && !jwtHelper.isTokenExpired(jwt);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('FileUploadService', ['$q', 'Upload', function FileUploadFactory($q, Upload) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      function uploadFile(url, file) {
 | 
			
		||||
        var deferred = $q.defer();
 | 
			
		||||
        Upload.upload({
 | 
			
		||||
          url: url,
 | 
			
		||||
          data: { file: file }
 | 
			
		||||
        }).then(function success(data) {
 | 
			
		||||
          deferred.resolve(data);
 | 
			
		||||
        }, function error(e) {
 | 
			
		||||
          deferred.reject(e);
 | 
			
		||||
        }, function progress(evt) {
 | 
			
		||||
        });
 | 
			
		||||
        return deferred.promise;
 | 
			
		||||
      }
 | 
			
		||||
      return {
 | 
			
		||||
        uploadTLSFilesForEndpoint: function(endpointID, TLSCAFile, TLSCertFile, TLSKeyFile) {
 | 
			
		||||
          var deferred = $q.defer();
 | 
			
		||||
          var queue = [];
 | 
			
		||||
 | 
			
		||||
          if (TLSCAFile !== null) {
 | 
			
		||||
            var uploadTLSCA = uploadFile('api/upload/tls/' + endpointID + '/ca', TLSCAFile);
 | 
			
		||||
            queue.push(uploadTLSCA);
 | 
			
		||||
          }
 | 
			
		||||
          if (TLSCertFile !== null) {
 | 
			
		||||
            var uploadTLSCert = uploadFile('api/upload/tls/' + endpointID + '/cert', TLSCertFile);
 | 
			
		||||
            queue.push(uploadTLSCert);
 | 
			
		||||
          }
 | 
			
		||||
          if (TLSKeyFile !== null) {
 | 
			
		||||
            var uploadTLSKey = uploadFile('api/upload/tls/' + endpointID + '/key', TLSKeyFile);
 | 
			
		||||
            queue.push(uploadTLSKey);
 | 
			
		||||
          }
 | 
			
		||||
          $q.all(queue).then(function (data) {
 | 
			
		||||
            deferred.resolve(data);
 | 
			
		||||
          }, function (err) {
 | 
			
		||||
            deferred.reject(err);
 | 
			
		||||
          }, function update(evt) {
 | 
			
		||||
            deferred.notify(evt);
 | 
			
		||||
          });
 | 
			
		||||
          return deferred.promise;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Endpoints', ['$resource', 'ENDPOINTS_ENDPOINT', function EndpointsFactory($resource, ENDPOINTS_ENDPOINT) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return $resource(ENDPOINTS_ENDPOINT + '/:id/:action', {}, {
 | 
			
		||||
        create: { method: 'POST' },
 | 
			
		||||
        query: { method: 'GET', isArray: true },
 | 
			
		||||
        get: { method: 'GET', params: { id: '@id' } },
 | 
			
		||||
        update: { method: 'PUT', params: { id: '@id' } },
 | 
			
		||||
        remove: { method: 'DELETE', params: { id: '@id'} },
 | 
			
		||||
        getActiveEndpoint: { method: 'GET', params: { id: '0' } },
 | 
			
		||||
        setActiveEndpoint: { method: 'POST', params: { id: '@id', action: 'active' } }
 | 
			
		||||
      });
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Pagination', ['LocalStorage', 'Settings', function PaginationFactory(LocalStorage, Settings) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return {
 | 
			
		||||
        getPaginationCount: function(key) {
 | 
			
		||||
          var storedCount = LocalStorage.getPaginationCount(key);
 | 
			
		||||
          var paginationCount = Settings.pagination_count;
 | 
			
		||||
          if (storedCount !== null) {
 | 
			
		||||
            paginationCount = storedCount;
 | 
			
		||||
          }
 | 
			
		||||
          return '' + paginationCount;
 | 
			
		||||
        },
 | 
			
		||||
        setPaginationCount: function(key, count) {
 | 
			
		||||
          LocalStorage.storePaginationCount(key, count);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('LocalStorage', ['localStorageService', function LocalStorageFactory(localStorageService) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return {
 | 
			
		||||
        storeEndpointState: function(state) {
 | 
			
		||||
          localStorageService.set('ENDPOINT_STATE', state);
 | 
			
		||||
        },
 | 
			
		||||
        getEndpointState: function() {
 | 
			
		||||
          return localStorageService.get('ENDPOINT_STATE');
 | 
			
		||||
        },
 | 
			
		||||
        storeJWT: function(jwt) {
 | 
			
		||||
          localStorageService.set('JWT', jwt);
 | 
			
		||||
        },
 | 
			
		||||
        getJWT: function() {
 | 
			
		||||
          return localStorageService.get('JWT');
 | 
			
		||||
        },
 | 
			
		||||
        deleteJWT: function() {
 | 
			
		||||
          localStorageService.remove('JWT');
 | 
			
		||||
        },
 | 
			
		||||
        storePaginationCount: function(key, count) {
 | 
			
		||||
          localStorageService.cookie.set('pagination_' + key, count);
 | 
			
		||||
        },
 | 
			
		||||
        getPaginationCount: function(key) {
 | 
			
		||||
          return localStorageService.cookie.get('pagination_' + key);
 | 
			
		||||
        },
 | 
			
		||||
        clean: function() {
 | 
			
		||||
          localStorageService.clearAll();
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('StateManager', ['$q', 'Info', 'InfoHelper', 'Version', 'LocalStorage', function StateManagerFactory($q, Info, InfoHelper, Version, LocalStorage) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
 | 
			
		||||
      var state = {
 | 
			
		||||
        loading: true,
 | 
			
		||||
        application: {},
 | 
			
		||||
        endpoint: {}
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        init: function() {
 | 
			
		||||
          var endpointState = LocalStorage.getEndpointState();
 | 
			
		||||
          if (endpointState) {
 | 
			
		||||
            state.endpoint = endpointState;
 | 
			
		||||
          }
 | 
			
		||||
          state.loading = false;
 | 
			
		||||
        },
 | 
			
		||||
        clean: function() {
 | 
			
		||||
          state.endpoint = {};
 | 
			
		||||
        },
 | 
			
		||||
        updateEndpointState: function(loading) {
 | 
			
		||||
          var deferred = $q.defer();
 | 
			
		||||
          if (loading) {
 | 
			
		||||
            state.loading = true;
 | 
			
		||||
          }
 | 
			
		||||
          $q.all([Info.get({}).$promise, Version.get({}).$promise])
 | 
			
		||||
          .then(function success(data) {
 | 
			
		||||
            var endpointMode = InfoHelper.determineEndpointMode(data[0]);
 | 
			
		||||
            var endpointAPIVersion = parseFloat(data[1].ApiVersion);
 | 
			
		||||
            state.endpoint.mode = endpointMode;
 | 
			
		||||
            state.endpoint.apiVersion = endpointAPIVersion;
 | 
			
		||||
            LocalStorage.storeEndpointState(state.endpoint);
 | 
			
		||||
            state.loading = false;
 | 
			
		||||
            deferred.resolve();
 | 
			
		||||
          }, function error(err) {
 | 
			
		||||
            state.loading = false;
 | 
			
		||||
            deferred.reject({msg: 'Unable to connect to the Docker endpoint', err: err});
 | 
			
		||||
          });
 | 
			
		||||
          return deferred.promise;
 | 
			
		||||
        },
 | 
			
		||||
        getState: function() {
 | 
			
		||||
          return state;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('EndpointService', ['$q', 'Endpoints', 'FileUploadService', function EndpointServiceFactory($q, Endpoints, FileUploadService) {
 | 
			
		||||
      'use strict';
 | 
			
		||||
      return {
 | 
			
		||||
        getActive: function() {
 | 
			
		||||
          return Endpoints.getActiveEndpoint().$promise;
 | 
			
		||||
        },
 | 
			
		||||
        setActive: function(endpointID) {
 | 
			
		||||
          return Endpoints.setActiveEndpoint({id: endpointID}).$promise;
 | 
			
		||||
        },
 | 
			
		||||
        endpoint: function(endpointID) {
 | 
			
		||||
          return Endpoints.get({id: endpointID}).$promise;
 | 
			
		||||
        },
 | 
			
		||||
        endpoints: function() {
 | 
			
		||||
          return Endpoints.query({}).$promise;
 | 
			
		||||
        },
 | 
			
		||||
        updateEndpoint: function(ID, name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, type) {
 | 
			
		||||
          var endpoint = {
 | 
			
		||||
            id: ID,
 | 
			
		||||
            Name: name,
 | 
			
		||||
            URL: type === 'local' ? ("unix://" + URL) : ("tcp://" + URL),
 | 
			
		||||
            TLS: TLS
 | 
			
		||||
          };
 | 
			
		||||
          var deferred = $q.defer();
 | 
			
		||||
          Endpoints.update({}, endpoint, function success(data) {
 | 
			
		||||
            FileUploadService.uploadTLSFilesForEndpoint(ID, TLSCAFile, TLSCertFile, TLSKeyFile).then(function success(data) {
 | 
			
		||||
              deferred.notify({upload: false});
 | 
			
		||||
              deferred.resolve(data);
 | 
			
		||||
            }, function error(err) {
 | 
			
		||||
              deferred.notify({upload: false});
 | 
			
		||||
              deferred.reject({msg: 'Unable to upload TLS certs', err: err});
 | 
			
		||||
            });
 | 
			
		||||
          }, function error(err) {
 | 
			
		||||
            deferred.reject({msg: 'Unable to update endpoint', err: err});
 | 
			
		||||
          });
 | 
			
		||||
          return deferred.promise;
 | 
			
		||||
        },
 | 
			
		||||
        deleteEndpoint: function(endpointID) {
 | 
			
		||||
          return Endpoints.remove({id: endpointID}).$promise;
 | 
			
		||||
        },
 | 
			
		||||
        createLocalEndpoint: function(name, URL, TLS, active) {
 | 
			
		||||
          var endpoint = {
 | 
			
		||||
            Name: "local",
 | 
			
		||||
            URL: "unix:///var/run/docker.sock",
 | 
			
		||||
            TLS: false
 | 
			
		||||
          };
 | 
			
		||||
          return Endpoints.create({active: active}, endpoint).$promise;
 | 
			
		||||
        },
 | 
			
		||||
        createRemoteEndpoint: function(name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, active) {
 | 
			
		||||
          var endpoint = {
 | 
			
		||||
            Name: name,
 | 
			
		||||
            URL: 'tcp://' + URL,
 | 
			
		||||
            TLS: TLS
 | 
			
		||||
          };
 | 
			
		||||
          var deferred = $q.defer();
 | 
			
		||||
          Endpoints.create({active: active}, endpoint, function success(data) {
 | 
			
		||||
            var endpointID = data.Id;
 | 
			
		||||
            if (TLS) {
 | 
			
		||||
              deferred.notify({upload: true});
 | 
			
		||||
              FileUploadService.uploadTLSFilesForEndpoint(endpointID, TLSCAFile, TLSCertFile, TLSKeyFile).then(function success(data) {
 | 
			
		||||
                deferred.notify({upload: false});
 | 
			
		||||
                if (active) {
 | 
			
		||||
                  Endpoints.setActiveEndpoint({}, {id: endpointID}, function success(data) {
 | 
			
		||||
                    deferred.resolve(data);
 | 
			
		||||
                  }, function error(err) {
 | 
			
		||||
                    deferred.reject({msg: 'Unable to create endpoint', err: err});
 | 
			
		||||
                  });
 | 
			
		||||
                } else {
 | 
			
		||||
                  deferred.resolve(data);
 | 
			
		||||
                }
 | 
			
		||||
              }, function error(err) {
 | 
			
		||||
                deferred.notify({upload: false});
 | 
			
		||||
                deferred.reject({msg: 'Unable to upload TLS certs', err: err});
 | 
			
		||||
              });
 | 
			
		||||
            } else {
 | 
			
		||||
              deferred.resolve(data);
 | 
			
		||||
            }
 | 
			
		||||
          }, function error(err) {
 | 
			
		||||
            deferred.reject({msg: 'Unable to create endpoint', err: err});
 | 
			
		||||
          });
 | 
			
		||||
          return deferred.promise;
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('Messages', ['$rootScope', '$sanitize', function MessagesFactory($rootScope, $sanitize) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        return {
 | 
			
		||||
            send: function (title, text) {
 | 
			
		||||
                $.gritter.add({
 | 
			
		||||
                    title: $sanitize(title),
 | 
			
		||||
                    text: $sanitize(text),
 | 
			
		||||
                    time: 2000,
 | 
			
		||||
                    before_open: function () {
 | 
			
		||||
                        if ($('.gritter-item-wrapper').length === 3) {
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            },
 | 
			
		||||
            error: function (title, e, fallbackText) {
 | 
			
		||||
                var msg = fallbackText;
 | 
			
		||||
                if (e.data && e.data.message) {
 | 
			
		||||
                  msg = e.data.message;
 | 
			
		||||
                } else if (e.message) {
 | 
			
		||||
                  msg = e.message;
 | 
			
		||||
                } else if (e.data && e.data.length > 0 && e.data[0].message) {
 | 
			
		||||
                  msg = e.data[0].message;
 | 
			
		||||
                }
 | 
			
		||||
                $.gritter.add({
 | 
			
		||||
                    title: $sanitize(title),
 | 
			
		||||
                    text: $sanitize(msg),
 | 
			
		||||
                    time: 10000,
 | 
			
		||||
                    before_open: function () {
 | 
			
		||||
                        if ($('.gritter-item-wrapper').length === 4) {
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }])
 | 
			
		||||
    .factory('LineChart', ['Settings', function LineChartFactory(Settings) {
 | 
			
		||||
        'use strict';
 | 
			
		||||
        return {
 | 
			
		||||
            build: function (id, data, getkey) {
 | 
			
		||||
                var chart = new Chart($(id).get(0).getContext("2d"));
 | 
			
		||||
                var map = {};
 | 
			
		||||
 | 
			
		||||
                for (var i = 0; i < data.length; i++) {
 | 
			
		||||
                    var c = data[i];
 | 
			
		||||
                    var key = getkey(c);
 | 
			
		||||
 | 
			
		||||
                    var count = map[key];
 | 
			
		||||
                    if (count === undefined) {
 | 
			
		||||
                        count = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                    count += 1;
 | 
			
		||||
                    map[key] = count;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var labels = [];
 | 
			
		||||
                data = [];
 | 
			
		||||
                var keys = Object.keys(map);
 | 
			
		||||
                var max = 1;
 | 
			
		||||
 | 
			
		||||
                for (i = keys.length - 1; i > -1; i--) {
 | 
			
		||||
                    var k = keys[i];
 | 
			
		||||
                    labels.push(k);
 | 
			
		||||
                    data.push(map[k]);
 | 
			
		||||
                    if (map[k] > max) {
 | 
			
		||||
                        max = map[k];
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                var steps = Math.min(max, 10);
 | 
			
		||||
                var dataset = {
 | 
			
		||||
                    fillColor: "rgba(151,187,205,0.5)",
 | 
			
		||||
                    strokeColor: "rgba(151,187,205,1)",
 | 
			
		||||
                    pointColor: "rgba(151,187,205,1)",
 | 
			
		||||
                    pointStrokeColor: "#fff",
 | 
			
		||||
                    data: data
 | 
			
		||||
                };
 | 
			
		||||
                chart.Line({
 | 
			
		||||
                        labels: labels,
 | 
			
		||||
                        datasets: [dataset]
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        scaleStepWidth: Math.ceil(max / steps),
 | 
			
		||||
                        pointDotRadius: 1,
 | 
			
		||||
                        scaleIntegersOnly: true,
 | 
			
		||||
                        scaleOverride: true,
 | 
			
		||||
                        scaleSteps: steps
 | 
			
		||||
                    });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }]);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,240 +0,0 @@
 | 
			
		|||
function ImageViewModel(data) {
 | 
			
		||||
  this.Id = data.Id;
 | 
			
		||||
  this.Tag = data.Tag;
 | 
			
		||||
  this.Repository = data.Repository;
 | 
			
		||||
  this.Created = data.Created;
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.RepoTags = data.RepoTags;
 | 
			
		||||
  this.VirtualSize = data.VirtualSize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function TaskViewModel(data, node_data) {
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Created = data.CreatedAt;
 | 
			
		||||
  this.Updated = data.UpdatedAt;
 | 
			
		||||
  this.Slot = data.Slot;
 | 
			
		||||
  this.Status = data.Status.State;
 | 
			
		||||
  this.Image = data.Spec.ContainerSpec ? data.Spec.ContainerSpec.Image : '';
 | 
			
		||||
  if (node_data) {
 | 
			
		||||
    for (var i = 0; i < node_data.length; ++i) {
 | 
			
		||||
      if (data.NodeID === node_data[i].ID) {
 | 
			
		||||
        this.Node = node_data[i].Description.Hostname;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ServiceViewModel(data) {
 | 
			
		||||
  this.Model = data;
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Name = data.Spec.Name;
 | 
			
		||||
  this.Image = data.Spec.TaskTemplate.ContainerSpec.Image;
 | 
			
		||||
  this.Version = data.Version.Index;
 | 
			
		||||
  if (data.Spec.Mode.Replicated) {
 | 
			
		||||
    this.Mode = 'replicated' ;
 | 
			
		||||
    this.Replicas = data.Spec.Mode.Replicated.Replicas;
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Mode = 'global';
 | 
			
		||||
  }
 | 
			
		||||
  this.Labels = data.Spec.Labels;
 | 
			
		||||
  if (data.Spec.TaskTemplate.ContainerSpec) {
 | 
			
		||||
    this.ContainerLabels = data.Spec.TaskTemplate.ContainerSpec.Labels;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Spec.TaskTemplate.ContainerSpec.Env) {
 | 
			
		||||
    this.Env = data.Spec.TaskTemplate.ContainerSpec.Env;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Endpoint.Ports) {
 | 
			
		||||
    this.Ports = data.Endpoint.Ports;
 | 
			
		||||
  }
 | 
			
		||||
  if (data.Spec.UpdateConfig) {
 | 
			
		||||
    this.UpdateParallelism = (typeof data.Spec.UpdateConfig.Parallelism !== undefined) ? data.Spec.UpdateConfig.Parallelism || 0 : 1;
 | 
			
		||||
    this.UpdateDelay = data.Spec.UpdateConfig.Delay || 0;
 | 
			
		||||
    this.UpdateFailureAction = data.Spec.UpdateConfig.FailureAction || 'pause';
 | 
			
		||||
  } else {
 | 
			
		||||
    this.UpdateParallelism = 1;
 | 
			
		||||
    this.UpdateDelay = 0;
 | 
			
		||||
    this.UpdateFailureAction = 'pause';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.Scale = false;
 | 
			
		||||
  this.EditName = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NodeViewModel(data) {
 | 
			
		||||
  this.Model = data;
 | 
			
		||||
  this.Id = data.ID;
 | 
			
		||||
  this.Version = data.Version.Index;
 | 
			
		||||
  this.Name = data.Spec.Name;
 | 
			
		||||
  this.Role = data.Spec.Role;
 | 
			
		||||
  this.CreatedAt = data.CreatedAt;
 | 
			
		||||
  this.UpdatedAt = data.UpdatedAt;
 | 
			
		||||
  this.Availability = data.Spec.Availability;
 | 
			
		||||
 | 
			
		||||
  var labels = data.Spec.Labels;
 | 
			
		||||
  if (labels) {
 | 
			
		||||
    this.Labels = Object.keys(labels).map(function(key) {
 | 
			
		||||
      return { key: key, value: labels[key], originalKey: key, originalValue: labels[key], added: true };
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Labels = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this.Hostname = data.Description.Hostname;
 | 
			
		||||
  this.PlatformArchitecture = data.Description.Platform.Architecture;
 | 
			
		||||
  this.PlatformOS = data.Description.Platform.OS;
 | 
			
		||||
  this.CPUs = data.Description.Resources.NanoCPUs;
 | 
			
		||||
  this.Memory = data.Description.Resources.MemoryBytes;
 | 
			
		||||
  this.EngineVersion = data.Description.Engine.EngineVersion;
 | 
			
		||||
  this.EngineLabels = data.Description.Engine.Labels;
 | 
			
		||||
  this.Plugins = data.Description.Engine.Plugins;
 | 
			
		||||
  this.Status = data.Status.State;
 | 
			
		||||
 | 
			
		||||
  if (data.ManagerStatus) {
 | 
			
		||||
    this.Leader = data.ManagerStatus.Leader;
 | 
			
		||||
    this.Reachability = data.ManagerStatus.Reachability;
 | 
			
		||||
    this.ManagerAddr = data.ManagerStatus.Addr;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ContainerViewModel(data) {
 | 
			
		||||
  this.Id = data.Id;
 | 
			
		||||
  this.Status = data.Status;
 | 
			
		||||
  this.State = data.State;
 | 
			
		||||
  this.Names = data.Names;
 | 
			
		||||
  // Unavailable in Docker < 1.10
 | 
			
		||||
  if (data.NetworkSettings && !_.isEmpty(data.NetworkSettings.Networks)) {
 | 
			
		||||
    this.IP = data.NetworkSettings.Networks[Object.keys(data.NetworkSettings.Networks)[0]].IPAddress;
 | 
			
		||||
  }
 | 
			
		||||
  this.Image = data.Image;
 | 
			
		||||
  this.Command = data.Command;
 | 
			
		||||
  this.Checked = false;
 | 
			
		||||
  this.Ports = [];
 | 
			
		||||
  for (var i = 0; i < data.Ports.length; ++i) {
 | 
			
		||||
    var p = data.Ports[i];
 | 
			
		||||
    if (p.PublicPort) {
 | 
			
		||||
      this.Ports.push({ host: p.IP, private: p.PrivatePort, public: p.PublicPort });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createEventDetails(event) {
 | 
			
		||||
  var eventAttr = event.Actor.Attributes;
 | 
			
		||||
  var details = '';
 | 
			
		||||
  switch (event.Type) {
 | 
			
		||||
    case 'container':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'stop':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' stopped';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'start':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' started';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'kill':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' killed';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'die':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' exited with status code ' + eventAttr.exitCode;
 | 
			
		||||
      break;
 | 
			
		||||
      case 'commit':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' committed';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'restart':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' restarted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'pause':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' paused';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'unpause':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' unpaused';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'attach':
 | 
			
		||||
      details = 'Container ' + eventAttr.name + ' attached';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      if (event.Action.indexOf('exec_create') === 0) {
 | 
			
		||||
        details = 'Exec instance created';
 | 
			
		||||
      } else if (event.Action.indexOf('exec_start') === 0) {
 | 
			
		||||
        details = 'Exec instance started';
 | 
			
		||||
      } else {
 | 
			
		||||
        details = 'Unsupported event';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'image':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'delete':
 | 
			
		||||
      details = 'Image deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'tag':
 | 
			
		||||
      details = 'New tag created for ' + eventAttr.name;
 | 
			
		||||
      break;
 | 
			
		||||
      case 'untag':
 | 
			
		||||
      details = 'Image untagged';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'pull':
 | 
			
		||||
      details = 'Image ' + event.Actor.ID + ' pulled';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'network':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Network ' + eventAttr.name + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Network ' + eventAttr.name + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'connect':
 | 
			
		||||
      details = 'Container connected to ' + eventAttr.name + ' network';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'disconnect':
 | 
			
		||||
      details = 'Container disconnected from ' + eventAttr.name + ' network';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    case 'volume':
 | 
			
		||||
    switch (event.Action) {
 | 
			
		||||
      case 'create':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' created';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'destroy':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' deleted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'mount':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' mounted';
 | 
			
		||||
      break;
 | 
			
		||||
      case 'unmount':
 | 
			
		||||
      details = 'Volume ' + event.Actor.ID + ' unmounted';
 | 
			
		||||
      break;
 | 
			
		||||
      default:
 | 
			
		||||
      details = 'Unsupported event';
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
    default:
 | 
			
		||||
    details = 'Unsupported event';
 | 
			
		||||
  }
 | 
			
		||||
  return details;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function EventViewModel(data) {
 | 
			
		||||
  // Type, Action, Actor unavailable in Docker < 1.10
 | 
			
		||||
  this.Time = data.time;
 | 
			
		||||
  if (data.Type) {
 | 
			
		||||
    this.Type = data.Type;
 | 
			
		||||
    this.Details = createEventDetails(data);
 | 
			
		||||
  } else {
 | 
			
		||||
    this.Type = data.status;
 | 
			
		||||
    this.Details = data.from;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue