mirror of
https://github.com/nextcloud/passman.git
synced 2026-01-06 23:57:12 +08:00
Add grid view
This commit is contained in:
parent
5398d2ba74
commit
389fd23b66
9 changed files with 278 additions and 58 deletions
95
css/app.css
95
css/app.css
|
|
@ -172,6 +172,36 @@
|
|||
right: inherit;
|
||||
left: 10px;
|
||||
top: -19px; }
|
||||
#app-content #app-content-wrapper .viewModes {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
margin-top: 3px; }
|
||||
#app-content #app-content-wrapper .viewModes .view-mode:first-child {
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid rgba(240, 240, 240, 0.9); }
|
||||
#app-content #app-content-wrapper .viewModes .view-mode:last-child {
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
background-clip: padding-box;
|
||||
border: 1px solid rgba(240, 240, 240, 0.9); }
|
||||
#app-content #app-content-wrapper .viewModes .view-mode {
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
background-color: rgba(240, 240, 240, 0.9); }
|
||||
#app-content #app-content-wrapper .viewModes .view-mode.active {
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
background-color: rgba(226, 226, 226, 0.9); }
|
||||
#app-content #app-content-wrapper .viewModes .view-mode {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 7px; }
|
||||
#app-content #app-content-wrapper .searchboxContainer {
|
||||
display: inline-block;
|
||||
margin-right: 14px;
|
||||
|
|
@ -194,19 +224,6 @@
|
|||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-left: 3px; }
|
||||
#app-content #app-content-wrapper .credential-table tr td .tags {
|
||||
float: right; }
|
||||
#app-content #app-content-wrapper .credential-table tr td .tags .tag {
|
||||
background-color: rgba(240, 240, 240, 0.9);
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
margin-right: 3px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background-clip: padding-box;
|
||||
/* stops bg color from leaking outside the border: */ }
|
||||
#app-content #app-content-wrapper .credential-table tr td .tags .tag:last-child {
|
||||
margin-right: 8px; }
|
||||
#app-content #app-content-wrapper .credential-table tr td .icon-more {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
|
|
@ -236,6 +253,58 @@
|
|||
#app-content #app-content-wrapper .credential-table tr td .popovermenu .action {
|
||||
padding: 10px;
|
||||
margin: -10px; }
|
||||
#app-content #app-content-wrapper .tags {
|
||||
float: right; }
|
||||
#app-content #app-content-wrapper .tags .tag {
|
||||
background-color: rgba(240, 240, 240, 0.9);
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
margin-right: 3px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background-clip: padding-box;
|
||||
/* stops bg color from leaking outside the border: */ }
|
||||
#app-content #app-content-wrapper .tags .tag:last-child {
|
||||
margin-right: 8px; }
|
||||
#app-content #app-content-wrapper .grid-view {
|
||||
margin-top: 44px;
|
||||
display: flex;
|
||||
flex-wrap: wrap; }
|
||||
#app-content #app-content-wrapper .grid-view .credential {
|
||||
display: flex;
|
||||
padding: 0.5em;
|
||||
width: 100%;
|
||||
border: 1px solid rgba(240, 240, 240, 0.9);
|
||||
margin: 25px;
|
||||
cursor: pointer;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background-clip: padding-box;
|
||||
/* stops bg color from leaking outside the border: */ }
|
||||
#app-content #app-content-wrapper .grid-view .credential .credential_content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
font-size: 1.75em;
|
||||
text-align: center; }
|
||||
#app-content #app-content-wrapper .grid-view .credential .credential_content .label {
|
||||
padding-top: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
line-height: 1.3em; }
|
||||
#app-content #app-content-wrapper .grid-view .credential .credential_content .tags .tag {
|
||||
margin-top: 5px;
|
||||
display: inline-block; }
|
||||
@media all and (min-width: 40em) {
|
||||
#app-content #app-content-wrapper .grid-view .credential {
|
||||
width: 40%; } }
|
||||
@media all and (min-width: 58em) {
|
||||
#app-content #app-content-wrapper .grid-view .credential {
|
||||
width: 26%; } }
|
||||
@media all and (min-width: 78em) {
|
||||
#app-content #app-content-wrapper .grid-view .credential {
|
||||
width: 20%; } }
|
||||
#app-content #app-content-wrapper .edit_credential label {
|
||||
display: block; }
|
||||
#app-content #app-content-wrapper .edit_credential input[type="text"], #app-content #app-content-wrapper .edit_credential input[type="password"] {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -125,6 +125,10 @@ angular.module('passmanApp')
|
|||
});
|
||||
};
|
||||
|
||||
$scope.view_mode = 'list'; //@TODO make this a setting
|
||||
$scope.switchViewMode = function (viewMode) {
|
||||
$scope.view_mode = viewMode;
|
||||
};
|
||||
|
||||
$scope.filterOptions = {
|
||||
filterText: '',
|
||||
|
|
|
|||
34
js/app/directives/colorfromstring.js
Normal file
34
js/app/directives/colorfromstring.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name passmanApp.directive:passwordGen
|
||||
* @description
|
||||
* # passwordGen
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.directive('colorFromString', ['$window', function ($window) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope:{
|
||||
string: '=colorFromString'
|
||||
},
|
||||
link: function (scope, el, attr, ctrl) {
|
||||
function genColor(str) { // java String#hashCode
|
||||
var hash = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
var c = (hash & 0x00FFFFFF)
|
||||
.toString(16)
|
||||
.toUpperCase();
|
||||
|
||||
return '#' + '00000'.substring(0, 6 - c.length) + c;
|
||||
}
|
||||
scope.$watch('string', function(){
|
||||
$(el).css('border-color', genColor(scope.string));
|
||||
})
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
@ -151,7 +151,7 @@ angular.module('passmanApp')
|
|||
|
||||
scope.onError = function(e) {
|
||||
OC.Notification.showTemporary('Press Ctrl+C to copy!');
|
||||
}
|
||||
};
|
||||
scope.progressDivShow = false;
|
||||
scope.generatePasswordStart = function() {
|
||||
scope.progressDivShow = true;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -35,10 +35,37 @@
|
|||
left: 10px;
|
||||
top: -19px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.viewModes{
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
margin-top: 3px;
|
||||
.view-mode:first-child{
|
||||
@include border-left-radius(5px);
|
||||
border: 1px solid rgba(240,240,240,.9);
|
||||
}
|
||||
.view-mode:last-child{
|
||||
@include border-right-radius(5px);
|
||||
border: 1px solid rgba(240,240,240,.9);
|
||||
}
|
||||
.view-mode{
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
background-color: rgba(240,240,240,.9);
|
||||
}
|
||||
.view-mode.active{
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
background-color: rgba(226, 226, 226, 0.9);
|
||||
}
|
||||
.view-mode{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.searchboxContainer{
|
||||
display: inline-block;
|
||||
margin-right: 14px;
|
||||
|
|
@ -67,19 +94,7 @@
|
|||
margin-right: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.tags {
|
||||
float: right;
|
||||
.tag {
|
||||
background-color: rgba(240, 240, 240, .9);
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
margin-right: 3px;
|
||||
@include border-radius(5px);
|
||||
}
|
||||
.tag:last-child{
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-more {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
|
|
@ -120,6 +135,73 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
float: right;
|
||||
.tag {
|
||||
background-color: rgba(240, 240, 240, .9);
|
||||
padding: 4px;
|
||||
font-size: 12px;
|
||||
margin-right: 3px;
|
||||
@include border-radius(5px);
|
||||
}
|
||||
.tag:last-child{
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-view{
|
||||
margin-top: 44px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.credential{
|
||||
display: flex;
|
||||
padding: 0.5em;
|
||||
width: 100%;
|
||||
border: 1px solid rgba(240,240,240,.9);
|
||||
margin: 25px;
|
||||
cursor: pointer;
|
||||
@include border-radius(5px);
|
||||
.credential_content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
font-size: 1.75em;
|
||||
text-align: center;
|
||||
.label{
|
||||
padding-top: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
line-height: 1.3em;
|
||||
|
||||
}
|
||||
.tags{
|
||||
.tag{
|
||||
margin-top: 5px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 40em) {
|
||||
.credential {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 58em) {
|
||||
.credential {
|
||||
width: 26%;
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 78em) {
|
||||
.credential {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.edit_credential {
|
||||
label {
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ script('passman', 'app/directives/credentialfield');
|
|||
script('passman', 'app/directives/ngenter');
|
||||
script('passman', 'app/directives/autoscroll');
|
||||
script('passman', 'app/directives/clickselect');
|
||||
script('passman', 'app/directives/colorfromstring');
|
||||
script('passman', 'importers/import-main');
|
||||
script('passman', 'importers/importer-keepasscsv');
|
||||
script('passman', 'importers/importer-lastpasscsv');
|
||||
|
|
@ -128,7 +129,7 @@ style('passman', 'app');
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="app-content" ng-class="{'with-app-sidebar': app_sidebar}">
|
||||
<div id="app-content">
|
||||
<div id="app-content-wrapper">
|
||||
<div id="content" ng-view="">
|
||||
|
||||
|
|
|
|||
|
|
@ -45,29 +45,50 @@
|
|||
<input type="text" ng-model="filterOptions.filterText" class="searchbox"
|
||||
placeholder="Search credential..." select-on-click>
|
||||
</div>
|
||||
<div class="viewModes">
|
||||
<div class="view-mode" ng-class="{'active': view_mode === 'list' }"
|
||||
ng-click="switchViewMode('list')"><i class="fa fa-list"></i></div>
|
||||
<div class="view-mode" ng-class="{'active': view_mode === 'grid' }"
|
||||
ng-click="switchViewMode('grid')"><i class="fa fa-th-large"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div off-click="closeSelected()">
|
||||
|
||||
<div class="loaderContainer" ng-show="show_spinner">
|
||||
<div class="loader" use-theme type="'border-bottom-color'"></div>
|
||||
</div>
|
||||
|
||||
<table class="credential-table" ng-init="menuOpen = false;">
|
||||
<tr ng-repeat="credential in credentials | credentialSearch:filterOptions | tagFilter:selectedtags | orderBy:'label'| as:this:'filtered_credentials'"
|
||||
ng-if="credential.hidden == 0 && showCredentialRow(credential)"
|
||||
ng-click="selectCredential(credential)"
|
||||
ng-class="{'selected': selectedCredential.credential_id == credential.credential_id}">
|
||||
<td>
|
||||
<span class="icon"><i class="fa fa-lock"></i> </span>
|
||||
<span class="label">{{credential.label}}</span>
|
||||
<span class="tags">
|
||||
<div ng-init="menuOpen = false;">
|
||||
<table class="credential-table"
|
||||
ng-if="view_mode === 'list'">
|
||||
<tr ng-repeat="credential in credentials | credentialSearch:filterOptions | tagFilter:selectedtags | orderBy:'label'| as:this:'filtered_credentials'"
|
||||
ng-if="credential.hidden == 0 && showCredentialRow(credential)"
|
||||
ng-click="selectCredential(credential)"
|
||||
ng-class="{'selected': selectedCredential.credential_id == credential.credential_id}">
|
||||
<td>
|
||||
<span class="icon"><i class="fa fa-lock"></i> </span>
|
||||
<span class="label">{{credential.label}}</span>
|
||||
<span class="tags">
|
||||
<span class="tag" ng-repeat="tag in credential.tags_raw">{{tag.text}}</span>
|
||||
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul class="grid-view" ng-show="view_mode === 'grid'">
|
||||
<li class="credential" ng-repeat="credential in credentials | credentialSearch:filterOptions | tagFilter:selectedtags | orderBy:'label'| as:this:'filtered_credentials'"
|
||||
ng-if="credential.hidden == 0 && showCredentialRow(credential)"
|
||||
ng-click="selectCredential(credential)"
|
||||
color-from-string="credential.label">
|
||||
<div class="credential_content">
|
||||
<div class="label">{{credential.label}}</div>
|
||||
<div class="tags">
|
||||
<div class="tag" ng-repeat="tag in credential.tags_raw">{{tag.text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="app-sidebar" class="detailsView scroll-container app_sidebar"
|
||||
ng-show="selectedCredential">
|
||||
<span class="close icon-close" ng-click="closeSelected()"
|
||||
|
|
@ -151,7 +172,8 @@
|
|||
Expire time
|
||||
</td>
|
||||
<td>
|
||||
{{selectedCredential.expire_time * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
|
||||
{{selectedCredential.expire_time * 1000 | date:'dd-MM-yyyy @
|
||||
HH:mm:ss'}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="selectedCredential.changed">
|
||||
|
|
@ -159,7 +181,8 @@
|
|||
Changed
|
||||
</td>
|
||||
<td>
|
||||
{{selectedCredential.changed * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
|
||||
{{selectedCredential.changed * 1000 | date:'dd-MM-yyyy @
|
||||
HH:mm:ss'}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="selectedCredential.created">
|
||||
|
|
@ -167,37 +190,44 @@
|
|||
Created
|
||||
</td>
|
||||
<td>
|
||||
{{selectedCredential.created * 1000 | date:'dd-MM-yyyy @ HH:mm:ss'}}
|
||||
{{selectedCredential.created * 1000 | date:'dd-MM-yyyy @
|
||||
HH:mm:ss'}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div class="tags">
|
||||
<span class="tag" ng-repeat="tag in selectedCredential.tags">{{tag.text}}</span>
|
||||
<span class="tag" ng-repeat="tag in selectedCredential.tags">{{tag.text}}</span>
|
||||
</div>
|
||||
|
||||
<div ng-show="selectedCredential">
|
||||
<button class="button" ng-click="editCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
|
||||
<button class="button" ng-click="editCredential(selectedCredential)"
|
||||
ng-if="selectedCredential.delete_time == 0">
|
||||
<span class="fa fa-edit"></span> Edit
|
||||
</button>
|
||||
<button class="button" ng-click="deleteCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
|
||||
<span class="fa fa-trash" ></span> Delete
|
||||
<button class="button"
|
||||
ng-click="deleteCredential(selectedCredential)"
|
||||
ng-if="selectedCredential.delete_time == 0">
|
||||
<span class="fa fa-trash"></span> Delete
|
||||
</button>
|
||||
<button class="button" ng-click="shareCredential(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
|
||||
<button class="button"
|
||||
ng-click="shareCredential(selectedCredential)"
|
||||
ng-if="selectedCredential.delete_time == 0">
|
||||
<span class="fa fa-share"></span> Share
|
||||
</button>
|
||||
|
||||
<button class="button" ng-click="getRevisions(selectedCredential)" ng-if="selectedCredential.delete_time == 0" >
|
||||
<button class="button" ng-click="getRevisions(selectedCredential)"
|
||||
ng-if="selectedCredential.delete_time == 0">
|
||||
<span class="fa fa-undo"></span> Revisions
|
||||
</button>
|
||||
|
||||
<button class="button" ng-if="selectedCredential.delete_time > 0"
|
||||
ng-click="recoverCredential(selectedCredential)">
|
||||
ng-click="recoverCredential(selectedCredential)">
|
||||
<span class="fa fa-recycle"></span> Recover
|
||||
</button>
|
||||
<button class="button" ng-if="selectedCredential.delete_time > 0"
|
||||
ng-click="destroyCredential(selectedCredential)">
|
||||
ng-click="destroyCredential(selectedCredential)">
|
||||
<span class="fa fa-bomb"></span> Destroy
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue