action buttons component

This commit is contained in:
Kyle Spearrin 2017-10-16 14:45:47 -04:00
parent 276be2fa87
commit ad285a7605
14 changed files with 199 additions and 198 deletions

View File

@ -64,9 +64,18 @@
"copyPassword": {
"message": "Copy Password"
},
"copyUri": {
"message": "Copy URI"
},
"copyUsername": {
"message": "Copy Username"
},
"copyNumber": {
"message": "Copy Number"
},
"copySecurityCode": {
"message": "Copy Security Code"
},
"autoFill": {
"message": "Auto-fill"
},

View File

@ -140,6 +140,7 @@ var Login = function (obj, alreadyEncrypted, localData) {
var Cipher = function (obj, alreadyEncrypted, localData) {
this.constantsService = chrome.extension.getBackgroundPage().bg_constantsService;
this.utilsService = chrome.extension.getBackgroundPage().bg_utilsService;
buildDomainModel(this, obj, {
id: null,
@ -417,6 +418,9 @@ function buildDomainModel(model, obj, map, alreadyEncrypted, notEncList) {
case self.constantsService.cipherType.login:
model.login = decObj;
model.subTitle = model.login.username;
if (model.login.uri) {
model.login.domain = self.utilsService.getDomain(model.login.uri);
}
break;
case self.constantsService.cipherType.secureNote:
model.secureNote = decObj;

View File

@ -1,18 +1,41 @@
angular
.module('bit.components')
.component('actionButtonsComponent', {
.component('actionButtons', {
bindings: {
uri: '<'
cipher: '<',
showView: '<',
onView: '&'
},
template: '',
controller: function (stateService) {
this.$onInit = (function () {
}).bind(this);
templateUrl: 'app/components/views/actionButtons.html',
controller: function (i18nService, $analytics, constantsService, toastr, $timeout, $window, utilsService) {
var ctrl = this;
this.$onChanges = (function () {
}).bind(this);
ctrl.$onInit = function () {
ctrl.i18n = i18nService;
ctrl.constants = constantsService;
ctrl.launch = function () {
$timeout(function () {
if (ctrl.cipher.login.uri.startsWith('http://') || ctrl.cipher.login.uri.startsWith('https://')) {
$analytics.eventTrack('Launched Website From Listing');
chrome.tabs.create({ url: ctrl.cipher.login.uri });
if (utilsService.inPopup($window)) {
$window.close();
}
}
});
};
ctrl.clipboardError = function (e) {
toastr.info(i18n.browserNotSupportClipboard);
};
ctrl.clipboardSuccess = function (e, type, aType) {
e.clearSelection();
$analytics.eventTrack('Copied ' + aType);
toastr.info(type + i18nService.valueCopied);
};
};
}
});

View File

@ -0,0 +1,38 @@
<div class="action-buttons">
<div ng-if="$ctrl.cipher.type === $ctrl.constants.cipherType.login">
<span class="btn-list" stop-prop stop-click title="{{$ctrl.i18n.launchWebsite}}" ng-click="$ctrl.launch()"
ng-if="$ctrl.cipher.login.uri && !$ctrl.showView">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<span class="btn-list" ng-click="$ctrl.onView($ctrl.cipher)" stop-prop stop-click title="{{i18n.view}}"
ng-if="$ctrl.showView">
<i class="fa fa-lg fa-eye"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{$ctrl.i18n.copyUsername}}" ngclipboard
ngclipboard-error="$ctrl.clipboardError(e)"
ngclipboard-success="$ctrl.clipboardSuccess(e, $ctrl.i18n.username, 'Username')"
data-clipboard-text="{{$ctrl.cipher.login.username}}" ng-if="$ctrl.cipher.login.username">
<i class="fa fa-lg fa-user"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{$ctrl.i18n.copyPassword}}" ngclipboard
ngclipboard-error="$ctrl.clipboardError(e)"
ngclipboard-success="$ctrl.clipboardSuccess(e, $ctrl.i18n.password, 'Password')"
data-clipboard-text="{{$ctrl.cipher.login.password}}" ng-if="$ctrl.cipher.login.password">
<i class="fa fa-lg fa-key"></i>
</span>
</div>
<div ng-if="$ctrl.cipher.type === $ctrl.constants.cipherType.card">
<span class="btn-list" stop-prop stop-click title="{{$ctrl.i18n.copyNumber}}" ngclipboard
ngclipboard-error="$ctrl.clipboardError(e)"
ngclipboard-success="$ctrl.clipboardSuccess(e, $ctrl.i18n.number, 'Card Number')"
data-clipboard-text="{{$ctrl.cipher.card.number}}" ng-if="$ctrl.cipher.card.number">
<i class="fa fa-lg fa-hashtag"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{$ctrl.i18n.copySecurityCode}}" ngclipboard
ngclipboard-error="$ctrl.clipboardError(e)"
ngclipboard-success="$ctrl.clipboardSuccess(e, $ctrl.i18n.securityCode, 'Security Code')"
data-clipboard-text="{{$ctrl.cipher.card.code}}" ng-if="$ctrl.cipher.card.code">
<i class="fa fa-lg fa-key"></i>
</span>
</div>
</div>

View File

@ -25,15 +25,17 @@ angular
url = tabs[0].url;
}
else {
$scope.loaded = true;
$scope.$apply();
$timeout(function () {
$scope.loaded = true;
});
return;
}
domain = utilsService.getDomain(url);
if (!domain) {
$scope.loaded = true;
$scope.$apply();
$timeout(function () {
$scope.loaded = true;
});
return;
}
@ -42,23 +44,15 @@ angular
canAutofill = true;
});
loginService.getAllDecryptedForDomain(domain).then(function (logins) {
$scope.loaded = true;
$scope.ciphers = ciphers;
loginService.getAllDecryptedForDomain(domain).then(function (ciphers) {
$timeout(function () {
$scope.loaded = true;
$scope.ciphers = ciphers;
});
});
});
}
$scope.clipboardError = function (e, password) {
toastr.info(i18n.browserNotSupportClipboard);
};
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
toastr.info(type + i18nService.valueCopied);
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
};
$scope.addCipher = function () {
$state.go('addCipher', {
animation: 'in-slide-up',

View File

@ -21,23 +21,8 @@
title="{{i18n.autoFill}} {{cipher.name}}"
ng-repeat="cipher in theCiphers = (ciphers | orderBy: [sortUriMatch, sortLastUsed, 'name', 'subTitle'])
track by $index">
<span class="btn-list" stop-prop stop-click title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.password}}" ng-class="{'disabled': !cipher.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.username}}" ng-class="{'disabled': !cipher.username}">
<i class="fa fa-lg fa-user"></i>
</span>
<span class="btn-list" ng-click="viewCipher(cipher)" stop-prop stop-click
title="{{i18n.edit}} {{cipher.name}}">
<i class="fa fa-lg fa-pencil"></i>
</span>
<icon uri="cipher.uri"></icon>
<action-buttons cipher="cipher" show-view="true" on-view="viewCipher(cipher)"></action-buttons>
<icon cipher="cipher"></icon>
<span class="text">
{{cipher.name}}
<i class="fa fa-share-alt text-muted" ng-if="cipher.organizationId" title="{{i18n.shared}}"></i>

