From 04afd774aecc70dca37559fdd8b9a716829c18cd Mon Sep 17 00:00:00 2001
From: Roberto Sánchez <roberto.sanchez@curisit.net>
Date: Fri, 17 Jan 2014 12:27:16 +0000
Subject: [PATCH] #396 feature - Added LocalStorage support and http interceptor for unauthorized access
---
securis/src/main/resources/static/js/store.min.js | 2
securis/src/main/resources/static/main.html | 14
securis/src/main/resources/static/js/store.js | 165 +++++++++
securis/src/main/resources/static/js/licenses.js | 81 ++++
securis/src/main/resources/static/js/catalogs.js | 473 +++++++++++++++----------
securis/src/main/resources/static/js/main.js | 77 +++
securis/src/main/resources/static/admin.html | 25 -
securis/src/main/resources/static/css/font-awesome.min.css | 4
securis/src/main/resources/static/js/i18n.js | 2
securis/src/main/resources/static/licenses.html | 165 +++++++-
securis/src/main/resources/static/js/login.js | 12
securis/src/main/resources/static/js/admin.js | 16
securis/src/main/resources/db/schema.sql | 12
securis/src/main/resources/static/header.html | 19 +
14 files changed, 788 insertions(+), 279 deletions(-)
diff --git a/securis/src/main/resources/db/schema.sql b/securis/src/main/resources/db/schema.sql
index e13879a..ee3bda6 100644
--- a/securis/src/main/resources/db/schema.sql
+++ b/securis/src/main/resources/db/schema.sql
@@ -68,16 +68,20 @@
CREATE TABLE IF NOT EXISTS license (
id INT NOT NULL,
code VARCHAR(100) NOT NULL ,
+ request_data VARCHAR(1024) NULL ,
+ license_data VARCHAR(1024) NULL ,
pack_id INT NOT NULL,
- user_name INT NULL,
- user_email INT NOT NULL,
+ full_name VARCHAR(150) NULL,
+ email VARCHAR(100) NOT NULL,
creation_timestamp DATETIME NOT NULL ,
- sent_timestamp DATETIME NULL ,
+ send_timestamp DATETIME NULL ,
modification_timestamp DATETIME NULL ,
+ activation_timestamp DATETIME NULL ,
cancelation_timestamp DATETIME NULL ,
+ last_access_timestamp DATETIME NULL ,
canceled_by varchar(45) NULL ,
created_by varchar(45) NULL ,
- status VARCHAR(3) NULL ,
+ status VARCHAR(3) NOT NULL default 0,
PRIMARY KEY (id));
diff --git a/securis/src/main/resources/static/admin.html b/securis/src/main/resources/static/admin.html
index 2053ec3..bc71148 100644
--- a/securis/src/main/resources/static/admin.html
+++ b/securis/src/main/resources/static/admin.html
@@ -1,21 +1,5 @@
- <div class="navbar navbar-inverse navbar-fixed-top">
- <div class="container">
- <div class="navbar-header">
- <ul class="nav navbar-nav navbar-left">
- <li style="color: white; padding-top: 15px;">SeCuris</li>
- <li><a href="#licenses">Licenses</a></li>
- <li><a href="#admin">Admin</a></li>
- </ul>
- </div>
- <div class="navbar-collapse collapse">
- <ul class="nav navbar-nav navbar-right">
- <li><a href="#about">About</a></li>
- <li><a href="#contact">Contact</a></li>
- </ul>
- </div>
- </div>
- </div>
+ <div ng-include="'header.html'" ></div>
<div class="container">
<div class="col-md-12"> </div>
@@ -38,9 +22,9 @@
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
- <li><a ng-click="editNew()"><span class="glyphicon glyphicon-plus"></span>
+ <li><a i18n ng-click="editNew()"><span class="glyphicon glyphicon-plus"></span>
New</a></li>
- <li><a ng-click="cancel()"> <span
+ <li><a i18n ng-click="cancel()"> <span
class="glyphicon glyphicon-ban-circle"></span> Cancel
</a></li>
</ul>
@@ -53,6 +37,7 @@
</div>
</div>
</nav>
+
<div class="panel panel-default animate-show ng-hide" ng-show="showForm">
<form role="form" class="form-horizontal " name="catalogForm" id="catalogForm" ng-submit="saveCatalog()" >
<!-- <pre>formu: {{formu | json}}</pre>-->
@@ -86,7 +71,7 @@
<div class="form-group">
<div class="col-md-offset-3 col-md-10" id="saveContainer">
<button id="save" type="submit" class="btn btn-primary" >
- <span class="glyphicon glyphicon-floppy-disk"></span> Save
+ <span i18n class="glyphicon glyphicon-floppy-disk"></span> Save
</button>
</div>
</div>
diff --git a/securis/src/main/resources/static/css/font-awesome.min.css b/securis/src/main/resources/static/css/font-awesome.min.css
new file mode 100644
index 0000000..449d6ac
--- /dev/null
+++ b/securis/src/main/resources/static/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}
\ No newline at end of file
diff --git a/securis/src/main/resources/static/header.html b/securis/src/main/resources/static/header.html
new file mode 100644
index 0000000..a8233f4
--- /dev/null
+++ b/securis/src/main/resources/static/header.html
@@ -0,0 +1,19 @@
+
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <ul class="nav navbar-nav navbar-left">
+ <li i18n style="color: white; padding-top: 15px;">SeCuris</li>
+ <li><a i18n href="/licenses">Licenses</a></li>
+ <li><a i18n href="/admin">Admin</a></li>
+ </ul>
+ </div>
+ <div class="navbar-collapse collapse">
+ <ul class="nav navbar-nav navbar-right">
+ <li><a i18n href="#about">About</a></li>
+ <li><a i18n href="#contact">Contact</a></li>
+ <li><a i18n ng-click="logout()">Logout</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
diff --git a/securis/src/main/resources/static/js/admin.js b/securis/src/main/resources/static/js/admin.js
index 6d806ac..fc1857a 100644
--- a/securis/src/main/resources/static/js/admin.js
+++ b/securis/src/main/resources/static/js/admin.js
@@ -33,7 +33,9 @@
'$http',
'toaster',
'Catalogs',
- function($scope, $http, toaster, Catalogs) {
+ '$store',
+ '$L',
+ function($scope, $http, toaster, Catalogs, $store, $L) {
$scope.showForm = false;
$scope.isNew = false;
$scope.formu = {};
@@ -78,16 +80,16 @@
}
$scope.delete = function(data) {
- BootstrapDialog.confirm('The record will be deleted, are you sure?', function(result){
+ BootstrapDialog.confirm($L.get('The record will be deleted, are you sure?'), function(result){
if(result) {
var promise = Catalogs.remove(data).$promise;
promise.then(function(data) {
$scope.list = Catalogs.query();
Catalogs.refreshRef($scope.refs, Catalogs.getMetadata().resource, $scope.list);
- toaster.pop('success', Catalogs.getName(), "Element deleted successfully");
+ toaster.pop('success', Catalogs.getName(), $L.get("Element deleted successfully"));
},function(error) {
console.log(error);
- toaster.pop('error', Catalogs.getName(), "Error deleting element, reason: " + HTTP_ERRORS[error.status] + ". Details: " + error.headers('X-SECURIS-ERROR'), 10000);
+ toaster.pop('error', Catalogs.getName(), $L.get("Error deleting element, reason: {0}. Details: {1}", $L.get(HTTP_ERRORS[error.status]), error.headers('X-SECURIS-ERROR')), 10000);
});
}
});
@@ -136,7 +138,7 @@
$scope.saveCatalog = function() {
if ($scope.catalogForm.$invalid) {
- toaster.pop('error', Catalogs.getName(), "There are wrong data in current form, please fix it before to save");
+ toaster.pop('error', Catalogs.getName(), $L.get("There are wrong data in current form, please fix it before to save"));
} else {
var promise = Catalogs.save($scope.formu).$promise;
promise.then(function(data, otro) {
@@ -150,10 +152,10 @@
$scope.$parent.list = Catalogs.query();
Catalogs.refreshRef($scope.refs, Catalogs.getMetadata().resource, $scope.$parent.list);
- toaster.pop('success', Catalogs.getName(), "Element saved successfully");
+ toaster.pop('success', Catalogs.getName(), $L.get("Element saved successfully"));
}, function(error) {
console.log(error);
- toaster.pop('error', Catalogs.getName(), "Error saving element, reason: " + HTTP_ERRORS[error.status] + ". Details: " + error.headers('X-SECURIS-ERROR'), 10000);
+ toaster.pop('error', Catalogs.getName(), $L.get("Error saving element, reason: {0}. Details: {1}", $L.get(HTTP_ERRORS[error.status]), error.headers('X-SECURIS-ERROR')), 10000);
});
}
diff --git a/securis/src/main/resources/static/js/catalogs.js b/securis/src/main/resources/static/js/catalogs.js
index 77ad975..7dc6614 100644
--- a/securis/src/main/resources/static/js/catalogs.js
+++ b/securis/src/main/resources/static/js/catalogs.js
@@ -5,209 +5,294 @@
* Catalogs module
*/
- angular.module('catalogs', ['ngResource'])
+ angular
+ .module('catalogs', [ 'ngResource' ])
- .service('Catalogs', ['$rootScope', '$http', '$resource', '$q', function ($rootScope, $http, $resource, $q) {
- var resources = {
- application : $resource('/application/:appId', {
- appId : '@id'
- }),
- user : $resource('/user/:userId', {
- userId : '@username'
- }),
- organization : $resource('/organization/:orgId', {
- orgId : '@id'
- }),
- licensetype : $resource('/licensetype/:licenseTypeId', {
- licenseTypeId : '@id'
- })
- }
+ .service(
+ 'Catalogs',
+ [
+ '$rootScope',
+ '$http',
+ '$resource',
+ '$q',
+ function($rootScope, $http, $resource, $q) {
+ var resources = {
+ application : $resource(
+ '/application/:appId', {
+ appId : '@id'
+ }),
+ user : $resource('/user/:userId', {
+ userId : '@username'
+ }),
+ organization : $resource(
+ '/organization/:orgId', {
+ orgId : '@id'
+ }),
+ licensetype : $resource(
+ '/licensetype/:licenseTypeId', {
+ licenseTypeId : '@id'
+ })
+ }
- var _metadata = null;
- var _current = null;
+ var _metadata = null;
+ var _current = null;
- var _list = function() {
- return $http.get('/js/catalogs.json').success(function(data) {
- _metadata = data;
- })
- }
- this.init = function() {
- return _list();
- }
- this.getList = function() {
- return _metadata;
- }
- this.getName = function(index) {
- if (index === undefined)
- return _current ? _current.name : '';
- return _metadata ? _metadata[index].name : '';
- }
- this.getResource = function(res) {
- if (res === undefined)
- return _current ? resources[_current.resource] : null;
- return _current ? resources[res] : null;
- }
- this.getPk = function(catalogMetadata) {
- if (!catalogMetadata) catalogMetadata = _current;
-
- for(var i = 0; i < catalogMetadata.fields.length; i++)
- if (catalogMetadata.fields[i].pk) return catalogMetadata.fields[i].name;
-
- return null;
- }
- /**
- * Returns catalog metadata
- * @param index: Return current catalog if undefined, if string It find the catalog by resoource name if number it find it by position
- */
- this.getMetadata = function(index) {
- if (!_metadata) throw new Error('There is no catalog metadata info');
- if (index === undefined)
- return _current;
- if (typeof index === 'string') {
- for (var i = _metadata.length - 1; i >= 0 && _metadata[i].resource !== index; i--);
- index = i;
- }
+ var _list = function() {
+ return $http.get('/js/catalogs.json')
+ .success(function(data) {
+ _metadata = data;
+ })
+ }
+ this.init = function() {
+ return _list();
+ }
+ this.getList = function() {
+ return _metadata;
+ }
+ this.getName = function(index) {
+ if (index === undefined)
+ return _current ? _current.name : '';
+ return _metadata ? _metadata[index].name
+ : '';
+ }
+ this.getResource = function(res) {
+ if (res === undefined)
+ return _current ? resources[_current.resource]
+ : null;
+ return _current ? resources[res] : null;
+ }
+ this.getPk = function(catalogMetadata) {
+ if (!catalogMetadata)
+ catalogMetadata = _current;
- return _metadata[index];
- }
- this.setCurrent = function(index) {
- if (!_metadata) throw new Error('There is no catalog metadata info');
- if (index === undefined)
- _current = null;
- else
- _current = _metadata[index];
- }
- /********************************************
- * Catalog fields methods *
- ********************************************/
+ for (var i = 0; i < catalogMetadata.fields.length; i++)
+ if (catalogMetadata.fields[i].pk)
+ return catalogMetadata.fields[i].name;
- /**
- * Returns the first field in form that should get the focus. We find the first field that is not read only
- */
- this.getFFF = this.getFirstFocusableField = function() {
- if (!_current) throw new Error('There is no current catalog selected');
-
- for(var i = 0; i < _current.fields.length; i++)
- if (!_current.fields[i].readOnly) return _current.fields[i].name;
-
- return null;
- }
+ return null;
+ }
+ /**
+ * Returns catalog metadata
+ *
+ * @param index:
+ * Return current catalog if
+ * undefined, if string It find the
+ * catalog by resoource name if
+ * number it find it by position
+ */
+ this.getMetadata = function(index) {
+ if (!_metadata)
+ throw new Error(
+ 'There is no catalog metadata info');
+ if (index === undefined)
+ return _current;
+ if (typeof index === 'string') {
+ for (var i = _metadata.length - 1; i >= 0
+ && _metadata[i].resource !== index; i--)
+ ;
+ index = i;
+ }
- /**
- * Find the field by name or position
- */
- this.getField = function(key) {
- if (!_current) throw new Error('There is no current catalog selected');
- var index = -1;
- if (typeof key === 'string') {
- for (var i = _current.fields.length - 1; i >= 0 && _current.fields[i].name !== key; i--);
- index = i;
- } else {
- index = key; // In this case key === field position
- }
+ return _metadata[index];
+ }
+ this.setCurrent = function(index) {
+ if (!_metadata)
+ throw new Error(
+ 'There is no catalog metadata info');
+ if (index === undefined)
+ _current = null;
+ else
+ _current = _metadata[index];
+ }
+ /***********************************************
+ * Catalog fields methods *
+ **********************************************/
- return index === -1 ? {} : _current.fields[index];
- }
-
- /********************************************
- * Catalog resource operations on server *
- ********************************************/
+ /**
+ * Returns the first field in form that should
+ * get the focus. We find the first field that
+ * is not read only
+ */
+ this.getFFF = this.getFirstFocusableField = function() {
+ if (!_current)
+ throw new Error(
+ 'There is no current catalog selected');
- function _success(response) {
- console.log('$resource')
- console.log(response)
- }
- function _fail(response) {
- console.error('Error trying to get data, HTTP error code: ' + response.status)
- }
-
-
- this.save = function(data) {
- if (!_current) throw new Error('There is no current catalog selected');
+ for (var i = 0; i < _current.fields.length; i++)
+ if (!_current.fields[i].readOnly)
+ return _current.fields[i].name;
- var resource = this.getResource();
- return resource.save(data, _success, _fail);
- }
- this.remove = function(data) {
- return this.getResource().remove({}, data, _success, _fail)
- }
- this.query = function() {
- return this.getResource().query({}, _success, _fail);
- }
- this.refreshRef = function(refs, res, preloadedData) {
- // We check if there is some field for the resource passed as parameter
- var field = (function() {
- for (var i = _current.fields.length - 1; i >= 0; i--) {
- if (_current.fields[i].resource === res)
- return _current.fields[i];
- }
- return null;
- })();
-
- // If field for that resource is not found there is nothing to refresh
- if (!field) return;
- var resource = this.getResource(res);
- var data = preloadedData || resource.query({}, _success, _fail);
- var that = this;
- data.$promise.then(function(responseData) {
- var pk = that.getPk(that.getMetadata(field.resource))
- var comboData = []
- responseData.forEach(function(row) {
- comboData.push({
- id: row[pk],
- label: row.label || row.name || row.code || row.first_name + ' ' + row.last_name
- });
- })
- refs[field.name] = comboData;
- })
- }
- this.loadRefs = function(refs) {
- if (!_current) throw new Error('There is no current catalog selected');
- var refsFields = [];
- _current.fields.forEach(function(f) {
- if (f.resource)
- refsFields.push(f)
+ return null;
+ }
- });
-
- var that = this;
- var promises = []
- refsFields.forEach(function(f) {
- var resource = that.getResource(f.resource);
- refs[f.name] = resource.query({}, _success, _fail);
- promises.push(refs[f.name].$promise);
- });
-
- console.log('promises: ' + promises.length + ' ')
- console.log(promises)
- $q.all(promises).then(function() {
-
- for (var k in refs) {
- var field = that.getField(k);
- var pk = that.getPk(that.getMetadata(field.resource))
- console.log('PK field for ' + k + ' is ' + pk)
- var comboData = []
- refs[k].forEach(function(row) {
- console.log('field.resource !== _current.resource: ' + field.resource +' '+ _current.resource)
- comboData.push({
- id: row[pk],
- label: row.label || row.name || row.code || row.first_name + ' ' + (row.last_name || '')
- });
- })
- refs[k] = comboData;
- console.log('Ready for combo for ' + k)
- console.log(comboData);
- }
- _current.fields.forEach(function(f) {
- if (f.values)
- refs[f.name] = f.values;
- });
- })
-
- console.log(refs);
- return refs;
- }
-
- }])
+ /**
+ * Find the field by name or position
+ */
+ this.getField = function(key) {
+ if (!_current)
+ throw new Error(
+ 'There is no current catalog selected');
+ var index = -1;
+ if (typeof key === 'string') {
+ for (var i = _current.fields.length - 1; i >= 0
+ && _current.fields[i].name !== key; i--)
+ ;
+ index = i;
+ } else {
+ index = key; // In this case key ===
+ // field position
+ }
+
+ return index === -1 ? {}
+ : _current.fields[index];
+ }
+
+ /***********************************************
+ * Catalog resource operations on server *
+ **********************************************/
+
+ function _success(response) {
+ console.log('$resource')
+ console.log(response)
+ }
+ function _fail(response) {
+ console
+ .error('Error trying to get data, HTTP error code: '
+ + response.status)
+ }
+
+ this.save = function(data) {
+ if (!_current)
+ throw new Error(
+ 'There is no current catalog selected');
+
+ var resource = this.getResource();
+ return resource.save(data, _success, _fail);
+ }
+ this.remove = function(data) {
+ return this.getResource().remove({}, data,
+ _success, _fail)
+ }
+ this.query = function() {
+ return this.getResource().query({},
+ _success, _fail);
+ }
+ this.refreshRef = function(refs, res,
+ preloadedData) {
+ // We check if there is some field for the
+ // resource passed as parameter
+ var field = (function() {
+ for (var i = _current.fields.length - 1; i >= 0; i--) {
+ if (_current.fields[i].resource === res)
+ return _current.fields[i];
+ }
+ return null;
+ })();
+
+ // If field for that resource is not found
+ // there is nothing to refresh
+ if (!field)
+ return;
+ var resource = this.getResource(res);
+ var data = preloadedData
+ || resource.query({}, _success,
+ _fail);
+ var that = this;
+ data.$promise.then(function(responseData) {
+ var pk = that.getPk(that
+ .getMetadata(field.resource))
+ var comboData = []
+ responseData.forEach(function(row) {
+ comboData.push({
+ id : row[pk],
+ label : row.label || row.name
+ || row.code
+ || row.first_name + ' '
+ + row.last_name
+ });
+ })
+ refs[field.name] = comboData;
+ })
+ }
+ this.loadRefs = function(refs) {
+ if (!_current)
+ throw new Error(
+ 'There is no current catalog selected');
+ var refsFields = [];
+ _current.fields.forEach(function(f) {
+ if (f.resource)
+ refsFields.push(f)
+
+ });
+
+ var that = this;
+ var promises = []
+ refsFields.forEach(function(f) {
+ var resource = that
+ .getResource(f.resource);
+ refs[f.name] = resource.query({},
+ _success, _fail);
+ promises.push(refs[f.name].$promise);
+ });
+
+ console.log('promises: ' + promises.length
+ + ' ')
+ console.log(promises)
+ $q
+ .all(promises)
+ .then(
+ function() {
+
+ for ( var k in refs) {
+ var field = that
+ .getField(k);
+ var pk = that
+ .getPk(that
+ .getMetadata(field.resource))
+ console
+ .log('PK field for '
+ + k
+ + ' is '
+ + pk)
+ var comboData = []
+ refs[k]
+ .forEach(function(
+ row) {
+ console
+ .log('field.resource !== _current.resource: '
+ + field.resource
+ + ' '
+ + _current.resource)
+ comboData
+ .push({
+ id : row[pk],
+ label : row.label
+ || row.name
+ || row.code
+ || row.first_name
+ + ' '
+ + (row.last_name || '')
+ });
+ })
+ refs[k] = comboData;
+ console
+ .log('Ready for combo for '
+ + k)
+ console
+ .log(comboData);
+ }
+ _current.fields
+ .forEach(function(
+ f) {
+ if (f.values)
+ refs[f.name] = f.values;
+ });
+ })
+
+ console.log(refs);
+ return refs;
+ }
+
+ } ])
})();
\ No newline at end of file
diff --git a/securis/src/main/resources/static/js/i18n.js b/securis/src/main/resources/static/js/i18n.js
index c895497..be4eed6 100644
--- a/securis/src/main/resources/static/js/i18n.js
+++ b/securis/src/main/resources/static/js/i18n.js
@@ -72,7 +72,7 @@
restrict : 'A', // only activate on element attribute
require : '',
link : function(scope, element, attrs) {
- var txt = attrs.i18n || element[0].innerText;
+ var txt = attrs.i18n || element.text();
element.text($L.get(txt));
}
};
diff --git a/securis/src/main/resources/static/js/licenses.js b/securis/src/main/resources/static/js/licenses.js
index 286500f..3db4b48 100644
--- a/securis/src/main/resources/static/js/licenses.js
+++ b/securis/src/main/resources/static/js/licenses.js
@@ -8,8 +8,87 @@
'$http',
'toaster',
'Catalogs',
- function($scope, $http, toaster, Catalogs) {
+ '$store',
+ '$L',
+ function($scope, $http, toaster, Catalogs, $store, $L) {
+ $scope.currentPack = $store.get('currentPack');
+ $scope.packs = [
+ {id: 1,
+ "organization_name": "BP-Spain",
+ "application_name": "CurisIntegrity",
+ "licensetype_code": "CIBS",
+ "code": "BP-SA-0001",
+ "licenses": 50,
+ "lic_available": 23},
+ {id: 2,
+ "organization_name": "Exxon",
+ "application_name": "CurisData",
+ "licensetype_code": "CDL1",
+ "code": "EX-SA-0001",
+ "licenses": 1,
+ "lic_available": 0},
+ {id: 3,
+ "organization_name": "Repsol S.A. empresa con nombre muy largo",
+ "application_name": "CurisData",
+ "licensetype_code": "CDL2",
+ "code": "RE-SA-0001",
+ "licenses": 5,
+ "lic_available": 2},
+ {id: 4,
+ "organization_name": "BP-Spain",
+ "application_name": "CurisIntegrity v3.0",
+ "code": "BP-SA-0002",
+ "licensetype_code": "CISA",
+ "licenses": 150,
+ "lic_available": 13},
+ ];
+ $scope.licenses = [
+ {id: 1,
+ "code": "BP-SA-001-AKSJMS234",
+ "user_fullname": "Johnny Belmonte",
+ "user_email": "jb@curisit.net",
+ "status": 3},
+ {id: 2,
+ "code": "BP-SA-001-KAJSDHAJS",
+ "user_fullname": "Walter Simons",
+ "user_email": "ws@curisit.net",
+ "status": 1},
+ {id: 3,
+ "code": "BP-SA-001-ASKDGHKA",
+ "user_fullname": "Frank Belmonte",
+ "user_email": "fb@curisit.net",
+ "status": 2},
+ {id: 4,
+ "code": "BP-SA-001-BBBGGGG",
+ "user_fullname": "John Dalton",
+ "user_email": "jd@curisit.net",
+ "status": 3},
+ {id: 5,
+ "code": "BP-SA-001-AKADNAJANA",
+ "user_fullname": "Walter Martins",
+ "user_email": "wm@curisit.net",
+ "status": 3},
+ {id: 6,
+ "code": "BP-SA-001-AKANDAKS",
+ "user_fullname": "Joe Bolton",
+ "user_email": "jbol@curisit.net",
+ "status": 2}
+ ];
+
+
+
+ $scope.ellipsis = function(txt, len) {
+ if (!txt || txt.length <= len) return txt;
+ return txt.substring(0, len) + '...';
+ }
+
+ $scope.selectPack = function(pack) {
+ console.log('Pack selected: ' + JSON.stringify(pack));
+ $scope.currentPack = pack;
+ $store.put('currentPack', pack);
+ }
+
} ]);
})();
diff --git a/securis/src/main/resources/static/js/login.js b/securis/src/main/resources/static/js/login.js
index 29a7eae..704bdc3 100644
--- a/securis/src/main/resources/static/js/login.js
+++ b/securis/src/main/resources/static/js/login.js
@@ -3,9 +3,10 @@
var app = angular.module('securis');
- app.controller('LoginCtrl', ['$scope', '$http', '$window', '$location', 'toaster', '$L',
- function($scope, $http, $window, $location, toaster, $L) {
+ app.controller('LoginCtrl', ['$scope', '$http', '$location', 'toaster', '$L', '$store',
+ function($scope, $http, $location, toaster, $L, $store) {
+
$('#username').focus();
$scope.submit = function() {
@@ -21,14 +22,17 @@
})
}).
success(function(data, status, headers, config) {
- toaster.pop('success', $L.get('Login successful'), $L.get('User {0} has logged in SeCuris', $scope.username), 1500);
+ toaster.pop('success', $L.get('Login successful'), $L.get('User {0} has logged in application', $scope.username), 1500);
$location.path('/licenses');
+ $store.put('username', $scope.username);
+ $store.put('token', data.token);
+ $http.defaults.headers.common['X-SECURIS-TOKEN'] = data.token;
}).
error(function(data, status, headers, config) {
- console.error(data + " status: "+ status);
if (status === 403 /* forbidden */) {
toaster.pop('error', $L.get('Login error'), $L.get('Invalid credentials'), 3000);
} else {
+ console.error(data + " status: "+ status);
toaster.pop('error', $L.get('Unexpected Login error'), $L.get('Unexpected error HTTP ({0}) accessing to server. Contact with the administrator.', status), 5000);
}
$('#username').focus();
diff --git a/securis/src/main/resources/static/js/main.js b/securis/src/main/resources/static/js/main.js
index 8428bc3..14521b6 100644
--- a/securis/src/main/resources/static/js/main.js
+++ b/securis/src/main/resources/static/js/main.js
@@ -2,35 +2,84 @@
'use strict';
var m = angular.module('securis', [ 'ngRoute', 'ngResource', 'toaster', 'localytics.directives', 'catalogs', 'i18n' ]);
+
+ m.service('$store', function() {
+ this.get = function(key, defaultValue) {
+ return store.get(key) || defaultValue;
+ }
+ this.set = this.put = function(key, value) {
+ store.set(key, value);
+ }
+ this.remove = this.delete = function(key) {
+ return store.remove(key);
+ }
+ this.clear = this.clearAll = function() {
+ store.clear();
+ }
+ this.getAll = function() {
+ return store.getAll();
+ }
+ });
- m.config(function($routeProvider, $locationProvider) {
+ m.factory('securisHttpInterceptor', function($q, $location, $store) {
+ var isUnauthorizedAccess = function(rejection) {
+ console.log('rejection -----------------------');
+ console.log(rejection);
+ return rejection.status === 401 /* Unauthorized */;
+ }
+ return {
+
+ 'responseError': function(rejection) {
+ // do something on error
+ if (isUnauthorizedAccess(rejection)) {
+ if ($location.path() !== '/login') {
+ $store.clear();
+ $location.path('/login');
+ console.error('There was an unathorized access to url {0}, method: {1}'.$i18n(rejection.config.url, rejection.config.method));
+ } else {
+ // console.log('Error on login ...')
+ }
+ }
+ return $q.reject(rejection);
+ }
+ };
+ });
+
+ m.config(function($routeProvider, $locationProvider, $httpProvider) {
console.log('Configuring routes...');
$routeProvider.when('/login', {
templateUrl: 'login.html',
- controller: 'LoginCtrl',
- controllerAs: 'login'
+ controller: 'LoginCtrl'
});
$routeProvider.when('/licenses', {
templateUrl: 'licenses.html',
- controller: 'LicensesCtrl',
- controllerAs: 'licenses'
+ controller: 'LicensesCtrl'
});
$routeProvider.when('/admin', {
templateUrl: 'admin.html',
- controller: 'AdminCtrl',
- controllerAs: 'admin'
+ controller: 'AdminCtrl'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
+ $httpProvider.interceptors.push('securisHttpInterceptor');
});
- m.controller('MainCtrl', ['$scope', '$location', '$L',
- function($scope, $location, $L) {
- console.log('Moving to login...');
- console.log('Test 1 lang: ' + 'Hello {0}!! this is {1}'.$i18n('World', 'cool'));
- console.log('Test 2 lang: ' + $L.get('Hello Pepe!!'));
- $location.path('/login');
- }]);
+ m.controller('MainCtrl', ['$scope', '$http', '$location', '$L', '$store',
+ function($scope, $http, $location, $L, $store) {
+ if ($store.get('token') != null) {
+ $http.defaults.headers.common['X-SECURIS-TOKEN'] = $store.get('token');
+ $location.path('/licenses');
+ } else {
+ $location.path('/login');
+ }
+
+ $scope.logout = function() {
+ $store.remove('user');
+ $store.remove('token');
+ $location.path('/login');
+ }
+
+ }]);
})();
\ No newline at end of file
diff --git a/securis/src/main/resources/static/js/store.js b/securis/src/main/resources/static/js/store.js
new file mode 100644
index 0000000..cf38791
--- /dev/null
+++ b/securis/src/main/resources/static/js/store.js
@@ -0,0 +1,165 @@
+;(function(win){
+ var store = {},
+ doc = win.document,
+ localStorageName = 'localStorage',
+ scriptTag = 'script',
+ storage
+
+ store.disabled = false
+ store.set = function(key, value) {}
+ store.get = function(key) {}
+ store.remove = function(key) {}
+ store.clear = function() {}
+ store.transact = function(key, defaultVal, transactionFn) {
+ var val = store.get(key)
+ if (transactionFn == null) {
+ transactionFn = defaultVal
+ defaultVal = null
+ }
+ if (typeof val == 'undefined') { val = defaultVal || {} }
+ transactionFn(val)
+ store.set(key, val)
+ }
+ store.getAll = function() {}
+ store.forEach = function() {}
+
+ store.serialize = function(value) {
+ return JSON.stringify(value)
+ }
+ store.deserialize = function(value) {
+ if (typeof value != 'string') { return undefined }
+ try { return JSON.parse(value) }
+ catch(e) { return value || undefined }
+ }
+
+ // Functions to encapsulate questionable FireFox 3.6.13 behavior
+ // when about.config::dom.storage.enabled === false
+ // See https://github.com/marcuswestin/store.js/issues#issue/13
+ function isLocalStorageNameSupported() {
+ try { return (localStorageName in win && win[localStorageName]) }
+ catch(err) { return false }
+ }
+
+ if (isLocalStorageNameSupported()) {
+ storage = win[localStorageName]
+ store.set = function(key, val) {
+ if (val === undefined) { return store.remove(key) }
+ storage.setItem(key, store.serialize(val))
+ return val
+ }
+ store.get = function(key) { return store.deserialize(storage.getItem(key)) }
+ store.remove = function(key) { storage.removeItem(key) }
+ store.clear = function() { storage.clear() }
+ store.getAll = function() {
+ var ret = {}
+ store.forEach(function(key, val) {
+ ret[key] = val
+ })
+ return ret
+ }
+ store.forEach = function(callback) {
+ for (var i=0; i<storage.length; i++) {
+ var key = storage.key(i)
+ callback(key, store.get(key))
+ }
+ }
+ } else if (doc.documentElement.addBehavior) {
+ var storageOwner,
+ storageContainer
+ // Since #userData storage applies only to specific paths, we need to
+ // somehow link our data to a specific path. We choose /favicon.ico
+ // as a pretty safe option, since all browsers already make a request to
+ // this URL anyway and being a 404 will not hurt us here. We wrap an
+ // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
+ // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
+ // since the iframe access rules appear to allow direct access and
+ // manipulation of the document element, even for a 404 page. This
+ // document can be used instead of the current document (which would
+ // have been limited to the current path) to perform #userData storage.
+ try {
+ storageContainer = new ActiveXObject('htmlfile')
+ storageContainer.open()
+ storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
+ storageContainer.close()
+ storageOwner = storageContainer.w.frames[0].document
+ storage = storageOwner.createElement('div')
+ } catch(e) {
+ // somehow ActiveXObject instantiation failed (perhaps some special
+ // security settings or otherwse), fall back to per-path storage
+ storage = doc.createElement('div')
+ storageOwner = doc.body
+ }
+ function withIEStorage(storeFunction) {
+ return function() {
+ var args = Array.prototype.slice.call(arguments, 0)
+ args.unshift(storage)
+ // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
+ // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
+ storageOwner.appendChild(storage)
+ storage.addBehavior('#default#userData')
+ storage.load(localStorageName)
+ var result = storeFunction.apply(store, args)
+ storageOwner.removeChild(storage)
+ return result
+ }
+ }
+
+ // In IE7, keys may not contain special chars. See all of https://github.com/marcuswestin/store.js/issues/40
+ var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
+ function ieKeyFix(key) {
+ return key.replace(forbiddenCharsRegex, '___')
+ }
+ store.set = withIEStorage(function(storage, key, val) {
+ key = ieKeyFix(key)
+ if (val === undefined) { return store.remove(key) }
+ storage.setAttribute(key, store.serialize(val))
+ storage.save(localStorageName)
+ return val
+ })
+ store.get = withIEStorage(function(storage, key) {
+ key = ieKeyFix(key)
+ return store.deserialize(storage.getAttribute(key))
+ })
+ store.remove = withIEStorage(function(storage, key) {
+ key = ieKeyFix(key)
+ storage.removeAttribute(key)
+ storage.save(localStorageName)
+ })
+ store.clear = withIEStorage(function(storage) {
+ var attributes = storage.XMLDocument.documentElement.attributes
+ storage.load(localStorageName)
+ for (var i=0, attr; attr=attributes[i]; i++) {
+ storage.removeAttribute(attr.name)
+ }
+ storage.save(localStorageName)
+ })
+ store.getAll = function(storage) {
+ var ret = {}
+ store.forEach(function(key, val) {
+ ret[key] = val
+ })
+ return ret
+ }
+ store.forEach = withIEStorage(function(storage, callback) {
+ var attributes = storage.XMLDocument.documentElement.attributes
+ for (var i=0, attr; attr=attributes[i]; ++i) {
+ callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
+ }
+ })
+ }
+
+ try {
+ var testKey = '__storejs__'
+ store.set(testKey, testKey)
+ if (store.get(testKey) != testKey) { store.disabled = true }
+ store.remove(testKey)
+ } catch(e) {
+ store.disabled = true
+ }
+ store.enabled = !store.disabled
+
+ if (typeof module != 'undefined' && module.exports) { module.exports = store }
+ else if (typeof define === 'function' && define.amd) { define(store) }
+ else { win.store = store }
+
+})(this.window || global);
diff --git a/securis/src/main/resources/static/js/store.min.js b/securis/src/main/resources/static/js/store.min.js
new file mode 100644
index 0000000..133226c
--- /dev/null
+++ b/securis/src/main/resources/static/js/store.min.js
@@ -0,0 +1,2 @@
+/* Copyright (c) 2010-2013 Marcus Westin */
+(function(e){function o(){try{return r in e&&e[r]}catch(t){return!1}}var t={},n=e.document,r="localStorage",i="script",s;t.disabled=!1,t.set=function(e,t){},t.get=function(e){},t.remove=function(e){},t.clear=function(){},t.transact=function(e,n,r){var i=t.get(e);r==null&&(r=n,n=null),typeof i=="undefined"&&(i=n||{}),r(i),t.set(e,i)},t.getAll=function(){},t.forEach=function(){},t.serialize=function(e){return JSON.stringify(e)},t.deserialize=function(e){if(typeof e!="string")return undefined;try{return JSON.parse(e)}catch(t){return e||undefined}};if(o())s=e[r],t.set=function(e,n){return n===undefined?t.remove(e):(s.setItem(e,t.serialize(n)),n)},t.get=function(e){return t.deserialize(s.getItem(e))},t.remove=function(e){s.removeItem(e)},t.clear=function(){s.clear()},t.getAll=function(){var e={};return t.forEach(function(t,n){e[t]=n}),e},t.forEach=function(e){for(var n=0;n<s.length;n++){var r=s.key(n);e(r,t.get(r))}};else if(n.documentElement.addBehavior){var u,a;try{a=new ActiveXObject("htmlfile"),a.open(),a.write("<"+i+">document.w=window</"+i+'><iframe src="/favicon.ico"></iframe>'),a.close(),u=a.w.frames[0].document,s=u.createElement("div")}catch(f){s=n.createElement("div"),u=n.body}function l(e){return function(){var n=Array.prototype.slice.call(arguments,0);n.unshift(s),u.appendChild(s),s.addBehavior("#default#userData"),s.load(r);var i=e.apply(t,n);return u.removeChild(s),i}}var c=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g");function h(e){return e.replace(c,"___")}t.set=l(function(e,n,i){return n=h(n),i===undefined?t.remove(n):(e.setAttribute(n,t.serialize(i)),e.save(r),i)}),t.get=l(function(e,n){return n=h(n),t.deserialize(e.getAttribute(n))}),t.remove=l(function(e,t){t=h(t),e.removeAttribute(t),e.save(r)}),t.clear=l(function(e){var t=e.XMLDocument.documentElement.attributes;e.load(r);for(var n=0,i;i=t[n];n++)e.removeAttribute(i.name);e.save(r)}),t.getAll=function(e){var n={};return t.forEach(function(e,t){n[e]=t}),n},t.forEach=l(function(e,n){var r=e.XMLDocument.documentElement.attributes;for(var i=0,s;s=r[i];++i)n(s.name,t.deserialize(e.getAttribute(s.name)))})}try{var p="__storejs__";t.set(p,p),t.get(p)!=p&&(t.disabled=!0),t.remove(p)}catch(f){t.disabled=!0}t.enabled=!t.disabled,typeof module!="undefined"&&module.exports?module.exports=t:typeof define=="function"&&define.amd?define(t):e.store=t})(this.window||global)
\ No newline at end of file
diff --git a/securis/src/main/resources/static/licenses.html b/securis/src/main/resources/static/licenses.html
index a3f3c43..53e911a 100644
--- a/securis/src/main/resources/static/licenses.html
+++ b/securis/src/main/resources/static/licenses.html
@@ -1,32 +1,145 @@
- <div class="navbar navbar-inverse navbar-fixed-top">
- <div class="container">
- <div class="navbar-header">
- <button type="button" class="navbar-toggle" data-toggle="collapse"
- data-target=".navbar-collapse">
- <span class="icon-bar"></span> <span class="icon-bar"></span> <span
- class="icon-bar"></span>
- </button>
- <a class="navbar-brand" href="#">SeCuris</a>
- </div>
- <div class="navbar-collapse collapse">
- <ul class="nav navbar-nav navbar-right">
- <li><a href="#about">About</a></li>
- <li><a href="#contact">Contact</a></li>
- </ul>
- </div>
- </div>
- </div>
-
- <!-- Main jumbotron for a primary marketing message or call to action -->
- <div class="jumbotron">
- <div class="container">
- <h2>SeCuris</h2>
- <p>Licenses management</p>
- </div>
- </div>
+ <div ng-include="'header.html'" ></div>
<div class="container">
+ <div class="col-md-12"> </div>
+ <div id="packs_section" class="col-md-6">
+ <nav class="navbar navbar-default navbar-static-top">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <a class="navbar-brand" i18n >Packs</a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse"
+ id="bs-example-navbar-collapse-1">
+ <ul class="nav navbar-nav">
+ <li><a i18n ng-click="editNew()"><span class="glyphicon glyphicon-plus"></span>
+ New</a></li>
+ <li><a i18n ng-click="cancel()"> <span
+ class="glyphicon glyphicon-ban-circle"></span> Cancel
+ </a></li>
+ </ul>
+ <div class="navbar-form navbar-right">
+ <div class="input-group input-group-sm">
+ <span class="input-group-addon glyphicon glyphicon-search" style="top: 0px;"></span>
+ <input type="text" class="form-control" placeholder="Search" ng-model="$parent.searchText" >
+ <span class="btn input-group-addon glyphicon glyphicon-remove" ng-click="$parent.searchText = ''" style="top: 0px;"></span>
+ </div>
+ </div>
+ </div>
+ </nav>
+ <div class="panel panel-default" >
+ <div class="panel-heading">
+ Packs <span class="badge pull-right" ng-bind="packs.length || 0"></span>
+ </div>
+
+ <table class="table table-hover table-condensed">
+ <thead>
+ <tr>
+ <th i18n >Organization</th>
+ <th i18n >Application</th>
+ <th i18n >Code</th>
+ <th i18n >Licenses</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="pack in packs | filter:searchText" ng-dblclick="editPack(row)" ng-class="{success: currentPack.id === pack.id}" ng-click="selectPack(pack)">
+ <td ng-bind="ellipsis(pack.organization_name, 20)" title="{{pack.organization_name}}" ></td>
+ <td ng-bind="pack.application_name"></td>
+ <td style="white-space: nowrap;" ng-bind="pack.code"></td>
+ <td title="Total: {{pack.licenses}}, avaliable: {{pack.lic_available}}">{{pack.licenses}} ({{pack.lic_available}})</td>
+ <td><span ng-click="editPack(row)"
+ class="glyphicon glyphicon-pencil"></span>
+ <span ng-click="deletePack(row)"
+ class="glyphicon glyphicon-remove"></span>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ </tfoot>
+ </table>
+ </div>
+ </div>
+
+ <div id="licenses_section" class="col-md-6" >
+ <nav class="navbar navbar-default navbar-static-top" ng-disabled="!!currentPack">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header success">
+ <a class="navbar-brand" i18n>Licenses</a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse"
+ id="bs-example-navbar-collapse-1">
+ <ul class="nav navbar-nav">
+ <li><a i18n ng-click="editNewLicense()"><span class="glyphicon glyphicon-plus"></span>
+ New</a></li>
+ <li><a i18n ng-click="cancelEditionLicense()"> <span
+ class="glyphicon glyphicon-ban-circle"></span> Cancel
+ </a></li>
+ </ul>
+ <div class="navbar-form navbar-right">
+ <div class="input-group input-group-sm">
+ <span class="input-group-addon glyphicon glyphicon-search" style="top: 0px;"></span>
+ <input type="text" class="form-control" placeholder="Search" ng-model="$searchPacksText" >
+ <span class="btn input-group-addon glyphicon glyphicon-remove" ng-click="$searchPacksText = ''" style="top: 0px;"></span>
+ </div>
+ </div>
+ </div>
+ </nav>
+
+ <div ng-if="!currentPack" class="well well-lg">
+ <h4 i18n>No pack selected</h4>
+ <p i18n>Please, select a pack to manage its licenses</p>
+ </div>
+
+ <div class="panel panel-default" ng-if="currentPack">
+ <div class="panel-heading">
+ <span i18n>Licenses for pack: </span>{{currentPack.code}}
+ <span style="color: lightgreen;" class="badge pull-right" ng-bind="currentPack.lic_available || 0"></span>
+ <span class="badge pull-right" ng-bind="licenses.length || 0"></span>
+ </div>
+
+
+ <table class="table table-hover table-condensed" >
+ <thead>
+ <tr>
+ <th i18n >License code</th>
+ <th i18n >User fullname</th>
+ <th i18n >Email</th>
+ <th i18n >Status</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="lic in licenses | filter:searchLicenseText" ng-dblclick="editLicense(lic)" >
+ <td style="white-space: nowrap;" ng-bind="lic.code"></td>
+ <td ng-bind="ellipsis(lic.user_fullname, 20)" title="{{lic.user_fullname}}" ></td>
+ <td ng-bind="ellipsis(lic.user_email, 30)" title="{{lic.user_email}}" ></td>
+ <td ng-bind="lic.status"></td>
+ <td>
+ <div class="dropdown">
+ <a class="dropdown-toggle" data-toggle="dropdown" >
+ <span class="glyphicon glyphicon-align-justify"></span> <span class="caret"></span>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a ng-click="editLicense(lic)"><span class="glyphicon glyphicon-pencil"></span> <span i18n>Edit</span></a></li>
+ <li><a ng-click="activateLicense(lic)"><span class="glyphicon glyphicon-check"></span> <span i18n>Activate</span></a></li>
+ <li><a ng-click="sendEmail(lic)"><span class="glyphicon glyphicon-send"></span> <span i18n>Send email</span></a></li>
+ <li><a ng-click="editLicense(lic)"><span class="glyphicon glyphicon-remove"></span> <span i18n>Remove</span></a></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ <tfoot>
+ </tfoot>
+ </table>
+ </div>
+
+ </div>
</div>
diff --git a/securis/src/main/resources/static/main.html b/securis/src/main/resources/static/main.html
index aad1333..a99b9a5 100644
--- a/securis/src/main/resources/static/main.html
+++ b/securis/src/main/resources/static/main.html
@@ -45,6 +45,8 @@
<script type="text/javascript"
src="/js/angular-resource.min.js"></script>
<script type="text/javascript"
+ src="/js/angular-resource.min.js"></script>
+ <script type="text/javascript"
src="/js/bootstrap-dialog.js"></script>
<script type="text/javascript"
src="/js/toaster.js"></script>
@@ -54,21 +56,17 @@
src="/js/vendor/chosen.jquery.js"></script>
<script type="text/javascript"
src="/js/chosen.js"></script>
+ <script type="text/javascript"
+ src="/js/store.min.js"></script>
<script type="text/javascript" src="js/i18n.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<script type="text/javascript" src="js/login.js"></script>
<script type="text/javascript" src="js/catalogs.js"></script>
+ <script type="text/javascript" src="js/licenses.js"></script>
<script type="text/javascript" src="js/admin.js"></script>
- <!-- <script src="js/main.js"></script> -->
- <script type="text/javascript">
- $(function() {
- });
-
- </script>
-
- <toaster-container toaster-options="{'time-out': 3000}"></toaster-container>
+ <toaster-container toaster-options="{'time-out': 3000}"></toaster-container>
</div>
</body>
</html>
\ No newline at end of file
--
Gitblit v1.3.2