Merge branch 'ui-improvements' into next

This commit is contained in:
Marcos Zuriaga 2021-08-22 13:45:17 +02:00
commit 88fef6029b
No known key found for this signature in database
GPG key ID: 7D15585354D072FF
21 changed files with 418 additions and 305 deletions

View file

@ -65,6 +65,7 @@ class TranslationController extends ApiController {
// js/app/controllers/export.js
'export.starting' => $this->trans->t('Starting export'),
'export.decrypt' => $this->trans->t('Decrypting credentials'),
'export.decrypt.error' => $this->trans->t('Failed to decrypt {{credential}}'),
'done' => $this->trans->t('Done'),
// js/app/controllers/import.js

View file

@ -140,38 +140,42 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
.tab_header {
width: calc(100vw - 300px);
margin: 0 0 0;
list-style: none;
padding: 0; }
.tab_header li.tab:first-child {
margin-left: 0; }
.tab_header li.tab {
/*@include border-top-radius(2px);*/
float: left;
border-bottom-width: 0;
margin: 0;
padding: 10px 10px 10px 10px;
cursor: pointer;
border-right: 1px solid #eee;
-webkit-transition: background-color 250ms linear;
-moz-transition: background-color 250ms linear;
-o-transition: background-color 250ms linear;
-ms-transition: background-color 250ms linear;
transition: background-color 250ms linear; }
.tab_header li.tab .indicator {
display: none; }
.tab_header li.inactive {
background-color: #fff !important;
color: unset !important; }
.tab_header li.active .indicator {
display: inline-block;
position: absolute;
height: 7px;
left: 0;
right: 0;
bottom: -1px; }
.app-sidebar-tabs {
display: flex;
flex-direction: column;
min-height: 0;
flex: 1 1 100%; }
.app-sidebar-tabs__nav ul {
display: flex;
justify-content: stretch; }
.app-sidebar-tabs__tab.active {
color: var(--color-text-light);
border-bottom-color: var(--color-primary-element);
box-shadow: inset 0 -1px 0 var(--color-primary-element);
font-weight: bold; }
.app-sidebar-tabs__tab:not(.active):hover, .app-sidebar-tabs__tab:not(.active):focus {
border-bottom-color: var(--color-background-darker);
box-shadow: inset 0 -1px 0 var(--color-background-darker); }
.app-sidebar-tabs__tab:hover, .app-sidebar-tabs__tab:focus, .app-sidebar-tabs__tab:active, .app-sidebar-tabs__tab.active {
opacity: 1;
cursor: pointer; }
.app-sidebar-tabs__tab {
position: relative;
display: block;
overflow: hidden;
padding: 10px 10px 10px 10px;
transition: color var(--animation-quick), opacity var(--animation-quick), border-color var(--animation-quick);
text-align: center;
white-space: nowrap;
text-overflow: ellipsis;
opacity: .7;
color: var(--color-main-text);
border-bottom: 1px solid var(--color-border); }
.tab_container {
border: 1px solid #eee;
@ -1067,7 +1071,6 @@
width: inherit !important;
border-right: 1px solid #eee; }
.nav-trashbin a {
background-color: #fff !important;
opacity: 1 !important;
z-index: 140; }
.nav-trashbin a.active {
@ -1075,8 +1078,21 @@
.nav-trashbin a .fa {
margin-right: 15px; }
#app-navigation .collapsible:hover .app-navigation-entry-bullet {
background: var(--color-primary) !important; }
#app-navigation {
/* Custom bullet icon */ }
#app-navigation .collapsible:hover .app-navigation-entry-bullet {
background: var(--color-primary) !important; }
#app-navigation .app-navigation-entry-bullet-with-hover {
position: absolute;
display: block;
margin: 16px;
width: 12px;
height: 12px;
border: none;
border-radius: 50%;
cursor: pointer;
transition: background 100ms ease-in-out;
z-index: 101; }
#app-navigation a .selected {
opacity: 1 !important;

File diff suppressed because one or more lines are too long

View file