View File

@ -161,28 +161,6 @@
});
};
$scope.clipboardError = function (e) {
toastr.info(i18n.browserNotSupportClipboard);
};
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
toastr.info(type + i18nService.valueCopied);
};
$scope.launchWebsite = function (cipher) {
$timeout(function () {
if (cipher.uri.startsWith('http://') || cipher.uri.startsWith('https://')) {
$analytics.eventTrack('Launched Website From Listing');
chrome.tabs.create({ url: cipher.uri });
if (utilsService.inPopup($window)) {
$window.close();
}
}
});
};
$scope.$on('syncCompleted', function (event, successfully) {
$timeout(loadVault, 500);
});

View File

@ -111,9 +111,9 @@ angular
return masked;
};
$scope.clipboardSuccess = function (e, type) {
$scope.clipboardSuccess = function (e, type, aType) {
e.clearSelection();
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
$analytics.eventTrack('Copied ' + aType);
toastr.info(type + i18nService.valueCopied);
};

View File

@ -130,18 +130,6 @@
resetList(matchedCiphers);
};
$scope.launchWebsite = function (cipher) {
$timeout(function () {
if (cipher.uri.startsWith('http://') || cipher.uri.startsWith('https://')) {
$analytics.eventTrack('Launched Website From Listing');
chrome.tabs.create({ url: cipher.uri });
if (utilsService.inPopup($window)) {
$window.close();
}
}
});
};
function resetList(ciphers) {
$scope.vaultCiphers = ciphers;
$scope.pagedVaultCiphers = [];
@ -201,16 +189,6 @@
}, 200);
};
$scope.clipboardError = function (e) {
toastr.info(i18n.browserNotSupportClipboard);
};
$scope.clipboardSuccess = function (e, type) {
e.clearSelection();
$analytics.eventTrack('Copied ' + (type === i18nService.username ? 'Username' : 'Password'));
toastr.info(type + i18nService.valueCopied);
};
function storeState() {
angular.extend(state, {
scrollY: getScrollY(),

View File

@ -41,20 +41,7 @@
class="list-grouped-item condensed" title="{{i18n.edit}} {{cipher.name}}"
ng-repeat="cipher in vaultFolderCiphers = (vaultCiphers | filter: { folderId: folder.id }
| filter: searchCiphers() | orderBy: ['name', 'subTitle']) track by $index">
<span class="btn-list" stop-prop stop-click title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.password}}" ng-class="{'disabled': !cipher.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.username}}" ng-class="{'disabled': !cipher.username}">
<i class="fa fa-lg fa-user"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-class="{'disabled': !cipher.uri}">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<action-buttons cipher="cipher"></action-buttons>
<icon cipher="cipher"></icon>
<span class="text">
{{cipher.name}}
@ -74,20 +61,7 @@
class="list-section-item condensed" title="{{i18n.edit}} {{cipher.name}}"
ng-repeat="cipher in searchResults = (vaultCiphers | filter: searchCiphers() | orderBy: ['name', 'subTitle'])
track by $index">
<span class="btn-list" stop-prop stop-click title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.password}}" ng-class="{'disabled': !cipher.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.username}}" ng-class="{'disabled': !cipher.username}">
<i class="fa fa-lg fa-user"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-class="{'disabled': !cipher.uri}">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<action-buttons cipher="cipher"></action-buttons>
<icon cipher="cipher"></icon>
<span class="text">
{{cipher.name}}

View File

@ -21,43 +21,58 @@
</div>
<div ng-if="cipher.type === constants.cipherType.login">
<div class="list-section-item" ng-if="cipher.login.uri" title="{{cipher.login.uri}}">
<a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-show="cipher.showLaunch">
<i class="fa fa-lg fa-share-square-o"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-show="cipher.showLaunch">
<i class="fa fa-lg fa-share-square-o"></i>
</a>
<a class="btn-list" href="" title="{{i18n.copyUri}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.uri, 'URI')"
data-clipboard-text="{{cipher.login.uri}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{i18n.website}}</span>
{{cipher.login.website}}
</div>
<div class="list-section-item" ng-if="cipher.login.username">
<a class="btn-list" href="" title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.login.username}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.copyUsername}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.username, 'Username')"
data-clipboard-text="{{cipher.login.username}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{i18n.username}}</span>
<span id="username">{{cipher.login.username}}</span>
</div>
<div class="list-section-item" ng-if="cipher.login.password">
<a class="btn-list" href="" title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.login.password}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<a class="btn-list" href="" title="{{i18n.togglePassword}}" ng-click="togglePassword()">
<i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.togglePassword}}" ng-click="togglePassword()">
<i class="fa fa-lg" ng-class="[{'fa-eye': !showPassword}, {'fa-eye-slash': showPassword}]"></i>
</a>
<a class="btn-list" href="" title="{{i18n.copyPassword}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.password, 'Password')"
data-clipboard-text="{{cipher.login.password}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{i18n.password}}</span>
<span ng-show="!showPassword" class="monospaced">{{cipher.maskedPassword}}</span>
<span id="password" ng-show="showPassword" class="monospaced">{{cipher.login.password}}</span>
</div>
<div class="list-section-item totp" ng-class="{'low': totpLow}" ng-if="cipher.login.totp && totpCode">
<a class="btn-list" href="" title="{{i18n.copyVerificationCode}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.verificationCodeTotp)" data-clipboard-text="{{totpCode}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.copyVerificationCode}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.verificationCodeTotp, 'TOTP')"
data-clipboard-text="{{totpCode}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="totp-countdown">
<span class="totp-sec">{{totpSec}}</span>
<svg>
@ -70,26 +85,31 @@
</span>
<span class="item-label">{{i18n.verificationCodeTotp}}</span>
<span id="totp" class="totp-code">{{totpCodeFormatted}}</span>
</div>
</div>
<div ng-if="cipher.type === constants.cipherType.card">
<div class="list-section-item" ng-if="cipher.card.cardholderName">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.cardholderName)"
data-clipboard-text="{{cipher.card.cardholderName}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.cardholderName, 'Cardholder Name')"
data-clipboard-text="{{cipher.card.cardholderName}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{i18n.cardholderName}}</span>
<span id="username">{{cipher.card.cardholderName}}</span>
</div>
<div class="list-section-item" ng-if="cipher.card.number">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.number)"
data-clipboard-text="{{cipher.card.number}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.copy}}"
ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.number, 'Number')"
data-clipboard-text="{{cipher.card.number}}">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{i18n.number}}</span>
<span id="username">{{cipher.card.number}}</span>
</div>
@ -127,15 +147,17 @@
</div>
<div class="list-section-items">
<div class="list-section-item" ng-repeat="field in cipher.fields">
<a class="btn-list" href="" title="{{i18n.copyValue}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.value)" data-clipboard-text="{{field.value}}"
ng-if="field.type !== constants.fieldType.boolean && field.value">
<i class="fa fa-lg fa-clipboard"></i>
</a>
<a class="btn-list" href="" title="{{i18n.toggleValue}}" ng-click="toggleFieldValue(field)"
ng-if="field.type === constants.fieldType.hidden">
<i class="fa fa-lg" ng-class="[{'fa-eye': !field.showValue}, {'fa-eye-slash': field.showValue}]"></i>
</a>
<div class="action-buttons">
<a class="btn-list" href="" title="{{i18n.toggleValue}}" ng-click="toggleFieldValue(field)"
ng-if="field.type === constants.fieldType.hidden">
<i class="fa fa-lg" ng-class="[{'fa-eye': !field.showValue}, {'fa-eye-slash': field.showValue}]"></i>
</a>
<a class="btn-list" href="" title="{{i18n.copyValue}}" ngclipboard ngclipboard-error="clipboardError(e)"
ngclipboard-success="clipboardSuccess(e, i18n.value, 'Field')" data-clipboard-text="{{field.value}}"
ng-if="field.type !== constants.fieldType.boolean && field.value">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
<span class="item-label">{{field.name}}</span>
<div ng-if="field.type === constants.fieldType.text">
{{field.value || '&nbsp;'}}

