aboutsummaryrefslogtreecommitdiffstats
path: root/moon_gui/static/app
diff options
context:
space:
mode:
Diffstat (limited to 'moon_gui/static/app')
-rwxr-xr-xmoon_gui/static/app/authentication/authentication.controller.js58
-rwxr-xr-xmoon_gui/static/app/authentication/authentication.tpl.html28
-rwxr-xr-xmoon_gui/static/app/common/404/404.tpl.html3
-rwxr-xr-xmoon_gui/static/app/common/compatibility/compatibility.tpl.html26
-rwxr-xr-xmoon_gui/static/app/common/footer/footer.controller.js54
-rwxr-xr-xmoon_gui/static/app/common/footer/footer.tpl.html7
-rwxr-xr-xmoon_gui/static/app/common/header/header.controller.js56
-rwxr-xr-xmoon_gui/static/app/common/header/header.tpl.html52
-rwxr-xr-xmoon_gui/static/app/common/loader/loader.dir.js19
-rwxr-xr-xmoon_gui/static/app/common/loader/loader.tpl.html1
-rwxr-xr-xmoon_gui/static/app/common/waiting/waiting.tpl.html15
-rwxr-xr-xmoon_gui/static/app/dashboard/dashboard.tpl.html14
-rwxr-xr-xmoon_gui/static/app/logs/logs.controller.js16
-rwxr-xr-xmoon_gui/static/app/logs/logs.tpl.html3
-rwxr-xr-xmoon_gui/static/app/model/action/model-add.tpl.html66
-rwxr-xr-xmoon_gui/static/app/model/action/model-delete.tpl.html39
-rwxr-xr-xmoon_gui/static/app/model/action/model-view.tpl.html41
-rwxr-xr-xmoon_gui/static/app/model/action/model.controller.add.js71
-rwxr-xr-xmoon_gui/static/app/model/action/model.controller.delete.js72
-rwxr-xr-xmoon_gui/static/app/model/action/model.controller.view.js53
-rwxr-xr-xmoon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html99
-rwxr-xr-xmoon_gui/static/app/model/edit/metadata/metadata-list.tpl.html491
-rwxr-xr-xmoon_gui/static/app/model/edit/metadata/metadata.edit.dir.js332
-rwxr-xr-xmoon_gui/static/app/model/edit/metadata/metadata.list.dir.js372
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html50
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html102
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html35
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js99
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js213
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js74
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html67
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html62
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js49
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js98
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/metarules-list.tpl.html138
-rwxr-xr-xmoon_gui/static/app/model/edit/metarules/metarules.list.dir.js240
-rwxr-xr-xmoon_gui/static/app/model/edit/model-edit-basic.tpl.html65
-rwxr-xr-xmoon_gui/static/app/model/edit/model-edit.tpl.html70
-rwxr-xr-xmoon_gui/static/app/model/edit/model.controller.edit.js61
-rwxr-xr-xmoon_gui/static/app/model/edit/model.edit.basic.dir.js97
-rwxr-xr-xmoon_gui/static/app/model/model-list.tpl.html123
-rwxr-xr-xmoon_gui/static/app/model/model.controller.list.js195
-rw-r--r--moon_gui/static/app/moon.constants.js79
-rwxr-xr-xmoon_gui/static/app/moon.module.js362
-rwxr-xr-xmoon_gui/static/app/pdp/action/pdp-add.tpl.html88
-rwxr-xr-xmoon_gui/static/app/pdp/action/pdp-delete.tpl.html35
-rwxr-xr-xmoon_gui/static/app/pdp/action/pdp.controller.add.js108
-rwxr-xr-xmoon_gui/static/app/pdp/action/pdp.controller.delete.js66
-rwxr-xr-xmoon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html65
-rwxr-xr-xmoon_gui/static/app/pdp/edit/pdp-edit.tpl.html64
-rwxr-xr-xmoon_gui/static/app/pdp/edit/pdp.controller.edit.js50
-rwxr-xr-xmoon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js97
-rwxr-xr-xmoon_gui/static/app/pdp/pdp-list.tpl.html133
-rwxr-xr-xmoon_gui/static/app/pdp/pdp.controller.list.js284
-rwxr-xr-xmoon_gui/static/app/policy/action/mapping/policy-map.tpl.html64
-rwxr-xr-xmoon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html33
-rwxr-xr-xmoon_gui/static/app/policy/action/mapping/policy.controller.map.js106
-rwxr-xr-xmoon_gui/static/app/policy/action/mapping/policy.controller.unmap.js74
-rwxr-xr-xmoon_gui/static/app/policy/action/policy-add.tpl.html113
-rwxr-xr-xmoon_gui/static/app/policy/action/policy-delete.tpl.html40
-rwxr-xr-xmoon_gui/static/app/policy/action/policy.controller.add.js113
-rwxr-xr-xmoon_gui/static/app/policy/action/policy.controller.delete.js69
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/assignments/assignments-edit.tpl.html165
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html335
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/assignments/assignments.edit.dir.js439
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js393
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/data/data-edit.tpl.html110
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html390
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js260
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/data/data.list.dir.js293
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/perimeter/perimeter-edit.tpl.html166
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html240
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/perimeter/perimeter.edit.dir.js437
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js284
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/rules/rules-edit.tpl.html341
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html134
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/rules/rules.edit.dir.js537
-rwxr-xr-xmoon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js302
-rwxr-xr-xmoon_gui/static/app/policy/edit/policy-edit-basic.tpl.html89
-rwxr-xr-xmoon_gui/static/app/policy/edit/policy-edit.tpl.html202
-rwxr-xr-xmoon_gui/static/app/policy/edit/policy.controller.edit.js74
-rwxr-xr-xmoon_gui/static/app/policy/edit/policy.edit.basic.dir.js134
-rwxr-xr-xmoon_gui/static/app/policy/policy-list.tpl.html131
-rwxr-xr-xmoon_gui/static/app/policy/policy-mapped-list.tpl.html88
-rwxr-xr-xmoon_gui/static/app/policy/policy.controller.list.js175
-rwxr-xr-xmoon_gui/static/app/policy/policy.mapped.list.dir.js202
-rwxr-xr-xmoon_gui/static/app/project/action/mapping/project-map.tpl.html62
-rwxr-xr-xmoon_gui/static/app/project/action/mapping/project-unmap.tpl.html33
-rwxr-xr-xmoon_gui/static/app/project/action/mapping/project.controller.map.js107
-rwxr-xr-xmoon_gui/static/app/project/action/mapping/project.controller.unmap.js74
-rwxr-xr-xmoon_gui/static/app/project/action/project-add.tpl.html89
-rwxr-xr-xmoon_gui/static/app/project/action/project-delete.tpl.html45
-rwxr-xr-xmoon_gui/static/app/project/action/project-view.tpl.html194
-rwxr-xr-xmoon_gui/static/app/project/action/project.controller.add.js78
-rwxr-xr-xmoon_gui/static/app/project/action/project.controller.delete.js134
-rwxr-xr-xmoon_gui/static/app/project/action/project.controller.view.js216
-rwxr-xr-xmoon_gui/static/app/project/project-list.tpl.html157
-rwxr-xr-xmoon_gui/static/app/project/project.controller.list.js310
-rwxr-xr-xmoon_gui/static/app/services/gui/alert.service.js39
-rwxr-xr-xmoon_gui/static/app/services/gui/browser.service.js47
-rwxr-xr-xmoon_gui/static/app/services/gui/form.service.js47
-rwxr-xr-xmoon_gui/static/app/services/gui/menu.service.js49
-rwxr-xr-xmoon_gui/static/app/services/gui/security.pipeline.service.js29
-rwxr-xr-xmoon_gui/static/app/services/gui/util.service.js66
-rwxr-xr-xmoon_gui/static/app/services/gui/version.service.js27
-rwxr-xr-xmoon_gui/static/app/services/moon/model/model.service.js105
-rwxr-xr-xmoon_gui/static/app/services/moon/pdp.service.js128
-rwxr-xr-xmoon_gui/static/app/services/moon/policy/parameters/assignements.service.js133
-rwxr-xr-xmoon_gui/static/app/services/moon/policy/parameters/data.service.js249
-rwxr-xr-xmoon_gui/static/app/services/moon/policy/parameters/perimeter.service.js460
-rw-r--r--moon_gui/static/app/services/moon/policy/parameters/rule.service.js49
-rwxr-xr-xmoon_gui/static/app/services/moon/policy/parameters/rules.service.js56
-rwxr-xr-xmoon_gui/static/app/services/moon/policy/policy.service.js108
-rwxr-xr-xmoon_gui/static/app/services/moon/rule/metadata.service.js354
-rwxr-xr-xmoon_gui/static/app/services/moon/rule/metarule.service.js208
-rwxr-xr-xmoon_gui/static/app/services/partner/authentication.service.js106
-rwxr-xr-xmoon_gui/static/app/services/partner/nova.service.js35
-rwxr-xr-xmoon_gui/static/app/services/partner/project.service.js60
118 files changed, 15644 insertions, 0 deletions
diff --git a/moon_gui/static/app/authentication/authentication.controller.js b/moon_gui/static/app/authentication/authentication.controller.js
new file mode 100755
index 00000000..ce38bc5f
--- /dev/null
+++ b/moon_gui/static/app/authentication/authentication.controller.js
@@ -0,0 +1,58 @@
+/**
+ * @author Samy Abdallah
+ */
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('AuthenticationController', AuthenticationController);
+
+ AuthenticationController.$inject = ['authenticationService', '$translate', 'alertService', '$state', '$rootScope'];
+
+ function AuthenticationController(authenticationService, $translate, alertService, $state, $rootScope) {
+
+ var vm = this;
+
+ vm.login = login;
+ vm.loading = false;
+
+ vm.credentials = {
+ username : '',
+ password : ''
+ };
+
+ activate();
+
+ function activate(){
+ if($rootScope.connected){
+ $state.go('moon.dashboard');
+ }
+ }
+
+ function login(){
+ vm.loading = true;
+ authenticationService.Login(vm.credentials, loginSuccess, loginError);
+ }
+
+ function loginSuccess() {
+
+ $translate('moon.login.success').then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ $state.go('moon.dashboard');
+ vm.loading = false;
+ });
+
+ }
+
+ function loginError(reason) {
+
+ $translate('moon.login.error', { errorCode: reason.status }).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ vm.loading = false;
+ });
+
+ }
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/authentication/authentication.tpl.html b/moon_gui/static/app/authentication/authentication.tpl.html
new file mode 100755
index 00000000..77d1646b
--- /dev/null
+++ b/moon_gui/static/app/authentication/authentication.tpl.html
@@ -0,0 +1,28 @@
+<div class="col-md-6 col-md-offset-3">
+
+ <h2 data-translate="moon.login.titlePage">Login</h2>
+
+ <form name="form" ng-submit="form.$valid && auth.login()" novalidate>
+
+ <div class="form-group" ng-class="{ 'has-error': form.$submitted && form.username.$invalid }">
+ <label for="username" data-translate="moon.login.username" >Username</label>
+ <input type="text" id="username" name="username" class="form-control" ng-model="auth.credentials.username" required />
+ <div ng-messages="form.$submitted && form.username.$error" class="help-block">
+ <div ng-message="required" data-translate="moon.login.check.username.required" >Username is required</div>
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{ 'has-error': form.$submitted && form.password.$invalid }">
+ <label for="password" data-translate="moon.login.password" >Password</label>
+ <input type="password" id="password" name="password" class="form-control" ng-model="auth.credentials.password" required />
+ <div ng-messages="form.$submitted && form.password.$error" class="help-block">
+ <div ng-message="required" data-translate="moon.login.check.password.required">Password is required</div>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <button ng-disabled="auth.loading" class="btn btn-primary" data-translate="moon.login.login" >Login</button>
+ <img ng-if="auth.loading" src="assets/img/ajax-loader.gif" />
+ </div>
+ </form>
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/common/404/404.tpl.html b/moon_gui/static/app/common/404/404.tpl.html
new file mode 100755
index 00000000..61e0420c
--- /dev/null
+++ b/moon_gui/static/app/common/404/404.tpl.html
@@ -0,0 +1,3 @@
+<div data-translate="moon.global.404">Not found!</div>
+
+<div> Go <a href="" ui-sref="moon.project.list">Projects ?</a></div> \ No newline at end of file
diff --git a/moon_gui/static/app/common/compatibility/compatibility.tpl.html b/moon_gui/static/app/common/compatibility/compatibility.tpl.html
new file mode 100755
index 00000000..0e32dc4f
--- /dev/null
+++ b/moon_gui/static/app/common/compatibility/compatibility.tpl.html
@@ -0,0 +1,26 @@
+<div class="modal" tabindex="-1" data-role="modalCompatibility">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.compatibility.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <span data-translate="moon.compatibility.content"></span>
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+ <button ng-click="$hide()" class="btn btn-default" data-translate="moon.compatibility.close">Close</button>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/common/footer/footer.controller.js b/moon_gui/static/app/common/footer/footer.controller.js
new file mode 100755
index 00000000..d7506840
--- /dev/null
+++ b/moon_gui/static/app/common/footer/footer.controller.js
@@ -0,0 +1,54 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('FooterController', FooterController);
+
+ FooterController.$inject = ['$modal', 'versionService'];
+
+ function FooterController($modal, versionService) {
+
+ var footer = this;
+
+ footer.version = null;
+ footer.browsersModal = null;
+ footer.showBrowsersCompliance = showBrowsersCompliance;
+
+ newBrowsersModal();
+ currentVersion();
+
+ function newBrowsersModal() {
+
+ footer.browsersModal = $modal({ template: 'html/common/compatibility/compatibility.tpl.html', show: false });
+
+ return footer.browsersModal;
+
+ }
+
+ function showBrowsersCompliance() {
+ footer.browsersModal.$promise.then(footer.browsersModal.show);
+ }
+
+ function currentVersion() {
+
+ var _self = footer;
+
+ versionService.version.get().$promise.then(function(data) {
+
+ _self.version = (data.version) ? data.version : 'SNAPSHOT';
+
+ return _self.version;
+
+ });
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/common/footer/footer.tpl.html b/moon_gui/static/app/common/footer/footer.tpl.html
new file mode 100755
index 00000000..aacb392d
--- /dev/null
+++ b/moon_gui/static/app/common/footer/footer.tpl.html
@@ -0,0 +1,7 @@
+<div class="container footer" ng-controller="FooterController as footer">
+ <div class="row">
+ <div class="pull-right">
+ <span>v<span ng-bind="footer.version"></span></span> - <a href="" ng-click="footer.showBrowsersCompliance()" data-translate="moon.compatibility.label">browser compatibility</a>
+ </div>
+ </div>
+</div>
diff --git a/moon_gui/static/app/common/header/header.controller.js b/moon_gui/static/app/common/header/header.controller.js
new file mode 100755
index 00000000..13ef4d6f
--- /dev/null
+++ b/moon_gui/static/app/common/header/header.controller.js
@@ -0,0 +1,56 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('HeaderController', HeaderController);
+
+ HeaderController.$inject = ['$translate', 'menuService', 'authenticationService', 'alertService'];
+
+ function HeaderController($translate, menuService, authenticationService, alertService) {
+
+ var header = this;
+
+ /*
+ *
+ */
+
+ header.isProjectTabActive = menuService.isProjectTabActive;
+ header.isPDPTabActive = menuService.isPDPTabActive;
+ header.isLogsTabActive = menuService.isLogsTabActive;
+ header.isPolicyTabActive = menuService.isPolicyTabActive;
+ header.isModelTabActive = menuService.isModelTabActive;
+ header.changeLocale = changeLocale;
+ header.logout = logout;
+ header.currentLanguage = $translate.use();
+
+ header.getUser = authenticationService.GetUser;
+
+ /*
+ *
+ */
+
+ function changeLocale(localeKey, event) {
+
+ event.preventDefault();
+ $translate.use(localeKey);
+ $translate.preferredLanguage(localeKey);
+ header.currentLanguage = localeKey;
+
+ }
+
+ function logout(){
+
+ authenticationService.Logout();
+ $translate('moon.logout.success').then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ }
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/common/header/header.tpl.html b/moon_gui/static/app/common/header/header.tpl.html
new file mode 100755
index 00000000..f703fa79
--- /dev/null
+++ b/moon_gui/static/app/common/header/header.tpl.html
@@ -0,0 +1,52 @@
+<div class="container banner" ng-controller="HeaderController as header">
+
+ <div class="row">
+
+ <div class="col-md-3 sub-banner">
+ <a ui-sref="moon.dashboard"><img src="assets/img/logo-orange.gif" alt="Orange" /> </a>
+ <img src="assets/img/logo-openstack.png" alt="OpenStack" />
+ </div>
+
+ <div class="col-md-6 center-block">
+ <h1 data-translate="moon.global.applicationName">Moon UI</h1>
+ </div>
+
+ <div class="col-md-3">
+
+ <span class="pull-right">
+
+ <a href="" ng-click="header.changeLocale('fr', $event)" ng-class="{'strong' : header.currentLanguage === 'fr'}"><img src="assets/img/arrow-link.gif" alt="fr_" />fr</a>
+ <a href="" ng-click="header.changeLocale('en', $event)" ng-class="{'strong' : header.currentLanguage === 'en'}"><img src="assets/img/arrow-link.gif" alt="en_" />en</a>
+
+ <a href="" ng-if="connected" ng-click="header.logout()" class="left30">
+ <span class="glyphicon glyphicon-log-out"></span>
+ <span data-translate="moon.logout.title">Logout</span>(<span ng-bind="header.getUser().token.user.name"></span>)
+ </a>
+
+ <a href="" ng-if="!connected" class="left30">
+ <span class="glyphicon glyphicon-log-in"></span>
+ <span data-translate="moon.login.title">Login</span>
+ </a>
+ </span>
+
+ </div>
+
+ </div>
+
+ <div class="row">
+ <toaster-container toaster-options="{'position-class': 'toast-top-right', 'close-button': true}"></toaster-container>
+ </div>
+
+ <div class="row" ng-if="connected">
+
+ <ul class="nav nav-tabs">
+ <li ng-class="{active: header.isProjectTabActive()}"><a ui-sref="moon.project.list" data-translate="moon.menu.project">Projects</a></li>
+ <li ng-class="{active: header.isModelTabActive()}"><a ui-sref="moon.model.list" data-translate="moon.menu.model">Models</a></li>
+ <li ng-class="{active: header.isPolicyTabActive()}"><a ui-sref="moon.policy.list" data-translate="moon.menu.policy">Policy</a></li>
+ <li ng-class="{active: header.isPDPTabActive()}"><a ui-sref="moon.pdp.list" data-translate="moon.menu.pdp">PDP</a></li>
+ <!--<li ng-class="{active: header.isLogsTabActive()}"><a ui-sref="moon.logs" data-translate="moon.menu.logs">Logs</a></li>-->
+ </ul>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/common/loader/loader.dir.js b/moon_gui/static/app/common/loader/loader.dir.js
new file mode 100755
index 00000000..ba40c121
--- /dev/null
+++ b/moon_gui/static/app/common/loader/loader.dir.js
@@ -0,0 +1,19 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonLoader', moonLoader);
+
+ moonLoader.$inject = [];
+
+ function moonLoader() {
+
+ return {
+ templateUrl : 'html/common/loader/loader.tpl.html',
+ restrict : 'E'
+ };
+ }
+
+})();
diff --git a/moon_gui/static/app/common/loader/loader.tpl.html b/moon_gui/static/app/common/loader/loader.tpl.html
new file mode 100755
index 00000000..51da439f
--- /dev/null
+++ b/moon_gui/static/app/common/loader/loader.tpl.html
@@ -0,0 +1 @@
+<img src="assets/img/ajax-loader.gif" /> \ No newline at end of file
diff --git a/moon_gui/static/app/common/waiting/waiting.tpl.html b/moon_gui/static/app/common/waiting/waiting.tpl.html
new file mode 100755
index 00000000..6c042635
--- /dev/null
+++ b/moon_gui/static/app/common/waiting/waiting.tpl.html
@@ -0,0 +1,15 @@
+<div class="modal" tabindex="-1" data-role="modalWaiting">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-body centered">
+ <img src="assets/img/ajax-waiting.gif" />
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/dashboard/dashboard.tpl.html b/moon_gui/static/app/dashboard/dashboard.tpl.html
new file mode 100755
index 00000000..67184bcc
--- /dev/null
+++ b/moon_gui/static/app/dashboard/dashboard.tpl.html
@@ -0,0 +1,14 @@
+<div class="container">
+
+ <div class="row">
+
+ <h1 data-translate="moon.dashboard.content">Moon:Software-Defined Security Framework</h1>
+ </div>
+
+ <div class="row">
+
+ <img src="assets/img/et.jpg" alt="ET" class="img-responsive img-dashboard"/>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/logs/logs.controller.js b/moon_gui/static/app/logs/logs.controller.js
new file mode 100755
index 00000000..e48e2b8b
--- /dev/null
+++ b/moon_gui/static/app/logs/logs.controller.js
@@ -0,0 +1,16 @@
+/**
+ * @author Samy Abdallah
+ */
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('LogsController', LogsController);
+
+ function LogsController() {
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/logs/logs.tpl.html b/moon_gui/static/app/logs/logs.tpl.html
new file mode 100755
index 00000000..fecc0289
--- /dev/null
+++ b/moon_gui/static/app/logs/logs.tpl.html
@@ -0,0 +1,3 @@
+<div class="container">
+ Logs
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/action/model-add.tpl.html b/moon_gui/static/app/model/action/model-add.tpl.html
new file mode 100755
index 00000000..dee53a97
--- /dev/null
+++ b/moon_gui/static/app/model/action/model-add.tpl.html
@@ -0,0 +1,66 @@
+<div ng-controller="ModelAddController as add" class="modal" tabindex="-1" data-role="modalAddModel">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.add.title"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="add.form">
+
+ <div class="form-group" ng-class="{'has-error': add.form.name.$invalid && add.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.model.add.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="add.model.name" required />
+
+ <div class="help-block" ng-show="add.form.name.$dirty && add.form.name.$invalid">
+ <small class="error" ng-show="add.form.name.$error.required" data-translate="moon.model.add.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.model.add.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="add.model.description"></textarea>
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.model.add.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="add.loading" ng-click="add.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.model.add.action.create">Create Model</span>
+ </a>
+ <moon-loader ng-if="add.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/model/action/model-delete.tpl.html b/moon_gui/static/app/model/action/model-delete.tpl.html
new file mode 100755
index 00000000..cde16d0e
--- /dev/null
+++ b/moon_gui/static/app/model/action/model-delete.tpl.html
@@ -0,0 +1,39 @@
+<div ng-controller="ModelDeleteController as del" class="modal" tabindex="-1" data-role="modalDeleteModel">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.remove.title"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <p><span data-translate="moon.model.remove.content.query" data-translate-values="{ modelName: del.model.name }"></span></p>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.model.remove.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="del.loading" ng-click="del.remove()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.model.remove.action.delete">Delete</span>
+ </a>
+
+ <moon-loader ng-if="del.loading" ></moon-loader>
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/action/model-view.tpl.html b/moon_gui/static/app/model/action/model-view.tpl.html
new file mode 100755
index 00000000..46c295c7
--- /dev/null
+++ b/moon_gui/static/app/model/action/model-view.tpl.html
@@ -0,0 +1,41 @@
+<div ng-controller="ModelViewController as view" class="modal" tabindex="-1" data-role="modalViewProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.view.title" data-translate-values="{modelName: view.model.name}"></h4>
+ </div>
+ <div class="modal-body">
+ <dl class="dl-horizontal">
+ <dt data-translate="moon.model.view.id">Id</dt>
+ <dd ng-bind="view.model.id"></dd>
+ <dt data-translate="moon.model.view.name">Name</dt>
+ <dd ng-bind="view.model.name"></dd>
+ <dt data-translate="moon.model.view.description">Description</dt>
+ <dd ng-bind="view.model.description"></dd>
+ </dl>
+
+ <div ng-if="view.meta_rules_values">
+ <moon-meta-rules-list mapped-model="view.model" edit-mode="false"></moon-meta-rules-list>
+ </div>
+
+ <div ng-if="!view.meta_rules_values">
+ <moon-loader></moon-loader>
+ </div>
+
+ </div>
+
+ <div class="modal-footer top10">
+ <div class="btn-toolbar" style="float: right;">
+ <button ng-click="$hide()" class="btn btn-default" data-translate="moon.model.view.action.close">Close</button>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/model/action/model.controller.add.js b/moon_gui/static/app/model/action/model.controller.add.js
new file mode 100755
index 00000000..11d3abf4
--- /dev/null
+++ b/moon_gui/static/app/model/action/model.controller.add.js
@@ -0,0 +1,71 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelAddController', ModelAddController);
+
+ ModelAddController.$inject = ['$scope', 'modelService', 'alertService', '$translate', 'formService', 'utilService'];
+
+ function ModelAddController($scope, modelService, alertService, $translate, formService, utilService) {
+
+ var add = this;
+
+ /*
+ *
+ */
+
+ add.form = {};
+
+ add.loading = false;
+
+ add.model = { name: null, description: null, meta_rules : [] };
+
+ add.create = createModel;
+
+ function createModel() {
+
+ if(formService.isInvalid(add.form)) {
+
+ formService.checkFieldsValidity(add.form);
+
+ } else {
+
+ add.loading = true;
+
+ modelService.data.create({}, add.model, createSuccess, createError);
+
+ }
+
+ function createSuccess(data) {
+
+ var createdModel = utilService.transformOne(data, 'models');
+
+ $translate('moon.model.add.success', { modelName: createdModel.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:modelCreatedSuccess', createdModel);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.model.add.error', { modelName: add.model.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:modelCreatedError', add.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/action/model.controller.delete.js b/moon_gui/static/app/model/action/model.controller.delete.js
new file mode 100755
index 00000000..5d9dae1a
--- /dev/null
+++ b/moon_gui/static/app/model/action/model.controller.delete.js
@@ -0,0 +1,72 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelDeleteController', ModelDeleteController);
+
+ ModelDeleteController.$inject = ['$scope', '$translate', 'alertService', 'modelService'];
+
+ function ModelDeleteController($scope, $translate, alertService, modelService) {
+
+ var del = this;
+
+ /*
+ *
+ */
+
+ del.model = $scope.model;
+ del.loading = false;
+
+ del.remove = deleteModel;
+
+ activate();
+
+ /**
+ *
+ */
+
+ function activate(){
+
+ }
+
+
+ function deleteModel(){
+
+ del.loading = true;
+
+ modelService.delete(del.model, deleteSuccess, deleteError);
+
+ function deleteSuccess(data) {
+
+ $translate('moon.model.remove.success', { modelName: del.model.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:modelDeletedSuccess', del.model);
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.model.remove.error', { modelName: del.model.name, errorCode: reason.data.error.code, message : reason.data.error.message } ).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:modelDeletedError', del.model);
+
+ }
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/model/action/model.controller.view.js b/moon_gui/static/app/model/action/model.controller.view.js
new file mode 100755
index 00000000..7605eecf
--- /dev/null
+++ b/moon_gui/static/app/model/action/model.controller.view.js
@@ -0,0 +1,53 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelViewController', ModelViewController);
+
+ ModelViewController.$inject = ['$scope', 'metaRuleService'];
+
+ function ModelViewController($scope, metaRuleService) {
+
+ var view = this;
+
+ /*
+ *
+ */
+
+ view.model = $scope.model;
+
+ view.meta_rules_values = false;
+
+ activate();
+
+ function activate(){
+
+ if(view.model.meta_rules.length > 0 ){
+
+ findMetaRules();
+
+ }else{
+
+ view.meta_rules_values = [];
+
+ }
+
+ }
+
+ function findMetaRules(){
+
+ metaRuleService.findSomeWithMetaData(view.model.meta_rules).then(function(metaRules){
+
+ view.meta_rules_values = metaRules;
+
+ view.model.meta_rules_values = metaRules;
+
+ });
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html b/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html
new file mode 100755
index 00000000..2616be1c
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html
@@ -0,0 +1,99 @@
+<div>
+
+ <div class="col-md-4 col-sm-4 col-xs-4">
+ <a class="btn btn-primary" type="button" style="white-space: normal;" ng-click="edit.fromList = !edit.fromList">
+ <span ng-if="!edit.fromList" data-translate="moon.model.metadata.edit.action.list">Add from the list</span>
+ <span ng-if="edit.fromList" data-translate="moon.model.metadata.edit.action.new">Add a new Category</span>
+ </a>
+ </div>
+
+ <div class="col-md-8 col-sm-8 col-xs-8">
+
+ <form name="selectMetaData" ng-if="edit.fromList" class="form-horizontal" role="form" >
+
+ <div class="form-group" >
+
+ <ui-select ng-model="edit.selectedMetaData" name="object">
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="ametaData in edit.list">
+ <div ng-value="ametaData" ng-bind="ametaData.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-left col-md-4 col-sm-4 col-xs-4">
+
+ <a href="" ng-disabled="edit.loading || !edit.selectedMetaData" ng-click="edit.deleteMetaData()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.model.metadata.edit.action.delete">Delete</span>
+ </a>
+
+ </div>
+
+ <div class="pull-right col-md-7 col-md-offset-1 col-sm-7 col-sm-offset-1 col-xs-7 col-xs-offset-1 ">
+
+ <a href="" ng-disabled="edit.loading || !edit.selectedMetaData" ng-click="edit.addToMetaRule()" class="btn btn-warning" style="white-space: normal;">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.model.metadata.edit.action.add">Add the selected Category</span>
+ </a>
+
+ </div>
+
+ </div>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </form>
+
+ <form ng-if="!edit.fromList" class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.model.metadata.edit.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.metaData.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.model.metadata.edit.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.model.metadata.edit.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.metaData.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.model.metadata.edit.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html b/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html
new file mode 100755
index 00000000..30a42dbc
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html
@@ -0,0 +1,491 @@
+<div>
+ <!--
+ !shortDisplay allow to display more details than shortDisplay.
+ It will display panels row by row and each panels list have a table with more columns
+ -->
+ <div ng-if="!list.shortDisplay">
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.subject.title">List of associated Subject Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.id">Id</th>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ <th data-translate="moon.model.metadata.table.description">Description</th>
+ <th ng-if="list.editMode" data-translate="moon.model.metadata.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatSub"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatSub && list.getSubjectCategories().length > 0">
+ <tr ng-repeat="(key, value) in list.catSub">
+ <td ng-bind="value.id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td ng-if="list.editMode">
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapSub(value)">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+
+ <!--<div ng-if="!value.loader" class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.model.metadata.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapSub(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteSub(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.model.metadata.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>-->
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+
+ </tr>
+ </tbody>
+
+
+ <tbody ng-if="!list.loadingCatSub && list.catSub.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.subject.notFound">There is no Subjects</td>
+ <td></td>
+ <td></td>
+ <td ng-if="list.editMode"></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.subject.add.title">Add a Subject Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-meta-data-edit meta-rule="list.metaRule"
+ meta-data-type="list.typeOfSubject"></moon-meta-data-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.object.title">List associated of Object Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.id">Id</th>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ <th data-translate="moon.model.metadata.table.description">Description</th>
+ <th ng-if="list.editMode" data-translate="moon.model.metadata.table.action.title"></th>
+
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatObj"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatObj && list.catObj.length > 0">
+ <tr ng-repeat="(key, value) in list.catObj">
+ <td ng-bind="value.id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td ng-if="list.editMode">
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapObj(value)">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+
+
+ <!--<div ng-if="!value.loader" class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.model.metadata.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapObj(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteObj(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.model.metadata.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>-->
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingCatObj && list.catObj.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.object.notFound">There is no Objects</td>
+ <td></td>
+ <td></td>
+ <td ng-if="list.editMode"></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.object.add.title">Add an Object Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-meta-data-edit meta-rule="list.metaRule" meta-data-type="list.typeOfObject"></moon-meta-data-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.action.title">List associated of Action Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.id">Id</th>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ <th data-translate="moon.model.metadata.table.description">Description</th>
+ <th ng-if="list.editMode" data-translate="moon.model.metadata.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatAct"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatAct && list.catAct.length > 0">
+ <tr ng-repeat="(key, value) in list.catAct">
+ <td ng-bind="value.id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td ng-if="list.editMode">
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapAct(value)">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+
+ <!--<div ng-if="!value.loader" class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.model.metadata.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapAct(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metadata.action.remove">Remove</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteAct(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.model.metadata.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>-->
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingCatAct && list.catAct.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.action.notFound">There is no Actions</td>
+ <td></td>
+ <td></td>
+ <td ng-if="list.editMode"></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.action.add.title">Add an Action Category</h4>
+
+ </div>
+
+ <div class="panel-body">.
+
+ <moon-meta-data-edit meta-rule="list.metaRule" meta-data-type="list.typeOfAction"></moon-meta-data-edit>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <!--
+ !shortDisplay allow to display less details than shortDisplay.
+ It will display 3 panels on the same row, each panels have a table with on columns (name)
+ -->
+ <div ng-if="list.shortDisplay">
+
+ <div class="row">
+
+ <div class="col-md-4">
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.subject.title">List of associated Subject Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatSub"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatSub && list.getSubjectCategories().length > 0">
+ <tr ng-repeat="(key, value) in list.catSub">
+ <td ng-bind="value.name"></td>
+ </tr>
+ </tbody>
+
+
+ <tbody ng-if="!list.loadingCatSub && list.catSub.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.subject.notFound">There is no Subjects</td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="col-md-4">
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.object.title">List associated of Object Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatObj"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatObj && list.catObj.length > 0">
+ <tr ng-repeat="(key, value) in list.catObj">
+ <td ng-bind="value.name"></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingCatObj && list.catObj.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.object.notFound">There is no Objects</td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="col-md-4">
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.model.metadata.action.title">List associated of Action Categories</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.model.metadata.table.name">Name</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingCatAct"></moon-loader>
+
+ <tbody ng-if="!list.loadingCatAct && list.catAct.length > 0">
+ <tr ng-repeat="(key, value) in list.catAct">
+ <td ng-bind="value.name"></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingCatAct && list.catAct.length === 0">
+ <tr>
+ <td data-translate="moon.model.metadata.action.notFound">There is no Actions</td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js b/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js
new file mode 100755
index 00000000..10df83b0
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js
@@ -0,0 +1,332 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonMetaDataEdit', moonMetaDataEdit);
+
+ moonMetaDataEdit.$inject = [];
+
+ function moonMetaDataEdit() {
+
+ return {
+ templateUrl : 'html/model/edit/metadata/metadata-edit.tpl.html',
+ bindToController : true,
+ controller : moonMetaDataEditController,
+ controllerAs : 'edit',
+ scope : {
+ //Type can be 'ACTION', 'OBJECT', 'SUBJECT'
+ metaDataType: '=',
+ metaRule : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonMetaDataEditController', moonMetaDataEditController);
+
+ moonMetaDataEditController.$inject = ['$scope', 'metaDataService', 'META_DATA_CST', 'alertService',
+ '$translate', 'formService', 'metaRuleService', 'utilService'];
+
+ function moonMetaDataEditController($scope, metaDataService, META_DATA_CST, alertService,
+ $translate, formService, metaRuleService, utilService) {
+
+ var edit = this;
+
+ edit.metaDataType = $scope.edit.metaDataType;
+ edit.metaRule = $scope.edit.metaRule;
+
+ edit.fromList = true;
+
+ edit.laoading = false;
+
+ edit.form = {};
+
+ edit.metaData = { name: null, description: null};
+
+ edit.list = [];
+
+ edit.create = createMetaData;
+ edit.addToMetaRule = addToMetaRule;
+ edit.deleteMetaData = deleteMetaData;
+
+ activate();
+
+ /*
+ *
+ */
+
+ function activate(){
+
+ switch(edit.metaDataType){
+
+ case META_DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.findAllWithCallback(callBackList);
+ break;
+
+ case META_DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.findAllWithCallback(callBackList);
+ break;
+
+ case META_DATA_CST.TYPE.ACTION:
+
+ metaDataService.action.findAllWithCallback(callBackList);
+ break;
+
+ default :
+
+ edit.list = [];
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.list = list;
+
+ }
+
+ }
+
+ /**
+ * Add
+ */
+
+ function addToMetaRule(){
+
+ if(!edit.selectedMetaData){
+
+ return;
+
+ }
+
+ var metaRuleToSend = edit.metaRule;
+
+ switch(edit.metaDataType){
+
+ case META_DATA_CST.TYPE.SUBJECT:
+
+ metaRuleToSend.subject_categories.push(edit.selectedMetaData.id);
+ break;
+
+ case META_DATA_CST.TYPE.OBJECT:
+
+ metaRuleToSend.object_categories.push(edit.selectedMetaData.id);
+ break;
+
+ case META_DATA_CST.TYPE.ACTION:
+
+ metaRuleToSend.action_categories.push(edit.selectedMetaData.id);
+ break;
+ }
+
+ metaRuleService.update(metaRuleToSend, updateMetaRuleSuccess, updateMetaRuleError);
+
+ function updateMetaRuleSuccess(data){
+
+ $translate('moon.model.metarules.update.success', { metaRuleName: metaRuleToSend.name }).then( function(translatedValue) {
+
+ alertService.alertSuccess(translatedValue);
+
+ });
+
+ metaRuleToSend = utilService.transformOne(data, 'meta_rules');
+
+ $scope.$emit('event:updateMetaRuleFromMetaDataAddSuccess', metaRuleToSend);
+
+ stopLoading();
+
+ }
+
+ function updateMetaRuleError(reason){
+
+ $translate('moon.model.metarules.update.error', { metaRuleName: metaRuleToSend.name, reason: reason.message}).then( function(translatedValue) {
+
+ alertService.alertError(translatedValue);
+
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ /**
+ * Create
+ */
+
+ function createMetaData() {
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ } else {
+
+ startLoading();
+
+ var metaDataToSend = angular.copy(edit.metaData);
+
+ switch(edit.metaDataType){
+
+ case META_DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.add(metaDataToSend, createSuccess, createError);
+ break;
+
+ case META_DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.add(metaDataToSend, createSuccess, createError);
+ break;
+
+ case META_DATA_CST.TYPE.ACTION:
+
+ metaDataService.action.add(metaDataToSend, createSuccess, createError);
+ break;
+ }
+
+ }
+
+ function createSuccess(data) {
+
+ var created = {};
+
+ switch(edit.metaDataType){
+
+ case META_DATA_CST.TYPE.SUBJECT:
+
+ created = utilService.transformOne(data, 'subject_categories');
+ break;
+
+ case META_DATA_CST.TYPE.OBJECT:
+
+ created = utilService.transformOne(data, 'object_categories');
+ break;
+
+ case META_DATA_CST.TYPE.ACTION:
+
+ created = utilService.transformOne(data, 'action_categories');
+ break;
+ }
+
+ $translate('moon.model.metadata.edit.create.success', { name: created.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ stopLoading();
+
+ edit.list.push(created);
+
+ displayList();
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.model.metadata.edit.create.error', { name: metaDataToSend.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ function deleteMetaData(){
+
+ if(!edit.selectedMetaData){
+
+ return;
+
+ }
+
+ startLoading();
+
+ var metaDataToDelete = angular.copy(edit.selectedMetaData);
+
+ switch(edit.metaDataType){
+ case META_DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.delete(metaDataToDelete, deleteSuccess, deleteError);
+ break;
+
+ case META_DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.delete(metaDataToDelete, deleteSuccess, deleteError);
+ break;
+
+ case META_DATA_CST.TYPE.ACTION:
+
+ metaDataService.action.delete(metaDataToDelete, deleteSuccess, deleteError);
+ break;
+ }
+
+
+ function deleteSuccess(data) {
+
+ $translate('moon.model.metadata.edit.delete.success', { name: metaDataToDelete.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ metaRuleService.findOneWithMetaData(edit.metaRule.id).then( function(metaRule){
+
+ edit.metaRule = metaRule;
+
+ cleanSelectedValue();
+
+ activate();
+
+ stopLoading();
+
+ $scope.$emit('event:deleteMetaDataFromMetaDataAddSuccess', edit.metaRule);
+
+ });
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.model.metadata.edit.delete.error', { name: metaDataToDelete.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+ }
+
+ function cleanSelectedValue(){
+
+ delete edit.selectedMetaData;
+
+ }
+
+ function startLoading(){
+
+ edit.loading = true;
+
+ }
+
+ function stopLoading(){
+
+ edit.loading = false;
+
+ }
+
+ function displayList(){
+
+ edit.fromList = true;
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js b/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js
new file mode 100755
index 00000000..beb2ed86
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js
@@ -0,0 +1,372 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonMetaDataList', moonMetaDataList);
+
+ moonMetaDataList.$inject = [];
+
+ function moonMetaDataList() {
+
+ return {
+ templateUrl : 'html/model/edit/metadata/metadata-list.tpl.html',
+ bindToController : true,
+ controller : moonMetaDataListController,
+ controllerAs : 'list',
+ scope : {
+ metaRule: '=',
+ editMode: '=',
+ // shortDisplay : boolean value
+ shortDisplay: '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonMetaDataListController', moonMetaDataListController);
+
+ moonMetaDataListController.$inject = ['$scope', '$rootScope', 'metaDataService', '$translate', 'alertService', 'metaRuleService', 'META_DATA_CST', 'utilService'];
+
+ function moonMetaDataListController($scope, $rootScope, metaDataService, $translate, alertService, metaRuleService, META_DATA_CST, utilService){
+
+ var list = this;
+
+ list.metaRule = $scope.list.metaRule;
+ list.editMode = $scope.list.editMode;
+ list.shortDisplay = $scope.list.shortDisplay;
+
+ list.typeOfSubject = META_DATA_CST.TYPE.SUBJECT;
+ list.typeOfObject = META_DATA_CST.TYPE.OBJECT;
+ list.typeOfAction = META_DATA_CST.TYPE.ACTION;
+
+ list.unMapSub = unMapSub;
+ list.unMapObj = unMapObj;
+ list.unMapAct = unMapAct;
+
+ // list.deleteSub = deleteSub;
+ // list.deleteObj = deleteObj;
+ // list.deleteAct = deleteAct;
+
+ list.getSubjectCategories = getSubjectCategories;
+ list.getObjectCategories = getObjectCategories;
+ list.getActionCategories = getActionCategories;
+
+ activate();
+
+ function activate(){
+
+ manageSubjectCategories();
+
+ manageObjectCategories();
+
+ manageActionCategories();
+
+ }
+
+ var rootListeners = {
+
+ 'event:updateMetaRuleFromMetaDataAddSuccess': $rootScope.$on('event:updateMetaRuleFromMetaDataAddSuccess', updateMetaRuleCategories),
+
+ 'event:deleteMetaDataFromMetaDataAddSuccess': $rootScope.$on('event:deleteMetaDataFromMetaDataAddSuccess', deleteMetaRuleCategories)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+ function manageSubjectCategories(){
+
+ list.loadingCatSub = true;
+
+ metaDataService.subject.findSomeWithCallback(list.metaRule.subject_categories, function(categories){
+
+ list.catSub = categories;
+ list.loadingCatSub = false;
+
+ });
+ }
+
+ function manageObjectCategories(){
+
+ list.loadingCatObj = true;
+
+ metaDataService.object.findSomeWithCallback(list.metaRule.object_categories, function(categories){
+
+ list.catObj = categories;
+ list.loadingCatObj = false;
+
+ });
+
+ }
+
+ function manageActionCategories(){
+
+ list.loadingCatAct = true;
+
+ metaDataService.action.findSomeWithCallback(list.metaRule.action_categories, function(categories){
+
+ list.catAct = categories;
+ list.loadingCatAct = false;
+
+ });
+
+ }
+
+
+ /**
+ * UnMap
+ */
+
+ function unMapSub(subject){
+
+ subject.loader = true;
+
+ var metaRuleToSend = angular.copy(list.metaRule);
+
+ metaRuleToSend.subject_categories = _.without(metaRuleToSend.subject_categories, subject.id);
+
+ metaRuleService.update(metaRuleToSend, updateMetaRuleSuccess, updateMetaRuleError);
+
+ function updateMetaRuleSuccess(data){
+
+ $translate('moon.model.metarules.update.success', { metaRuleName: list.metaRule.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.metaRule = metaRuleService.findMetaDataFromMetaRule(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ subject.loader = false;
+
+ }
+
+ function updateMetaRuleError(reason){
+
+ $translate('moon.model.metarules.update.error', { metaRuleName: list.metaRule.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+
+ }
+
+ function unMapObj(object){
+
+ object.loader = true;
+
+ var metaRuleToSend = angular.copy(list.metaRule);
+
+ metaRuleToSend.object_categories = _.without(metaRuleToSend.object_categories, object.id);
+
+ metaRuleService.update(metaRuleToSend, updateMetaRuleSuccess, updateMetaRuleError);
+
+ function updateMetaRuleSuccess(data){
+
+ $translate('moon.model.metarules.update.success', { metaRuleName: list.metaRule.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.metaRule = metaRuleService.findMetaDataFromMetaRule(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ object.loader = false;
+
+ }
+
+ function updateMetaRuleError(reason){
+
+ $translate('moon.model.metarules.update.error', { metaRuleName: list.metaRule.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+
+ }
+
+ }
+
+ function unMapAct(action){
+
+ action.loader = true;
+
+ var metaRuleToSend = angular.copy(list.metaRule);
+
+ metaRuleToSend.action_categories = _.without(metaRuleToSend.action_categories, action.id);
+
+ metaRuleService.update(metaRuleToSend, updateMetaRuleSuccess, updateMetaRuleError);
+
+ function updateMetaRuleSuccess(data){
+
+ $translate('moon.model.metarules.update.success', { metaRuleName: list.metaRule.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.metaRule = metaRuleService.findMetaDataFromMetaRule(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ action.loader = false;
+
+ }
+
+ function updateMetaRuleError(reason){
+
+ $translate('moon.model.metarules.update.error', { metaRuleName: list.metaRule.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+
+ }
+
+ // /**
+ // * Delete
+ // */
+ //
+ // function deleteSub(subject){
+ //
+ // subject.loader = true;
+ //
+ // metaDataService.subject.delete(subject, deleteSubSuccess, deleteSubError);
+ //
+ // function deleteSubSuccess(data){
+ //
+ // $translate('moon.model.metadata.subject.delete.success', { subjectName: subject.name }).then( function(translatedValue) {
+ // alertService.alertSuccess(translatedValue);
+ // });
+ //
+ // removeSubFromSubList(subject);
+ //
+ // subject.loader = false;
+ //
+ // }
+ //
+ // function deleteSubError(reason){
+ //
+ // $translate('moon.model.metadata.subject.delete.error',
+ // { subjectName: subject.name, reason: reason.message}).then( function(translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // subject.loader = false;
+ //
+ // }
+ // }
+ //
+ // function deleteObj(object){
+ //
+ // object.loader = true;
+ //
+ // metaDataService.object.delete(object, deleteObjSuccess, deleteObjError);
+ //
+ // function deleteObjSuccess(data){
+ //
+ // $translate('moon.model.metadata.object.delete.success', { objectName: object.name }).then( function(translatedValue) {
+ // alertService.alertSuccess(translatedValue);
+ // });
+ //
+ // removeObjFromObjList(object);
+ // /*list.catSub = metaDataService.subject.findSome(list.metaRule.subject_categories);
+ // list.catObj = metaDataService.object.findSome(list.metaRule.object_categories);
+ // list.catAct = metaDataService.action.findSome(list.metaRule.action_categories);*/
+ //
+ // object.loader = false;
+ //
+ // }
+ //
+ // function deleteObjError(reason){
+ //
+ // $translate('moon.model.metadata.object.delete.error', { objectName: object.name, reason: reason.message}).then( function(translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // object.loader = false;
+ // }
+ // }
+ //
+ // function deleteAct(action){
+ //
+ // action.loader = true;
+ //
+ // metaDataService.action.delete(action, deleteActSuccess, deleteActError);
+ //
+ // function deleteActSuccess(data){
+ //
+ // $translate('moon.model.metadata.action.delete.success', { actionName: action.name }).then( function(translatedValue) {
+ // alertService.alertSuccess(translatedValue);
+ // });
+ //
+ // removeActFromActList(action);
+ //
+ // action.loader = false;
+ //
+ // }
+ //
+ // function deleteActError(reason){
+ //
+ // $translate('moon.model.metadata.action.delete.error', { actionName: action.name, reason: reason.message}).then( function(translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // action.loader = false;
+ //
+ // }
+ // }
+
+ function getSubjectCategories(){
+ return list.catSub ? list.catSub : [];
+ }
+
+ function getObjectCategories(){
+ return list.catObj ? list.catObj : [];
+ }
+
+ function getActionCategories(){
+ return list.catAct ? list.catAct : [];
+ }
+
+ // function removeSubFromSubList(subject){
+ // list.catSub = _.without(list.catSub, subject);
+ // }
+ //
+ // function removeObjFromObjList(object){
+ // list.catObj = _.without(list.catObj, object);
+ // }
+ //
+ // function removeActFromActList(action){
+ // list.catAct = _.without(list.catAct, action);
+ // }
+
+ function updateMetaRuleCategories( event, metaRule){
+
+ list.metaRule = metaRule;
+
+ activate();
+
+ }
+
+
+ function deleteMetaRuleCategories( event, metaRule){
+
+ list.metaRule = metaRule;
+
+ activate();
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html
new file mode 100755
index 00000000..a721e6d0
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html
@@ -0,0 +1,50 @@
+<div class="row">
+
+ <form class="form-horizontal" role="form" name="add.form">
+
+ <div class="form-group" ng-class="{'has-error': add.form.name.$invalid && add.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.model.metarules.add.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="add.metaRule.name" required />
+
+ <div class="help-block" ng-show="add.form.name.$dirty && add.form.name.$invalid">
+ <small class="error" ng-show="add.form.name.$error.required" data-translate="moon.model.metarules.add.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.model.metarules.add.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="add.metaRule.description"></textarea>
+ </div>
+
+ </div>
+
+
+ <div class="form-group">
+
+ <div class="col-sm-8">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="add.loading" ng-click="add.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.model.metarules.add.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="add.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </div>
+ </form>
+
+</div>
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html
new file mode 100755
index 00000000..1830204b
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html
@@ -0,0 +1,102 @@
+<div ng-controller="moonMetaRulesMapController as map" class="modal" tabindex="-1" data-role="MapMetaRules">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.metarules.map.title"></h4>
+
+ </div>
+
+ <div class="modal-body">
+
+ <div class="row">
+
+ <div class="col-sm-3">
+
+ <button class="btn btn-primary" style="white-space: normal;" ng-click="map.addMetaRuleToList = !map.addMetaRuleToList">
+
+ <span ng-if="!map.addMetaRuleToList" data-translate="moon.model.metarules.map.action.new">Add a new Meta Rule</span>
+ <span ng-if="map.addMetaRuleToList" data-translate="moon.model.metarules.map.action.list">List of Meta Rules</span>
+
+ </button>
+
+ </div>
+
+ <div class="col-sm-9">
+
+ <form class="form-horizontal" role="form" name="map.form">
+
+ <div class="form-group" ng-if="!map.addMetaRuleToList">
+
+ <label class="col-sm-3 control-label" data-translate="moon.model.metarules.map.form.list">List of Meta Rule</label>
+
+ <div class="col-sm-9">
+
+ <ui-select ng-model="map.selectedMetaRule" name="object">
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="ametaRule in map.metaRules">
+ <div ng-value="ametaRule" ng-bind="ametaRule.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-if="!map.addMetaRuleToList">
+
+ <moon-loader ng-if="map.metaRulesLoading || map.mappingLoading" ></moon-loader>
+
+ <div class="col-sm-5">
+ <a href="" ng-disabled="map.metaRulesLoading || map.mappingLoading || !map.selectedMetaRule" ng-click="map.deleteMetaRule()" class="btn btn-warning" style="white-space: normal;">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.model.metarules.map.action.delete">Delete the selected Meta Rule</span>
+ </a>
+ </div>
+
+ <div class="col-sm-5 col-sm-offset-2">
+ <a href="" ng-disabled="map.metaRulesLoading || map.mappingLoading || !map.selectedMetaRule" ng-click="map.mapToModel()" class="btn btn-warning" style="white-space: normal;">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.model.metarules.map.action.add">Add the selected Meta Rule</span>
+ </a>
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-if="map.addMetaRuleToList">
+
+ <moon-meta-rules-add></moon-meta-rules-add>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.model.metarules.add.action.cancel">Cancel</span>
+ </a>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html
new file mode 100755
index 00000000..bb02aba2
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html
@@ -0,0 +1,35 @@
+<div ng-controller="MetaRulesUnMapController as unmap" class="modal" tabindex="-1" data-role="modalUnMapMetaRule">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.metarules.unmap.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <span data-translate="moon.model.metarules.unmap.content" data-translate-values="{ modelName: unmap.model.name, metaRuleName: unmap.metaRule.name }"></span>
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.model.metarules.unmap.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="unmap.unMappingLoading" ng-click="unmap.unmap()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span data-translate="moon.model.metarules.unmap.action.unmap">Unmap</span>
+ </a>
+ <moon-loader ng-if="unmap.unMappingLoading" ></moon-loader>
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js
new file mode 100755
index 00000000..a95951fa
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js
@@ -0,0 +1,99 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonMetaRulesAdd', moonMetaRulesAdd);
+
+ moonMetaRulesAdd.$inject = [];
+
+ function moonMetaRulesAdd() {
+
+ return {
+ templateUrl : 'html/model/edit/metarules/action/mapping/metarules-add.tpl.html',
+ bindToController : true,
+ controller : moonMetaRulesAddController,
+ controllerAs : 'add',
+ scope : {
+ metaRules : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+
+ angular
+ .module('moon')
+ .controller('moonMetaRulesAddController', moonMetaRulesAddController);
+
+ moonMetaRulesAddController.$inject = ['$scope', 'metaRuleService', 'alertService', '$translate', 'formService', 'utilService'];
+
+ function moonMetaRulesAddController($scope, metaRuleService, alertService, $translate, formService, utilService) {
+
+ var add = this;
+
+ /*
+ *
+ */
+
+ add.laoading = false;
+
+ add.form = {};
+
+ add.metaRule = { name: null, description: null, subject_categories : [], object_categories : [], action_categories : [] };
+
+ add.create = createMetaRule;
+
+ activate();
+
+ function activate(){
+
+ }
+
+ function createMetaRule() {
+
+ if(formService.isInvalid(add.form)) {
+
+ formService.checkFieldsValidity(add.form);
+
+ } else {
+
+ add.loading = true;
+
+ metaRuleService.data.create({}, add.metaRule, createSuccess, createError);
+
+ }
+
+ function createSuccess(data) {
+
+ var createdMetaRule = utilService.transformOne(data, 'meta_rules');
+
+ $translate('moon.model.metarules.add.success', { metaRuleName: createdMetaRule.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:metaRuleCreatedSuccess', createdMetaRule);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.model.metarules.add.error', { metaRuleName: add.metaRule.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:metaRuleCreatedError', add.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js
new file mode 100755
index 00000000..cf9ba06c
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js
@@ -0,0 +1,213 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('moonMetaRulesMapController', moonMetaRulesMapController);
+
+ moonMetaRulesMapController.$inject = ['$scope', '$rootScope', 'alertService', '$translate', 'formService', 'metaRuleService', 'modelService', 'utilService'];
+
+ function moonMetaRulesMapController($scope, $rootScope, alertService, $translate, formService, metaRuleService, modelService, utilService ) {
+
+ var map = this;
+
+ /*
+ *
+ */
+
+ map.metaRules = [];
+
+ map.model = $scope.model;
+
+ map.addMetaRuleToList = false;
+
+ map.mapToModel = mapToModel;
+
+ map.deleteMetaRule = deleteMetaRule;
+
+ activate();
+
+ function activate() {
+
+ resolveMetaRules();
+
+ }
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:metaRuleCreatedSuccess': $rootScope.$on('event:metaRuleCreatedSuccess', metaRuleCreatedSuccess),
+ 'event:metaRuleCreatedError': $rootScope.$on('event:metaRuleCreatedError', metaRuleCreatedError)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+ /*
+ *
+ */
+
+ function resolveMetaRules() {
+
+ map.metaRulesLoading = true;
+
+ metaRuleService.findAllWithCallback(
+ function(metaRules){
+ map.metaRules = metaRules;
+ map.metaRulesLoading = false;
+ }
+ );
+
+ }
+
+ function mapToModel() {
+
+ if (formService.isInvalid(map.form)) {
+
+ formService.checkFieldsValidity(map.form);
+
+ } else {
+
+ map.mappingLoading = true;
+
+ var modelToSend = angular.copy(map.model);
+
+ modelToSend.meta_rules.push(map.selectedMetaRule.id);
+
+ modelService.update(modelToSend, mapSuccess, mapError);
+
+ }
+
+ function mapSuccess(data) {
+
+ var modelReceived = utilService.transformOne(data, 'models');
+
+ metaRuleService.findSomeWithMetaData(modelReceived.meta_rules).then(function(metaRules){
+
+ modelReceived.meta_rules_values = metaRules;
+
+ $translate('moon.model.metarules.map.success', {
+
+ modelName: modelReceived.name,
+ metaRuleName: map.selectedMetaRule.name
+
+ }).then(function (translatedValue) {
+
+ alertService.alertSuccess(translatedValue);
+
+ });
+
+ map.mappingLoading = false;
+
+ $scope.$emit('event:metaRuleMapToModelSuccess', modelReceived);
+
+ });
+
+ }
+
+ function mapError(response) {
+
+ $translate('moon.model.metarules.map.error', {
+
+ modelName: map.model.name,
+ metaRuleName: map.selectedMetaRule.name
+
+ }).then(function (translatedValue) {
+
+ alertService.alertError(translatedValue);
+
+ });
+
+ map.mappingLoading = false;
+
+ }
+ }
+
+ function cleanSelectedValue(){
+
+ delete map.selectedMetaRule;
+
+ }
+
+
+ function deleteMetaRule(){
+
+ if(!map.selectedMetaRule){
+
+ return;
+
+ }
+
+ map.mappingLoading = true;
+
+ var metaRuleTodelete = angular.copy(map.selectedMetaRule);
+
+ metaRuleService.delete(metaRuleTodelete, deleteSuccess, deleteError);
+
+ function deleteSuccess(data) {
+
+ $translate('moon.model.metarules.delete.success', { metaRuleName: metaRuleTodelete.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ cleanSelectedValue();
+
+ map.mappingLoading = false;
+
+ resolveMetaRules();
+
+ // later this event will have to be catch, because the model can use the deleted MetaRule
+ $scope.$emit('event:deleteMetaRule', metaRuleTodelete);
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.model.metarules.delete.error', { metaRuleName: metaRuleTodelete.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ map.mappingLoading = false;
+
+ }
+ }
+
+
+
+
+
+
+ /**
+ * This function will add a metaRule to the current list of metaRules
+ * @param event
+ * @param metaRule {...} metaRule to add
+ */
+ function metaRuleCreatedSuccess(event, metaRule) {
+
+ map.metaRules.push(metaRule);
+ showList();
+
+ }
+
+ /**
+ * This function hide the add MetaRule Modal
+ * @param event
+ */
+ function metaRuleCreatedError(event) {
+
+ }
+
+ function showList(){
+ map.addMetaRuleToList = false;
+ }
+
+ }
+
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js
new file mode 100755
index 00000000..30f32d51
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js
@@ -0,0 +1,74 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('MetaRulesUnMapController', MetaRulesUnMapController);
+
+ MetaRulesUnMapController.$inject = ['$scope', '$translate', 'alertService', 'modelService'];
+
+ function MetaRulesUnMapController($scope, $translate, alertService, modelService) {
+
+ var unmap = this;
+
+ /*
+ *
+ */
+
+ unmap.model = $scope.model;
+ unmap.metaRule = $scope.metaRule;
+
+ unmap.unMappingLoading = false;
+
+ unmap.unmap = unMapModelToMetaRule;
+
+ /*
+ *
+ */
+
+ function unMapModelToMetaRule() {
+
+ unmap.unMappingLoading = true;
+
+ var modelToUpdate = angular.copy(unmap.model);
+
+ modelToUpdate.meta_rules = _.without(modelToUpdate.meta_rules, unmap.metaRule.id);
+
+ modelService.update(modelToUpdate, unMapSuccess, unMapError);
+
+ function unMapSuccess(data) {
+
+ $translate('moon.model.metarules.unmap.success', { modelName: unmap.model.name, metaRuleName: unmap.metaRule.name })
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ $scope.$emit('event:metaRuleUnMappedToModelSuccess', modelToUpdate);
+
+ }
+
+ function unMapError(reason) {
+
+ $translate('moon.model.metarules.unmap.error', { modelName: unmap.model.name, metaRuleName: unmap.metaRule.name })
+ .then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ $scope.$emit('event:metaRuleUnMappedToModelError');
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html b/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html
new file mode 100755
index 00000000..b6136195
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html
@@ -0,0 +1,67 @@
+<div class="row">
+
+ <form class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group">
+
+ <label for="id" class="col-sm-3 control-label" data-translate="moon.model.metarules.edit.basic.form.id">Id</label>
+
+ <div class="col-sm-6">
+
+ <input name="id" id="id" disabled class="form-control" type="text" data-ng-model="edit.metaRuleToEdit.id" required />
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.model.metarules.edit.basic.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.metaRuleToEdit.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.model.metarules.edit.basic.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.model.metarules.edit.basic.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.metaRuleToEdit.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="col-sm-2 col-sm-offset-3">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.init()" class="btn btn-default">
+ <span data-translate="moon.model.metarules.edit.basic.action.init">Init</span>
+ </a>
+
+ </div>
+
+ <div class="col-sm-4 col-sm-offset-2">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.editMetaRule()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.model.metarules.edit.basic.action.update">Update</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </form>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html b/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html
new file mode 100755
index 00000000..7b074448
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html
@@ -0,0 +1,62 @@
+<div ng-controller="MetaRulesEditController as edit" class="modal" tabindex="-1" data-role="modalViewProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.model.metarules.edit.title" data-translate-values="{metaRuleName: edit.metaRule.name}"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4>
+ <span data-translate="moon.model.edit.basic.title" >Basic Information</span>
+ <a href="" ng-click="edit.editBasic = !edit.editBasic">
+ <span data-translate="moon.model.metarules.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>
+ </h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div ng-if="edit.editBasic">
+ <moon-meta-rules-edit-basic meta-rule="edit.metaRule"></moon-meta-rules-edit-basic>
+ </div>
+
+ <div ng-if="!edit.editBasic">
+ <dl class="dl-horizontal">
+ <dt>Id</dt>
+ <dd ng-bind="edit.metaRule.id"></dd>
+ <dt>Name</dt>
+ <dd ng-bind="edit.metaRule.name"></dd>
+ <dt>Description</dt>
+ <dd ng-bind="edit.metaRule.description"></dd>
+ </dl>
+ </div>
+ </div>
+
+ </div>
+
+ <moon-meta-data-list edit-mode="true" meta-rule="edit.metaRule"></moon-meta-data-list>
+
+ </div>
+
+ <div class="modal-footer top10">
+ <div class="btn-toolbar" style="float: right;">
+ <button ng-click="$hide()" class="btn btn-default" data-translate="moon.model.view.action.close">Close</button>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js b/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js
new file mode 100755
index 00000000..b2ebc45d
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js
@@ -0,0 +1,49 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('MetaRulesEditController', MetaRulesEditController);
+
+ MetaRulesEditController.$inject = ['$scope', '$rootScope'];
+
+ function MetaRulesEditController($scope, $rootScope) {
+
+ var edit = this;
+
+ edit.metaRule = $scope.metaRule;
+
+ activate();
+
+ function activate(){
+ }
+
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:metaRuleBasicUpdatedSuccess': $rootScope.$on('event:metaRuleBasicUpdatedSuccess', metaRuleUpdatedSuccess)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ /**
+ * When the MetaRule is updated, this function refresh the current metaRule with the new changes
+ * @param event
+ * @param metaRule
+ */
+ function metaRuleUpdatedSuccess(event, metaRule){
+
+ edit.metaRule = metaRule;
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js b/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js
new file mode 100755
index 00000000..603e7a33
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js
@@ -0,0 +1,98 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonMetaRulesEditBasic', moonMetaRulesEditBasic);
+
+ moonMetaRulesEditBasic.$inject = [];
+
+ function moonMetaRulesEditBasic() {
+
+ return {
+ templateUrl : 'html/model/edit/metarules/action/metarules-edit-basic.tpl.html',
+ bindToController : true,
+ controller : moonMetaRulesEditBasicController,
+ controllerAs : 'edit',
+ scope : {
+ metaRule : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+
+ }
+
+ angular
+ .module('moon')
+ .controller('moonMetaRulesEditBasicController', moonMetaRulesEditBasicController);
+
+ moonMetaRulesEditBasicController.$inject = ['$scope', 'metaRuleService', 'formService', 'alertService', '$translate', 'utilService'];
+
+ function moonMetaRulesEditBasicController($scope, metaRuleService, formService, alertService, $translate, utilService){
+
+ var edit = this;
+
+ edit.editMetaRule = editMetaRule;
+ edit.init = init;
+
+ edit.form = {};
+
+ activate();
+
+ function activate(){
+
+ edit.metaRule = $scope.edit.metaRule;
+
+ edit.metaRuleToEdit = angular.copy(edit.metaRule);
+
+ }
+
+ function editMetaRule(){
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ }else{
+
+ edit.loading = true;
+
+ metaRuleService.update(edit.metaRuleToEdit, updateSuccess, updateError);
+
+ }
+
+ function updateSuccess(data) {
+
+ var updatedMetaRule = utilService.transformOne(data, 'meta_rules');
+
+ $translate('moon.model.metarules.edit.basic.success', { metaRuleName: updatedMetaRule.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ edit.loading = false;
+
+ $scope.$emit('event:metaRuleBasicUpdatedSuccess', updatedMetaRule);
+
+ }
+
+ function updateError(reason) {
+
+ $translate('moon.model.edit.basic.error', { metaRuleName: edit.metaRule.name }).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ edit.loading = false;
+
+ }
+ }
+
+ function init(){
+
+ edit.metaRuleToEdit = angular.copy(edit.metaRule);
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html b/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html
new file mode 100755
index 00000000..ebe307c3
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html
@@ -0,0 +1,138 @@
+<div>
+
+
+ <div><h4 data-translate="moon.model.metarules.title">List of Meta Rules</h4></div>
+
+ <div class="table-responsive" data-role="table">
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <colgroup>
+ <col class="col-md-2" />
+ <col class="col-md-2" />
+ <col class="col-md-1" />
+ <col class="col-md-1" />
+ <col class="col-md-1" />
+ <col class="col-md-2" />
+ </colgroup>
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.model.metarules.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.model.metarules.table.description">Description</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.model.metarules.table.metadata.subject.number">Number of Subjects</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.model.metarules.table.metadata.object.number">Number of Subjects</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.model.metarules.table.metadata.action.number">Number of Actions</div>
+ </th>
+
+ <th class="customTables">
+ <div data-translate="moon.model.metarules.action.title">Actions</div>
+ </th>
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasMetaRules()">
+ <tr>
+ <td colspan="2"><span data-translate="moon.model.metarules.table.notFound">There is no Meta Rules</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasMetaRules()">
+
+ <tr ng-repeat="aMetaRules in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td ng-bind="aMetaRules.name"></td>
+ <td ng-bind="aMetaRules.description"></td>
+ <td ng-bind="aMetaRules.subject_categories.length"></td>
+ <td ng-bind="aMetaRules.object_categories.length"></td>
+ <td ng-bind="aMetaRules.action_categories.length"></td>
+ <td>
+
+ <div ng-if="list.editMode">
+
+ <div ng-if="!value.loader" class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.model.metadata.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unmap.showModal(aMetaRules)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.remove">Remove</span>
+ </a>
+ </li>
+
+ <li>
+ <a href="" ng-click="list.edit.showModal(aMetaRules)">
+ <span class="glyphicon glyphicon-cog"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.edit">Edit</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>
+
+ </div>
+
+ <div ng-if="!list.editMode">
+
+ <a href="" ng-click="list.showDetail(aMetaRules)">
+
+ <span ng-if="aMetaRules.id !== list.getShowDetailValue().id">
+ <span class="glyphicon glyphicon-eye-open"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.detail.open">Consult</span>
+ </span>
+
+ <span ng-if="aMetaRules.id === list.getShowDetailValue().id">
+ <span class="glyphicon glyphicon-eye-close"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.detail.close">Close</span>
+ </span>
+
+ </a>
+
+ </div>
+
+ </td>
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ <div ng-if="list.showDetailValue">
+ <moon-meta-data-list edit-mode="list.editMode" meta-rule="list.getShowDetailValue()"></moon-meta-data-list>
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-if="list.editMode">
+ <a href="" ng-click="list.map.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.model.metarules.action.settings">Settings</span>
+ </a>
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js b/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js
new file mode 100755
index 00000000..120b6a8b
--- /dev/null
+++ b/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js
@@ -0,0 +1,240 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonMetaRulesList', moonMetaRulesList);
+
+ moonMetaRulesList.$inject = [];
+
+ function moonMetaRulesList() {
+
+ return {
+ templateUrl : 'html/model/edit/metarules/metarules-list.tpl.html',
+ bindToController : true,
+ controller : moonMetaRulesListController,
+ controllerAs : 'list',
+ scope : {
+ // if edit and delete possibilities are displayed
+ // Value are True or False
+ editMode : '=',
+ mappedModel : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonMetaRulesListController', moonMetaRulesListController);
+
+ moonMetaRulesListController.$inject = ['$scope', '$rootScope', 'NgTableParams', '$filter', '$modal', 'metaRuleService'];
+
+ function moonMetaRulesListController($scope, $rootScope, NgTableParams, $filter, $modal, metaRuleService ){
+
+ var list = this;
+
+ list.table = {};
+
+ list.editMode = $scope.list.editMode;
+ list.model = $scope.list.mappedModel;
+ list.metaRules = list.model.meta_rules_values;
+
+ list.getMetaRules = getMetaRules;
+ list.hasMetaRules = hasMetaRules;
+ list.showDetail = showDetail;
+ list.getSubjectList = getSubjectList;
+ list.getObjectList = getObjectList;
+ list.getActionlist = getActionlist;
+ list.getShowDetailValue = getShowDetailValue;
+
+ list.showDetailValue = false;
+
+ list.subject_list = [];
+ list.object_list = [];
+ list.action_list = [];
+
+ list.edit = { modal: $modal({ template: 'html/model/edit/metarules/action/metarules-edit.tpl.html', show: false }),
+ showModal: showEditModal };
+
+ /*list.edit.modal.result.finally(function(){
+ console.log('CATCHING');
+ });*/
+
+
+ list.map = { modal: $modal({ template: 'html/model/edit/metarules/action/mapping/metarules-map.tpl.html', show: false }),
+ showModal: showMapModal };
+
+ list.unmap = { modal: $modal({ template: 'html/model/edit/metarules/action/mapping/metarules-unmap.tpl.html', show: false }),
+ showModal: showUnmapModal };
+
+ activate();
+
+ function activate(){
+
+ newMetaRulesTable();
+
+ }
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:metaRuleMapToModelSuccess': $rootScope.$on('event:metaRuleMapToModelSuccess', updateModelFromMapSuccess),
+
+ 'event:metaRuleUnMappedToModelSuccess': $rootScope.$on('event:metaRuleUnMappedToModelSuccess', modelUnmappedSuccess),
+ 'event:metaRuleUnMappedToModelError': $rootScope.$on('event:metaRuleUnMappedToModelError', modelUnmappedError)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+
+ function newMetaRulesTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ total: function () { return list.getMetaRules().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getMetaRules(), params.orderBy()) : list.getMetaRules();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+ /**
+ * If the directive is not in editMode and displaying MetaData Content, if the editMode change to true, MetaData Content need to be hidden
+ */
+ $scope.$watch('list.editMode', function(newValue, oldValue){
+ list.showDetailValue = false;
+ });
+
+ function getMetaRules() {
+ return (list.metaRules) ? list.metaRules : [];
+ }
+
+ function hasMetaRules() {
+ return list.getMetaRules().length > 0;
+ }
+
+ function showDetail(aMetaRule){
+
+ if(aMetaRule.id === getShowDetailValue().id){
+
+ list.showDetailValue = false;
+ list.subject_list = [];
+ list.object_list = [];
+ list.action_list = [];
+
+ }else{
+
+ list.subject_list = aMetaRule.subject_categories_values;
+ list.object_list = aMetaRule.object_categories_values;
+ list.action_list = aMetaRule.action_categories_values;
+ list.showDetailValue = aMetaRule;
+
+ }
+
+ }
+
+ function showEditModal(aMetaRule) {
+ list.edit.modal.$scope.metaRule = aMetaRule;
+ list.edit.modal.$promise.then(list.edit.modal.show);
+ }
+
+ function getShowDetailValue(){
+ return list.showDetailValue;
+ }
+
+ function getSubjectList(){
+ return list.subject_list;
+ }
+
+ function getObjectList(){
+ return list.object_list;
+ }
+
+ function getActionlist(){
+ return list.action_list;
+ }
+
+ /*
+ * ---- add
+ */
+ function showMapModal() {
+ list.map.modal.$scope.model = list.model;
+ list.map.modal.$promise.then(list.map.modal.show);
+ }
+
+ function refreshRules(){
+
+ list.metaRules = list.model.meta_rules_values;
+ list.table.total(list.getMetaRules().length);
+ list.table.reload();
+
+ }
+
+ function updateModelFromMapSuccess(event, model){
+
+ list.model = model;
+
+ refreshRules();
+
+ list.map.modal.hide();
+
+ }
+
+ /*
+ * ---- unmap
+ */
+
+ function showUnmapModal(metaRule) {
+
+ list.unmap.modal.$scope.model = list.model;
+ list.unmap.modal.$scope.metaRule = metaRule;
+ list.unmap.modal.$promise.then(list.unmap.modal.show);
+
+ }
+
+ function modelUnmappedSuccess(event, model) {
+
+ list.model = model;
+
+ metaRuleService.findSomeWithCallback(list.model.meta_rules, function(meta_rules){
+
+ list.model.meta_rules_values = meta_rules;
+ refreshRules();
+ list.unmap.modal.hide();
+
+ });
+
+ }
+
+ function modelUnmappedError(event) {
+ list.unmap.modal.hide();
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/model-edit-basic.tpl.html b/moon_gui/static/app/model/edit/model-edit-basic.tpl.html
new file mode 100755
index 00000000..bd73b4ef
--- /dev/null
+++ b/moon_gui/static/app/model/edit/model-edit-basic.tpl.html
@@ -0,0 +1,65 @@
+<div class="row">
+
+ <form class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group">
+
+ <label for="id" class="col-sm-3 control-label" data-translate="moon.model.edit.basic.form.id">Id</label>
+
+ <div class="col-sm-6">
+
+ <input name="id" id="id" disabled class="form-control" type="text" data-ng-model="edit.modelToEdit.id" required />
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.model.edit.basic.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.modelToEdit.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.model.edit.basic.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.model.edit.basic.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.modelToEdit.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="col-sm-2 col-sm-offset-3">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.init()" class="btn btn-default">
+ <span data-translate="moon.model.edit.basic.action.init">Init</span>
+ </a>
+ </div>
+
+ <div class="col-sm-4 col-sm-offset-2">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.editModel()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.model.edit.basic.action.update">Update</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+ </div>
+
+ </div>
+
+ </form>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/edit/model-edit.tpl.html b/moon_gui/static/app/model/edit/model-edit.tpl.html
new file mode 100755
index 00000000..4955f441
--- /dev/null
+++ b/moon_gui/static/app/model/edit/model-edit.tpl.html
@@ -0,0 +1,70 @@
+<div class="container">
+
+ <div class="row">
+ <h3 class="pull-left" data-translate="moon.model.edit.title" data-translate-values="{ modelName: edit.model.name }">Edit</h3>
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.model.edit.basic.title" >Basic Information</span>
+ <a href="" ng-click="edit.editBasic = !edit.editBasic">
+ <span data-translate="moon.model.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div ng-if="edit.editBasic">
+ <moon-model-edit-basic model="edit.model"></moon-model-edit-basic>
+ </div>
+
+ <div ng-if="!edit.editBasic">
+ <dl class="dl-horizontal">
+
+ <dt data-translate="moon.model.edit.basic.form.id">Id</dt>
+ <dd ng-bind="edit.model.id"></dd>
+
+ <dt data-translate="moon.model.edit.basic.form.name">Name</dt>
+ <dd ng-bind="edit.model.name"></dd>
+
+ <dt data-translate="moon.model.edit.basic.form.description">Description</dt>
+ <dd ng-bind="edit.model.description"></dd>
+
+ </dl>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.model.edit.metarules.title" >Meta Rule</span>
+ <!--<a href="" ng-click="edit.editMetaRules = !edit.editMetaRules">
+ <span data-translate="moon.model.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>-->
+
+ </div>
+
+ <div class="panel-body" ng-if="edit.model.meta_rules_values">
+ <div class="">
+
+ <moon-meta-rules-list mapped-model="edit.model" edit-mode="edit.editMetaRules"></moon-meta-rules-list>
+
+ </div>
+ </div>
+
+ <div class="panel-body" ng-if="!edit.model.meta_rules_values">
+ <moon-loader></moon-loader>
+ </div>
+
+ </div>
+
+
+</div>
diff --git a/moon_gui/static/app/model/edit/model.controller.edit.js b/moon_gui/static/app/model/edit/model.controller.edit.js
new file mode 100755
index 00000000..3e10a533
--- /dev/null
+++ b/moon_gui/static/app/model/edit/model.controller.edit.js
@@ -0,0 +1,61 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelEditController', ModelEditController);
+
+ ModelEditController.$inject = ['$scope', '$rootScope', 'model', 'metaRuleService'];
+
+ function ModelEditController($scope, $rootScope, model, metaRuleService) {
+
+ var edit = this;
+
+ edit.model = model;
+
+ edit.editBasic = false;
+
+ edit.editMetaRules = true;
+
+ activate();
+
+ function activate(){
+
+ }
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:modelUpdatedSuccess': $rootScope.$on('event:modelUpdatedSuccess', modelUpdatedSuccess),
+
+ 'event:updateModelFromMetaRuleAddSuccess': $rootScope.$on('event:updateModelFromMetaRuleAddSuccess', modelUpdatedSuccess)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ /**
+ * When the model is updated, this function refresh the current model with the new changes
+ * @param event
+ * @param model
+ */
+ function modelUpdatedSuccess(event, model){
+
+ edit.model = model;
+
+ metaRuleService.findSomeWithCallback(model.meta_rules, function(metaRules){
+
+ edit.model.meta_rules_values = metaRules;
+
+ });
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/model/edit/model.edit.basic.dir.js b/moon_gui/static/app/model/edit/model.edit.basic.dir.js
new file mode 100755
index 00000000..54bb7071
--- /dev/null
+++ b/moon_gui/static/app/model/edit/model.edit.basic.dir.js
@@ -0,0 +1,97 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonModelEditBasic', moonModelEditBasic);
+
+ moonModelEditBasic.$inject = [];
+
+ function moonModelEditBasic() {
+
+ return {
+ templateUrl : 'html/model/edit/model-edit-basic.tpl.html',
+ bindToController : true,
+ controller : moonModelEditBasicController,
+ controllerAs : 'edit',
+ scope : {
+ model : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonModelEditBasicController', moonModelEditBasicController);
+
+ moonModelEditBasicController.$inject = ['$scope', 'modelService', 'formService', 'alertService', '$translate', 'utilService'];
+
+ function moonModelEditBasicController($scope, modelService, formService, alertService, $translate, utilService){
+
+ var edit = this;
+
+ edit.editModel = editModel;
+ edit.init = init;
+
+ edit.form = {};
+
+ activate();
+
+ function activate(){
+
+ edit.model = $scope.edit.model;
+
+ edit.modelToEdit = angular.copy(edit.model);
+
+ }
+
+ function editModel(){
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ }else{
+
+ edit.loading = true;
+
+ modelService.update(edit.modelToEdit, updateSuccess, updateError);
+
+ }
+
+ function updateSuccess(data) {
+
+ var updatedModel = utilService.transformOne(data, 'models');
+
+ $translate('moon.model.edit.basic.success', { modelName: updatedModel.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ edit.loading = false;
+
+ $scope.$emit('event:modelUpdatedSuccess', updatedModel);
+
+ }
+
+ function updateError(reason) {
+
+ $translate('moon.model.edit.basic.error', { modelName: edit.model.name }).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ edit.loading = false;
+
+ }
+ }
+
+ function init(){
+
+ edit.modelToEdit = angular.copy(edit.model);
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/model/model-list.tpl.html b/moon_gui/static/app/model/model-list.tpl.html
new file mode 100755
index 00000000..89c682cc
--- /dev/null
+++ b/moon_gui/static/app/model/model-list.tpl.html
@@ -0,0 +1,123 @@
+<div class="container">
+
+ <div>
+ <form class="form-inline pull-right">
+ <div class="form-group">
+ <div>
+ <input id="searchProject" data-ng-model="list.search.query" type="text" class="form-control" placeholder="{{'moon.model.list.search.placeholder' | translate}}" />
+ </div>
+ </div>
+ <div class="form-group">
+ <div>
+ <button type="submit" class="btn btn-danger" data-ng-click="list.search.reset()" data-translate="moon.model.list.search.reset">Reset</button>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+
+ <div class="row">
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.model.list.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.model.list.table.description">Description</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.model.list.table.metaRules.number">Number of Meta Rules</div>
+ </th>
+
+ <th class="customTables">
+ <div data-translate="moon.model.list.action.title">Actions</div>
+ </th>
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasModels()">
+ <tr>
+ <td colspan="2"><span data-translate="moon.model.list.table.notFound">There is no Models</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasModels()">
+
+ <tr ng-repeat="aModel in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td ng-bind="aModel.name"></td>
+ <td ng-bind="aModel.description"></td>
+ <td ng-bind="aModel.meta_rules.length"></td>
+ <td>
+ <div class="dropdown">
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.model.list.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+
+ <!-- <li>
+ <a href="" ng-click="list.view.showModal(aModel)">
+ <span class="glyphicon glyphicon-eye-open"></span>
+ <span class="control-label" data-translate="moon.model.list.action.detail">Detail</span>
+ </a>
+ </li>-->
+
+ <li>
+ <a href="" ui-sref="moon.model.edit({id: aModel.id})">
+ <span class="glyphicon glyphicon-cog"></span>
+ <span class="control-label" data-translate="moon.model.list.action.edit">Edit</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.del.showModal(aModel)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.model.list.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+ </div>
+ </td>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ <div class="container">
+
+ <div class="form-inline form-group">
+ <a href="" ng-click="list.add.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-plus-sign"></span>
+ <span data-translate="moon.model.list.action.add">Add Model</span>
+ </a>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/model/model.controller.list.js b/moon_gui/static/app/model/model.controller.list.js
new file mode 100755
index 00000000..5021a57e
--- /dev/null
+++ b/moon_gui/static/app/model/model.controller.list.js
@@ -0,0 +1,195 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelListController', ModelListController);
+
+ ModelListController.$inject = ['$scope', '$rootScope', 'models', 'NgTableParams', '$filter', '$modal'];
+
+ function ModelListController($scope, $rootScope, models, NgTableParams, $filter, $modal) {
+
+ var list = this;
+
+ list.models = models;
+
+ list.table = {};
+
+ list.search = { query: '',
+ find: searchModel,
+ reset: searchReset };
+
+ list.getModels = getModels;
+ list.hasModels = hasModels;
+ list.deleteModel = deleteModel;
+ list.refreshModels = refreshModels;
+
+ list.add = { modal: $modal({ template: 'html/model/action/model-add.tpl.html', show: false }),
+ showModal: showAddModal };
+
+ list.view = { modal: $modal({ template: 'html/model/action/model-view.tpl.html', show: false }),
+ showModal: showViewModal };
+
+ list.del = { modal: $modal({ template: 'html/model/action/model-delete.tpl.html', show: false }),
+ showModal: showDeleteModal };
+
+ activate();
+
+ function activate(){
+ newModelsTable();
+ }
+
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:modelCreatedSuccess': $rootScope.$on('event:modelCreatedSuccess', modelCreatedSuccess),
+ 'event:modelCreatedError': $rootScope.$on('event:modelCreatedError', modelCreatedError),
+
+ 'event:modelDeletedSuccess': $rootScope.$on('event:modelDeletedSuccess', modelDeletedSuccess),
+ 'event:modelDeletedError': $rootScope.$on('event:modelDeletedError', modelDeletedError)
+
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+ function newModelsTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ total: function () { return list.getModels().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getModels(), params.orderBy()) : list.getModels();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+ function getModels() {
+ return (list.models) ? list.models : [];
+ }
+
+ function hasModels() {
+ return list.getModels().length > 0;
+ }
+
+ /**
+ * Blank the search field
+ */
+ function searchReset() {
+ list.search.query = '';
+ }
+
+ /*
+ * ---- search
+ */
+
+ function searchModel(model){
+ return (model.name.indexOf(list.search.query) !== -1 || model.description.indexOf(list.search.query) !== -1);
+ }
+
+ /*
+ * ---- add
+ */
+ function showAddModal() {
+ list.add.modal.$promise.then(list.add.modal.show);
+ }
+
+ function addModel(model) {
+ list.models.push(model);
+ }
+
+ /**
+ * Refresh the table
+ */
+ function refreshModels(){
+ list.table.total(list.models.length);
+ list.table.reload();
+ }
+
+ /**
+ * This function will add a model to the current list of models and refresh the table
+ * @param event
+ * @param model
+ */
+ function modelCreatedSuccess(event, model) {
+ addModel(model);
+ refreshModels();
+ list.add.modal.hide();
+ }
+
+ /**
+ * This function hide the add modal
+ * @param event
+ */
+ function modelCreatedError(event) {
+ list.add.modal.hide();
+ }
+
+ /*
+ * ---- view
+ */
+
+ function showViewModal(model) {
+
+ list.view.modal.$scope.model = model;
+ list.view.modal.$promise.then(list.view.modal.show);
+
+ }
+
+
+ /*
+ * ---- delete
+ */
+
+ function showDeleteModal(model) {
+
+ list.del.modal.$scope.model = model;
+ list.del.modal.$promise.then(list.del.modal.show);
+
+ }
+
+ function deleteModel(model) {
+ list.models = _.chain(list.models).reject({id: model.id}).value();
+ }
+
+
+ function modelDeletedSuccess(event, model) {
+
+ list.deleteModel(model);
+ list.refreshModels();
+
+ list.del.modal.hide();
+
+ }
+
+ function modelDeletedError(event, model) {
+ list.del.modal.hide();
+ }
+
+
+ }
+
+})();
diff --git a/moon_gui/static/app/moon.constants.js b/moon_gui/static/app/moon.constants.js
new file mode 100644
index 00000000..9681e3dc
--- /dev/null
+++ b/moon_gui/static/app/moon.constants.js
@@ -0,0 +1,79 @@
+/**
+# Copyright 2014 Orange
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .constant('DEFAULT_CST', {
+ DOMAIN: {
+ DEFAULT: 'Default'
+ }
+ })
+ .constant('SECURITY_PIPELINE_CST', {
+ TYPE: {
+ POLICY: 'policy'
+ }
+ })
+ .constant('META_DATA_CST', {
+ TYPE: {
+ SUBJECT: 'SUBJECT',
+ OBJECT: 'OBJECT',
+ ACTION: 'ACTION'
+ }
+ })
+ .constant('PERIMETER_CST', {
+ TYPE: {
+ SUBJECT: 'SUBJECT',
+ OBJECT: 'OBJECT',
+ ACTION: 'ACTION'
+ }
+ })
+ .constant('DATA_CST', {
+ TYPE: {
+ SUBJECT: 'SUBJECT',
+ OBJECT: 'OBJECT',
+ ACTION: 'ACTION'
+ }
+ })
+ .constant('ASSIGNMENTS_CST', {
+ TYPE: {
+ SUBJECT: 'SUBJECT',
+ OBJECT: 'OBJECT',
+ ACTION: 'ACTION'
+ }
+ })
+ .constant('REST_URI', {
+ PDP : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/pdp/',
+ MODELS : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/models/',
+ METARULES: 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/meta_rules/',
+ RULES: 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/rules/',
+ POLICIES: 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/policies/',
+ METADATA: {
+ subject : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/subject_categories/',
+ object : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/object_categories/',
+ action : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/action_categories/'
+ },
+ PERIMETERS :{
+ subject : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/subjects/',
+ object : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/objects/',
+ action : 'http://{{MANAGER_HOST}}:{{MANAGER_PORT}}/actions/'
+ },
+ KEYSTONE : 'http://{{KEYSTONE_HOST}}:{{KEYSTONE_PORT}}/v3/'
+ });
+})();
diff --git a/moon_gui/static/app/moon.module.js b/moon_gui/static/app/moon.module.js
new file mode 100755
index 00000000..a653f8f3
--- /dev/null
+++ b/moon_gui/static/app/moon.module.js
@@ -0,0 +1,362 @@
+/**
+# Copyright 2015 Orange
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+ */
+
+(function() {
+
+ 'use strict';
+
+ var moon = angular
+
+ .module('moon', ['ngResource',
+ 'ngRoute',
+ 'ui.router',
+ 'ngMessages',
+ 'ui.bootstrap',
+ 'ngTable',
+ 'ngCookies',
+ 'ngStorage',
+ 'pascalprecht.translate',
+ 'ngAnimate',
+ 'mgcrea.ngStrap',
+ 'NgSwitchery',
+ 'ui.select',
+ 'toaster'])
+
+ .config(configure)
+ .run(runner);
+
+ /*
+ * configure
+ */
+
+ configure.$inject = ['$urlRouterProvider', '$translateProvider', '$stateProvider', 'uiSelectConfig'];
+
+ function configure($urlRouterProvider, $translateProvider, $stateProvider, uiSelectConfig) {
+
+ /*
+ * translate
+ */
+
+ $translateProvider
+ .useStaticFilesLoader({
+ prefix: 'assets/i18n/',
+ suffix: '.json'
+ })
+ .preferredLanguage('en')
+ .useCookieStorage();
+
+ /*
+ * ui-select
+ */
+
+ uiSelectConfig.theme = 'selectize';
+
+ /*
+ * routes
+ */
+
+ $urlRouterProvider.when('', '/project');
+ $urlRouterProvider.when('/', '/project');
+ $urlRouterProvider.otherwise('/404');
+
+ configureDefaultRoutes($stateProvider);
+
+ configureDashboard($stateProvider);
+
+ configureAuthRoutes($stateProvider);
+
+ configureProjectRoutes($stateProvider);
+
+ configureModelRoutes($stateProvider);
+
+ configurePDPRoutes($stateProvider);
+
+ configurePolicyRoutes($stateProvider);
+
+ configureLogsRoutes($stateProvider);
+
+ }
+
+ function configureDefaultRoutes($stateProvider) {
+
+ $stateProvider
+
+ .state('moon', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.404', {
+ url: '/404',
+ templateUrl: 'html/common/404/404.tpl.html'
+ });
+
+ return $stateProvider;
+
+ }
+
+ function configureDashboard($stateProvider){
+
+ $stateProvider
+
+ .state('moon.dashboard',{
+ url: '/dashboard',
+ templateUrl: 'html/dashboard/dashboard.tpl.html'
+ });
+
+ return $stateProvider;
+
+ }
+
+ function configureAuthRoutes($stateProvider){
+
+ $stateProvider
+
+ .state('moon.auth', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.auth.login', {
+ url: '/login',
+ templateUrl: 'html/authentication/authentication.tpl.html',
+ controller: 'AuthenticationController',
+ controllerAs: 'auth'
+ });
+
+ return $stateProvider;
+ }
+
+ function configureModelRoutes($stateProvider) {
+
+ $stateProvider
+
+ .state('moon.model', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.model.list', {
+ url: '/model',
+ templateUrl: 'html/model/model-list.tpl.html',
+ controller: 'ModelListController',
+ controllerAs: 'list',
+ resolve: {
+ models: ['modelService', function(modelService) {
+ return modelService.findAll();
+ }]
+ }
+ })
+
+ .state('moon.model.edit', {
+ url: '/model/:id',
+ templateUrl: 'html/model/edit/model-edit.tpl.html',
+ controller: 'ModelEditController',
+ controllerAs: 'edit',
+ resolve: {
+ model: ['$stateParams','modelService', function($stateParams, modelService) {
+ return modelService.findOneWithMetaRules($stateParams.id);
+ }]
+ }
+ });
+
+
+ return $stateProvider;
+
+ }
+
+ function configureProjectRoutes($stateProvider) {
+
+ $stateProvider
+
+ .state('moon.project', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.project.list', {
+ url: '/project',
+ templateUrl: 'html/project/project-list.tpl.html',
+ controller: 'ProjectListController',
+ controllerAs: 'list',
+ resolve: {
+ projects: ['projectService', function(projectService) {
+ return projectService.findAll();
+ }]
+ }
+ });
+
+ return $stateProvider;
+
+ }
+
+ function configurePDPRoutes($stateProvider) {
+
+ $stateProvider
+
+ .state('moon.pdp', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.pdp.list', {
+ url: '/pdp',
+ templateUrl: 'html/pdp/pdp-list.tpl.html',
+ controller: 'PDPListController',
+ controllerAs: 'list',
+ resolve: {
+ pdps: ['pdpService', function(pdpService) {
+ return pdpService.findAll();
+ }]
+ }
+ })
+
+ .state('moon.pdp.edit', {
+ url: '/pdp/:id',
+ templateUrl: 'html/pdp/edit/pdp-edit.tpl.html',
+ controller: 'PDPEditController',
+ controllerAs: 'edit',
+ resolve: {
+ pdp: ['$stateParams','pdpService', function($stateParams, pdpService) {
+ return pdpService.findOne($stateParams.id);
+ }]
+ }
+ });
+
+ return $stateProvider;
+
+ }
+
+ function configurePolicyRoutes($stateProvider) {
+
+ $stateProvider
+
+ .state('moon.policy', {
+ abstract: true,
+ template: '<div ui-view></div>'
+ })
+
+ .state('moon.policy.list', {
+ url: '/policy',
+ templateUrl: 'html/policy/policy-list.tpl.html',
+ controller: 'PolicyListController',
+ controllerAs: 'list',
+ resolve: {
+ policies: ['policyService', function(policyService) {
+ return policyService.findAll();
+ }]
+ }
+ })
+
+ .state('moon.policy.edit', {
+ url: '/policy/:id',
+ templateUrl: 'html/policy/edit/policy-edit.tpl.html',
+ controller: 'PolicyEditController',
+ controllerAs: 'edit',
+ resolve: {
+ policy: ['$stateParams','policyService', function($stateParams, policyService) {
+ return policyService.findOne($stateParams.id);
+ }]
+ }
+ });
+
+
+ return $stateProvider;
+
+ }
+
+ function configureLogsRoutes($stateProvider){
+
+ $stateProvider
+
+ .state('moon.logs', {
+ url: '/logs',
+ templateUrl: 'html/logs/logs.tpl.html',
+ controller: 'LogsController',
+ controllerAs: 'logs'
+ });
+
+ return $stateProvider;
+ }
+
+ /*
+ * runner
+ */
+
+ runner.$inject = ['$rootScope', '$modal', '$translate', 'alertService', 'authenticationService', '$sessionStorage', '$location'];
+
+ function runner($rootScope, $modal, $translate, alertService, authenticationService, $sessionStorage, $location) {
+
+ $rootScope.connected = authenticationService.IsConnected();
+
+ $rootScope.transitionModal = $modal({ scope: $rootScope, template: 'html/common/waiting/waiting.tpl.html', backdrop: 'static', show: false });
+
+ $rootScope.$on('$stateChangeStart', stateChangeStart);
+ $rootScope.$on('$stateChangeSuccess', stateChangeSuccess);
+ $rootScope.$on('$stateChangeError', stateChangeError);
+ $rootScope.$on('$locationChangeStart', locationChangeStart);
+
+ // keep user logged in after page refresh
+ if (authenticationService.IsConnected()) {
+ authenticationService.SetTokenHeader(authenticationService.GetTokenHeader());
+ }
+
+ // redirect to login page if not logged in and trying to access a restricted pages
+ function locationChangeStart(event, next, current) {
+ var publicPages = ['/login'];
+ var restrictedPage = publicPages.indexOf($location.path()) === -1;
+ if (restrictedPage && !$sessionStorage.currentUser) {
+ $location.path('/login');
+ }
+ }
+
+ function stateChangeStart() {
+ $rootScope.connected = authenticationService.IsConnected();
+ $rootScope.transitionModal.$promise.then($rootScope.transitionModal.show);
+ }
+
+ function stateChangeSuccess() {
+ $rootScope.transitionModal.hide();
+ }
+
+ function stateChangeError(event, toState, toParams, fromState, fromParams, error) {
+
+ var stacktrace = getStacktrace(event, toState, toParams, fromState, fromParams, error);
+
+ $translate('moon.global.error', { stacktrace: stacktrace }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ $rootScope.transitionModal.hide();
+
+ }
+
+ function getStacktrace(event, toState, toParams, fromState, fromParams, error) {
+
+ var stacktrace = {};
+
+ stacktrace.status = error.status;
+ stacktrace.message = error.statusText;
+ stacktrace.state = toState;
+ stacktrace.params = toParams;
+
+ return stacktrace;
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/pdp/action/pdp-add.tpl.html b/moon_gui/static/app/pdp/action/pdp-add.tpl.html
new file mode 100755
index 00000000..f83fb85c
--- /dev/null
+++ b/moon_gui/static/app/pdp/action/pdp-add.tpl.html
@@ -0,0 +1,88 @@
+<div ng-controller="PDPAddController as add" class="modal" tabindex="-1" data-role="modalAddPDP">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.pdp.add.title"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="add.form">
+
+ <div class="form-group" ng-class="{'has-error': add.form.name.$invalid && add.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.pdp.add.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="add.pdp.name" required />
+
+ <div class="help-block" ng-show="add.form.name.$dirty && add.form.name.$invalid">
+ <small class="error" ng-show="add.form.name.$error.required" data-translate="moon.pdp.add.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': add.form.policy.$dirty && (add.form.policy.$invalid || !add.selectedPolicy)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.pdp.add.form.policy">Policy</label>
+
+ <div class="col-sm-6" ng-if="!add.loadingPolicies">
+
+ <ui-select ng-model="add.selectedPolicy" name="policy" required>
+ <ui-select-match placeholder="(None)">{{$select.selected.name}}</ui-select-match>
+ <ui-select-choices repeat="policy in add.policies">
+ <div ng-value="policy">{{policy.name}}</div>
+ </ui-select-choices>
+ </ui-select>
+
+ <div class="help-block" ng-show="add.form.policy.$dirty && (add.form.policy.$invalid || !add.selectedPolicy)">
+ <small class="error" ng-show="add.form.policy.$error.required" data-translate="moon.pdp.add.check.policy.required">Policy is required</small>
+ </div>
+
+ </div>
+
+ <div class="col-sm-6" ng-if="add.loadingPolicies">
+ <moon-loader ng-if="add.loadingPolicies" ></moon-loader>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.pdp.add.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea name="description" id="description" class="form-control" ng-model="add.pdp.description"></textarea>
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.pdp.add.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="add.loading" ng-click="add.create(add.pdp)" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.pdp.add.action.create">Create</span>
+ </a>
+ <moon-loader ng-if="add.loading"></moon-loader>
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/pdp/action/pdp-delete.tpl.html b/moon_gui/static/app/pdp/action/pdp-delete.tpl.html
new file mode 100755
index 00000000..167ba417
--- /dev/null
+++ b/moon_gui/static/app/pdp/action/pdp-delete.tpl.html
@@ -0,0 +1,35 @@
+<div ng-controller="PDPDeleteController as del" class="modal" tabindex="-1" data-role="modalDeletePDP">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.pdp.remove.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <span data-translate="moon.pdp.remove.content" data-translate-values="{ pdpName: del.pdp.name}"></span>
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.pdp.remove.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="del.loading" ng-click="del.remove()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.pdp.remove.action.delete">Delete</span>
+ </a>
+
+ <moon-loader ng-if="del.loading"></moon-loader>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/pdp/action/pdp.controller.add.js b/moon_gui/static/app/pdp/action/pdp.controller.add.js
new file mode 100755
index 00000000..d1c34c79
--- /dev/null
+++ b/moon_gui/static/app/pdp/action/pdp.controller.add.js
@@ -0,0 +1,108 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PDPAddController', PDPAddController);
+
+ PDPAddController.$inject = ['$scope', '$translate', 'alertService', 'formService', 'pdpService', 'policyService', 'utilService'];
+
+ function PDPAddController($scope, $translate, alertService, formService, pdpService, policyService, utilService) {
+
+ var add = this;
+
+ /*
+ *
+ */
+
+ add.form = {};
+
+ add.pdp = {};
+
+ add.policies = [];
+
+ add.selectedPolicy = null;
+
+ add.loading = false;
+ add.loadingPolicies = true;
+
+ add.create = createPDP;
+
+ resolvePolicies();
+
+ /*
+ *
+ */
+
+ /**
+ * This function return an array of all policies/template ids
+ */
+ function resolvePolicies() {
+
+ policyService.findAllWithCallback(function(policies){
+
+ add.policies = policies;
+ add.loadingPolicies = false;
+ });
+
+ }
+
+ function createPDP(pdp) {
+
+ if(formService.isInvalid(add.form)) {
+
+ formService.checkFieldsValidity(add.form);
+
+ } else {
+
+ add.loading = true;
+
+ pdpService.data.pdp.create({}, {
+
+ name: add.pdp.name,
+ description: add.pdp.description,
+ security_pipeline: [add.selectedPolicy.id],
+ keystone_project_id: null
+
+ }, createSuccess, createError);
+
+ }
+
+ function createSuccess(data) {
+
+ $translate('moon.pdp.add.success', { pdpName: pdp.name })
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ var createdPdp = utilService.transformOne(data, 'pdps');
+
+ add.loading = false;
+
+ $scope.$emit('event:pdpCreatedSuccess', createdPdp);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.pdp.add.error', { pdpName: pdp.name })
+ .then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:pdpCreatedError');
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/pdp/action/pdp.controller.delete.js b/moon_gui/static/app/pdp/action/pdp.controller.delete.js
new file mode 100755
index 00000000..62557864
--- /dev/null
+++ b/moon_gui/static/app/pdp/action/pdp.controller.delete.js
@@ -0,0 +1,66 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PDPDeleteController', PDPDeleteController);
+
+ PDPDeleteController.$inject = ['$scope', '$translate', 'alertService', 'pdpService'];
+
+ function PDPDeleteController($scope, $translate, alertService, pdpService) {
+
+ var del = this;
+
+ /*
+ *
+ */
+
+ del.pdp = $scope.pdp;
+ del.loading = false;
+ del.remove = deletePDP;
+
+ /*
+ *
+ */
+
+ function deletePDP() {
+ del.loading = true;
+
+ pdpService.data.pdp.remove({pdp_id: del.pdp.id}, deleteSuccess, deleteError);
+
+ function deleteSuccess(data) {
+
+ $translate('moon.pdp.remove.success', { pdpName: del.pdp.name })
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:pdpDeletedSuccess', del.pdp);
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.pdp.remove.error', { pdpName: del.pdp.name })
+ .then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:pdpDeletedError', del.pdp);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html b/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html
new file mode 100755
index 00000000..887d81ca
--- /dev/null
+++ b/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html
@@ -0,0 +1,65 @@
+<div class="row">
+
+ <form class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group">
+
+ <label for="id" class="col-sm-3 control-label" data-translate="moon.pdp.edit.basic.form.id">Id</label>
+
+ <div class="col-sm-6">
+
+ <input name="id" id="id" disabled class="form-control" type="text" data-ng-model="edit.pdpToEdit.id" required />
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.pdp.edit.basic.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.pdpToEdit.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.pdp.edit.basic.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.pdp.edit.basic.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.pdpToEdit.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="col-sm-2 col-sm-offset-3">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.init()" class="btn btn-default">
+ <span data-translate="moon.pdp.edit.basic.action.init">Init</span>
+ </a>
+ </div>
+
+ <div class="col-sm-4 col-sm-offset-2">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.editPdp()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.pdp.edit.basic.action.update">Update</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+ </div>
+
+ </div>
+
+ </form>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html b/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html
new file mode 100755
index 00000000..1fbd555a
--- /dev/null
+++ b/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html
@@ -0,0 +1,64 @@
+<div class="container">
+
+ <div class="row">
+ <h3 class="pull-left" data-translate="moon.pdp.edit.title" data-translate-values="{ pdpName: edit.pdp.name }">Edit</h3>
+ </div>
+
+ <div class="row">
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4>
+ <span data-translate="moon.pdp.edit.basic.title" >Basic Information</span>
+ <a href="" ng-click="edit.editBasic = !edit.editBasic">
+ <span data-translate="moon.pdp.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>
+ </h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div ng-if="edit.editBasic">
+ <moon-p-d-p-edit-basic pdp="edit.pdp"></moon-p-d-p-edit-basic>
+ </div>
+
+ <div ng-if="!edit.editBasic">
+ <dl class="dl-horizontal">
+ <dt>Id</dt>
+ <dd ng-bind="edit.pdp.id"></dd>
+ <dt>Name</dt>
+ <dd ng-bind="edit.pdp.name"></dd>
+ <dt>Description</dt>
+ <dd ng-bind="edit.pdp.description"></dd>
+ </dl>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.pdp.edit.policy.title" >Policies</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="row">
+
+ <moon-policy-mapped-list pdp="edit.pdp"></moon-policy-mapped-list>
+
+ </div>
+
+ </div>
+
+ </div>
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/pdp/edit/pdp.controller.edit.js b/moon_gui/static/app/pdp/edit/pdp.controller.edit.js
new file mode 100755
index 00000000..41b73098
--- /dev/null
+++ b/moon_gui/static/app/pdp/edit/pdp.controller.edit.js
@@ -0,0 +1,50 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PDPEditController', PDPEditController);
+
+ PDPEditController.$inject = ['$scope', '$rootScope', 'pdp', '$stateParams'];
+
+ function PDPEditController($scope, $rootScope, pdp, $stateParams) {
+
+ var edit = this;
+
+ edit.pdp = pdp;
+
+ edit.editBasic = false;
+
+ activate();
+
+ function activate(){
+
+ }
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:pdpUpdatedSuccess': $rootScope.$on('event:pdpUpdatedSuccess', pdpUpdatedSuccess)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ /**
+ * When the model is updated, this function refresh the current model with the new changes
+ * @param event
+ * @param pdp
+ */
+ function pdpUpdatedSuccess(event, pdp){
+
+ edit.pdp = pdp;
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js b/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js
new file mode 100755
index 00000000..402422b6
--- /dev/null
+++ b/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js
@@ -0,0 +1,97 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonPDPEditBasic', moonPDPEditBasic);
+
+ moonPDPEditBasic.$inject = [];
+
+ function moonPDPEditBasic() {
+
+ return {
+ templateUrl : 'html/pdp/edit/pdp-edit-basic.tpl.html',
+ bindToController : true,
+ controller : moonPDPEditBasicController,
+ controllerAs : 'edit',
+ scope : {
+ pdp : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonPDPEditBasicController', moonPDPEditBasicController);
+
+ moonPDPEditBasicController.$inject = ['$scope', 'pdpService', 'formService', 'alertService', '$translate', 'utilService'];
+
+ function moonPDPEditBasicController($scope, pdpService, formService, alertService, $translate, utilService){
+
+ var edit = this;
+
+ edit.editPdp = editPdp;
+ edit.init = init;
+
+ edit.form = {};
+
+ activate();
+
+ function activate(){
+
+ edit.pdp = $scope.edit.pdp;
+
+ edit.pdpToEdit = angular.copy(edit.pdp);
+
+ }
+
+ function editPdp(){
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ }else{
+
+ edit.loading = true;
+
+ pdpService.update(edit.pdpToEdit, updateSuccess, updateError);
+
+ }
+
+ function updateSuccess(data) {
+
+ var updatedPdp = utilService.transformOne(data, 'pdps');
+
+ $translate('moon.pdp.edit.basic.success', { pdpName: updatedPdp.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ edit.loading = false;
+
+ $scope.$emit('event:pdpUpdatedSuccess', updatedPdp);
+
+ }
+
+ function updateError(reason) {
+
+ $translate('moon.pdp.edit.basic.error', { pdpName: edit.pdp.name }).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ edit.loading = false;
+
+ }
+ }
+
+ function init(){
+
+ edit.pdpToEdit = angular.copy(edit.pdp);
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/pdp/pdp-list.tpl.html b/moon_gui/static/app/pdp/pdp-list.tpl.html
new file mode 100755
index 00000000..8aa4e653
--- /dev/null
+++ b/moon_gui/static/app/pdp/pdp-list.tpl.html
@@ -0,0 +1,133 @@
+
+<div class="container">
+
+ <div>
+ <form class="form-inline pull-right">
+ <div class="form-group">
+ <div>
+ <input id="searchPDP" data-ng-model="list.search.query" type="text" class="form-control" placeholder="{{'moon.pdp.list.search.placeholder' | translate}}" />
+ </div>
+ </div>
+ <div class="form-group">
+ <div>
+ <button type="submit" class="btn btn-danger" data-ng-click="list.search.reset()" data-translate="moon.pdp.list.search.reset">Reset</button>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+
+ <div class="row" >
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.pdp.list.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('security_pipeline', 'asc'), 'sort-desc': list.table.isSortBy('security_pipeline', 'desc') }"
+ ng-click="list.table.sorting('security_pipeline', list.table.isSortBy('policy', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.pdp.list.table.security_pipeline.number">Number of Securities</div>
+ </th>
+
+ <th class="customTables"
+ ng-class="{ 'sort-asc': list.table.isSortBy('project', 'asc'), 'sort-desc': list.table.isSortBy('project', 'desc') }"
+ ng-click="list.table.sorting('project', list.table.isSortBy('project', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.pdp.list.table.project">Project</div>
+ </th>
+
+ <th class="customTables">
+ <div data-translate="moon.pdp.list.action.title">Actions</div>
+ </th>
+
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasPDPs()">
+ <tr>
+ <td colspan="12"><span data-translate="moon.pdp.list.table.notFound">There is no PDP</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasPDPs()">
+
+ <tr ng-repeat="pdp in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td ng-bind="list.getPDPName(pdp)"></td>
+ <td ng-bind="list.getSecPipelineFromPdp(pdp).length"></td>
+ <td>
+ <div ng-if="list.isMapped(pdp)">
+
+ <div ng-if="!list.getProjectFromPDP(pdp)">
+ <moon-loader ng-if="!list.getProjectFromPDP(pdp)" ></moon-loader>
+ <em data-translate="moon.pdp.list.table.loading.project">Loading Project</em>
+ </div>
+
+ <div ng-if="list.getProjectFromPDP(pdp)">
+ <span ng-bind="pdp.project.name"></span>
+ </div>
+
+ </div>
+
+ <div ng-if="!list.isMapped(pdp)">
+ <span data-translate="moon.pdp.list.table.mapping.map">Is not mapped</span>
+ </div>
+ </td>
+ <td>
+ <div class="dropdown">
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.pdp.list.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ui-sref="moon.pdp.edit({id: pdp.id})">
+ <span class="glyphicon glyphicon-cog"></span>
+ <span class="control-label" data-translate="moon.pdp.list.action.edit">Edit</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.del.showModal(pdp)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.pdp.list.action.delete">Delete</span>
+ </a>
+ </li>
+ </ul>
+ </div>
+ </td>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ <div class="container">
+ <div class="form-inline form-group">
+ <a href="" ng-click="list.add.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-plus-sign"></span>
+ <span data-translate="moon.pdp.list.action.add">Add PDP</span>
+ </a>
+ </div>
+ </div>
+
+ </div>
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/pdp/pdp.controller.list.js b/moon_gui/static/app/pdp/pdp.controller.list.js
new file mode 100755
index 00000000..a831cfe3
--- /dev/null
+++ b/moon_gui/static/app/pdp/pdp.controller.list.js
@@ -0,0 +1,284 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PDPListController', PDPListController);
+
+ PDPListController.$inject = [
+ '$rootScope',
+ '$scope',
+ '$filter',
+ '$modal',
+ 'NgTableParams',
+ 'pdps',
+ 'projectService'];
+
+ function PDPListController($rootScope,
+ $scope,
+ $filter,
+ $modal,
+ NgTableParams,
+ pdps,
+ projectService) {
+
+ var list = this;
+
+ list.pdps = pdps;
+ list.mappings = [];
+
+
+ list.getPDPs = getPDPs;
+ list.hasPDPs = hasPDPs;
+ list.getPDPName = getPDPName;
+ list.isMapped = isMapped;
+ list.getProjectFromPDP = getProjectFromPDP;
+ list.getidFromPDP = getidFromPDP;
+
+ list.table = {};
+
+ list.addPDP = addPDP;
+ list.deletePDP = deletePDP;
+ list.refreshPDPs = refreshPDPs;
+ list.updatePDPs = updatePDPs;
+
+ list.getMappedProjectName = getMappedProjectName;
+ list.getSecPipelineFromPdp = getSecPipelineFromPdp;
+
+ list.search = { query: '',
+ find: searchPDP,
+ reset: searchReset };
+
+ list.add = { modal: $modal({ template: 'html/pdp/action/pdp-add.tpl.html', show: false }),
+ showModal: showAddModal };
+
+ list.del = { modal: $modal({ template: 'html/pdp/action/pdp-delete.tpl.html', show: false }),
+ showModal: showDeleteModal };
+
+ activate();
+
+ function activate(){
+ newPDPsTable();
+ }
+
+ /*
+ * ---- events
+ */
+
+ var rootListeners = {
+
+ 'event:pdpCreatedSuccess': $rootScope.$on('event:pdpCreatedSuccess', pdpCreatedSuccess),
+ 'event:pdpCreatedError': $rootScope.$on('event:pdpCreatedError', pdpCreatedError),
+
+ 'event:pdpDeletedSuccess': $rootScope.$on('event:pdpDeletedSuccess', pdpDeletedSuccess),
+ 'event:pdpDeletedError': $rootScope.$on('event:pdpDeletedError', pdpDeletedError),
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+ /*
+ *
+ */
+
+ /**
+ * Function getting an array of PDP JSON
+ * @return An array of valid pdp.
+ */
+ function getPDPs() {
+ return (list.pdps) ? list.pdps : [];
+ }
+
+ function hasPDPs() {
+ return list.getPDPs().length > 0;
+ }
+
+ function addPDP(pdp) {
+ list.pdps.push(pdp);
+ }
+
+ function deletePDP(pdp) {
+
+ list.pdps = _.chain(list.pdps).reject({id: pdp.id}).value();
+
+ }
+
+ function refreshPDPs() {
+
+ list.table.total(list.pdps.length);
+ list.table.reload();
+
+ }
+
+ function updatePDPs(pdp) {
+
+ _(_.values(list.getPDPs())).each(function(anPDP) {
+ if(anPDP.id === pdp.id) {
+ //@todo: Determine what this code should have been designed to do
+ anPDP = _.clone(pdp);
+ }
+ });
+
+ return list.pdps;
+
+ }
+
+ /**
+ * Get the id from an PDP
+ * @param pdp The inspected pdp
+ * @returns {*} Its UUID
+ */
+ function getidFromPDP(pdp) {
+ return pdp.id;
+ }
+
+ function getMappedProjectName(pdp) {
+ return pdp.tenant.name;
+ }
+
+ /**
+ * Get the name of the PDP
+ * @param pdp The PDP to inspect
+ * @returns {*} Its name.
+ */
+ function getPDPName(pdp) {
+ return (pdp) ? pdp.name : '';
+ }
+
+ function isMapped(pdp) {
+ return !_.isNull(pdp.keystone_project_id);
+ }
+
+ /**
+ * Prerequisite : before calling this method, isMapped should return true before
+ * @param pdp
+ * @returns false or {*}, false if the project is currently loading
+ */
+ function getProjectFromPDP(pdp) {
+
+ if(_.has(pdp, 'project')){
+ return pdp.project;
+ }
+
+ // if the call has not been made
+ if(!_.has(pdp, 'callPdpInProgress')){
+
+ pdp.callPdpInProgress = true;
+
+ projectService.findOne(pdp.keystone_project_id, function(project){
+ pdp.callPdpInProgress = false;
+ pdp.project = project;
+ return pdp.project;
+ });
+ }
+
+ // if the call is in progress return false
+ return false;
+ }
+
+ /**
+ * Generate a table item, directly usable by the rendering engine
+ * @returns {{}|*} the table
+ */
+ function newPDPsTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+
+ }, {
+
+ total: function () { return list.getPDPs().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getPDPs(), params.orderBy()) : list.getPDPs();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+
+ /*
+ * --- search
+ */
+
+ /**
+ * Indicate if an pdp having a specified name exists
+ * @param pdp Searched name
+ * @returns {boolean} True if a corresponding pdp is found, false otherwise
+ */
+ function searchPDP(pdp){
+ return list.getPDPName(pdp).indexOf(list.search.query) !== -1 || list.getSecPipelineFromPdp(pdp).indexOf(list.search.query) !== -1 ;
+ }
+
+ function getSecPipelineFromPdp(pdp){
+ return (pdp.security_pipeline) ? pdp.security_pipeline : [];
+ }
+
+ /**
+ * Blank the search field
+ */
+ function searchReset() {
+ list.search.query = '';
+ }
+
+ /*
+ * ---- add
+ */
+
+ function showAddModal() {
+ list.add.modal.$promise.then(list.add.modal.show);
+ }
+
+ function pdpCreatedSuccess(event, pdp) {
+
+ list.addPDP(pdp);
+ list.refreshPDPs();
+
+ list.add.modal.hide();
+
+ }
+
+ function pdpCreatedError(event, pdp) {
+ list.add.modal.hide();
+ }
+
+ /*
+ * ---- delete
+ */
+
+ function showDeleteModal(pdp) {
+ list.del.modal.$scope.pdp = pdp;
+ list.del.modal.$promise.then(list.del.modal.show);
+ }
+
+ function pdpDeletedSuccess(event, pdp) {
+
+ list.deletePDP(pdp);
+ list.refreshPDPs();
+
+ list.del.modal.hide();
+
+ }
+
+ function pdpDeletedError() {
+ list.del.modal.hide();
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html b/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html
new file mode 100755
index 00000000..8b787f14
--- /dev/null
+++ b/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html
@@ -0,0 +1,64 @@
+<div ng-controller="PolicyMapController as map" class="modal" tabindex="-1" data-role="modalMappingPolicy">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.policy.map.title" data-translate-values="{ pdpName: map.pdp.name}"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="map.form">
+
+ <div class="form-group" ng-class="{'has-error': map.form.policy.$dirty && (map.form.policy.$invalid || !map.selectedPolicy)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.map.form.list">List of Policies</label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="map.selectedPolicy" name="policy" required>
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="policy in map.policies">
+ <div ng-bind="policy.name" ng-value="policy"></div>
+ </ui-select-choices>
+ </ui-select>
+
+ <moon-loader ng-if="map.policiesLoading"></moon-loader>
+
+ <div class="help-block" ng-show="map.form.policy.$dirty && (map.form.policy.$invalid || !map.selectedPolicy)">
+ <small class="error" ng-show="map.form.policy.$error.required" data-translate="moon.policy.map.check.policy.required">Policy is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.policy.map.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="map.mappingLoading" ng-click="map.map()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.policy.map.action.map">Map</span>
+ </a>
+
+ <moon-loader ng-if="map.mappingLoading"></moon-loader>
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html b/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html
new file mode 100755
index 00000000..a2cda52a
--- /dev/null
+++ b/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html
@@ -0,0 +1,33 @@
+<div ng-controller="PolicyUnMapController as unmap" class="modal" tabindex="-1" data-role="modalUnmapPolicy">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.policy.unmap.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <span data-translate="moon.policy.unmap.content" data-translate-values="{ policyName: unmap.policy.name, pdpName: unmap.pdp.name }"></span>
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.policy.unmap.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="unmap.unMappingLoading" ng-click="unmap.unmap()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span data-translate="moon.policy.unmap.action.unmap">Unmap</span>
+ </a>
+ <moon-loader ng-if="unmap.unMappingLoading"></moon-loader>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/action/mapping/policy.controller.map.js b/moon_gui/static/app/policy/action/mapping/policy.controller.map.js
new file mode 100755
index 00000000..6ad8caa7
--- /dev/null
+++ b/moon_gui/static/app/policy/action/mapping/policy.controller.map.js
@@ -0,0 +1,106 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyMapController', PolicyMapController);
+
+ PolicyMapController.$inject = ['$scope', 'alertService', '$translate', 'formService', 'policyService', 'pdpService', 'utilService'];
+
+ function PolicyMapController($scope, alertService, $translate, formService, policyService, pdpService, utilService ) {
+
+ var map = this;
+
+ /*
+ *
+ */
+
+ map.pdps = [];
+
+ map.pdp = $scope.pdp;
+
+ map.addPolicyToList = false;
+
+ map.map = mapToPdp;
+
+ activate();
+
+ function activate() {
+
+ resolvePolicies();
+
+ }
+
+ function resolvePolicies() {
+
+ map.policiesLoading = true;
+
+ policyService.findAllWithCallback(function(policies){
+ map.policies = policies;
+ map.policiesLoading = false;
+ }
+ );
+
+ }
+
+ function mapToPdp() {
+
+ if (formService.isInvalid(map.form)) {
+
+ formService.checkFieldsValidity(map.form);
+
+ } else {
+
+ map.mappingLoading = true;
+
+ var pdpToSend = angular.copy(map.pdp);
+
+ pdpToSend.security_pipeline.push(map.selectedPolicy.id);
+
+ pdpService.update(pdpToSend, mapSuccess, mapError);
+
+ }
+
+ function mapSuccess(data) {
+
+ var pdpReceived = utilService.transformOne(data, 'pdps');
+
+
+ $translate('moon.policy.map.success', {pdpName: pdpReceived.name, policyName: map.selectedPolicy.name}).then(function (translatedValue) {
+
+ alertService.alertSuccess(translatedValue);
+
+ });
+
+ map.mappingLoading = false;
+
+ $scope.$emit('event:policyMapToPdpSuccess', pdpReceived);
+
+ }
+
+ function mapError(response) {
+
+ $translate('moon.policy.map.error', {
+
+ pdpName: map.pdp.name,
+ policyName: map.selectedPolicy.name
+
+ }).then(function (translatedValue) {
+
+ alertService.alertError(translatedValue);
+
+ });
+
+ map.mappingLoading = false;
+
+ $scope.$emit('event:policyMapToPdpError');
+
+ }
+ }
+
+
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js b/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js
new file mode 100755
index 00000000..d309ec0f
--- /dev/null
+++ b/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js
@@ -0,0 +1,74 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyUnMapController', PolicyUnMapController);
+
+ PolicyUnMapController.$inject = ['$scope', '$translate', 'alertService', 'pdpService', 'utilService'];
+
+ function PolicyUnMapController($scope, $translate, alertService, pdpService, utilService) {
+
+ var unmap = this;
+
+ /*
+ *
+ */
+
+ unmap.pdp = $scope.pdp;
+ unmap.policy = $scope.policy;
+
+ unmap.unMappingLoading = false;
+
+ unmap.unmap = unMapPolicyToPdp;
+
+ /*
+ *
+ */
+
+ function unMapPolicyToPdp() {
+
+ unmap.unMappingLoading = true;
+
+ var pdpToUpdate = angular.copy(unmap.pdp);
+
+ pdpToUpdate.security_pipeline = _.without(pdpToUpdate.security_pipeline, unmap.policy.id);
+
+ pdpService.update(pdpToUpdate, unMapSuccess, unMapError);
+
+ function unMapSuccess(data) {
+
+ $translate('moon.policy.unmap.success', { pdpName: unmap.pdp.name, policyName: unmap.policy.name })
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ $scope.$emit('event:policyUnMappedToPdpSuccess', utilService.transformOne(data, 'pdps'));
+
+ }
+
+ function unMapError(reason) {
+
+ $translate('moon.policy.unmap.error', { pdpName: unmap.pdp.name, policyName: unmap.policy.name })
+ .then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ $scope.$emit('event:policyUnMappedToPdpError');
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/action/policy-add.tpl.html b/moon_gui/static/app/policy/action/policy-add.tpl.html
new file mode 100755
index 00000000..d20c41be
--- /dev/null
+++ b/moon_gui/static/app/policy/action/policy-add.tpl.html
@@ -0,0 +1,113 @@
+<div ng-controller="PolicyAddController as add" class="modal" tabindex="-1" data-role="modalAddPolicy">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.policy.add.title"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="add.form">
+
+ <div class="form-group" ng-class="{'has-error': add.form.name.$invalid && add.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.policy.add.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="add.policy.name" required />
+
+ <div class="help-block" ng-show="add.form.name.$dirty && add.form.name.$invalid">
+ <small class="error" ng-show="add.form.name.$error.required" data-translate="moon.policy.add.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error': add.form.genre.$dirty && (add.form.genre.$invalid || !add.selectedGenre)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.add.form.genre">Genre</label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="add.selectedGenre" name="genre" required>
+ <ui-select-match placeholder="(None)">{{$select.selected}}</ui-select-match>
+ <ui-select-choices repeat="genre in add.genres">
+ <div ng-value="genre">{{genre}}</div>
+ </ui-select-choices>
+ </ui-select>
+
+ <div class="help-block" ng-show="add.form.genre.$dirty && (add.form.genre.$invalid || !add.selectedPolicy)">
+ <small class="error" ng-show="add.form.genre.$error.required" data-translate="moon.policy.add.check.genre.required">Genre is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': add.form.model.$dirty && (add.form.model.$invalid || !add.selectedModel)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.add.form.model">Models</label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="add.selectedModel" name="model" required>
+ <ui-select-match placeholder="(None)">{{$select.selected.name}}</ui-select-match>
+ <ui-select-choices repeat="model in add.models">
+ <div ng-value="model">{{model.name}}</div>
+ </ui-select-choices>
+ </ui-select>
+
+ <moon-loader ng-if="add.modelsLoading"></moon-loader>
+
+ <div class="help-block" ng-show="add.form.model.$dirty && (add.form.model.$invalid || !add.selectedModel)">
+ <small class="error" ng-show="add.form.model.$error.required" data-translate="moon.policy.add.check.model.required">Model is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.policy.add.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="add.policy.description"></textarea>
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.policy.add.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="add.loading" ng-click="add.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.add.action.create">Create Policy</span>
+ </a>
+ <moon-loader ng-if="add.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/policy/action/policy-delete.tpl.html b/moon_gui/static/app/policy/action/policy-delete.tpl.html
new file mode 100755
index 00000000..3b5df88b
--- /dev/null
+++ b/moon_gui/static/app/policy/action/policy-delete.tpl.html
@@ -0,0 +1,40 @@
+<div ng-controller="PolicyDeleteController as del" class="modal" tabindex="-1" data-role="modalDeletePolicy">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.policy.remove.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <p><span data-translate="moon.policy.remove.content.query" data-translate-values="{ policyName: del.policy.name }"></span></p>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.policy.remove.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="del.loading" ng-click="del.remove()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.policy.remove.action.delete">Delete</span>
+ </a>
+
+ <moon-loader ng-if="del.loading" ></moon-loader>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/action/policy.controller.add.js b/moon_gui/static/app/policy/action/policy.controller.add.js
new file mode 100755
index 00000000..0320c2e9
--- /dev/null
+++ b/moon_gui/static/app/policy/action/policy.controller.add.js
@@ -0,0 +1,113 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyAddController', PolicyAddController);
+
+ PolicyAddController.$inject = ['$scope', '$translate', 'alertService', 'formService', 'policyService', 'utilService', 'modelService'];
+
+ function PolicyAddController($scope, $translate, alertService, formService, policyService, utilService, modelService) {
+
+ var add = this;
+
+ /*
+ *
+ */
+
+ add.loading = false;
+
+ add.form = {};
+
+ add.policy = {name: null, genre: null, description: null, model_id: null};
+
+ add.genres = ['admin', 'authz'];
+
+ add.models = [];
+
+ add.modelsLoading = true;
+
+ add.create = createPolicy;
+
+
+ activate();
+
+ function activate(){
+
+ resolveModels();
+
+ }
+
+ /*
+ *
+ */
+
+ function resolveModels() {
+
+ modelService.findAllWithCallBack(resolveModelsCallback);
+
+ }
+
+ function resolveModelsCallback(models) {
+
+ add.models = models;
+
+ add.modelsLoading = false;
+
+ }
+
+
+ function createPolicy() {
+
+ if(formService.isInvalid(add.form)) {
+
+ formService.checkFieldsValidity(add.form);
+
+ } else {
+
+
+ add.loading = true;
+
+ policyService.data.policy.create({}, {
+
+ name: add.policy.name,
+ description: add.policy.description,
+ genre: [add.selectedGenre],
+ model_id: add.selectedModel.id
+
+ }, createSuccess, createError);
+
+ }
+
+ function createSuccess(data) {
+
+ var createdPolicy = utilService.transformOne(data, 'policies');
+
+ $translate('moon.policy.add.success', { policyName: createdPolicy.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:policyCreatedSuccess', createdPolicy);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.policy.add.error', { policyName: add.model.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:policyCreatedError', add.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/action/policy.controller.delete.js b/moon_gui/static/app/policy/action/policy.controller.delete.js
new file mode 100755
index 00000000..9a718ddc
--- /dev/null
+++ b/moon_gui/static/app/policy/action/policy.controller.delete.js
@@ -0,0 +1,69 @@
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyDeleteController', PolicyDeleteController);
+
+ PolicyDeleteController.$inject = ['$scope', '$translate', 'alertService', 'policyService'];
+
+ function PolicyDeleteController($scope, $translate, alertService, policyService) {
+
+ var del = this;
+
+ /*
+ *
+ */
+
+ del.policy = $scope.policy;
+ del.loading = false;
+
+ del.remove = deletePolicy;
+
+ activate();
+
+ /**
+ *
+ */
+
+ function activate(){
+
+ }
+
+
+ function deletePolicy(){
+
+ del.loading = true;
+
+ policyService.delete(del.policy, deleteSuccess, deleteError);
+
+ function deleteSuccess(data) {
+
+ $translate('moon.policy.remove.success', { policyName: del.policy.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:policyDeletedSuccess', del.policy);
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.policy.remove.error', { policyName: del.policy.name, errorCode: reason.data.error.code, message : reason.data.error.message } ).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:policyDeletedError', del.policy);
+
+ }
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/edit/parameter/assignments/assignments-edit.tpl.html b/moon_gui/static/app/policy/edit/parameter/assignments/assignments-edit.tpl.html
new file mode 100755
index 00000000..9069dcd0
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/assignments/assignments-edit.tpl.html
@@ -0,0 +1,165 @@
+<div>
+
+ <div class="col-md-12 col-sm-12 col-xs-12">
+
+ <form ng-if="!edit.fromList" class="form-horizontal" role="form" name="edit.form">
+
+ <!-- Select Policy -->
+ <div class="form-group" ng-class="{'has-error': edit.form.policyList.$invalid && edit.form.policyList.$dirty}" >
+
+ <label for="policyList" class="col-sm-3 control-label" data-translate="moon.policy.assignments.edit.policies">Policy List</label>
+
+ <div class="col-sm-6" ng-if="edit.loadingPolicies" >
+ <moon-loader></moon-loader>
+ </div>
+
+ <div class="col-sm-6" ng-if="!edit.loadingPolicies" >
+
+ <ui-select ng-model="edit.selectedPolicy" name="policyList" id="policyList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPolicy in edit.policyList">
+ <div ng-value="aPolicy" ng-bind="aPolicy.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.policyList.$dirty && edit.form.policyList.$invalid">
+ <small class="error" ng-show="edit.form.policyList.$error.required" data-translate="moon.policy.assignments.edit.check.policy.required">Policy is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <!-- Select Perimeter -->
+ <div class="form-group" ng-class="{'has-error': edit.form.perimeterList.$invalid && edit.form.perimeterList.$dirty}" >
+
+ <label for="perimeterList" class="col-sm-3 control-label" data-translate="moon.policy.assignments.edit.perimeters">Perimeter List</label>
+
+ <div class="col-sm-6" ng-if="edit.loadingPerimeters" >
+ <moon-loader></moon-loader>
+ </div>
+
+ <div class="col-sm-6" ng-if="!edit.loadingPerimeters" >
+
+ <ui-select ng-model="edit.selectedPerimeter" name="perimeterList" id="perimeterList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPerimeter in edit.perimeterList">
+ <div ng-value="aPerimeter" ng-bind="aPerimeter.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.perimeterList.$dirty && edit.form.perimeterList.$invalid">
+ <small class="error" ng-show="edit.form.perimeterList.$error.required" data-translate="moon.policy.assignments.edit.check.perimeter.required">Perimeter is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <!-- Select Category -->
+ <div class="form-group" ng-class="{'has-error': edit.form.categoryList.$invalid && edit.form.categoryList.$dirty}" >
+
+ <label for="categoryList" class="col-sm-3 control-label" data-translate="moon.policy.assignments.edit.categories">Category List</label>
+
+ <div class="col-sm-6" ng-if="edit.loadingCategories" >
+ <moon-loader></moon-loader>
+ </div>
+
+ <div class="col-sm-6" ng-if="!edit.loadingCategories" >
+
+ <ui-select ng-model="edit.selectedCategory" name="categoryList" id="categoryList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aCategory in edit.categoryList">
+ <div ng-value="aCategory" ng-bind="aCategory.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.categoryList.$dirty && edit.form.categoryList.$invalid">
+ <small class="error" ng-show="edit.form.categoryList.$error.required" data-translate="moon.policy.assignments.edit.check.category.required">Category is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <!-- Select Data -->
+ <div class="form-group" ng-if="edit.selectedCategory" ng-class="{'has-error': edit.form.dataList.$invalid && edit.form.dataList.$dirty}" >
+
+ <label for="dataList" class="col-sm-3 control-label" data-translate="moon.policy.assignments.edit.data">Data List</label>
+
+ <div class="col-sm-6" ng-if="edit.loadingData" >
+ <moon-loader></moon-loader>
+ </div>
+
+ <div class="col-sm-4" ng-if="!edit.loadingData" >
+
+ <ui-select ng-model="edit.selectedData" name="dataList" id="dataList">
+
+ <ui-select-match placeholder="(None)" ng-bind="edit.getName($select.selected)"></ui-select-match>
+ <ui-select-choices repeat="aData in edit.dataToBeSelected">
+ <div ng-value="aData" ng-bind="edit.getName(aData)"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.dataList.$dirty && edit.form.dataList.$invalid || !edit.assignementsAttributeValid">
+ <small class="error" ng-show="edit.form.dataList.$error.required || !edit.assignementsAttributeValid" data-translate="moon.policy.assignments.edit.check.data.required">Data is required</small>
+ </div>
+
+ </div>
+
+ <div class="col-sm-2 text-center">
+ <a href="" ng-if="edit.selectedData"
+ ng-click="edit.addSelectedData()"><span style="font-size:1.5em; line-height: 1.5em;" class="glyphicon glyphicon-plus-sign"></span></a>
+ </div>
+
+ </div>
+
+ <!-- Selected DataList -->
+ <div class="form-group" ng-if="!edit.loadingData">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.assignments.edit.selectedData">Selected Data)</label>
+
+ <div class="col-sm-6">
+
+ <ul>
+
+ <li ng-repeat="(key, value) in edit.selectedDataList">
+
+ <span ng-bind="edit.getName(value)" ></span> <a href="" ng-click="edit.removeSelectedData(value)"><span style="font-size:1.5em; line-height: 1.5em" class="glyphicon glyphicon-remove"></span></a>
+
+ </li>
+
+ </ul>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.assignments.edit.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+
+ </form>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html b/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html
new file mode 100755
index 00000000..34bbc7a8
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html
@@ -0,0 +1,335 @@
+<div>
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.subject.title">List of associated Subjects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.assignments.table.perimeter.name">Perimeter name</th>
+ <th data-translate="moon.policy.assignments.table.category.name">Category name</th>
+ <th data-translate="moon.policy.assignments.table.data.name">Data name</th></tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingSub"></moon-loader>
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length > 0">
+
+ <tr ng-repeat="(key, value) in list.subjects">
+
+ <td>
+
+ <div ng-if="!list.getPerimeterFromAssignment(value, list.typeOfSubject)">
+ <moon-loader ng-if="!list.getPerimeterFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.perimeter">Loading </em>
+ </div>
+
+ <div ng-if="list.getPerimeterFromAssignment(value)">
+ <span ng-bind="value.perimeter.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <div ng-if="!list.getCategoryFromAssignment(value, list.typeOfSubject)">
+ <moon-loader ng-if="!list.getCategoryFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromAssignment(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <span ng-repeat="(index, id) in value.assignments">
+
+ <span ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfSubject)">
+ <moon-loader ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfSubject)" ></moon-loader>
+ </span>
+
+ <span ng-if="list.getDataFromAssignmentsIndex(index, value, list.typeOfSubject)">
+ <span ng-bind="value.assignments_value[index].data.name"></span>
+ <a href="" ng-if="!value.loader" ng-click="list.deleteSub(value, value.assignments_value[index].data.id)" >
+ <span>(</span><span class="glyphicon glyphicon-transfer"></span><span>)</span>
+ </a>
+ <span ng-if="index < value.assignments.length-1">,&nbsp;</span>
+ </span>
+
+ </span>
+
+ </td>
+
+ <td>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+
+ </tr>
+ </tbody>
+
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length === 0">
+ <tr>
+ <td data-translate="moon.policy.assignments.subject.notFound">There is no Subjects</td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.subject.add.title">Add a Subject Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-assignments-edit policy="list.policy" assignments-type="list.typeOfSubject"></moon-assignments-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.object.title">List associated of Objects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.assignments.table.perimeter.name">Perimeter name</th>
+ <th data-translate="moon.policy.assignments.table.category.name">Category name</th>
+ <th data-translate="moon.policy.assignments.table.data.name">Data name</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingObj"></moon-loader>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length > 0">
+ <tr ng-repeat="(key, value) in list.objects">
+ <td>
+
+ <div ng-if="!list.getPerimeterFromAssignment(value, list.typeOfObject)">
+ <moon-loader ng-if="!list.getPerimeterFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.perimeter">Loading </em>
+ </div>
+
+ <div ng-if="list.getPerimeterFromAssignment(value)">
+ <span ng-bind="value.perimeter.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <div ng-if="!list.getCategoryFromAssignment(value, list.typeOfObject)">
+ <moon-loader ng-if="!list.getCategoryFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromAssignment(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+ <span ng-repeat="(index, id) in value.assignments">
+
+ <span ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfObject)">
+ <moon-loader ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfObject)" ></moon-loader>
+ </span>
+
+ <span ng-if="list.getDataFromAssignmentsIndex(index, value, list.typeOfObject)">
+
+ <span ng-if="value.assignments_value[index].data.name" ng-bind="value.assignments_value[index].data.name"></span>
+ <span ng-if="value.assignments_value[index].data.value.name" ng-bind="value.assignments_value[index].data.value.name"></span>
+ <a href="" ng-if="!value.loader" ng-click="list.deleteObj(value, value.assignments_value[index].data.id)" >
+ <span>(</span><span class="glyphicon glyphicon-transfer"></span><span>)</span>
+ </a>
+ <span ng-if="index < value.assignments.length-1">,&nbsp;</span>
+ </span>
+
+ </span>
+ </td>
+
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length === 0">
+ <tr>
+ <td data-translate="moon.policy.assignments.object.notFound">There is no Objects</td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.object.add.title">Add an Object Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-assignments-edit policy="list.policy" assignments-type="list.typeOfObject"></moon-assignments-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.action.title">List associated of Actions</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.assignments.table.perimeter.name">Perimeter name</th>
+ <th data-translate="moon.policy.assignments.table.category.name">Category name</th>
+ <th data-translate="moon.policy.assignments.table.data.name">Data name</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingAct"></moon-loader>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length > 0">
+ <tr ng-repeat="(key, value) in list.actions">
+
+ <td>
+ <div ng-if="!list.getPerimeterFromAssignment(value, list.typeOfAction)">
+ <moon-loader ng-if="!list.getPerimeterFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.perimeter">Loading </em>
+ </div>
+
+ <div ng-if="list.getPerimeterFromAssignment(value)">
+ <span ng-bind="value.perimeter.name"></span>
+ </div>
+ </td>
+
+ <td>
+
+ <div ng-if="!list.getCategoryFromAssignment(value, list.typeOfAction)">
+ <moon-loader ng-if="!list.getCategoryFromAssignment(value)" ></moon-loader>
+ <em data-translate="moon.policy.assignments.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromAssignment(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <span ng-repeat="(index, id) in value.assignments">
+
+ <span ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfAction)">
+ <moon-loader ng-if="!list.getDataFromAssignmentsIndex(index, value, list.typeOfAction)" ></moon-loader>
+ </span>
+
+ <span ng-if="list.getDataFromAssignmentsIndex(index, value, list.typeOfAction)">
+ <span ng-if="value.assignments_value[index].data.name" ng-bind="value.assignments_value[index].data.name"></span>
+ <span ng-if="value.assignments_value[index].data.value.name" ng-bind="value.assignments_value[index].data.value.name"></span>
+ <a href="" ng-if="!value.loader" ng-click="list.deleteAct(value, value.assignments_value[index].data.id)" >
+ <span>(</span><span class="glyphicon glyphicon-transfer"></span><span>)</span>
+ </a>
+ <span ng-if="index < value.assignments.length-1">,&nbsp;</span>
+ </span>
+
+ </span>
+
+ </td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length === 0">
+ <tr>
+ <td data-translate="moon.policy.assignments.action.notFound">There is no Actions</td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.assignments.action.add.title">Add an Action Category</h4>
+
+ </div>
+
+ <div class="panel-body">.
+
+ <moon-assignments-edit policy="list.policy" assignments-type="list.typeOfAction"></moon-assignments-edit>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/assignments/assignments.edit.dir.js b/moon_gui/static/app/policy/edit/parameter/assignments/assignments.edit.dir.js
new file mode 100755
index 00000000..5297eccb
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/assignments/assignments.edit.dir.js
@@ -0,0 +1,439 @@
+(function () {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonAssignmentsEdit', moonAssignmentsEdit);
+
+ moonAssignmentsEdit.$inject = [];
+
+ function moonAssignmentsEdit() {
+
+ return {
+ templateUrl: 'html/policy/edit/parameter/assignments/assignments-edit.tpl.html',
+ bindToController: true,
+ controller: moonAssignmentsEditController,
+ controllerAs: 'edit',
+ scope: {
+ //Type can be 'ACTION', 'OBJECT', 'SUBJECT'
+ assignmentsType: '=',
+ policy: '='
+ },
+ restrict: 'E',
+ replace: true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonAssignmentsEditController', moonAssignmentsEditController);
+
+ moonAssignmentsEditController.$inject = ['$scope', 'assignmentsService', 'alertService', '$translate', 'formService',
+ 'policyService', 'utilService', 'perimeterService', 'ASSIGNMENTS_CST',
+ 'metaDataService', 'dataService'];
+
+ function moonAssignmentsEditController($scope, assignmentsService, alertService, $translate, formService,
+ policyService, utilService, perimeterService, ASSIGNMENTS_CST,
+ metaDataService, dataService ) {
+
+ var edit = this;
+
+ edit.assignmentsType = $scope.edit.assignmentsType;
+ edit.policy = $scope.edit.policy;
+
+ edit.laoading = false;
+
+ edit.form = {};
+
+ edit.policyList = [];
+ edit.loadingPolicies = true;
+
+ edit.categoryList = [];
+ edit.loadingCategories = true;
+
+ edit.perimeterList = [];
+ edit.loadingPerimeters = true;
+
+ edit.dataList = [];
+ edit.dataToBeSelected = [];
+ edit.selectedDataList = [];
+ edit.loadingData = true;
+
+ edit.assignementsAttributeValid = true;
+
+ edit.addSelectedData = addSelectedData;
+ edit.removeSelectedData = removeSelectedData;
+ edit.getName = getName;
+ edit.create = createAssignments;
+
+ activate();
+
+ /*
+ *
+ */
+
+ function activate() {
+
+ edit.assignments = {id: null, category_id: null, data_id: null, policy_id: null};
+
+ loadAllPolicies();
+ loadAllCategories();
+
+ }
+
+ function createAssignments() {
+
+ edit.assignementsAttributeValid = true;
+
+ manageSelectedDataListy();
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ }else if(edit.assignementsAttributeValid){
+
+ startLoading();
+
+ var throwEvent = false;
+ edit.assignments.id = edit.selectedPerimeter.id;
+ edit.assignments.category_id = edit.selectedCategory.id;
+ edit.assignments.policy_id = edit.selectedPolicy.id;
+
+ var selectedDataListTemp = angular.copy(edit.selectedDataList);
+
+ _.each(selectedDataListTemp, function(elem){
+
+ edit.assignments.data_id = elem.id;
+
+ var assignmentsToSend = angular.copy(edit.assignments);
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ assignmentsService.subject.add(assignmentsToSend, edit.policy.id, createSuccess, createError);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ assignmentsService.object.add(assignmentsToSend, edit.policy.id, createSuccess, createError);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ assignmentsService.action.add(assignmentsToSend, edit.policy.id, createSuccess, createError);
+ break;
+
+ default :
+
+ break;
+
+ }
+
+ });
+
+ throwEvent = true;
+
+ }
+
+ function createSuccess(data) {
+
+ var created = {};
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ created = utilService.transformOne(data, 'subject_assignments');
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ created = utilService.transformOne(data, 'object_assignments');
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ created = utilService.transformOne(data, 'action_assignments');
+ break;
+
+ default:
+
+ break;
+
+ }
+
+ $translate('moon.policy.assignments.edit.create.success').then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ if(throwEvent && created.policy_id === edit.policy.id){
+
+ $scope.$emit('event:createAssignmentsFromAssignmentsEditSuccess', edit.assignmentsType);
+
+ activate();
+
+ stopLoading();
+
+ }else if(throwEvent){
+
+ activate();
+
+ stopLoading();
+
+ }
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.policy.rules.edit.action.add.create.error').then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ $scope.$watch('edit.selectedPolicy', function(newValue){
+
+ if(!_.isUndefined(newValue)){
+
+ loadRelatedPerimeters();
+
+ }
+
+ });
+
+
+ $scope.$watch('edit.selectedCategory', function(newValue){
+
+ clearSelectedCategories();
+
+ if(!_.isUndefined(newValue)){
+
+ loadRelatedData(newValue.id);
+
+ }
+
+ });
+
+ function loadAllPolicies() {
+
+ edit.policyList = [];
+ edit.loadingPolicies = true;
+
+ policyService.findAllWithCallback( function(data) {
+
+ _.each(data, function(element){
+
+ if(element.id === edit.policy.id){
+ edit.selectedPolicy = element;
+ }
+
+ });
+
+ edit.policyList = data;
+ edit.loadingPolicies = false;
+
+ });
+ }
+
+ function loadRelatedPerimeters(){
+
+ edit.perimeterList = [];
+ edit.loadingPerimeters = true;
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ perimeterService.subject.findAllFromPolicyWithCallback(edit.selectedPolicy.id, callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ perimeterService.object.findAllFromPolicyWithCallback(edit.selectedPolicy.id,callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ perimeterService.action.findAllFromPolicyWithCallback(edit.selectedPolicy.id, callBackList);
+ break;
+
+ default :
+
+ edit.perimeterList = [];
+ edit.loadingPerimeters = false;
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.perimeterList = list;
+
+ edit.loadingPerimeters = false;
+
+ }
+ }
+
+ function loadAllCategories(){
+
+ edit.categoryList = [];
+ edit.loadingCategories = true;
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.findAllWithCallback(callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ metaDataService.object.findAllWithCallback(callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ metaDataService.action.findAllWithCallback(callBackList);
+ break;
+
+ default :
+
+ edit.categoryList = [];
+ edit.loadingCategories = false;
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.categoryList = list;
+ edit.loadingCategories = false;
+
+ }
+ }
+
+ function loadRelatedData(categoryId){
+
+ edit.dataList = [];
+ edit.dataToBeSelected = [];
+ edit.selectedDataList = [];
+ edit.loadingData = true;
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ dataService.subject.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, categoryId, callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ dataService.object.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, categoryId, callBackList);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ dataService.action.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, categoryId, callBackList);
+ break;
+
+ default :
+
+ edit.loadingData = false;
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.dataList = list;
+ edit.dataToBeSelected = angular.copy(edit.dataList);
+ edit.selectedDataList = [];
+ edit.loadingData = false;
+
+ }
+
+ }
+
+ function addSelectedData(){
+
+ edit.dataToBeSelected = _.without(edit.dataToBeSelected, edit.selectedData);
+ edit.selectedDataList.push(edit.selectedData);
+ clearSelectedCategories();
+
+ }
+
+ function removeSelectedData(data){
+
+ edit.dataToBeSelected.push(data);
+ edit.selectedDataList = _.without(edit.selectedDataList, data);
+
+ }
+
+ function clearSelectedCategories(){
+
+ edit.selectedData = undefined;
+
+ }
+
+ function getName(assignment){
+
+ if(_.isUndefined(assignment)) return '(None)';
+
+ switch(edit.assignmentsType){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ return assignment.name;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ return assignment.value.name;
+
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ return assignment.value.name;
+
+ default :
+
+ return assignment.name;
+
+ }
+
+ }
+
+ function manageSelectedDataListy(){
+
+ if (edit.selectedDataList.length >= 1 ){
+
+ edit.assignementsAttributeValid = true;
+
+ }else{
+
+ edit.assignementsAttributeValid = false;
+
+ }
+ }
+
+ function startLoading(){
+
+ edit.loading = true;
+
+ }
+
+ function stopLoading(){
+
+ edit.loading = false;
+
+ }
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js b/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js
new file mode 100755
index 00000000..22931e4d
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js
@@ -0,0 +1,393 @@
+(function () {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonAssignmentsList', moonAssignmentsList);
+
+ moonAssignmentsList.$inject = [];
+
+ function moonAssignmentsList() {
+
+ return {
+ templateUrl: 'html/policy/edit/parameter/assignments/assignments-list.tpl.html',
+ bindToController: true,
+ controller: moonAssignmentsListController,
+ controllerAs: 'list',
+ scope: {
+ policy: '=',
+ editMode: '='
+ },
+ restrict: 'E',
+ replace: true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonAssignmentsListController', moonAssignmentsListController);
+
+ moonAssignmentsListController.$inject = ['$scope', '$rootScope', 'assignmentsService', '$translate', 'alertService',
+ 'policyService', 'ASSIGNMENTS_CST', 'utilService', 'metaDataService', 'perimeterService', 'dataService'];
+
+ function moonAssignmentsListController($scope, $rootScope, assignmentsService, $translate, alertService,
+ policyService, ASSIGNMENTS_CST, utilService, metaDataService, perimeterService, dataService) {
+
+ var list = this;
+
+ list.policy = $scope.list.policy;
+ list.editMode = $scope.list.editMode;
+
+ list.typeOfSubject = ASSIGNMENTS_CST.TYPE.SUBJECT;
+ list.typeOfObject = ASSIGNMENTS_CST.TYPE.OBJECT;
+ list.typeOfAction = ASSIGNMENTS_CST.TYPE.ACTION;
+
+ list.deleteSub = deleteSub;
+ list.deleteObj = deleteObj;
+ list.deleteAct = deleteAct;
+
+ list.getSubjects = getSubjects;
+ list.getObjects = getObjects;
+ list.getActions = getActions;
+
+ list.getCategoryFromAssignment = getCategoryFromAssignment;
+ list.getPerimeterFromAssignment = getPerimeterFromAssignment;
+ list.getDataFromAssignmentsIndex = getDataFromAssignmentsIndex;
+
+ activate();
+
+ function activate() {
+
+ manageSubjects();
+
+ manageObjects();
+
+ manageActions();
+
+ }
+
+ var rootListeners = {
+
+ 'event:createAssignmentsFromAssignmentsEditSuccess': $rootScope.$on('event:createAssignmentsFromAssignmentsEditSuccess', updateList)
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+ function manageSubjects() {
+
+ list.loadingSub = true;
+
+ assignmentsService.subject.findAllFromPolicyWithCallback(list.policy.id, function (data) {
+
+ list.subjects = data;
+ list.loadingSub = false;
+
+ });
+ }
+
+ function manageObjects() {
+
+ list.loadingObj = true;
+
+ assignmentsService.object.findAllFromPolicyWithCallback(list.policy.id, function (data) {
+
+ list.objects = data;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions() {
+
+ list.loadingAct = true;
+
+ assignmentsService.action.findAllFromPolicyWithCallback(list.policy.id, function (data) {
+
+ list.actions = data;
+ list.loadingAct = false;
+
+ });
+
+ }
+
+ function getPerimeterFromAssignment(assignment, type) {
+
+ if (_.has(assignment, 'perimeter')) {
+ return assignment.perimeter;
+ }
+
+ // if the call has not been made
+ if (!_.has(assignment, 'callPerimeterInProgress')) {
+
+ assignment.callPerimeterInProgress = true;
+
+ switch (type) {
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+ perimeterService.subject.findOneFromPolicyWithCallback(list.policy.id, assignment.subject_id, setPerimeterToAssignment);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+ perimeterService.object.findOneFromPolicyWithCallback(list.policy.id, assignment.object_id, setPerimeterToAssignment);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+ perimeterService.action.findOneFromPolicyWithCallback(list.policy.id, assignment.action_id, setPerimeterToAssignment);
+ break;
+
+ }
+
+ }
+
+ // if the call is in progress return false
+ return false;
+
+ function setPerimeterToAssignment(perimeter) {
+
+ assignment.callPerimeterInProgress = false;
+ assignment.perimeter = perimeter;
+
+ }
+ }
+
+ function getCategoryFromAssignment(data, type) {
+
+ if (_.has(data, 'category')) {
+ return data.category;
+ }
+
+ // if the call has not been made
+ if (!_.has(data, 'callCategoryInProgress')) {
+
+ data.callCategoryInProgress = true;
+
+ switch (type) {
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+ metaDataService.subject.findOne(data.subject_cat_id, setCategoryToData);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+ metaDataService.object.findOne(data.object_cat_id, setCategoryToData);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+ metaDataService.action.findOne(data.action_cat_id, setCategoryToData);
+ break;
+
+ }
+
+ }
+
+ // if the call is in progress return false
+ return false;
+
+ function setCategoryToData(category) {
+
+ data.callCategoryInProgress = false;
+ data.category = category;
+
+ }
+ }
+
+ /**
+ * @param index
+ * @param assignment
+ * @param type
+ */
+ function getDataFromAssignmentsIndex(index, assignment, type) {
+
+ if (!_.has(assignment, 'assignments_value')) {
+ // setting an array which will contains every value of the category
+ assignment.assignments_value = Array.apply(null, new Array(assignment.assignments.length)).map(function () {
+ return {
+ data: {}
+ };
+ });
+ }
+
+ if (_.has(assignment.assignments_value[index], 'callDataInProgress') && !assignment.assignments_value[index].callDataInProgress) {
+ return assignment.assignments_value[index].data;
+ }
+
+ // if the call has not been made
+ if (!_.has(assignment.assignments_value[index], 'callDataInProgress')) {
+
+ assignment.assignments_value[index].callDataInProgress = true;
+
+ switch (type) {
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+ dataService.subject.data.findOne(list.policy.id, assignment.category_id, assignment.assignments[index], setDataToAssignment);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+ dataService.object.data.findOne(list.policy.id, assignment.category_id, assignment.assignments[index], setDataToAssignment);
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+ dataService.action.data.findOne(list.policy.id, assignment.category_id, assignment.assignments[index], setDataToAssignment);
+ break;
+
+ }
+
+ }
+
+ // if the call is in progress return false
+ return false;
+
+ function setDataToAssignment(data) {
+
+ assignment.assignments_value[index].callDataInProgress = false;
+ assignment.assignments_value[index].data = data;
+
+ }
+ }
+
+ /**
+ * Delete
+ */
+
+ function deleteSub(subject, dataId) {
+
+ subject.loader = true;
+
+ assignmentsService.subject.delete(list.policy.id, subject.subject_id, subject.subject_cat_id, dataId, deleteSubSuccess, deleteSubError);
+
+ function deleteSubSuccess(data) {
+
+ $translate('moon.policy.assignments.subject.delete.success').then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ manageSubjects();
+
+ subject.loader = false;
+
+ }
+
+ function deleteSubError(reason) {
+
+ $translate('moon.policy.assignments.subject.delete.error', {
+ subjectName: subject.name,
+ reason: reason.message
+ }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+ }
+
+ function deleteObj(object, dataId) {
+
+ object.loader = true;
+
+ assignmentsService.object.delete(list.policy.id, object.object_id, object.object_cat_id, dataId, deleteObjSuccess, deleteObjError);
+
+ function deleteObjSuccess(data) {
+
+ $translate('moon.policy.assignments.object.delete.success').then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ manageObjects();
+
+ object.loader = false;
+
+ }
+
+ function deleteObjError(reason) {
+
+ $translate('moon.policy.assignments.object.delete.error', {
+ objectName: object.name,
+ reason: reason.message
+ }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+ }
+ }
+
+ function deleteAct(action, dataId) {
+
+ action.loader = true;
+
+ assignmentsService.action.delete(list.policy.id, action.action_id, action.action_cat_id, dataId, deleteActSuccess, deleteActError);
+
+ function deleteActSuccess(data) {
+
+ $translate('moon.policy.assignments.action.delete.success').then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ manageActions();
+
+ action.loader = false;
+
+ }
+
+ function deleteActError(reason) {
+
+ $translate('moon.policy.assignments.action.delete.error', {
+ actionName: action.name,
+ reason: reason.message
+ }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+ }
+
+ function getSubjects() {
+ return list.subjects ? list.subjects : [];
+ }
+
+ function getObjects() {
+ return list.objects ? list.objects : [];
+ }
+
+ function getActions() {
+ return list.actions ? list.actions : [];
+ }
+
+ function updateList(event, type) {
+
+ switch(type){
+
+ case ASSIGNMENTS_CST.TYPE.SUBJECT:
+
+ manageSubjects();
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.OBJECT:
+
+ manageObjects();
+ break;
+
+ case ASSIGNMENTS_CST.TYPE.ACTION:
+
+ manageActions();
+ break;
+
+ default :
+
+ activate();
+ break;
+
+ }
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/data/data-edit.tpl.html b/moon_gui/static/app/policy/edit/parameter/data/data-edit.tpl.html
new file mode 100755
index 00000000..3f11a641
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/data/data-edit.tpl.html
@@ -0,0 +1,110 @@
+<div>
+
+ <div class="col-md-12 col-sm-12 col-xs-12">
+
+ <form ng-if="!edit.fromList" class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label"
+ data-translate="moon.policy.data.edit.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.data.name"
+ required/>
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required"
+ data-translate="moon.policy.data.edit.check.name.required">Name is required
+ </small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label"
+ data-translate="moon.policy.data.edit.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control"
+ data-ng-model="edit.data.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group"
+ ng-class="{'has-error': edit.form.policyList.$invalid && edit.form.policyList.$dirty}">
+
+ <label for="policyList" class="col-sm-3 control-label" data-translate="moon.policy.data.edit.policies">Policy
+ List </label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="edit.selectedPolicy" name="policyList" id="policyList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPolicy in edit.policyList">
+ <div ng-value="aPolicy" ng-bind="aPolicy.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.policyList.$dirty && edit.form.policyList.$invalid">
+ <small class="error" ng-show="edit.form.policyList.$error.required"
+ data-translate="moon.policy.data.edit.check.policy.required">Policy is required
+ </small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group"
+ ng-class="{'has-error': edit.form.categoryList.$invalid && edit.form.categoryList.$dirty}">
+
+ <label for="categoryList" class="col-sm-3 control-label"
+ data-translate="moon.policy.data.edit.categories">Category List </label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="edit.selectedCategory" name="categoryList" id="categoryList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aCategory in edit.categoriesToBeSelected">
+ <div ng-value="aCategory" ng-bind="aCategory.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.categoryList.$dirty && edit.form.categoryList.$invalid">
+ <small class="error" ng-show="edit.form.categoryList.$error.required"
+ data-translate="moon.policy.data.edit.check.category.required">Category is required
+ </small>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.data.edit.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html b/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html
new file mode 100755
index 00000000..b69a4eed
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html
@@ -0,0 +1,390 @@
+<div>
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.subject.title">List of associated Subjects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.data.table.name">Name</th>
+ <th data-translate="moon.policy.data.table.description">Description</th>
+ <th data-translate="moon.policy.data.table.category.name">Category</th>
+ <th data-translate="moon.policy.data.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingSub"></moon-loader>
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length > 0">
+ <tr ng-repeat="(key, value) in list.subjects">
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td>
+
+ <div ng-if="!list.getCategoryFromData(value, list.typeOfSubject)">
+ <moon-loader ng-if="!list.getCategoryFromData(value)" ></moon-loader>
+ <em data-translate="moon.policy.list.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromData(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.deleteSub(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+
+
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.data.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapSub(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.unmap">Unmap</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteSub(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>-->
+
+ </tr>
+ </tbody>
+
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length === 0">
+ <tr>
+ <td colspan="4" data-translate="moon.policy.data.subject.notFound">There is no Subjects</td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.subject.add.title">Add a Subject Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-data-edit policy="list.policy" mn-data-type="list.typeOfSubject"></moon-data-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.object.title">List associated of Objects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.data.table.name">Name</th>
+ <th data-translate="moon.policy.data.table.description">Description</th>
+ <th data-translate="moon.policy.data.table.category.name">Category</th>
+ <th data-translate="moon.policy.data.table.action.title">Actions</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingObj"></moon-loader>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length > 0">
+ <tr ng-repeat="(key, value) in list.objects">
+ <td ng-bind="value.value.name"></td>
+ <td ng-bind="value.value.description"></td>
+ <td>
+
+ <div ng-if="!list.getCategoryFromData(value, list.typeOfObject)">
+ <moon-loader ng-if="!list.getCategoryFromData(value)" ></moon-loader>
+ <em data-translate="moon.policy.list.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromData(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.deleteObj(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.data.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapObj(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.unmap">Unmap</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteObj(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ </tr>-->
+ </tbody>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length === 0">
+ <tr>
+
+ <td colspan="4" data-translate="moon.policy.data.object.notFound">There is no Objects</td>
+
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.object.add.title">Add an Object Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-data-edit policy="list.policy" mn-data-type="list.typeOfObject"></moon-data-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.action.title">List associated of Actions</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.data.table.name">Name</th>
+ <th data-translate="moon.policy.data.table.description">Description</th>
+ <th data-translate="moon.policy.data.table.category.name">Category</th>
+ <th data-translate="moon.policy.data.table.action.title">Actions</th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingAct"></moon-loader>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length > 0">
+ <tr ng-repeat="(key, value) in list.actions">
+ <td ng-bind="value.value.name"></td>
+ <td ng-bind="value.value.description"></td>
+ <td>
+
+ <div ng-if="!list.getCategoryFromData(value, list.typeOfAction)">
+ <moon-loader ng-if="!list.getCategoryFromData(value)" ></moon-loader>
+ <em data-translate="moon.policy.list.table.loading.category">Loading </em>
+ </div>
+
+ <div ng-if="list.getCategoryFromData(value)">
+ <span ng-bind="value.category.name"></span>
+ </div>
+
+ </td>
+
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.deleteSub(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.data.table.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ng-click="list.unMapAct(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.model.metarules.action.unmap">Unmap</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.deleteAct(value)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.policy.data.table.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+
+ </div>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>-->
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length === 0">
+ <tr>
+ <td colspan="4" data-translate="moon.policy.data.action.notFound">There is no Actions</td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.data.action.add.title">Add an Action Category</h4>
+
+ </div>
+
+ <div class="panel-body">.
+
+ <moon-data-edit policy="list.policy" mn-data-type="list.typeOfAction"></moon-data-edit>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js b/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js
new file mode 100755
index 00000000..57ad0c9b
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js
@@ -0,0 +1,260 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonDataEdit', moonDataEdit);
+
+ moonDataEdit.$inject = [];
+
+ function moonDataEdit() {
+
+ return {
+ templateUrl : 'html/policy/edit/parameter/data/data-edit.tpl.html',
+ bindToController : true,
+ controller : moonDataEditController,
+ controllerAs : 'edit',
+ scope : {
+ //Type can be 'ACTION', 'OBJECT', 'SUBJECT'
+ mnDataType: '=',
+ policy : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+
+ }
+
+ angular
+ .module('moon')
+ .controller('moonDataEditController', moonDataEditController);
+
+ moonDataEditController.$inject = ['$scope', 'dataService', 'DATA_CST', 'alertService', '$translate',
+ 'formService', 'policyService', 'utilService', 'metaDataService'];
+
+ function moonDataEditController($scope, dataService, DATA_CST, alertService, $translate,
+ formService, policyService, utilService, metaDataService) {
+
+ var edit = this;
+
+ edit.dataType = $scope.edit.mnDataType;
+ edit.policy = $scope.edit.policy;
+
+ edit.fromList = false;
+
+ edit.loading = false;
+
+ edit.form = {};
+
+ edit.data = { name: null, description: null};
+
+ edit.list = [];
+ edit.policyList = [];
+ edit.categoriesToBeSelected = [];
+
+ edit.create = createData;
+
+ activate();
+
+ /*
+ *
+ */
+
+ function activate(){
+
+ loadAllCategories();
+ loadAllPolicies();
+
+ switch(edit.dataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ dataService.subject.findAllFromPolicyWithCallback(edit.policy.id, callBackList);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ dataService.object.findAllFromPolicyWithCallback(edit.policy.id, callBackList);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ dataService.action.findAllFromPolicyWithCallback(edit.policy.id, callBackList);
+ break;
+
+ default :
+
+ edit.list = [];
+ break;
+
+ }
+
+ function callBackList(list){
+
+ // For each Data, there is a check about the mapping between the Data and the policy
+ _.each(list, function (element) {
+ if (element.policy_id !== edit.policy.id) {
+
+ edit.list.push(element);
+
+ }
+ });
+
+ }
+
+ }
+
+ function loadAllCategories(){
+
+ switch(edit.dataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.findAllWithCallback(callBackList);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.findAllWithCallback(callBackList);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ metaDataService.action.findAllWithCallback(callBackList);
+ break;
+
+ default :
+
+ edit.categoriesToBeSelected = [];
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.categoriesToBeSelected = list;
+
+ }
+ }
+
+ function loadAllPolicies() {
+
+ edit.policyList = [];
+
+ policyService.findAllWithCallback( function(data) {
+
+ _.each(data, function(element){
+
+ if(element.id === edit.policy.id){
+ edit.selectedPolicy = element;
+ }
+
+ });
+
+ edit.policyList = data;
+
+ });
+ }
+
+
+ /**
+ * Create
+ */
+
+ function createData() {
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ } else {
+
+ startLoading();
+
+ var dataToSend = angular.copy(edit.data);
+
+ switch(edit.dataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ dataService.subject.add(dataToSend, edit.policy.id, edit.selectedCategory.id, createSuccess, createError);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ dataService.object.add(dataToSend, edit.policy.id, edit.selectedCategory.id, createSuccess, createError);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ dataService.action.add(dataToSend, edit.policy.id, edit.selectedCategory.id, createSuccess, createError);
+ break;
+ }
+
+ }
+
+ /**
+ * @param data
+ */
+ function createSuccess(data) {
+
+ var created = {};
+
+ switch(edit.dataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ created = utilService.transformOne(data['subject_data'], 'data');
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ created = utilService.transformOne(data['object_data'], 'data');
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ created = utilService.transformOne(data['action_data'], 'data');
+ break;
+ }
+
+ $translate('moon.policy.data.edit.create.success', { name: created.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ $scope.$emit('event:createDataFromDataEditSuccess', created, edit.dataType);
+
+ stopLoading();
+
+ edit.list.push(created);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.policy.data.edit.create.error', { name: dataToSend.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ function startLoading(){
+
+ edit.loading = true;
+
+ }
+
+ function stopLoading(){
+
+ edit.loading = false;
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js b/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js
new file mode 100755
index 00000000..23a7e535
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js
@@ -0,0 +1,293 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonDataList', moonDataList);
+
+ moonDataList.$inject = [];
+
+ function moonDataList() {
+
+ return {
+ templateUrl : 'html/policy/edit/parameter/data/data-list.tpl.html',
+ bindToController : true,
+ controller : moonDataListController,
+ controllerAs : 'list',
+ scope : {
+ policy: '=',
+ editMode : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonDataListController', moonDataListController);
+
+ moonDataListController.$inject = ['$scope', '$rootScope', 'dataService', '$translate', 'alertService', 'DATA_CST', 'metaDataService'];
+
+ function moonDataListController($scope, $rootScope, dataService, $translate, alertService, DATA_CST, metaDataService){
+
+ var list = this;
+
+ list.policy = $scope.list.policy;
+ list.editMode = $scope.list.editMode;
+
+ list.typeOfSubject = DATA_CST.TYPE.SUBJECT;
+ list.typeOfObject = DATA_CST.TYPE.OBJECT;
+ list.typeOfAction = DATA_CST.TYPE.ACTION;
+
+ list.deleteSub = deleteSub;
+ list.deleteObj = deleteObj;
+ list.deleteAct = deleteAct;
+
+ list.getSubjects = getSubjects;
+ list.getObjects = getObjects;
+ list.getActions = getActions;
+
+ list.getCategoryFromData = getCategoryFromData;
+
+ activate();
+
+ function activate(){
+
+ manageSubjects();
+
+ manageObjects();
+
+ manageActions();
+
+ }
+
+ var rootListeners = {
+
+ 'event:createDataFromDataEditSuccess': $rootScope.$on('event:createDataFromDataEditSuccess', addDataToList)
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+
+ function manageSubjects(){
+
+ list.loadingSub = true;
+
+ dataService.subject.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ list.subjects = data;
+ list.loadingSub = false;
+
+ });
+ }
+
+ function manageObjects(){
+
+ list.loadingObj = true;
+
+ dataService.object.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ list.objects = data;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions(){
+
+ list.loadingAct = true;
+
+ dataService.action.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ list.actions = data;
+ list.loadingAct = false;
+
+ });
+
+ }
+
+ function getCategoryFromData(data, type) {
+
+ if(_.has(data, 'category')){
+ return data.category;
+ }
+
+ // if the call has not been made
+ if(!_.has(data, 'callCategoryInProgress')){
+
+ data.callCategoryInProgress = true;
+
+ switch(type){
+
+ case DATA_CST.TYPE.SUBJECT:
+ metaDataService.subject.findOne(data.category_id, setCategoryToData);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+ metaDataService.object.findOne(data.category_id, setCategoryToData);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+ metaDataService.action.findOne(data.category_id, setCategoryToData);
+ break;
+
+ }
+
+ }
+
+ // if the call is in progress return false
+ return false;
+
+ function setCategoryToData(category){
+
+ data.callCategoryInProgress = false;
+ data.category = category;
+
+ }
+ }
+
+ /**
+ * Delete
+ */
+
+ function deleteSub(subject){
+
+ subject.loader = true;
+
+ dataService.subject.delete(subject, list.policy.id, subject.category_id, deleteSubSuccess, deleteSubError);
+
+ function deleteSubSuccess(data){
+
+ $translate('moon.policy.data.subject.delete.success', { subjectName: subject.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeSubFromSubList(subject);
+
+ subject.loader = false;
+
+ }
+
+ function deleteSubError(reason){
+
+ $translate('moon.policy.data.subject.delete.error', { subjectName: subject.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+ }
+
+ function deleteObj(object){
+
+ object.loader = true;
+
+ dataService.object.delete(object, list.policy.id, object.category_id, deleteObjSuccess, deleteObjError);
+
+ function deleteObjSuccess(data){
+
+ $translate('moon.policy.data.object.delete.success', { objectName: object.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeObjFromObjList(object);
+
+ object.loader = false;
+
+ }
+
+ function deleteObjError(reason){
+
+ $translate('moon.policy.data.object.delete.error', { objectName: object.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+ }
+ }
+
+ function deleteAct(action){
+
+ action.loader = true;
+
+ dataService.action.delete(action, list.policy.id, action.category_id, deleteActSuccess, deleteActError);
+
+ function deleteActSuccess(data){
+
+ $translate('moon.policy.data.action.delete.success', { actionName: action.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeActFromActList(action);
+
+ action.loader = false;
+
+ }
+
+ function deleteActError(reason){
+
+ $translate('moon.policy.data.action.delete.error', { actionName: action.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+ }
+
+ function getSubjects(){
+ return list.subjects ? list.subjects : [];
+ }
+
+ function getObjects(){
+ return list.objects ? list.objects : [];
+ }
+
+ function getActions(){
+ return list.actions ? list.actions : [];
+ }
+
+ function removeSubFromSubList(subject){
+ list.subjects = _.without(list.subjects, subject);
+ }
+
+ function removeObjFromObjList(object){
+ list.objects = _.without(list.objects, object);
+ }
+
+ function removeActFromActList(action){
+ list.actions = _.without(list.actions, action);
+ }
+
+ function addDataToList( event, data, typeOfData){
+
+ switch(typeOfData){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ list.subjects.push(data);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ list.objects.push(data);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ list.actions.push(data);
+ break;
+ }
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-edit.tpl.html b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-edit.tpl.html
new file mode 100755
index 00000000..fa2f93c0
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-edit.tpl.html
@@ -0,0 +1,166 @@
+<div>
+
+ <div class="col-md-4 col-sm-4 col-xs-4">
+ <a class="btn btn-primary" type="button" style="white-space: normal;" ng-click="edit.fromList = !edit.fromList">
+ <span ng-if="!edit.fromList" data-translate="moon.policy.perimeter.edit.action.list">Add from the list</span>
+ <span ng-if="edit.fromList" data-translate="moon.policy.perimeter.edit.action.new">Add a new Perimeter</span>
+ </a>
+ </div>
+
+ <div class="col-md-8 col-sm-8 col-xs-8">
+
+ <form name="selectMetaData" ng-if="edit.fromList" class="form-horizontal" role="form" >
+
+ <div class="form-group" >
+
+ <ui-select ng-model="edit.selectedPerimeter" name="object">
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPerimeter in edit.list">
+ <div ng-value="aPerimeter" ng-bind="aPerimeter.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-left col-md-4 col-sm-4 col-xs-4">
+
+ <a href="" ng-disabled="edit.loading || !edit.selectedPerimeter" ng-click="edit.deletePerimeter()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.policy.perimeter.edit.action.delete">Delete</span>
+ </a>
+
+ </div>
+
+ <div class="pull-right col-md-7 col-md-offset-1 col-sm-7 col-sm-offset-1 col-xs-7 col-xs-offset-1 ">
+
+ <a href="" ng-disabled="edit.loading || !edit.selectedPerimeter" ng-click="edit.addToPolicy()" class="btn btn-warning" style="white-space: normal;">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.policy.perimeter.edit.action.add">Add the selected Perimeter</span>
+ </a>
+
+ </div>
+
+ </div>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </form>
+
+ <form ng-if="!edit.fromList" class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.perimeter.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.policy.perimeter.edit.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.perimeter.description"></textarea>
+ </div>
+
+ </div>
+
+ <!--
+ <div class="form-group">
+
+ <label for="partnerId" class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.partnerId">Partner Id</label>
+
+ <div class="col-sm-6">
+ <input name="partnerId" id="partnerId" class="form-control" type="text" data-ng-model="edit.perimeter.partnerId" />
+ </div>
+
+ </div>
+ -->
+
+
+ <div class="form-group" ng-if="edit.perimeterType === edit.subjectType" ng-class="{'has-error': edit.form.email.$invalid && edit.form.email.$dirty}">
+
+ <label for="email" class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.email">Email</label>
+
+ <div class="col-sm-6">
+ <input name="email" id="email" class="form-control" type="email" data-ng-model="edit.perimeter.email" />
+ </div>
+
+ </div>
+
+
+ <div class="form-group" >
+
+ <label for="policyList" class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.policies">Policy List </label>
+
+ <div class="col-sm-5">
+
+ <ui-select ng-model="edit.selectedPolicy" id="policyList">
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPolicy in edit.policiesToBeSelected">
+ <div ng-value="aPolicy" ng-bind="aPolicy.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ </div>
+
+ <div class="col-sm-1 text-center">
+ <a href="" ng-click="edit.addPolicyToPerimeter()"><span style="font-size:1.5em; line-height: 1.5em;" class="glyphicon glyphicon-plus-sign"></span></a>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.perimeter.edit.selectedPolicies">Selected Policies</label>
+
+ <div class="col-sm-6">
+
+ <ul>
+
+ <li ng-repeat="(key, value) in edit.selectedPolicyList">
+
+ <span ng-bind="value.name" ></span> <a href="" ng-click="edit.removeSelectedPolicy(value)"><span style="font-size:1.5em; line-height: 1.5em" class="glyphicon glyphicon-remove"></span></a>
+
+ </li>
+
+ </ul>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.perimeter.edit.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html
new file mode 100755
index 00000000..a94d663e
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html
@@ -0,0 +1,240 @@
+<div>
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.subject.title">List of associated Subjects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.perimeter.table.name">Name</th>
+ <th data-translate="moon.policy.perimeter.table.description">Description</th>
+ <th data-translate="moon.policy.perimeter.table.email">Email</th>
+ <th data-translate="moon.policy.perimeter.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingSub"></moon-loader>
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length > 0">
+ <tr ng-repeat="(key, value) in list.subjects">
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td ng-bind="value.email"></td>
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapSub(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.perimeter.table.action.unmap">Unmap</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+
+ </tr>
+ </tbody>
+
+
+ <tbody ng-if="!list.loadingSub && list.getSubjects().length === 0">
+ <tr>
+ <td data-translate="moon.policy.perimeter.subject.notFound">There is no Subjects</td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.subject.add.title">Add a Subject Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-perimeter-edit policy="list.policy" perimeter-type="list.typeOfSubject"></moon-perimeter-edit>
+
+ </div>
+
+ </div>
+
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.object.title">List associated of Objects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.perimeter.table.name">Name</th>
+ <th data-translate="moon.policy.perimeter.table.description">Description</th>
+ <th data-translate="moon.policy.perimeter.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingObj"></moon-loader>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length > 0">
+ <tr ng-repeat="(key, value) in list.objects">
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapObj(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.perimeter.table.action.unmap">Unmap</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingObj && list.getObjects().length === 0">
+ <tr>
+ <td data-translate="moon.policy.perimeter.object.notFound">There is no Objects</td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.object.add.title">Add an Object Category</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <moon-perimeter-edit policy="list.policy" perimeter-type="list.typeOfObject"></moon-perimeter-edit>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.action.title">List associated of Actions</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive">
+
+ <table class="table table-striped">
+
+ <thead>
+ <tr>
+ <th data-translate="moon.policy.perimeter.table.name">Name</th>
+ <th data-translate="moon.policy.perimeter.table.description">Description</th>
+ <th data-translate="moon.policy.perimeter.table.action.title"></th>
+ </tr>
+ </thead>
+
+ <moon-loader ng-if="list.loadingAct"></moon-loader>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length > 0">
+ <tr ng-repeat="(key, value) in list.actions">
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td>
+
+ <a href="" ng-if="!value.loader" ng-click="list.unMapAct(value)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.perimeter.table.action.unmap">Unmap</span>
+ </a>
+
+ <div ng-if="value.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingAct && list.getActions().length === 0">
+ <tr>
+ <td data-translate="moon.policy.perimeter.action.notFound">There is no Actions</td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+
+ </table>
+
+ </div>
+
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.perimeter.action.add.title">Add an Action Category</h4>
+
+ </div>
+
+ <div class="panel-body">.
+
+ <moon-perimeter-edit policy="list.policy" perimeter-type="list.typeOfAction"></moon-perimeter-edit>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.edit.dir.js b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.edit.dir.js
new file mode 100755
index 00000000..a96741fe
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.edit.dir.js
@@ -0,0 +1,437 @@
+(function () {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonPerimeterEdit', moonPerimeterEdit);
+
+ moonPerimeterEdit.$inject = [];
+
+ function moonPerimeterEdit() {
+
+ return {
+ templateUrl: 'html/policy/edit/parameter/perimeter/perimeter-edit.tpl.html',
+ bindToController: true,
+ controller: moonPerimeterEditController,
+ controllerAs: 'edit',
+ scope: {
+ //Type can be 'ACTION', 'OBJECT', 'SUBJECT'
+ perimeterType: '=',
+ policy: '='
+ },
+ restrict: 'E',
+ replace: true
+ };
+ }
+
+
+ angular
+ .module('moon')
+ .controller('moonPerimeterEditController', moonPerimeterEditController);
+
+ moonPerimeterEditController.$inject = ['$scope', '$rootScope',
+ 'perimeterService', 'PERIMETER_CST', 'alertService',
+ '$translate', 'formService', 'policyService', 'utilService'];
+
+ function moonPerimeterEditController($scope, $rootScope,
+ perimeterService, PERIMETER_CST, alertService,
+ $translate, formService, policyService, utilService) {
+
+ var edit = this;
+
+ edit.perimeterType = $scope.edit.perimeterType;
+ // This variable is used in the view in order to display or not display email field
+ edit.subjectType = PERIMETER_CST.TYPE.SUBJECT;
+ edit.policy = $scope.edit.policy;
+
+ edit.fromList = true;
+
+ edit.loading = false;
+
+ edit.form = {};
+
+ edit.perimeter = {name: null, description: null, partner_id: null, policy_list: [], email: null};
+
+ edit.list = [];
+ edit.policyList = [];
+ edit.policiesToBeSelected = [];
+ edit.selectedPolicyList = []; // List of Policies to be added to a new perimeter
+
+ edit.create = createPerimeter;
+ edit.addToPolicy = addToPolicy;
+ edit.addPolicyToPerimeter = addPolicyToPerimeter;
+ edit.clearSelectedPolicies = clearSelectedPolicies;
+ edit.removeSelectedPolicy = removeSelectedPolicy;
+ edit.deletePerimeter = deletePerimeter;
+
+ activate();
+
+ /*
+ *
+ */
+
+ function activate() {
+
+ loadAllPolicies();
+
+ switch (edit.perimeterType) {
+
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ perimeterService.subject.findAllWithCallback(callBackList);
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ perimeterService.object.findAllWithCallback(callBackList);
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ perimeterService.action.findAllWithCallback(callBackList);
+ break;
+
+ default :
+
+ edit.list = [];
+ break;
+
+ }
+
+ function callBackList(list) {
+
+ // For each Perimeter, there is a check about the mapping between the perimeter and the policy
+ _.each(list, function (element) {
+
+ if (_.indexOf(element.policy_list, edit.policy.id) === -1) {
+
+ edit.list.push(element);
+
+ }
+
+ });
+
+ }
+
+ }
+
+ var rootListeners = {
+
+ 'event:unMapPerimeterFromPerimeterList': $rootScope.$on('event:unMapPerimeterFromPerimeterList', manageUnMappedPerimeter)
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+
+ function loadAllPolicies() {
+
+ edit.policyList = [];
+
+ policyService.findAllWithCallback( function(data) {
+
+ edit.policyList = data;
+ edit.policiesToBeSelected = angular.copy(edit.policyList);
+
+ });
+ }
+
+ function addPolicyToPerimeter() {
+
+ if (!edit.selectedPolicy || _.contains(edit.perimeter.policy_list, edit.selectedPolicy.id)) {
+ return;
+ }
+
+ edit.perimeter.policy_list.push(edit.selectedPolicy.id);
+ edit.selectedPolicyList.push(edit.selectedPolicy);
+ edit.policiesToBeSelected = _.without(edit.policiesToBeSelected, edit.selectedPolicy);
+
+ }
+
+ function clearSelectedPolicies() {
+
+ edit.perimeter.policy_list = [];
+ edit.selectedPolicyList = [];
+ edit.policiesToBeSelected = angular.copy(edit.policyList);
+
+ }
+
+ function removeSelectedPolicy(policy) {
+
+ edit.policiesToBeSelected.push(policy);
+ edit.perimeter.policy_list = _.without(edit.perimeter.policy_list, policy.id);
+ edit.selectedPolicyList = _.without(edit.selectedPolicyList, policy);
+
+ }
+
+ /**
+ * Add
+ */
+
+ function addToPolicy() {
+
+ if (!edit.selectedPerimeter) {
+
+ return;
+
+ }
+
+ startLoading();
+
+ var perimeterToSend = edit.selectedPerimeter;
+
+ perimeterToSend.policy_list.push(edit.policy.id);
+
+ switch (edit.perimeterType) {
+
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ perimeterService.subject.update(perimeterToSend, updatePerimeterSuccess, updatePerimeterError);
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ perimeterService.object.update(perimeterToSend, updatePerimeterSuccess, updatePerimeterError);
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ perimeterService.action.update(perimeterToSend, updatePerimeterSuccess, updatePerimeterError);
+ break;
+ }
+
+
+ function updatePerimeterSuccess(data) {
+
+ $translate('moon.perimeter.update.success', {policyName: perimeterToSend.name}).then(function (translatedValue) {
+
+ alertService.alertSuccess(translatedValue);
+
+ });
+
+ stopLoading();
+
+ }
+
+ function updatePerimeterError(reason) {
+
+ $translate('moon.policy.update.error', {
+ policyName: perimeterToSend.name,
+ reason: reason.message
+ }).then(function (translatedValue) {
+
+ alertService.alertError(translatedValue);
+
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ /**
+ * Create
+ */
+
+ function createPerimeter() {
+
+ if (formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ } else {
+
+ startLoading();
+
+ var perimeterToSend = angular.copy(edit.perimeter);
+
+ switch (edit.perimeterType) {
+
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ perimeterService.subject.add(perimeterToSend, createSuccess, createError);
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ perimeterService.object.add(perimeterToSend, createSuccess, createError);
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ perimeterService.action.add(perimeterToSend, createSuccess, createError);
+ break;
+ }
+
+ }
+
+ function createSuccess(data) {
+
+ var created = {};
+
+ switch (edit.perimeterType) {
+
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ created = utilService.transformOne(data, 'subjects');
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ created = utilService.transformOne(data, 'objects');
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ created = utilService.transformOne(data, 'actions');
+ break;
+ }
+
+ $translate('moon.policy.perimeter.edit.create.success', {name: created.name}).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ stopLoading();
+
+ /**
+ * If during the creating the created assignments has be mapped with the current policy, then it is not required to push the new Assignments in the list
+ */
+ if (_.indexOf(created.policy_list, edit.policy.id) === -1) {
+
+ edit.list.push(created);
+
+ }else{
+
+ $scope.$emit('event:createAssignmentsFromAssignmentsEditSuccess', created, edit.perimeterType);
+
+ }
+
+ displayList();
+
+ clearSelectedPolicies();
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.policy.perimeter.edit.create.error', {name: perimeterToSend.name}).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ /**
+ * Delete
+ */
+ function deletePerimeter() {
+
+ if (!edit.selectedPerimeter) {
+
+ return;
+
+ }
+
+ startLoading();
+
+ var perimeterToDelete = angular.copy(edit.selectedPerimeter);
+
+ switch (edit.perimeterType) {
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ perimeterService.subject.delete(perimeterToDelete, deleteSuccess, deleteError);
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ perimeterService.object.delete(perimeterToDelete, deleteSuccess, deleteError);
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ perimeterService.action.delete(perimeterToDelete, deleteSuccess, deleteError);
+ break;
+ }
+
+
+ function deleteSuccess(data) {
+
+ $translate('moon.policy.perimeter.edit.delete.success', {name: perimeterToDelete.name})
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ policyService.findOneReturningPromise(edit.policy.id).then(function (data) {
+
+ edit.policy = utilService.transformOne(data, 'policies');
+
+ cleanSelectedValue();
+ activate();
+ stopLoading();
+
+ $scope.$emit('event:deletePerimeterFromPerimeterAddSuccess', edit.policy);
+
+ });
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.policy.perimeter.edit.delete.error', {name: perimeterToDelete.name}).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+ }
+
+ function cleanSelectedValue() {
+
+ delete edit.selectedPerimeter;
+
+ }
+
+ function startLoading() {
+
+ edit.loading = true;
+
+ }
+
+ function stopLoading() {
+
+ edit.loading = false;
+
+ }
+
+ function displayList() {
+
+ edit.fromList = true;
+
+ }
+
+ /**
+ * If A perimeter has been unMapped, maybe it has to be display into the available list of Perimeter
+ * @param perimeter
+ * @param type
+ */
+ function manageUnMappedPerimeter(event, perimeter, type){
+
+ if(type === edit.perimeterType && _.indexOf(perimeter.policy_list, edit.policy.id) === -1){
+
+ edit.list.push(perimeter);
+
+ }
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js
new file mode 100755
index 00000000..dffa7783
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js
@@ -0,0 +1,284 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonPerimeterList', moonPerimeterList);
+
+ moonPerimeterList.$inject = [];
+
+ function moonPerimeterList() {
+
+ return {
+ templateUrl : 'html/policy/edit/parameter/perimeter/perimeter-list.tpl.html',
+ bindToController : true,
+ controller : moonPerimeterListController,
+ controllerAs : 'list',
+ scope : {
+ policy: '=',
+ editMode : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+
+ }
+
+ angular
+ .module('moon')
+ .controller('moonPerimeterListController', moonPerimeterListController);
+
+ moonPerimeterListController.$inject = ['$scope', '$rootScope', 'perimeterService', '$translate', 'alertService', 'PERIMETER_CST'];
+
+ function moonPerimeterListController($scope, $rootScope, perimeterService, $translate, alertService, PERIMETER_CST){
+
+ var list = this;
+
+ list.policy = $scope.list.policy;
+ list.editMode = $scope.list.editMode;
+
+ list.typeOfSubject = PERIMETER_CST.TYPE.SUBJECT;
+ list.typeOfObject = PERIMETER_CST.TYPE.OBJECT;
+ list.typeOfAction = PERIMETER_CST.TYPE.ACTION;
+
+ list.unMapSub = unMapSub;
+ list.unMapObj = unMapObj;
+ list.unMapAct = unMapAct;
+
+ list.getSubjects = getSubjects;
+ list.getObjects = getObjects;
+ list.getActions = getActions;
+
+ activate();
+
+ function activate(){
+
+ manageSubjects();
+
+ manageObjects();
+
+ manageActions();
+
+ }
+
+ var rootListeners = {
+
+ 'event:deletePerimeterFromPerimeterAddSuccess': $rootScope.$on('event:deletePerimeterFromPerimeterAddSuccess', deletePolicy),
+ 'event:createAssignmentsFromAssignmentsEditSuccess': $rootScope.$on('event:createAssignmentsFromAssignmentsEditSuccess', addAssignmentsToPolicy)
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+
+ function manageSubjects(){
+
+ list.loadingSub = true;
+
+ perimeterService.subject.findAllFromPolicyWithCallback(list.policy.id, function(perimeters){
+
+ list.subjects = perimeters;
+ list.loadingSub = false;
+
+ });
+ }
+
+ function manageObjects(){
+
+ list.loadingObj = true;
+
+ perimeterService.object.findAllFromPolicyWithCallback(list.policy.id, function(perimeters){
+
+ list.objects = perimeters;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions(){
+
+ list.loadingAct = true;
+
+ perimeterService.action.findAllFromPolicyWithCallback(list.policy.id, function(perimeters){
+
+ list.actions = perimeters;
+ list.loadingAct = false;
+
+ });
+
+ }
+
+ /**
+ * UnMap
+ */
+
+ function unMapSub(perimeter){
+
+ perimeter.policy_list = _.without(perimeter.policy_list, list.policy.id);
+
+ perimeter.loader = true;
+
+ var perimeterToSend = angular.copy(perimeter);
+
+ perimeterService.subject.unMapPerimeterFromPolicy(list.policy.id , perimeter.id, updatePerimeterSuccess, updatePerimeterError);
+
+ function updatePerimeterSuccess(data){
+
+ $translate('moon.policy.perimeter.update.success', { perimeterName: perimeterToSend.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ $scope.$emit('event:unMapPerimeterFromPerimeterList', perimeter, PERIMETER_CST.TYPE.SUBJECT);
+
+ activate();
+
+ perimeter.loader = false;
+ }
+
+ function updatePerimeterError(reason){
+
+ $translate('moon.policy.perimeter.update.error', { perimeterName: perimeter.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ perimeter.loader = false;
+
+ }
+
+ }
+
+ function unMapObj(perimeter){
+
+ perimeter.policy_list = _.without(perimeter.policy_list, list.policy.id);
+
+ perimeter.loader = true;
+
+ var perimeterToSend = angular.copy(perimeter);
+
+ perimeterService.object.unMapPerimeterFromPolicy(list.policy.id , perimeter.id, updatePerimeterSuccess, updatePerimeterError);
+
+ function updatePerimeterSuccess(data){
+
+ $translate('moon.policy.perimeter.update.success', { perimeterName: perimeterToSend.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ $scope.$emit('event:unMapPerimeterFromPerimeterList', perimeter, PERIMETER_CST.TYPE.OBJECT);
+
+ activate();
+
+ perimeter.loader = false;
+ }
+
+ function updatePerimeterError(reason){
+
+ $translate('moon.policy.perimeter.update.error', { perimeterName: perimeter.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ perimeter.loader = false;
+
+ }
+
+ }
+
+ function unMapAct(perimeter){
+
+ perimeter.policy_list = _.without(perimeter.policy_list, list.policy.id);
+
+ perimeter.loader = true;
+
+ var perimeterToSend = angular.copy(perimeter);
+
+ perimeterService.action.unMapPerimeterFromPolicy(list.policy.id , perimeter.id, updatePerimeterSuccess, updatePerimeterError);
+
+ function updatePerimeterSuccess(data){
+
+ $translate('moon.policy.perimeter.update.success', { perimeterName: perimeterToSend.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ $scope.$emit('event:unMapPerimeterFromPerimeterList', perimeter, PERIMETER_CST.TYPE.ACTION);
+
+ activate();
+
+ perimeter.loader = false;
+ }
+
+ function updatePerimeterError(reason){
+
+ $translate('moon.policy.perimeter.update.error', { perimeterName: perimeter.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ perimeter.loader = false;
+
+ }
+
+ }
+
+ function getSubjects(){
+ return list.subjects ? list.subjects : [];
+ }
+
+ function getObjects(){
+ return list.objects ? list.objects : [];
+ }
+
+ function getActions(){
+ return list.actions ? list.actions : [];
+ }
+
+ function removeSubFromSubList(subject){
+ list.subjects = _.without(list.subjects, subject);
+ }
+
+ function removeObjFromObjList(object){
+ list.objects = _.without(list.objects, object);
+ }
+
+ function removeActFromActList(action){
+ list.actions = _.without(list.actions, action);
+ }
+
+ function deletePolicy( event, policy){
+
+ list.policy = policy;
+
+ activate();
+
+ }
+
+ function addAssignmentsToPolicy( event, assignments, type){
+
+ switch (type) {
+
+ case PERIMETER_CST.TYPE.SUBJECT:
+
+ list.subjects.push(assignments);
+ break;
+
+ case PERIMETER_CST.TYPE.OBJECT:
+
+ list.objects.push(assignments);
+ break;
+
+ case PERIMETER_CST.TYPE.ACTION:
+
+ list.actions.push(assignments);
+ break;
+
+ default :
+ break;
+
+ }
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/rules/rules-edit.tpl.html b/moon_gui/static/app/policy/edit/parameter/rules/rules-edit.tpl.html
new file mode 100755
index 00000000..685046a5
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/rules/rules-edit.tpl.html
@@ -0,0 +1,341 @@
+<div>
+
+ <div class="col-md-12 col-sm-12 col-xs-12">
+
+ <form ng-if="!edit.fromList" class="form-horizontal" role="form" name="edit.form">
+
+ <!-- Select Policy -->
+ <div class="form-group" ng-class="{'has-error': edit.form.policyList.$invalid && edit.form.policyList.$dirty}" >
+
+ <label for="policyList" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.policies">Policy List</label>
+
+ <div class="col-sm-6" >
+
+ <ui-select ng-model="edit.selectedPolicy" name="policyList" id="policyList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aPolicy in edit.policyList">
+ <div ng-value="aPolicy" ng-bind="aPolicy.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.policyList.$dirty && edit.form.policyList.$invalid">
+ <small class="error" ng-show="edit.form.policyList.$error.required" data-translate="moon.policy.rules.edit.action.add.check.policy.required">Policy is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="!edit.selectedPolicy.meta_rules_values">
+ <div class="col-sm-6 col-sm-offset-3">
+ <moon-loader></moon-loader>
+ </div>
+ </div>
+
+ <div ng-if="edit.selectedPolicy.meta_rules_values">
+
+ <!-- Select Meta Rules -->
+ <div class="form-group" ng-class="{'has-error': edit.form.metaRulesList.$invalid && edit.form.metaRulesList.$dirty}" >
+
+ <label for="metaRulesList" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.metarules">MetaRules List</label>
+
+ <div class="col-sm-6" >
+
+ <ui-select ng-model="edit.selectedMetaRules" name="metaRulesList" id="metaRulesList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aMetaRules in edit.selectedPolicy.meta_rules_values">
+ <div ng-value="aMetaRules" ng-bind="aMetaRules.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.metaRulesList.$dirty && edit.form.metaRulesList.$invalid">
+ <small class="error" ng-show="edit.form.metaRulesList.$error.required" data-translate="moon.policy.rules.edit.action.add.check.metarules.required">A MetaRules is required</small>
+ </div>
+
+ </div>
+
+ <div>
+ <a href="" ng-if="edit.selectedMetaRules" ng-click="edit.showDetailselectedMetaRules = !edit.showDetailselectedMetaRules">
+
+ <span ng-if="!edit.showDetailselectedMetaRules">
+ <span data-translate="moon.policy.rules.edit.action.add.details.show">Show</span>
+ <span class="glyphicon glyphicon-eye-open"></span>
+ </span>
+
+ <span ng-if="edit.showDetailselectedMetaRules">
+ <span data-translate="moon.policy.rules.edit.action.add.details.close">Close</span>
+ <span class="glyphicon glyphicon-eye-close"></span>
+ </span>
+
+ </a>
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-if="edit.showDetailselectedMetaRules && edit.selectedMetaRules">
+ <moon-meta-data-list edit-mode="edit.editMode" meta-rule="edit.selectedMetaRules" short-display="true"></moon-meta-data-list>
+ </div>
+
+ <!-- Select Data -->
+ <div class="form-group" ng-if="edit.selectedMetaRules">
+
+ <div class="col-md-4">
+
+ <div ng-if="edit.selectedMetaRules.subject_categories.length > 0">
+
+ <div class="row">
+
+ <div ng-if="!edit.data.loadingSubjects">
+
+ <label for="subjectsList" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.categories.subject" data-translate-values="{ number: edit.selectedMetaRules.subject_categories.length }">Select Subject(s)</label>
+
+ <div class="col-sm-7" >
+
+ <ui-select ng-model="edit.selectedSubject" name="subjectsList" id="subjectsList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="aSubject in edit.data.subjectsToBeSelected">
+ <div ng-value="aSubject" ng-bind="aSubject.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.subjectsList.$dirty && edit.form.subjectsList.$invalid || !edit.numberOfSelectedSubjectValid">
+ <small class="error" ng-show="edit.form.subjectsList.$error.required || !edit.numberOfSelectedSubjectValid" data-translate="moon.policy.rules.edit.action.add.check.subject.required" data-translate-values="{ number: edit.selectedMetaRules.subject_categories.length }">Some subject are required</small>
+ </div>
+
+ </div>
+
+ <div class="col-sm-2 text-center">
+ <a href="" ng-if="edit.selectedSubject && !edit.isNumberSelectedDataAtMaximum(edit.data.subjectCST)"
+ ng-click="edit.addDataToRules(edit.data.subjectCST)"><span style="font-size:1.5em; line-height: 1.5em;" class="glyphicon glyphicon-plus-sign"></span></a>
+ </div>
+
+ </div>
+
+ <div ng-if="edit.data.loadingSubjects">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </div>
+
+ <div class="row" ng-if="!edit.data.loadingSubjects">
+
+ <div class="form-group">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.selectedSubjects">Selected Subjcet(s)</label>
+
+ <div class="col-sm-6">
+
+ <ul>
+
+ <li ng-repeat="(key, value) in edit.data.selectedSubjectsList">
+
+ <span ng-bind="value.name" ></span> <a href="" ng-click="edit.removeSelectedDataFromRules(value, edit.data.subjectCST)"><span style="font-size:1.5em; line-height: 1.5em" class="glyphicon glyphicon-remove"></span></a>
+
+ </li>
+
+ </ul>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="edit.selectedMetaRules.subject_categories.length === 0">
+
+ </div>
+
+ </div>
+
+ <div class="col-md-4">
+
+ <div ng-if="edit.selectedMetaRules.object_categories.length > 0">
+
+ <div class="row">
+
+ <div ng-if="!edit.data.loadingObjects">
+
+ <label for="objectsList" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.categories.object" data-translate-values="{ number: edit.selectedMetaRules.object_categories.length }">Select Object(s)</label>
+
+ <div class="col-sm-7" >
+
+ <ui-select ng-model="edit.selectedObject" name="objectsList" id="objectsList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.value.name"></ui-select-match>
+ <ui-select-choices repeat="aObject in edit.data.objectsToBeSelected">
+ <div ng-value="aObject" ng-bind="aObject.value.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.objectsList.$dirty && edit.form.objectsList.$invalid || !edit.numberOfSelectedObjecttValid">
+ <small class="error" ng-show="edit.form.objectsList.$error.required || !edit.numberOfSelectedObjecttValid" data-translate="moon.policy.rules.edit.action.add.check.object.required" data-translate-values="{ number: edit.selectedMetaRules.object_categories.length }">Some objects are required</small>
+ </div>
+
+ </div>
+
+ <div class="col-sm-2 text-center">
+ <a href="" ng-if="edit.selectedObject && !edit.isNumberSelectedDataAtMaximum(edit.data.objectCST)"
+ ng-click="edit.addDataToRules(edit.data.objectCST)"><span style="font-size:1.5em; line-height: 1.5em;" class="glyphicon glyphicon-plus-sign"></span></a>
+ </div>
+
+ </div>
+
+ <div ng-if="edit.data.loadingObjects">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </div>
+
+ <div class="row" ng-if="!edit.data.loadingObjects">
+
+ <div class="form-group">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.selectedObjects">Selected Objcet(s)</label>
+
+ <div class="col-sm-6">
+
+ <ul>
+
+ <li ng-repeat="(key, value) in edit.data.selectedObjectsList">
+
+ <span ng-bind="value.value.name" ></span> <a href="" ng-click="edit.removeSelectedDataFromRules(value, edit.data.objectCST)"><span style="font-size:1.5em; line-height: 1.5em" class="glyphicon glyphicon-remove"></span></a>
+
+ </li>
+
+ </ul>
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="edit.selectedMetaRules.object_categories.length === 0">
+
+ </div>
+
+ </div>
+
+ <div class="col-md-4">
+
+ <div ng-if="edit.selectedMetaRules.action_categories.length > 0">
+
+ <div class="row">
+
+ <div ng-if="!edit.data.loadingActions">
+
+ <label for="actionsList" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.categories.action" data-translate-values="{ number: edit.selectedMetaRules.action_categories.length }">Select Action(s)</label>
+
+ <div class="col-sm-7" >
+
+ <ui-select ng-model="edit.selectedAction" name="actionsList" id="actionsList" required>
+
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.value.name"></ui-select-match>
+ <ui-select-choices repeat="aAction in edit.data.actionsToBeSelected">
+ <div ng-value="aAction" ng-bind="aAction.value.name"></div>
+ </ui-select-choices>
+
+ </ui-select>
+
+ <div class="help-block" ng-show="edit.form.actionsList.$dirty && edit.form.actionsList.$invalid || !edit.numberOfSelectedActionsValid">
+ <small class="error" ng-show="edit.form.actionsList.$error.required || !edit.numberOfSelectedActionsValid" data-translate="moon.policy.rules.edit.action.add.check.action.required" data-translate-values="{ number: edit.selectedMetaRules.action_categories.length }">Some action are required</small>
+ </div>
+ </div>
+
+ <div class="col-sm-2 text-center">
+ <a href="" ng-if="edit.selectedAction && !edit.isNumberSelectedDataAtMaximum(edit.data.actionCST)"
+ ng-click="edit.addDataToRules(edit.data.actionCST)"><span style="font-size:1.5em; line-height: 1.5em;" class="glyphicon glyphicon-plus-sign"></span></a>
+ </div>
+
+ </div>
+
+ <div ng-if="edit.data.loadingActions">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </div>
+
+ <div class="row" ng-if="!edit.data.loadingActions">
+
+ <div class="form-group">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.selectedActions">Selected Action(s)</label>
+
+ <div class="col-sm-6">
+
+ <ul>
+
+ <li ng-repeat="(key, value) in edit.data.selectedActionsList">
+
+ <span ng-bind="value.value.name" ></span> <a href="" ng-click="edit.removeSelectedDataFromRules(value, edit.data.actionCST)"><span style="font-size:1.5em; line-height: 1.5em" class="glyphicon glyphicon-remove"></span></a>
+
+ </li>
+
+ </ul>
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="edit.selectedMetaRules.action_categories.length === 0">
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': edit.form.instructions.$invalid && edit.form.instructions.$dirty || !edit.instructionsValid}">
+
+ <label for="instructions" class="col-sm-3 control-label" data-translate="moon.policy.rules.edit.action.add.instructions">Instruction</label>
+
+ <div class="col-sm-6">
+ <textarea id="instructions" name="instructions" class="form-control" ng-model="edit.rules.instructions" rows="6" required></textarea>
+ <div class="help-block" ng-show="edit.form.instructions.$dirty && edit.form.instructions.$invalid || !edit.instructionsValid ">
+ <small class="error" data-translate="moon.policy.rules.edit.action.add.check.instructions.required">An instructions is required</small>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="pull-right">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.rules.edit.action.create">Create</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html b/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html
new file mode 100755
index 00000000..76ac4365
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html
@@ -0,0 +1,134 @@
+<div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.rules.edit.title">List of associated Subjects</h4>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.rules.list.table.metaRule">Meta Rule</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.policy.rules.list.table.rule">Rule</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.policy.rules.list.table.instructions">Instruction</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.policy.rules.list.table.action.title">Actions</div>
+ </th>
+ </tr>
+
+ </thead>
+
+ <moon-loader ng-if="list.loadingRules"></moon-loader>
+
+ <tbody ng-if="!list.loadingRules && !list.hasRules()">
+ <tr>
+ <td colspan="4"><span data-translate="moon.policy.rules.list.table.notFound">There is no Rules</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="!list.loadingRules && list.hasRules()">
+
+ <tr ng-repeat="aRule in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td>
+ <span ng-if="!list.getMetaRuleFromRule(aRule)">
+ <moon-loader ng-if="!list.getMetaRuleFromRule(aRule)" ></moon-loader>
+ <em data-translate="moon.policy.rules.list.table.loading.metaRule">Loading </em>
+ </span>
+
+ <span ng-if="list.getMetaRuleFromRule(aRule)">
+ <span ng-bind="aRule.meta_rule.name"></span>
+ </span>
+ </td>
+
+ <td>
+
+ <span ng-if="!list.getMetaRuleFromRule(aRule)">
+ <moon-loader ng-if="!list.getMetaRuleFromRule(aRule)" ></moon-loader>
+ <em data-translate="moon.policy.rules.list.table.loading.metaRule">Loading </em>
+ </span>
+
+ <span ng-if="list.getMetaRuleFromRule(aRule)" ng-repeat="(key, value) in aRule.rule">
+
+ <span ng-if="!list.getCategoryFromRuleIndex(key, aRule)">
+ <moon-loader ng-if="!list.getCategoryFromRuleIndex(key, aRule)" ></moon-loader>
+ </span>
+
+ <span ng-if="list.getCategoryFromRuleIndex(key, aRule)">
+ <span ng-if="aRule.rule_value[key].category.name" ng-bind="aRule.rule_value[key].category.name"></span>
+ <span ng-if="aRule.rule_value[key].category.value.name" ng-bind="aRule.rule_value[key].category.value.name"></span>
+ <span ng-if="key < aRule.rule.length-1">,</span>
+ </span>
+
+ </span>
+
+ </td>
+
+ <td>
+ <pre ng-bind="aRule.instructions | json "></pre>
+ </td>
+
+ <td>
+
+ <a href="" ng-if="!aRule.loader" ng-click="list.deleteRules(aRule)" >
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span class="control-label" data-translate="moon.policy.rules.list.table.action.delete">Delete</span>
+ </a>
+
+ <div ng-if="aRule.loader">
+
+ <moon-loader></moon-loader>
+
+ </div>
+
+ </td>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div ng-if="list.editMode" class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <h4 data-translate="moon.policy.rules.edit.action.add.title">Add a Rules</h4>
+
+ </div>
+
+ <div class="panel-body">.
+
+ <moon-rules-edit policy="list.policy"></moon-rules-edit>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/rules/rules.edit.dir.js b/moon_gui/static/app/policy/edit/parameter/rules/rules.edit.dir.js
new file mode 100755
index 00000000..b7bb7614
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/rules/rules.edit.dir.js
@@ -0,0 +1,537 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonRulesEdit', moonRulesEdit);
+
+ moonRulesEdit.$inject = [];
+
+ function moonRulesEdit() {
+
+ return {
+ templateUrl : 'html/policy/edit/parameter/rules/rules-edit.tpl.html',
+ bindToController : true,
+ controller : moonRulesEditController,
+ controllerAs : 'edit',
+ scope : {
+ policy : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+
+ }
+
+ angular
+ .module('moon')
+ .controller('moonRulesEditController', moonRulesEditController);
+
+ moonRulesEditController.$inject = ['$scope', 'rulesService', 'alertService', '$translate',
+ 'formService', 'policyService', 'utilService', 'metaRuleService', 'metaDataService', 'modelService', 'dataService', 'DATA_CST'];
+
+ function moonRulesEditController($scope, rulesService, alertService, $translate,
+ formService, policyService, utilService, metaRuleService, metaDataService, modelService, dataService, DATA_CST) {
+
+ var edit = this;
+
+ edit.policy = $scope.edit.policy;
+ edit.editMode = true;
+
+ edit.fromList = false;
+
+ edit.loading = false;
+
+ edit.form = {};
+ edit.showDetailselectedMetaRules = false;
+
+ edit.list = [];
+ edit.policyList = [];
+
+ edit.categories = {
+ subject : [],
+ loadingSubjects: true,
+ object : [],
+ loadingObjects: true,
+ action : [],
+ loadingActions : true
+ };
+
+ edit.data = {}; // this object is filled in declareDataObject():
+
+ edit.create = createRules;
+ edit.addDataToRules = addDataToRules;
+ edit.removeSelectedDataFromRules = removeSelectedDataFromRules;
+ edit.isNumberSelectedDataAtMaximum = isNumberSelectedDataAtMaximum;
+
+ //this variable is related to checks on Instruction field which is in JSON
+ edit.instructionsValid = true;
+ edit.numberOfSelectedSubjectValid = true;
+ edit.numberOfSelectedObjecttValid = true;
+ edit.numberOfSelectedActionsValid = true;
+
+ activate();
+
+ /*
+ *
+ */
+ function activate(){
+
+ edit.rules = {meta_rule_id: null, rule: [], policy_id: null, instructions: '[{"decision": "grant"}]', enabled: true};
+ declareDataObject();
+ loadAllPolicies();
+ clearSelectedMetaRules();
+
+ }
+
+ function loadAllPolicies() {
+
+ edit.policyList = [];
+
+ policyService.findAllWithCallback( function(data) {
+
+ _.each(data, function(element){
+
+ if(element.id === edit.policy.id){
+ edit.selectedPolicy = element;
+ }
+
+ });
+
+ edit.policyList = data;
+
+ });
+ }
+
+ $scope.$watch('edit.selectedPolicy', function(newValue){
+
+ clearSelectedMetaRules();
+
+ if(!_.isUndefined(newValue)){
+
+ loadRelatedMetaRules();
+
+ }
+
+ });
+
+ $scope.$watch('edit.selectedMetaRules', function(newValue){
+
+ clearSelectedData();
+
+ edit.categories = {
+ subject : [],
+ loadingSubjects: true,
+ object : [],
+ loadingObjects: true,
+ action : [],
+ loadingActions : true
+ };
+
+ declareDataObject();
+
+ if(!_.isUndefined(newValue)){
+
+ loadRelatedCategoriesAndData(newValue.subject_categories, newValue.object_categories, newValue.action_categories);
+
+ }
+
+ });
+
+ /**
+ * To get the related MetaRules, it is required to :
+ * - Get the model related to the policy
+ * - Get the metaRules associated to the model
+ * - Get the MetaData associated to the metaRules
+ */
+ function loadRelatedMetaRules() {
+
+ edit.selectedPolicy.meta_rules_values = undefined;
+
+ modelService.findOneWithCallback(edit.selectedPolicy.model_id, function(model){
+
+ metaRuleService.findSomeWithCallback(model.meta_rules, function(metaRules){
+
+ edit.selectedPolicy.meta_rules_values = metaRules;
+
+ });
+
+ });
+
+ }
+
+ /**
+ * Load categories from arrays of id in args
+ * @param subjectsCategories, list of subject id related to the metaRule
+ * @param objectCategories, list of object id related to the metaRule
+ * @param actionsCategories, list of action id related to the metaRule
+ */
+ function loadRelatedCategoriesAndData(subjectsCategories, objectCategories, actionsCategories){
+
+ metaDataService.subject.findSomeWithCallback(subjectsCategories, function(list){
+
+ edit.categories.subject = list;
+ edit.categories.loadingSubjects = false;
+
+ _.each(edit.categories.subject, function(aSubject){
+
+ dataService.subject.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, aSubject.id, function(subjects){
+
+ edit.data.subject = subjects;
+ edit.data.loadingSubjects = false;
+ edit.data.subjectsToBeSelected = angular.copy(edit.data.subject);
+
+ });
+
+ });
+
+ });
+
+ metaDataService.object.findSomeWithCallback(objectCategories, function(list){
+
+ edit.categories.object = list;
+ edit.categories.loadingObjects = false;
+
+ _.each(edit.categories.object, function(aObject){
+
+ dataService.object.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, aObject.id, function(objects){
+
+ edit.data.object = objects;
+ edit.data.loadingObjects = false;
+ edit.data.objectsToBeSelected = angular.copy(edit.data.object);
+
+ });
+
+ });
+
+ });
+
+ metaDataService.action.findSomeWithCallback(actionsCategories, function(list){
+
+ edit.categories.action = list;
+ edit.categories.loadingActions = false;
+
+ _.each(edit.categories.action, function(aAction){
+
+ dataService.action.findAllFromCategoriesWithCallback(edit.selectedPolicy.id, aAction.id, function(actions){
+
+ edit.data.action = actions;
+ edit.data.loadingActions = false;
+ edit.data.actionsToBeSelected = angular.copy(edit.data.action);
+
+ });
+
+ });
+
+ });
+
+ }
+
+ /**
+ * createRules, create Rules depending of what has been filled in the view
+ */
+ function createRules() {
+
+ edit.instructionsValid = true;
+ edit.numberOfSelectedSubjectValid = true;
+ edit.numberOfSelectedObjecttValid = true;
+ edit.numberOfSelectedActionsValid = true;
+
+ manageInstructionContent();
+ // bellow function is called here in order to display errors into the view
+ manageNumberOfSelectedData();
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ //manageNumberOfSelectedData is call again in order to check if errors have been display into the view
+ }else if(edit.instructionsValid && manageNumberOfSelectedData()){
+
+ startLoading();
+ buildRulesArray();
+
+ edit.rules.meta_rule_id = edit.selectedMetaRules.id;
+ edit.rules.policy_id = edit.selectedPolicy.id;
+
+ var rulesToSend = angular.copy(edit.rules);
+ rulesToSend.instructions = JSON.parse(edit.rules.instructions);
+
+ rulesService.add(rulesToSend, edit.policy.id, createSuccess, createError);
+ }
+
+
+ function createSuccess(data) {
+
+ var created = utilService.transformOne(data, 'rules');
+
+ $translate('moon.policy.rules.edit.action.add.create.success').then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ $scope.$emit('event:createRulesFromDataRulesSuccess', created);
+
+ activate();
+
+ stopLoading();
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.policy.rules.edit.action.add.create.error').then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ stopLoading();
+
+ }
+
+ }
+
+ /**
+ * if instructions attribute is not good then edit.instructionsValid is set to false
+ * it will allow the view to display an error
+ */
+ function manageInstructionContent(){
+
+ if (!isInstructionValid(edit.rules.instructions)){
+
+ edit.instructionsValid = false;
+
+ }else{
+
+ edit.instructionsValid = true;
+
+ }
+ }
+
+ /**
+ * return true if the user has selected the number required of Selected Data (subject, object or action)
+ * if one is missing then return false
+ * it will also set numberOfSelected(Subject/Object/Action)Valid to true or false in order to display errors form in the view
+ * @returns {boolean}
+ */
+ function manageNumberOfSelectedData(){
+
+ isNumberSelectedDataAtMaximum(DATA_CST.TYPE.SUBJECT) ?
+ edit.numberOfSelectedSubjectValid = true: edit.numberOfSelectedSubjectValid = false;
+ isNumberSelectedDataAtMaximum(DATA_CST.TYPE.OBJECT) ?
+ edit.numberOfSelectedObjecttValid = true: edit.numberOfSelectedObjecttValid = false;
+ isNumberSelectedDataAtMaximum(DATA_CST.TYPE.ACTION) ?
+ edit.numberOfSelectedActionsValid = true: edit.numberOfSelectedActionsValid = false;
+
+ return edit.numberOfSelectedSubjectValid && edit.numberOfSelectedObjecttValid && edit.numberOfSelectedActionsValid;
+ }
+
+ /**
+ * Check if the variables in param is not undefined and if it is a JSON
+ * It is used for instructions attribute of a Rules object
+ * @param str
+ * @returns {boolean|*}
+ */
+ function isInstructionValid(str){
+
+ return !_.isUndefined(str) && isJsonString(str);
+
+ }
+
+ function isJsonString(str) {
+
+ var item = null;
+
+ try {
+ item = JSON.parse(str);
+ } catch (e) {
+
+ return false;
+ }
+
+ if (typeof item === 'object' && item !== null) {
+
+ return true;
+ }
+
+ return false;
+ }
+
+ function startLoading(){
+
+ edit.loading = true;
+
+ }
+
+ function stopLoading(){
+
+ edit.loading = false;
+
+ }
+
+ /**
+ * allow to clear selected values in the form
+ */
+ function clearSelectedMetaRules(){
+
+ edit.selectedMetaRules = undefined;
+
+ clearSelectedData();
+
+ }
+
+ function clearSelectedData(){
+
+ edit.selectedSubject = undefined;
+ edit.selectedObject = undefined;
+ edit.selectedAction = undefined;
+
+ }
+
+ /**
+ * check if the number of Selected Data is equal to the number of categories associated to the metaRule
+ * @param typeCST : 'SUBJECT', 'OBJECT', 'ACTION'
+ * @returns {boolean}
+ */
+ function isNumberSelectedDataAtMaximum(typeCST){
+
+ if(!edit.selectedMetaRules){
+ return false;
+ }
+
+ switch (typeCST) {
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ return edit.data.selectedSubjectsList.length === edit.selectedMetaRules.subject_categories.length;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ return edit.data.selectedObjectsList.length === edit.selectedMetaRules.object_categories.length;
+
+ case DATA_CST.TYPE.ACTION:
+
+ return edit.data.selectedActionsList.length === edit.selectedMetaRules.action_categories.length;
+ }
+ }
+
+ /**
+ * Add a data to an array of selected value (SUBJECT/OBJECT/ACTION)
+ * those arrays will used in the create function in order to filled the rule attribute of a rules object
+ * it will remove the selected value from the possible value to be selected once the data is added
+ * @param typeCST
+ */
+ function addDataToRules(typeCST){
+
+ switch (typeCST) {
+ case DATA_CST.TYPE.SUBJECT:
+
+ if (!edit.selectedSubject || isNumberSelectedDataAtMaximum(typeCST)
+ || _.contains(edit.data.selectedSubjectsList, edit.selectedSubject)) {
+ return;
+ }
+
+ edit.data.selectedSubjectsList.push(edit.selectedSubject);
+ edit.data.subjectsToBeSelected = _.without(edit.data.subjectsToBeSelected, edit.selectedSubject);
+
+ break;
+ case DATA_CST.TYPE.OBJECT:
+
+ if (!edit.selectedObject || isNumberSelectedDataAtMaximum(typeCST)
+ || _.contains(edit.data.selectedObjectsList, edit.selectedObject)) {
+ return;
+ }
+
+ edit.data.selectedObjectsList.push(edit.selectedObject);
+ edit.data.objectsToBeSelected = _.without(edit.data.objectsToBeSelected, edit.selectedObject);
+
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+ if (!edit.selectedAction || isNumberSelectedDataAtMaximum(typeCST)
+ || _.contains(edit.data.selectedActionsList, edit.selectedAction)) {
+ return;
+ }
+
+ edit.data.selectedActionsList.push(edit.selectedAction);
+ edit.data.actionsToBeSelected = _.without(edit.data.actionsToBeSelected, edit.selectedAction);
+
+ break;
+ }
+
+ }
+
+ /**
+ * Remove a selected value,
+ * refresh the list of possible value to be selected with the removed selected value
+ * @param data
+ * @param typeCST
+ */
+ function removeSelectedDataFromRules(data, typeCST) {
+
+ switch (typeCST) {
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ edit.data.subjectsToBeSelected.push(data);
+ edit.data.selectedSubjectsList = _.without(edit.data.selectedSubjectsList, data);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ edit.data.objectsToBeSelected.push(data);
+ edit.data.selectedObjectsList = _.without(edit.data.selectedObjectsList, data);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ edit.data.actionsToBeSelected.push(data);
+ edit.data.selectedActionsList = _.without(edit.data.selectedActionsList, data);
+ break;
+ }
+
+ }
+
+ /**
+ * fill edit.rules.rule array with the selected data
+ * it will first add subject list, object list and then action list
+ */
+ function buildRulesArray(){
+
+ _.each(edit.data.selectedSubjectsList, pushInRulesTab);
+ _.each(edit.data.selectedObjectsList, pushInRulesTab);
+ _.each(edit.data.selectedActionsList, pushInRulesTab);
+
+ function pushInRulesTab(elem){
+ edit.rules.rule.push(elem.id);
+ }
+ }
+
+ /**
+ * Declare the data object which contains attributes related to data,
+ * values to be selected, values selected, loader...
+ */
+ function declareDataObject(){
+
+ edit.data = {
+ subject : [], // List of subjects related to the policy
+ loadingSubjects: true, // allow to know if a call to the API is in progress
+ subjectsToBeSelected : [], // List of subjects the user can select
+ selectedSubjectsList: [], // List of subjects selected by the user from subjectsToBeSelected
+ subjectCST : DATA_CST.TYPE.SUBJECT,
+ object : [],
+ loadingObjects: true,
+ objectsToBeSelected: [],
+ selectedObjectsList: [],
+ objectCST : DATA_CST.TYPE.OBJECT,
+ action : [],
+ loadingActions : true,
+ actionsToBeSelected : [],
+ selectedActionsList: [],
+ actionCST : DATA_CST.TYPE.ACTION
+ }
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js b/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js
new file mode 100755
index 00000000..5c3e7457
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js
@@ -0,0 +1,302 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonRulesList', moonRulesList);
+
+ moonRulesList.$inject = [];
+
+ function moonRulesList() {
+
+ return {
+ templateUrl : 'html/policy/edit/parameter/rules/rules-list.tpl.html',
+ bindToController : true,
+ controller : moonRulesListController,
+ controllerAs : 'list',
+ scope : {
+ policy: '=',
+ editMode : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonRulesListController', moonRulesListController);
+
+ moonRulesListController.$inject = [ '$scope', '$rootScope', 'NgTableParams', '$filter', 'metaRuleService', 'rulesService', 'dataService', '$translate', 'alertService' ];
+
+ function moonRulesListController( $scope, $rootScope, NgTableParams, $filter, metaRuleService, rulesService, dataService, $translate, alertService ) {
+
+ var list = this;
+
+ list.rules = [];
+ list.editMode = $scope.list.editMode;
+
+ list.loadingRules = true;
+
+ list.table = {};
+
+ list.getRules = getRules;
+ list.hasRules = hasRules;
+ list.refreshRules = refreshRules;
+ list.deleteRules = deleteRules;
+
+ list.getMetaRuleFromRule = getMetaRuleFromRule;
+ list.getCategoryFromRuleIndex = getCategoryFromRuleIndex;
+
+ list.isRuleIndexSubjectCategory = isRuleIndexSubjectCategory;
+ list.isRuleIndexObjectCategory = isRuleIndexObjectCategory;
+ list.isRuleIndexActionCategory = isRuleIndexActionCategory;
+
+ activate();
+
+ function activate(){
+
+ newRulesTable();
+
+ manageRules();
+
+ }
+
+ var rootListeners = {
+
+ 'event:createRulesFromDataRulesSuccess': $rootScope.$on('event:createRulesFromDataRulesSuccess', addRulesToList)
+
+ };
+
+ _.each(rootListeners, function(unbind){
+ $scope.$on('$destroy', rootListeners[unbind]);
+ });
+
+ function manageRules(){
+
+ rulesService.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ list.rules = data;
+ list.loadingRules = false;
+
+ refreshRules();
+
+ });
+ }
+
+ function newRulesTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10 // count per page
+
+ }, {
+
+ total: function () { return list.getRules().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getRules(), params.orderBy()) : list.getRules();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+ function getMetaRuleFromRule(rule) {
+
+ if(_.has(rule, 'meta_rule')){
+ return rule.meta_rule;
+ }
+
+ // if the call has not been made
+ if(!_.has(rule, 'callMetaRuleInProgress')){
+
+ rule.callMetaRuleInProgress = true;
+
+ metaRuleService.findOneWithCallback(rule.meta_rule_id, function(meta_rule){
+
+ rule.callMetaRuleInProgress = false;
+ rule.meta_rule = meta_rule;
+
+ });
+
+ }
+
+ // if the call is in progress return false
+ return false;
+ }
+
+
+ /**
+ * Prerequisite : meta Rule must be completely loader
+ * Depending on the meta_rule, the rule array will be filled by subject(s), object(s) or an action(s)
+ * the only way to know if rule[i] contains a subject/object/action is to check
+ * how many subject/object/action are associated to a MetaRule
+ * For example if the associated MetaRule contains 2 subjects, 1 object and 2 actions
+ * then the 2 first elements of rule array are 2 subject, the third one will be an object, and the 2 last will be action
+ * @param index
+ * @param rule
+ */
+ function getCategoryFromRuleIndex(index, rule){
+
+ if(!_.has(rule, 'rule_value')){
+ // setting an array which will contains every value of the category
+ rule.rule_value = Array.apply(null, new Array(rule.rule.length)).map(function(){
+ return {
+ category: {}
+ };
+ });
+ }
+
+ if(_.has(rule.rule_value[index], 'callCategoryInProgress') && !rule.rule_value[index].callCategoryInProgress ){
+ return rule.rule_value[index].category;
+ }
+
+ // if the call has not been made
+ if(!_.has(rule.rule_value[index], 'callCategoryInProgress')){
+
+ rule.rule_value[index].callCategoryInProgress = true;
+
+ var categoryId = 0;
+
+ if(list.isRuleIndexSubjectCategory(index, rule)){
+
+ categoryId = rule.meta_rule.subject_categories[index];
+
+ dataService.subject.data.findOne(list.policy.id, categoryId, rule.rule[index], function(category){
+
+ rule.rule_value[index].callCategoryInProgress = false;
+ rule.rule_value[index].category = category;
+
+ });
+
+ }else if(list.isRuleIndexObjectCategory(index, rule)){
+
+
+ categoryId = rule.meta_rule.object_categories[index - rule.meta_rule.subject_categories.length ];
+
+ dataService.object.data.findOne(list.policy.id, categoryId, rule.rule[index], function(category){
+
+ rule.rule_value[index].callCategoryInProgress = false;
+ rule.rule_value[index].category = category;
+
+ });
+
+
+ }else if(list.isRuleIndexActionCategory(index, rule)){
+
+ categoryId = rule.meta_rule.action_categories[index - rule.meta_rule.subject_categories.length - rule.meta_rule.object_categories.length ];
+
+ dataService.action.data.findOne(list.policy.id, categoryId, rule.rule[index], function(category){
+
+ rule.rule_value[index].callCategoryInProgress = false;
+ rule.rule_value[index].category = category;
+
+ });
+
+ }else{
+
+ rule.rule_value[index].callCategoryInProgress = false;
+ rule.rule_value[index].category = {
+ name : 'ERROR'
+ };
+ }
+
+ }
+
+ // if the call is in progress return false
+ return false;
+ }
+
+ function isRuleIndexSubjectCategory(index, rule){
+
+ var ind = index + 1;
+
+ return ind <= rule.meta_rule.subject_categories.length;
+
+ }
+
+ function isRuleIndexObjectCategory(index, rule){
+
+ var ind = index + 1;
+
+ return rule.meta_rule.subject_categories.length < ind && ind <= ( rule.meta_rule.object_categories.length + rule.meta_rule.subject_categories.length );
+
+ }
+
+ function isRuleIndexActionCategory(index, rule){
+
+ var ind = index + 1;
+
+ return ( rule.meta_rule.object_categories.length + rule.meta_rule.subject_categories.length ) < ind && ind <= ( rule.meta_rule.object_categories.length + rule.meta_rule.subject_categories.length + rule.meta_rule.action_categories.length);
+
+ }
+
+ function getRules() {
+ return (list.rules) ? list.rules : [];
+ }
+
+ function hasRules() {
+ return list.getRules().length > 0;
+ }
+
+ /**
+ * Refresh the table
+ */
+ function refreshRules(){
+ list.table.total(list.rules.length);
+ list.table.reload();
+ }
+
+ function addRulesToList(event, rules){
+ list.rules.push(rules);
+ refreshRules();
+ }
+
+ /**
+ * Delete
+ */
+ function deleteRules(rules){
+
+ rules.loader = true;
+
+ rulesService.delete(rules.id, list.policy.id, deleteRulesSuccess, deleteRulesError );
+
+ function deleteRulesSuccess(){
+
+ $translate('moon.policy.rules.edit.action.add.delete.success').then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeRulesFromList(rules);
+ refreshRules();
+
+ rules.loader = false;
+
+ }
+
+ function deleteRulesError(reason){
+
+ $translate('moon.policy.rules.edit.action.add.delete.success', {reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ rules.loader = false;
+
+ }
+
+ }
+
+ function removeRulesFromList(rules){
+ list.rules = _.without(list.rules, rules);
+ }
+ }
+
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html b/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html
new file mode 100755
index 00000000..f55c1d05
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html
@@ -0,0 +1,89 @@
+<div class="row">
+
+ <form class="form-horizontal" role="form" name="edit.form">
+
+ <div class="form-group">
+
+ <label for="id" class="col-sm-3 control-label" data-translate="moon.policy.edit.basic.form.id">Id</label>
+
+ <div class="col-sm-6">
+
+ <input name="id" id="id" disabled class="form-control" type="text" data-ng-model="edit.policyToEdit.id" required />
+
+ </div>
+
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': edit.form.name.$invalid && edit.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.policy.edit.basic.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="edit.policyToEdit.name" required />
+
+ <div class="help-block" ng-show="edit.form.name.$dirty && edit.form.name.$invalid">
+ <small class="error" ng-show="edit.form.name.$error.required" data-translate="moon.policy.edit.basic.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+
+ <div class="form-group" ng-class="{'has-error': edit.form.model.$dirty && (edit.form.model.$invalid || !edit.selectedModel)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.policy.edit.basic.form.model">Models</label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="edit.selectedModel" name="model" required>
+ <ui-select-match placeholder="(None)">{{$select.selected.name}}</ui-select-match>
+ <ui-select-choices repeat="model in edit.models">
+ <div ng-value="model">{{model.name}}</div>
+ </ui-select-choices>
+ </ui-select>
+
+ <moon-loader ng-if="edit.modelsLoading"></moon-loader>
+
+ <div class="help-block" ng-show="edit.form.model.$dirty && (edit.form.model.$invalid || !edit.selectedModel)">
+ <small class="error" ng-show="edit.form.model.$error.required" data-translate="moon.policy.edit.basic.check.model.required">Model is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.policy.edit.basic.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="edit.policyToEdit.description"></textarea>
+ </div>
+
+ </div>
+
+ <div class="form-group">
+
+ <div class="col-sm-2 col-sm-offset-3">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.init()" class="btn btn-default">
+ <span data-translate="moon.policy.edit.basic.action.init">Init</span>
+ </a>
+ </div>
+
+ <div class="col-sm-4 col-sm-offset-2">
+
+ <a href="" ng-disabled="edit.loading" ng-click="edit.editPolicy()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.policy.edit.basic.action.update">Update</span>
+ </a>
+
+ <moon-loader ng-if="edit.loading"></moon-loader>
+ </div>
+
+ </div>
+
+ </form>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/edit/policy-edit.tpl.html b/moon_gui/static/app/policy/edit/policy-edit.tpl.html
new file mode 100755
index 00000000..a1a6a54a
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/policy-edit.tpl.html
@@ -0,0 +1,202 @@
+<div class="container">
+
+ <div class="row">
+ <h3 class="pull-left" data-translate="moon.policy.edit.title" data-translate-values="{ policyName: edit.policy.name }">Edit</h3>
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.policy.edit.basic.title" >Basic Information</span>
+ <a href="" ng-click="edit.editBasic = !edit.editBasic">
+ <span data-translate="moon.policy.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>
+
+ </div>
+
+ <div class="panel-body">
+
+ <div ng-if="edit.editBasic">
+ <moon-policy-edit-basic policy="edit.policy"></moon-policy-edit-basic>
+ </div>
+
+ <div ng-if="!edit.editBasic">
+
+ <dl class="dl-horizontal">
+
+ <dt data-translate="moon.policy.edit.basic.form.id">Id</dt>
+ <dd ng-bind="edit.policy.id"></dd>
+
+ <dt data-translate="moon.policy.edit.basic.form.name">Name</dt>
+ <dd ng-bind="edit.policy.name"></dd>
+
+ <dt data-translate="moon.policy.edit.basic.form.genre">Genre</dt>
+ <dd ng-bind="edit.policy.genre"></dd>
+
+ <dt data-translate="moon.policy.edit.basic.form.model">Model</dt>
+ <dd>
+
+ <span ng-if="edit.loadingModel">
+ <moon-loader ng-if="edit.loadingModel"></moon-loader>
+ </span>
+ <span ng-if="!edit.loadingModel">
+ <span ng-bind="edit.policy.model.name" ></span>
+ </span>
+
+ </dd>
+
+ <dt data-translate="moon.policy.edit.basic.form.description">Description</dt>
+ <dd ng-bind="edit.policy.description"></dd>
+
+ </dl>
+
+ </div>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.policy.edit.perimeter.title" >Perimeters</span>
+
+ <a href="" ng-click="edit.showPerimeters = !edit.showPerimeters">
+
+ <span ng-if="!edit.showPerimeters">
+ <span data-translate="moon.policy.edit.show.open">Show</span>
+ <span class="glyphicon glyphicon-eye-open"></span>
+ </span>
+
+ <span ng-if="edit.showPerimeters">
+ <span data-translate="moon.policy.edit.show.close">Show</span>
+ <span class="glyphicon glyphicon-eye-close"></span>
+ </span>
+
+ </a>
+
+ <!--<a href="" ng-if="edit.showPerimeters">
+ <span data-translate="moon.policy.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>-->
+
+ </div>
+
+ <div class="panel-body" ng-if="edit.showPerimeters">
+
+ <moon-perimeter-list edit-mode="true" policy="edit.policy" ></moon-perimeter-list>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.policy.edit.data.title" >Data</span>
+
+ <a href="" ng-click="edit.showData = !edit.showData">
+
+ <span ng-if="!edit.showData">
+ <span data-translate="moon.policy.edit.show.open">Show</span>
+ <span class="glyphicon glyphicon-eye-open"></span>
+ </span>
+
+ <span ng-if="edit.showData">
+ <span data-translate="moon.policy.edit.show.close">Show</span>
+ <span class="glyphicon glyphicon-eye-close"></span>
+ </span>
+
+ </a>
+
+ <!--<a href="" ng-if="edit.showData">
+ <span data-translate="moon.policy.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>-->
+
+ </div>
+
+ <div class="panel-body" ng-if="edit.showData" > <!-- -->
+
+ <moon-data-list edit-mode="true" policy="edit.policy" ></moon-data-list>
+
+ </div>
+
+ </div>
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.policy.edit.rules.title" >Rules</span>
+
+ <a href="" ng-click="edit.showRules = !edit.showRules">
+
+ <span ng-if="!edit.showRules">
+ <span data-translate="moon.policy.edit.show.open">Show</span>
+ <span class="glyphicon glyphicon-eye-open"></span>
+ </span>
+
+ <span ng-if="edit.showRules">
+ <span data-showRules="moon.policy.edit.show.close">Close</span>
+ <span class="glyphicon glyphicon-eye-close"></span>
+ </span>
+
+ </a>
+
+ <!--<a href="" ng-if="edit.showRules">
+ <span data-translate="moon.policy.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>-->
+
+ </div>
+
+ <div class="panel-body" ng-if="edit.showRules">
+
+ <moon-rules-list edit-mode="true" policy="edit.policy" ></moon-rules-list>
+
+ </div>
+
+ </div>
+
+
+ <div class="panel panel-default">
+
+ <div class="panel-heading">
+
+ <span data-translate="moon.policy.edit.assignments.title" >Assignments</span>
+
+ <a href="" ng-click="edit.showAssignments = !edit.showAssignments">
+
+ <span ng-if="!edit.showAssignments">
+ <span data-translate="moon.policy.edit.show.open">Show</span>
+ <span class="glyphicon glyphicon-eye-open"></span>
+ </span>
+
+ <span ng-if="edit.showAssignments">
+ <span data-showRules="moon.policy.edit.show.close">Close</span>
+ <span class="glyphicon glyphicon-eye-close"></span>
+ </span>
+
+ </a>
+
+ <!--<a href="" ng-if="edit.showRules">
+ <span data-translate="moon.policy.edit.update">Update</span>
+ <span class="glyphicon glyphicon-cog"></span>
+ </a>-->
+
+ </div>
+
+ <div class="panel-body" ng-if="edit.showAssignments">
+
+ <moon-assignments-list edit-mode="true" policy="edit.policy" ></moon-assignments-list>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/policy/edit/policy.controller.edit.js b/moon_gui/static/app/policy/edit/policy.controller.edit.js
new file mode 100755
index 00000000..123ee58b
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/policy.controller.edit.js
@@ -0,0 +1,74 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyEditController', PolicyEditController);
+
+ PolicyEditController.$inject = ['$scope', '$rootScope', 'policy', 'modelService'];
+
+ function PolicyEditController($scope, $rootScope, policy, modelService) {
+
+ var edit = this;
+
+ edit.policy = policy;
+
+ edit.editBasic = false;
+
+ edit.showPerimeters = false;
+ edit.showData = false;
+ edit.showRules = false;
+ edit.showAssignments = false;
+
+
+ activate();
+
+ function activate(){
+
+ manageModel();
+
+ }
+
+ function manageModel(){
+
+ edit.loadingModel = true;
+
+ modelService.findOneWithCallback( edit.policy.model_id, function(model){
+
+ edit.loadingModel = false;
+ edit.policy.model = model;
+
+ });
+
+ }
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:policyUpdatedSuccess': $rootScope.$on('event:policyUpdatedSuccess', policyUpdatedSuccess)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ /**
+ * When the model is updated, this function refresh the current model with the new changes
+ * @param event
+ * @param policy
+ */
+ function policyUpdatedSuccess(event, policy){
+
+ edit.policy = policy;
+
+ manageModel();
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js b/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js
new file mode 100755
index 00000000..c32d9e69
--- /dev/null
+++ b/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js
@@ -0,0 +1,134 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonPolicyEditBasic', moonPolicyEditBasic);
+
+ moonPolicyEditBasic.$inject = [];
+
+ function moonPolicyEditBasic() {
+
+ return {
+ templateUrl : 'html/policy/edit/policy-edit-basic.tpl.html',
+ bindToController : true,
+ controller : moonPolicyEditBasicController,
+ controllerAs : 'edit',
+ scope : {
+ policy : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonPolicyEditBasicController', moonPolicyEditBasicController);
+
+ moonPolicyEditBasicController.$inject = ['$scope', 'policyService', 'formService', 'alertService', '$translate', 'utilService', 'modelService'];
+
+ function moonPolicyEditBasicController($scope, policyService, formService, alertService, $translate, utilService, modelService){
+
+ var edit = this;
+
+ edit.editPolicy = editPolicy;
+ edit.init = init;
+
+ edit.form = {};
+ edit.modelsLoading = true;
+
+
+ activate();
+
+ function activate(){
+
+ edit.policy = $scope.edit.policy;
+
+ edit.policyToEdit = angular.copy(edit.policy);
+
+ console.log(edit.policyToEdit);
+
+ resolveModels();
+
+ }
+
+ /*
+ *
+ */
+
+ function resolveModels() {
+
+ modelService.findAllWithCallBack(resolveModelsCallback);
+
+ }
+
+ function resolveModelsCallback(models) {
+
+ edit.models = models;
+
+ _.each(models, function(model){
+
+ if(model.id === edit.policy.model_id){
+ edit.selectedModel = model;
+ }
+
+ });
+
+ edit.modelsLoading = false;
+
+ }
+
+
+ function editPolicy(){
+
+ if(formService.isInvalid(edit.form)) {
+
+ formService.checkFieldsValidity(edit.form);
+
+ }else{
+
+ edit.loading = true;
+
+ delete edit.policyToEdit.model;
+
+ edit.policyToEdit.model_id = edit.selectedModel.id;
+
+ policyService.update(edit.policyToEdit, updateSuccess, updateError);
+
+ }
+
+ function updateSuccess(data) {
+
+ var updatedPolicy = utilService.transformOne(data, 'policies');
+
+ $translate('moon.policy.edit.basic.success', { policyName: updatedPolicy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ edit.loading = false;
+
+ $scope.$emit('event:policyUpdatedSuccess', updatedPolicy);
+
+ }
+
+ function updateError(reason) {
+
+ $translate('moon.policy.edit.basic.error', { policyName: edit.policy.name }).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ edit.loading = false;
+
+ }
+ }
+
+ function init(){
+
+ edit.policyToEdit = angular.copy(edit.policy);
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/policy-list.tpl.html b/moon_gui/static/app/policy/policy-list.tpl.html
new file mode 100755
index 00000000..aeb90f0b
--- /dev/null
+++ b/moon_gui/static/app/policy/policy-list.tpl.html
@@ -0,0 +1,131 @@
+<div class="container">
+
+ <div>
+ <form class="form-inline pull-right">
+ <div class="form-group">
+ <div>
+ <input id="searcPolicy" data-ng-model="list.search.query" type="text" class="form-control" placeholder="{{'moon.policy.list.search.placeholder' | translate}}" />
+ </div>
+ </div>
+ <div class="form-group">
+ <div>
+ <button type="submit" class="btn btn-danger" data-ng-click="list.search.reset()" data-translate="moon.policy.list.search.reset">Reset</button>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+
+
+ <div class="row" >
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <colgroup>
+ <col class="col-md-4" />
+ <col class="col-md-2" />
+ <col class="col-md-2" />
+ <col class="col-md-1" />
+ </colgroup>
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('genre', 'asc'), 'sort-desc': list.table.isSortBy('genre', 'desc') }"
+ ng-click="list.table.sorting('genre', list.table.isSortBy('genre', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.genre">Genre</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.description">Description</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.policy.list.action.title">Actions</div>
+ </th>
+
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasPolicies()">
+ <tr>
+ <td colspan="12"><span data-translate="moon.policy.list.table.notFound">There is no policy</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasPolicies()">
+
+ <tr ng-repeat="policy in $data | filter:list.search.find | orderBy:sort:reverse">
+
+ <td ng-bind="policy.name"></td>
+
+ <td ng-bind="policy.genre"></td>
+
+ <td ng-bind="policy.description"></td>
+
+ <td>
+ <div class="dropdown">
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.list.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+
+ <li>
+ <a href="" ui-sref="moon.policy.edit({id: policy.id})">
+ <span class="glyphicon glyphicon-cog"></span>
+ <span class="control-label" data-translate="moon.policy.list.action.edit">Edit</span>
+ </a>
+ </li>
+
+ <li class="divider"></li>
+
+ <li>
+ <a href="" ng-click="list.del.showModal(policy)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.policy.list.action.delete">Delete</span>
+ </a>
+ </li>
+
+ </ul>
+ </div>
+ </td>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ <div class="container">
+
+ <div class="form-inline form-group">
+ <a href="" ng-click="list.add.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-plus-sign"></span>
+ <span data-translate="moon.policy.list.action.add">Add Model</span>
+ </a>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/policy-mapped-list.tpl.html b/moon_gui/static/app/policy/policy-mapped-list.tpl.html
new file mode 100755
index 00000000..127dae3b
--- /dev/null
+++ b/moon_gui/static/app/policy/policy-mapped-list.tpl.html
@@ -0,0 +1,88 @@
+<div class="container">
+
+ <div class="row" ng-if="list.loadingPolicies">
+ <moon-loader ng-if="list.loadingPolicies"></moon-loader>
+ </div>
+
+ <div class="row" ng-if="!list.loadingPolicies" >
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <colgroup>
+ <col class="col-md-4" />
+ <col class="col-md-2" />
+ <col class="col-md-2" />
+ <col class="col-md-1" />
+ </colgroup>
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('genre', 'asc'), 'sort-desc': list.table.isSortBy('genre', 'desc') }"
+ ng-click="list.table.sorting('genre', list.table.isSortBy('genre', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.genre">Genre</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.policy.list.table.description">Description</div>
+ </th>
+
+ <th class="customTables sortable">
+ <div data-translate="moon.policy.list.action.title">Actions</div>
+ </th>
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasPolicies()">
+ <tr>
+ <td colspan="12"><span data-translate="moon.policy.list.table.notFound">There is no policy</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasPolicies()">
+
+ <tr ng-repeat="policy in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td ng-bind="policy.name"></td>
+ <td ng-bind="policy.genre"></td>
+ <td ng-bind="policy.description"></td>
+ <td>
+ <a href="" ng-click="list.unmap.showModal(policy)">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <em data-translate="moon.policy.list.action.unmap">Unmap</em>
+ </a>
+ </td>
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ <div class="container">
+
+ <div class="form-inline form-group">
+ <a href="" ng-click="list.map.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-link"></span>
+ <em data-translate="moon.policy.list.action.map">Map a Policy to PDP</em>
+ </a>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/policy/policy.controller.list.js b/moon_gui/static/app/policy/policy.controller.list.js
new file mode 100755
index 00000000..fc2c6503
--- /dev/null
+++ b/moon_gui/static/app/policy/policy.controller.list.js
@@ -0,0 +1,175 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('PolicyListController', PolicyListController);
+
+ PolicyListController.$inject = ['$scope', 'policies', 'NgTableParams', '$filter', '$modal', '$rootScope'];
+
+ function PolicyListController($scope, policies, NgTableParams, $filter, $modal, $rootScope) {
+
+ var list = this;
+
+ list.policies = policies;
+
+ list.getPolicies = getPolicies;
+ list.hasPolicies = hasPolicies;
+ list.addPolicy = addPolicy;
+ list.refreshPolicies = refreshPolicies;
+ list.deletePolicy = deletePolicy;
+
+ list.table = {};
+
+ list.search = { query: '',
+ find: searchPolicy,
+ reset: searchReset };
+
+ list.add = { modal: $modal({ template: 'html/policy/action/policy-add.tpl.html', show: false }),
+ showModal: showAddModal };
+
+ list.del = { modal: $modal({ template: 'html/policy/action/policy-delete.tpl.html', show: false }),
+ showModal: showDeleteModal };
+
+ activate();
+
+ function activate(){
+
+ newPoliciesTable();
+
+ }
+
+
+ /*
+ * ---- events
+ */
+
+ var rootListeners = {
+
+ 'event:policyCreatedSuccess': $rootScope.$on('event:policyCreatedSuccess', policyCreatedSuccess),
+ 'event:policyCreatedError': $rootScope.$on('event:policyCreatedError', policyCreatedError),
+
+ 'event:policyDeletedSuccess': $rootScope.$on('event:policyDeletedSuccess', policyDeletedSuccess),
+ 'event:policyDeletedError': $rootScope.$on('event:policyDeletedError', policyDeletedError)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ function getPolicies() {
+ return (list.policies) ? list.policies : [];
+ }
+
+ function hasPolicies() {
+ return list.getPolicies().length > 0;
+ }
+
+ function newPoliciesTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ name: 'asc',
+ genre: 'asc'
+ }
+
+ }, {
+
+ total: function () { return list.getPolicies().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getPolicies(), params.orderBy()) : list.getPolicies();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+
+ /*
+ * ---- search
+ */
+
+ function searchPolicy(policy){
+ return (policy.name.indexOf(list.search.query) !== -1 || policy.genre.indexOf(list.search.query) !== -1 || policy.description.indexOf(list.search.query) !== -1);
+ }
+
+ function searchReset() {
+ list.search.query = '';
+ }
+
+ /*
+ * ---- add
+ */
+ function showAddModal() {
+ list.add.modal.$promise.then(list.add.modal.show);
+ }
+
+ function policyCreatedSuccess(event, pdp) {
+
+ list.addPolicy(pdp);
+ list.refreshPolicies();
+
+ list.add.modal.hide();
+
+ }
+
+ function policyCreatedError(event, pdp) {
+ list.add.modal.hide();
+ }
+
+ function addPolicy(policy) {
+ list.policies.push(policy);
+ }
+
+ function refreshPolicies() {
+
+ list.table.total(list.policies.length);
+ list.table.reload();
+
+ }
+
+ /*
+ * ---- delete
+ */
+
+ function showDeleteModal(policy) {
+
+ list.del.modal.$scope.policy = policy;
+ list.del.modal.$promise.then(list.del.modal.show);
+
+ }
+
+ function deletePolicy(policy) {
+
+ list.policies = _.chain(list.policies).reject({id: policy.id}).value();
+
+ }
+
+ function policyDeletedSuccess(event, policy) {
+
+ list.deletePolicy(policy);
+ list.refreshPolicies();
+
+ list.del.modal.hide();
+
+ }
+
+ function policyDeletedError(event, policy) {
+ list.del.modal.hide();
+ }
+
+
+ }
+
+})();
diff --git a/moon_gui/static/app/policy/policy.mapped.list.dir.js b/moon_gui/static/app/policy/policy.mapped.list.dir.js
new file mode 100755
index 00000000..78bb3b8d
--- /dev/null
+++ b/moon_gui/static/app/policy/policy.mapped.list.dir.js
@@ -0,0 +1,202 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .directive('moonPolicyMappedList', moonPolicyMappedList);
+
+ moonPolicyMappedList.$inject = [];
+
+ function moonPolicyMappedList() {
+
+ return {
+ templateUrl : 'html/policy/policy-mapped-list.tpl.html',
+ bindToController : true,
+ controller : moonPolicyMappedListController,
+ controllerAs : 'list',
+ scope : {
+ pdp : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonPolicyMappedListController', moonPolicyMappedListController);
+
+ moonPolicyMappedListController.$inject = ['$scope', '$rootScope', 'NgTableParams', '$modal', '$filter', 'policyService'];
+
+ function moonPolicyMappedListController($scope, $rootScope, NgTableParams, $modal, $filter, policyService){
+
+ var list = this;
+
+ list.table = {};
+
+
+ list.pdp = $scope.list.pdp;
+
+ list.getPolicies = getPolicies;
+ list.hasPolicies = hasPolicies;
+ list.refreshPolicies = refreshPolicies;
+
+ list.loadingPolicies = true;
+
+ list.policies = [];
+
+
+ activate();
+
+ function activate() {
+
+ loadPolicices(false);
+
+ }
+
+ /**
+ *
+ * @param refresh boolean, if !refresh then newPolicYtable will be called, if refresh, then refreshPolicies is called
+ */
+ function loadPolicices(refresh){
+
+ if(_.isUndefined( list.pdp.security_pipeline)){
+ return;
+ }
+ list.policiesId = list.pdp.security_pipeline;
+
+ policyService.findSomeWithCallback(list.policiesId, function(policies){
+
+ list.policies = policies;
+
+ list.loadingPolicies = false;
+
+ if(refresh){
+
+ refreshPolicies();
+
+ }else{
+
+ newMPolicyTable();
+
+ }
+
+ });
+
+ }
+
+ list.map = { modal: $modal({ template: 'html/policy/action/mapping/policy-map.tpl.html', show: false }),
+ showModal: showMapModal };
+
+ list.unmap = { modal: $modal({ template: 'html/policy/action/mapping/policy-unmap.tpl.html', show: false }),
+ showModal: showUnmapModal };
+
+ /*
+ * ---- events
+ */
+ var rootListeners = {
+
+ 'event:policyMapToPdpSuccess': $rootScope.$on('event:policyMapToPdpSuccess', policyMapToPdpSuccess),
+ 'event:policyMapToPdpError': $rootScope.$on('event:policyMapToPdpError', policyMapToPdpError),
+
+ 'event:policyUnMappedToPdpSuccess': $rootScope.$on('event:policyUnMappedToPdpSuccess', policyUnmappedSuccess),
+ 'event:policyUnMappedToPdpError': $rootScope.$on('event:policyUnMappedToPdpError', policyUnmappedError)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+
+ function newMPolicyTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10 // count per page
+
+ }, {
+
+ total: function () { return list.getPolicies().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getPolicies(), params.orderBy()) : list.getPolicies();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+
+ function getPolicies() {
+ return (list.policies) ? list.policies : [];
+ }
+
+ function hasPolicies() {
+ return list.getPolicies().length > 0;
+ }
+
+ function refreshPolicies(){
+
+ list.table.total(list.getPolicies().length);
+ list.table.reload();
+
+ }
+
+ function showMapModal(){
+ list.map.modal.$scope.pdp = list.pdp;
+ list.map.modal.$promise.then(list.map.modal.show);
+ }
+
+ function showUnmapModal(policy){
+
+ list.unmap.modal.$scope.pdp = list.pdp;
+ list.unmap.modal.$scope.policy = policy;
+
+ list.unmap.modal.$promise.then(list.unmap.modal.show);
+
+ }
+
+ function policyMapToPdpSuccess(event, pdp){
+
+ list.pdp = pdp;
+
+ loadPolicices(true);
+
+ list.map.modal.hide();
+
+ }
+
+
+ function policyMapToPdpError(event) {
+
+ list.map.modal.hide();
+
+ }
+
+ function policyUnmappedSuccess(event, pdp) {
+
+ list.pdp = pdp;
+
+ loadPolicices(true);
+
+ list.unmap.modal.hide();
+
+ }
+
+ function policyUnmappedError(event) {
+ list.unmap.modal.hide();
+ }
+
+
+ }
+
+})();
diff --git a/moon_gui/static/app/project/action/mapping/project-map.tpl.html b/moon_gui/static/app/project/action/mapping/project-map.tpl.html
new file mode 100755
index 00000000..5ffd98e2
--- /dev/null
+++ b/moon_gui/static/app/project/action/mapping/project-map.tpl.html
@@ -0,0 +1,62 @@
+<div ng-controller="ProjectMapController as map" class="modal" tabindex="-1" data-role="modalMappingProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.project.map.title" data-translate-values="{projectName: map.project.name}"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="map.form">
+
+ <div class="form-group" ng-class="{'has-error': map.form.pdp.$dirty && (map.form.pdp.$invalid || !map.selectedPDP)}">
+
+ <label class="col-sm-3 control-label" data-translate="moon.project.map.form.pdp">PDP</label>
+
+ <div class="col-sm-6">
+
+ <ui-select ng-model="map.selectedPDP" name="pdp" required>
+ <ui-select-match placeholder="(None)" ng-bind="$select.selected.name"></ui-select-match>
+ <ui-select-choices repeat="pdp in map.pdps">
+ <div ng-bind="pdp.name" ng-value="pdp"></div>
+ </ui-select-choices>
+ </ui-select>
+
+ <img ng-if="map.pdpsLoading" src="assets/img/ajax-loader.gif" />
+
+ <div class="help-block" ng-show="map.form.pdp.$dirty && (map.form.pdp.$invalid || !map.selectedPDP)">
+ <small class="error" ng-show="map.form.pdp.$error.required" data-translate="moon.project.map.check.pdp.required">PDP is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.project.map.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="map.mappingLoading" ng-click="map.map()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-link"></span>
+ <span data-translate="moon.project.map.action.map">Map</span>
+ </a>
+
+ <img ng-if="map.mappingLoading" src="assets/img/ajax-loader.gif" />
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html b/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html
new file mode 100755
index 00000000..5cc5c6dd
--- /dev/null
+++ b/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html
@@ -0,0 +1,33 @@
+<div ng-controller="ProjectUnMapController as unmap" class="modal" tabindex="-1" data-role="modalUnmapProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.project.unmap.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <span data-translate="moon.project.unmap.content" data-translate-values="{ projectName: unmap.project.name, pdpName: unmap.project.mapping.authz.pdp.name }"></span>
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.project.unmap.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="unmap.unMappingLoading" ng-click="unmap.unmap()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-transfer"></span>
+ <span data-translate="moon.project.unmap.action.unmap">Unmap</span>
+ </a>
+ <img ng-if="unmap.unMappingLoading" src="assets/img/ajax-loader.gif" />
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/project/action/mapping/project.controller.map.js b/moon_gui/static/app/project/action/mapping/project.controller.map.js
new file mode 100755
index 00000000..afa2bfc0
--- /dev/null
+++ b/moon_gui/static/app/project/action/mapping/project.controller.map.js
@@ -0,0 +1,107 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectMapController', ProjectMapController);
+
+ ProjectMapController.$inject = ['$scope', '$translate', 'alertService', 'formService', 'pdpService'];
+
+ function ProjectMapController($scope, $translate, alertService, formService, pdpService) {
+
+ var map = this;
+
+ /*
+ *
+ */
+
+ map.form = {};
+
+ map.project = $scope.project;
+
+ map.pdps = [];
+
+ map.pdpsLoading = true;
+
+ map.selectedPDP = null;
+
+ map.map = mapProject;
+
+ activate();
+
+ function activate(){
+
+ resolvePDPs();
+
+ }
+
+ /*
+ *
+ */
+
+ function resolvePDPs() {
+
+ pdpService.findAllWithCallBack(resolveMappedProjects);
+
+ }
+
+ function resolveMappedProjects(pdps) {
+
+ map.pdps = _.filter(pdps, function(pdp){
+ return _.isNull(pdp.keystone_project_id);
+ });
+
+ map.pdpsLoading = false;
+
+ }
+
+ function mapProject() {
+
+ if(formService.isInvalid(map.form)) {
+
+ formService.checkFieldsValidity(map.form);
+
+ } else {
+
+ map.mappingLoading = true;
+
+ pdpService.map( map.selectedPDP, map.project.id, mapSuccess, mapError);
+
+ }
+
+ function mapSuccess(data) {
+
+ map.project.pdp = map.selectedPDP;
+
+ $translate('moon.project.map.success', { projectName: map.project.name, pdpName: map.selectedPDP.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ map.mappingLoading = false;
+
+ $scope.$emit('event:projectMappedSuccess', map.project);
+
+ }
+
+ function mapError(response) {
+
+ $translate('moon.project.map.error', { projectName: map.project.name, pdpName: map.selectedPDP.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ map.mappingLoading = false;
+
+ $scope.$emit('event:projectMappedError', map.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/project/action/mapping/project.controller.unmap.js b/moon_gui/static/app/project/action/mapping/project.controller.unmap.js
new file mode 100755
index 00000000..911b30ff
--- /dev/null
+++ b/moon_gui/static/app/project/action/mapping/project.controller.unmap.js
@@ -0,0 +1,74 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectUnMapController', ProjectUnMapController);
+
+ ProjectUnMapController.$inject = ['$scope', '$translate', 'alertService', 'pdpService'];
+
+ function ProjectUnMapController($scope, $translate, alertService, pdpService) {
+
+ var unmap = this;
+
+ /*
+ *
+ */
+
+ unmap.project = $scope.project;
+ unmap.unMappingLoading = false;
+
+ unmap.unmap = unMapProject;
+
+ /*
+ *
+ */
+
+ function unMapProject() {
+
+
+ unmap.unMappingLoading = true;
+
+ var pdpName = unmap.project.pdp.name;
+
+ pdpService.unMap(unmap.project.pdp, unMapSuccess, unMapError);
+
+ function unMapSuccess(data) {
+
+ $translate('moon.project.unmap.success', { projectName: unmap.project.name, pdpName: pdpName })
+ .then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ delete unmap.project.mapping;
+ delete unmap.project.pdp;
+
+ $scope.$emit('event:projectUnmappedSuccess', unmap.project);
+
+ }
+
+ function unMapError(reason) {
+
+ $translate('moon.project.unmap.error', { projectName: unmap.project.name, pdpName: pdpName })
+ .then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ unmap.unMappingLoading = false;
+
+ $scope.$emit('event:projectUnmappedError', unmap.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/project/action/project-add.tpl.html b/moon_gui/static/app/project/action/project-add.tpl.html
new file mode 100755
index 00000000..a90dcfa1
--- /dev/null
+++ b/moon_gui/static/app/project/action/project-add.tpl.html
@@ -0,0 +1,89 @@
+<div ng-controller="ProjectAddController as add" class="modal" tabindex="-1" data-role="modalAddProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.project.add.title"></h4>
+ </div>
+
+ <div class="modal-body">
+
+ <form class="form-horizontal" role="form" name="add.form">
+
+ <div class="form-group" ng-class="{'has-error': add.form.name.$invalid && add.form.name.$dirty}">
+
+ <label for="name" class="col-sm-3 control-label" data-translate="moon.project.add.form.name">Name</label>
+
+ <div class="col-sm-6">
+
+ <input name="name" id="name" class="form-control" type="text" data-ng-model="add.project.project.name" required />
+
+ <div class="help-block" ng-show="add.form.name.$dirty && add.form.name.$invalid">
+ <small class="error" ng-show="add.form.name.$error.required" data-translate="moon.project.add.check.name.required">Name is required</small>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="description" class="col-sm-3 control-label" data-translate="moon.project.add.form.description">Description</label>
+ <div class="col-sm-6">
+ <textarea id="description" name="description" class="form-control" data-ng-model="add.project.project.description"></textarea>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="enabled" class="col-sm-3 control-label" data-translate="moon.project.add.form.enabled">Enabled</label>
+ <div class="col-sm-6">
+ <div class="radio">
+ <input type="checkbox" id="enabled" name="enabled" class="js-switch" data-ng-model="add.project.project.enabled" ui-switch />
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': add.form.domain.$invalid && add.form.domain.$dirty}">
+
+ <label for="domain" class="col-sm-3 control-label" data-translate="moon.project.add.form.domain">Domain</label>
+
+ <div class="col-sm-6">
+
+ <input name="domain" id="domain" type="text" class="form-control" data-ng-model="add.project.project.domain" required />
+
+ <div class="help-block" ng-show="add.form.domain.$dirty && add.form.domain.$invalid">
+ <small class="error" ng-show="add.form.domain.$error.required" data-translate="moon.project.add.check.domain.required">Domain is required</small>
+ </div>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+
+ <div class="modal-footer">
+
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.project.add.action.cancel">Cancel</span>
+ </a>
+
+ <a href="" ng-disabled="add.loading" ng-click="add.create()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-save"></span>
+ <span data-translate="moon.project.add.action.create">Create</span>
+ </a>
+ <img ng-if="add.loading" src="assets/img/ajax-loader.gif" />
+
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/project/action/project-delete.tpl.html b/moon_gui/static/app/project/action/project-delete.tpl.html
new file mode 100755
index 00000000..96b4f2e3
--- /dev/null
+++ b/moon_gui/static/app/project/action/project-delete.tpl.html
@@ -0,0 +1,45 @@
+<div ng-controller="ProjectDeleteController as del" class="modal" tabindex="-1" data-role="modalDeleteProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.project.remove.title"></h4>
+ </div>
+
+ <div class="modal-body">
+ <p><span data-translate="moon.project.remove.content.query" data-translate-values="{ projectName: del.project.name }"></span></p>
+
+ <p ng-if="del.loadingPDP"><img src="assets/img/ajax-loader.gif" /></p>
+
+ <div ng-if="!del.loadingPDP">
+ <p ng-if="!del.isProjectMapped()"><span data-translate="moon.project.remove.content.isNotMapped">This Project is not map with any PDP</span></p>
+ <p ng-if="del.isProjectMapped()">
+ <span data-translate="moon.project.remove.content.isMapped" data-translate-values="{ pdpName: del.project.pdp.name }"></span>
+ </p>
+ </div>
+
+ </div>
+
+ <div class="modal-footer">
+ <div class="btn-toolbar" style="float: right;">
+
+ <a href="" ng-click="$hide()" class="btn btn-default">
+ <span data-translate="moon.project.remove.action.cancel">Cancel</span>
+ </a>
+ <a href="" ng-disabled="del.loading || del.loadingPDP" ng-click="del.remove()" class="btn btn-warning">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span data-translate="moon.project.remove.action.delete">Delete</span>
+ </a>
+ <img ng-if="del.loading" src="assets/img/ajax-loader.gif" />
+
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/project/action/project-view.tpl.html b/moon_gui/static/app/project/action/project-view.tpl.html
new file mode 100755
index 00000000..3228c915
--- /dev/null
+++ b/moon_gui/static/app/project/action/project-view.tpl.html
@@ -0,0 +1,194 @@
+<div ng-controller="ProjectViewController as view" class="modal" tabindex="-1" data-role="modalViewProject">
+
+ <div class="modal-dialog">
+
+ <div class="modal-content">
+
+ <div class="modal-header">
+ <button type="button" class="close" ng-click="$hide()">&times;</button>
+ <h4 class="modal-title" data-translate="moon.project.view.title" data-translate-values="{projectName: view.project.name}"></h4>
+ </div>
+ <div class="modal-body">
+ <dl class="dl-horizontal">
+ <dt>Id</dt>
+ <dd ng-bind="view.project.id"></dd>
+ <dt>Name</dt>
+ <dd ng-bind="view.project.name"></dd>
+ <dt>Is_domain</dt>
+ <dd ng-bind="view.project.is_domain"></dd>
+ <dt>Link</dt>
+ <dd ng-bind="view.project.links.self"></dd>
+ <dt>enabled</dt>
+ <dd ng-bind="view.project.enabled"></dd>
+ <dt>Parent id</dt>
+ <dd ng-bind="view.project.parent_id"></dd>
+ <dt>Domain id</dt>
+ <dd ng-bind="view.project.domain_id"></dd>
+ <dt>Description</dt>
+ <dd ng-bind="view.project.description"></dd>
+ </dl>
+ </div>
+
+ <!--<div class="modal-body">-->
+ <!---->
+ <!--&lt;!&ndash; objects &ndash;&gt;-->
+ <!---->
+ <!--<div class="row">-->
+ <!--<div class="col-md-12">-->
+ <!--<h1 class="pull-left" data-translate="moon.project.view.object.title">Objects</h1>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row top05">-->
+ <!--<div class="col-md-3"><label data-translate="moon.project.view.object.name">Name</label></div>-->
+ <!--<div class="col-md-7"><label data-translate="moon.project.view.object.description">Description</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.object.enabled">Enabled</label></div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="view.objectsLoading">-->
+ <!--<div class="col-md-12"><img src="assets/img/ajax-loader.gif" /> <em data-translate="moon.project.view.object.loading">Loading Objects</em></div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.objectsLoading && !view.hasObjects()">-->
+ <!--<div class="col-md-12" data-translate="moon.project.view.object.notFound">Objects not found</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.objectsLoading && view.hasObjects()" ng-repeat="object in view.objects">-->
+ <!--<div class="col-md-3">{{object.name}}</div> -->
+ <!--<div class="col-md-7">{{object.description}}</div>-->
+ <!--<div class="col-md-2">-->
+ <!--<span ng-if="object.enabled" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--&lt;!&ndash; subjects &ndash;&gt;-->
+ <!---->
+ <!--<div class="row top10">-->
+ <!--<div class="col-md-12">-->
+ <!--<h1 class="pull-left" data-translate="moon.project.view.subject.title">Subjects</h1>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row top05">-->
+ <!--<div class="col-md-3"><label data-translate="moon.project.view.subject.name">Name</label></div>-->
+ <!--<div class="col-md-3"><label data-translate="moon.project.view.subject.domain">Domain</label></div>-->
+ <!--<div class="col-md-4"><label data-translate="moon.project.view.subject.mail">Mail</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.subject.enabled">Enabled</label></div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row">-->
+ <!--<div class="col-md-3">-->
+ <!--<ui-select ng-model="view.selectedSubject" on-select="view.resolveRoles($item); view.resolveGroups($item)">-->
+ <!--<ui-select-match placeholder="(None)">{{$select.selected.name}}</ui-select-match>-->
+ <!--<ui-select-choices repeat="subject in view.subjects">-->
+ <!--<div ng-value="subject">{{subject.name}}</div>-->
+ <!--</ui-select-choices>-->
+ <!--</ui-select>-->
+ <!--<img ng-if="view.subjectsLoading" src="assets/img/ajax-loader.gif" />-->
+ <!--</div> -->
+ <!--<div class="col-md-3">{{view.selectedSubject.domain}}</div>-->
+ <!--<div class="col-md-4">{{view.selectedSubject.mail}}</div>-->
+ <!--<div class="col-md-2">-->
+ <!--<div ng-if="view.selectedSubject != null">-->
+ <!--<span ng-if="view.selectedSubject.enabled" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--&lt;!&ndash; roles &ndash;&gt;-->
+ <!---->
+ <!--<div ng-if="view.hasSelectedSubject()">-->
+ <!---->
+ <!--<div class="row top10">-->
+ <!--<div class="col-md-12">-->
+ <!--<h1 class="pull-left" data-translate="moon.project.view.role.title">Roles</h1>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row top05">-->
+ <!---->
+ <!--<div class="col-md-3"><label data-translate="moon.project.view.role.value">Value</label></div>-->
+ <!--<div class="col-md-5"><label data-translate="moon.project.view.role.description">Description</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.role.assigned">Assigned</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.role.enabled">Enabled</label></div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="view.rolesLoading">-->
+ <!--<div class="col-md-12"><img src="assets/img/ajax-loader.gif" /> <em data-translate="moon.project.view.role.loading">Loading Roles</em></div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.rolesLoading && !view.hasRoles()">-->
+ <!--<div class="col-md-12" data-translate="moon.project.view.role.notFound">Roles not found</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.rolesLoading && view.hasRoles()" ng-repeat="role in view.roles">-->
+ <!---->
+ <!--<div class="col-md-3" ng-bind="role.value"></div>-->
+ <!--<div class="col-md-5" ng-bind="role.description"></div>-->
+ <!--<div class="col-md-2">-->
+ <!--<span ng-if="view.isRoleAssigned(role)" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!--<div class="col-md-2">-->
+ <!--<span ng-if="role.enabled" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--&lt;!&ndash; groups &ndash;&gt;-->
+ <!---->
+ <!--<div ng-if="view.hasSelectedSubject()">-->
+ <!---->
+ <!--<div class="row top10">-->
+ <!--<div class="col-md-12">-->
+ <!--<h1 class="pull-left" data-translate="moon.project.view.group.title">Groups</h1>-->
+ <!--</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row top05">-->
+ <!---->
+ <!--<div class="col-md-3"><label data-translate="moon.project.view.group.value">Value</label></div>-->
+ <!--<div class="col-md-5"><label data-translate="moon.project.view.group.description">Description</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.group.assigned">Assigned</label></div>-->
+ <!--<div class="col-md-2"><label data-translate="moon.project.view.group.enabled">Enabled</label></div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="view.groupsLoading">-->
+ <!--<div class="col-md-12"><img src="assets/img/ajax-loader.gif" /> <em data-translate="moon.project.view.group.loading">Loading Groups</em></div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.groupsLoading && !view.hasGroups()">-->
+ <!--<div class="col-md-12" data-translate="moon.project.view.group.notFound">Groups not found</div>-->
+ <!--</div>-->
+ <!---->
+ <!--<div class="row" ng-if="!view.groupsLoading && view.hasGroups()" ng-repeat="group in view.groups">-->
+ <!---->
+ <!--<div class="col-md-3">{{group.value}}</div>-->
+ <!--<div class="col-md-5">{{group.description}}</div>-->
+ <!--<div class="col-md-2">-->
+ <!--<span ng-if="view.isGroupAssigned(group)" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!--<div class="col-md-2">-->
+ <!--<span ng-if="group.enabled" class="glyphicon glyphicon-ok"></span>-->
+ <!--</div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <!--</div>-->
+ <!---->
+ <div class="modal-footer top10">
+ <div class="btn-toolbar" style="float: right;">
+ <button ng-click="$hide()" class="btn btn-default" data-translate="moon.project.view.action.close">Close</button>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moon_gui/static/app/project/action/project.controller.add.js b/moon_gui/static/app/project/action/project.controller.add.js
new file mode 100755
index 00000000..4d12b75d
--- /dev/null
+++ b/moon_gui/static/app/project/action/project.controller.add.js
@@ -0,0 +1,78 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectAddController', ProjectAddController);
+
+ ProjectAddController.$inject = ['$scope', '$translate', 'alertService', 'formService', 'projectService', 'DEFAULT_CST'];
+
+ function ProjectAddController($scope, $translate, alertService, formService, projectService, DEFAULT_CST) {
+
+ var add = this;
+
+ /*
+ *
+ */
+
+ add.form = {};
+
+ add.loading = false;
+
+ //@todo: verify if enable argument is understood serrver-side
+ add.project = { project: {name: null, description: null, enabled: true, domain: DEFAULT_CST.DOMAIN.DEFAULT} };
+ add.create= createProject;
+
+ /*
+ * ---- create
+ */
+
+ function createProject() {
+
+ if(formService.isInvalid(add.form)) {
+
+ formService.checkFieldsValidity(add.form);
+
+ } else {
+
+ add.loading = true;
+
+ projectService.data.projects.create({}, add.project, createSuccess, createError);
+
+ }
+
+ function createSuccess(data) {
+
+ var created = data.project;
+ $translate('moon.project.add.success', { projectName: created.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:projectCreatedSuccess', created);
+
+ }
+
+ function createError(reason) {
+
+ $translate('moon.project.add.error', { projectName: add.project.project.name }).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ add.loading = false;
+
+ $scope.$emit('event:projectCreatedError', add.project);
+
+ }
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/project/action/project.controller.delete.js b/moon_gui/static/app/project/action/project.controller.delete.js
new file mode 100755
index 00000000..4f18f8e6
--- /dev/null
+++ b/moon_gui/static/app/project/action/project.controller.delete.js
@@ -0,0 +1,134 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectDeleteController', ProjectDeleteController);
+
+ ProjectDeleteController.$inject = ['$scope', '$translate', 'alertService', 'projectService', 'pdpService'];
+
+ function ProjectDeleteController($scope, $translate, alertService, projectService, pdpService) {
+
+ var del = this;
+
+ /*
+ *
+ */
+
+ del.project = $scope.project;
+ del.loading = false;
+ del.loadingPDP = true;
+ del.remove = deleteProjectAndMapping;
+ del.isProjectMapped = isProjectMapped;
+ del.pdps = [];
+
+ activate();
+
+ /**
+ *
+ */
+
+ function activate(){
+
+ resolvePDPs();
+
+ }
+
+ function resolvePDPs() {
+
+ pdpService.findAllWithCallBack(function(data){
+
+ del.pdps = data;
+
+ pdpService.mapPdpsToProject(del.project, del.pdps);
+
+ del.loadingPDP = false;
+
+ });
+
+ }
+
+ function isProjectMapped(){
+ return _.has(del.project, 'pdp');
+ }
+
+ /*
+ * ---- delete
+ */
+
+
+ function deleteProjectAndMapping() {
+
+ del.loading = true;
+
+
+ if(isProjectMapped() ) {
+
+ removeMapping(deleteProject);
+
+ }else{
+ deleteProject();
+ }
+
+ }
+
+ function removeMapping(callbackSuccess){
+
+
+ var pdpName = unmap.project.pdp.name;
+
+ pdpService.unMap(unmap.project, callbackSuccess, deleteMappingError);
+
+
+ function deleteMappingError(reason) {
+
+ $translate('moon.project.remove.mapping.remove.error', { pdpName: pdpName} ).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:projectDeletedError', del.project);
+
+ }
+
+
+ }
+
+ function deleteProject(){
+
+ projectService.data.projects.remove({project_id: del.project.id}, deleteSuccess, deleteError);
+
+ function deleteSuccess(data) {
+
+ $translate('moon.project.remove.success', { projectName: del.project.name }).then(function (translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:projectDeletedSuccess', del.project);
+
+ }
+
+ function deleteError(reason) {
+
+ $translate('moon.project.remove.error', { projectName: del.project.name, errorCode: reason.data.error.code, message : reason.data.error.message } ).then(function (translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ del.loading = false;
+
+ $scope.$emit('event:projectDeletedError', del.project);
+
+ }
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/project/action/project.controller.view.js b/moon_gui/static/app/project/action/project.controller.view.js
new file mode 100755
index 00000000..fe98a507
--- /dev/null
+++ b/moon_gui/static/app/project/action/project.controller.view.js
@@ -0,0 +1,216 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectViewController', ProjectViewController);
+
+ ProjectViewController.$inject = ['$q', '$scope', '$translate', 'alertService', 'projectService'];
+
+ function ProjectViewController($q, $scope, $translate, alertService, projectService) {
+
+ var view = this;
+
+ /*
+ *
+ */
+
+ view.project = $scope.project;
+
+ // view.subjects = [];
+ // view.subjectsLoading = true;
+ // view.selectedSubject = null;
+ // view.hasSubjects = hasSubjects;
+ // view.hasSelectedSubject = hasSelectedSubject;
+ //
+ // view.objects = [];
+ // view.objectsLoading = true;
+ // view.hasObjects = hasObjects;
+ //
+ // view.roles = [];
+ // view.groups = [];
+ // view.roleAssignments = [];
+ // view.groupAssignments = [];
+ //
+ // view.hasRoles = hasRoles;
+ // view.hasGroups = hasGroups;
+ //
+ // view.isRoleAssigned = isRoleAssigned;
+ // view.isGroupAssigned = isGroupAssigned;
+ //
+ // view.resolveRoles = resolveRoles;
+ // view.resolveGroups = resolveGroups;
+ //
+ // //resolveObjects();
+ // //resolveSubjects();
+ //
+ // /*
+ // * ---- objects
+ // */
+ //
+ // function resolveObjects() {
+ //
+ // projectService.data.object.query({project_uuid: view.project.id}).$promise.then(resolveSuccess, resolveError);
+ //
+ // function resolveSuccess(data) {
+ //
+ // view.objectsLoading = false;
+ // view.objects = data.objects;
+ //
+ // }
+ //
+ // function resolveError(reason) {
+ //
+ // view.objectsLoading = false;
+ //
+ // $translate('moon.project.view.object.error').then(function (translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // }
+ //
+ // }
+ //
+ // function hasObjects() {
+ // return view.objects.length > 0;
+ // }
+ //
+ // /*
+ // * ---- subjects
+ // */
+ //
+ // function resolveSubjects() {
+ //
+ // projectService.data.subject.query({project_uuid: view.project.uuid}).$promise.then(resolveSuccess, resolveError);
+ //
+ // function resolveSuccess(data) {
+ //
+ // view.subjectsLoading = false;
+ // view.subjects = data.users;
+ //
+ // }
+ //
+ // function resolveError(reason) {
+ //
+ // view.subjectsLoading = false;
+ //
+ // $translate('moon.project.view.subject.error').then(function (translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // }
+ //
+ // }
+ //
+ // function hasSubjects() {
+ // return view.subjects.lenght > 0;
+ // }
+ //
+ // function hasSelectedSubject() {
+ // return view.selectedSubject != null;
+ // }
+ //
+ // /*
+ // * ---- role
+ // */
+ //
+ // function isRoleAssigned(role) {
+ //
+ // return _(view.roleAssignment.attributes).find(function(role_uuid) {
+ // return role.uuid === role_uuid;
+ // }).length !== 0;
+ //
+ // }
+ //
+ // function hasRoles() {
+ // return view.roles.length > 0;
+ // }
+ //
+ // function resolveRoles(subject) {
+ //
+ // view.rolesLoading = true;
+ //
+ // view.roles = [];
+ // view.roleAssignment = null;
+ //
+ // var promises = { roles: projectService.data.subjectRole.get({project_uuid: view.project.uuid, user_uuid: subject.uuid}).$promise,
+ // roleAssigment: projectService.data.roleAssigment.get({project_uuid: view.project.uuid, user_uuid: subject.uuid}).$promise };
+ //
+ // $q.all(promises).then(resolveSuccess, resolveError);
+ //
+ // function resolveSuccess(data) {
+ //
+ // view.rolesLoading = false;
+ // view.roles = data.roles.roles;
+ // view.roleAssignment = _.first(data.roleAssigment.role_assignments);
+ //
+ // }
+ //
+ // function resolveError(reason) {
+ //
+ // view.rolesLoading = false;
+ //
+ // $translate('moon.project.view.role.error').then(function (translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // }
+ //
+ // }
+ //
+ // /*
+ // * ---- group
+ // */
+ //
+ // function isGroupAssigned(group) {
+ //
+ // return _($scope.view.groupAssignment.attributes).find(function(group_uuid) {
+ // return group.uuid === group_uuid;
+ // }).length !== 0;
+ //
+ // }
+ //
+ // function hasGroups() {
+ // return view.groups.length > 0;
+ // }
+ //
+ // function resolveGroups(subject) {
+ //
+ // view.groupsLoading = true;
+ //
+ // view.groups = [];
+ // view.groupAssignment = null;
+ //
+ // var promises = { groups: projectService.data.subjectGroup.get({project_uuid: view.project.uuid, user_uuid: subject.uuid}).$promise,
+ // groupAssignment: projectService.data.groupAssigment.get({project_uuid: view.project.uuid, user_uuid: subject.uuid}).$promise };
+ //
+ // $q.all(promises).then(resolveSuccess, resolveError);
+ //
+ // function resolveSuccess(data) {
+ //
+ // view.groupsLoading = false;
+ // view.groups = data.groups.groups;
+ // view.groupAssignment = _.first(data.groupAssignment.group_assignments);
+ //
+ // }
+ //
+ // function resolveError(reason) {
+ //
+ // view.groupsLoading = false;
+ //
+ // $translate('moon.project.view.group.error').then(function (translatedValue) {
+ // alertService.alertError(translatedValue);
+ // });
+ //
+ // }
+ //
+ // }
+ //
+ }
+
+})();
diff --git a/moon_gui/static/app/project/project-list.tpl.html b/moon_gui/static/app/project/project-list.tpl.html
new file mode 100755
index 00000000..82a3745e
--- /dev/null
+++ b/moon_gui/static/app/project/project-list.tpl.html
@@ -0,0 +1,157 @@
+
+<div class="container">
+
+ <div>
+ <form class="form-inline pull-right">
+ <div class="form-group">
+ <div>
+ <input id="searchProject" data-ng-model="list.search.query" type="text" class="form-control" placeholder="{{'moon.project.list.search.placeholder' | translate}}" />
+ </div>
+ </div>
+ <div class="form-group">
+ <div>
+ <button type="submit" class="btn btn-danger" data-ng-click="list.search.reset()" data-translate="moon.project.list.search.reset">Reset</button>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+ <div>&nbsp;</div>
+
+ <div class="row">
+
+ <div class="table-responsive" data-role="table">
+
+ <table class="table table-striped table-hover" ng-table="list.table">
+
+ <colgroup>
+ <col class="col-md-2" />
+ <col class="col-md-2" />
+ <col class="col-md-1" />
+ <col class="col-md-1" />
+ <col class="col-md-2" />
+ <col class="col-md-1" />
+ </colgroup>
+
+ <thead>
+
+ <tr>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('name', 'asc'), 'sort-desc': list.table.isSortBy('name', 'desc') }"
+ ng-click="list.table.sorting('name', list.table.isSortBy('name', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.project.list.table.name">Name</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('domain', 'asc'), 'sort-desc': list.table.isSortBy('domain', 'desc') }"
+ ng-click="list.table.sorting('domain', list.table.isSortBy('domain', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.project.list.table.domain">Domain</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('enabled', 'asc'), 'sort-desc': list.table.isSortBy('enabled', 'desc') }"
+ ng-click="list.table.sorting('enabled', list.table.isSortBy('enabled', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.project.list.table.enabled">Enabled</div>
+ </th>
+
+ <th class="customTables sortable"
+ ng-class="{ 'sort-asc': list.table.isSortBy('description', 'asc'), 'sort-desc': list.table.isSortBy('description', 'desc') }"
+ ng-click="list.table.sorting('description', list.table.isSortBy('description', 'asc') ? 'desc' : 'asc')">
+ <div data-translate="moon.project.list.table.description">Description</div>
+ </th>
+
+ <th class="customTables">
+ <div data-translate="moon.project.list.table.mapping">Mapping</div>
+ </th>
+
+ <th class="customTables">
+ <div data-translate="moon.project.list.action.title">Actions</div>
+ </th>
+
+ </tr>
+
+ </thead>
+
+ <tbody ng-if="!list.hasProjects()">
+ <tr>
+ <td colspan="2"><span data-translate="moon.project.list.table.notFound">There is no Projects</span></td>
+ </tr>
+ </tbody>
+
+ <tbody ng-if="list.hasProjects()">
+
+ <tr ng-repeat="aProject in $data | filter:list.search.find | orderBy:sort:reverse">
+ <td ng-bind="aProject.name"></td>
+ <td ng-bind="aProject.domain_id"></td>
+ <td>
+ <span ng-if="aProject.enabled" class="glyphicon glyphicon-ok"></span>
+ </td>
+ <td ng-bind="aProject.description"></td>
+ <td>
+
+ <div ng-if="list.loadingPDPs">
+ <img src="assets/img/ajax-loader.gif" /> <em data-translate="moon.project.list.table.loading.pdp">Loading PDP</em>
+ </div>
+
+ <div ng-if="!list.loadingPDPs">
+ <a href="" ng-if="!list.isProjectMapped(aProject)" ng-click="list.map.showModal(aProject)">
+ <span class="glyphicon glyphicon-link"></span> <em data-translate="moon.project.list.action.map">Map to a PDP</em>
+ </a>
+
+ <div ng-if="list.isProjectMapped(aProject)">
+
+ <span ng-bind="list.getMappedPDPName(aProject)"></span>
+ (<a href="" ng-click="list.unmap.showModal(aProject)">
+ <span class="glyphicon glyphicon-transfer"></span> <em data-translate="moon.project.list.action.unmap">Unmap to a PDP</em>
+ </a>)
+
+ </div>
+ </div>
+
+ </td>
+ <td>
+ <div class="dropdown">
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.project.list.action.title">Actions</span>
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="" ng-click="list.view.showModal(aProject)">
+ <span class="glyphicon glyphicon-eye-open"></span>
+ <span class="control-label" data-translate="moon.project.list.action.detail">Detail</span>
+ </a>
+ </li>
+ <li>
+ <a href="" ng-click="list.del.showModal(aProject)">
+ <span class="glyphicon glyphicon-trash"></span>
+ <span class="control-label" data-translate="moon.project.list.action.delete">Delete</span>
+ </a>
+ </li>
+ </ul>
+ </div>
+ </td>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ <div class="container">
+ <div class="form-inline form-group">
+ <a href="" ng-click="list.add.showModal()" class="btn btn-default">
+ <span class="glyphicon glyphicon-plus-sign"></span>
+ <span data-translate="moon.project.list.action.add">Add Project</span>
+ </a>
+ </div>
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moon_gui/static/app/project/project.controller.list.js b/moon_gui/static/app/project/project.controller.list.js
new file mode 100755
index 00000000..b1cb2056
--- /dev/null
+++ b/moon_gui/static/app/project/project.controller.list.js
@@ -0,0 +1,310 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ProjectListController', ProjectListController);
+
+ ProjectListController.$inject = ['$rootScope', '$scope', '$filter', '$modal', 'ngTableParams', 'pdpService', 'projects'];
+
+ function ProjectListController($rootScope, $scope, $filter, $modal, ngTableParams, pdpService, projects) {
+
+ var list = this;
+
+ /*
+ *
+ */
+
+ list.projects = projects;
+ list.pdps = [];
+
+ list.getProjects = getProjects;
+ list.hasProjects = hasProjects;
+ list.isProjectMapped = isProjectMapped;
+
+ list.table = {};
+
+ list.addProject = addProject;
+ list.deleteProject = deleteProject;
+ list.refreshProjects = refreshProjects;
+
+ list.getMappedPDPName = getMappedPDPName;
+ list.getPdpFromProject = getPdpFromProject;
+
+ list.search = { query: '',
+ find: searchProject,
+ reset: searchReset };
+
+ list.add = { modal: $modal({ template: 'html/project/action/project-add.tpl.html', show: false }),
+ showModal: showAddModal };
+
+ list.del = { modal: $modal({ template: 'html/project/action/project-delete.tpl.html', show: false }),
+ showModal: showDeleteModal };
+
+ list.map = { modal: $modal({ template: 'html/project/action/mapping/project-map.tpl.html', show: false }),
+ showModal: showMapModal };
+
+ list.unmap = { modal: $modal({ template: 'html/project/action/mapping/project-unmap.tpl.html', show: false }),
+ showModal: showUnmapModal };
+
+ list.view = { modal: $modal({ template: 'html/project/action/project-view.tpl.html', show: false }),
+ showModal: showViewModal };
+
+ activate();
+
+
+ function activate(){
+
+ list.loadingPDPs = true;
+
+ newProjectsTable();
+
+ pdpService.findAllWithCallBack(function(data){
+
+ list.pdps = data;
+
+ pdpService.mapPdpsToProjects(list.projects, list.pdps);
+
+ list.loadingPDPs = false;
+
+ });
+ }
+
+
+ /*
+ * ---- events
+ */
+
+ var rootListeners = {
+
+ 'event:projectCreatedSuccess': $rootScope.$on('event:projectCreatedSuccess', projectCreatedSuccess),
+ 'event:projectCreatedError': $rootScope.$on('event:projectCreatedError', projectCreatedError),
+
+ 'event:projectDeletedSuccess': $rootScope.$on('event:projectDeletedSuccess', projectDeletedSuccess),
+ 'event:projectDeletedError': $rootScope.$on('event:projectDeletedError', projectDeletedError),
+
+ 'event:projectMappedSuccess': $rootScope.$on('event:projectMappedSuccess', projectMappedSuccess),
+ 'event:projectMappedError': $rootScope.$on('event:projectMappedError', projectMappedError),
+
+ 'event:projectUnmappedSuccess': $rootScope.$on('event:projectUnmappedSuccess', projectUnmappedSuccess),
+ 'event:projectUnmappedError': $rootScope.$on('event:projectUnmappedError', projectUnmappedError)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+ /*
+ * ---- table
+ */
+
+ /**
+ * Get projects array from the Keystone Moon.
+ * @return an array containing projects JSON
+ */
+ function getProjects() {
+ return (list.projects) ? list.projects : [];
+ }
+
+ function hasProjects() {
+ return list.getProjects().length > 0;
+ }
+
+ function isProjectMapped(project){
+ return _.has(project, 'pdp');
+ }
+
+ /**
+ * Prerequisite, isProjectMapped should return true
+ * @param project
+ * @returns {*}
+ */
+ function getPdpFromProject(project){
+ return project.pdp;
+ }
+
+ function addProject(project) {
+ list.projects.push(project);
+ }
+
+ function deleteProject(project) {
+ list.projects = _.chain(list.projects).reject({id: project.id}).value();
+ }
+
+ function refreshProjects() {
+
+ list.table.total(list.projects.length);
+ list.table.reload();
+
+ }
+
+ function newProjectsTable() {
+
+ list.table = new ngTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ total: function () { return list.getProjects().length; }, // length of data
+ getData: function($defer, params) {
+
+ var orderedData = params.sorting() ? $filter('orderBy')(list.getProjects(), params.orderBy()) : list.getProjects();
+ $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
+
+ },
+ $scope: { $data: {} }
+
+ });
+
+ return list.table;
+
+ }
+
+ /**
+ *
+ * @param project should have project.mapping.authz.pdp.name attribute
+ */
+ function getMappedPDPName(project) {
+ return _.has(project, 'pdp') ? project.pdp.name : 'error';
+ }
+
+ /*
+ * ---- search
+ */
+
+ function searchProject(project){
+ return (project.name.indexOf(list.search.query) !== -1 || project.description.indexOf(list.search.query) !== -1);
+ }
+
+ function searchReset() {
+ list.search.query = '';
+ }
+
+ /*
+ * ---- add
+ */
+
+ function showAddModal() {
+ list.add.modal.$promise.then(list.add.modal.show);
+ }
+
+ function projectCreatedSuccess(event, project) {
+
+ list.addProject(project);
+ list.refreshProjects();
+
+ list.add.modal.hide();
+
+ }
+
+ function projectCreatedError(event, project) {
+ list.add.modal.hide();
+ }
+
+ /*
+ * ---- delete
+ */
+
+ function showDeleteModal(project) {
+
+ list.del.modal.$scope.project = project;
+ list.del.modal.$promise.then(list.del.modal.show);
+
+ }
+
+ function projectDeletedSuccess(event, project) {
+
+ list.deleteProject(project);
+ list.refreshProjects();
+
+ list.del.modal.hide();
+
+ }
+
+ function projectDeletedError(event, project) {
+ list.del.modal.hide();
+ }
+
+ /*
+ * ---- map
+ */
+
+ function showMapModal(project) {
+
+ list.map.modal.$scope.project = project;
+ list.map.modal.$promise.then(list.map.modal.show);
+
+ }
+
+ function projectMappedSuccess(event, project) {
+
+ activate();
+ list.map.modal.hide();
+
+ }
+
+ function projectMappedError(event, project) {
+ list.map.modal.hide();
+ }
+
+ /*
+ * ---- unmap
+ */
+
+ function showUnmapModal(project) {
+
+ list.unmap.modal.$scope.project = project;
+ list.unmap.modal.$promise.then(list.unmap.modal.show);
+
+ }
+
+ function projectUnmappedSuccess(event, project) {
+
+
+ var index = _.findIndex(list.projects, function(aProject){
+ return project.id === aProject.id;
+ });
+
+ if(index === -1){
+ list.unmap.modal.hide();
+ return false;
+ }
+
+ list.projects[index] = project;
+
+ list.refreshProjects();
+
+ list.unmap.modal.hide();
+
+ }
+
+ function projectUnmappedError(event, project) {
+ list.unmap.modal.hide();
+ }
+
+
+ /*
+ * ---- view
+ */
+
+ function showViewModal(project) {
+
+ list.view.modal.$scope.project = project;
+ list.view.modal.$promise.then(list.view.modal.show);
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/alert.service.js b/moon_gui/static/app/services/gui/alert.service.js
new file mode 100755
index 00000000..8435eab1
--- /dev/null
+++ b/moon_gui/static/app/services/gui/alert.service.js
@@ -0,0 +1,39 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('alertService', alertService);
+
+ alertService.$inject = [ 'toaster'];
+
+ function alertService( toaster) {
+
+ var service = {};
+
+ service.alertError = alertError;
+ service.alertSuccess = alertSuccess;
+ service.alertInfo = alertInfo;
+
+ return service;
+
+ function alertError(msg){
+ toaster.pop('error', null, msg, 5000);
+ }
+
+ function alertSuccess(msg){
+ toaster.pop('success', null, msg, 5000);
+ }
+
+ function alertInfo(msg){
+ toaster.pop('note', null, msg, 5000);
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/browser.service.js b/moon_gui/static/app/services/gui/browser.service.js
new file mode 100755
index 00000000..88c693a8
--- /dev/null
+++ b/moon_gui/static/app/services/gui/browser.service.js
@@ -0,0 +1,47 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('browserService', browserService);
+
+ function browserService() {
+
+ var service = {};
+
+ service.sayWho = sayWho;
+
+ return service;
+
+ function sayWho() {
+
+ var ua= navigator.userAgent, tem,
+
+ M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
+
+ if(/trident/i.test(M[1])){
+ tem= /\brv[ :]+(\d+)/g.exec(ua) || [];
+ return 'IE '+(tem[1] || '');
+ }
+
+ if(M[1]=== 'Chrome'){
+ tem= ua.match(/\bOPR\/(\d+)/);
+ if(tem!= null){ return 'Opera '+tem[1];}
+ }
+
+ M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
+
+ if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
+
+ return M.join(' ');
+
+ };
+
+ };
+
+})();
diff --git a/moon_gui/static/app/services/gui/form.service.js b/moon_gui/static/app/services/gui/form.service.js
new file mode 100755
index 00000000..e436593c
--- /dev/null
+++ b/moon_gui/static/app/services/gui/form.service.js
@@ -0,0 +1,47 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('formService', formService);
+
+ function formService() {
+
+ var service = {};
+
+ service.isInvalid = isInvalid;
+ service.checkFieldsValidity = checkFieldsValidity;
+
+ return service;
+
+ function isInvalid(form) {
+ return form.$invalid;
+ }
+
+ function checkFieldsValidity(form) {
+
+ var validationErrorKeys = _.keys(form.$error);
+
+ _(validationErrorKeys).each(function(anErrorKey) {
+
+ var formFields = _.values(form.$error[anErrorKey]);
+
+ _(formFields).each(function(aFormField) {
+
+ aFormField.$dirty = true;
+ aFormField.$setValidity(anErrorKey, false);
+
+ });
+
+ });
+
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/menu.service.js b/moon_gui/static/app/services/gui/menu.service.js
new file mode 100755
index 00000000..fd90a2fa
--- /dev/null
+++ b/moon_gui/static/app/services/gui/menu.service.js
@@ -0,0 +1,49 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('menuService', menuService);
+
+ menuService.$inject = ['$state'];
+
+ function menuService($state) {
+
+ var service = {};
+
+ service.isProjectTabActive = isProjectTabActive;
+ service.isPDPTabActive = isPDPTabActive;
+ service.isPolicyTabActive = isPolicyTabActive;
+ service.isLogsTabActive = isLogsTabActive;
+ service.isModelTabActive = isModelTabActive;
+
+ return service;
+
+ function isProjectTabActive() {
+ return $state.includes('moon.project');
+ }
+
+ function isPDPTabActive() {
+ return $state.includes('moon.pdp');
+ }
+
+ function isPolicyTabActive(){
+ return $state.includes('moon.policy');
+ }
+
+ function isLogsTabActive(){
+ return $state.includes('moon.logs');
+ }
+
+ function isModelTabActive(){
+ return $state.includes('moon.model');
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/security.pipeline.service.js b/moon_gui/static/app/services/gui/security.pipeline.service.js
new file mode 100755
index 00000000..3831e487
--- /dev/null
+++ b/moon_gui/static/app/services/gui/security.pipeline.service.js
@@ -0,0 +1,29 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('securityPipelineService', securityPipelineService);
+
+ securityPipelineService.$inject = ['SECURITY_PIPELINE_CST','policyService'];
+
+ function securityPipelineService(SECURITY_PIPELINE_CST, policyService) {
+ var service = {};
+
+ service.findAll = findAll;
+
+ return service;
+
+ function findAll(type){
+ switch(type){
+ case SECURITY_PIPELINE_CST.TYPE.POLICY :
+ return policyService.findAll();
+ default :
+ return policyService.findAll();
+ }
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/util.service.js b/moon_gui/static/app/services/gui/util.service.js
new file mode 100755
index 00000000..7274244a
--- /dev/null
+++ b/moon_gui/static/app/services/gui/util.service.js
@@ -0,0 +1,66 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('utilService', utilService);
+
+ utilService.$inject = [];
+
+ function utilService() {
+
+ return {
+
+
+ /**
+ * Transforms an answer from server and return an array of objects instead the @param data
+
+ * @param data object : {
+ * 'typeOfTheRreturnedObject' : {
+ * 'idObject1' : {....},
+ * 'idObject2' : {....}
+ * }
+ * }
+ * @param typeOfObject
+ * @returns {Array}
+ */
+ transform : function(data, typeOfObject){
+
+ var result = [];
+
+ _.each(data[typeOfObject],function(item, key){
+ item.id = key;
+ result.push(item);
+ });
+
+ return result;
+ },
+
+ /**
+ * same as transform but with only one object
+ * @param data
+ * @param typeOfObject the first elem of the dictonnary
+ */
+ transformOne : function(data, typeOfObject){
+
+ var result = [];
+
+ _.each(data[typeOfObject], function (item, key) {
+ item.id = key;
+ result.push(item);
+ });
+
+ return result[0];
+
+ }
+
+ };
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/gui/version.service.js b/moon_gui/static/app/services/gui/version.service.js
new file mode 100755
index 00000000..5f9f2786
--- /dev/null
+++ b/moon_gui/static/app/services/gui/version.service.js
@@ -0,0 +1,27 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('versionService', versionService);
+
+ versionService.$inject = ['$resource'];
+
+ function versionService($resource) {
+
+ return {
+
+ version: $resource('version.json', {}, {
+ get: {method: 'GET', isArray: false}
+ })
+
+ };
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/moon/model/model.service.js b/moon_gui/static/app/services/moon/model/model.service.js
new file mode 100755
index 00000000..a676fc1a
--- /dev/null
+++ b/moon_gui/static/app/services/moon/model/model.service.js
@@ -0,0 +1,105 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('modelService', modelService);
+
+ modelService.$inject = ['$resource', 'REST_URI', 'metaRuleService', 'utilService'];
+
+ function modelService($resource, REST_URI, metaRuleService, utilService) {
+
+ return {
+
+ data: $resource(REST_URI.MODELS + ':model_id', {}, {
+ get: {method: 'GET'},
+ query: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: {method: 'PATCH'}
+ }),
+
+ findAll: function () {
+
+ return this.data.query().$promise.then(function (data) {
+
+ return utilService.transform(data, 'models');
+
+ });
+
+ },
+
+
+ findAllWithCallBack : function (callback){
+
+ return this.data.query().$promise.then(function (data) {
+
+ callback( utilService.transform(data, 'models'));
+
+ });
+
+ },
+
+ findOneWithCallback : function(modelId, callback){
+
+ return this.data.get({model_id: modelId}).$promise.then(function (data) {
+
+ callback(utilService.transformOne(data, 'models'));
+
+ });
+
+ },
+
+ findOneWithMetaRules: function (modelId) {
+
+ return this.data.get({model_id: modelId}).$promise.then(function (data) {
+
+ var res = utilService.transformOne(data, 'models');
+
+ if(res.meta_rules.length > 0){
+
+ metaRuleService.findSomeWithMetaData(res.meta_rules).then(function(metaRules){
+
+ res.meta_rules_values = metaRules;
+ res.id = modelId;
+
+ return res;
+
+ });
+
+ }else{
+
+ res.meta_rules_values = [];
+ res.id = modelId;
+
+ }
+
+ return res;
+
+ });
+
+ },
+
+ delete: function (model, callbackSuccess, callbackError ) {
+
+ delete model.meta_rules_values;
+
+ this.data.remove({model_id: model.id}, model, callbackSuccess, callbackError);
+
+ },
+
+ update: function (model, callbackSuccess, callbackError) {
+
+ delete model.meta_rules_values;
+ this.data.update({model_id: model.id}, model, callbackSuccess, callbackError);
+
+ }
+
+ }
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/pdp.service.js b/moon_gui/static/app/services/moon/pdp.service.js
new file mode 100755
index 00000000..822f7414
--- /dev/null
+++ b/moon_gui/static/app/services/moon/pdp.service.js
@@ -0,0 +1,128 @@
+/**
+ * service allowing the client to interact with pdp
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('pdpService', pdpService);
+
+ pdpService.$inject = ['$q', '$resource','REST_URI', 'utilService'];
+
+ function pdpService($q, $resource, REST_URI, utilService) {
+
+ return {
+
+ data: {
+
+ pdp: $resource(REST_URI.PDP + ':pdp_id', {}, {
+ query: { method: 'GET', isArray: false },
+ get: { method: 'GET', isArray: false },
+ create: { method: 'POST' },
+ update: { method:'PATCH'},
+ remove: { method: 'DELETE' }
+ })
+
+ },
+
+ findAll: function() {
+
+ return this.data.pdp.query().$promise.then(function (data) {
+
+ return utilService.transform(data, 'pdps');
+
+ });
+
+ },
+
+ findAllWithCallBack : function (callback){
+
+ return this.data.pdp.query().$promise.then(function (data) {
+
+ callback( utilService.transform(data, 'pdps'));
+
+ });
+
+ },
+
+ findOne: function(id) {
+
+ return this.data.pdp.get({pdp_id: id}).$promise.then(function (data) {
+
+ return utilService.transformOne(data, 'pdps');
+
+ });
+
+ },
+
+ unMap: function(pdp, callbackSuccess, callbackError){
+
+ pdp.keystone_project_id = null;
+
+ if(_.has(pdp, 'project')){
+ delete pdp.project;
+ }
+
+ this.data.pdp.update({pdp_id: pdp.id}, pdp, callbackSuccess, callbackError);
+
+ },
+
+ map: function(pdp, projectId, callbackSuccess, callbackError){
+
+ pdp.keystone_project_id = projectId;
+
+ this.data.pdp.update({pdp_id: pdp.id}, pdp, callbackSuccess, callbackError);
+ },
+
+ update: function (pdp, callbackSuccess, callbackError) {
+
+ this.data.pdp.update({pdp_id: pdp.id}, pdp, callbackSuccess, callbackError);
+
+ },
+
+ mapPdpsToProjects : mapPdpsToProjects,
+
+ mapPdpsToProject : mapPdpsToProject
+
+ };
+
+ /**
+ * Will assign each project to it related pdp
+ * @param projects a list of Project, a new attribute pdp will be add, if the related pdp is existing in @param pdps
+ * @param pdps a list of Pdp
+ */
+ function mapPdpsToProjects(projects, pdps){
+
+ _.each(projects, function(project){
+
+ return mapPdpsToProject(project, pdps);
+
+ });
+ }
+
+ function mapPdpsToProject(project, pdps){
+
+ if (_.isNull(project.keystone_project_id)){
+ return false;
+ }
+
+ var index = _.findIndex(pdps, function(pdp){
+ return project.id === pdp.keystone_project_id;
+ });
+
+ if(index === -1){
+ return false;
+ }
+
+ project.pdp = pdps[index];
+
+ return true;
+ }
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js b/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js
new file mode 100755
index 00000000..ca138b45
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js
@@ -0,0 +1,133 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('assignmentsService', assignmentsService);
+
+ assignmentsService.$inject = ['$resource', 'REST_URI', 'utilService'];
+
+ function assignmentsService($resource, REST_URI, utilService) {
+
+ var data = {
+
+ subject: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/subject_assignments/:perimeter_id/:category_id/:data_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+
+ object: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/object_assignments/:perimeter_id/:category_id/:data_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ action: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/action_assignments/:perimeter_id/:category_id/:data_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ }
+
+ };
+
+ return {
+
+ subject : {
+
+ delete: function (policyId, perimeterId, categoryId, dataId, callbackSuccess, callbackError ) {
+
+ data.subject.policy.remove({policy_id: policyId, perimeter_id: perimeterId, category_id: categoryId, data_id: dataId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ add:function (subject, policyId, callbackSuccess, callbackError ) {
+
+ data.subject.policy.create({policy_id: policyId}, subject, callbackSuccess, callbackError);
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.subject.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'subject_assignments'));
+
+ });
+
+ }
+ },
+
+ object : {
+
+
+ delete: function (policyId, perimeterId, categoryId, dataId, callbackSuccess, callbackError ) {
+
+ data.object.policy.remove({policy_id: policyId, perimeter_id: perimeterId, category_id: categoryId, data_id: dataId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ add:function (object, policyId, callbackSuccess, callbackError ) {
+
+ data.object.policy.create({policy_id: policyId}, object, callbackSuccess, callbackError);
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.object.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'object_assignments'));
+
+ });
+
+ }
+ },
+
+ action : {
+
+ delete: function (policyId, perimeterId, categoryId, dataId, callbackSuccess, callbackError ) {
+
+ data.action.policy.remove({policy_id: policyId, perimeter_id: perimeterId, category_id: categoryId, data_id: dataId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ add:function (action, policyId, callbackSuccess, callbackError ) {
+
+ data.action.policy.create({policy_id: policyId}, action, callbackSuccess, callbackError);
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.action.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'action_assignments'));
+
+ });
+
+ }
+ }
+
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/policy/parameters/data.service.js b/moon_gui/static/app/services/moon/policy/parameters/data.service.js
new file mode 100755
index 00000000..1bbd3b24
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/parameters/data.service.js
@@ -0,0 +1,249 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('dataService', dataService);
+
+ dataService.$inject = ['$resource', 'REST_URI', 'utilService'];
+
+ function dataService($resource, REST_URI, utilService) {
+
+ var data = {
+
+ subject: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/subject_data/:subject_id/:category_id/:data_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ object: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/object_data/:object_id/:category_id/:data_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ action: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/action_data/:action_id/:category_id/:data_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ }
+
+ };
+
+ return {
+
+ subject : {
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.subject.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data['subject_data'][0], 'data'));
+
+ });
+
+ },
+
+ findAllFromCategoriesWithCallback: function(policyId, categoryId, callback){
+
+ data.subject.policy.get({policy_id: policyId, category_id: categoryId}).$promise.then(function(data) {
+
+ if(data['subject_data'][0]) {
+
+ callback(utilService.transform(data['subject_data'][0], 'data'));
+
+ }else{
+
+ callback([])
+
+ }
+
+ });
+
+ },
+
+ delete: function (subject, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.subject.policy.remove({policy_id: policyId, category_id: categoryId, data_id: subject.id}, subject, callbackSuccess, callbackError);
+
+ },
+
+ add: function (subject, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.subject.policy.create({policy_id: policyId, category_id: categoryId}, subject, callbackSuccess, callbackError);
+
+ },
+
+ data: {
+
+ findOne: function(policyId, subjectId, dataId, callback){
+
+ data.subject.policy.get({policy_id: policyId, subject_id: subjectId, data_id : dataId}).$promise.then(function(data) {
+
+ if(data['subject_data'][0]){
+
+ callback(utilService.transformOne(data['subject_data'][0], 'data'));
+
+ }else{
+
+ callback({ });
+
+ }
+
+ });
+
+ }
+ }
+ },
+
+ object : {
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.object.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data['object_data'][0], 'data'));
+
+ });
+
+ },
+
+ findAllFromCategoriesWithCallback: function(policyId, categoryId, callback){
+
+ data.object.policy.get({policy_id: policyId, category_id: categoryId}).$promise.then(function(data) {
+
+ if(data['object_data'][0]) {
+
+ callback(utilService.transform(data['object_data'][0], 'data'));
+
+ }else{
+
+ callback([])
+
+ }
+
+ });
+
+ },
+
+ delete: function (object, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.object.policy.remove({policy_id: policyId, category_id: categoryId, data_id: object.id}, object, callbackSuccess, callbackError);
+
+ },
+
+ add:function (object, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.object.policy.create({policy_id: policyId, category_id: categoryId}, object, callbackSuccess, callbackError);
+
+ },
+
+ data: {
+
+ findOne: function(policyId, objectId, dataId, callback){
+
+ data.object.policy.get({policy_id: policyId, object_id: objectId, data_id : dataId}).$promise.then(function(data) {
+
+ if(data['object_data'][0]){
+
+ callback(utilService.transformOne(data['object_data'][0], 'data'));
+
+ }else{
+
+ callback({ });
+
+ }
+
+ });
+
+ }
+ }
+ },
+
+ action : {
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.action.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data['action_data'][0], 'data'));
+
+ });
+
+ },
+
+ findAllFromCategoriesWithCallback: function(policyId, categoryId, callback){
+
+ data.action.policy.get({policy_id: policyId, category_id: categoryId}).$promise.then(function(data) {
+
+ if(data['action_data'][0]) {
+
+ callback(utilService.transform(data['action_data'][0], 'data'));
+
+ }else{
+
+ callback([])
+
+ }
+
+ });
+
+ },
+
+ delete: function (action, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.action.policy.remove({policy_id: policyId, category_id: categoryId, data_id: action.id}, action, callbackSuccess, callbackError);
+
+ },
+
+ add:function (action, policyId, categoryId, callbackSuccess, callbackError ) {
+
+ data.action.policy.create({policy_id: policyId, category_id: categoryId}, action, callbackSuccess, callbackError);
+
+ },
+
+
+ data: {
+
+ findOne: function(policyId, actionId, dataId, callback){
+
+ data.action.policy.get({policy_id: policyId, action_id: actionId, data_id : dataId}).$promise.then(function(data) {
+
+ if(data['action_data'][0]){
+
+ callback(utilService.transformOne(data['action_data'][0], 'data'));
+
+ }else{
+
+ callback({ });
+
+ }
+
+ });
+
+ }
+ }
+ }
+
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js b/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js
new file mode 100755
index 00000000..42e7288a
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js
@@ -0,0 +1,460 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('perimeterService', perimeterService);
+
+ perimeterService.$inject = ['$resource', 'REST_URI', '$q', 'utilService'];
+
+ function perimeterService($resource, REST_URI, $q, utilService) {
+
+ var data = {
+
+ subject: {
+
+ perimeter: $resource(REST_URI.PERIMETERS.subject + ':subject_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/subjects/:subject_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ })
+
+ },
+
+ object: {
+
+ perimeter: $resource(REST_URI.PERIMETERS.object + ':object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/objects/:object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ })
+
+ },
+
+ action: {
+
+ perimeter: $resource(REST_URI.PERIMETERS.action + ':action_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/actions/:action_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'},
+ update: { method: 'PATCH' }
+ })
+
+ }
+
+ };
+
+ return {
+
+ subject : {
+
+ findOne: function(subjectId, callback){
+
+ data.subject.perimeter.get({subject_id: subjectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'subjects'));
+
+ });
+
+ },
+
+ findOneReturningPromise: function (subjectId){
+
+ return data.subject.perimeter.get({subject_id: subjectId}).$promise;
+
+ },
+
+ findSome: function(subjectListId) {
+
+ var _self = this;
+
+ if(subjectListId.length === 0){
+ return [];
+ }
+
+ var promises = _(subjectListId).map( function(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'subjects');
+
+ });
+
+ });
+
+ },
+
+ unMapPerimeterFromPolicy: function(policyId, subjectId, callbackSuccess, callbackError ){
+
+ data.subject.policy.remove({policy_id: policyId, subject_id: subjectId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.subject.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'subjects'));
+
+ });
+
+ },
+
+ findOneFromPolicyWithCallback: function(policyId, subjectId, callback){
+
+ data.subject.policy.get({policy_id: policyId, subject_id: subjectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'subjects'));
+
+ });
+
+ },
+
+ findAll: function(){
+
+ return data.subject.perimeter.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'subjects');
+
+ });
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.subject.perimeter.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'subjects'));
+
+ });
+
+ },
+
+ delete: function (subject, callbackSuccess, callbackError ) {
+
+ data.subject.perimeter.remove({subject_id: subject.id}, subject, callbackSuccess, callbackError);
+
+ },
+
+ add: function (subject, callbackSuccess, callbackError ) {
+
+ data.subject.perimeter.create({}, subject, callbackSuccess, callbackError);
+
+ },
+
+ update: function(subject, callbackSuccess, callbackError){
+
+ data.subject.perimeter.update({subject_id: subject.id}, subject, callbackSuccess, callbackError);
+
+ }
+ },
+
+ object : {
+
+ findOne: function(objectId, callback){
+
+ data.object.perimeter.get({object_id: objectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'objects'));
+
+ });
+
+ },
+
+ findOneReturningPromise: function(objectId){
+
+ return data.object.perimeter.get({object_id: objectId}).$promise;
+
+ },
+
+ findSome: function(objectListId) {
+
+
+ var _self = this;
+
+ if(objectListId.length === 0){
+ return [];
+ }
+
+ var promises = _(objectListId).map( function(objectId) {
+
+ return _self.findOneReturningPromise(objectId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'objects');
+
+ });
+
+ });
+
+ },
+
+ unMapPerimeterFromPolicy: function(policyId, objectId, callbackSuccess, callbackError ){
+
+ data.object.policy.remove({policy_id: policyId, object_id: objectId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ findSomeWithCallback: function(objectListId, callback){
+
+ var _self = this;
+
+ if(objectListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(objectListId).map( function(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'objects');
+
+ }));
+
+ });
+
+ },
+
+ findAll : function(){
+
+ return data.object.perimeter.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'objects');
+
+ });
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.object.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'objects'));
+
+ });
+
+ },
+
+ findOneFromPolicyWithCallback: function(policyId, objectId, callback){
+
+
+ data.object.policy.get({policy_id: policyId, object_id: objectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'objects'));
+
+ });
+
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.object.perimeter.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'objects'));
+
+ });
+
+ },
+
+ delete: function (object, callbackSuccess, callbackError ) {
+
+ data.object.perimeter.remove({object_id: object.id}, object, callbackSuccess, callbackError);
+
+ },
+
+ add:function (object, callbackSuccess, callbackError ) {
+
+ data.object.perimeter.create({}, object, callbackSuccess, callbackError);
+
+ },
+
+ update: function(object, callbackSuccess, callbackError){
+
+ data.object.perimeter.update({object_id: object.id}, object, callbackSuccess, callbackError);
+
+ }
+ },
+
+ action : {
+
+ findOne: function(actionId, callback){
+
+ data.action.perimeter.get({actionId: actionId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'actions'));
+
+ });
+
+ },
+
+ findOneReturningPromise: function(actionId){
+
+ return data.action.perimeter.get({actionId: actionId}).$promise;
+
+ },
+
+ findSome: function(actionListId) {
+
+ var _self = this;
+
+ if(actionListId.length === 0){
+ return [];
+ }
+
+ var promises = _(actionListId).map( function(actionId) {
+
+ return _self.findOneReturningPromise(actionId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'actions');
+
+ });
+
+ });
+
+ },
+
+ unMapPerimeterFromPolicy: function(policyId, actionId, callbackSuccess, callbackError){
+
+ data.action.policy.remove({policy_id: policyId, action_id: actionId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ findSomeWithCallback: function(actionListId, callback){
+
+ var _self = this;
+
+ if(actionListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(actionListId).map( function(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'actions');
+
+ }));
+
+ });
+
+ },
+
+ findAll : function(){
+
+ return data.action.perimeter.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'actions');
+
+ });
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.action.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'actions'));
+
+ });
+
+ },
+
+ findOneFromPolicyWithCallback: function(policyId, actionId, callback){
+
+ data.action.policy.get({policy_id: policyId, action_id: actionId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'actions'));
+
+ });
+
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.action.perimeter.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'actions'));
+
+ });
+
+ },
+
+ delete: function (action, callbackSuccess, callbackError ) {
+
+ data.action.perimeter.remove({action_id: action.id}, action, callbackSuccess, callbackError);
+
+ },
+
+ add:function (action, callbackSuccess, callbackError ) {
+
+ data.action.perimeter.create({}, action, callbackSuccess, callbackError);
+
+ },
+
+ update: function(action, callbackSuccess, callbackError){
+
+ data.action.perimeter.update({action_id: action.id}, action, callbackSuccess, callbackError);
+
+ }
+ }
+
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/policy/parameters/rule.service.js b/moon_gui/static/app/services/moon/policy/parameters/rule.service.js
new file mode 100644
index 00000000..b1a350ae
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/parameters/rule.service.js
@@ -0,0 +1,49 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('ruleService', ruleService);
+
+ ruleService.$inject = ['$resource', 'REST_URI', 'utilService'];
+
+ function ruleService($resource, REST_URI, utilService) {
+
+ return {
+
+ data: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/rules/:rule_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ this.data.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ console.log('ruleService - findAllFromPolicyWithCallback()');
+ console.log(data);
+
+ var array = data['rules'];
+
+ console.log(JSON.stringify(array));
+ callback(utilService.transform(array, 'rules'));
+
+ });
+
+ }
+
+
+ }
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/policy/parameters/rules.service.js b/moon_gui/static/app/services/moon/policy/parameters/rules.service.js
new file mode 100755
index 00000000..76b24011
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/parameters/rules.service.js
@@ -0,0 +1,56 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('rulesService', rulesService);
+
+ rulesService.$inject = ['$resource', 'REST_URI', 'utilService'];
+
+ function rulesService($resource, REST_URI, utilService) {
+
+ return {
+
+ data: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/rules/:rule_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ add: function (rules, policyId, callbackSuccess, callbackError ) {
+
+ this.data.policy.create({policy_id: policyId}, rules, callbackSuccess, callbackError);
+
+ },
+
+ delete: function (ruleId, policyId, callbackSuccess, callbackError ) {
+
+ this.data.policy.remove({policy_id: policyId, rule_id: ruleId}, {}, callbackSuccess, callbackError);
+
+ },
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ this.data.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(data.rules.rules);
+ //callback(utilService.transform(data['rules'], 'rules'));
+
+ });
+
+ }
+
+
+ }
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/policy/policy.service.js b/moon_gui/static/app/services/moon/policy/policy.service.js
new file mode 100755
index 00000000..5ad31421
--- /dev/null
+++ b/moon_gui/static/app/services/moon/policy/policy.service.js
@@ -0,0 +1,108 @@
+/**
+ * Service providing access to the tenants
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('policyService', policyService);
+
+ policyService.$inject = ['$resource', 'REST_URI', 'utilService', '$q'];
+
+ function policyService($resource, REST_URI, utilService, $q) {
+
+ return {
+
+ data: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id', {}, {
+ query: {method: 'GET'},
+ create: { method: 'POST' },
+ update: { method: 'PATCH' },
+ remove: { method: 'DELETE' }
+ })
+
+ },
+
+ findAll: function () {
+
+ return this.data.policy.query().$promise.then(function (data) {
+
+ return utilService.transform(data, 'policies');
+
+ });
+
+ },
+
+ findAllWithCallback: function (callback) {
+
+ return this.data.policy.query().$promise.then(function (data) {
+
+ callback(utilService.transform(data, 'policies'));
+
+ });
+
+ },
+
+ findOneReturningPromise: function(policyId){
+
+ return this.data.policy.get({policy_id: policyId}).$promise;
+
+ },
+
+ findSomeWithCallback: function(policyListId, callback){
+
+ var _self = this;
+
+ if(policyListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(policyListId).map( function(policyId) {
+
+ return _self.findOneReturningPromise(policyId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'policies');
+
+ }));
+
+ });
+
+ },
+
+ findOne: function (policyId) {
+
+ return this.data.policy.get({policy_id: policyId}).$promise.then(function (data) {
+
+ return utilService.transformOne(data, 'policies');
+
+ });
+
+ },
+
+ update: function (policy, callbackSuccess, callbackError) {
+
+ this.data.policy.update({policy_id: policy.id}, policy, callbackSuccess, callbackError);
+
+ },
+
+ delete: function (policy, callbackSuccess, callbackError ) {
+
+ this.data.policy.remove({policy_id: policy.id}, policy, callbackSuccess, callbackError);
+
+ }
+
+ }
+ }
+
+})();
diff --git a/moon_gui/static/app/services/moon/rule/metadata.service.js b/moon_gui/static/app/services/moon/rule/metadata.service.js
new file mode 100755
index 00000000..8c68b2ef
--- /dev/null
+++ b/moon_gui/static/app/services/moon/rule/metadata.service.js
@@ -0,0 +1,354 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('metaDataService', metaDataService);
+
+ metaDataService.$inject = ['$resource', 'REST_URI', '$q', 'utilService'];
+
+ function metaDataService($resource, REST_URI, $q, utilService) {
+
+ var data = {
+
+ subject: $resource(REST_URI.METADATA.subject + ':subject_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ }),
+
+
+ object: $resource(REST_URI.METADATA.object + ':object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ }),
+
+ action: $resource(REST_URI.METADATA.action + ':action_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ };
+
+ return {
+
+ subject : {
+
+ findOne: function(subjectId, callback){
+
+ data.subject.get({subject_id: subjectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'subject_categories'));
+
+ });
+
+ },
+
+ findOneReturningPromise: function (subjectId){
+
+ return data.subject.get({subject_id: subjectId}).$promise;
+
+ },
+
+ findSome: function(subjectListId) {
+
+ var _self = this;
+
+ if(subjectListId.length === 0){
+ return [];
+ }
+
+ var promises = _(subjectListId).map( function(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'subject_categories');
+
+ });
+
+ });
+
+ },
+
+ findSomeWithCallback: function(subjectListId, callback){
+
+ var _self = this;
+
+ if(subjectListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(subjectListId).map( function(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'subject_categories');
+
+ }));
+
+ });
+
+ },
+
+ findAll: function(){
+
+ return data.subject.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'subject_categories');
+
+ });
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.subject.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'subject_categories'));
+
+ });
+
+ },
+
+ delete: function (subject, callbackSuccess, callbackError ) {
+
+ data.subject.remove({subject_id: subject.id}, subject, callbackSuccess, callbackError);
+
+ },
+
+ add: function (subject, callbackSuccess, callbackError ) {
+
+ data.subject.create({}, subject, callbackSuccess, callbackError);
+
+ }
+ },
+
+ object : {
+
+ findOne: function(objectId, callback){
+
+ data.object.get({object_id: objectId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'object_categories'));
+
+ })
+
+ },
+
+ findOneReturningPromise: function(objectId){
+
+ return data.object.get({object_id: objectId}).$promise;
+
+ },
+
+ findSome: function(objectListId) {
+
+
+ var _self = this;
+
+ if(objectListId.length === 0){
+ return [];
+ }
+
+ var promises = _(objectListId).map( function(objectId) {
+
+ return _self.findOneReturningPromise(objectId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'object_categories');
+
+ });
+
+ });
+
+ },
+
+ findSomeWithCallback: function(objectListId, callback){
+
+ var _self = this;
+
+ if(objectListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(objectListId).map( function(objectId) {
+
+ return _self.findOneReturningPromise(objectId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'object_categories');
+
+ }));
+
+ });
+
+ },
+
+ findAll : function(){
+
+ return data.object.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'object_categories');
+
+ });
+
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.object.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'object_categories'));
+
+ });
+
+ },
+
+ delete: function (object, callbackSuccess, callbackError ) {
+
+ data.object.remove({object_id: object.id}, object, callbackSuccess, callbackError);
+
+ },
+
+ add:function (object, callbackSuccess, callbackError ) {
+
+ data.object.create({}, object, callbackSuccess, callbackError);
+
+ }
+ },
+
+ action : {
+
+ findOne: function(actionId, callback){
+
+ data.action.get({action_id: actionId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'action_categories'));
+
+ })
+
+ },
+
+ findOneReturningPromise: function(actionId){
+
+ return data.action.get({action_id: actionId}).$promise;
+
+ },
+
+ findSome: function(actionListId) {
+
+ var _self = this;
+
+ if(actionListId.length === 0){
+ return [];
+ }
+
+ var promises = _(actionListId).map( function(actionId) {
+
+ return _self.findOneReturningPromise(actionId);
+
+ });
+
+ return $q.all(promises).then( function(result) {
+
+ return _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'action_categories');
+
+ });
+
+ });
+
+ },
+
+ findSomeWithCallback: function(actionListId, callback){
+
+ var _self = this;
+
+ if(actionListId.length === 0){
+ callback([]);
+ }
+
+ var promises = _(actionListId).map( function(actionId) {
+
+ return _self.findOneReturningPromise(actionId);
+
+ });
+
+ $q.all(promises).then( function(result) {
+
+ callback( _(result).map( function(resource) {
+
+ return utilService.transformOne(resource, 'action_categories');
+
+ }));
+
+ });
+
+ },
+
+ findAll : function(){
+
+ return data.action.get().$promise.then(function(data) {
+
+ return utilService.transform(data, 'action_categories');
+
+ });
+
+ },
+
+ findAllWithCallback: function(callback){
+
+ return data.action.get().$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'action_categories'));
+
+ });
+
+ },
+
+ delete: function (action, callbackSuccess, callbackError ) {
+
+ data.action.remove({action_id: action.id}, action, callbackSuccess, callbackError);
+
+ },
+
+ add:function (action, callbackSuccess, callbackError ) {
+
+ data.action.create({}, action, callbackSuccess, callbackError);
+
+ }
+ }
+
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/moon/rule/metarule.service.js b/moon_gui/static/app/services/moon/rule/metarule.service.js
new file mode 100755
index 00000000..2679fc5b
--- /dev/null
+++ b/moon_gui/static/app/services/moon/rule/metarule.service.js
@@ -0,0 +1,208 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('metaRuleService', metaRuleService);
+
+ metaRuleService.$inject = ['$resource', 'REST_URI', 'metaDataService', '$q', 'utilService'];
+
+ function metaRuleService($resource, REST_URI, metaDataService, $q, utilService) {
+
+ return {
+
+ data: $resource(REST_URI.METARULES + ':metarule_id', {}, {
+ query: {method: 'GET' },
+ get: {method: 'GET', isArray: false},
+ update: {method: 'PATCH'},
+ create: { method: 'POST' },
+ remove: { method: 'DELETE' }
+ }),
+
+
+ findAll: function () {
+
+ return this.data.query().$promise.then(function (data) {
+
+ return utilService.transform(data, 'meta_rules');
+
+ });
+
+ },
+
+ findAllWithCallback : function (callback) {
+
+ this.data.query().$promise.then(function (data) {
+
+ callback(utilService.transform(data, 'meta_rules'));
+
+ });
+
+ },
+
+ findSomeWithMetaData : function(metaRuleListId){
+
+ var _self = this;
+
+ if(metaRuleListId.length === 0){
+ return [];
+ }
+
+ var promises = _(metaRuleListId).map(function(objectId) {
+
+ return _self.findOneReturningPromise(objectId);
+
+ });
+
+ return $q.all(promises).then(function(result) {
+
+ return _(result).map(function(resource) {
+
+ var metaRule = utilService.transformOne(resource, 'meta_rules');
+
+ metaRule = _self.findMetaDataFromMetaRule(metaRule);
+
+ return metaRule;
+
+ });
+
+ });
+
+
+ },
+
+ findSomeWithCallback : function(metaRuleListId, callback){
+
+ var _self = this;
+
+ if(metaRuleListId.length === 0){
+ return [];
+ }
+
+ var promises = _(metaRuleListId).map(function(objectId) {
+
+ return _self.findOneReturningPromise(objectId);
+
+ });
+
+ return $q.all(promises).then(function(result) {
+
+ callback( _(result).map(function(resource) {
+
+ return utilService.transformOne(resource, 'meta_rules');
+
+ }));
+
+ });
+
+
+ },
+
+ findOneReturningPromise: function(metaRuleId){
+
+ return this.data.get({metarule_id: metaRuleId}).$promise;
+
+ },
+
+ findOne : function(metaRuleId){
+
+ return this.data.get({metarule_id: metaRuleId}).$promise.then(function(data) {
+
+ return utilService.transformOne(data, 'meta_rules');
+
+ });
+
+ },
+
+ findOneWithCallback: function(metaRuleId, callback){
+
+ this.data.get({metarule_id: metaRuleId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'meta_rules'));
+
+ });
+
+ },
+
+ findOneWithMetaData: function(metaRuleId){
+
+ var _self = this;
+
+ return this.data.get({metarule_id: metaRuleId}).$promise.then(function(data) {
+
+ var metaRule = utilService.transformOne(data, 'meta_rules');
+
+ metaRule = _self.findMetaDataFromMetaRule(metaRule);
+
+ return metaRule;
+
+ });
+
+ },
+
+ findMetaDataFromMetaRule : function (metaRule){
+
+ if(metaRule.subject_categories.length > 0){
+
+ metaDataService.subject.findSome(metaRule.subject_categories).then(function(categories){
+ metaRule.subject_categories_values = categories;
+ });
+
+ }else{
+
+ metaRule.subject_categories_values = [];
+
+ }
+
+ if(metaRule.object_categories.length > 0){
+
+ metaDataService.object.findSome(metaRule.object_categories).then(function(categories){
+ metaRule.object_categories_values = categories;
+ });
+
+ }else{
+
+ metaRule.object_categories_values = [];
+
+ }
+
+ if(metaRule.action_categories.length > 0){
+
+ metaDataService.action.findSome(metaRule.action_categories).then(function(categories){
+ metaRule.action_categories_values = categories;
+ });
+
+
+ }else{
+
+ metaRule.action_categories_values = [];
+
+ }
+
+ return metaRule;
+ },
+
+ delete: function (metaRule, callbackSuccess, callbackError ) {
+
+ this.data.remove({metarule_id: metaRule.id}, metaRule, callbackSuccess, callbackError);
+
+ },
+
+ update: function(metaRule, callbackSuccess, callbackError){
+
+ delete metaRule.subject_categories_values;
+ delete metaRule.object_categories_values;
+ delete metaRule.action_categories_values;
+
+ this.data.update({metarule_id: metaRule.id}, metaRule, callbackSuccess, callbackError);
+
+ }
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/partner/authentication.service.js b/moon_gui/static/app/services/partner/authentication.service.js
new file mode 100755
index 00000000..b6d3f36d
--- /dev/null
+++ b/moon_gui/static/app/services/partner/authentication.service.js
@@ -0,0 +1,106 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('authenticationService', authenticationService);
+
+ authenticationService.$inject = ['$resource', 'REST_URI', '$sessionStorage', '$http', '$location'];
+
+ function authenticationService($resource, REST_URI, $sessionStorage, $http, $location) {
+
+ return {
+ data: $resource(REST_URI.KEYSTONE + 'auth/tokens', {}, {
+ login: { method: 'POST' ,
+ /**
+ * Transform Response is needed to add headers into the response object
+ * @param data
+ * @param headersGetter
+ * @returns {{}}
+ */
+ transformResponse : function (data, headersGetter) {
+ var response = {};
+ response.data = angular.fromJson(data) ;
+ response.headers = headersGetter();
+ return response;
+ }
+ },
+ logout: { method: 'DELETE' }
+ }),
+
+ /**
+ *
+ * @param credentials object : {username : '', password : ''}
+ * @param callbackSuccess
+ * @param callbackError
+ * @constructor
+ */
+ Login : function (credentials, callbackSuccess, callbackError){
+ var requestData = {
+ auth:{
+ identity:{
+ methods:[
+ 'password'
+ ],
+ password:{
+ user:{
+ name: credentials.username,
+ domain:{
+ name:'Default'
+ },
+ password: credentials.password
+ }
+ }
+ },
+ scope: {
+ project: {
+ name:'admin',
+ domain:{
+ name:'Default'
+ }
+ }
+ }
+ }
+ };
+ this.data.login({}, requestData, function (response){
+ $sessionStorage.currentUser = response.data;
+ $sessionStorage.currentUser.connectionToken = response.headers['x-subject-token'];
+ SetTokenHeader(response.headers['x-subject-token']);
+ callbackSuccess();
+ }, callbackError);
+ },
+ IsConnected : IsConnected,
+ SetTokenHeader : SetTokenHeader,
+ GetTokenHeader : GetTokenHeader,
+ GetUser : GetUser,
+ Logout : Logout
+ };
+
+ function IsConnected(){
+ return _.has($sessionStorage, 'currentUser');
+ }
+
+ function Logout(){
+ delete $sessionStorage.currentUser;
+ $http.defaults.headers.common['X-Auth-Token'] = '';
+ $location.path('/');
+ }
+
+ function GetUser(){
+ return $sessionStorage.currentUser;
+ }
+
+ function GetTokenHeader(){
+ return $sessionStorage.currentUser.connectionToken;
+ }
+
+ function SetTokenHeader(token){
+ $http.defaults.headers.common['X-Auth-Token'] = token;
+ }
+ }
+})(); \ No newline at end of file
diff --git a/moon_gui/static/app/services/partner/nova.service.js b/moon_gui/static/app/services/partner/nova.service.js
new file mode 100755
index 00000000..38e2a0fc
--- /dev/null
+++ b/moon_gui/static/app/services/partner/nova.service.js
@@ -0,0 +1,35 @@
+/**
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('novaService', novaService);
+
+ novaService.$inject = ['$resource'];
+
+ function novaService($resource) {
+
+ return {
+
+ data: {
+
+ image: $resource('./pip/nova/images', {}, {
+ query: {method: 'GET', isArray: false}
+ }),
+
+ flavor: $resource('./pip/nova/flavors', {}, {
+ query: {method: 'GET', isArray: false}
+ })
+
+ }
+
+ };
+
+ }
+
+})();
diff --git a/moon_gui/static/app/services/partner/project.service.js b/moon_gui/static/app/services/partner/project.service.js
new file mode 100755
index 00000000..4ec27f2e
--- /dev/null
+++ b/moon_gui/static/app/services/partner/project.service.js
@@ -0,0 +1,60 @@
+/**
+ * Service providing access to the tenants
+ * @author arnaud marhin<arnaud.marhin@orange.com>
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('projectService', projectService);
+
+ projectService.$inject = [ '$resource' , 'REST_URI' ];
+
+ function projectService( $resource, REST_URI) {
+
+ return {
+
+ data: {
+
+ projects: $resource(REST_URI.KEYSTONE + 'projects/:project_id', {}, {
+ query: {method: 'GET', isArray: false},
+ get: { method: 'GET', isArray: false },
+ create: { method: 'POST' },
+ remove: { method: 'DELETE' }
+ })
+
+ },
+
+ findOne: function(project_id, callback){
+
+ return this.data.projects.get({project_id: project_id}).$promise.then(function(data) {
+
+ callback(data.project);
+
+ });
+
+ },
+
+ findAll: function() {
+
+ return this.data.projects.query().$promise.then(function(listProjects) {
+
+ var result = [];
+
+ _.each(listProjects['projects'], function(item){
+ result.push(item);
+ });
+
+ return result;
+ });
+
+ }
+
+ };
+
+ }
+
+})();