aboutsummaryrefslogtreecommitdiffstats
path: root/moonv4/moon_gui/static
diff options
context:
space:
mode:
Diffstat (limited to 'moonv4/moon_gui/static')
-rw-r--r--moonv4/moon_gui/static/app/authentication/authentication.controller.js54
-rw-r--r--moonv4/moon_gui/static/app/authentication/authentication.tpl.html28
-rw-r--r--moonv4/moon_gui/static/app/common/404/404.tpl.html3
-rw-r--r--moonv4/moon_gui/static/app/common/compatibility/compatibility.tpl.html26
-rw-r--r--moonv4/moon_gui/static/app/common/footer/footer.controller.js54
-rw-r--r--moonv4/moon_gui/static/app/common/footer/footer.tpl.html7
-rw-r--r--moonv4/moon_gui/static/app/common/header/header.controller.js53
-rw-r--r--moonv4/moon_gui/static/app/common/header/header.tpl.html50
-rw-r--r--moonv4/moon_gui/static/app/common/loader/loader.dir.js19
-rw-r--r--moonv4/moon_gui/static/app/common/loader/loader.tpl.html1
-rw-r--r--moonv4/moon_gui/static/app/common/waiting/waiting.tpl.html15
-rw-r--r--moonv4/moon_gui/static/app/dashboard/dashboard.tpl.html14
-rw-r--r--moonv4/moon_gui/static/app/logs/logs.controller.js16
-rw-r--r--moonv4/moon_gui/static/app/logs/logs.tpl.html3
-rw-r--r--moonv4/moon_gui/static/app/model/action/model-add.tpl.html66
-rw-r--r--moonv4/moon_gui/static/app/model/action/model-delete.tpl.html39
-rw-r--r--moonv4/moon_gui/static/app/model/action/model-view.tpl.html41
-rw-r--r--moonv4/moon_gui/static/app/model/action/model.controller.add.js71
-rw-r--r--moonv4/moon_gui/static/app/model/action/model.controller.delete.js72
-rw-r--r--moonv4/moon_gui/static/app/model/action/model.controller.view.js53
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html99
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html333
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js330
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js367
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html50
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html102
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html35
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js99
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js213
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js74
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html67
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html62
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js49
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js98
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html149
-rw-r--r--moonv4/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js237
-rw-r--r--moonv4/moon_gui/static/app/model/edit/model-edit-basic.tpl.html65
-rw-r--r--moonv4/moon_gui/static/app/model/edit/model-edit.tpl.html66
-rw-r--r--moonv4/moon_gui/static/app/model/edit/model.controller.edit.js55
-rw-r--r--moonv4/moon_gui/static/app/model/edit/model.edit.basic.dir.js97
-rw-r--r--moonv4/moon_gui/static/app/model/model-list.tpl.html123
-rw-r--r--moonv4/moon_gui/static/app/model/model.controller.list.js195
-rw-r--r--moonv4/moon_gui/static/app/moon.constants.js86
-rw-r--r--moonv4/moon_gui/static/app/moon.module.js362
-rw-r--r--moonv4/moon_gui/static/app/pdp/action/pdp-add.tpl.html88
-rw-r--r--moonv4/moon_gui/static/app/pdp/action/pdp-delete.tpl.html35
-rw-r--r--moonv4/moon_gui/static/app/pdp/action/pdp.controller.add.js108
-rw-r--r--moonv4/moon_gui/static/app/pdp/action/pdp.controller.delete.js66
-rw-r--r--moonv4/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html65
-rw-r--r--moonv4/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html56
-rw-r--r--moonv4/moon_gui/static/app/pdp/edit/pdp.controller.edit.js50
-rw-r--r--moonv4/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js97
-rw-r--r--moonv4/moon_gui/static/app/pdp/pdp-list.tpl.html133
-rw-r--r--moonv4/moon_gui/static/app/pdp/pdp.controller.list.js287
-rw-r--r--moonv4/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html64
-rw-r--r--moonv4/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html33
-rw-r--r--moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.map.js106
-rw-r--r--moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js74
-rw-r--r--moonv4/moon_gui/static/app/policy/action/policy-add.tpl.html113
-rw-r--r--moonv4/moon_gui/static/app/policy/action/policy-delete.tpl.html40
-rw-r--r--moonv4/moon_gui/static/app/policy/action/policy.controller.add.js113
-rw-r--r--moonv4/moon_gui/static/app/policy/action/policy.controller.delete.js69
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html323
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js500
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html349
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js330
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js401
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html320
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js358
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html102
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js254
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html89
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/policy-edit.tpl.html202
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/policy.controller.edit.js74
-rw-r--r--moonv4/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js134
-rw-r--r--moonv4/moon_gui/static/app/policy/policy-list.tpl.html131
-rw-r--r--moonv4/moon_gui/static/app/policy/policy-mapped-list.tpl.html88
-rw-r--r--moonv4/moon_gui/static/app/policy/policy.controller.list.js175
-rw-r--r--moonv4/moon_gui/static/app/policy/policy.mapped.list.dir.js203
-rw-r--r--moonv4/moon_gui/static/app/project/action/mapping/project-map.tpl.html62
-rw-r--r--moonv4/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html33
-rw-r--r--moonv4/moon_gui/static/app/project/action/mapping/project.controller.map.js107
-rw-r--r--moonv4/moon_gui/static/app/project/action/mapping/project.controller.unmap.js74
-rw-r--r--moonv4/moon_gui/static/app/project/action/project-add.tpl.html89
-rw-r--r--moonv4/moon_gui/static/app/project/action/project-delete.tpl.html45
-rw-r--r--moonv4/moon_gui/static/app/project/action/project-view.tpl.html194
-rw-r--r--moonv4/moon_gui/static/app/project/action/project.controller.add.js78
-rw-r--r--moonv4/moon_gui/static/app/project/action/project.controller.delete.js134
-rw-r--r--moonv4/moon_gui/static/app/project/action/project.controller.view.js216
-rw-r--r--moonv4/moon_gui/static/app/project/project-list.tpl.html157
-rw-r--r--moonv4/moon_gui/static/app/project/project.controller.list.js310
-rw-r--r--moonv4/moon_gui/static/app/services/gui/alert.service.js39
-rw-r--r--moonv4/moon_gui/static/app/services/gui/browser.service.js47
-rw-r--r--moonv4/moon_gui/static/app/services/gui/form.service.js47
-rw-r--r--moonv4/moon_gui/static/app/services/gui/menu.service.js49
-rw-r--r--moonv4/moon_gui/static/app/services/gui/security.pipeline.service.js29
-rw-r--r--moonv4/moon_gui/static/app/services/gui/util.service.js66
-rw-r--r--moonv4/moon_gui/static/app/services/gui/version.service.js27
-rw-r--r--moonv4/moon_gui/static/app/services/moon/model/model.service.js105
-rw-r--r--moonv4/moon_gui/static/app/services/moon/pdp.service.js128
-rw-r--r--moonv4/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js96
-rw-r--r--moonv4/moon_gui/static/app/services/moon/policy/parameters/data.service.js196
-rw-r--r--moonv4/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js419
-rw-r--r--moonv4/moon_gui/static/app/services/moon/policy/parameters/rule.service.js49
-rw-r--r--moonv4/moon_gui/static/app/services/moon/policy/policy.service.js108
-rw-r--r--moonv4/moon_gui/static/app/services/moon/rule/metadata.service.js354
-rw-r--r--moonv4/moon_gui/static/app/services/moon/rule/metarule.service.js208
-rw-r--r--moonv4/moon_gui/static/app/services/partner/authentication.service.js106
-rw-r--r--moonv4/moon_gui/static/app/services/partner/nova.service.js35
-rw-r--r--moonv4/moon_gui/static/app/services/partner/project.service.js60
-rwxr-xr-xmoonv4/moon_gui/static/favicon.icobin0 -> 318 bytes
-rwxr-xr-xmoonv4/moon_gui/static/i18n/en.json1266
-rwxr-xr-xmoonv4/moon_gui/static/i18n/fr.json1266
-rwxr-xr-xmoonv4/moon_gui/static/img/ajax-loader.gifbin0 -> 673 bytes
-rwxr-xr-xmoonv4/moon_gui/static/img/ajax-waiting.gifbin0 -> 10819 bytes
-rwxr-xr-xmoonv4/moon_gui/static/img/arrow-link.gifbin0 -> 87 bytes
-rw-r--r--moonv4/moon_gui/static/img/et.jpgbin0 -> 31641 bytes
-rwxr-xr-xmoonv4/moon_gui/static/img/logo-openstack.pngbin0 -> 3180 bytes
-rwxr-xr-xmoonv4/moon_gui/static/img/logo-orange.gifbin0 -> 981 bytes
-rw-r--r--moonv4/moon_gui/static/styles/main.css169
-rwxr-xr-xmoonv4/moon_gui/static/version.json3
121 files changed, 16099 insertions, 0 deletions
diff --git a/moonv4/moon_gui/static/app/authentication/authentication.controller.js b/moonv4/moon_gui/static/app/authentication/authentication.controller.js
new file mode 100644
index 00000000..d3510fed
--- /dev/null
+++ b/moonv4/moon_gui/static/app/authentication/authentication.controller.js
@@ -0,0 +1,54 @@
+/**
+ * @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/moonv4/moon_gui/static/app/authentication/authentication.tpl.html b/moonv4/moon_gui/static/app/authentication/authentication.tpl.html
new file mode 100644
index 00000000..77d1646b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/404/404.tpl.html b/moonv4/moon_gui/static/app/common/404/404.tpl.html
new file mode 100644
index 00000000..61e0420c
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/compatibility/compatibility.tpl.html b/moonv4/moon_gui/static/app/common/compatibility/compatibility.tpl.html
new file mode 100644
index 00000000..0e32dc4f
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/footer/footer.controller.js b/moonv4/moon_gui/static/app/common/footer/footer.controller.js
new file mode 100644
index 00000000..d7506840
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/footer/footer.tpl.html b/moonv4/moon_gui/static/app/common/footer/footer.tpl.html
new file mode 100644
index 00000000..aacb392d
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/header/header.controller.js b/moonv4/moon_gui/static/app/common/header/header.controller.js
new file mode 100644
index 00000000..dfab502f
--- /dev/null
+++ b/moonv4/moon_gui/static/app/common/header/header.controller.js
@@ -0,0 +1,53 @@
+/**
+ * @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.getUser = authenticationService.GetUser;
+
+ /*
+ *
+ */
+
+ function changeLocale(localeKey, event) {
+
+ event.preventDefault();
+
+ $translate.use(localeKey);
+ $translate.preferredLanguage(localeKey);
+
+ }
+
+ function logout(){
+ authenticationService.Logout();
+ $translate('moon.logout.success').then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+ }
+ }
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/common/header/header.tpl.html b/moonv4/moon_gui/static/app/common/header/header.tpl.html
new file mode 100644
index 00000000..ad7b461d
--- /dev/null
+++ b/moonv4/moon_gui/static/app/common/header/header.tpl.html
@@ -0,0 +1,50 @@
+<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)"><img src="assets/img/arrow-link.gif" alt="fr_" />fr</a>
+ <a href="" ng-click="header.changeLocale('en', $event)"><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/moonv4/moon_gui/static/app/common/loader/loader.dir.js b/moonv4/moon_gui/static/app/common/loader/loader.dir.js
new file mode 100644
index 00000000..ba40c121
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/loader/loader.tpl.html b/moonv4/moon_gui/static/app/common/loader/loader.tpl.html
new file mode 100644
index 00000000..51da439f
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/common/waiting/waiting.tpl.html b/moonv4/moon_gui/static/app/common/waiting/waiting.tpl.html
new file mode 100644
index 00000000..6c042635
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/dashboard/dashboard.tpl.html b/moonv4/moon_gui/static/app/dashboard/dashboard.tpl.html
new file mode 100644
index 00000000..03da1b71
--- /dev/null
+++ b/moonv4/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-center"/>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/logs/logs.controller.js b/moonv4/moon_gui/static/app/logs/logs.controller.js
new file mode 100644
index 00000000..e48e2b8b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/logs/logs.tpl.html b/moonv4/moon_gui/static/app/logs/logs.tpl.html
new file mode 100644
index 00000000..fecc0289
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model-add.tpl.html b/moonv4/moon_gui/static/app/model/action/model-add.tpl.html
new file mode 100644
index 00000000..dee53a97
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model-delete.tpl.html b/moonv4/moon_gui/static/app/model/action/model-delete.tpl.html
new file mode 100644
index 00000000..cde16d0e
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model-view.tpl.html b/moonv4/moon_gui/static/app/model/action/model-view.tpl.html
new file mode 100644
index 00000000..46c295c7
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model.controller.add.js b/moonv4/moon_gui/static/app/model/action/model.controller.add.js
new file mode 100644
index 00000000..11d3abf4
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model.controller.delete.js b/moonv4/moon_gui/static/app/model/action/model.controller.delete.js
new file mode 100644
index 00000000..5d9dae1a
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/action/model.controller.view.js b/moonv4/moon_gui/static/app/model/action/model.controller.view.js
new file mode 100644
index 00000000..7605eecf
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html b/moonv4/moon_gui/static/app/model/edit/metadata/metadata-edit.tpl.html
new file mode 100644
index 00000000..fde6cdb0
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html b/moonv4/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html
new file mode 100644
index 00000000..35b61f57
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/metadata/metadata-list.tpl.html
@@ -0,0 +1,333 @@
+<div>
+ <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> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js b/moonv4/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js
new file mode 100644
index 00000000..2e927c44
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/metadata/metadata.edit.dir.js
@@ -0,0 +1,330 @@
+(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/moonv4/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js b/moonv4/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js
new file mode 100644
index 00000000..c4654be1
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/metadata/metadata.list.dir.js
@@ -0,0 +1,367 @@
+(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 : '='
+ },
+ 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.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(metaRule.subject_categories);
+ list.catObj = metaDataService.object.findSome(metaRule.object_categories);
+ list.catAct = metaDataService.action.findSome(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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-add.tpl.html
new file mode 100644
index 00000000..a721e6d0
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-map.tpl.html
new file mode 100644
index 00000000..1830204b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules-unmap.tpl.html
new file mode 100644
index 00000000..bb02aba2
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.controller.add.js
new file mode 100644
index 00000000..a95951fa
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.map.controller.js
new file mode 100644
index 00000000..cf9ba06c
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js b/moonv4/moon_gui/static/app/model/edit/metarules/action/mapping/metarules.unmap.controller.js
new file mode 100644
index 00000000..30f32d51
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit-basic.tpl.html
new file mode 100644
index 00000000..b6136195
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules-edit.tpl.html
new file mode 100644
index 00000000..7b074448
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js b/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.controller.edit.js
new file mode 100644
index 00000000..b2ebc45d
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js b/moonv4/moon_gui/static/app/model/edit/metarules/action/metarules.edit.basic.dir.js
new file mode 100644
index 00000000..603e7a33
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html b/moonv4/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html
new file mode 100644
index 00000000..c36700ff
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/metarules/metarules-list.tpl.html
@@ -0,0 +1,149 @@
+<div>
+
+ <div class="row">
+
+ <div><h4 data-translate="moon.model.metarules.title">List of Meta Rules</h4></div>
+
+ </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-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>
+
+ <div class="row" ng-if="list.editMode">
+
+ <div class="form-group">
+ <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>
+
+</div>
diff --git a/moonv4/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js b/moonv4/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js
new file mode 100644
index 00000000..8fba0266
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/metarules/metarules.list.dir.js
@@ -0,0 +1,237 @@
+(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.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/moonv4/moon_gui/static/app/model/edit/model-edit-basic.tpl.html b/moonv4/moon_gui/static/app/model/edit/model-edit-basic.tpl.html
new file mode 100644
index 00000000..bd73b4ef
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/edit/model-edit.tpl.html b/moonv4/moon_gui/static/app/model/edit/model-edit.tpl.html
new file mode 100644
index 00000000..c86d05ec
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/model-edit.tpl.html
@@ -0,0 +1,66 @@
+<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">
+ <moon-meta-rules-list mapped-model="edit.model" edit-mode="edit.editMetaRules"></moon-meta-rules-list>
+ </div>
+
+ <div class="panel-body" ng-if="!edit.model.meta_rules_values">
+ <moon-loader></moon-loader>
+ </div>
+
+ </div>
+
+
+</div>
diff --git a/moonv4/moon_gui/static/app/model/edit/model.controller.edit.js b/moonv4/moon_gui/static/app/model/edit/model.controller.edit.js
new file mode 100644
index 00000000..f5972052
--- /dev/null
+++ b/moonv4/moon_gui/static/app/model/edit/model.controller.edit.js
@@ -0,0 +1,55 @@
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .controller('ModelEditController', ModelEditController);
+
+ ModelEditController.$inject = ['$scope', '$rootScope', 'model', '$stateParams'];
+
+ function ModelEditController($scope, $rootScope, model, $stateParams) {
+
+ 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;
+
+ }
+
+ }
+
+})();
diff --git a/moonv4/moon_gui/static/app/model/edit/model.edit.basic.dir.js b/moonv4/moon_gui/static/app/model/edit/model.edit.basic.dir.js
new file mode 100644
index 00000000..54bb7071
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/model-list.tpl.html b/moonv4/moon_gui/static/app/model/model-list.tpl.html
new file mode 100644
index 00000000..89c682cc
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/model/model.controller.list.js b/moonv4/moon_gui/static/app/model/model.controller.list.js
new file mode 100644
index 00000000..5021a57e
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/moon.constants.js b/moonv4/moon_gui/static/app/moon.constants.js
new file mode 100644
index 00000000..e3fd7595
--- /dev/null
+++ b/moonv4/moon_gui/static/app/moon.constants.js
@@ -0,0 +1,86 @@
+/**
+# 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('RULES_CST', {
+ TYPE: {
+ SUBJECT: 'SUBJECT',
+ OBJECT: 'OBJECT',
+ ACTION: 'ACTION'
+ }
+ })
+ .constant('REST_URI', {
+ PDP : 'http://172.18.0.11:38001/pdp/',
+ MODELS : 'http://172.18.0.11:38001/models/',
+ METARULES: 'http://172.18.0.11:38001/meta_rules/',
+ RULES: 'http://172.18.0.11:38001/rules/',
+ POLICIES: 'http://172.18.0.11:38001/policies/',
+ METADATA: {
+ subject : 'http://172.18.0.11:38001/subject_categories/',
+ object : 'http://172.18.0.11:38001/object_categories/',
+ action : 'http://172.18.0.11:38001/action_categories/'
+ },
+ PERIMETERS :{
+ subject : 'http://172.18.0.11:38001/subjects/',
+ object : 'http://172.18.0.11:38001/objects/',
+ action : 'http://172.18.0.11:38001/actions/'
+ },
+ KEYSTONE : 'http://keystone:5000/v3/'
+ });
+})();
diff --git a/moonv4/moon_gui/static/app/moon.module.js b/moonv4/moon_gui/static/app/moon.module.js
new file mode 100644
index 00000000..a653f8f3
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/action/pdp-add.tpl.html b/moonv4/moon_gui/static/app/pdp/action/pdp-add.tpl.html
new file mode 100644
index 00000000..f83fb85c
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/action/pdp-delete.tpl.html b/moonv4/moon_gui/static/app/pdp/action/pdp-delete.tpl.html
new file mode 100644
index 00000000..167ba417
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/action/pdp.controller.add.js b/moonv4/moon_gui/static/app/pdp/action/pdp.controller.add.js
new file mode 100644
index 00000000..d1c34c79
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/action/pdp.controller.delete.js b/moonv4/moon_gui/static/app/pdp/action/pdp.controller.delete.js
new file mode 100644
index 00000000..62557864
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html b/moonv4/moon_gui/static/app/pdp/edit/pdp-edit-basic.tpl.html
new file mode 100644
index 00000000..887d81ca
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html b/moonv4/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html
new file mode 100644
index 00000000..bc4582ce
--- /dev/null
+++ b/moonv4/moon_gui/static/app/pdp/edit/pdp-edit.tpl.html
@@ -0,0 +1,56 @@
+<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>
+
+ <moon-policy-mapped-list pdp="edit.pdp"></moon-policy-mapped-list>
+
+ </div>
+ </div>
+
+</div>
diff --git a/moonv4/moon_gui/static/app/pdp/edit/pdp.controller.edit.js b/moonv4/moon_gui/static/app/pdp/edit/pdp.controller.edit.js
new file mode 100644
index 00000000..41b73098
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js b/moonv4/moon_gui/static/app/pdp/edit/pdp.edit.basic.dir.js
new file mode 100644
index 00000000..402422b6
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/pdp-list.tpl.html b/moonv4/moon_gui/static/app/pdp/pdp-list.tpl.html
new file mode 100644
index 00000000..6716ebba
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/pdp/pdp.controller.list.js b/moonv4/moon_gui/static/app/pdp/pdp.controller.list.js
new file mode 100644
index 00000000..07c9aa2a
--- /dev/null
+++ b/moonv4/moon_gui/static/app/pdp/pdp.controller.list.js
@@ -0,0 +1,287 @@
+/**
+ * @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),
+
+ };
+
+ for (var unbind in rootListeners) {
+ $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
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ 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/moonv4/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html b/moonv4/moon_gui/static/app/policy/action/mapping/policy-map.tpl.html
new file mode 100644
index 00000000..8b787f14
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html b/moonv4/moon_gui/static/app/policy/action/mapping/policy-unmap.tpl.html
new file mode 100644
index 00000000..a2cda52a
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.map.js b/moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.map.js
new file mode 100644
index 00000000..6ad8caa7
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js b/moonv4/moon_gui/static/app/policy/action/mapping/policy.controller.unmap.js
new file mode 100644
index 00000000..d309ec0f
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/policy-add.tpl.html b/moonv4/moon_gui/static/app/policy/action/policy-add.tpl.html
new file mode 100644
index 00000000..d20c41be
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/policy-delete.tpl.html b/moonv4/moon_gui/static/app/policy/action/policy-delete.tpl.html
new file mode 100644
index 00000000..3b5df88b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/policy.controller.add.js b/moonv4/moon_gui/static/app/policy/action/policy.controller.add.js
new file mode 100644
index 00000000..0320c2e9
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/action/policy.controller.delete.js b/moonv4/moon_gui/static/app/policy/action/policy.controller.delete.js
new file mode 100644
index 00000000..9a718ddc
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html b/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html
new file mode 100644
index 00000000..0f919a4a
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments-list.tpl.html
@@ -0,0 +1,323 @@
+<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>
+ <!--<th data-translate="moon.policy.assignments.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>
+ <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.category.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>
+
+ <span ng-if="index < value.assignments.length-1">,</span>
+ </span>
+
+ </span>
+
+ </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-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.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>
+
+ <!--<th data-translate="moon.policy.assignments.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>
+
+ <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.category.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>
+
+ <span ng-if="index < value.assignments.length-1">,</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-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.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>
+
+ <!--<th data-translate="moon.policy.assignments.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>
+ <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>
+
+ <span ng-if="index < value.assignments.length-1">,</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-meta-data-edit meta-rule="list.metaRule" meta-data-type="list.typeOfAction"></moon-meta-data-edit>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js b/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js
new file mode 100644
index 00000000..747fd487
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/assignments/assignments.list.dir.js
@@ -0,0 +1,500 @@
+(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', 'assignmentService', '$translate', 'alertService', 'policyService', 'ASSIGNMENTS_CST', 'utilService', 'metaDataService', 'perimeterService', 'dataService'];
+
+ function moonAssignmentsListController($scope, $rootScope, assignmentService, $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.unMapSub = unMapSub;
+ list.unMapObj = unMapObj;
+ list.unMapAct = unMapAct;
+
+ 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:deleteDataFromDataAddSuccess': $rootScope.$on('event:deleteDataFromDataAddSuccess', deletePolicy)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+ function manageSubjects(){
+
+ list.loadingSub = true;
+
+ assignmentService.subject.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('subjects');
+ console.log(data);
+ list.subjects = data;
+ list.loadingSub = false;
+
+ });
+ }
+
+ function manageObjects(){
+
+ list.loadingObj = true;
+
+ assignmentService.object.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('objects');
+ console.log(data);
+ list.objects = data;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions(){
+
+ list.loadingAct = true;
+
+ assignmentService.action.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('actions');
+ console.log(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;
+
+ }
+ }
+
+ /**
+ * Prerequisite : meta Rule should be completely loaded
+ * @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;
+
+ }
+ }
+
+
+
+ /**
+ * UnMap
+ */
+
+ function unMapSub(subject){
+
+ subject.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.subject_categories = _.without(policyToSend.subject_categories, subject.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ subject.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+
+ }
+
+ function unMapObj(object){
+
+ object.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.object_categories = _.without(policyToSend.object_categories, object.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ object.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+
+ }
+
+ }
+
+ function unMapAct(action){
+
+ action.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.action_categories = _.without(policyToSend.action_categories, action.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ action.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+
+ }
+
+ /**
+ * Delete
+ */
+
+ function deleteSub(subject){
+
+ subject.loader = true;
+
+ assignmentService.subject.delete(subject, deleteSubSuccess, deleteSubError);
+
+ function deleteSubSuccess(data){
+
+ $translate('moon.policy.perimeter.subject.delete.success', { subjectName: subject.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeSubFromSubList(subject);
+
+ subject.loader = false;
+
+ }
+
+ function deleteSubError(reason){
+
+ $translate('moon.policy.perimeter.subject.delete.error', { subjectName: subject.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+ }
+
+ function deleteObj(object){
+
+ object.loader = true;
+
+ assignmentService.object.delete(object, deleteObjSuccess, deleteObjError);
+
+ function deleteObjSuccess(data){
+
+ $translate('moon.policy.perimeter.object.delete.success', { objectName: object.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeObjFromObjList(object);
+
+ object.loader = false;
+
+ }
+
+ function deleteObjError(reason){
+
+ $translate('moon.policy.perimeter.object.delete.error', { objectName: object.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+ }
+ }
+
+ function deleteAct(action){
+
+ action.loader = true;
+
+ assignmentService.action.delete(action, deleteActSuccess, deleteActError);
+
+ function deleteActSuccess(data){
+
+ $translate('moon.policy.perimeter.action.delete.success', { actionName: action.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeActFromActList(action);
+
+ action.loader = false;
+
+ }
+
+ function deleteActError(reason){
+
+ $translate('moon.policy.perimeter.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 deletePolicy( event, policy){
+
+ list.policy = policy;
+
+ activate();
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html
new file mode 100644
index 00000000..b2bac597
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data-list.tpl.html
@@ -0,0 +1,349 @@
+<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>
+
+ <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 data-translate="moon.policy.data.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.data.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.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"></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>
+
+ <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 data-translate="moon.policy.data.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.data.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.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"></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>
+
+ <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 data-translate="moon.policy.data.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.data.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> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js
new file mode 100644
index 00000000..11f0d480
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.edit.dir.js
@@ -0,0 +1,330 @@
+(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'
+ metaDataType: '=',
+ metaRule : '='
+ },
+ restrict : 'E',
+ replace : true
+ };
+ }
+
+ angular
+ .module('moon')
+ .controller('moonDataEditController', moonDataEditController);
+
+ moonDataEditController.$inject = ['$scope', 'metaDataService', 'DATA_CST', 'alertService', '$translate', 'formService', 'policyService', 'utilService'];
+
+ function moonDataEditController($scope, metaDataService, DATA_CST, alertService, $translate, formService, policyService, 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 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.list = [];
+ break;
+
+ }
+
+ function callBackList(list){
+
+ edit.list = list
+
+ }
+
+ }
+
+ /**
+ * Add
+ */
+
+ function addToMetaRule(){
+
+ if(!edit.selectedMetaData){
+
+ return;
+
+ }
+
+ var metaRuleToSend = edit.metaRule;
+
+ switch(edit.metaDataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ metaRuleToSend.subject_categories.push(edit.selectedMetaData.id);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ metaRuleToSend.object_categories.push(edit.selectedMetaData.id);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ metaRuleToSend.action_categories.push(edit.selectedMetaData.id);
+ break;
+ }
+
+ policyService.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 DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.add(metaDataToSend, createSuccess, createError);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.add(metaDataToSend, createSuccess, createError);
+ break;
+
+ case DATA_CST.TYPE.ACTION:
+
+ metaDataService.action.add(metaDataToSend, createSuccess, createError);
+ break;
+ }
+
+ }
+
+ function createSuccess(data) {
+
+ var created = {};
+
+ switch(edit.metaDataType){
+
+ case DATA_CST.TYPE.SUBJECT:
+
+ created = utilService.transformOne(data, 'subject_categories');
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ created = utilService.transformOne(data, 'object_categories');
+ break;
+
+ case 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 DATA_CST.TYPE.SUBJECT:
+
+ metaDataService.subject.delete(metaDataToDelete, deleteSuccess, deleteError);
+ break;
+
+ case DATA_CST.TYPE.OBJECT:
+
+ metaDataService.object.delete(metaDataToDelete, deleteSuccess, deleteError);
+ break;
+
+ case 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);
+ });
+
+ policyService.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/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js
new file mode 100644
index 00000000..07afd1b9
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/data/data.list.dir.js
@@ -0,0 +1,401 @@
+(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', 'policyService', 'DATA_CST', 'utilService', 'metaDataService'];
+
+ function moonDataListController($scope, $rootScope, dataService, $translate, alertService, policyService, DATA_CST, utilService, 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.unMapSub = unMapSub;
+ list.unMapObj = unMapObj;
+ list.unMapAct = unMapAct;
+
+ 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:deleteDataFromDataAddSuccess': $rootScope.$on('event:deleteDataFromDataAddSuccess', deletePolicy)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $scope.$on('$destroy', rootListeners[unbind]);
+ }
+
+
+ function manageSubjects(){
+
+ list.loadingSub = true;
+
+ dataService.subject.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('subjects');
+ console.log(data);
+ list.subjects = data;
+ list.loadingSub = false;
+
+ });
+ }
+
+ function manageObjects(){
+
+ list.loadingObj = true;
+
+ dataService.object.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('objects');
+ console.log(data);
+ list.objects = data;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions(){
+
+ list.loadingAct = true;
+
+ dataService.action.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('actions');
+ console.log(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;
+
+ }
+ }
+
+ /**
+ * UnMap
+ */
+
+ function unMapSub(subject){
+
+ subject.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.subject_categories = _.without(policyToSend.subject_categories, subject.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ subject.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+
+ }
+
+ function unMapObj(object){
+
+ object.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.object_categories = _.without(policyToSend.object_categories, object.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ object.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+
+ }
+
+ }
+
+ function unMapAct(action){
+
+ action.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.action_categories = _.without(policyToSend.action_categories, action.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findDataFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ action.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+
+ }
+
+ /**
+ * Delete
+ */
+
+ function deleteSub(subject){
+
+ subject.loader = true;
+
+ dataService.subject.delete(subject, deleteSubSuccess, deleteSubError);
+
+ function deleteSubSuccess(data){
+
+ $translate('moon.policy.perimeter.subject.delete.success', { subjectName: subject.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeSubFromSubList(subject);
+
+ subject.loader = false;
+
+ }
+
+ function deleteSubError(reason){
+
+ $translate('moon.policy.perimeter.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, deleteObjSuccess, deleteObjError);
+
+ function deleteObjSuccess(data){
+
+ $translate('moon.policy.perimeter.object.delete.success', { objectName: object.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeObjFromObjList(object);
+
+ object.loader = false;
+
+ }
+
+ function deleteObjError(reason){
+
+ $translate('moon.policy.perimeter.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, deleteActSuccess, deleteActError);
+
+ function deleteActSuccess(data){
+
+ $translate('moon.policy.perimeter.action.delete.success', { actionName: action.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeActFromActList(action);
+
+ action.loader = false;
+
+ }
+
+ function deleteActError(reason){
+
+ $translate('moon.policy.perimeter.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 deletePolicy( event, policy){
+
+ list.policy = policy;
+
+ activate();
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html b/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html
new file mode 100644
index 00000000..6111888a
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter-list.tpl.html
@@ -0,0 +1,320 @@
+<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.partner.id">Id</th>
+ <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.partner_id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <td ng-bind="value.email"></td>
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.perimeter.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.perimeter.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 data-translate="moon.policy.perimeter.subject.notFound">There is no Subjects</td>
+ <td></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-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.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.partner.id">Id</th>
+ <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.partner_id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.perimeter.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.perimeter.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 data-translate="moon.policy.perimeter.object.notFound">There is no Objects</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.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.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.partner.id">Id</th>
+ <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.partner_id"></td>
+ <td ng-bind="value.name"></td>
+ <td ng-bind="value.description"></td>
+ <!--<td>
+
+ <div class="dropdown">
+
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
+ <span data-translate="moon.policy.perimeter.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.perimeter.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 data-translate="moon.policy.perimeter.action.notFound">There is no Actions</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.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> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js b/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js
new file mode 100644
index 00000000..8c50b22e
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/perimeter/perimeter.list.dir.js
@@ -0,0 +1,358 @@
+(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', 'policyService', 'PERIMETER_CST', 'utilService'];
+
+ function moonPerimeterListController($scope, $rootScope, perimeterService, $translate, alertService, policyService, PERIMETER_CST, utilService){
+
+ 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.deleteSub = deleteSub;
+ list.deleteObj = deleteObj;
+ list.deleteAct = deleteAct;
+
+ list.getSubjects = getSubjects;
+ list.getObjects = getObjects;
+ list.getActions = getActions;
+
+ activate();
+
+ function activate(){
+
+ manageSubjects();
+
+ manageObjects();
+
+ manageActions();
+
+ }
+
+ var rootListeners = {
+
+ 'event:deletePerimeterFromPerimeterAddSuccess': $rootScope.$on('event:deletePerimeterFromPerimeterAddSuccess', deletePolicy)
+
+ };
+
+ for (var unbind in rootListeners) {
+ $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){
+
+ console.log('objects');
+ console.log(perimeters);
+ list.objects = perimeters;
+ list.loadingObj = false;
+
+ });
+
+ }
+
+ function manageActions(){
+
+ list.loadingAct = true;
+
+ perimeterService.action.findAllFromPolicyWithCallback(list.policy.id, function(perimeters){
+
+ console.log('actions');
+ console.log(perimeters);
+ list.actions = perimeters;
+ list.loadingAct = false;
+
+ });
+
+ }
+
+
+ /**
+ * UnMap
+ */
+
+ function unMapSub(subject){
+
+ subject.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.subject_categories = _.without(policyToSend.subject_categories, subject.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findPerimeterFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ subject.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+
+ }
+
+ function unMapObj(object){
+
+ object.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.object_categories = _.without(policyToSend.object_categories, object.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findPerimeterFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ object.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+
+ }
+
+ }
+
+ function unMapAct(action){
+
+ action.loader = true;
+
+ var policyToSend = angular.copy(list.policy);
+
+ policyToSend.action_categories = _.without(policyToSend.action_categories, action.id);
+
+ policyService.update(policyToSend, updatePolicySuccess, updatePolicyError);
+
+ function updatePolicySuccess(data){
+
+ $translate('moon.policy.metarules.update.success', { policyName: list.policy.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ list.policy = policyService.findPerimeterFromPolicy(utilService.transformOne(data, 'meta_rules'));
+
+ activate();
+
+ action.loader = false;
+
+ }
+
+ function updatePolicyError(reason){
+
+ $translate('moon.policy.metarules.update.error', { policyName: list.policy.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ action.loader = false;
+
+ }
+
+ }
+
+ /**
+ * Delete
+ */
+
+ function deleteSub(subject){
+
+ subject.loader = true;
+
+ perimeterService.subject.delete(subject, deleteSubSuccess, deleteSubError);
+
+ function deleteSubSuccess(data){
+
+ $translate('moon.policy.perimeter.subject.delete.success', { subjectName: subject.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeSubFromSubList(subject);
+
+ subject.loader = false;
+
+ }
+
+ function deleteSubError(reason){
+
+ $translate('moon.policy.perimeter.subject.delete.error', { subjectName: subject.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ subject.loader = false;
+
+ }
+ }
+
+ function deleteObj(object){
+
+ object.loader = true;
+
+ perimeterService.object.delete(object, deleteObjSuccess, deleteObjError);
+
+ function deleteObjSuccess(data){
+
+ $translate('moon.policy.perimeter.object.delete.success', { objectName: object.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeObjFromObjList(object);
+
+ object.loader = false;
+
+ }
+
+ function deleteObjError(reason){
+
+ $translate('moon.policy.perimeter.object.delete.error', { objectName: object.name, reason: reason.message}).then( function(translatedValue) {
+ alertService.alertError(translatedValue);
+ });
+
+ object.loader = false;
+ }
+ }
+
+ function deleteAct(action){
+
+ action.loader = true;
+
+ perimeterService.action.delete(action, deleteActSuccess, deleteActError);
+
+ function deleteActSuccess(data){
+
+ $translate('moon.policy.perimeter.action.delete.success', { actionName: action.name }).then( function(translatedValue) {
+ alertService.alertSuccess(translatedValue);
+ });
+
+ removeActFromActList(action);
+
+ action.loader = false;
+
+ }
+
+ function deleteActError(reason){
+
+ $translate('moon.policy.perimeter.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 deletePolicy( event, policy){
+
+ list.policy = policy;
+
+ activate();
+
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html b/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html
new file mode 100644
index 00000000..3ec54239
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules-list.tpl.html
@@ -0,0 +1,102 @@
+<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.policy.rules.list.table.id">Id</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.rules.list.table.metaRule">Meta Rule</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.policy.rules.list.table.enabled">Enabled</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.policy.rules.list.table.rule">Rule</div>
+ </th>
+ </tr>
+
+ </thead>
+
+ <moon-loader ng-if="list.loadingRules"></moon-loader>
+
+ <tbody ng-if="!list.loadingRules && !list.hasRules()">
+ <tr>
+ <td colspan="2"><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 ng-bind="aRule.id"></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)">
+ <span ng-bind="aRule.meta_rule.name"></span>
+ </span>
+ </td>
+
+ <td>
+ <span ng-if="aRule.enabled" class="glyphicon glyphicon-ok"></span>
+ <span ng-if="!aRule.enabled" class="glyphicon glyphicon-remove"></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>
+
+ </tr>
+
+ </tbody>
+
+ </table>
+
+ </div>
+
+ </div>
+
+</div> \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js b/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js
new file mode 100644
index 00000000..98e1d62b
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/edit/parameter/rules/rules.list.dir.js
@@ -0,0 +1,254 @@
+(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 = [ 'NgTableParams', '$filter', 'metaRuleService', 'ruleService', 'dataService'];
+
+ function moonRulesListController( NgTableParams, $filter, metaRuleService, ruleService, dataService) {
+
+ var list = this;
+
+ list.rules = [];
+
+ list.loadingRules = true;
+
+ list.table = {};
+
+ list.getRules = getRules;
+ list.hasRules = hasRules;
+ list.refreshRules = refreshRules;
+
+ list.getMetaRuleFromRule = getMetaRuleFromRule;
+ list.getCategoryFromRuleIndex = getCategoryFromRuleIndex;
+
+ list.isRuleIndexSubjectCategory = isRuleIndexSubjectCategory;
+ list.isRuleIndexObjectCategory = isRuleIndexObjectCategory;
+ list.isRuleIndexActionCategory = isRuleIndexActionCategory;
+
+ activate();
+
+ function activate(){
+
+
+ newRulesTable();
+
+ manageRules();
+ }
+
+
+
+ function manageRules(){
+
+ ruleService.findAllFromPolicyWithCallback(list.policy.id, function(data){
+
+ console.log('rules');
+ console.log(data);
+
+ list.rules = data;
+ list.loadingRules = false;
+
+ refreshRules();
+ });
+ }
+
+
+
+
+
+ function newRulesTable() {
+
+ list.table = new NgTableParams({
+
+ page: 1, // show first page
+ count: 10, // count per page
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ 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 should be completely loaded
+ * @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();
+ }
+
+ }
+
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html b/moonv4/moon_gui/static/app/policy/edit/policy-edit-basic.tpl.html
new file mode 100644
index 00000000..f55c1d05
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/edit/policy-edit.tpl.html b/moonv4/moon_gui/static/app/policy/edit/policy-edit.tpl.html
new file mode 100644
index 00000000..550d1e4c
--- /dev/null
+++ b/moonv4/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="false" 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="false" 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="false" 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="false" policy="edit.policy" ></moon-assignments-list>
+
+ </div>
+
+ </div>
+
+</div>
diff --git a/moonv4/moon_gui/static/app/policy/edit/policy.controller.edit.js b/moonv4/moon_gui/static/app/policy/edit/policy.controller.edit.js
new file mode 100644
index 00000000..123ee58b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js b/moonv4/moon_gui/static/app/policy/edit/policy.edit.basic.dir.js
new file mode 100644
index 00000000..c32d9e69
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/policy-list.tpl.html b/moonv4/moon_gui/static/app/policy/policy-list.tpl.html
new file mode 100644
index 00000000..aeb90f0b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/policy-mapped-list.tpl.html b/moonv4/moon_gui/static/app/policy/policy-mapped-list.tpl.html
new file mode 100644
index 00000000..127dae3b
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/policy.controller.list.js b/moonv4/moon_gui/static/app/policy/policy.controller.list.js
new file mode 100644
index 00000000..dc2db2cc
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/policy/policy.mapped.list.dir.js b/moonv4/moon_gui/static/app/policy/policy.mapped.list.dir.js
new file mode 100644
index 00000000..b3becde9
--- /dev/null
+++ b/moonv4/moon_gui/static/app/policy/policy.mapped.list.dir.js
@@ -0,0 +1,203 @@
+(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){
+
+ 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
+ sorting: {
+ name: 'asc' // initial sorting
+ }
+
+ }, {
+
+ 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/moonv4/moon_gui/static/app/project/action/mapping/project-map.tpl.html b/moonv4/moon_gui/static/app/project/action/mapping/project-map.tpl.html
new file mode 100644
index 00000000..5ffd98e2
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html b/moonv4/moon_gui/static/app/project/action/mapping/project-unmap.tpl.html
new file mode 100644
index 00000000..5cc5c6dd
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/mapping/project.controller.map.js b/moonv4/moon_gui/static/app/project/action/mapping/project.controller.map.js
new file mode 100644
index 00000000..afa2bfc0
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/mapping/project.controller.unmap.js b/moonv4/moon_gui/static/app/project/action/mapping/project.controller.unmap.js
new file mode 100644
index 00000000..911b30ff
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project-add.tpl.html b/moonv4/moon_gui/static/app/project/action/project-add.tpl.html
new file mode 100644
index 00000000..a90dcfa1
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project-delete.tpl.html b/moonv4/moon_gui/static/app/project/action/project-delete.tpl.html
new file mode 100644
index 00000000..96b4f2e3
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project-view.tpl.html b/moonv4/moon_gui/static/app/project/action/project-view.tpl.html
new file mode 100644
index 00000000..3228c915
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project.controller.add.js b/moonv4/moon_gui/static/app/project/action/project.controller.add.js
new file mode 100644
index 00000000..4d12b75d
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project.controller.delete.js b/moonv4/moon_gui/static/app/project/action/project.controller.delete.js
new file mode 100644
index 00000000..4f18f8e6
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/action/project.controller.view.js b/moonv4/moon_gui/static/app/project/action/project.controller.view.js
new file mode 100644
index 00000000..fe98a507
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/project-list.tpl.html b/moonv4/moon_gui/static/app/project/project-list.tpl.html
new file mode 100644
index 00000000..82a3745e
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/project/project.controller.list.js b/moonv4/moon_gui/static/app/project/project.controller.list.js
new file mode 100644
index 00000000..b1cb2056
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/alert.service.js b/moonv4/moon_gui/static/app/services/gui/alert.service.js
new file mode 100644
index 00000000..8435eab1
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/browser.service.js b/moonv4/moon_gui/static/app/services/gui/browser.service.js
new file mode 100644
index 00000000..88c693a8
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/form.service.js b/moonv4/moon_gui/static/app/services/gui/form.service.js
new file mode 100644
index 00000000..bc137943
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/menu.service.js b/moonv4/moon_gui/static/app/services/gui/menu.service.js
new file mode 100644
index 00000000..fd90a2fa
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/security.pipeline.service.js b/moonv4/moon_gui/static/app/services/gui/security.pipeline.service.js
new file mode 100644
index 00000000..3831e487
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/util.service.js b/moonv4/moon_gui/static/app/services/gui/util.service.js
new file mode 100644
index 00000000..7274244a
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/gui/version.service.js b/moonv4/moon_gui/static/app/services/gui/version.service.js
new file mode 100644
index 00000000..5f9f2786
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/moon/model/model.service.js b/moonv4/moon_gui/static/app/services/moon/model/model.service.js
new file mode 100644
index 00000000..a676fc1a
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/moon/pdp.service.js b/moonv4/moon_gui/static/app/services/moon/pdp.service.js
new file mode 100644
index 00000000..822f7414
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js b/moonv4/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js
new file mode 100644
index 00000000..ad7d8e8b
--- /dev/null
+++ b/moonv4/moon_gui/static/app/services/moon/policy/parameters/assignements.service.js
@@ -0,0 +1,96 @@
+/**
+ * @author Samy Abdallah
+ */
+
+(function() {
+
+ 'use strict';
+
+ angular
+ .module('moon')
+ .factory('assignmentService', assignmentService);
+
+ assignmentService.$inject = ['$resource', 'REST_URI', 'utilService'];
+
+ function assignmentService($resource, REST_URI, utilService) {
+
+ var data = {
+
+ subject: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/subject_assignments/:subject_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+
+ object: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/object_assignments/:object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ action: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/action_assignments/:action_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_assignments'));
+
+ });
+
+ }
+ },
+
+ object : {
+
+ findAllFromPolicyWithCallback: function(policyId, callback){
+
+ data.object.policy.get({policy_id: policyId}).$promise.then(function(data) {
+
+ callback(utilService.transform(data, 'object_assignments'));
+
+ });
+
+ }
+ },
+
+ action : {
+
+ 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/moonv4/moon_gui/static/app/services/moon/policy/parameters/data.service.js b/moonv4/moon_gui/static/app/services/moon/policy/parameters/data.service.js
new file mode 100644
index 00000000..22f35e45
--- /dev/null
+++ b/moonv4/moon_gui/static/app/services/moon/policy/parameters/data.service.js
@@ -0,0 +1,196 @@
+/**
+ * @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/:data_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ object: {
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/object_data/:object_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/: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'));
+
+ });
+
+ },
+
+ 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);
+
+ },
+
+ 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'));
+
+ });
+
+ },
+
+ 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);
+
+ },
+
+ 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'));
+
+ });
+
+ },
+
+ 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);
+
+ },
+
+
+ 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/moonv4/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js b/moonv4/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js
new file mode 100644
index 00000000..6e929aba
--- /dev/null
+++ b/moonv4/moon_gui/static/app/services/moon/policy/parameters/perimeter.service.js
@@ -0,0 +1,419 @@
+/**
+ * @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'}
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/subjects/:subject_id', {}, {
+ get: {method: 'GET'},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+
+ object: {
+
+ perimeter: $resource(REST_URI.PERIMETERS.object + ':object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/objects/:object_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ },
+
+ action: {
+
+ perimeter: $resource(REST_URI.PERIMETERS.action + ':action_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ }),
+
+ policy: $resource(REST_URI.POLICIES + ':policy_id/actions/:action_id', {}, {
+ get: {method: 'GET', isArray: false},
+ create: {method: 'POST'},
+ remove: {method: 'DELETE'}
+ })
+
+ }
+
+ };
+
+ 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');
+
+ });
+
+ });
+
+ },
+
+ 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);
+
+ }
+ },
+
+ 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');
+
+ });
+
+ });
+
+ },
+
+ 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);
+
+ }
+ },
+
+ 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');
+
+ });
+
+ });
+
+ },
+
+ 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);
+
+ }
+ }
+
+ };
+
+ }
+})(); \ No newline at end of file
diff --git a/moonv4/moon_gui/static/app/services/moon/policy/parameters/rule.service.js b/moonv4/moon_gui/static/app/services/moon/policy/parameters/rule.service.js
new file mode 100644
index 00000000..b1a350ae
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/moon/policy/policy.service.js b/moonv4/moon_gui/static/app/services/moon/policy/policy.service.js
new file mode 100644
index 00000000..5c8ad4f5
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/moon/rule/metadata.service.js b/moonv4/moon_gui/static/app/services/moon/rule/metadata.service.js
new file mode 100644
index 00000000..659e0b30
--- /dev/null
+++ b/moonv4/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(subjectId) {
+
+ return _self.findOneReturningPromise(subjectId);
+
+ });
+
+ $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({actionId: actionId}).$promise.then(function(data) {
+
+ callback(utilService.transformOne(data, 'action_categories'));
+
+ })
+
+ },
+
+ findOneReturningPromise: function(actionId){
+
+ return data.action.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, 'action_categories');
+
+ });
+
+ });
+
+ },
+
+ 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, '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/moonv4/moon_gui/static/app/services/moon/rule/metarule.service.js b/moonv4/moon_gui/static/app/services/moon/rule/metarule.service.js
new file mode 100644
index 00000000..71a36c50
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/partner/authentication.service.js b/moonv4/moon_gui/static/app/services/partner/authentication.service.js
new file mode 100644
index 00000000..b6d3f36d
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/partner/nova.service.js b/moonv4/moon_gui/static/app/services/partner/nova.service.js
new file mode 100644
index 00000000..38e2a0fc
--- /dev/null
+++ b/moonv4/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/moonv4/moon_gui/static/app/services/partner/project.service.js b/moonv4/moon_gui/static/app/services/partner/project.service.js
new file mode 100644
index 00000000..4ec27f2e
--- /dev/null
+++ b/moonv4/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;
+ });
+
+ }
+
+ };
+
+ }
+
+})();
diff --git a/moonv4/moon_gui/static/favicon.ico b/moonv4/moon_gui/static/favicon.ico
new file mode 100755
index 00000000..a7910bf5
--- /dev/null
+++ b/moonv4/moon_gui/static/favicon.ico
Binary files differ
diff --git a/moonv4/moon_gui/static/i18n/en.json b/moonv4/moon_gui/static/i18n/en.json
new file mode 100755
index 00000000..fb0a0774
--- /dev/null
+++ b/moonv4/moon_gui/static/i18n/en.json
@@ -0,0 +1,1266 @@
+{
+ "moon": {
+ "global": {
+ "applicationName": "Moon",
+ "404": "Page not found",
+ "error": "A global error occurs: {{stacktrace}}"
+ },
+ "compatibility": {
+ "label": "Browsers compatibility",
+ "title": "Existing browsers compatibility",
+ "content": "Moon is compliant with : <ul><li>Internet Explorer 9 or +</li><li><a href=\"http://www.mozilla.org/fr/firefox/\">Firefox</a> up-to-date</li><li><a href=\"http://chrome.google.com\">Chrome</a> up-to-date</li></ul>",
+ "close": "Close"
+ },
+ "menu": {
+ "project": "Project",
+ "pdp": "PDP",
+ "logs": "Log",
+ "policy": "Policy",
+ "model":"Model"
+ },
+ "login":{
+ "title" : "Login",
+ "titlePage" : "Login page",
+ "username" : "Username",
+ "password" : "Password",
+ "login": "Login",
+ "check": {
+ "username": {
+ "required": "Username is required"
+ },
+ "password": {
+ "required": "Password is required"
+ }
+ },
+ "error" :"Unable to login into Keystone, error code : {{errorCode}}",
+ "success" : "Connection established. Welcome to Moon GUI, \"Moon is uppon cloud\""
+ },
+ "logout": {
+ "title": "Logout",
+ "success" : "Successfully logout"
+ },
+ "dashboard":{
+ "content" : "Moon:Software-Defined Security Framework"
+ },
+ "policy":{
+ "title": "Policies",
+ "list" : {
+ "search": {
+ "placeholder": "Search Policies",
+ "reset": "Reset"
+ },
+ "table" : {
+ "name":"Name",
+ "genre" : "Genre",
+ "description": "Description",
+ "loading": {
+ "category" : "Loading Category"
+ },
+ "notFound": "There is no Policy"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Add Policy",
+ "detail": "Consut",
+ "edit": "Edit",
+ "map" : "Map Policy to PDP",
+ "unmap" : "Unmap",
+ "delete": "Delete"
+ }
+ },
+ "unmap": {
+ "title": "Unmap Policy to PDP",
+ "content": "Are you sure you want to unmap PDP `{{pdpName}}` / Policy `{{policyName}}` ?",
+ "action": {
+ "unmap": "Unmap",
+ "cancel": "Cancel"
+ },
+ "error": "Unable to unmap PDP `{{pdpName}}` /Policy `{{policyName}}`",
+ "success": "PDP `{{pdpName}}` / Policy `{{policyName}}` successfully unmapped"
+ },
+ "map":{
+ "title": "Map a Policy to PDP `{{pdpName}}`",
+ "form" :{
+ "list": "List of Policies"
+ },
+ "action": {
+ "create": "Map Policy",
+ "cancel": "Cancel",
+ "new": "Create a Policy",
+ "list": "Map an existing Policy",
+ "map": "Map the selected Policy",
+ "delete" : "Delete the selected Policy"
+ },
+ "check": {
+ "policy":{
+ "required" : "Policy is required"
+ }
+ },
+ "error": "Unable to map Policy `{{policyName}}` to the PDP `{{pdpName}}`",
+ "success": "Policy `{{policyName}}` successfully mapped to the PDP `{{pdpName}}`"
+ },
+ "remove": {
+ "title": "Delete Policy",
+ "content": {
+ "query": "Are you sure you want to delete `{{policyName}}` Policy ?"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Policy `{{policyName}}`, error code : {{errorCode}}, message : \"{{message}}\"",
+ "success": "Model `{{policyName}}` successfully deleted"
+ },
+ "edit" : {
+ "title": "Policy `{{policyName}}` configuration",
+ "update" : "- update",
+ "show": {
+ "open": "( show )",
+ "close": "( close )"
+ },
+ "basic" : {
+ "title" : "Basic Information",
+ "form": {
+ "id": "Id",
+ "name": "Name",
+ "genre": "Genre",
+ "model": "Model",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Update"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "genre": {
+ "required": "Genre is required"
+ }
+ },
+ "error": "Unable to update Policy `{{policyName}}`",
+ "success": "Policy `{{policyName}}` successfully updated"
+ },
+ "perimeter": {
+ "title" : "Perimeters"
+ },
+ "data": {
+ "title" : "Data"
+ },
+ "rules" : {
+ "title" : "Rules"
+ },
+ "assignments": {
+ "title" : "Assignments"
+ }
+ },
+ "add":{
+ "title": "Add new Policy",
+ "form": {
+ "name": "Name",
+ "genre": "Genre",
+ "model": "Models",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Create Policy",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "genre": {
+ "required": "Genre is required"
+ },
+ "model": {
+ "required": "Model is required"
+ }
+ },
+ "error": "Unable to create Policy `{{policyName}}`",
+ "success": "Policy `{{policyName}}` successfully created"
+ },
+ "perimeter": {
+ "subject" : {
+ "title" : "List of associated Subjects",
+ "delete": {
+ "error" : "Unable to delete {{subjectName}} Subject, reason : {{reason}}",
+ "success": "Subject `{{subjectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Subject"
+ },
+ "notFound": "There is no Subject"
+ },
+ "object" : {
+ "title" : "List of associated Objects",
+ "delete": {
+ "error" : "Unable to delete {{objectName}} Object, reason : {{reason}}",
+ "success": "Object `{{objectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add an Object"
+ },
+ "notFound": "There is no Object"
+ },
+ "action" : {
+ "title" : "List of associated Actions",
+ "delete": {
+ "error" : "Unable to delete {{actionName}} Action, reason : {{reason}}",
+ "success": "Action `{{actionName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add an Action"
+ },
+ "notFound": "There is no Action"
+ },
+ "table": {
+ "id" : "Id",
+ "name" : "Name",
+ "description" : "Description",
+ "email" : "Email",
+ "partner":{
+ "id" : "Partner Id"
+ },
+ "action": {
+ "title": "Actions",
+ "delete": "Delete",
+ "update": "Update"
+ }
+ },
+ "edit": {
+ "name" : "Name",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "action": {
+ "list": "Map an existing",
+ "new": "Create a new",
+ "create": "Create",
+ "map": "Map the selected",
+ "delete": "Delete"
+ },
+ "create":{
+ "error": "Unable to create `{{name}}`",
+ "success": "`{{name}}` successfully created"
+ },
+ "delete":{
+ "error": "Unable to delete `{{name}}`",
+ "success": "`{{name}}` successfully deleted"
+ }
+ }
+ },
+ "data": {
+ "subject" : {
+ "title" : "List of associated Data Subjects",
+ "delete": {
+ "error" : "Unable to delete {{subjectName}} Subject, reason : {{reason}}",
+ "success": "Subject `{{subjectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Data Subject"
+ },
+ "notFound": "There is no Data Subject"
+ },
+ "object" : {
+ "title" : "List of associated Data Objects",
+ "delete": {
+ "error" : "Unable to delete {{objectName}} Object, reason : {{reason}}",
+ "success": "Object `{{objectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Data Object"
+ },
+ "notFound": "There is no Data Object"
+ },
+ "action" : {
+ "title" : "List of associated Actions",
+ "delete": {
+ "error" : "Unable to delete {{actionName}} Action, reason : {{reason}}",
+ "success": "Action `{{actionName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Data Action"
+ },
+ "notFound": "There is no Data Action"
+ },
+ "table": {
+ "category" : {
+ "id" : "Category Id",
+ "name" : "Category Name"
+ },
+ "name" : "Name",
+ "description" : "Description",
+ "action": {
+ "title": "Actions",
+ "delete": "Delete",
+ "update": "Update"
+ },
+ "loading": {
+ "category" : "Loading Category"
+ }
+ },
+ "edit": {
+ "name" : "Name",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "action": {
+ "list": "Map an existing",
+ "new": "Create a new",
+ "create": "Create",
+ "map": "Map the selected",
+ "delete": "Delete"
+ },
+ "create":{
+ "error": "Unable to create `{{name}}`",
+ "success": "`{{name}}` successfully created"
+ },
+ "delete":{
+ "error": "Unable to delete `{{name}}`",
+ "success": "`{{name}}` successfully deleted"
+ }
+ }
+ },
+ "rules": {
+ "title": "Rules",
+ "list": {
+ "search": {
+ "placeholder": "Search Rule",
+ "reset": "Reset"
+ },
+ "table": {
+ "id" : "Id",
+ "metaRule": "Meta Rule",
+ "description": "Description",
+ "enabled": "Enabled",
+ "rule": "Rule",
+ "notFound": "There is no Rule",
+ "loading": {
+ "metaRule" : "Loading Meta Rule"
+ }
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Add Rule",
+ "detail": "Consult",
+ "edit": "Edit",
+ "delete": "Delete"
+ },
+ "error": "Unable to retrieve Rule"
+ }
+ },
+ "assignments": {
+ "subject" : {
+ "title" : "List of associated Assignments Subjects",
+ "delete": {
+ "error" : "Unable to delete {{subjectName}} Subject, reason : {{reason}}",
+ "success": "Subject `{{subjectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Assignments Subject"
+ },
+ "notFound": "There is no Assignments Subject"
+ },
+ "object" : {
+ "title" : "List of associated Assignments Objects",
+ "delete": {
+ "error" : "Unable to delete {{objectName}} Object, reason : {{reason}}",
+ "success": "Object `{{objectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Assignments Object"
+ },
+ "notFound": "There is no Assignments Object"
+ },
+ "action" : {
+ "title" : "List of associated Assignments Actions",
+ "delete": {
+ "error" : "Unable to delete {{actionName}} Action, reason : {{reason}}",
+ "success": "Action `{{actionName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Assignments Action"
+ },
+ "notFound": "There is no Assignments Action"
+ },
+ "table": {
+ "action": {
+ "title": "Actions",
+ "delete": "Delete",
+ "update": "Update"
+ },
+ "perimeter": {
+ "name" : "Perimeter name"
+ },
+ "data": {
+ "name": "Data name"
+ },
+ "category": {
+ "name" : "Category name"
+ },
+ "loading": {
+ "category" : "Loading Category",
+ "perimeter": "Loading Perimeter",
+ "data": "Loading Data"
+ }
+ },
+ "edit": {
+ "name" : "Name",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "action": {
+ "list": "Map an existing",
+ "new": "Create a new",
+ "create": "Create",
+ "map": "Map the selected",
+ "delete": "Delete"
+ },
+ "create":{
+ "error": "Unable to create `{{name}}`",
+ "success": "`{{name}}` successfully created"
+ },
+ "delete":{
+ "error": "Unable to delete `{{name}}`",
+ "success": "`{{name}}` successfully deleted"
+ }
+ }
+ }
+ },
+ "model":{
+ "title": "Models",
+ "list": {
+ "search": {
+ "placeholder": "Search Model",
+ "reset": "Reset"
+ },
+ "table":{
+ "name":"Name",
+ "description": "Description",
+ "metaRules":{
+ "number" : "Number of Meta Rules"
+ },
+ "notFound": "There is no Models"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Add Model",
+ "detail": "Consult",
+ "edit": "Edit",
+ "delete": "Delete"
+ },
+ "error": "Unable to retrieve Models"
+ },
+ "edit" : {
+ "title": "Model `{{modelName}}` configuration",
+ "update" : "- update",
+ "basic" : {
+ "title" : "Basic Information",
+ "form": {
+ "id": "Id",
+ "name": "Name",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Update"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to update Model `{{modelName}}`",
+ "success": "Model `{{modelName}}` successfully updated"
+ },
+ "metarules": {
+ "title" : "Meta Rules"
+ }
+ },
+ "view": {
+ "title": "Model `{{modelName}}` details",
+ "name": "Name",
+ "id": "Id",
+ "description": "Description",
+ "action": {
+ "close": "Close"
+ }
+ },
+ "remove": {
+ "title": "Delete Model",
+ "content": {
+ "query": "Are you sure you want to delete `{{modelName}}` Model ?"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Model `{{modelName}}`, error code : {{errorCode}}, message : \"{{message}}\"",
+ "success": "Model `{{modelName}}` successfully deleted"
+ },
+ "metarules": {
+ "title": "List of Meta Rules",
+ "table": {
+ "name":"Name",
+ "description": "Description",
+ "metadata": {
+ "subject": {
+ "number": "Number of Subject Categories"
+ },
+ "object" : {
+ "number": "Number of Object Categories"
+ },
+ "action": {
+ "number": "Number of Action Categories"
+ }
+ },
+ "notFound": "There is no Meta Rules"
+ },
+ "edit" : {
+ "title" : "Meta Rule `{{metaRuleName}}` configuration",
+ "update": "- update",
+ "basic": {
+ "title": "Basic Information",
+ "form": {
+ "id": "Id",
+ "name": "Name",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Update"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to update Meta Rule `{{metaRuleName}}`",
+ "success": "Meta Rule `{{metaRuleName}}` successfully updated"
+ }
+ },
+ "update":{
+ "error": "Unable to update Meta Rule `{{metaRuleName}}`",
+ "success": "Meta Rule `{{metaRuleName}}` successfully updated"
+ },
+ "action": {
+ "title": "Actions",
+ "edit": "Edit",
+ "remove": "Remove",
+ "settings" : "Settings",
+ "add": "Add",
+ "detail": {
+ "open": "Consult",
+ "close": "Close"
+ }
+ },
+ "add": {
+ "title": "Add new Meta Rule",
+ "form": {
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Add Meta Rule",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to create Meta Rule `{{metaRuleName}}`",
+ "success": "Meta Rule `{{metaRuleName}}` successfully created"
+ },
+ "map":{
+ "title": "Add a Meta Rule",
+ "form" :{
+ "list": "List of Meta Rules"
+ },
+ "action": {
+ "create": "Add a new Meta Rule",
+ "cancel": "Cancel",
+ "new": "Add a Meta Rule",
+ "list": "Add an existing Meta Rule",
+ "add": "Add the selected Meta Rule",
+ "delete" : "Delete the selected Meta Rule"
+ },
+ "error": "Unable to map Model `{{modelName}}` to the Meta Rule `{{metaRuleName}}`",
+ "success": "Model `{{modelName}}` successfully mapped to the Meta Rule `{{metaRuleName}}`"
+ },
+ "unmap": {
+ "title": "Remove Meta Rule to Model",
+ "content": "Are you sure you want to remove Model `{{modelName}}` / Meta Rule `{{metaRuleName}}` ?",
+ "action": {
+ "unmap": "Remove",
+ "cancel": "Cancel"
+ },
+ "error": "Unable to remove Model `{{modelName}}` / Meta Rule `{{metaRuleName}}`",
+ "success": "Model `{{modelName}}` / Meta Rule `{{metaRuleName}}` successfully removed"
+ },
+ "delete":{
+ "error": "Unable to delete Meta Rule `{{metaRuleName}}`",
+ "success": "Meta Rule `{{metaRuleName}}` successfully deleted"
+ }
+ },
+ "metadata": {
+ "subject" : {
+ "title" : "List of associated Subject Categories",
+ "delete": {
+ "error" : "Unable to delete {{subjectName}} Subject, reason : {{reason}}",
+ "success": "Subject `{{subjectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add a Subject Category"
+ },
+ "notFound": "There is no Subject"
+ },
+ "object" : {
+ "title" : "List of associated Object Categories",
+ "delete": {
+ "error" : "Unable to delete {{objectName}} Object, reason : {{reason}}",
+ "success": "Object `{{objectName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add an Object Category"
+ },
+ "notFound": "There is no Object"
+ },
+ "action" : {
+ "title" : "List of associated Action Categories",
+ "remove": "Remove",
+ "delete": {
+ "error" : "Unable to delete {{actionName}} Action, reason : {{reason}}",
+ "success": "Action `{{actionName}}` successfully deleted"
+ },
+ "add": {
+ "title": "Add an Action Category"
+ },
+ "notFound": "There is no Action"
+ },
+ "table": {
+ "id" : "Id",
+ "name" : "Name",
+ "description" : "Description",
+ "action": {
+ "title": "Actions",
+ "delete": "Delete",
+ "update": "Update"
+ }
+ },
+ "edit": {
+ "name" : "Name",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "action": {
+ "list": "Add an existing Category",
+ "new": "Add a new Category",
+ "create": "Add Category",
+ "add": "Add the selected Category",
+ "delete": "Delete"
+ },
+ "create":{
+ "error": "Unable to create Category `{{name}}`",
+ "success": "Category `{{name}}` successfully created"
+ },
+ "delete":{
+ "error": "Unable to delete Category `{{name}}`",
+ "success": "Category `{{name}}` successfully deleted"
+ }
+ }
+ },
+ "add":{
+ "title": "Add new Model",
+ "form": {
+ "name": "Name",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Create Model",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to create Model `{{modelName}}`",
+ "success": "Model `{{modelName}}` successfully created"
+ }
+ },
+ "project": {
+ "title": "Projects",
+ "list": {
+ "search": {
+ "placeholder": "Search Projects",
+ "reset": "Reset"
+ },
+ "table": {
+ "name": "Name",
+ "domain": "Domain",
+ "managed": "Managed",
+ "enabled": "Enabled",
+ "description": "Description",
+ "mapping": "PDP",
+ "loading": {
+ "project": "Loading Projects",
+ "pdp": "Loading PDP"
+ },
+ "notFound": "There is no Projects"
+ },
+ "action": {
+ "title": "Actions",
+ "detail": "Consult",
+ "delete": "Delete",
+ "add": "Add Project",
+ "map": "Map to a PDP",
+ "unmap": "Unmap"
+ },
+ "error": "Unable to retrieve Projects"
+ },
+ "view": {
+ "title": "Project `{{projectName}}` details",
+ "action": {
+ "close": "Close"
+ },
+ "subject": {
+ "title": "Subjects",
+ "name": "Name",
+ "mail": "Email",
+ "domain": "Domain",
+ "enabled": "Enabled",
+ "error": "Unable to retrieve Subjects"
+ },
+ "object": {
+ "title": "Objects",
+ "category": "Category",
+ "description": "Description",
+ "enabled": "Enabled",
+ "name": "Name",
+ "error": "Unable to retrieve Objects",
+ "loading": "Loading Objects",
+ "notFound": "There is no Objects"
+ },
+ "role": {
+ "title": "Roles",
+ "category": "Category",
+ "value": "Value",
+ "description": "Description",
+ "assigned": "Assigned",
+ "enabled": "Enabled",
+ "error": "Unable to retrieve Roles",
+ "loading": "Loading Roles",
+ "notFound": "There is no Roles"
+ },
+ "roleAssignment": {
+ "title": "Role Assignments",
+ "category": "Category",
+ "attributes": "Attributes",
+ "description": "Description",
+ "error": "Unable to retrieve Role Assignments",
+ "loading": "Loading Role Assignments",
+ "notFound": "There is no Role Assignments"
+ },
+ "group": {
+ "title": "Groups",
+ "category": "Category",
+ "value": "Value",
+ "description": "Description",
+ "assigned": "Assigned",
+ "enabled": "Enabled",
+ "error": "Unable to retrieve Groups",
+ "loading": "Loading Groups",
+ "notFound": "There is no Groups"
+ },
+ "groupAssignment": {
+ "title": "Group Assignments",
+ "category": "Category",
+ "attributes": "Attributes",
+ "description": "Description",
+ "error": "Unable to retrieve Group Assignments",
+ "loading": "Loading Group Assignments",
+ "notFound": "There is no Group Assignments"
+ }
+ },
+ "add": {
+ "title": "Add new Project",
+ "form": {
+ "name": "Name",
+ "description": "Description",
+ "enabled": "Enabled",
+ "domain": "Domain"
+ },
+ "action": {
+ "create": "Create Project",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "domain": {
+ "required": "Domain is required"
+ }
+ },
+ "error": "Unable to create Project `{{projectName}}`",
+ "success": "Project `{{projectName}}` successfully created"
+ },
+ "remove": {
+ "title": "Delete Project",
+ "content": {
+ "query": "Are you sure you want to delete `{{projectName}}` Project ?",
+ "isNotMapped": "This Project is not mapped to any PDP",
+ "isMapped": "This project is mapped to `{{pdpName}}` PDP, delete this Project, will remove the mapping."
+ },
+ "mapping":{
+ "remove":{
+ "error": "Unable to remove mapping with Pdp : `{{pdpName}}`"
+ }
+ },
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Project `{{projectName}}`, error code : {{errorCode}}, message : \"{{message}}\"",
+ "success": "Project `{{projectName}}` successfully deleted"
+ },
+ "map": {
+ "title": "Map Project `{{projectName}}` to a PDP",
+ "form": {
+ "pdp": "PDP"
+ },
+ "action": {
+ "map": "Map",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "pdp": {
+ "required": "PDP is required"
+ }
+ },
+ "error": "Unable to map Project `{{projectName}}` to a PDP `{{pdpName}}`",
+ "success": "Project `{{projectName}}` successfully mapped to a PDP `{{pdpName}}`"
+ },
+ "unmap": {
+ "title": "Unmap Project and PDP",
+ "content": "Are you sure you want to unmap Project `{{projectName}}` / PDP `{{pdpName}}` ?",
+ "action": {
+ "unmap": "Unmap",
+ "cancel": "Cancel"
+ },
+ "error": "Unable to unmap Project `{{projectName}}` / PDP `{{pdpName}}`",
+ "success": "Project `{{projectName}}` / PDP `{{pdpName}}` successfully unmapped"
+ }
+ },
+ "pdp": {
+ "title": "PDPs",
+ "edit" : {
+ "title": "Pdp `{{pdpName}}` configuration",
+ "update" : "- update",
+ "basic" : {
+ "title" : "Basic Information",
+ "form": {
+ "id": "Id",
+ "name": "Name",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Update"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to update PDP `{{pdpName}}`",
+ "success": "PDP `{{pdpName}}` successfully updated"
+ },
+ "policy": {
+ "title" : "Policies"
+ }
+ },
+ "list": {
+ "search": {
+ "placeholder": "Search PDPs",
+ "reset": "Reset"
+ },
+ "table": {
+ "name": "Name",
+ "security_pipeline":{
+ "number" : "Number of Securities"
+ },
+ "project": "Project",
+ "loading": {
+ "pdp": "Loading PDPs",
+ "project": "Loading Project"
+ },
+ "mapping" :{
+ "map": "Is not mapped"
+ },
+ "notFound": "There is no PDPs"
+ },
+ "action": {
+ "title": "Actions",
+ "detail": "Consult",
+ "configure": "Configure",
+ "rule": "Rules",
+ "delete": "Delete",
+ "add": "Add PDP",
+ "edit":"Editer"
+ },
+ "error": "Unable to retrieve PDPs"
+ },
+ "add": {
+ "title": "Add new PDP",
+ "form": {
+ "name": "Name",
+ "policy": "Policy",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Create PDP",
+ "cancel": "Cancel"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "policy": {
+ "required": "Policy is required"
+ }
+ },
+ "error": "Unable to create PDP `{{pdpName}}`",
+ "success": "PDP `{{pdpName}}` successfully created"
+ },
+ "remove": {
+ "title": "Delete PDP",
+ "content": "Are you sure you want to delete `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete PDP `{{pdpName}}`",
+ "success": "PDP `{{pdpName}}` successfully deleted"
+ },
+ "configure": {
+ "title": "PDP `{{pdpName}}` configuration",
+ "action": {
+ "back": "Back to PDPs"
+ },
+ "subject": {
+ "panelTitle": "Subjects configuration",
+ "title": "Subjects",
+ "add": {
+ "title": "Add new Subject",
+ "form": {
+ "name": "Name",
+ "domain": "Domain",
+ "enabled": "Enabled",
+ "project": "Project",
+ "password": "Password",
+ "description": "Description"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Subject"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "domain": {
+ "required": "Domain is required"
+ },
+ "project": {
+ "required": "Project is required"
+ },
+ "password": {
+ "required": "Password is required"
+ }
+ },
+ "error": "Unable to add Subject `{{subjectName}}`",
+ "success": "Subject `{{subjectName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Subject",
+ "content": "Are you sure you want to delete `{{subjectName}}` subject of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Subject `{{subjectName}}`",
+ "success": "Subject `{{subjectName}}` successfully deleted"
+ },
+ "category": {
+ "title": "Categories",
+ "add": {
+ "title": "Add new Category",
+ "form": {
+ "name": "Name"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Category"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to add Subject Category `{{categoryName}}`",
+ "success": "Subject Category `{{categoryName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Category",
+ "content": "Are you sure you want to delete `{{categoryName}}` subject category of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Subject Category `{{categoryName}}`",
+ "success": "Subject Category `{{categoryName}}` successfully deleted"
+ }
+ },
+ "categoryValue": {
+ "title": "Values",
+ "add": {
+ "title": "Add new Value",
+ "form": {
+ "value": "Value"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Value"
+ },
+ "check": {
+ "value": {
+ "required": "Value is required"
+ }
+ },
+ "error": "Unable to add Subject Category Value`{{valueName}}`",
+ "success": "Subject Category Value `{{valueName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Value",
+ "content": "Are you sure you want to delete `{{valueName}}` subject category value of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Subject Category Value `{{valueName}}`",
+ "success": "Subject Category Value `{{valueName}}` successfully deleted"
+ }
+ },
+ "assignment": {
+ "title": "Subject Assignments",
+ "action": {
+ "assign": "Assign",
+ "unassign": "Unassign"
+ },
+ "list": {
+ "notFound": "There is no assignments"
+ },
+ "add": {
+ "error": "Unable to assign Subject `{{subjectName}}` / Category `{{categoryName}}` / Value `{{valueName}}`",
+ "success": "Subject `{{subjectName}}` / Category `{{categoryName}}` / Value `{{valueName}}` assignment successfully done"
+ },
+ "remove": {
+ "error": "Unable to unassign Subject `{{subjectName}}` / Category `{{categoryName}}` / Value `{{valueName}}`",
+ "success": "Subject `{{subjectName}}` / Category `{{categoryName}}` / Value `{{valueName}}` unassignment successfully done"
+ }
+ }
+ },
+ "object": {
+ "panelTitle": "Objects configuration",
+ "title": "Objects",
+ "add": {
+ "title": "Add new Object",
+ "form": {
+ "name": "Name",
+ "image": "Image",
+ "flavor": "Flavor"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Object"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ },
+ "image": {
+ "required": "Image is required"
+ },
+ "flavor": {
+ "required": "Flavor is required"
+ }
+ },
+ "error": "Unable to add Object `{{objectName}}`",
+ "success": "Object `{{objectName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Object",
+ "content": "Are you sure you want to delete `{{objectName}}` object of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Object `{{objectName}}`",
+ "success": "Object `{{objectName}}` successfully deleted"
+ },
+ "category": {
+ "title": "Categories",
+ "add": {
+ "title": "Add new Category",
+ "form": {
+ "name": "Name"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Category"
+ },
+ "check": {
+ "name": {
+ "required": "Name is required"
+ }
+ },
+ "error": "Unable to add Object Category `{{categoryName}}`",
+ "success": "Object Category `{{categoryName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Category",
+ "content": "Are you sure you want to delete `{{categoryName}}` object category of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Object Category `{{categoryName}}`",
+ "success": "Object Category `{{categoryName}}` successfully deleted"
+ }
+ },
+ "categoryValue": {
+ "title": "Values",
+ "add": {
+ "title": "Add new Value",
+ "form": {
+ "value": "Value"
+ },
+ "action": {
+ "cancel": "Cancel",
+ "add": "Add Value"
+ },
+ "check": {
+ "value": {
+ "required": "Value is required"
+ }
+ },
+ "error": "Unable to add Object Category Value`{{valueName}}`",
+ "success": "Object Category Value `{{valueName}}` successfully added"
+ },
+ "remove": {
+ "title": "Delete Value",
+ "content": "Are you sure you want to delete `{{valueName}}` object category value of `{{pdpName}}` PDP ?",
+ "action": {
+ "cancel": "Cancel",
+ "delete": "Delete"
+ },
+ "error": "Unable to delete Object Category Value `{{valueName}}`",
+ "success": "Object Category Value `{{valueName}}` successfully deleted"
+ }
+ },
+ "assignment": {
+ "title": "Object Assignments",
+ "action": {
+ "assign": "Assign",
+ "unassign": "Unassign"
+ },
+ "list": {
+ "notFound": "There is no assignments"
+ },
+ "add": {
+ "error": "Unable to assign Object `{{objectName}}` / Category `{{categoryName}}` / Value `{{valueName}}`",
+ "success": "Object `{{objectName}}` / Category `{{categoryName}}` / Value `{{valueName}}` assignment successfully done"
+ },
+ "remove": {
+ "error": "Unable to unassign Object `{{ObjectName}}` / Category `{{categoryName}}` / Value `{{valueName}}`",
+ "success": "Object `{{objectName}}` / Category `{{categoryName}}` / Value `{{valueName}}` unassignment successfully done"
+ }
+ }
+ }
+ },
+ "rule": {
+ "title": "PDP `{{pdpName}}` rules",
+ "list": {
+ "table": {
+ "subject": "Subjects",
+ "object": "Objects",
+ "notFound": "There is no Rules"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Add Rule",
+ "delete": "Delete Rule"
+ }
+ },
+ "add": {
+ "title": "Add new Rule",
+ "action": {
+ "create": "Create Rule",
+ "cancel": "Cancel"
+ },
+ "form": {
+ "subject": {
+ "subject": "Subjects",
+ "category": "Categories",
+ "categoryValue": "Values",
+ "action": {
+ "add": "Add",
+ "delete": "Delete"
+ }
+ },
+ "object": {
+ "object": "Objects",
+ "category": "Categories",
+ "categoryValue": "Values",
+ "action": {
+ "add": "Add",
+ "delete": "Delete"
+ }
+ }
+ },
+ "success": "Rule successfully created",
+ "error": "Unable to create Rule"
+ },
+ "delete": {
+ "title": "Delete Rule",
+ "content": "Are you sure you want to delete rule `{{ruleJson}}` of `{{pdpName}}` PDP ?",
+ "action": {
+ "delete": "Delete Rule",
+ "cancel": "Cancel"
+ },
+ "error": "Unable to delete Rule `{{ruleJson}}`",
+ "success": "Rule `{{ruleJson}}` successfully deleted"
+ },
+ "action": {
+ "back": "Back to PDPs"
+ }
+ }
+ }
+ }
+}
diff --git a/moonv4/moon_gui/static/i18n/fr.json b/moonv4/moon_gui/static/i18n/fr.json
new file mode 100755
index 00000000..957fbac5
--- /dev/null
+++ b/moonv4/moon_gui/static/i18n/fr.json
@@ -0,0 +1,1266 @@
+{
+ "moon": {
+ "global": {
+ "applicationName": "Moon",
+ "404": "Page non trouvée",
+ "error": "Une erreur globale est survenue: {{stacktrace}}"
+ },
+ "compatibility": {
+ "label": "Compatibilité navigateurs Web",
+ "title": "Compatibilité avec les navigateurs existants",
+ "content": "Moon est compatible avec : <ul><li>Internet Explorer 9 ou +</li><li><a href=\"http://www.mozilla.org/fr/firefox/\">Firefox</a> à jour</li><li><a href=\"http://chrome.google.com\">Chrome</a> à jour</li></ul>",
+ "close": "Fermer"
+ },
+ "menu": {
+ "project": "Project",
+ "pdp": "PDP",
+ "logs": "Log",
+ "policy": "Politique",
+ "model": "Modèle"
+ },
+ "login":{
+ "title":"Connexion",
+ "titlePage" : "Page d'idenditifcation",
+ "username" : "Nom d'utilisateur",
+ "password" : "Mot de passe",
+ "login" : "Connexion",
+ "check": {
+ "username": {
+ "required": "Le nom d'utilisateur est requis"
+ },
+ "password": {
+ "required": "Le mot de passe est requis"
+ }
+ },
+ "error" : "Impossible de se connecter à Keystone, code d'erreur {{errorCode}}",
+ "success" : "Connexion établie, Bienvenue sur la GUI de Moon, \"La lune est au dessus des nuages\""
+ },
+ "logout": {
+ "title": "Déconnexion",
+ "success" : "Déconnxion réussie"
+ },
+ "dashboard":{
+ "content" : "Moon:Software-Defined Security Framework"
+ },
+ "policy": {
+ "title": "Politiques",
+ "list" : {
+ "search": {
+ "placeholder": "Rechercher des Politiques",
+ "reset": "Effacer"
+ },
+ "table" : {
+ "name":"Nom",
+ "genre" : "Genre",
+ "description": "Description",
+ "loading": {
+ "category" : "Chargement de la Catégorie"
+ },
+ "notFound": "Il n'existe aucune Politique"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Ajouter une Politique",
+ "detail": "Consulter",
+ "edit": "Editer",
+ "map" : "Associer une Politique à la PDP",
+ "unmap" : "Dissocier",
+ "delete": "Supprimer"
+ }
+ },
+ "unmap": {
+ "title": "Dissociation de la Policy et de la PDP",
+ "content": "Voulez-vous dissocier la PDP `{{pdpName}}` et la Policy `{{policyName}}` ?",
+ "action": {
+ "unmap": "Dissocier",
+ "cancel": "Annuler"
+ },
+ "error": "Impossible de dissocier la PDP `{{pdpName}}` et la Policy`{{policyName}}`",
+ "success": "La dissociation de la PDP `{{pdpName}}` et de la Policy `{{policyName}}` a été effectuée avec succès"
+ },
+ "map":{
+ "title": "Associer une Politique à la PDP `{{pdpName}}`",
+ "form" :{
+ "list": "Liste des Politiques"
+ },
+ "action": {
+ "create": "Associer une Politique",
+ "cancel": "Fermer",
+ "new": "Créer une Politique",
+ "list": "Associer une Politique existante",
+ "map": "Associer la Politique sélectionnée",
+ "delete" : "Supprimer la Politique sélectionnée"
+ },
+ "check": {
+ "policy":{
+ "required" : "La politique est requise"
+ }
+ },
+ "error": "Impossible d'associer la Politique `{{policyName}}` à la PDP `{{pdpName}}`",
+ "success": "L'association dde la Politique `{{policyName}}` avec la PDP `{{pdpName}}` a été effectuée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une Politique",
+ "content": {
+ "query": "Voulez-vous supprimer la Politique `{{policyName}}` ?"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la Politique `{{policyName}}`",
+ "success": "La Politique `{{policyName}}` a été supprimée avec succès"
+ },
+ "edit" : {
+ "title": "Configuration de la Politique `{{policyName}}`",
+ "update": "- mettre à jour",
+ "show": {
+ "open": "( voir )",
+ "close": "( fermer )"
+ },
+ "basic" : {
+ "title" : "Informations de base",
+ "form": {
+ "id": "Id",
+ "name": "Nom",
+ "genre": "Genre",
+ "model": "Modèle",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Mettre à Jour"
+ },
+ "check": {
+ "name": {
+ "required": "Le Nom est requis"
+ },
+ "Genre": {
+ "required": "Le Genre est requis"
+ }
+ },
+ "error": "Impossible de mettre à jour la Politique `{{policyName}}`",
+ "success": "Le Politique `{{policyName}}` a été mise à jour avec succès"
+ },
+ "perimeter": {
+ "title" : "Périmètres"
+ },
+ "data": {
+ "title" : "Données"
+ },
+ "rules" : {
+ "title" : "Règles"
+ },
+ "assignments": {
+ "title" : "Affectations"
+ }
+ },
+ "add": {
+ "title": "Ajouter une nouvelle Politique",
+ "form": {
+ "name": "Nom",
+ "genre" : "Genre",
+ "model": "Modèles",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Créer la Politique",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ },
+ "genre" : {
+ "required" :"Le Genre est requis"
+ },
+ "model" : {
+ "required" :"Un Modèle est requis"
+ }
+ },
+ "error": "Impossible de créer la Politique `{{policyName}}`",
+ "success": "La Politique `{{policyName}}` a été créée avec succès"
+ },
+ "perimeter" :{
+ "subject" : {
+ "title" : "Liste des Sujets associées",
+ "delete": {
+ "error" : "Impossible de supprimer le Sujet : {{subjectName}}, la raison : {{reason}}",
+ "success": "Sujet `{{subjectName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Element Sujet"
+ },
+ "notFound": "Il n'existe aucun Sujet"
+ },
+ "object" : {
+ "title" : "Liste des Objets associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Objet : {{objectName}}, la raison : {{reason}}",
+ "success": "Objet `{{objectName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Element Objet"
+ },
+ "notFound": "Il n'existe aucun Objet"
+ },
+ "action" : {
+ "title" : "Liste des Actions associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Action : {{actionName}}, la raison : {{reason}}",
+ "success": "Action `{{actionName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Element Action"
+ },
+ "notFound": "Il n'existe aucune Action"
+ },
+ "table": {
+ "id" : "Id",
+ "name" : "Nom",
+ "description" : "Description",
+ "email" : "Email",
+ "partner":{
+ "id" : "Id du Partenaire"
+ },
+ "action": {
+ "title": "Actions",
+ "delete": "Supprimer",
+ "update": "Mettre à jour"
+ }
+ },
+ "edit": {
+ "name" : "Nom",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "action": {
+ "list": "Associer un Element existante",
+ "new": "Créer une nouvelle Element",
+ "create":"Créer l'Element",
+ "map":"Asscoier l'Element selectionnée",
+ "delete": "Supprimer"
+ },
+ "create": {
+ "error": "Impossible de créer l'Element `{{name}}`",
+ "success": "L'Element `{{name}}` a été créé avec succès"
+ },
+ "delete": {
+ "error": "Impossible de supprimer la Element `{{name}}`",
+ "success": "L'Element `{{name}}` a été supprimée avec succès"
+ }
+ }
+ },
+ "data" :{
+ "subject" : {
+ "title" : "Liste des Data Sujets associées",
+ "delete": {
+ "error" : "Impossible de supprimer la Data Sujet : {{subjectName}}, la raison : {{reason}}",
+ "success": "Data Sujet `{{subjectName}}` a été supprimée avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Data Sujet"
+ },
+ "notFound": "Il n'existe aucune Data Sujet"
+ },
+ "object" : {
+ "title" : "Liste des Data Objets associées",
+ "delete": {
+ "error" : "Impossible de supprimer la Data Objet : {{objectName}}, la raison : {{reason}}",
+ "success": "Data Objet `{{objectName}}` a été supprimée avec succès"
+ },
+ "add": {
+ "title": "Ajouter un Data Objet"
+ },
+ "notFound": "Il n'existe aucun Data Objet"
+ },
+ "action" : {
+ "title" : "Liste des Data Actions associées",
+ "delete": {
+ "error" : "Impossible de supprimer la Data Action : {{actionName}}, la raison : {{reason}}",
+ "success": "Data Action `{{actionName}}` a été supprimée avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Data Action"
+ },
+ "notFound": "Il n'existe aucune Data Action"
+ },
+ "table": {
+ "category" : {
+ "id" : "Id de la Catégorie",
+ "name" : "Nom de la Catégorie"
+ },
+ "name" : "Nom",
+ "description" : "Description",
+ "action": {
+ "title": "Actions",
+ "delete": "Supprimer",
+ "update": "Mettre à jour"
+ },
+ "loading": {
+ "category" : "Loading Catégorie"
+ }
+ },
+ "edit": {
+ "name" : "Nom",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "action": {
+ "list": "Associer un Element existante",
+ "new": "Créer une nouvelle Element",
+ "create":"Créer l'Element",
+ "map":"Asscoier l'Element selectionnée",
+ "delete": "Supprimer"
+ },
+ "create": {
+ "error": "Impossible de créer l'Element `{{name}}`",
+ "success": "L'Element `{{name}}` a été créé avec succès"
+ },
+ "delete": {
+ "error": "Impossible de supprimer la Element `{{name}}`",
+ "success": "L'Element `{{name}}` a été supprimée avec succès"
+ }
+ }
+ },
+ "rules": {
+ "title": "Règles",
+ "list": {
+ "search": {
+ "placeholder": "Rechercher des Règles",
+ "reset": "Effacer"
+ },
+ "table": {
+ "id" : "Id",
+ "metaRule": "Meta Règle",
+ "description": "Description",
+ "enabled": "Enabled",
+ "rule": "Règle",
+ "notFound": "Il n'existe aucune Règle",
+ "loading": {
+ "metaRule" : "Chargement de la Meta Règle"
+ }
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Ajouter une Règle",
+ "detail": "Consulter",
+ "edit": "Editer",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de récupérer la liste des Règles"
+ }
+ },
+ "assignments" :{
+ "subject" : {
+ "title" : "Liste des Affectations Sujets associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Affectations Sujet : {{subjectName}}, la raison : {{reason}}",
+ "success": "Affectations Sujet `{{subjectName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Affectations Sujet"
+ },
+ "notFound": "Il n'existe aucune Affectations Sujet"
+ },
+ "object" : {
+ "title" : "Liste des Affectations Objets associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Affectations Objet : {{objectName}}, la raison : {{reason}}",
+ "success": "Affectations Objet `{{objectName}}` a été supprimée avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Affectations Objet"
+ },
+ "notFound": "Il n'existe aucune Affectations Objet"
+ },
+ "action" : {
+ "title" : "Liste des Affectations Actions associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Affectations Action : {{actionName}}, la raison : {{reason}}",
+ "success": "Affectations Action `{{actionName}}` a été supprimée avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Affectations Action"
+ },
+ "notFound": "Il n'existe aucune Affectations Action"
+ },
+ "table": {
+ "action": {
+ "title": "Actions",
+ "delete": "Supprimer",
+ "update": "Mettre à jour"
+ },
+ "perimeter": {
+ "name": "Nom du Périmètre"
+ },
+ "data":{
+ "name" : "Nom des Data"
+ },
+ "category": {
+ "name" : "Nom de la Catégorie"
+ },
+ "loading": {
+ "category" : "Chargement de la Catégorie",
+ "perimeter": "Chargement du Périmètre",
+ "data": "Chargement des Données"
+ }
+ },
+ "edit": {
+ "name" : "Nom",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "action": {
+ "list": "Associer une Affectations existante",
+ "new": "Créer une nouvelle Affectations",
+ "create":"Créer l'Affectations",
+ "map":"Asscoier l'Affectations selectionnée",
+ "delete": "Supprimer"
+ },
+ "create": {
+ "error": "Impossible de créer l'Affectations `{{name}}`",
+ "success": "L'Affectations `{{name}}` a été créé avec succès"
+ },
+ "delete": {
+ "error": "Impossible de supprimer l'Affectations `{{name}}`",
+ "success": "L'Affectations `{{name}}` a été supprimée avec succès"
+ }
+ }
+ }
+ },
+ "model":{
+ "title": "Modèles",
+ "list": {
+ "search": {
+ "placeholder": "Rechercher des Modèles",
+ "reset": "Effacer"
+ },
+ "table":{
+ "name":"Nom",
+ "description": "Description",
+ "metaRules":{
+ "number" : "Nombre de Meta Règles"
+ },
+ "notFound": "Il n'existe aucun Modèle"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Ajouter un modèle",
+ "detail": "Consulter",
+ "edit": "Editer",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de récupérer la liste des Modèles"
+ },
+ "edit" : {
+ "title": "Configuration du Modèle `{{modelName}}`",
+ "update": "- mettre à jour",
+ "basic" : {
+ "title" : "Informations de base",
+ "form": {
+ "id": "Id",
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Mettre à Jour"
+ },
+ "check": {
+ "name": {
+ "required": "Le Nom est requis"
+ }
+ },
+ "error": "Impossible de mettre à jour le Modèle `{{modelName}}`",
+ "success": "Le Modèle `{{modelName}}` a été mis à jour avec succès"
+ },
+ "metarules": {
+ "title" : "Meta Règles"
+ }
+ },
+ "view": {
+ "title": "Détail du Modèle `{{modelName}}`",
+ "name": "Name",
+ "id": "Id",
+ "description": "Description",
+ "action": {
+ "close": "Fermer"
+ }
+ },
+ "remove": {
+ "title": "Supprimer un Modèle",
+ "content": {
+ "query": "Voulez-vous supprimer le Modèle `{{modelName}}` ?"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer le Modèle `{{modelName}}`",
+ "success": "Le Modèle `{{modelName}}` a été supprimé avec succès"
+ },
+ "metarules" :{
+ "title" : "List des Meta Règles",
+ "table":{
+ "name":"Nom",
+ "description": "Description",
+ "metadata": {
+ "subject" : {
+ "number" : "Nombre de Catégories Sujet"
+ },
+ "object" : {
+ "number" : "Nombre de Catégories Objet"
+ },
+ "action" : {
+ "number" : "Nombre de Catégories Action"
+ }
+ },
+ "notFound": "Il n'existe aucune Meta Règles"
+ },
+ "edit" : {
+ "title" : "Configuration de la Meta Règle `{{metaRuleName}}`",
+ "update": "- mettre à jour",
+ "basic" : {
+ "title" : "Informations de base",
+ "form": {
+ "id": "Id",
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Mettre à Jour"
+ },
+ "check": {
+ "name": {
+ "required": "Le Nom est requis"
+ }
+ },
+ "error": "Impossible de mettre à jour la Meta Règle `{{metaRuleName}}`",
+ "success": "La Meta Règle `{{metaRuleName}}` a été mis à jour avec succès"
+ }
+ },
+ "update":{
+ "error": "Impossible de mettre à jour la Meta Règle `{{metaRuleName}}`",
+ "success": "La Meta Règle `{{metaRuleName}}` a été mis à jour avec succès"
+ },
+ "action": {
+ "title": "Actions",
+ "edit": "Editer",
+ "remove": "Enlever",
+ "settings" : "Paramètres",
+ "add": "Ajouter",
+ "detail": {
+ "open": "Consulter",
+ "close": "Fermer"
+ }
+ },
+ "add":{
+ "title": "Ajouter une nouvelle Meta Règle",
+ "form": {
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Ajouter la Meta Règle",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "error": "Impossible de créer la Meta Règle `{{metaRuleName}}`",
+ "success": "La Meta Règle `{{metaRuleName}}` a été créée avec succès"
+ },
+ "map":{
+ "title": "Ajouter une Meta Règle",
+ "form" :{
+ "list": "Liste des Meta Règles"
+ },
+ "action": {
+ "create": "Ajouter une nouvelle Meta Règle",
+ "cancel": "Fermer",
+ "new": "Ajouter une Meta Règle",
+ "list": "Ajouter une Meta Règle existante",
+ "add": "Ajouter la Meta Règle sélectionnée",
+ "delete" : "Supprimer la Meta Règle sélectionnée"
+ },
+ "error": "Impossible d'associer le Modèle `{{modelName}}` à la Meta Règle `{{metaRuleName}}`",
+ "success": "L'association du Modèle `{{modelName}}` avec la Meta Règle `{{metaRuleName}}` a été effectuée avec succès"
+ },
+ "unmap": {
+ "title": "Enlever de la Meta Règle du Modèle",
+ "content": "Voulez-vous enlever le Modèle `{{modelName}}` de la Meta Règle `{{metaRuleName}}` ?",
+ "action": {
+ "unmap": "Enlever",
+ "cancel": "Annuler"
+ },
+ "error": "Impossible d'enlever le Modèle `{{modelName}}` de la Meta Règle `{{metaRuleName}}`",
+ "success": "La dissociation du Modèle `{{modelName}}` de la Meta Règle `{{metaRuleName}}` a été effectuée avec succès"
+ },
+ "delete": {
+ "error": "Impossible de supprimer la Meta Rule `{{metaRuleName}}`",
+ "success": "La Meta Rule `{{metaRuleName}}` a été supprimée avec succès"
+ }
+ },
+ "metadata" :{
+ "subject" : {
+ "title" : "Liste des Catégories Sujet associées",
+ "delete": {
+ "error" : "Impossible de supprimer le Sujet : {{subjectName}}, la raison : {{reason}}",
+ "success": "Sujet `{{subjectName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Catégorie Sujet"
+ },
+ "notFound": "Il n'existe aucun Sujet"
+ },
+ "object" : {
+ "title" : "Liste des Catégories Objet associées",
+ "delete": {
+ "error" : "Impossible de supprimer l'Objet : {{objectName}}, la raison : {{reason}}",
+ "success": "Objet `{{objectName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Catégorie Objet"
+ },
+ "notFound": "Il n'existe aucun Objet"
+ },
+ "action" : {
+ "title" : "Liste des Catégories Action associées",
+ "remove": "Enlever",
+ "delete": {
+ "error" : "Impossible de supprimer l'Action : {{actionName}}, la raison : {{reason}}",
+ "success": "Action `{{actionName}}` a été supprimé avec succès"
+ },
+ "add": {
+ "title": "Ajouter une Catégorie Action"
+ },
+ "notFound": "Il n'existe aucune Action"
+ },
+ "table": {
+ "id" : "Id",
+ "name" : "Nom",
+ "description" : "Description",
+ "action": {
+ "title": "Actions",
+ "delete": "Supprimer",
+ "update": "Mettre à jour"
+ }
+ },
+ "edit": {
+ "name" : "Nom",
+ "description" : "Description",
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "action": {
+ "list": "Ajouter une Catégorie existante",
+ "new": "Ajouter une nouvelle Catégorie",
+ "create":"Ajouter la Catégorie",
+ "add":"Ajouter la Catégorie selectionnée",
+ "delete": "Supprimer"
+ },
+ "create": {
+ "error": "Impossible de créer la Catégorie `{{name}}`",
+ "success": "La Catégorie `{{name}}` a été créé avec succès"
+ },
+ "delete": {
+ "error": "Impossible de supprimer la Catégorie `{{name}}`",
+ "success": "La Catégorie `{{name}}` a été supprimée avec succès"
+ }
+ }
+ },
+ "add":{
+ "title": "Ajouter un nouveau Model",
+ "form": {
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Créer le Modèle",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "error": "Impossible de créer le Modèle `{{modelName}}`",
+ "success": "Le Modèle `{{modelName}}` a été créé avec succès"
+ }
+ },
+ "project": {
+ "title": "Projects",
+ "list": {
+ "search": {
+ "placeholder": "Rechercher des Projects",
+ "reset": "Effacer"
+ },
+ "table": {
+ "name": "Nom",
+ "domain": "Domaine",
+ "managed": "Supervisé",
+ "enabled": "Activé",
+ "description": "Description",
+ "mapping": "PDP",
+ "loading": {
+ "project": "Chargement des Projects",
+ "pdp": "Chargement du PDP"
+ },
+ "notFound": "Il n'existe aucun Project"
+ },
+ "action": {
+ "title": "Actions",
+ "detail": "Consulter",
+ "delete": "Supprimer",
+ "add": "Ajouter un Project",
+ "map": "Associer à un PDP",
+ "unmap": "Dissocier"
+ },
+ "error": "Impossible de récupérer la liste des Projects"
+ },
+ "view": {
+ "title": "Détail du Project `{{projectName}}`",
+ "action": {
+ "close": "Fermer"
+ },
+ "subject": {
+ "title": "Sujets",
+ "name": "Nom",
+ "mail": "Email",
+ "domain": "Domaine",
+ "enabled": "Activé",
+ "error": "Impossible de récupérer la liste des Sujets"
+ },
+ "object": {
+ "title": "Objets",
+ "category": "Catégorie",
+ "description": "Description",
+ "enabled": "Activé",
+ "name": "Nom",
+ "error": "Impossible de récupérer la liste des Objets",
+ "loading": "Chargement des Objets",
+ "notFound": "Il n'existe aucun Objet"
+ },
+ "role": {
+ "title": "Roles",
+ "category": "Catégorie",
+ "value": "Valeur",
+ "description": "Description",
+ "assigned": "Affecté",
+ "enabled": "Activé",
+ "error": "Impossible de récupérer la liste des Roles",
+ "loading": "Chargement des Roles",
+ "notFound": "Il n'existe aucun Role"
+ },
+ "roleAssignment": {
+ "title": "Affectation des roles",
+ "category": "Catégorie",
+ "attributes": "Attributs",
+ "description": "Description",
+ "error": "impossible de récupérer la liste des affectations",
+ "loading": "Chargement des Affectations",
+ "notFound": "Il n'existe aucune Affectation"
+ },
+ "group": {
+ "title": "Groupes",
+ "category": "Catégorie",
+ "value": "Valeur",
+ "description": "Description",
+ "assigned": "Affecté",
+ "enabled": "Activé",
+ "error": "Impossible de récupérer la liste des Groupes",
+ "loading": "Chargement des Groupes",
+ "notFound": "Il n'existe aucun Groupe"
+ },
+ "groupAssignment": {
+ "title": "Affectation des groupes",
+ "category": "Catégorie",
+ "attributes": "Attributs",
+ "description": "Description",
+ "error": "impossible de récupérer la liste des affectations",
+ "loading": "Chargement des Affectations",
+ "notFound": "Il n'existe aucune Affectation"
+ }
+ },
+ "add": {
+ "title": "Ajouter un nouveau Project",
+ "form": {
+ "name": "Nom",
+ "description": "Description",
+ "enabled": "Activé",
+ "domain": "Domaine"
+ },
+ "action": {
+ "create": "Créer le Project",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ },
+ "domain": {
+ "required": "Le domaine est requis"
+ }
+ },
+ "error": "Impossible de créer le Project `{{projectName}}`",
+ "success": "Le Project `{{projectName}}` a été créé avec succès"
+ },
+ "remove": {
+ "title": "Supprimer un Project",
+ "content": {
+ "query": "Voulez-vous supprimer le Project `{{projectName}}` ?",
+ "isNotMapped": "Ce Project est associé avec aucune PDP.",
+ "isMapped": "Ce project est associé avec le PDP `{{pdpName}}`, le supprimer va supprimer le mapping associé"
+ },
+ "mapping":{
+ "remove":{
+ "error": "Impossible de supprimer la relation avec `{{pdpName}}`"
+ }
+ },
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer le Project `{{projectName}}`",
+ "success": "Le Project `{{projectName}}` a été supprimé avec succès"
+ },
+ "map": {
+ "title": "Associé le Project `{{projectName}}` avec une PDP",
+ "form": {
+ "pdp": "PDP"
+ },
+ "action": {
+ "map": "Associer",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "pdp": {
+ "required": "L'PDP est requise"
+ }
+ },
+ "error": "Impossible d'associer le Project `{{projectName}}` avec la PDP `{{pdpName}}`",
+ "success": "L'association du Project `{{projectName}}` avec la PDP `{{pdpName}}` a été effectué avec succès"
+ },
+ "unmap": {
+ "title": "Dissociation Project et PDP",
+ "content": "Voulez-vous dissocier le Project `{{projectName}}` et la PDP `{{pdpName}}` ?",
+ "action": {
+ "unmap": "Dissocier",
+ "cancel": "Annuler"
+ },
+ "error": "Impossible de dissocier le Project `{{projectName}}` et la PDP `{{pdpName}}`",
+ "success": "La dissociation du Project `{{projectName}}` et de la PDP `{{pdpName}}` a été effectuée avec succès"
+ }
+ },
+ "pdp": {
+ "title": "PDPs",
+ "edit" : {
+ "title": "configuration du PDP `{{pdpName}}` ",
+ "update" : "- Mettre à jour",
+ "basic" : {
+ "title" : "Information de base",
+ "form": {
+ "id": "Id",
+ "name": "Nom",
+ "description": "Description"
+ },
+ "action": {
+ "init": "Init",
+ "update": "Mettre à jour"
+ },
+ "check": {
+ "name": {
+ "required": "Le Nom est requis"
+ }
+ },
+ "error": "Impossible de mettre à jour la PDP `{{pdpName}}`",
+ "success": "La PDP `{{pdpName}}` a été mis à jour avec succès"
+ },
+ "policy": {
+ "title" : "Politiques"
+ }
+ },
+ "list": {
+ "search": {
+ "placeholder": "Rechercher des PDPs",
+ "reset": "Effacer"
+ },
+ "table": {
+ "name": "Nom",
+ "security_pipeline":{
+ "number" : "Nombre de Règles"
+ },
+ "project": "Project",
+ "loading": {
+ "pdp": "Chargement des PDPs",
+ "project": "Chargement du Project"
+ },
+ "mapping" :{
+ "map": "n'est pas associé à un projet"
+ },
+ "notFound": "Il n'existe aucune PDP"
+ },
+ "action": {
+ "title": "Actions",
+ "detail": "Consulter",
+ "configure": "Configurer",
+ "rule": "Règles",
+ "delete": "Supprimer",
+ "add": "Ajouter une PDP",
+ "edit": "Editer"
+ },
+ "error": "Impossible de récupérer la liste des PDPs"
+ },
+ "add": {
+ "title": "Ajouter une nouvelle PDP",
+ "form": {
+ "name": "Nom",
+ "policy": "Règle",
+ "description": "Description"
+ },
+ "action": {
+ "create": "Créer la PDP",
+ "cancel": "Annuler"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ },
+ "policy": {
+ "required": "Une règle est requise"
+ }
+ },
+ "error": "Impossible de créer la PDP `{{pdpName}}`",
+ "success": "La PDP `{{pdpName}}` a été créée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une PDP",
+ "content": "Voulez-vous supprimer la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la PDP `{{pdpName}}`",
+ "success": "la PDP `{{pdpName}}` a été supprimé avec succès"
+ },
+ "configure": {
+ "title": "Configuration de la PDP `{{pdpName}}`",
+ "action": {
+ "back": "Liste des PDPs"
+ },
+ "subject": {
+ "panelTitle": "Configuration des Sujets",
+ "title": "Sujets",
+ "add": {
+ "title": "Ajouter un nouveau Sujet",
+ "form": {
+ "name": "Nom",
+ "domain": "Domaine",
+ "enabled": "Activé",
+ "project": "Projet",
+ "password": "Mot de passe",
+ "description": "Description"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Sujet"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ },
+ "domain": {
+ "required": "Le domaine est requis"
+ },
+ "project": {
+ "required": "Le projet est requis"
+ },
+ "password": {
+ "required": "Le mot de passe est requis"
+ }
+ },
+ "error": "Impossible d'ajouter le Sujet `{{subjectName}}`",
+ "success": "Le Sujet `{{subjectName}}` a été ajouté avec succès"
+ },
+ "remove": {
+ "title": "Supprimer un Sujet",
+ "content": "Voulez-vous supprimer le Sujet `{{subjectName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer le Sujet `{{subjectName}}`",
+ "success": "Le Sujet `{{subjectName}}` a été supprimé avec succès"
+ },
+ "category": {
+ "title": "Catégories",
+ "add": {
+ "title": "Ajouter une nouvelle Catégorie",
+ "form": {
+ "name": "Nom"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Catégorie"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "error": "Impossible d'ajouter la Catégorie `{{categoryName}}`",
+ "success": "Catégorie `{{categoryName}}` ajoutée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une Catégorie",
+ "content": "Voulez-vous supprimer la Catégorie `{{categoryName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la Catégorie `{{categoryName}}`",
+ "success": "La Catégorie `{{categoryName}}` a été supprimée avec succès"
+ }
+ },
+ "categoryValue": {
+ "title": "Valeurs",
+ "add": {
+ "title": "Ajouter une nouvelle Valeur",
+ "form": {
+ "value": "Valeur"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Valeur"
+ },
+ "check": {
+ "value": {
+ "required": "La valeur est requise"
+ }
+ },
+ "error": "Impossible d'ajouter la Valeur `{{valueName}}`",
+ "success": "Valeur `{{valueName}}` ajoutée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une Valeur",
+ "content": "Voulez-vous supprimer la Valeur `{{valueName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la Valeur `{{valueName}}`",
+ "success": "La Valeur `{{valueName}}` a été supprimée avec succès"
+ }
+ },
+ "assignment": {
+ "title": "Affectation des Sujets",
+ "action": {
+ "assign": "Affecter",
+ "unassign": "Désaffecter"
+ },
+ "list": {
+ "notFound": "Il n'existe aucune affectation"
+ },
+ "add": {
+ "error": "Impossible de réaliser l'affectation Sujet `{{subjectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}`",
+ "success": "Affectation de Sujet `{{subjectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}` réalisée avec succès"
+ },
+ "remove": {
+ "error": "Impossible de réaliser la désaffectation Sujet `{{subjectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}`",
+ "success": "Désaffectation de Sujet `{{subjectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}` réalisée avec succès"
+ }
+ }
+ },
+ "object": {
+ "panelTitle": "Configuration des Objets",
+ "title": "Objets",
+ "add": {
+ "title": "Ajouter un nouvel Objet",
+ "form": {
+ "name": "Nom",
+ "image": "Image",
+ "flavor": "Type"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Objet"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ },
+ "image": {
+ "required": "L'image est requise"
+ },
+ "flavor": {
+ "required": "Le type est requis"
+ }
+ },
+ "error": "Impossible d'ajouter l'Objet `{{objectName}}`",
+ "success": "L'Objet `{{objectName}}` a été ajouté avec succès"
+ },
+ "remove": {
+ "title": "Supprimer un Objet",
+ "content": "Voulez-vous supprimer l'Objet `{{objectName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer l'Objet `{{objectName}}`",
+ "success": "L'Objet `{{objectName}}` a été supprimé avec succès"
+ },
+ "category": {
+ "title": "Catégories",
+ "add": {
+ "title": "Ajouter une nouvelle Catégorie",
+ "form": {
+ "name": "Nom"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Catégorie"
+ },
+ "check": {
+ "name": {
+ "required": "Le nom est requis"
+ }
+ },
+ "error": "Impossible d'ajouter la Catégorie `{{categoryName}}`",
+ "success": "Catégorie `{{categoryName}}` ajoutée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une Catégorie",
+ "content": "Voulez-vous supprimer la Catégorie `{{categoryName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la Catégorie `{{categoryName}}`",
+ "success": "La Catégorie `{{categoryName}}` a été supprimée avec succès"
+ }
+ },
+ "categoryValue": {
+ "title": "Valeurs",
+ "add": {
+ "title": "Ajouter une nouvelle Valeur",
+ "form": {
+ "value": "Valeur"
+ },
+ "action": {
+ "cancel": "Annuler",
+ "add": "Ajouter Valeur"
+ },
+ "check": {
+ "value": {
+ "required": "La valeur est requise"
+ }
+ },
+ "error": "Impossible d'ajouter la Valeur `{{valueName}}`",
+ "success": "Valeur `{{valueName}}` ajoutée avec succès"
+ },
+ "remove": {
+ "title": "Supprimer une Valeur",
+ "content": "Voulez-vous supprimer la Valeur `{{valueName}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "cancel": "Annuler",
+ "delete": "Supprimer"
+ },
+ "error": "Impossible de supprimer la Valeur `{{valueName}}`",
+ "success": "La Valeur `{{valueName}}` a été supprimée avec succès"
+ }
+ },
+ "assignment": {
+ "title": "Affectation des Objets",
+ "action": {
+ "assign": "Affecter",
+ "unassign": "Désaffecter"
+ },
+ "list": {
+ "notFound": "Il n'existe aucune affectation"
+ },
+ "add": {
+ "error": "Impossible de réaliser l'affectation Objet `{{objectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}`",
+ "success": "Affectation de Objet `{{objectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}` réalisée avec succès"
+ },
+ "remove": {
+ "error": "Impossible de réaliser la désaffectation Objet `{{objectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}`",
+ "success": "Désaffectation de Objet `{{objectName}}` / Catégorie `{{categoryName}}` / Valeur `{{valueName}}` réalisée avec succès"
+ }
+ }
+ }
+ },
+ "rule": {
+ "title": "Règles de la PDP `{{pdpName}}`",
+ "list": {
+ "table": {
+ "subject": "Sujets",
+ "object": "Objects",
+ "notFound": "Il n'existe aucune règle"
+ },
+ "action": {
+ "title": "Actions",
+ "add": "Ajouter une règle",
+ "delete": "Supprimer une règle"
+ }
+ },
+ "add": {
+ "title": "Ajouter une nouvelle Règle",
+ "action": {
+ "create": "Créer la Règle",
+ "cancel": "Annuler"
+ },
+ "form": {
+ "subject": {
+ "subject": "Sujets",
+ "category": "Catégories",
+ "categoryValue": "Valeur",
+ "action": {
+ "add": "Ajouter",
+ "delete": "Supprimer"
+ }
+ },
+ "object": {
+ "object": "Objets",
+ "category": "Catégories",
+ "categoryValue": "Valeurs",
+ "action": {
+ "add": "Ajouter",
+ "delete": "Supprimer"
+ }
+ }
+ },
+ "success": "La règle a été créée avec succès",
+ "error": "Impossible de créer la règle"
+ },
+ "delete": {
+ "title": "Supprime une Règle",
+ "content": "Voulez-vous supprimer la Valeur règle `{{ruleJson}}` de la PDP `{{pdpName}}` ?",
+ "action": {
+ "delete": "Supprimer la Règle",
+ "cancel": "Annuler"
+ },
+ "error": "Impossible de supprimer la règle `{{ruleJson}}`",
+ "success": "La règle `{{ruleJson}}` a été supprimée avec succès"
+ },
+ "action": {
+ "back": "Liste des PDPs"
+ }
+ }
+ }
+ }
+}
diff --git a/moonv4/moon_gui/static/img/ajax-loader.gif b/moonv4/moon_gui/static/img/ajax-loader.gif
new file mode 100755
index 00000000..d0bce154
--- /dev/null
+++ b/moonv4/moon_gui/static/img/ajax-loader.gif
Binary files differ
diff --git a/moonv4/moon_gui/static/img/ajax-waiting.gif b/moonv4/moon_gui/static/img/ajax-waiting.gif
new file mode 100755
index 00000000..d84f6537
--- /dev/null
+++ b/moonv4/moon_gui/static/img/ajax-waiting.gif
Binary files differ
diff --git a/moonv4/moon_gui/static/img/arrow-link.gif b/moonv4/moon_gui/static/img/arrow-link.gif
new file mode 100755
index 00000000..ca17f44b
--- /dev/null
+++ b/moonv4/moon_gui/static/img/arrow-link.gif
Binary files differ
diff --git a/moonv4/moon_gui/static/img/et.jpg b/moonv4/moon_gui/static/img/et.jpg
new file mode 100644
index 00000000..67cc0a9d
--- /dev/null
+++ b/moonv4/moon_gui/static/img/et.jpg
Binary files differ
diff --git a/moonv4/moon_gui/static/img/logo-openstack.png b/moonv4/moon_gui/static/img/logo-openstack.png
new file mode 100755
index 00000000..60ab0e1e
--- /dev/null
+++ b/moonv4/moon_gui/static/img/logo-openstack.png
Binary files differ
diff --git a/moonv4/moon_gui/static/img/logo-orange.gif b/moonv4/moon_gui/static/img/logo-orange.gif
new file mode 100755
index 00000000..9c612291
--- /dev/null
+++ b/moonv4/moon_gui/static/img/logo-orange.gif
Binary files differ
diff --git a/moonv4/moon_gui/static/styles/main.css b/moonv4/moon_gui/static/styles/main.css
new file mode 100644
index 00000000..654a4741
--- /dev/null
+++ b/moonv4/moon_gui/static/styles/main.css
@@ -0,0 +1,169 @@
+/* ----------------------------------------------------------------------------------
+# 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.
+---------------------------------------------------------------------------------- */
+
+html {
+ overflow: auto;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+
+body {
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+ color: #323232;
+ font-family: Arial, Helvetica, sans-serif;
+ /* http://clagnut.com/blog/348/ */
+ font-size: 1em;
+}
+
+div, span, td, input, textarea, li {
+ font-size: 1em;
+}
+
+.container {
+ font-size: 1.2em;
+}
+
+.footer {
+ margin: 1em 0 1em 0
+}
+
+input[disabled], textarea[disabled] {
+ background-color: #f6f6f6;
+}
+
+strong, .strong {
+ font-weight: bold;
+}
+
+h1, h2, h3, .likeH2 {
+ color: #FF6600;
+ text-align: center;
+}
+
+h1 {
+ font-size: 2em;
+ margin: 0em;
+}
+
+h2, .likeH2 {
+ font-size: 1.8em;
+ font-weight: lighter;
+ line-height: 1em;
+ margin: 0 0 1em;
+}
+
+h3 {
+ font-size: 1.6em;
+ font-weight: lighter;
+ line-height: 1em;
+ margin: 0 0 1em;
+ text-align: left;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+
+.banner {
+ margin: 1.5em 0 1.5em 0;
+}
+
+.sub-banner {
+ margin: 0 0 1.5em 0;
+}
+
+.underlined {
+ text-decoration: underline;
+}
+
+.header img {
+ float: left;
+}
+
+.header h1 {
+ position: relative;
+}
+
+hr {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.table {
+ text-align: left !important;
+}
+
+.centered {
+ text-align: center;
+ color: #cbcbcb;
+}
+
+.customTables, .dropdown-menu {
+ text-align: left !important;
+}
+
+.resourceCombo {
+ width: 100%;
+}
+
+.top05 { margin-top: 0.5em; }
+.top10 { margin-top: 1.0em; }
+.top15 { margin-top: 1.5em; }
+.top20 { margin-top: 2.0em; }
+.top25 { margin-top: 2.5em; }
+.top30 { margin-top: 3.0em; }
+
+.left05 { margin-left: 0.5em }
+.left10 { margin-left: 1.0em }
+.left15 { margin-left: 1.5em }
+.left20 { margin-left: 2.0em }
+.left25 { margin-left: 2.5em }
+.left30 { margin-left: 3.0em }
+
+.black {
+ color: #333
+}
+
+.divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+
+/* */
+/*
+.modal-backdrop.am-fade {
+ opacity: .5;
+ transition: opacity .15s linear;
+ &.ng-enter {
+ opacity: 0;
+ &.ng-enter-active {
+ opacity: .5;
+ }
+ }
+ &.ng-leave {
+ opacity: .5;
+ &.ng-leave-active {
+ opacity: 0;
+ }
+ }
+}
+*/ \ No newline at end of file
diff --git a/moonv4/moon_gui/static/version.json b/moonv4/moon_gui/static/version.json
new file mode 100755
index 00000000..ec74a2db
--- /dev/null
+++ b/moonv4/moon_gui/static/version.json
@@ -0,0 +1,3 @@
+{
+ "version": "1.0.0"
+} \ No newline at end of file