View File

@ -22,20 +22,8 @@
<a href="#" stop-click ng-click="viewCipher(cipher)"
class="list-section-item condensed" title="{{i18n.edit}} {{cipher.name}}"
ng-repeat="cipher in pagedVaultCiphers track by $index">
<span class="btn-list" stop-prop stop-click title="{{i18n.copyPassword}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.password)"
data-clipboard-text="{{cipher.password}}" ng-class="{'disabled': !cipher.password}">
<i class="fa fa-lg fa-key"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.copyUsername}}" ngclipboard
ngclipboard-error="clipboardError(e)" ngclipboard-success="clipboardSuccess(e, i18n.username)"
data-clipboard-text="{{cipher.username}}" ng-class="{'disabled': !cipher.username}">
<i class="fa fa-lg fa-user"></i>
</span>
<span class="btn-list" stop-prop stop-click title="{{i18n.launchWebsite}}" ng-click="launchWebsite(cipher)"
ng-class="{'disabled': !cipher.uri}">
<i class="fa fa-lg fa-share-square-o"></i>
</span>
<action-buttons cipher="cipher"></action-buttons>
<icon cipher="cipher"></icon>
<span class="text">
{{cipher.name}}
<i class="fa fa-share-alt text-muted" ng-if="cipher.organizationId" title="{{i18n.shared}}"></i>

View File

@ -366,29 +366,34 @@
}
}
.btn-list {
cursor: pointer;
.action-buttons {
float: right;
display: block;
padding: 10px 8px 10px 8px;
background: none;
border: none;
color: @brand-primary;
&:hover, &:focus {
color: darken(@brand-primary, 10%);
}
.btn-list {
float: left;
cursor: pointer;
padding: 10px 8px;
background: none;
border: none;
color: @brand-primary;
&.disabled {
color: @list-icon-color;
&:hover {
color: @list-icon-color;
&:hover, &:focus {
color: darken(@brand-primary, 10%);
}
}
&:first-child {
padding-right: 2px !important;
&.disabled {
color: @list-icon-color;
&:hover {
color: @list-icon-color;
}
}
&:last-child {
padding-right: 2px !important;
}
}
}
@ -412,8 +417,10 @@
&.condensed {
padding: 3px 10px;
.btn-list {
padding: 8px 5px;
.action-buttons {
.btn-list {
padding: 8px 5px;
}
}
&:not(:hover):focus {

View File

@ -284,7 +284,8 @@ function initLoginService() {
ciphersToReturn = [];
for (var i = 0; i < ciphers.length; i++) {
if (ciphers[i].domain && matchingDomains.indexOf(ciphers[i].domain) > -1) {
if (ciphers[i].type === self.constantsService.cipherType.login && ciphers[i].login.domain &&
matchingDomains.indexOf(ciphers[i].login.domain) > -1) {
ciphersToReturn.push(ciphers[i]);
}
}