Building app and caching templates
diff --git a/xos/core/xoslib/xos-builder/dist/xosContentProvider.js b/xos/core/xoslib/xos-builder/dist/xosContentProvider.js
new file mode 100644
index 0000000..9c2b58d
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/dist/xosContentProvider.js
@@ -0,0 +1 @@
+angular.module("xos.contentProviderApp",["ngResource","ngRoute","ngCookies","ngLodash"]).config(["$interpolateProvider","$routeProvider","$resourceProvider",function(n,e,t){n.startSymbol("{$"),n.endSymbol("$}"),t.defaults.stripTrailingSlashes=!1,e.when("/",{template:"<content-provider-list></content-provider-list>"}).when("/contentProvider/:id?",{template:"<content-provider-detail></content-provider-detail>"}).when("/contentProvider/:id/cdn_prefix",{template:"<content-provider-cdn></content-provider-cdn>"}).when("/contentProvider/:id/origin_server",{template:"<content-provider-server></content-provider-server>"}).when("/contentProvider/:id/users",{template:"<content-provider-users></content-provider-users>"}).otherwise("/")}]).config(["$httpProvider",function(n){n.interceptors.push("SetCSRFToken")}]).factory("SetCSRFToken",["$cookies",function(n){return{request:function(e){return-1===e.url.indexOf(".html")&&(e.url+="?no_hyperlinks=1"),"GET"!==e.method&&(e.headers["X-CSRFToken"]=n.get("xoscsrftoken")),e}}}]).service("ContentProvider",["$resource",function(n){return n("/hpcapi/contentproviders/:id/",{id:"@id"},{update:{method:"PUT"}})}]).service("ServiceProvider",["$resource",function(n){return n("/hpcapi/serviceproviders/:id/",{id:"@id"})}]).service("CdnPrefix",["$resource",function(n){return n("/hpcapi/cdnprefixs/:id/",{id:"@id"})}]).service("OriginServer",["$resource",function(n){return n("/hpcapi/originservers/:id/",{id:"@id"})}]).service("User",["$resource",function(n){return n("/xos/users/:id/",{id:"@id"})}]).directive("cpActions",["ContentProvider","$location",function(n,e){return{restrict:"E",scope:{id:"=id"},bindToController:!0,controllerAs:"vm",templateUrl:"../../static/templates/contentProvider/cp_actions.html",controller:function(){this.deleteCp=function(t){n["delete"]({id:t}).$promise.then(function(){e.url("/")})}}}}]).directive("contentProviderList",["ContentProvider","lodash",function(n,e){return{restrict:"E",controllerAs:"vm",scope:{},templateUrl:"../../static/templates/contentProvider/cp_list.html",controller:function(){var t=this;n.query().$promise.then(function(n){t.contentProviderList=n})["catch"](function(n){throw new Error(n)}),this.deleteCp=function(i){n["delete"]({id:i}).$promise.then(function(){e.remove(t.contentProviderList,{id:i})})}}}}]).directive("contentProviderDetail",["ContentProvider","ServiceProvider","$routeParams","$location",function(n,e,t,i){return{restrict:"E",controllerAs:"vm",scope:{},templateUrl:"../../static/templates/contentProvider/cp_detail.html",controller:function(){this.pageName="detail";var s=this;t.id?n.get({id:t.id}).$promise.then(function(n){s.cp=n})["catch"](function(n){s.result={status:0,msg:n.data.detail}}):s.cp=new n,e.query().$promise.then(function(n){s.sp=n}),this.saveContentProvider=function(n){var e,t=!1;n.id?e=n.$update():(t=!0,n.name=n.humanReadableName,e=n.$save()),e.then(function(n){s.result={status:1,msg:"Content Provider Saved"},t&&i.url("contentProvider/"+n.id+"/")})["catch"](function(n){s.result={status:0,msg:n.data.detail}})}}}}]).directive("contentProviderCdn",["$routeParams","CdnPrefix","ContentProvider","lodash",function(n,e,t,i){return{restrict:"E",controllerAs:"vm",scope:{},templateUrl:"../../static/templates/contentProvider/cp_cdn_prefix.html",controller:function(){var s=this;this.pageName="cdn",n.id&&t.get({id:n.id}).$promise.then(function(n){s.cp=n})["catch"](function(n){s.result={status:0,msg:n.data.detail}}),e.query().$promise.then(function(e){s.prf=e,s.cp_prf=i.where(e,{contentProvider:parseInt(n.id)})})["catch"](function(n){s.result={status:0,msg:n.data.detail}}),this.addPrefix=function(t){t.contentProvider=n.id;var i=new e(t);i.$save().then(function(n){s.cp_prf.push(n)})["catch"](function(n){s.result={status:0,msg:n.data.detail}})},this.removePrefix=function(n){n.$delete().then(function(){i.remove(s.cp_prf,n)})["catch"](function(n){s.result={status:0,msg:n.data.detail}})}}}}]).directive("contentProviderServer",["$routeParams","OriginServer","ContentProvider","lodash",function(n,e,t,i){return{restrict:"E",controllerAs:"vm",scope:{},templateUrl:"../../static/templates/contentProvider/cp_origin_server.html",controller:function(){this.pageName="server",this.protocols={http:"HTTP",rtmp:"RTMP",rtp:"RTP",shout:"SHOUTcast"};var s=this;n.id&&t.get({id:n.id}).$promise.then(function(n){s.cp=n})["catch"](function(n){s.result={status:0,msg:n.data.detail}}),e.query({contentProvider:n.id}).$promise.then(function(n){s.cp_os=n})["catch"](function(n){s.result={status:0,msg:n.data.detail}}),this.addOrigin=function(t){t.contentProvider=n.id;var i=new e(t);i.$save().then(function(n){s.cp_os.push(n)})["catch"](function(n){s.result={status:0,msg:n.data.detail}})},this.removeOrigin=function(n){n.$delete().then(function(){i.remove(s.cp_os,n)})["catch"](function(n){s.result={status:0,msg:n.data.detail}})}}}}]).directive("contentProviderUsers",["$routeParams","ContentProvider","User","lodash",function(n,e,t,i){return{restrict:"E",controllerAs:"vm",scope:{},templateUrl:"../../static/templates/contentProvider/cp_user.html",controller:function(){var s=this;this.pageName="user",this.cp_users=[],n.id&&t.query().$promise.then(function(t){return s.users=t,e.get({id:n.id}).$promise}).then(function(n){return n.users=s.populateUser(n.users,s.users),n}).then(function(n){s.cp=n})["catch"](function(n){s.result={status:0,msg:n.data.detail}}),this.populateUser=function(n,e){for(var t=0;t<n.length;t++)n[t]=i.find(e,{id:n[t]});return n},this.addUserToCp=function(n){s.cp.users.push(n)},this.removeUserFromCp=function(n){i.remove(s.cp.users,n)},this.saveContentProvider=function(n){n.users=i.pluck(n.users,"id"),n.$update().then(function(n){s.cp.users=s.populateUser(n.users,s.users),s.result={status:1,msg:"Content Provider Saved"}})["catch"](function(n){s.result={status:0,msg:n.data.detail}})}}}}]),angular.module("xos.contentProviderApp").run(["$templateCache",function(n){n.put("../../static/templates/contentProvider/cp_actions.html",'<a href="#/" class="btn btn-default">\n <i class="icon icon-arrow-left"></i>Back\n</a>\n<a href="#/contentProvider/" class="btn btn-success">\n <i class="icon icon-plus"></i>Create\n</a>\n<a ng-click="vm.deleteCp(vm.id)" class="btn btn-danger">\n <i class="icon icon-remove"></i>Remove\n</a>'),n.put("../../static/templates/contentProvider/cp_cdn_prefix.html",'<div class="row-fluid">\n <div class="span6">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class="span6 text-right">\n <cp-actions id="vm.cp.id"></cp-actions>\n </div>\n</div>\n<hr>\n<div class="row-fluid">\n <div class="span2">\n <div ng-include="\'../../static/templates/contentProvider/cp_side_nav.html\'"></div>\n </div>\n <div class="span10">\n <div ng-repeat="item in vm.cp_prf" class="well">\n <div class="row-fluid">\n <div class="span4">\n {{item.humanReadableName}}\n </div>\n <div class="span6">\n <!-- TODO show the name instead that id -->\n {{item.defaultOriginServer}}\n </div>\n <div class="span2">\n <a ng-click="vm.removePrefix(item)" class="btn btn-danger pull-right">\n <i class="icon icon-remove"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit="vm.addPrefix(vm.new_prf)">\n <div class="row-fluid">\n <div class="span4">\n <label>Prefix</label>\n <input type="text" ng-model="vm.new_prf.prefix" required style="max-width: 90%">\n </div>\n <div class="span6">\n <label>Default Origin Server</label>\n <select ng-model="vm.new_prf.defaultOriginServer" style="max-width: 100%">\n <option ng-repeat="prf in vm.prf" ng-value="prf.id">{$ prf.humanReadableName $}</option>\n </select>\n </div>\n <div class="span2 text-right">\n <button class="btn btn-success margin-wells">\n <i class="icon icon-plus"></i>\n </button>\n </div>\n </div>\n </form>\n <div class="alert" ng-show="vm.result" ng-class="{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>'),n.put("../../static/templates/contentProvider/cp_detail.html",'<div class="row-fluid">\n <div class="span6">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class="span6 text-right">\n <cp-actions id="vm.cp.id"></cp-actions>\n </div>\n</div>\n<hr>\n<div class="row-fluid">\n <div ng-show="vm.cp.id" class="span2">\n <div ng-include="\'../../static/templates/contentProvider/cp_side_nav.html\'"></div>\n </div>\n <div ng-class="{span10: vm.cp.id, span12: !vm.cp.id}">\n <!-- TODO hide form on not found -->\n <form ng-submit="vm.saveContentProvider(vm.cp)">\n <fieldset>\n <div class="row-fluid">\n <div class="span6">\n <label>Name:</label>\n <input type="text" ng-model="vm.cp.humanReadableName" required/>\n </div>\n <div class="span6">\n <label class="checkbox">\n <input type="checkbox" ng-model="vm.cp.enabled" /> Enabled\n </label>\n </div>\n </div>\n <div class="row-fluid">\n <div class="span12">\n <label>Description</label>\n <textarea style="width: 100%" ng-model="vm.cp.description"></textarea>\n </div>\n </div>\n <div class="row-fluid">\n <div class="span12">\n <label>Service provider</label>\n <select required ng-model="vm.cp.serviceProvider" ng-options="sp.id as sp.humanReadableName for sp in vm.sp"></select>\n </div>\n </div>\n <div class="row-fluid">\n <div class="span12">\n <button class="btn btn-success">\n <span ng-show="vm.cp.id">Save</span>\n <span ng-show="!vm.cp.id">Create</span>\n </button>\n </div>\n </div>\n </fieldset>\n </form>\n <div class="alert" ng-show="vm.result" ng-class="{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>'),n.put("../../static/templates/contentProvider/cp_list.html",'<table class="table table-striped" ng-show="vm.contentProviderList.length > 0">\n <thead>\n <tr>\n <th>\n Name\n </th>\n <th>Description</th>\n <th>Status</th>\n <th></th>\n </tr>\n </thead>\n <tr ng-repeat="item in vm.contentProviderList">\n <td>\n <a href="#/contentProvider/{$ item.id $}">{$ item.humanReadableName $}</a>\n </td>\n <td>\n {$ item.description $}\n </td>\n <td>\n {$ item.enabled $}\n </td>\n <td class="text-right">\n <a ng-click="vm.deleteCp(item.id)" class="btn btn-danger"><i class="icon icon-remove"></i></a></td>\n </tr>\n</table>\n<div class="alert alert-error" ng-show="vm.contentProviderList.length == 0">\n No Content Provider defined\n</div>\n\n<div class="row">\n <div class="span12 text-right">\n <a class="btn btn-success"href="#/contentProvider/">Create</a>\n </div>\n</div>'),n.put("../../static/templates/contentProvider/cp_origin_server.html",'<div class="row-fluid">\n <div class="span6">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class="span6 text-right">\n <cp-actions id="vm.cp.id"></cp-actions>\n </div>\n</div>\n<hr>\n<div class="row-fluid">\n <div class="span2">\n <div ng-include="\'../../static/templates/contentProvider/cp_side_nav.html\'"></div>\n </div>\n <div class="span10">\n <div ng-repeat="item in vm.cp_os" class="well">\n <div class="row-fluid">\n <div class="span4">\n {{item.humanReadableName}}\n </div>\n <div class="span6">\n <!-- TODO shoe the name instead that url -->\n {{item.defaultOriginServer}}\n </div>\n <div class="span2">\n <a ng-click="vm.removeOrigin(item)" class="btn btn-danger pull-right">\n <i class="icon icon-remove"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit="vm.addOrigin(vm.new_os)">\n <div class="row-fluid">\n <div class="span4">\n <label>Protocol</label>\n <select ng-model="vm.new_os.protocol" ng-options="k as v for (k,v) in vm.protocols" style="max-width: 100%;"></select>\n </div>\n <div class="span6">\n <label>Url</label>\n <input type="text" ng-model="vm.new_os.url" required>\n </div>\n <div class="span2 text-right">\n <button class="btn btn-success margin-wells">\n <i class="icon icon-plus"></i>\n </button>\n </div>\n </div>\n </form>\n <div class="alert" ng-show="vm.result" ng-class="{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>'),n.put("../../static/templates/contentProvider/cp_side_nav.html",'<ul class="nav nav-list">\n <li>\n <a class="btn" ng-class="{\'btn-primary\': vm.pageName == \'detail\'}" href="#/contentProvider/{$ vm.cp.id $}">Details</a>\n </li>\n <li>\n <a class="btn" ng-class="{\'btn-primary\': vm.pageName == \'cdn\'}" href="#/contentProvider/{$ vm.cp.id $}/cdn_prefix">Cdn Prexix</a>\n </li>\n <li>\n <a class="btn" ng-class="{\'btn-primary\': vm.pageName == \'server\'}" href="#/contentProvider/{$ vm.cp.id $}/origin_server">Origin Server</a>\n </li>\n <li>\n <a class="btn" ng-class="{\'btn-primary\': vm.pageName == \'user\'}" href="#/contentProvider/{$ vm.cp.id $}/users">Users</a>\n </li>\n</ul>'),n.put("../../static/templates/contentProvider/cp_user.html",'<div class="row-fluid">\n <div class="span6">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class="span6 text-right">\n <cp-actions id="vm.cp.id"></cp-actions>\n </div>\n</div>\n<hr>\n<div class="row-fluid">\n <div class="span2">\n <div ng-include="\'../../static/templates/contentProvider/cp_side_nav.html\'"></div>\n </div>\n <div class="span10">\n <div ng-repeat="item in vm.cp.users" class="well">\n <div class="row-fluid">\n <div class="span3">\n {{item.firstname}}\n </div>\n <div class="span3">\n {{item.lastname}}\n </div>\n <div class="span4">\n {{item.email}}\n </div>\n <div class="span2">\n <a ng-click="vm.removeUserFromCp(item)" class="btn btn-danger pull-right">\n <i class="icon icon-remove"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit="vm.saveContentProvider(vm.cp)">\n <div class="row-fluid">\n <div class="span8">\n <label>Select user:</label>\n <select ng-model="vm.user" ng-options="u as u.username for u in vm.users" ng-change="vm.addUserToCp(vm.user)"></select>\n </div> \n <div class="span4 text-right">\n <button class="btn btn-success margin-wells">\n Save\n </button>\n </div>\n </div>\n </form>\n <div class="alert" ng-show="vm.result" ng-class="{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>')}]);
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/gulpfile.js b/xos/core/xoslib/xos-builder/gulpfile.js
new file mode 100644
index 0000000..87dda39
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/gulpfile.js
@@ -0,0 +1,56 @@
+'use strict';
+
+// BUILD
+//
+// The only purpose of this gulpfile is to build a XOS view and copy the correct files into
+// .html => dashboards
+// .js (minified and concat) => static/js
+//
+// The template are parsed and added to js with angular $templateCache
+
+var gulp = require('gulp');
+var ngmin = require('gulp-ngmin');
+var uglify = require('gulp-uglify');
+var templateCache = require('gulp-angular-templatecache');
+var runSequence = require('run-sequence');
+var minifyHtml = require("gulp-minify-html");
+var concat = require("gulp-concat");
+var del = require('del');
+
+gulp.task('clean', function(){
+ return del(['dist/**/*']);
+});
+
+gulp.task('scripts', function() {
+ return gulp.src([
+ 'src/xosContentProvider.js',
+ 'src/templates.js'
+ ])
+ .pipe(ngmin())
+ .pipe(concat('xosContentProvider.js'))
+ .pipe(uglify())
+ .pipe(gulp.dest('dist'));
+});
+
+gulp.task('templates', function(){
+ return gulp.src("./src/templates/*.html")
+ .pipe(templateCache({
+ module: 'xos.contentProviderApp',
+ root: '../../static/templates/contentProvider/'
+ }))
+ .pipe(gulp.dest("src"));
+});
+
+gulp.task('copyJs', function(){
+ return gulp.src('dist/xosContentProvider.js')
+ .pipe(gulp.dest('../static/js/'))
+});
+
+gulp.task('default', function() {
+ runSequence(
+ 'clean',
+ 'templates',
+ 'scripts',
+ 'copyJs'
+ );
+});
diff --git a/xos/core/xoslib/xos-builder/package.json b/xos/core/xoslib/xos-builder/package.json
new file mode 100644
index 0000000..e5800b0
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "xos-builder",
+ "version": "1.0.0",
+ "description": "Angular Application Builder tailored to XOS needings",
+ "main": "xos-builder.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "XOS",
+ "Angular",
+ "XOSlib"
+ ],
+ "author": "Matteo Scandolo",
+ "license": "ISC",
+ "dependencies": {},
+ "devDependencies": {
+ "del": "^2.0.2",
+ "gulp": "^3.9.0",
+ "gulp-angular-templatecache": "^1.8.0",
+ "gulp-concat": "^2.6.0",
+ "gulp-minify-html": "^1.0.4",
+ "gulp-ngmin": "^0.3.0",
+ "gulp-uglify": "^1.4.2",
+ "run-sequence": "^1.1.4"
+ }
+}
diff --git a/xos/core/xoslib/xos-builder/src/contentProvider.html b/xos/core/xoslib/xos-builder/src/contentProvider.html
new file mode 100644
index 0000000..24cd7f1
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/contentProvider.html
@@ -0,0 +1,21 @@
+<!--
+To setup hpc:
+- cd /opt/xos/tosca
+- python ./run.py padmin@vicci.org samples/cdn.yaml
+
+To generate hpcapi:
+- cd /opt/xos
+- python apigen/modelgen apigen/hpc-api.template.py -n User -n Service -a hpc > xos/hpcapi.py
+ -->
+
+<div ng-app="xos.contentProviderApp">
+ <ng-view></ng-view>
+</div>
+
+<link rel="stylesheet" href="{{ STATIC_URL }}/css/xosLib.css">
+<script src="{{ STATIC_URL }}/js/vendor/angular/angular.min.js"></script>
+<script src="{{ STATIC_URL }}/js/vendor/angular-resource/angular-resource.min.js"></script>
+<script src="{{ STATIC_URL }}/js/vendor/angular-route/angular-route.min.js"></script>
+<script src="{{ STATIC_URL }}/js/vendor/angular-cookies/angular-cookies.min.js"></script>
+<script src="{{ STATIC_URL }}/js/vendor/ng-lodash/build/ng-lodash.min.js"></script>
+<script src="{{ STATIC_URL }}/js/xosContentProvider.js"></script>
diff --git a/xos/core/xoslib/xos-builder/src/templates.js b/xos/core/xoslib/xos-builder/src/templates.js
new file mode 100644
index 0000000..8abe693
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates.js
@@ -0,0 +1,7 @@
+angular.module("xos.contentProviderApp").run(["$templateCache", function($templateCache) {$templateCache.put("../../static/templates/contentProvider/cp_actions.html","<a href=\"#/\" class=\"btn btn-default\">\n <i class=\"icon icon-arrow-left\"></i>Back\n</a>\n<a href=\"#/contentProvider/\" class=\"btn btn-success\">\n <i class=\"icon icon-plus\"></i>Create\n</a>\n<a ng-click=\"vm.deleteCp(vm.id)\" class=\"btn btn-danger\">\n <i class=\"icon icon-remove\"></i>Remove\n</a>");
+$templateCache.put("../../static/templates/contentProvider/cp_cdn_prefix.html","<div class=\"row-fluid\">\n <div class=\"span6\">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class=\"span6 text-right\">\n <cp-actions id=\"vm.cp.id\"></cp-actions>\n </div>\n</div>\n<hr>\n<div class=\"row-fluid\">\n <div class=\"span2\">\n <div ng-include=\"\'../../static/templates/contentProvider/cp_side_nav.html\'\"></div>\n </div>\n <div class=\"span10\">\n <div ng-repeat=\"item in vm.cp_prf\" class=\"well\">\n <div class=\"row-fluid\">\n <div class=\"span4\">\n {{item.humanReadableName}}\n </div>\n <div class=\"span6\">\n <!-- TODO show the name instead that id -->\n {{item.defaultOriginServer}}\n </div>\n <div class=\"span2\">\n <a ng-click=\"vm.removePrefix(item)\" class=\"btn btn-danger pull-right\">\n <i class=\"icon icon-remove\"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit=\"vm.addPrefix(vm.new_prf)\">\n <div class=\"row-fluid\">\n <div class=\"span4\">\n <label>Prefix</label>\n <input type=\"text\" ng-model=\"vm.new_prf.prefix\" required style=\"max-width: 90%\">\n </div>\n <div class=\"span6\">\n <label>Default Origin Server</label>\n <select ng-model=\"vm.new_prf.defaultOriginServer\" style=\"max-width: 100%\">\n <option ng-repeat=\"prf in vm.prf\" ng-value=\"prf.id\">{$ prf.humanReadableName $}</option>\n </select>\n </div>\n <div class=\"span2 text-right\">\n <button class=\"btn btn-success margin-wells\">\n <i class=\"icon icon-plus\"></i>\n </button>\n </div>\n </div>\n </form>\n <div class=\"alert\" ng-show=\"vm.result\" ng-class=\"{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}\">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>");
+$templateCache.put("../../static/templates/contentProvider/cp_detail.html","<div class=\"row-fluid\">\n <div class=\"span6\">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class=\"span6 text-right\">\n <cp-actions id=\"vm.cp.id\"></cp-actions>\n </div>\n</div>\n<hr>\n<div class=\"row-fluid\">\n <div ng-show=\"vm.cp.id\" class=\"span2\">\n <div ng-include=\"\'../../static/templates/contentProvider/cp_side_nav.html\'\"></div>\n </div>\n <div ng-class=\"{span10: vm.cp.id, span12: !vm.cp.id}\">\n <!-- TODO hide form on not found -->\n <form ng-submit=\"vm.saveContentProvider(vm.cp)\">\n <fieldset>\n <div class=\"row-fluid\">\n <div class=\"span6\">\n <label>Name:</label>\n <input type=\"text\" ng-model=\"vm.cp.humanReadableName\" required/>\n </div>\n <div class=\"span6\">\n <label class=\"checkbox\">\n <input type=\"checkbox\" ng-model=\"vm.cp.enabled\" /> Enabled\n </label>\n </div>\n </div>\n <div class=\"row-fluid\">\n <div class=\"span12\">\n <label>Description</label>\n <textarea style=\"width: 100%\" ng-model=\"vm.cp.description\"></textarea>\n </div>\n </div>\n <div class=\"row-fluid\">\n <div class=\"span12\">\n <label>Service provider</label>\n <select required ng-model=\"vm.cp.serviceProvider\" ng-options=\"sp.id as sp.humanReadableName for sp in vm.sp\"></select>\n </div>\n </div>\n <div class=\"row-fluid\">\n <div class=\"span12\">\n <button class=\"btn btn-success\">\n <span ng-show=\"vm.cp.id\">Save</span>\n <span ng-show=\"!vm.cp.id\">Create</span>\n </button>\n </div>\n </div>\n </fieldset>\n </form>\n <div class=\"alert\" ng-show=\"vm.result\" ng-class=\"{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}\">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>");
+$templateCache.put("../../static/templates/contentProvider/cp_list.html","<table class=\"table table-striped\" ng-show=\"vm.contentProviderList.length > 0\">\n <thead>\n <tr>\n <th>\n Name\n </th>\n <th>Description</th>\n <th>Status</th>\n <th></th>\n </tr>\n </thead>\n <tr ng-repeat=\"item in vm.contentProviderList\">\n <td>\n <a href=\"#/contentProvider/{$ item.id $}\">{$ item.humanReadableName $}</a>\n </td>\n <td>\n {$ item.description $}\n </td>\n <td>\n {$ item.enabled $}\n </td>\n <td class=\"text-right\">\n <a ng-click=\"vm.deleteCp(item.id)\" class=\"btn btn-danger\"><i class=\"icon icon-remove\"></i></a></td>\n </tr>\n</table>\n<div class=\"alert alert-error\" ng-show=\"vm.contentProviderList.length == 0\">\n No Content Provider defined\n</div>\n\n<div class=\"row\">\n <div class=\"span12 text-right\">\n <a class=\"btn btn-success\"href=\"#/contentProvider/\">Create</a>\n </div>\n</div>");
+$templateCache.put("../../static/templates/contentProvider/cp_origin_server.html","<div class=\"row-fluid\">\n <div class=\"span6\">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class=\"span6 text-right\">\n <cp-actions id=\"vm.cp.id\"></cp-actions>\n </div>\n</div>\n<hr>\n<div class=\"row-fluid\">\n <div class=\"span2\">\n <div ng-include=\"\'../../static/templates/contentProvider/cp_side_nav.html\'\"></div>\n </div>\n <div class=\"span10\">\n <div ng-repeat=\"item in vm.cp_os\" class=\"well\">\n <div class=\"row-fluid\">\n <div class=\"span4\">\n {{item.humanReadableName}}\n </div>\n <div class=\"span6\">\n <!-- TODO shoe the name instead that url -->\n {{item.defaultOriginServer}}\n </div>\n <div class=\"span2\">\n <a ng-click=\"vm.removeOrigin(item)\" class=\"btn btn-danger pull-right\">\n <i class=\"icon icon-remove\"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit=\"vm.addOrigin(vm.new_os)\">\n <div class=\"row-fluid\">\n <div class=\"span4\">\n <label>Protocol</label>\n <select ng-model=\"vm.new_os.protocol\" ng-options=\"k as v for (k,v) in vm.protocols\" style=\"max-width: 100%;\"></select>\n </div>\n <div class=\"span6\">\n <label>Url</label>\n <input type=\"text\" ng-model=\"vm.new_os.url\" required>\n </div>\n <div class=\"span2 text-right\">\n <button class=\"btn btn-success margin-wells\">\n <i class=\"icon icon-plus\"></i>\n </button>\n </div>\n </div>\n </form>\n <div class=\"alert\" ng-show=\"vm.result\" ng-class=\"{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}\">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>");
+$templateCache.put("../../static/templates/contentProvider/cp_side_nav.html","<ul class=\"nav nav-list\">\n <li>\n <a class=\"btn\" ng-class=\"{\'btn-primary\': vm.pageName == \'detail\'}\" href=\"#/contentProvider/{$ vm.cp.id $}\">Details</a>\n </li>\n <li>\n <a class=\"btn\" ng-class=\"{\'btn-primary\': vm.pageName == \'cdn\'}\" href=\"#/contentProvider/{$ vm.cp.id $}/cdn_prefix\">Cdn Prexix</a>\n </li>\n <li>\n <a class=\"btn\" ng-class=\"{\'btn-primary\': vm.pageName == \'server\'}\" href=\"#/contentProvider/{$ vm.cp.id $}/origin_server\">Origin Server</a>\n </li>\n <li>\n <a class=\"btn\" ng-class=\"{\'btn-primary\': vm.pageName == \'user\'}\" href=\"#/contentProvider/{$ vm.cp.id $}/users\">Users</a>\n </li>\n</ul>");
+$templateCache.put("../../static/templates/contentProvider/cp_user.html","<div class=\"row-fluid\">\n <div class=\"span6\">\n <h1>{$ vm.cp.humanReadableName $}</h1>\n </div>\n <div class=\"span6 text-right\">\n <cp-actions id=\"vm.cp.id\"></cp-actions>\n </div>\n</div>\n<hr>\n<div class=\"row-fluid\">\n <div class=\"span2\">\n <div ng-include=\"\'../../static/templates/contentProvider/cp_side_nav.html\'\"></div>\n </div>\n <div class=\"span10\">\n <div ng-repeat=\"item in vm.cp.users\" class=\"well\">\n <div class=\"row-fluid\">\n <div class=\"span3\">\n {{item.firstname}}\n </div>\n <div class=\"span3\">\n {{item.lastname}}\n </div>\n <div class=\"span4\">\n {{item.email}}\n </div>\n <div class=\"span2\">\n <a ng-click=\"vm.removeUserFromCp(item)\" class=\"btn btn-danger pull-right\">\n <i class=\"icon icon-remove\"></i>\n </a>\n </div>\n </div>\n </div>\n <hr>\n <form ng-submit=\"vm.saveContentProvider(vm.cp)\">\n <div class=\"row-fluid\">\n <div class=\"span8\">\n <label>Select user:</label>\n <select ng-model=\"vm.user\" ng-options=\"u as u.username for u in vm.users\" ng-change=\"vm.addUserToCp(vm.user)\"></select>\n </div> \n <div class=\"span4 text-right\">\n <button class=\"btn btn-success margin-wells\">\n Save\n </button>\n </div>\n </div>\n </form>\n <div class=\"alert\" ng-show=\"vm.result\" ng-class=\"{\'alert-success\': vm.result.status === 1,\'alert-error\': vm.result.status === 0}\">\n {$ vm.result.msg $}\n </div>\n </div>\n</div>");}]);
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_actions.html b/xos/core/xoslib/xos-builder/src/templates/cp_actions.html
new file mode 100644
index 0000000..8c6ae97
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_actions.html
@@ -0,0 +1,9 @@
+<a href="#/" class="btn btn-default">
+ <i class="icon icon-arrow-left"></i>Back
+</a>
+<a href="#/contentProvider/" class="btn btn-success">
+ <i class="icon icon-plus"></i>Create
+</a>
+<a ng-click="vm.deleteCp(vm.id)" class="btn btn-danger">
+ <i class="icon icon-remove"></i>Remove
+</a>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_cdn_prefix.html b/xos/core/xoslib/xos-builder/src/templates/cp_cdn_prefix.html
new file mode 100644
index 0000000..cc39aab
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_cdn_prefix.html
@@ -0,0 +1,55 @@
+<div class="row-fluid">
+ <div class="span6">
+ <h1>{$ vm.cp.humanReadableName $}</h1>
+ </div>
+ <div class="span6 text-right">
+ <cp-actions id="vm.cp.id"></cp-actions>
+ </div>
+</div>
+<hr>
+<div class="row-fluid">
+ <div class="span2">
+ <div ng-include="'../../static/templates/contentProvider/cp_side_nav.html'"></div>
+ </div>
+ <div class="span10">
+ <div ng-repeat="item in vm.cp_prf" class="well">
+ <div class="row-fluid">
+ <div class="span4">
+ {{item.humanReadableName}}
+ </div>
+ <div class="span6">
+ <!-- TODO show the name instead that id -->
+ {{item.defaultOriginServer}}
+ </div>
+ <div class="span2">
+ <a ng-click="vm.removePrefix(item)" class="btn btn-danger pull-right">
+ <i class="icon icon-remove"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ <hr>
+ <form ng-submit="vm.addPrefix(vm.new_prf)">
+ <div class="row-fluid">
+ <div class="span4">
+ <label>Prefix</label>
+ <input type="text" ng-model="vm.new_prf.prefix" required style="max-width: 90%">
+ </div>
+ <div class="span6">
+ <label>Default Origin Server</label>
+ <select ng-model="vm.new_prf.defaultOriginServer" style="max-width: 100%">
+ <option ng-repeat="prf in vm.prf" ng-value="prf.id">{$ prf.humanReadableName $}</option>
+ </select>
+ </div>
+ <div class="span2 text-right">
+ <button class="btn btn-success margin-wells">
+ <i class="icon icon-plus"></i>
+ </button>
+ </div>
+ </div>
+ </form>
+ <div class="alert" ng-show="vm.result" ng-class="{'alert-success': vm.result.status === 1,'alert-error': vm.result.status === 0}">
+ {$ vm.result.msg $}
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_detail.html b/xos/core/xoslib/xos-builder/src/templates/cp_detail.html
new file mode 100644
index 0000000..0c11329
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_detail.html
@@ -0,0 +1,55 @@
+<div class="row-fluid">
+ <div class="span6">
+ <h1>{$ vm.cp.humanReadableName $}</h1>
+ </div>
+ <div class="span6 text-right">
+ <cp-actions id="vm.cp.id"></cp-actions>
+ </div>
+</div>
+<hr>
+<div class="row-fluid">
+ <div ng-show="vm.cp.id" class="span2">
+ <div ng-include="'../../static/templates/contentProvider/cp_side_nav.html'"></div>
+ </div>
+ <div ng-class="{span10: vm.cp.id, span12: !vm.cp.id}">
+ <!-- TODO hide form on not found -->
+ <form ng-submit="vm.saveContentProvider(vm.cp)">
+ <fieldset>
+ <div class="row-fluid">
+ <div class="span6">
+ <label>Name:</label>
+ <input type="text" ng-model="vm.cp.humanReadableName" required/>
+ </div>
+ <div class="span6">
+ <label class="checkbox">
+ <input type="checkbox" ng-model="vm.cp.enabled" /> Enabled
+ </label>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="span12">
+ <label>Description</label>
+ <textarea style="width: 100%" ng-model="vm.cp.description"></textarea>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="span12">
+ <label>Service provider</label>
+ <select required ng-model="vm.cp.serviceProvider" ng-options="sp.id as sp.humanReadableName for sp in vm.sp"></select>
+ </div>
+ </div>
+ <div class="row-fluid">
+ <div class="span12">
+ <button class="btn btn-success">
+ <span ng-show="vm.cp.id">Save</span>
+ <span ng-show="!vm.cp.id">Create</span>
+ </button>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ <div class="alert" ng-show="vm.result" ng-class="{'alert-success': vm.result.status === 1,'alert-error': vm.result.status === 0}">
+ {$ vm.result.msg $}
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_list.html b/xos/core/xoslib/xos-builder/src/templates/cp_list.html
new file mode 100644
index 0000000..3303564
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_list.html
@@ -0,0 +1,34 @@
+<table class="table table-striped" ng-show="vm.contentProviderList.length > 0">
+ <thead>
+ <tr>
+ <th>
+ Name
+ </th>
+ <th>Description</th>
+ <th>Status</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tr ng-repeat="item in vm.contentProviderList">
+ <td>
+ <a href="#/contentProvider/{$ item.id $}">{$ item.humanReadableName $}</a>
+ </td>
+ <td>
+ {$ item.description $}
+ </td>
+ <td>
+ {$ item.enabled $}
+ </td>
+ <td class="text-right">
+ <a ng-click="vm.deleteCp(item.id)" class="btn btn-danger"><i class="icon icon-remove"></i></a></td>
+ </tr>
+</table>
+<div class="alert alert-error" ng-show="vm.contentProviderList.length == 0">
+ No Content Provider defined
+</div>
+
+<div class="row">
+ <div class="span12 text-right">
+ <a class="btn btn-success"href="#/contentProvider/">Create</a>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_origin_server.html b/xos/core/xoslib/xos-builder/src/templates/cp_origin_server.html
new file mode 100644
index 0000000..ff77864
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_origin_server.html
@@ -0,0 +1,53 @@
+<div class="row-fluid">
+ <div class="span6">
+ <h1>{$ vm.cp.humanReadableName $}</h1>
+ </div>
+ <div class="span6 text-right">
+ <cp-actions id="vm.cp.id"></cp-actions>
+ </div>
+</div>
+<hr>
+<div class="row-fluid">
+ <div class="span2">
+ <div ng-include="'../../static/templates/contentProvider/cp_side_nav.html'"></div>
+ </div>
+ <div class="span10">
+ <div ng-repeat="item in vm.cp_os" class="well">
+ <div class="row-fluid">
+ <div class="span4">
+ {{item.humanReadableName}}
+ </div>
+ <div class="span6">
+ <!-- TODO shoe the name instead that url -->
+ {{item.defaultOriginServer}}
+ </div>
+ <div class="span2">
+ <a ng-click="vm.removeOrigin(item)" class="btn btn-danger pull-right">
+ <i class="icon icon-remove"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ <hr>
+ <form ng-submit="vm.addOrigin(vm.new_os)">
+ <div class="row-fluid">
+ <div class="span4">
+ <label>Protocol</label>
+ <select ng-model="vm.new_os.protocol" ng-options="k as v for (k,v) in vm.protocols" style="max-width: 100%;"></select>
+ </div>
+ <div class="span6">
+ <label>Url</label>
+ <input type="text" ng-model="vm.new_os.url" required>
+ </div>
+ <div class="span2 text-right">
+ <button class="btn btn-success margin-wells">
+ <i class="icon icon-plus"></i>
+ </button>
+ </div>
+ </div>
+ </form>
+ <div class="alert" ng-show="vm.result" ng-class="{'alert-success': vm.result.status === 1,'alert-error': vm.result.status === 0}">
+ {$ vm.result.msg $}
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_side_nav.html b/xos/core/xoslib/xos-builder/src/templates/cp_side_nav.html
new file mode 100644
index 0000000..a2c8633
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_side_nav.html
@@ -0,0 +1,14 @@
+<ul class="nav nav-list">
+ <li>
+ <a class="btn" ng-class="{'btn-primary': vm.pageName == 'detail'}" href="#/contentProvider/{$ vm.cp.id $}">Details</a>
+ </li>
+ <li>
+ <a class="btn" ng-class="{'btn-primary': vm.pageName == 'cdn'}" href="#/contentProvider/{$ vm.cp.id $}/cdn_prefix">Cdn Prexix</a>
+ </li>
+ <li>
+ <a class="btn" ng-class="{'btn-primary': vm.pageName == 'server'}" href="#/contentProvider/{$ vm.cp.id $}/origin_server">Origin Server</a>
+ </li>
+ <li>
+ <a class="btn" ng-class="{'btn-primary': vm.pageName == 'user'}" href="#/contentProvider/{$ vm.cp.id $}/users">Users</a>
+ </li>
+</ul>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/templates/cp_user.html b/xos/core/xoslib/xos-builder/src/templates/cp_user.html
new file mode 100644
index 0000000..b35c2e9
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/templates/cp_user.html
@@ -0,0 +1,51 @@
+<div class="row-fluid">
+ <div class="span6">
+ <h1>{$ vm.cp.humanReadableName $}</h1>
+ </div>
+ <div class="span6 text-right">
+ <cp-actions id="vm.cp.id"></cp-actions>
+ </div>
+</div>
+<hr>
+<div class="row-fluid">
+ <div class="span2">
+ <div ng-include="'../../static/templates/contentProvider/cp_side_nav.html'"></div>
+ </div>
+ <div class="span10">
+ <div ng-repeat="item in vm.cp.users" class="well">
+ <div class="row-fluid">
+ <div class="span3">
+ {{item.firstname}}
+ </div>
+ <div class="span3">
+ {{item.lastname}}
+ </div>
+ <div class="span4">
+ {{item.email}}
+ </div>
+ <div class="span2">
+ <a ng-click="vm.removeUserFromCp(item)" class="btn btn-danger pull-right">
+ <i class="icon icon-remove"></i>
+ </a>
+ </div>
+ </div>
+ </div>
+ <hr>
+ <form ng-submit="vm.saveContentProvider(vm.cp)">
+ <div class="row-fluid">
+ <div class="span8">
+ <label>Select user:</label>
+ <select ng-model="vm.user" ng-options="u as u.username for u in vm.users" ng-change="vm.addUserToCp(vm.user)"></select>
+ </div>
+ <div class="span4 text-right">
+ <button class="btn btn-success margin-wells">
+ Save
+ </button>
+ </div>
+ </div>
+ </form>
+ <div class="alert" ng-show="vm.result" ng-class="{'alert-success': vm.result.status === 1,'alert-error': vm.result.status === 0}">
+ {$ vm.result.msg $}
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/src/xosContentProvider.js b/xos/core/xoslib/xos-builder/src/xosContentProvider.js
new file mode 100644
index 0000000..632ba5b
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/src/xosContentProvider.js
@@ -0,0 +1,393 @@
+/* global angular */
+/* eslint-disable dot-location*/
+
+// TODO
+// - Add Cache
+// - Refactor routing with ui.router and child views (share the navigation and header)
+// - Add Eslint
+// - Add Es6 (Babel) and a build script
+// - Autogenerate ngResource from swagger definition json
+
+angular.module('xos.contentProviderApp', [
+ 'ngResource',
+ 'ngRoute',
+ 'ngCookies',
+ 'ngLodash'
+])
+.config(function($interpolateProvider, $routeProvider, $resourceProvider){
+ $interpolateProvider.startSymbol('{$');
+ $interpolateProvider.endSymbol('$}');
+
+ // NOTE http://www.masnun.com/2013/09/18/django-rest-framework-angularjs-resource-trailing-slash-problem.html
+ $resourceProvider.defaults.stripTrailingSlashes = false;
+
+ $routeProvider
+ .when('/', {
+ template: '<content-provider-list></content-provider-list>',
+ })
+ .when('/contentProvider/:id?', {
+ template: '<content-provider-detail></content-provider-detail>'
+ })
+ .when('/contentProvider/:id/cdn_prefix', {
+ template: '<content-provider-cdn></content-provider-cdn>'
+ })
+ .when('/contentProvider/:id/origin_server', {
+ template: '<content-provider-server></content-provider-server>'
+ })
+ .when('/contentProvider/:id/users', {
+ template: '<content-provider-users></content-provider-users>'
+ })
+ .otherwise('/');
+})
+.config(function($httpProvider){
+
+ // add X-CSRFToken header for update, create, delete (!GET)
+ $httpProvider.interceptors.push('SetCSRFToken');
+})
+.factory('SetCSRFToken', function($cookies){
+ return {
+ request: function(request){
+
+ // if request is not HTML
+ if(request.url.indexOf('.html') === -1){
+ request.url += '?no_hyperlinks=1';
+ }
+
+ if(request.method !== 'GET'){
+ // request.headers['X-CSRFToken'] = $cookies.get('csrftoken');
+ request.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
+ }
+ return request;
+ }
+ };
+})
+.service('ContentProvider', function($resource){
+ return $resource('/hpcapi/contentproviders/:id/', {id: '@id'}, {
+ 'update': {method: 'PUT'}
+ });
+})
+.service('ServiceProvider', function($resource){
+ return $resource('/hpcapi/serviceproviders/:id/', {id: '@id'});
+})
+.service('CdnPrefix', function($resource){
+ return $resource('/hpcapi/cdnprefixs/:id/', {id: '@id'});
+})
+.service('OriginServer', function($resource){
+ return $resource('/hpcapi/originservers/:id/', {id: '@id'});
+})
+.service('User', function($resource){
+ return $resource('/xos/users/:id/', {id: '@id'});
+})
+.directive('cpActions', function(ContentProvider, $location){
+ return {
+ restrict: 'E',
+ scope: {
+ id: '=id',
+ },
+ bindToController: true,
+ controllerAs: 'vm',
+ templateUrl: '../../static/templates/contentProvider/cp_actions.html',
+ controller: function(){
+ this.deleteCp = function(id){
+ ContentProvider.delete({id: id}).$promise
+ .then(function(){
+ $location.url('/');
+ });
+ };
+ }
+ };
+})
+.directive('contentProviderList', function(ContentProvider, lodash){
+ return {
+ restrict: 'E',
+ controllerAs: 'vm',
+ scope: {},
+ templateUrl: '../../static/templates/contentProvider/cp_list.html',
+ controller: function(){
+ var _this = this;
+
+ ContentProvider.query().$promise
+ .then(function(cp){
+ _this.contentProviderList = cp;
+ })
+ .catch(function(e){
+ throw new Error(e);
+ });
+
+ this.deleteCp = function(id){
+ ContentProvider.delete({id: id}).$promise
+ .then(function(){
+ lodash.remove(_this.contentProviderList, {id: id});
+ });
+ };
+ }
+ };
+})
+.directive('contentProviderDetail', function(ContentProvider, ServiceProvider, $routeParams, $location){
+ return {
+ restrict: 'E',
+ controllerAs: 'vm',
+ scope: {},
+ templateUrl: '../../static/templates/contentProvider/cp_detail.html',
+ controller: function(){
+ this.pageName = 'detail';
+ var _this = this;
+
+ if($routeParams.id){
+ ContentProvider.get({id: $routeParams.id}).$promise
+ .then(function(cp){
+ _this.cp = cp;
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ }
+ else{
+ _this.cp = new ContentProvider();
+ }
+
+ ServiceProvider.query().$promise
+ .then(function(sp){
+ _this.sp = sp;
+ });
+
+ this.saveContentProvider = function(cp){
+ var p, isNew = false;
+
+ if(cp.id){
+ p = cp.$update();
+ }
+ else{
+ isNew = true;
+ cp.name = cp.humanReadableName;
+ p = cp.$save();
+ }
+
+ p.then(function(res){
+ _this.result = {
+ status: 1,
+ msg: 'Content Provider Saved'
+ };
+ if(isNew){
+ $location.url('contentProvider/' + res.id + '/');
+ }
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+ }
+ };
+})
+.directive('contentProviderCdn', function($routeParams, CdnPrefix, ContentProvider, lodash){
+ return{
+ restrict: 'E',
+ controllerAs: 'vm',
+ scope: {},
+ templateUrl: '../../static/templates/contentProvider/cp_cdn_prefix.html',
+ controller: function(){
+ var _this = this;
+
+ this.pageName = 'cdn';
+
+ if($routeParams.id){
+ ContentProvider.get({id: $routeParams.id}).$promise
+ .then(function(cp){
+ _this.cp = cp;
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ }
+
+ CdnPrefix.query().$promise
+ .then(function(prf){
+ _this.prf = prf;
+ // set the active CdnPrefix for this contentProvider
+ _this.cp_prf = lodash.where(prf, {contentProvider: parseInt($routeParams.id)});
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+
+ this.addPrefix = function(prf){
+ prf.contentProvider = $routeParams.id;
+
+ var item = new CdnPrefix(prf);
+
+ item.$save()
+ .then(function(res){
+ _this.cp_prf.push(res);
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+
+ this.removePrefix = function(item){
+ item.$delete()
+ .then(function(){
+ lodash.remove(_this.cp_prf, item);
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+ }
+ };
+})
+.directive('contentProviderServer', function($routeParams, OriginServer, ContentProvider, lodash){
+ return{
+ restrict: 'E',
+ controllerAs: 'vm',
+ scope: {},
+ templateUrl: '../../static/templates/contentProvider/cp_origin_server.html',
+ controller: function(){
+ this.pageName = 'server';
+ this.protocols = {'http': 'HTTP', 'rtmp': 'RTMP', 'rtp': 'RTP','shout': 'SHOUTcast'};
+
+ var _this = this;
+
+ if($routeParams.id){
+ ContentProvider.get({id: $routeParams.id}).$promise
+ .then(function(cp){
+ _this.cp = cp;
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ }
+
+ OriginServer.query({contentProvider: $routeParams.id}).$promise
+ .then(function(cp_os){
+ _this.cp_os = cp_os;
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+
+ this.addOrigin = function(os){
+ os.contentProvider = $routeParams.id;
+
+ var item = new OriginServer(os);
+
+ item.$save()
+ .then(function(res){
+ _this.cp_os.push(res);
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+
+ this.removeOrigin = function(item){
+ item.$delete()
+ .then(function(){
+ lodash.remove(_this.cp_os, item);
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+ }
+ };
+})
+.directive('contentProviderUsers', function($routeParams, ContentProvider, User, lodash){
+ return{
+ restrict: 'E',
+ controllerAs: 'vm',
+ scope: {},
+ templateUrl: '../../static/templates/contentProvider/cp_user.html',
+ controller: function(){
+ var _this = this;
+
+ this.pageName = 'user';
+
+ this.cp_users = [];
+
+ if($routeParams.id){
+ User.query().$promise
+ .then(function(users){
+ _this.users = users;
+ return ContentProvider.get({id: $routeParams.id}).$promise;
+ })
+ .then(function(res){
+ res.users = _this.populateUser(res.users, _this.users);
+ return res;
+ })
+ .then(function(cp){
+ _this.cp = cp;
+ }).catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ }
+
+ this.populateUser = function(ids, list){
+ for(var i = 0; i < ids.length; i++){
+ ids[i] = lodash.find(list, {id: ids[i]});
+ }
+ return ids;
+ };
+
+ this.addUserToCp = function(user){
+ _this.cp.users.push(user);
+ };
+
+ this.removeUserFromCp = function(user){
+ lodash.remove(_this.cp.users, user);
+ };
+
+ this.saveContentProvider = function(cp){
+
+ // flatten the user to id of array
+ cp.users = lodash.pluck(cp.users, 'id');
+
+ cp.$update()
+ .then(function(res){
+
+ _this.cp.users = _this.populateUser(res.users, _this.users);
+
+ _this.result = {
+ status: 1,
+ msg: 'Content Provider Saved'
+ };
+
+ })
+ .catch(function(e){
+ _this.result = {
+ status: 0,
+ msg: e.data.detail
+ };
+ });
+ };
+ }
+ };
+});
\ No newline at end of file