@ -19,18 +19,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
header, nav {
header {
display: none; }
#content-wrapper {
padding-top: 0; }
#app-content {
margin-left: 0;
overflow-x: auto; }
#app-content-wrapper {
min-height: inherit !important; }
.warning_bar .fa-times {
margin-right: 20px; }
#passman-controls .breadcrumb {
padding-left: 0; }
#passman-controls .breadcrumb a, #passman-controls .breadcrumb a i {
cursor: default; }
.tab_container {
padding-top: 10px;
margin-bottom: 20px; }
@ -47,10 +56,10 @@ header, nav {
padding-right: 5px;
font-size: 10px; }
.tab_header {
margin: 0; }
.angularjs-datetime-picker {
z-index: 9999; }
.icon-picker {
display: none; }
/*# sourceMappingURL=bookmarklet.css.map */

View file

@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,WAAW;EACT,OAAO,EAAE,IAAI;;AAKf,gBAAgB;EACd,WAAW,EAAE,CAAC;;AAIhB,oBAAoB;EAClB,UAAU,EAAE,kBAAkB;;AAGhC,sBAAuB;EACtB,YAAY,EAAE,IAAI;;AAEnB,cAAc;EACZ,WAAW,EAAE,IAAI;EAKjB,aAAa,EAAE,IAAI;EAJnB,kBAAG;IACD,aAAa,EAAE,GAAG;IAClB,QAAQ,EAAE,MAAM;;AAIpB,cAAc;EACZ,UAAU,EAAE,IAAI;;AAElB,aAAa;EACX,KAAK,EAAE,KAAK;EACZ,UAAU,EAAE,KAAK;EACjB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,IAAI;;AAEjB,WAAW;EACT,MAAM,EAAE,CAAC;;AAEX,0BAA0B;EACxB,OAAO,EAAE,IAAI",
"mappings": "AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAO;EACL,OAAO,EAAE,IAAI;;AAOf,gBAAiB;EACf,WAAW,EAAE,CAAC;;AAIhB,YAAa;EACX,WAAW,EAAE,CAAC;EACd,UAAU,EAAE,IAAI;;AAGlB,oBAAqB;EACnB,UAAU,EAAE,kBAAkB;;AAGhC,sBAAuB;EACrB,YAAY,EAAE,IAAI;;AAGpB,6BAA8B;EAC5B,YAAY,EAAE,CAAC;EACf,kEAAO;IACL,MAAM,EAAE,OAAO;;AAInB,cAAe;EACb,WAAW,EAAE,IAAI;EAOjB,aAAa,EAAE,IAAI;EALnB,kBAAI;IACF,aAAa,EAAE,GAAG;IAClB,QAAQ,EAAE,MAAM;;AAMpB,cAAe;EACb,UAAU,EAAE,IAAI;;AAGlB,aAAc;EACZ,KAAK,EAAE,KAAK;EACZ,UAAU,EAAE,KAAK;EACjB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,IAAI;;AAGjB,0BAA2B;EACzB,OAAO,EAAE,IAAI;;AAGf,YAAa;EACX,OAAO,EAAE,IAAI",
"sources": ["../sass/bookmarklet.scss"],
"names": [],
"file": "bookmarklet.css"

View file

@ -411,9 +411,13 @@
NotificationService.showNotification($translate.instant('credential.created'), 5000);
});
}
setTimeout(() => window.close(), 3000);
};
$scope.cancel = function () {
window.close();
};
}
]);
}());
}());

View file

@ -72,15 +72,19 @@
if (vault.hasOwnProperty('credentials')) {
if (vault.credentials.length > 0) {
for (var i = 0; i < vault.credentials.length; i++) {
var _credential = angular.copy(vault.credentials[i]);
if (_credential.hidden === 0) {
var key = CredentialService.getSharedKeyFromCredential(_credential);
_credential = CredentialService.decryptCredential(_credential, key);
_credential.vault_key = key;
_credentials.push(_credential);
try {
var _credential = angular.copy(vault.credentials[i]);
if (_credential.hidden === 0) {
var key = CredentialService.getSharedKeyFromCredential(_credential);
_credential = CredentialService.decryptCredential(_credential, key);
_credential.vault_key = key;
_credentials.push(_credential);
}
} catch (e) {
_log($translate.instant('export.decrypt.error', {credential: (vault.credentials[i].label !== undefined) ? vault.credentials[i].label : i}));
}
}
$window.PassmanExporter[$scope.selectedExporter.id].export(_credentials, FileService, EncryptService).then(function () {
$window.PassmanExporter[$scope.selectedExporter.id].export(_credentials, FileService, EncryptService, $scope.log, $translate).then(function () {
_log($translate.instant('done'));
});
}
@ -92,4 +96,4 @@
}]);
}());
}());

