diff --git a/lemur/static/app/angular/destinations/destination/destination.js b/lemur/static/app/angular/destinations/destination/destination.js
new file mode 100644
index 00000000..15fb2b42
--- /dev/null
+++ b/lemur/static/app/angular/destinations/destination/destination.js
@@ -0,0 +1,40 @@
+'use strict';
+
+angular.module('lemur')
+
+ .controller('DestinationsCreateController', function ($scope, $modalInstance, PluginService, DestinationService, LemurRestangular){
+ $scope.destination = LemurRestangular.restangularizeElement(null, {}, 'destinations');
+
+ PluginService.get('destination').then(function (plugins) {
+ $scope.plugins = plugins;
+ });
+ $scope.save = function (destination) {
+ DestinationService.create(destination).then(function () {
+ $modalInstance.close();
+ });
+ };
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+ })
+
+ .controller('DestinationsEditController', function ($scope, $modalInstance, DestinationService, DestinationApi, PluginService, editId) {
+ DestinationApi.get(editId).then(function (destination) {
+ $scope.destination = destination;
+ });
+
+ PluginService.get('destination').then(function (plugins) {
+ $scope.plugins = plugins;
+ });
+
+ $scope.save = function (destination) {
+ DestinationService.update(destination).then(function () {
+ $modalInstance.close();
+ });
+ }
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+ });
diff --git a/lemur/static/app/angular/destinations/destination/destination.tpl.html b/lemur/static/app/angular/destinations/destination/destination.tpl.html
new file mode 100644
index 00000000..5ae1fdf3
--- /dev/null
+++ b/lemur/static/app/angular/destinations/destination/destination.tpl.html
@@ -0,0 +1,56 @@
+
+
diff --git a/lemur/static/app/angular/destinations/services.js b/lemur/static/app/angular/destinations/services.js
new file mode 100644
index 00000000..08d304d8
--- /dev/null
+++ b/lemur/static/app/angular/destinations/services.js
@@ -0,0 +1,53 @@
+'use strict';
+angular.module('lemur')
+ .service('DestinationApi', function (LemurRestangular) {
+ return LemurRestangular.all('destinations');
+ })
+ .service('DestinationService', function ($location, DestinationApi, toaster) {
+ var DestinationService = this;
+ DestinationService.findDestinationsByName = function (filterValue) {
+ return DestinationApi.getList({'filter[label]': filterValue})
+ .then(function (destinations) {
+ return destinations;
+ });
+ };
+
+ DestinationService.create = function (destination) {
+ return DestinationApi.post(destination).then(
+ function () {
+ toaster.pop({
+ type: 'success',
+ title: destination.label,
+ body: 'Successfully created!'
+ });
+ $location.path('destinations');
+ },
+ function (response) {
+ toaster.pop({
+ type: 'error',
+ title: destination.label,
+ body: 'Was not created! ' + response.data.message
+ });
+ });
+ };
+
+ DestinationService.update = function (destination) {
+ return destination.put().then(
+ function () {
+ toaster.pop({
+ type: 'success',
+ title: destination.label,
+ body: 'Successfully updated!'
+ });
+ $location.path('destinations');
+ },
+ function (response) {
+ toaster.pop({
+ type: 'error',
+ title: destination.label,
+ body: 'Was not updated! ' + response.data.message
+ });
+ });
+ };
+ return DestinationService;
+ });
diff --git a/lemur/static/app/angular/destinations/view/view.js b/lemur/static/app/angular/destinations/view/view.js
new file mode 100644
index 00000000..bd4974dd
--- /dev/null
+++ b/lemur/static/app/angular/destinations/view/view.js
@@ -0,0 +1,85 @@
+'use strict';
+
+angular.module('lemur')
+
+ .config(function config($routeProvider) {
+ $routeProvider.when('/destinations', {
+ templateUrl: '/angular/destinations/view/view.tpl.html',
+ controller: 'DestinationsViewController'
+ });
+ })
+
+ .controller('DestinationsViewController', function ($scope, $modal, DestinationApi, DestinationService, ngTableParams, toaster) {
+ $scope.filter = {};
+ $scope.destinationsTable = new ngTableParams({
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ id: 'desc' // initial sorting
+ },
+ filter: $scope.filter
+ }, {
+ total: 0, // length of data
+ getData: function ($defer, params) {
+ DestinationApi.getList(params.url()).then(
+ function (data) {
+ params.total(data.total);
+ $defer.resolve(data);
+ }
+ );
+ }
+ });
+
+ $scope.remove = function (destination) {
+ destination.remove().then(
+ function () {
+ $scope.destinationsTable.reload();
+ },
+ function (response) {
+ toaster.pop({
+ type: 'error',
+ title: 'Opps',
+ body: 'I see what you did there' + response.data.message
+ });
+ }
+ );
+ };
+
+ $scope.edit = function (destinationId) {
+ var modalInstance = $modal.open({
+ animation: true,
+ templateUrl: '/angular/destinations/destination/destination.tpl.html',
+ controller: 'DestinationsEditController',
+ size: 'lg',
+ resolve: {
+ editId: function () {
+ return destinationId;
+ }
+ }
+ });
+
+ modalInstance.result.then(function () {
+ $scope.destinationsTable.reload();
+ });
+
+ };
+
+ $scope.create = function () {
+ var modalInstance = $modal.open({
+ animation: true,
+ controller: 'DestinationsCreateController',
+ templateUrl: '/angular/destinations/destination/destination.tpl.html',
+ size: 'lg'
+ });
+
+ modalInstance.result.then(function () {
+ $scope.destinationsTable.reload();
+ });
+
+ };
+
+ $scope.toggleFilter = function (params) {
+ params.settings().$scope.show_filter = !params.settings().$scope.show_filter;
+ };
+
+ });
diff --git a/lemur/static/app/angular/destinations/view/view.tpl.html b/lemur/static/app/angular/destinations/view/view.tpl.html
new file mode 100644
index 00000000..83e9205a
--- /dev/null
+++ b/lemur/static/app/angular/destinations/view/view.tpl.html
@@ -0,0 +1,47 @@
+
+
+
Destinations
+ oh the places you will go
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - {{ destination.label }}
+ - {{ destination.description }}
+
+ |
+
+
+ - {{ destination.plugin.title }}
+ - {{ destination.plugin.description }}
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+
+