http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css index ec5baca..41ba63c 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/editUser.css @@ -17,6 +17,8 @@ specific language governing permissions and limitations under the License. */ +/* Default style +============================================================================= */ * { box-sizing: border-box; } @@ -27,6 +29,7 @@ under the License. margin-top:-4px; margin: 0 auto; text-align: center; + background-color: #F7F7F7; } #form-container .breadcrumb-header{ @@ -35,20 +38,23 @@ under the License. padding:10px; } -#form-container .page-header { background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */ - margin: 1% 9%; - width: 83%; padding:10px; - /* shadows and rounded borders */ - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px; - -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); - box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); +#form-container .page-header { + background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */ + margin: 1% 9%; + width: 83%; padding:10px; + /* shadows and rounded borders */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); + text-align: left; + font-weight: 700; } .signup-form { @@ -93,79 +99,41 @@ under the License. list-style: none; } -#previous { - background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /*FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /*Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Opera 11.10+*/ - background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*IE10+*/ - display: inline-block; - color: black; - padding-left: 8px; - padding-right: 8px; - margin-left: 5px; -} - -#previous:hover { - background: #658D5D; -} - -#next{ - background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /*FF3.6+ */ +#next, +#previous, +#save, +#finish { + background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /*FF3.6+*/ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /*Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Opera 11.10+ */ background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*IE10+ */ display: inline-block; - margin-left: 5px; + padding-left: 8px; padding-right: 8px; - float: right; + margin-left: 5px; + border: none; color: black; } +#save:hover, +#previous:hover, +#finish:hover, #next:hover { background: #658D5D; } -#save{ - background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /*FF3.6+*/ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /*Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Opera 11.10+ */ - background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*IE10+ */ - color: black; - display: inline-block; - padding-left: 8px; - padding-right: 8px; - margin-left: 5px; +#save { margin-right: 5px; } -#save:hover { - background: #658D5D; -} - -#finish{ - background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /*FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /*Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Chrome10+,Safari5.1+*/ - background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*Opera 11.10+ */ - background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /*IE10+*/ - display: inline-block; - margin-left:5px; - padding-left: 8px; - padding-right: 8px; - color: black; - margin-left: 5px; +#finish { margin-right: 5px; } -#finish:hover { - background: #658D5D; -} - #cancel { + color: #fff; margin-top: 0%; } @@ -228,31 +196,23 @@ span.k-datetimepicker{ /** Button breadcrumb **/ .btn-breadcrumb .btn:not(:last-child):after { - content: " "; - display: block; - width: 0; - height: 0; - border-top: 17px solid transparent; - border-bottom: 17px solid transparent; border-left: 10px solid white; - position: absolute; - top: 50%; - margin-top: -17px; - left: 100%; - z-index: 3; } .btn-breadcrumb .btn:not(:last-child):before { + margin-left: 1px; + border-left: 10px solid rgb(173, 173, 173); +} +.btn-breadcrumb .btn:not(:last-child):before, +.btn-breadcrumb .btn:not(:last-child):after { content: " "; display: block; width: 0; height: 0; border-top: 17px solid transparent; border-bottom: 17px solid transparent; - border-left: 10px solid rgb(173, 173, 173); position: absolute; top: 50%; margin-top: -17px; - margin-left: 1px; left: 100%; z-index: 3; } @@ -268,31 +228,72 @@ span.k-datetimepicker{ padding:6px 18px 6px 24px; } -/** Default button **/ -.btn-breadcrumb .btn.btn-default:not(:last-child):after { +/** Default buttons **/ +.breadcrumb-disabled-link { + pointer-events: none; + cursor: default; +} + +.breadcrumb-btn-elem { + border-color: #ccc; +} + +.btn-breadcrumb .breadcrumb-btn-elem:not(:last-child):after { border-left: 10px solid #fff; } -.btn-breadcrumb .btn.btn-default:not(:last-child):before { +.btn-breadcrumb .breadcrumb-btn-elem:not(:last-child):before { border-left: 10px solid #ccc; } -.btn-breadcrumb .btn.btn-default:hover:not(:last-child):after { + +.btn-breadcrumb .breadcrumb-btn-elem.active:not(:last-child):after, +.btn-breadcrumb .breadcrumb-btn-elem:hover:not(:last-child):after { border-left: 10px solid #ebebeb; } -.btn-breadcrumb .btn.btn-default:hover:not(:last-child):before { +.btn-breadcrumb .breadcrumb-btn-elem.active:not(:last-child):before, +.btn-breadcrumb .breadcrumb-btn-elem:hover:not(:last-child):before { border-left: 10px solid #adadad; } -.btn-breadcrumb .btn.btn-default.active:not(:last-child):after { - border-left: 10px solid #e6e6e6; +.btn-breadcrumb .breadcrumb-btn-elem.active { + box-shadow: 0 0px 0px rgba(0, 0, 0, 0.125) +} +.btn-breadcrumb .breadcrumb-btn-elem:focus { + box-shadow: none !important; } -.btn-breadcrumb .btn.btn-default.active { - box-shadow: 0 0px 0px rgba(0, 0, 0, 0.125) +.btn-breadcrumb .btn:before, +.btn-breadcrumb .btn:after { + transition: all .15s ease-in-out; } -.breadcrumb-disabled-link { - pointer-events: none; - cursor: default; +div[role="tablist"] { + margin-bottom: 20px; +} + +/* For Bootstrap 4 */ + +/* +.btn-breadcrumb .breadcrumb-btn-elem:hover { + color: #ffffff !important; +} + +.btn-breadcrumb .breadcrumb-btn-elem:not(:hover), +.btn-breadcrumb .breadcrumb-home:not(:hover) { + color: #333; + background-color: #fff; +} + +.btn-breadcrumb .breadcrumb-btn-elem:hover:not(:last-child):after, +.btn-breadcrumb .breadcrumb-btn-elem:hover:not(:last-child):before, +.btn-breadcrumb .breadcrumb-btn-elem.active:not(:last-child):after, +.btn-breadcrumb .breadcrumb-btn-elem.active:not(:last-child):before { + border-left: 10px solid #4c4c4c; +} +*/ + +.btn-file { + background: transparent; + color: black; } .text-validation-error{ @@ -300,9 +301,81 @@ span.k-datetimepicker{ font-weight: 600; } -/*--------------end default style*/ +.multivalue button{ + float: right +} +.schema-type #date{ + margin-top: 35px; + margin-bottom: 2px; +} + +.multivalue input{ + width: calc(100% - 70px); + margin-top: 10px +} + +.multivalue input:disabled{ + width: 100%; +} + +.multivalue button{ + margin-top: 2px +} + +.multivalue #datetime{ + margin-top: 0px +} + +#datetime input{ + width: 100%; + margin-top: 0px +} +#timepicker input{ + width: 50px; + margin-top: 0px +} -/*style for devices max width 350 */ +.multivalue #timepicker { + margin-top: -35px; +} + +.suggestions{ + font-size: 10px; + display: inline-block; + margin-bottom: 5px; +} + +#status-buttons { + padding-left: 15px; + -webkit-flex-flow: row wrap; /* Safari 6.1+ */ + flex-flow: row wrap; +} + +.card.card-open { + background-color: #ffffff; +} + +.card-header a { + text-decoration: none; +} + +.card-header h5 a { + color: black; +} + +.card-header { + padding: 2px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + background-color: #f5f5f5; + border-color: #ddd; +} +/* end default style +============================================================================= */ + +/* Style for devices max width 350 +============================================================================= */ @media only screen and (max-width: 350px) { input[type=file] { @@ -337,39 +410,42 @@ span.k-datetimepicker{ padding: 0px 0px 1px 0px } - #finish{ + #finish, + #save, + #next, + #previous { padding-left: 2px; padding-right: 2px; + } + + #finish{ margin-left:-27px; margin-top: 2px; } #next{ - padding-left: 2px; - padding-right: 2px; margin-left: 1px; } #previous{ - padding-left: 2px; - padding-right: 2px; margin-left:-126px; } #save{ margin-top: 4px; - padding-left: 2px; - padding-right: 2px; margin-top:-31px; margin-left: -42px; margin-right: 15px; } - + span.k-datetimepicker { width: 141%; margin-top: -50px; -} + } } +/* +============================================================================= */ -/*style for devices max width 400 */ +/* Style for devices max width 400 +============================================================================= */ @media only screen and (max-width: 400px) { input[type=file] { @@ -418,36 +494,42 @@ span.k-datetimepicker{ padding:6px 18px 6px 24px; } - #finish{ + #next, + #finish, + #previous, + #save { padding-left: 2px; + } + + #finish { padding-right: 2px; margin-right: -3px; margin-left: 0px; } - #next{ - padding-left: 2px; + #next { padding-right: 2px; margin-right: 23px; } - #previous{ - padding-left: 2px; + #previous { padding-right: 2px; margin-left: 0px } - #save{ - padding-left: 2px; + #save { padding-right: 0px; margin-left: -21px; margin-top: 4px; } - - span.k-datetimepicker{ + + span.k-datetimepicker{ width: 160%; } } +/* +============================================================================= */ -/*style for devices max width 500*/ +/* Style for devices max width 500 +============================================================================= */ @media only screen and (max-width: 500px) { * { @@ -483,17 +565,13 @@ span.k-datetimepicker{ font-size: 12px; } - .btn-group .btn+.btn, .btn-group .btn+.btn-group, .btn-group .btn-group+.btn, .btn-group .btn-group+.btn-group { + .btn-group .btn+.btn, + .btn-group .btn+.btn-group, + .btn-group .btn-group+.btn, + .btn-group .btn-group+.btn-group { margin-left: 0px; } - .btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; - /*width: 100%;*/ - } - .card-container.card { width: 295px; padding: 40px 40px 0px; @@ -543,12 +621,10 @@ span.k-datetimepicker{ .select2-results .select2-result-label{ font-size: 12px; - } .select2-container-multi .select2-choices .select2-search-field input{ font-size:12px; - } #datetime{ @@ -666,8 +742,11 @@ span.k-datetimepicker{ } } +/* +============================================================================= */ -/*style for devices max width 800) */ +/* Style for devices max width 800) +============================================================================= */ @media only screen and (max-width: 800px) { * { @@ -702,6 +781,8 @@ span.k-datetimepicker{ } } +/* +============================================================================= */ /* ANIMATIONS ============================================================================= */ @@ -729,41 +810,5 @@ span.k-datetimepicker{ from { -webkit-transform:translateX(300%); } to { -webkit-transform: translateX(0); } } - -.multivalue button{ - float: right -} -.schema-type #date{ - margin-top: 35px; - margin-bottom: 2px; -} - -.multivalue input{ - width: calc(100% - 70px); - margin-top: 10px -} - -.multivalue input:disabled{ - width: 100%; -} - -.multivalue button{ - margin-top: 2px -} - -.multivalue #datetime{ - margin-top: 0px -} - -#datetime input{ - width: 100%; - margin-top: 0px -} -#timepicker input{ - width: 50px; - margin-top: 0px -} - -.multivalue #timepicker { - margin-top: -35px; -} +/* +============================================================================= */
http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/login.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/login.css b/client/enduser/src/main/resources/META-INF/resources/app/css/login.css index a517ae5..03212f3 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/css/login.css +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/login.css @@ -54,26 +54,6 @@ body{ float: right; } -.card-container.card { - width: 350px; - padding: 40px 40px 0px; -} - -.card { - background-color: #F7F7F7; - /* just in case there no content*/ - padding: 20px 25px 30px; - margin: 0 auto 25px; - margin-top: 50px; - /* shadows and rounded borders */ - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); - box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -} - .login-logo { width: 200px; margin: 0px auto 10px; @@ -93,22 +73,11 @@ body{ box-sizing: border-box; } -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857; - color: #555; - background-color: #FFF; - background-image: none; - border: 1px solid #CCC; - border-radius: 4px; - box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset; - transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s; -} - input[type="number"]{ padding-right: 0px !important } + +.dropdown-toggle { + width: 100%; + text-align: left; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/notification.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/notification.css b/client/enduser/src/main/resources/META-INF/resources/app/css/notification.css new file mode 100644 index 0000000..f2d190e --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/notification.css @@ -0,0 +1,28 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +.k-notification-wrap { + white-space: normal !important; + word-wrap: break-word !important; +} + +.k-icon { + margin-right: 5px; + vertical-align: sub; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/passwordReset.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/passwordReset.css b/client/enduser/src/main/resources/META-INF/resources/app/css/passwordReset.css new file mode 100644 index 0000000..4f03f25 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/passwordReset.css @@ -0,0 +1,37 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +#resetpassword { + background: -moz-linear-gradient(top, #a9db80 0%, #96c56f 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a9db80), color-stop(100%,#96c56f)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #a9db80 0%,#96c56f 100%); /* IE10+ */ + margin-left: 5px; + color: black; + border: none; +} +#resetpassword:hover { + background: #658D5D; +} + +#captchaImg { + display: block; + margin: 0 auto; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css new file mode 100644 index 0000000..dd0d351 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/editUser.css @@ -0,0 +1,95 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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, +body { + height: 100%; +} +body { + background: -moz-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* ff3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(101,141,93,1)), color-stop(100%, rgba(51,51,51,1))); /* safari4+,chrome */ + background: -webkit-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* safari5.1+,chrome10+ */ + background: -o-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* opera 11.10+ */ + background: -ms-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* ie10+ */ + background: linear-gradient(356deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* w3c */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#658d5d', endColorstr='#333333',GradientType=0 ); /* ie6-9 */ +} + +#form-container .page-header, +#previous, +#next, +#save, +#finish, +#resetpassword { + background: -moz-linear-gradient(top, #6a9647 0%, #48543d 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6a9647), color-stop(100%,#48543d)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #6a9647 0%,#48543d 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #6a9647 0%,#48543d 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #6a9647 0%,#48543d 100%); /* IE10+ */ + color: white; +} + +#form-container .btn-danger { + background-color: #a93f3c; + border-color: #ffffff; +} + + +#form-container, +#form-container .panel { + background-color: #151515; + color: white; +} + +#form-container input, +#form-container select, +#form-container select option, +#form-container label { + color: white; +} + +#form-container input:disabled { + background: #6d6d6d; +} + +#form-container input, +#form-container select, +#form-container select option, +span.k-datepicker, +span.k-timepicker, +span.k-datetimepicker, +span.k-colorpicker, +span.k-numerictextbox, +span.k-combobox, +span.k-dropdown, +.k-toolbar .k-split-button, +.k-autocomplete.k-state-default, +.k-picker-wrap.k-state-default, +.k-numeric-wrap.k-state-default, +.k-dropdown-wrap.k-state-default { + background: #313131; +} + +.card-header h5 a { + color: white; +} + +.card-header { + background-color: #49553e; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/login.css ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/login.css b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/login.css new file mode 100644 index 0000000..90da4b0 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/css/templates/dark/login.css @@ -0,0 +1,78 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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, +body { + height: 100%; +} +body { + background: -moz-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* ff3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(101,141,93,1)), color-stop(100%, rgba(51,51,51,1))); /* safari4+,chrome */ + background: -webkit-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* safari5.1+,chrome10+ */ + background: -o-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* opera 11.10+ */ + background: -ms-linear-gradient(94deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* ie10+ */ + background: linear-gradient(356deg, rgba(51,51,51,1) 0%, rgba(101,141,93,1) 100%); /* w3c */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#658d5d', endColorstr='#333333',GradientType=0 ); /* ie6-9 */ +} + +#login-container .card { + background-color: #151515; + color: white; +} + +#login-container .login-logo { + background-color: rgba(255, 255, 255, 0.15); + border-radius: 10px; + + margin: 0px auto 20px auto; +} + +#login-container input, +#login-container select, +#login-container select option { + color: white; + background: #313131; +} + +#login-container input:disabled { + background: #6d6d6d; +} + +#login-container .btn-link { + color: #82b9e8; +} +#login-container .btn-link:focus, +#login-container .btn-link:hover { + color: #b5dcff; +} + +#login-container .login-btn { + color: white; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6a9647), color-stop(100%,#48543d)); + + background: linear-gradient(top, #6a9647 0%,#48543d 100%); + background: -webkit-linear-gradient(top, #6a9647 0%,#48543d 100%); + background: -moz-linear-gradient(top, #6a9647 0%, #48543d 100%); + background: -o-linear-gradient(top, #6a9647 0%,#48543d 100%); + background: -ms-linear-gradient(top, #6a9647 0%,#48543d 100%); +} + +#login-container .form-group { + margin-bottom: 20px; +} http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/index.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/index.html b/client/enduser/src/main/resources/META-INF/resources/app/index.html index 3aa57f5..6ef3c4d 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/index.html +++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html @@ -32,11 +32,10 @@ under the License. <link rel="shortcut icon" href="img/favicon.png" type="image/png"/> - <link href="css/login.css" rel="stylesheet" type="text/css"/> <link href="../webjars/jquery-ui/${jquery-ui.version}/jquery-ui.css" rel="stylesheet" type="text/css"/> <link href="../webjars/bootstrap/${bootstrap.version}/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> <link href="../webjars/bootstrap-select/${bootstrap-select.version}/css/bootstrap-select.min.css" rel="stylesheet" type="text/css"/> - <link href="../webjars/font-awesome/${font-awesome.version}/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> + <link href="../webjars/font-awesome/${font-awesome.version}/css/${font-awesome.filename}" rel="stylesheet" type="text/css"/> <link href="../webjars/ionicons/${ionicons.version}/css/ionicons.min.css" rel="stylesheet" type="text/css"/> <link href="../webjars/angular-ui-select/${angular-ui-select.version}/select.css" rel="stylesheet" type="text/css"/> <link href="../webjars//kendo-ui-core/${kendo-ui-core.version}/styles/web/kendo.common.core.min.css" rel="stylesheet" type="text/css"/> @@ -44,9 +43,8 @@ under the License. <link href="../webjars/angular-treasure-overlay-spinner/${angular-treasure-overlay-spinner.version}/dist/treasure-overlay-spinner.min.css" rel="stylesheet" type="text/css"/> <link href="../webjars/ng-password-strength/${ng-password-strength.version}/dist/styles/main.css" rel="stylesheet" type="text/css"> <link href="../webjars/select2/${select2.version}/select2.css" rel="stylesheet"/> - <link href="css/app.css" rel="stylesheet" type="text/css"/> - <link href="css/login.css" rel="stylesheet" type="text/css"/> - <link href="css/editUser.css" rel="stylesheet" type="text/css"/> + + <link href="css/customSpinner.css" rel="stylesheet" type="text/css"/> </head> <body ng-cloak > @@ -54,10 +52,11 @@ under the License. <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> <![endif]--> - <span id="notifications" kendo-notification="notifications"></span> + <span id="notifications"></span> <treasure-overlay-spinner active='spinner.active'> - <div ui-view ng-cloak ng-controller="ApplicationController" ng-init="initApplication()"> + <div ui-view ng-cloak ng-controller="ApplicationController" ng-init="initApplication()"> + </div> </treasure-overlay-spinner> @@ -65,10 +64,11 @@ under the License. <script src="../webjars/angular/${angular.version}/angular.js"></script> <script src="../webjars/angular-ui-router/${angular-ui-router.version}/release/angular-ui-router.js"></script> <script src="../webjars/angular-animate/${angular.version}/angular-animate.js"></script> - <script src="../webjars/angular-resource/${angular.version}/angular-resource.js"></script> + <script src="../webjars/angular-resource/${angular-resource.version}/angular-resource.js"></script> <script src="../webjars/angular-cookies/${angular.version}/angular-cookies.js"></script> <script src="../webjars/angular-sanitize/${angular.version}/angular-sanitize.js"></script> - <script src="../webjars/angular-ui-bootstrap/${angular-ui-bootstrap.version}/ui-bootstrap-tpls.js"></script> + <script src="../webjars/ui-bootstrap4/${ui-bootstrap.version}/dist/ui-bootstrap.js"></script> + <script src="../webjars/ui-bootstrap4/${ui-bootstrap.version}/dist/ui-bootstrap-tpls.js"></script> <script src="../webjars/angular-ui-select/${angular-ui-select.version}/select.js"></script> <script src="../webjars/kendo-ui-core/${kendo-ui-core.version}/js/kendo.ui.core.min.js"></script> <script src="../webjars/kendo-ui-core/${kendo-ui-core.version}/js/kendo.notification.min.js"></script> @@ -79,11 +79,11 @@ under the License. <script src="../webjars/kendo-ui-core/${kendo-ui-core.version}/js/cultures/kendo.culture.ja.js"></script> <script src="../webjars/angular-treasure-overlay-spinner/${angular-treasure-overlay-spinner.version}/dist/treasure-overlay-spinner.min.js"></script> <script src="../webjars/ng-password-strength/${ng-password-strength.version}/dist/scripts/ng-password-strength.min.js"></script> - <script type="text/javascript" src="../webjars/bootstrap-select/${bootstrap-select.version}/js/bootstrap-select.min.js"></script> + <script src="../webjars/bootstrap-select/${bootstrap-select.version}/js/bootstrap-select.min.js"></script> <script src="../webjars/FileSaver.js/${fileSaver.version}/FileSaver.js"></script> <script src="../webjars/lodash/${lodash.version}/lodash.min.js"></script> <script src="../webjars/angular-translate/${angular-translate.version}/angular-translate.js"></script> - <script src="../webjars/angular-translate-loader-partial/${angular-translate.version}/angular-translate-loader-partial.js"></script> + <script src="../webjars/angular-translate-loader-partial/${angular-translate-loader-partial.version}/angular-translate-loader-partial.js"></script> <script src="../webjars/angular-translate-storage-cookie/${angular-translate.version}/angular-translate-storage-cookie.js"></script> <script src="../webjars/bootstrap-fileinput/${bootstrap-fileinput.version}/js/fileinput.js"></script> @@ -96,6 +96,7 @@ under the License. <script src="js/services/realmService.js"></script> <script src="js/services/securityQuestionService.js"></script> <script src="js/services/infoService.js"></script> + <script src="js/services/dynamicTemplateService.js"></script> <script src="js/services/resourceService.js"></script> <script src="js/services/groupService.js"></script> <script src="js/services/anyService.js"></script> @@ -116,7 +117,7 @@ under the License. <script src="js/directives/dynamicPlainAttributes.js"></script> <script src="js/directives/dynamicDerivedAttributes.js"></script> <script src="js/directives/dynamicVirtualAttributes.js"></script> - <script src="js/directives/navigationButtons.js"></script> + <script src="js/directives/navigationButtonsPartial.js"></script> <script src="js/directives/loader.js"></script> <script src="js/directives/captcha.js"></script> <script src="js/directives/resources.js"></script> @@ -126,6 +127,7 @@ under the License. <script src="js/directives/validationMessage.js"></script> <script src="js/directives/validateDropdown.js"></script> <script src="js/directives/fileInput.js"></script> + <script src="js/directives/dynamicTemplateItem.js"></script> <!--validator--> <script src="js/validator/validationRules.js"></script> <script src="js/validator/validationExecutor.js"></script> @@ -134,5 +136,6 @@ under the License. <!--util--> <script src="js/util/userUtil.js"></script> <script src="js/util/genericUtil.js"></script> + <script src="js/util/assetsManager.js"></script> </body> </html> http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/app.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js index 93a4fea..bcd3fc4 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js @@ -66,12 +66,18 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$translate $stateProvider .state('home', { url: '/', - templateUrl: 'views/self.html' + templateUrl: 'views/self.html', + resolve: { + loadAssets: ['DynamicTemplateService', function (DynamicTemplateService) { + return DynamicTemplateService.getGeneralAssetsContent(["css"]); + }] + } }) .state('self', { url: '/self?errorMessage', templateUrl: 'views/self.html' }) + /* <Extensions> */ .state('self-saml2sp', { url: '/self-saml2sp', @@ -99,6 +105,7 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$translate } }) /* </Extensions> */ + .state('user-self-update', { url: '/user-self-update', templateUrl: 'views/home.html', @@ -289,8 +296,8 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$translate }; }); }]); -app.run(['$rootScope', '$location', '$state', 'AuthService', - function ($rootScope, $location, $state, AuthService) { +app.run(['$rootScope', '$location', '$state', 'AuthService', '$transitions', + function ($rootScope, $location, $state, AuthService, $transitions) { /* |-------------------------------------------------------------------------- | Main of Syncope Enduser application @@ -299,50 +306,63 @@ app.run(['$rootScope', '$location', '$state', 'AuthService', | If the route change failed due to authentication error, redirect them out |-------------------------------------------------------------------------- */ - $rootScope.$on('$routeChangeError', function (event, current, previous, rejection) { - if (rejection === 'Not Authenticated') { - $location.path('/self'); + $transitions.onError({}, function (trans) { + if (trans.error().message === 'Not Authenticated') { + $state.go('home'); } }); - $rootScope.$on('$stateChangeSuccess', function (event, toState) { + + $transitions.onSuccess({}, function (trans) { + var toState = trans.$to(); + var fromState = trans.$from(); + if (toState.name === 'create') { - $state.go('create.credentials'); + $state.go('create' + $rootScope.getWizardFirstStep()); } else if (toState.name === 'update') { - $state.go('update.credentials'); + $state.go('update' + $rootScope.getWizardFirstStep()); } else if (toState.name.indexOf("update") > -1) { AuthService.islogged().then(function (response) { if (response === "true") { $state.go(toState); } else { - $state.go('self'); + $state.go('home'); } }, function (response) { - console.error("not logged"); - $state.go('self'); + console.error("Not logged"); + $state.go('home'); } ); - } else if (toState.name === 'home' || toState.name === 'self') { + if (fromState.name === 'home' || fromState.name === 'self') { + return false; + } + AuthService.islogged().then(function (response) { if (response === "true") { - $state.go('update.credentials'); - } else { - $state.go('self'); + $state.go('update' + $rootScope.getWizardFirstStep()); } }, function (response) { console.error("not logged"); - $state.go('self'); - } - ); + $state.go('home'); + }); /* * enable "finish" button on every page in create mode */ } else if (toState.name === 'create.finish') { + if (fromState.name === 'create.finish') { + return false; + } + $rootScope.endReached = true; } else { + if (fromState.name === toState.name) { + return false; + } + $state.go(toState); } }); + $rootScope.spinner = { active: false, on: function () { @@ -353,9 +373,9 @@ app.run(['$rootScope', '$location', '$state', 'AuthService', } }; }]); -app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'InfoService', 'SAML2IdPService', - 'OIDCProviderService', - function ($scope, $rootScope, $location, InfoService, SAML2IdPService, OIDCProviderService) { +app.controller('ApplicationController', ['$scope', '$rootScope', 'InfoService', 'SAML2IdPService', + 'OIDCProviderService', 'DynamicTemplateService', + function ($scope, $rootScope, InfoService, SAML2IdPService, OIDCProviderService, DynamicTemplateService) { $scope.initApplication = function () { /* * disable by default wizard buttons in self-registration @@ -396,6 +416,57 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I selected: {} }; + var doGetDynamicTemplateJSON = function (callback) { + if (!$rootScope.dynTemplate) { + DynamicTemplateService.getContent().then( + function (response) { + /* + * USER dynamic template JSON + */ + $rootScope.dynTemplate = response; + + /* + * Wizard steps from JSON + */ + $scope.wizard = response.wizard.steps; + $scope.wizardFirstStep = response.wizard.firstStep; + + callback($rootScope.dynTemplate); + }, + function (response) { + console.error("Something went wrong while accessing dynamic template resource", response); + }); + } else { + callback($rootScope.dynTemplate); + } + }; + $rootScope.getDynamicTemplateInfo = function (type, key, callback) { + if (type) { + doGetDynamicTemplateJSON(function (templateJSON) { + callback((templateJSON && templateJSON["templates"] && templateJSON["templates"][type]) + ? templateJSON["templates"][type][key] + : ""); + }); + } else { + callback(""); + } + }; + $rootScope.getDynamicTemplateOtherInfo = function (type, key, callback) { + if (type) { + doGetDynamicTemplateJSON(function (templateJSON) { + callback((templateJSON && templateJSON[type]) + ? templateJSON[type][key] + : ""); + }); + } else { + callback(""); + } + }; + + $rootScope.getWizardFirstStep = function () { + return ($scope.wizardFirstStep ? ('.' + $scope.wizardFirstStep) : ''); + }; + InfoService.getInfo().then( function (response) { $rootScope.pwdResetAllowed = response.pwdResetAllowed; @@ -407,11 +478,12 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I /* * USER form customization JSON */ - $rootScope.customForm = response.customForm; + $rootScope.customFormAttributes = response.customFormAttributes; }, function (response) { console.error("Something went wrong while accessing info resource", response); }); + /* <Extensions> */ SAML2IdPService.getAvailableSAML2IdPs().then( function (response) { @@ -421,10 +493,6 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I console.debug("No SAML 2.0 SP extension available", response); }); /* </Extensions> */ - /* - * configuration getters - */ - /* <Extensions> */ OIDCProviderService.getAvailableOIDCProviders().then( function (response) { @@ -434,6 +502,7 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I console.debug("No OIDC Client extension available", response); }); /* </Extensions> */ + /* * configuration getters */ @@ -462,6 +531,7 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I $rootScope.getMaxUploadFileSizeMB = function () { return $rootScope.maxUploadFileSizeMB; }; + /* * USER Attributes sorting strategies */ @@ -477,19 +547,25 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I return schemaNameA < schemaNameB ? 1 : schemaNameA > schemaNameB ? -1 : 0; } }; + /* |-------------------------------------------------------------------------- | Notification mgmt |-------------------------------------------------------------------------- */ - $scope.notification = $('#notifications').kendoNotification().data("kendoNotification"); - $scope.notification.setOptions({stacking: "down"}); + $scope.notificationSuccessTimeout = 4000; +// $scope.notification = $('#notifications').kendoNotification().data("kendoNotification"); + $scope.notification = $("#notifications").kendoNotification({ + stacking: "down", + hideOnClick: true, + width: 320 + }).data("kendoNotification"); $scope.notification.options.position["top"] = 20; $scope.showSuccess = function (message, component) { if (!$scope.notificationExists(message)) { //forcing scrollTo since kendo doesn't disable scrollTop if pinned is true window.scrollTo(0, 0); - component.options.autoHideAfter = 3000; + component.options.autoHideAfter = $scope.notificationSuccessTimeout; component.show(message, "success"); } }; @@ -510,7 +586,7 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I }; $scope.notificationExists = function (message) { var result = false; - if ($scope.notification !== null) { + if ($scope.notification) { var pendingNotifications = $scope.notification.getNotifications(); pendingNotifications.each(function (idx, element) { var popup = $(element).data("kendoPopup"); @@ -523,7 +599,7 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I return result; }; $scope.hideNotifications = function (timer) { - if ($scope.notification !== null) { + if ($scope.notification) { var pendingNotifications = $scope.notification.getNotifications(); if (timer && timer > 0) { setTimeout(function () { @@ -547,12 +623,13 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I } } }; + /* * Intercepting location change event * When a location changes, old notifications should be removed */ $rootScope.$on("$locationChangeStart", function (event, next, current) { - $scope.hideNotifications(3000); + $scope.hideNotifications($scope.notificationSuccessTimeout); }); //Intercepting xhr start event $scope.$on('xhrStarted', function (event, next, current) { @@ -562,20 +639,7 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I $scope.$on('hideErrorMessage', function (event, popupMessage) { $scope.hideError(popupMessage, $scope.notification); }); - /* - |-------------------------------------------------------------------------- - | Wizard configuration - |-------------------------------------------------------------------------- - */ - $scope.wizard = { - "credentials": {url: "/credentials"}, - "groups": {url: "/groups"}, - "plainSchemas": {url: "/plainSchemas"}, - "derivedSchemas": {url: "/derivedSchemas"}, - "virtualSchemas": {url: "/virtualSchemas"}, - "resources": {url: "/resources"}, - "finish": {url: "/finish"} - }; + /* |-------------------------------------------------------------------------- | Utilities http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js index d2b755c..f92c15c 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js @@ -18,8 +18,9 @@ */ 'use strict'; -angular.module("login").controller("LoginController", ['$scope', '$rootScope', '$http', '$location', 'AuthService', - function ($scope, $rootScope, $http, $location, AuthService) { +angular.module("login").controller("LoginController", ['$scope', '$rootScope', '$http', '$state', '$location', + 'AuthService', + function ($scope, $rootScope, $http, $state, $location, AuthService) { $scope.credentials = { username: '', @@ -37,7 +38,7 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', ' // reset OIDC name $rootScope.oidcops.selected.name = null; // got to update page - $location.path("/self/update"); + $state.go("update" + $rootScope.getWizardFirstStep()); }, function (response) { console.info("Login failed for: ", response); var errorMessage; @@ -65,11 +66,11 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', ' }; $scope.selfCreate = function () { - $location.path("/self/create"); + $state.go("create" + $rootScope.getWizardFirstStep()); }; $scope.passwordReset = function () { - $location.path("/passwordreset"); + $state.go("passwordreset"); }; $scope.$watch(function () { http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/OIDCClientController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/OIDCClientController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/OIDCClientController.js index f3eab68..8d7b3cd 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/OIDCClientController.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/OIDCClientController.js @@ -18,9 +18,9 @@ */ 'use strict'; -angular.module("login").controller("OIDCClientController", function ($scope, $rootScope, $location, userAttrs) { +angular.module("login").controller("OIDCClientController", function ($scope, $rootScope, $state, userAttrs) { $scope.selfCreate = function () { - $location.path("/self/create"); + $state.go("create" + $rootScope.getWizardFirstStep()); }; $rootScope.oidcops.userAttrs = userAttrs; http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js index 05adf18..6d6bd33 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js @@ -18,9 +18,9 @@ */ 'use strict'; -angular.module("login").controller("SAML2SPController", function ($scope, $rootScope, $location, userAttrs) { +angular.module("login").controller("SAML2SPController", function ($scope, $rootScope, $state, userAttrs) { $scope.selfCreate = function () { - $location.path("/self/create"); + $state.go("create" + $rootScope.getWizardFirstStep()); }; $rootScope.saml2idps.userAttrs = userAttrs; http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js index 629c90d..7718db7 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js @@ -119,12 +119,12 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l // initialize plain attributes for (var i = 0; i < schemas.plainSchemas.length; i++) { var plainSchemaKey = schemas.plainSchemas[i].key; - var initialAttributeValues = $rootScope.customForm != null - && $rootScope.customForm["PLAIN"] != null - && $rootScope.customForm["PLAIN"]["attributes"] != null - && $rootScope.customForm["PLAIN"]["attributes"][plainSchemaKey] != null - && $rootScope.customForm["PLAIN"]["attributes"][plainSchemaKey].defaultValues - ? $rootScope.customForm["PLAIN"]["attributes"][plainSchemaKey].defaultValues + var initialAttributeValues = $rootScope.customFormAttributes + && $rootScope.customFormAttributes["PLAIN"] + && $rootScope.customFormAttributes["PLAIN"]["attributes"] + && $rootScope.customFormAttributes["PLAIN"]["attributes"][plainSchemaKey] + && $rootScope.customFormAttributes["PLAIN"]["attributes"][plainSchemaKey].defaultValues + ? $rootScope.customFormAttributes["PLAIN"]["attributes"][plainSchemaKey].defaultValues : []; if (!$scope.user.plainAttrs[plainSchemaKey]) { $scope.user.plainAttrs[plainSchemaKey] = { @@ -135,7 +135,7 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l if ($scope.loadFromSAML2AuthSelfReg) { $scope.user.plainAttrs[plainSchemaKey].values = findLoadedSAML2AttrValue(plainSchemaKey); } - + if ($scope.loadFromOIDCAuthSelfReg) { $scope.user.plainAttrs[plainSchemaKey].values = findLoadedOIDCAttrValue(plainSchemaKey); } @@ -193,8 +193,8 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l if ($scope.loadFromSAML2AuthSelfReg) { $scope.user.virAttrs[virSchemaKey].values = findLoadedSAML2AttrValue(virSchemaKey); } - - if ($scope.loadFromOIDCAuthSelfReg) { + + if ($scope.loadFromOIDCAuthSelfReg) { $scope.user.virAttrs[virSchemaKey].values = findLoadedOIDCAttrValue(virSchemaKey); } @@ -221,7 +221,7 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l //clean SAML Self Reg user attributes variable delete $rootScope.saml2idps.userAttrs; - + //clean OIDC Self Reg user attributes variable delete $rootScope.oidcops.userAttrs; }; @@ -364,7 +364,7 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l $scope.$emit("groupAdded", $scope.user.memberships[index].groupName); } if ($scope.user.mustChangePassword) { - $location.path('/mustchangepassword'); + $state.go('mustchangepassword'); } else { initProperties(); } @@ -469,14 +469,14 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l if (username.length) { $scope.user.username = username[0]; } - } - + } + if ($scope.loadFromOIDCAuthSelfReg) { var username = findLoadedOIDCAttrValue("username"); if (username.length) { $scope.user.username = username[0]; } - } + } } else { // read user from syncope core readUser(); @@ -490,11 +490,13 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l console.debug("User " + $scope.user.username + " successfully CREATED"); $rootScope.currentUser = $scope.user.username; $rootScope.currentOp = "SUCCESSFULLY_CREATED"; - $scope.success({successMessage: $filter('translate')(["USER"]).USER + $scope.success({ + successMessage: $filter('translate')(["USER"]).USER + " " + $scope.user.username + " " - + $filter('translate')(["SUCCESSFULLY_CREATED"]).SUCCESSFULLY_CREATED}); + + $filter('translate')(["SUCCESSFULLY_CREATED"]).SUCCESSFULLY_CREATED + }); }, function (response) { console.error("Error during user creation: ", response); var errorMessage; @@ -510,11 +512,13 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l console.debug("User " + $scope.user.username + " successfully UPDATED"); $rootScope.currentUser = $scope.user.username; $rootScope.currentOp = "SUCCESSFULLY_UPDATED"; - $scope.logout({successMessage: $filter('translate')(["USER"]).USER + $scope.logout({ + successMessage: $filter('translate')(["USER"]).USER + " " + $scope.user.username + " " - + $filter('translate')(["SUCCESSFULLY_UPDATED"]).SUCCESSFULLY_UPDATED}); + + $filter('translate')(["SUCCESSFULLY_UPDATED"]).SUCCESSFULLY_UPDATED + }); }, function (response) { console.info("Error during user update: ", response); var errorMessage; @@ -652,7 +656,7 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l $scope.redirect = function () { $translate.use($scope.languages.selectedLanguage.code); - $location.path('/self'); + $state.go('home'); $rootScope.endReached = false; }; http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttribute.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttribute.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttribute.js index 8ccaa02..7ed07e1 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttribute.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicPlainAttribute.js @@ -127,11 +127,11 @@ angular.module('self') }; $scope.customReadonly = function (schemaKey) { - return $rootScope.customForm != null - && $rootScope.customForm["PLAIN"] != null - && $rootScope.customForm["PLAIN"]["attributes"] != null - && $rootScope.customForm["PLAIN"]["attributes"][schemaKey] != null - && $rootScope.customForm["PLAIN"]["attributes"][schemaKey].readonly; + return $rootScope.customFormAttributes + && $rootScope.customFormAttributes["PLAIN"] + && $rootScope.customFormAttributes["PLAIN"]["attributes"] + && $rootScope.customFormAttributes["PLAIN"]["attributes"][schemaKey] + && $rootScope.customFormAttributes["PLAIN"]["attributes"][schemaKey].readonly; }; $scope.$watch(function () { http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicTemplateItem.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicTemplateItem.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicTemplateItem.js new file mode 100644 index 0000000..f822106 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicTemplateItem.js @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +'use strict'; + +angular.module('self') + .directive('dynamicTemplateItem', ['$rootScope', '$compile', '$http', 'AssetsManager', + function ($rootScope, $compile, $http, AssetsManager) { + + var checkGeneralAssets = function () { + $rootScope.getDynamicTemplateOtherInfo("generalAssets", "css", function (assets) { + if (assets && assets.length) { + for (var i = 0; i < assets.length; i++) { + if (!AssetsManager.checkAlreadyLoaded(assets[i], "css")) { + AssetsManager.inject("asset_general_css_" + i, assets[i], "css"); + } + } + } + }); + }; + + var linker = function ($scope, $element, $attrs) { + // compile template + $rootScope.getDynamicTemplateInfo($attrs.type, "templateUrl", function (templateUrl) { + if (templateUrl) { + $http.get(templateUrl).then(function (response) { + $element.html(response.data).show(); + $compile($element.contents())($scope); + }, function (e) { + console.error(e); + }); + } + }); + + // inject template assets + $rootScope.getDynamicTemplateInfo($attrs.type, "css", function (assets) { + if (assets && assets.length) { + for (var i = 0; i < assets.length; i++) { + AssetsManager.inject("asset_css_" + i, assets[i], "css"); + } + } + }); + + // remove useless assets for little optimization + if ($attrs.type !== "login") { + $rootScope.getDynamicTemplateInfo("login", "css", function (assets) { + for (var i = 0; i < assets.length; i++) { + AssetsManager.remove(assets[i], "css"); + } + }); + } + + // check general assets are always loaded (in case page refreshing in wizard) + checkGeneralAssets(); + }; + + return { + restrict: "E", + link: linker, + replace: true + }; + + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttribute.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttribute.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttribute.js index 85e2934..5a1d82c 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttribute.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttribute.js @@ -29,12 +29,12 @@ angular.module('self') user: "=" }, controller: function ($scope, $rootScope) { - var customValues = $rootScope.customForm != null - && $rootScope.customForm["VIRTUAL"] != null - && $rootScope.customForm["VIRTUAL"]["attributes"] != null - && $rootScope.customForm["VIRTUAL"]["attributes"][$scope.schema.key] != null - && $rootScope.customForm["VIRTUAL"]["attributes"][$scope.schema.key].defaultValues - ? $rootScope.customForm["VIRTUAL"]["attributes"][$scope.schema.key].defaultValues + var customValues = $rootScope.customFormAttributes + && $rootScope.customFormAttributes["VIRTUAL"] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"][$scope.schema.key] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"][$scope.schema.key].defaultValues + ? $rootScope.customFormAttributes["VIRTUAL"]["attributes"][$scope.schema.key].defaultValues : []; $scope.$watch(function () { @@ -55,11 +55,11 @@ angular.module('self') }); $scope.customReadonly = function (schemaKey) { - return $rootScope.customForm != null - && $rootScope.customForm["VIRTUAL"] != null - && $rootScope.customForm["VIRTUAL"]["attributes"] != null - && $rootScope.customForm["VIRTUAL"]["attributes"][schemaKey] != null - && $rootScope.customForm["VIRTUAL"]["attributes"][schemaKey].readonly; + return $rootScope.customFormAttributes + && $rootScope.customFormAttributes["VIRTUAL"] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"][schemaKey] + && $rootScope.customFormAttributes["VIRTUAL"]["attributes"][schemaKey].readonly; }; } //replace: true http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js index 300c73d..8532bef 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/dynamicVirtualAttributes.js @@ -56,7 +56,8 @@ angular.module('self') }; $scope.addVirtualAttributeField = function (virSchemaKey) { - $scope.dynamicForm.virtualAttributeTable[virSchemaKey].fields.push(virSchemaKey + "_" + ($scope.dynamicForm.virtualAttributeTable[virSchemaKey].fields.length)); + $scope.dynamicForm.virtualAttributeTable[virSchemaKey].fields.push(virSchemaKey + "_" + + ($scope.dynamicForm.virtualAttributeTable[virSchemaKey].fields.length)); }; $scope.removeVirtualAttributeField = function (virSchemaKey, index) { http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/fileInput.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/fileInput.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/fileInput.js index 50f4a7f..331c0f4 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/fileInput.js +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/fileInput.js @@ -35,8 +35,8 @@ angular.module('self') showClose: true, showRemove: false, fileActionSettings: {'showZoom': false, indicatorNew: '', 'removeTitle': 'boh'}, - removeClass: "btn btn-default", - browseClass: "btn btn-default", + removeClass: "btn btn-secondary btn-default", + browseClass: "btn btn-secondary btn-default", browseLabel: '', dragIcon: '', browseIcon: '', http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js deleted file mode 100644 index 9fa8292..0000000 --- a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtons.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -'use strict'; - -angular.module('self') - .directive('navigationButtons', ['$state', 'GenericUtil', 'ValidationExecutor', function ($state, GenericUtil, ValidationExecutor) { - return { - restrict: 'E', - templateUrl: 'views/navigationButtons.html', - scope: { - base: "@", - current: "@" - }, - link: function (scope, element, attrs) { - var base = (scope.base && scope.base !== "" ? scope.base + "." : ""); - scope.wizard = scope.$eval(attrs.wizard) || scope.$parent.wizard; - scope.previous = "none"; - if (scope.wizard) { - var urls = Object.keys(scope.wizard); - var index = urls.indexOf(scope.current); - scope.previous = (index > 0 ? base + urls[index - 1] : scope.previous = "none"); - scope.next = (index < urls.length - 1 ? base + urls[index + 1] : scope.next = "none"); - } - }, - controller: function ($scope) { - - $scope.validateAndNext = function (event, state) { - //getting the enclosing form in order to access to its name - var currentForm = GenericUtil.getEnclosingForm(event.target); - if (currentForm !== null) { - if (ValidationExecutor.validate(currentForm, $scope.$parent)) { - if (state) { - $scope.nextTab(state); - } else if ($scope.wizard) { - $scope.nextTab($scope.next); - } - } - } - - }; - - $scope.nextTab = function (state) { - //change route through parent event - $state.go(state); - }; - - $scope.previousTab = function () { - //change route through parent event - $state.go($scope.previous); - }; - } - - } - ; - }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtonsPartial.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtonsPartial.js b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtonsPartial.js new file mode 100644 index 0000000..6d0d81d --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/directives/navigationButtonsPartial.js @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +'use strict'; + +angular.module('self') + .directive('navigationButtonsPartial', ['$state', 'GenericUtil', 'ValidationExecutor', + function ($state, GenericUtil, ValidationExecutor) { + return { + + restrict: 'E', + templateUrl: 'views/navigationButtonsPartial.html', + scope: { + base: "@", + current: "@" + }, + link: function (scope, element, attrs) { + var base = (scope.base && scope.base !== "" ? scope.base + "." : ""); + scope.wizard = scope.$eval(attrs.wizard) || scope.$parent.wizard || scope.$parent.$parent.wizard; + scope.previous = "none"; + if (scope.wizard) { + var urls = Object.keys(scope.wizard); + var index = urls.indexOf(scope.current); + scope.previous = (index > 0 ? base + urls[index - 1] : scope.previous = "none"); + scope.next = (index < urls.length - 1 ? base + urls[index + 1] : scope.next = "none"); + } + }, + controller: function ($scope) { + $scope.validateAndNext = function (event, state) { + //getting the enclosing form in order to access to its name + var currentForm = GenericUtil.getEnclosingForm(event.target); + if (currentForm !== null) { + if (ValidationExecutor.validate(currentForm, $scope.$parent)) { + if (state) { + $scope.nextTab(state); + } else if ($scope.wizard) { + $scope.nextTab($scope.next); + } + } + } + + }; + + $scope.nextTab = function (state) { + //change route through parent event + $state.go(state); + }; + + $scope.previousTab = function () { + //change route through parent event + $state.go($scope.previous); + }; + } + + }; + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/services/dynamicTemplateService.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/dynamicTemplateService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/dynamicTemplateService.js new file mode 100644 index 0000000..b3348e0 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/dynamicTemplateService.js @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +'use strict'; + +angular.module('SyncopeEnduserApp') + .factory('DynamicTemplateService', ['$q', '$http', 'AssetsManager', + function ($q, $http, AssetsManager) { + + var dynTemplateService = {}; + var dynTemplateUrl = '../api/dynamicTemplate'; + + var error = function (response) { + console.error("Something went wrong while retrieving dynamic template resource", response); + return $q.reject(response.data || response.statusText); + }; + + var loadAssets = function (category, assets, types) { + var allPromises = types.reduce((acc, type) => { + if (assets[category][type]) { + var currentAssetsPromises = + assets[category][type].map((url, index) => AssetsManager. + inject("elem_" + index, url, type)); + return acc.concat(currentAssetsPromises); + } + }, []); + + return $q.all(allPromises); + }; + + dynTemplateService.getContent = function () { + return $http + .get(dynTemplateUrl) + .then(function (response) { + return response.data; + }, error); + }; + + dynTemplateService.getGeneralAssetsContent = function (types) { + return $http + .get(dynTemplateUrl) + .then(function (response) { + return loadAssets("generalAssets", response.data, types); + }, error); + }; + + return dynTemplateService; + + }]); + + http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/js/util/assetsManager.js ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/util/assetsManager.js b/client/enduser/src/main/resources/META-INF/resources/app/js/util/assetsManager.js new file mode 100644 index 0000000..48ec119 --- /dev/null +++ b/client/enduser/src/main/resources/META-INF/resources/app/js/util/assetsManager.js @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +'use strict'; + +angular.module('SyncopeEnduserApp') + .factory("AssetsManager", ['$q', function ($q) { + var assetsManager = {}; + + var createLink = function (id, url, deferred) { + if (!angular.element('link#' + id).length && !angular.element('link[href="' + url + '"').length) { + var link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = url; + link.onload = deferred.resolve; + link.onerror = deferred.reject; + angular.element('head').append(link); + } + }; + + var createScript = function (id, url, deferred) { + if (!angular.element('script#' + id).length && !angular.element('script[src="' + url + '"').length) { + var script = document.createElement('script'); + script.src = url; + script.onload = deferred.resolve; + script.onerror = deferred.reject; + angular.element('body').append(script); + } + }; + + assetsManager.checkAlreadyLoaded = function (url, type) { + var elems = (type === 'css') ? document.styleSheets : ((type === 'js') ? document.scripts : ''); + var attr = (type === 'js') ? 'src' : ((type === 'css') ? 'href' : 'none'); + for (var i in elems) { + var attrUrl = elems[i][attr] || ""; + var assetName = attrUrl.split("/").slice(-1).join(); + if (attrUrl !== "" + && (assetName === url.split("/").slice(-1).join() || assetName === url)) { + return true; + } + } + return false; + }; + + var checkLoaded = function (url, deferred, tries, type) { + if (assetsManager.checkAlreadyLoaded(url, type)) { + deferred.resolve(); + return; + } + tries++; + setTimeout(function () { + checkLoaded(url, deferred, tries, type); + }, 50); + }; + + var removeLoaded = function (url, type) { + var tag = (type === 'js') ? 'script' : ((type === 'css') ? 'link' : ''); + if (assetsManager.checkAlreadyLoaded(url, type)) { + $(tag + '[href~="' + url + '"]').remove(); + } + }; + + assetsManager.inject = function (id, url, type) { + var tries = 0, + deferred = $q.defer(); + + switch (type) { + case 'js': + createScript(id, url, deferred); + break; + + case 'css': + createLink(id, url, deferred); + break; + + default: + break; + } + checkLoaded(url, deferred, tries, type); + + return deferred.promise; + }; + + assetsManager.remove = function (url, type) { + removeLoaded(url, type); + }; + + return assetsManager; + }]); http://git-wip-us.apache.org/repos/asf/syncope/blob/ac909f2e/client/enduser/src/main/resources/META-INF/resources/app/views/captcha.html ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/captcha.html b/client/enduser/src/main/resources/META-INF/resources/app/views/captcha.html index 518ab35..88dfae1 100644 --- a/client/enduser/src/main/resources/META-INF/resources/app/views/captcha.html +++ b/client/enduser/src/main/resources/META-INF/resources/app/views/captcha.html @@ -21,16 +21,16 @@ under the License. <div class="container-fluid" style="text-align: center"> <div id="captchainput" > <img id="captchaImg" alt="captcha" ng-src="{{captchaUrl}}'"/> - <div id="captchaButtons" style="margin-top: 5%; margin-bottom: 10px"> - <button id="refresh" type="button" class="btn btn-default btn-xs glyphicon glyphicon-refresh" + <div id="captchaButtons"> + <button id="refresh" type="button" class="btn btn-default btn-xs fa fa-refresh" ng-click="refreshCaptcha()" title="Refresh Captcha"></button> - <a id="refresh" class="btn btn-default btn-xs glyphicon glyphicon-question-sign" title="What is?" - href="https://it.wikipedia.org/wiki/CAPTCHA" target="_blank"/> + <button id="questionCaptcha" class="btn btn-default btn-xs fa fa-question-circle" title="What is?" + onclick="window.open('https://it.wikipedia.org/wiki/CAPTCHA')"></button> </div> <input class="form-control" style="margin:auto; max-width: 260px" type="text" ng-model="input.value"/> - </div> - <div> - <span class="help-block">{{'CAPTCHA' | translate}}</span> + <div> + <span class="help-block">{{'CAPTCHA'| translate}}</span> + </div> </div> </div> </nav>