View file

@ -87,8 +87,8 @@
});
var btn_txt = $translate.instant('bookmarklet.text');
var http = location.protocol, slashes = http.concat("//"), host = slashes.concat(window.location.hostname), complete = host + location.pathname;
$scope.bookmarklet = $sce.trustAsHtml("<a class=\"button\" href=\"javascript:(function(){var a=window,b=document,c=encodeURIComponent,e=c(document.title),d=a.open('" + complete + "bookmarklet?url='+c(b.location)+'&title='+e,'bkmk_popup','left='+((a.screenX||a.screenLeft)+10)+',top='+((a.screenY||a.screenTop)+10)+',height=750px,width=475px,resizable=0,alwaysRaised=1');a.setTimeout(function(){d.focus()},300);})();\">" + btn_txt + "</a>");
var http = location.protocol, slashes = http.concat("//"), host = slashes.concat(window.location.hostname + ":" + window.location.port), complete = host + location.pathname;
$scope.bookmarklet = $sce.trustAsHtml("<a class=\"button\" href=\"javascript:(function(){var a=window,b=document,c=encodeURIComponent,e=c(document.title),d=a.open('" + complete + "/bookmarklet?url='+c(b.location)+'&title='+e,'bkmk_popup','left='+((a.screenX||a.screenLeft)+10)+',top='+((a.screenY||a.screenTop)+10)+',height=750px,width=475px,resizable=0,alwaysRaised=1');a.setTimeout(function(){d.focus()},300);})();\">" + btn_txt + "</a>");
$scope.saveVaultSettings = function () {
@ -322,4 +322,4 @@
}]);
}());
}());

View file

@ -30,10 +30,10 @@ PassmanExporter.csv = {
}
};
PassmanExporter.csv.export = function (credentials, FileService, EncryptService) {
PassmanExporter.csv.export = function (credentials, FileService, EncryptService, _log, $translate) {
/** global: C_Promise */
return new C_Promise(function () {
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService).then((function(){
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService, _log, $translate).then((function(){
var headers = ['label', 'username', 'password', 'email', 'description', 'tags', 'url', 'custom_fields', 'files'];
var file_data = '"' + headers.join('","') + '"\n';
for (var i = 0; i < credentials.length; i++) {

View file

@ -30,10 +30,10 @@ PassmanExporter.json = {
}
};
PassmanExporter.json.export = function (credentials, FileService, EncryptService) {
PassmanExporter.json.export = function (credentials, FileService, EncryptService, _log, $translate) {
/** global: C_Promise */
return new C_Promise(function () {
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService).then((function(){
PassmanExporter.getCredentialsWithFiles(credentials, FileService, EncryptService, _log, $translate).then((function(){
var _output = [];
for (var i = 0; i < credentials.length; i++) {
var _credential = angular.copy(credentials[i]);

View file

@ -23,87 +23,104 @@
// Importers should always start with this
if (!window['PassmanExporter']) {
var PassmanExporter = {
getCredentialsWithFiles: function(credentials, FileService, EncryptService) {
var t = {
cred: credentials,
FS: FileService,
ES: EncryptService
};
/** global: C_Promise */
return new C_Promise(function() {
var _this = this.parent;
var credentials = _this.cred;
this.parent.total = 0;
this.parent.finished = 0;
this.parent.fileGUID_cred = [];
this.parent.files = [];
this.parent.step = (function(file) {
this.parent.finished ++;
this.call_progress({
total: this.parent.total,
finished: this.parent.finished
});
var dta = this.parent.fileGUID_cred[file.guid];
file.filename = this.parent.ES.decryptString(file.filename, this.parent.cred[dta.cred_pos].vault_key);
file.file_data = this.parent.ES.decryptString(file.file_data, this.parent.cred[dta.cred_pos].vault_key);
// Files and custom_fields have different field structure
if (dta.on === 'files') {
this.parent.cred[dta.cred_pos][dta.on][dta.at] = file;
}
else {
this.parent.cred[dta.cred_pos][dta.on][dta.at].value = file;
}
// We have finished downloading everything, so let's hand over job to somewhere else!
if (this.parent.total === this.parent.finished) {
this.call_then(this.parent.cred);
}
}).bind(this);
getCredentialsWithFiles: function (credentials, FileService, EncryptService, _log, $translate) {
var t = {
cred: credentials,
FS: FileService,
ES: EncryptService
};
/** global: C_Promise */
return new C_Promise(function () {
var _this = this.parent;
var credentials = _this.cred;
this.parent.total = 0;
this.parent.finished = 0;
this.parent.fileGUID_cred = [];
this.parent.files = [];
this.parent.step = (function (file) {
this.parent.finished++;
this.call_progress({
total: this.parent.total,
finished: this.parent.finished
});
for (var i = 0; i < credentials.length; i++) {
var item = credentials[i];
// Custom fields
for (c = 0; c < item.custom_fields.length; c++) {
var cf = item.custom_fields[c];
if (cf.field_type === 'file') {
this.parent.total ++;
this.parent.fileGUID_cred[cf.value.guid] = {
cred_pos: i,
on: 'custom_fields',
at: c
};
var dta = this.parent.fileGUID_cred[file.guid];
this.parent.FS.getFile(cf.value).then((function(data){
this.parent.step(data);
}).bind(this));
}
}
// Also get all files
for (var c = 0; c < item.files.length; c++) {
this.parent.total ++;
this.parent.fileGUID_cred[item.files[c].guid] = {
cred_pos: i,
on: 'files',
at: c
};
file.filename = this.parent.ES.decryptString(file.filename, this.parent.cred[dta.cred_pos].vault_key);
file.file_data = this.parent.ES.decryptString(file.file_data, this.parent.cred[dta.cred_pos].vault_key);
this.parent.FS.getFile(item.files[c]).then((function(data){
this.parent.step(data);
}).bind(this));
}
}
// We have finished downloading everything, so let's hand over job to somewhere else!
if (this.parent.total === 0) {
this.call_then(this.parent.cred);
}
}, t);
}
// Files and custom_fields have different field structure
if (dta.on === 'files') {
this.parent.cred[dta.cred_pos][dta.on][dta.at] = file;
} else {
this.parent.cred[dta.cred_pos][dta.on][dta.at].value = file;
}
// We have finished downloading everything, so let's hand over job to somewhere else!
if (this.parent.total === this.parent.finished) {
this.call_then(this.parent.cred);
}
}).bind(this);
this.parent.stepFailed = (function (error) {
_log.push($translate.instant('export.decrypt.error', {credential: error.config.filename}));
this.parent.finished++;
this.call_progress({
total: this.parent.total,
finished: this.parent.finished
});
// We have finished downloading everything, so let's hand over job to somewhere else!
if (this.parent.total === this.parent.finished) {
this.call_then(this.parent.cred);
}
}).bind(this);
for (var i = 0; i < credentials.length; i++) {
var item = credentials[i];
// Custom fields
for (c = 0; c < item.custom_fields.length; c++) {
var cf = item.custom_fields[c];
if (cf.field_type === 'file') {
this.parent.total++;
this.parent.fileGUID_cred[cf.value.guid] = {
cred_pos: i,
on: 'custom_fields',
at: c
};
this.parent.FS.getFile(cf.value).then((function (data) {
this.parent.step(data);
}).bind(this), (function (error) {
this.parent.stepFailed(error);
}).bind(this));
}
}
// Also get all files
for (var c = 0; c < item.files.length; c++) {
this.parent.total++;
this.parent.fileGUID_cred[item.files[c].guid] = {
cred_pos: i,
on: 'files',
at: c
};
this.parent.FS.getFile(item.files[c]).then((function (data) {
this.parent.step(data);
}).bind(this), (function (error) {
this.parent.stepFailed(error);
}).bind(this));
}
}
// We have finished downloading everything, so let's hand over job to somewhere else!
console.warn("parent.total " + this.parent.total);
if (this.parent.total === 0) {
this.call_then(this.parent.cred);
}
}, t);
}
};
}
}

File diff suppressed because one or more lines are too long

View file

@ -20,44 +20,65 @@
*
*/
header, nav{
header {
display: none;
}
#content{
#content {
}
#content-wrapper{
#content-wrapper {
padding-top: 0;
}
#app-content-wrapper{
#app-content {
margin-left: 0;
overflow-x: auto;
}
#app-content-wrapper {
min-height: inherit !important;
}
.warning_bar .fa-times {
margin-right: 20px;
margin-right: 20px;
}
.tab_container{
#passman-controls .breadcrumb {
padding-left: 0;
a, a i {
cursor: default;
}
}
.tab_container {
padding-top: 10px;
div{
div {
margin-bottom: 5px;
overflow: hidden;
}
margin-bottom: 20px;
}
.vault_wrapper{
.vault_wrapper {
margin-top: 70px;
}
.active_vault{
.active_vault {
float: right;
text-align: right;
padding-right: 5px;
font-size: 10px;
}
.tab_header{
margin: 0;
}
.angularjs-datetime-picker{
.angularjs-datetime-picker {
z-index: 9999;
}
}
.icon-picker {
display: none;
}

View file

@ -55,7 +55,7 @@
//border-left: 3px solid #0082c9;
background-image: var(--icon-delete-e9322d);
}
background-color: #fff !important;
//background-color: #fff !important;
opacity: 1 !important;
z-index: 140;
//padding: 0 20px;
@ -70,6 +70,19 @@
.collapsible:hover .app-navigation-entry-bullet{
background: var(--color-primary) !important;
}
/* Custom bullet icon */
.app-navigation-entry-bullet-with-hover {
position: absolute;
display: block;
margin: 16px;
width: 12px;
height: 12px;
border: none;
border-radius: 50%;
cursor: pointer;
transition: background 100ms ease-in-out;
z-index: 101;
}
}
@ -82,7 +95,7 @@
}
}
li{
li {
.app-navigation-entry-bullet-color {
background-color: var(--color-primary);
}
@ -99,22 +112,22 @@
background-color: #4db728;
}
.highlight-selected{
background-color: var(--color-primary);
.highlight-selected {
background-color: var(--color-primary);
}
.autocomplete{
.autocomplete {
position: relative;
}
a.taginput{
a.taginput {
opacity: 1;
}
a{
a {
overflow: visible;
tags-input{
tags-input {
opacity: 1.0;
li{
li {
width: auto !important;
}
}
@ -129,4 +142,4 @@
//source https://material.io/tools/icons/?icon=restore&style=baseline
.icon-expired{
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><path d='M0 0h24v24H0z' fill='none'/><path d='M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z'/></svg>");
}
}

View file

@ -20,51 +20,47 @@
*
*/
.tab_header {
width: calc(100vw - 300px);
// margin: 44px 0 0;
margin: 0 0 0;
list-style: none;
padding: 0;
li.tab:first-child {
margin-left: 0;
}
li.tab {
/*@include border-top-radius(2px);*/
float: left;
border-bottom-width: 0;
margin: 0;
padding: 10px 10px 10px 10px;
.app-sidebar-tabs {
display: flex;
flex-direction: column;
min-height: 0;
flex: 1 1 100%;
}
cursor: pointer;
border-right: 1px solid #eee;
-webkit-transition: background-color 250ms linear;
-moz-transition: background-color 250ms linear;
-o-transition: background-color 250ms linear;
-ms-transition: background-color 250ms linear;
transition: background-color 250ms linear;
.indicator {
display: none;
}
}
.app-sidebar-tabs__nav ul {
display: flex;
justify-content: stretch;
}
li.inactive {
background-color: #fff !important;
color: unset !important;
}
.app-sidebar-tabs__tab.active {
color: var(--color-text-light);
border-bottom-color: var(--color-primary-element);
box-shadow: inset 0 -1px 0 var(--color-primary-element);
font-weight: bold;
}
li.active {
.app-sidebar-tabs__tab:not(.active):hover, .app-sidebar-tabs__tab:not(.active):focus {
border-bottom-color: var(--color-background-darker);
box-shadow: inset 0 -1px 0 var(--color-background-darker);
}
//position: relative;
.indicator {
display: inline-block;
position: absolute;
height: 7px;
left: 0;
right: 0;
bottom: -1px;
}
}
.app-sidebar-tabs__tab:hover, .app-sidebar-tabs__tab:focus, .app-sidebar-tabs__tab:active, .app-sidebar-tabs__tab.active {
opacity: 1;
cursor: pointer;
}
.app-sidebar-tabs__tab {
position: relative;
display: block;
overflow: hidden;
padding: 10px 10px 10px 10px;
transition: color var(--animation-quick), opacity var(--animation-quick), border-color var(--animation-quick);
text-align: center;
white-space: nowrap;
text-overflow: ellipsis;
opacity: .7;
color: var(--color-main-text);
border-bottom: 1px solid var(--color-border);
}
.tab_container {

View file

@ -17,7 +17,6 @@ script('passman', 'vendor/angular-translate/angular-translate.min');
script('passman', 'vendor/angular-translate/angular-translate-loader-url.min');
script('passman', 'vendor/ng-password-meter/ng-password-meter');
script('passman', 'vendor/sjcl/sjcl');
script('passman', 'vendor/ui-sortable/sortable');
script('passman', 'vendor/zxcvbn/zxcvbn');
script('passman', 'vendor/ng-clipboard/clipboard.min');
script('passman', 'vendor/ng-clipboard/ngclipboard');
@ -26,6 +25,9 @@ script('passman', 'vendor/angular-xeditable/xeditable.min');
script('passman', 'vendor/sha/sha');
script('passman', 'vendor/llqrcode/llqrcode');
script('passman', 'vendor/forge.0.6.9.min');
script('passman', 'vendor/download');
script('passman', 'vendor/ui-sortable/sortable');
script('passman', 'vendor/papa-parse/papaparse.min');
script('passman', 'lib/promise');
script('passman', 'lib/crypto_wrap');
@ -37,6 +39,9 @@ script('passman', 'app/controllers/bookmarklet');
script('passman', 'app/filters/range');
script('passman', 'app/filters/propsfilter');
script('passman', 'app/filters/byte');
script('passman', 'app/filters/tagfilter');
script('passman', 'app/filters/escapeHTML');
script('passman', 'app/filters/as');
script('passman', 'app/services/vaultservice');
script('passman', 'app/services/credentialservice');
script('passman', 'app/services/settingsservice');
@ -88,23 +93,43 @@ style('passman', 'bookmarklet');
<div ng-include="'views/vaults.html'"></div>
</div>
<div id="app-content-wrapper" ng-if="active_vault !== false">
<div class="active_vault">
{{ 'bm.active.vault' | translate}} {{active_vault.name}}<br />
<span class="link" ng-click="logout()">{{ 'change.vault' | translate }}</span>
</div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="{active:isActiveTab(tab)}"
ng-click="onClickTab(tab)" use-theme
>{{tab.title}}
</li>
</ul>
<div id="content">
<div id="passman-controls">
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg" data-dir="/Test">
<a>{{ active_vault.name }}</a>
</div>
<div class="crumb svg last" data-dir="/Test">
<a ng-if="storedCredential.credential_id">{{ 'edit.credential' | translate }}
"{{ storedCredential.label }}"</a>
<a ng-if="!storedCredential.credential_id">{{ 'create.credential' | translate }}</a>
</div>
</div>
<div class="tab_container edit_credential">
<div ng-include="currentTab.url"></div>
<button ng-click="saveCredential()">{{ 'save' | translate }}</button>
<button ng-click="cancel()">{{ 'cancel' | translate }}</button>
</div>
</div>
</div>
<div class="app-sidebar-tabs">
<nav class="app-sidebar-tabs__nav">
<ul>
<li ng-repeat="tab in tabs track by $index" class="app-sidebar-tabs__tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)">{{ tab.title }}
</li>
</ul>
</nav>
<div class="tab_container edit_credential">
<div ng-include="currentTab.url"></div>
<button ng-click="saveCredential()">{{ 'save' | translate }}</button>
<button ng-click="cancel()">{{ 'cancel' | translate }}</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -155,15 +155,15 @@ style('passman', 'app');
</ul>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-red"></div>
<div class="app-navigation-entry-bullet-with-hover bullet-color-red"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_low'}" ng-click="filterCredentialBySpecial('strength_low')">{{ 'navigation.strength.bad' | translate }}</a>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-yellow"></div>
<div class="app-navigation-entry-bullet-with-hover bullet-color-yellow"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_medium'}" ng-click="filterCredentialBySpecial('strength_medium')">{{ 'navigation.strength.medium' | translate }}</a>
</li>
<li>
<div class="app-navigation-entry-bullet bullet-color-green"></div>
<div class="app-navigation-entry-bullet-with-hover bullet-color-green"></div>
<a ng-class="{selected: clickedNavigationItem=='strength_good'}" ng-click="filterCredentialBySpecial('strength_good')">{{ 'navigation.strength.good' | translate }}</a>
</li>
<li>

View file

@ -1,35 +1,36 @@
<div id="passman-controls">
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg" data-dir="/Test">
<a ng-click="cancel()">{{ active_vault.name }}</a>
</div>
<div class="crumb svg last" data-dir="/Test">
<a ng-if="storedCredential.credential_id">{{ 'edit.credential' | translate }}
"{{ storedCredential.label }}"</a>
<a ng-if="!storedCredential.credential_id">{{ 'create.credential' | translate }}</a>
</div>
</div>
<div class="breadcrumb">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg" data-dir="/Test">
<a ng-click="cancel()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last" data-dir="/Test">
<a ng-if="storedCredential.credential_id">{{ 'edit.credential' | translate}}
"{{storedCredential.label}}"</a>
<a ng-if="!storedCredential.credential_id">{{ 'create.credential' | translate}}</a>
</div>
</div>
</div>
</div>
<div class="app-sidebar-tabs">
<nav class="app-sidebar-tabs__nav">
<ul>
<li ng-repeat="tab in tabs track by $index" class="app-sidebar-tabs__tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)">{{ tab.title }}
</li>
</ul>
</nav>
</div>
</div>
<div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)" use-theme color="'true'"
>{{tab.title}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container edit_credential" use-theme type="'border-top-color'">
<div ng-include="currentTab.url"></div>
<button ng-click="saveCredential()" ng-disabled="saving"><i class="fa fa-spinner fa-spin" ng-show="saving"></i> {{ 'save' | translate}}</button>
<button ng-click="cancel()">{{ 'cancel' | translate}}</button>
</div>
<div class="tab_container edit_credential" use-theme type="'border-top-color'">
<div ng-include="currentTab.url"></div>
<button ng-click="saveCredential()" ng-disabled="saving"><i class="fa fa-spinner fa-spin" ng-show="saving"></i>
{{ 'save' | translate }}
</button>
<button ng-click="cancel()">{{ 'cancel' | translate }}</button>
</div>
</div>

View file

@ -5,26 +5,26 @@
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg">
<a ng-click="cancel()">{{active_vault.name}}</a>
<a ng-click="cancel()">{{ active_vault.name }}</a>
</div>
<div class="crumb svg last">
<a>{{ 'settings' | translate}}</a>
<a>{{ 'settings' | translate }}</a>
</div>
</div>
</div>
</div>
<div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)" use-theme color="'true'">{{tab.title | translate}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="app-sidebar-tabs">
<nav class="app-sidebar-tabs__nav">
<ul>
<li ng-repeat="tab in tabs track by $index" class="app-sidebar-tabs__tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)">{{ tab.title | translate }}
</li>
</ul>
</nav>
<div class="tab_container settings edit_credential" use-theme type="'border-top-color'">
<div ng-include="currentTab.url"></div>
</div>
</div>
</div>

View file

@ -1,34 +1,40 @@
<div class="main_list.share">
<div id="passman-controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg" data-dir="/Test">
<a ng-click="cancel()">{{active_vault.name}}</a>
</div>
<div class="crumb svg last" data-dir="/Test">
<a ng-if="storedCredential.credential_id">
{{ 'share.credential' | translate}} {{storedCredential.label}}
</a>
</div>
</div>
</div>
<div id="passman-controls">
<div class="actions creatable">
<div class="breadcrumb">
<div class="crumb svg ui-droppable" data-dir="/">
<a ng-click="logout()"><i class="fa fa-home"></i></a>
</div>
<div class="crumb svg" data-dir="/Test">
<a ng-click="cancel()">{{ active_vault.name }}</a>
</div>
<div class="crumb svg last" data-dir="/Test">
<a ng-if="storedCredential.credential_id">
{{ 'share.credential' | translate }} {{ storedCredential.label }}
</a>
</div>
</div>
</div>
</div>
<ul class="tab_header">
<li ng-repeat="tab in tabs track by $index" class="tab"
ng-class="{active:isActiveTab(tab)}"
ng-click="onClickTab(tab)" use-theme color="'true'">{{tab.title | translate}}
<div class="indicator" use-theme negative="'true'"></div>
</li>
</ul>
<div class="tab_container share_credential" ng-show="currentTab">
<div ng-include="currentTab.url"></div>
<div class="app-sidebar-tabs">
<nav class="app-sidebar-tabs__nav">
<ul>
<li ng-repeat="tab in tabs track by $index" class="app-sidebar-tabs__tab"
ng-class="isActiveTab(tab)? 'active' : 'inactive'"
ng-click="onClickTab(tab)">{{ tab.title | translate }}
</li>
</ul>
</nav>
<button ng-click="applyShare()" ng-disabled="share_settings.linkSharing.enabled === false && share_settings.credentialSharedWithUserAndGroup.length === 0">{{ 'share' | translate}}</button>
<button ng-click="cancel()">{{ 'cancel' | translate}}</button>
<button class="btn btn-danger" ng-disabled="!storedCredential.shared_key" ng-click="unshareCredential(storedCredential)">{{ 'unshare' | translate}}</button>
</div>
</div>
<div class="tab_container share_credential" ng-show="currentTab">
<div ng-include="currentTab.url"></div>
<button ng-click="applyShare()"
ng-disabled="share_settings.linkSharing.enabled === false && share_settings.credentialSharedWithUserAndGroup.length === 0">
{{ 'share' | translate }}
</button>
<button ng-click="cancel()">{{ 'cancel' | translate }}</button>
<button class="btn btn-danger" ng-disabled="!storedCredential.shared_key"
ng-click="unshareCredential(storedCredential)">{{ 'unshare' | translate }}
</button>
</div>
</div>

View file

@ -51,10 +51,10 @@
<span class="tag" ng-repeat="tag in credential.tags_raw">{{ ::tag.text}}</span>
</span>
<span class="icon" ng-if="credential.url || credential.icon">
<span class="icon" ng-if="credential.url || (credential.icon && credential.icon.type !== false)">
<credential-icon credential="credential"></credential-icon>
</span>
<span class="icon" ng-if="!credential.url && !credential.icon">
<span class="icon" ng-if="!credential.url && (!credential.icon || (credential.icon && !credential.icon.type))">
<i class="fa fa-lock" ng-if="!credential.acl && !credential.shared_key"></i>
<i class="fa fa-share-alt" ng-if="credential.acl"></i>
<i class="fa fa-share-alt-square" ng-if="credential.shared_key"> </i>
@ -148,10 +148,10 @@
<span class="close icon-close" ng-click="closeSelected()" alt="Close"></span>
<div class="sidebar">
<span class="icon sidebar-icon" ng-if="selectedCredential.url || selectedCredential.icon">
<span class="icon sidebar-icon" ng-if="selectedCredential.url || (selectedCredential.icon && selectedCredential.icon.type !== false)">
<credential-icon credential="selectedCredential"></credential-icon>
</span>
<span class="icon sidebar-icon" ng-if="!selectedCredential.url && !selectedCredential.icon">
<span class="icon sidebar-icon" ng-if="!selectedCredential.url && (!selectedCredential.icon || (selectedCredential.icon && !selectedCredential.icon.type))">
<i class="fa fa-lock fa-3x icon-image"></i>
</span>
<h2 class="sidebar-label">{{selectedCredential.label}}</h2>