mirror of
https://github.com/nextcloud/passman.git
synced 2025-10-18 09:27:02 +08:00
Add tags input
This commit is contained in:
parent
d21d75d976
commit
675c736d88
23 changed files with 346 additions and 49 deletions
|
@ -40,6 +40,7 @@ return [
|
|||
|
||||
//File stuff
|
||||
['name' => 'file#uploadFile', 'url' => '/api/v2/file', 'verb' => 'POST'],
|
||||
['name' => 'file#getFile', 'url' => '/api/v2/file/{file_id}', 'verb' => 'GET'],
|
||||
['name' => 'file#deleteFile', 'url' => '/api/v2/file/{file_id}', 'verb' => 'DELETE'],
|
||||
|
||||
]
|
||||
|
|
|
@ -42,6 +42,12 @@ class FileController extends ApiController {
|
|||
return $this->fileService->createFile($file, $this->userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function getFile($file_id) {
|
||||
return $this->fileService->getFile($file_id, $this->userId);
|
||||
}
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
|
|
14
css/app.css
14
css/app.css
|
@ -14,6 +14,13 @@
|
|||
background: #d83a02;
|
||||
color: #fff; }
|
||||
|
||||
.link {
|
||||
color: #0066ff !important;
|
||||
cursor: pointer; }
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline; }
|
||||
|
||||
.tab_header {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
@ -216,6 +223,8 @@
|
|||
background-color: rgba(240, 240, 240, 0.9);
|
||||
padding: 4px;
|
||||
font-size: 11px; }
|
||||
#app-content #app-content-wrapper .edit_credential tags-input .tags {
|
||||
width: 100%; }
|
||||
#app-content #app-content-wrapper .edit_credential .credential_textarea {
|
||||
width: 100%;
|
||||
height: 100px; }
|
||||
|
@ -294,11 +303,6 @@
|
|||
|
||||
.settings-container div {
|
||||
padding-left: 15px; }
|
||||
.settings-container div .link {
|
||||
color: #0066ff !important;
|
||||
cursor: pointer; }
|
||||
.settings-container div .link:hover {
|
||||
text-decoration: underline; }
|
||||
|
||||
#app-settings-content:not(.ng-hide) {
|
||||
height: 60px;
|
||||
|
|
File diff suppressed because one or more lines are too long
170
css/vendor/ng-tags-input/ng-tags-input.min.css
vendored
Normal file
170
css/vendor/ng-tags-input/ng-tags-input.min.css
vendored
Normal file
|
@ -0,0 +1,170 @@
|
|||
tags-input {
|
||||
display: block
|
||||
}
|
||||
|
||||
tags-input *, tags-input :after, tags-input :before {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
tags-input .host {
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
tags-input .host:active {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
tags-input .tags {
|
||||
-moz-appearance: textfield;
|
||||
-webkit-appearance: textfield;
|
||||
padding: 1px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
cursor: text;
|
||||
background-color: #fff;
|
||||
border: 1px solid #a9a9a9;
|
||||
box-shadow: 1px 1px 1px 0 #d3d3d3 inset;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
tags-input .tags.focused {
|
||||
outline: 0;
|
||||
-webkit-box-shadow: 0 0 3px 1px rgba(5, 139, 242, .6);
|
||||
-moz-box-shadow: 0 0 3px 1px rgba(5, 139, 242, .6);
|
||||
box-shadow: 0 0 3px 1px rgba(5, 139, 242, .6)
|
||||
}
|
||||
|
||||
tags-input .tags .tag-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none
|
||||
}
|
||||
|
||||
tags-input .tags .tag-item {
|
||||
margin: 2px;
|
||||
padding: 0 5px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
height: 26px;
|
||||
line-height: 25px;
|
||||
border: 1px solid #acacac;
|
||||
border-radius: 3px;
|
||||
color: #ececec;
|
||||
}
|
||||
|
||||
tags-input .tags .tag-item.selected {
|
||||
background: #ce3702 !important;
|
||||
}
|
||||
|
||||
tags-input .tags .tag-item .remove-button {
|
||||
margin: 0 0 0 5px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: 0 0;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
font: 700 16px Arial, sans-serif;
|
||||
color: #585858
|
||||
}
|
||||
|
||||
tags-input .tags .input.invalid-tag, tags-input .tags .tag-item .remove-button:active {
|
||||
color: red
|
||||
}
|
||||
|
||||
tags-input .tags .input {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
margin: 2px;
|
||||
padding: 0 0 0 5px;
|
||||
float: left;
|
||||
height: 26px;
|
||||
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif
|
||||
}
|
||||
|
||||
tags-input .tags .input::-ms-clear {
|
||||
display: none
|
||||
}
|
||||
|
||||
tags-input.ng-invalid .tags {
|
||||
-webkit-box-shadow: 0 0 3px 1px rgba(255, 0, 0, .6);
|
||||
-moz-box-shadow: 0 0 3px 1px rgba(255, 0, 0, .6);
|
||||
box-shadow: 0 0 3px 1px rgba(255, 0, 0, .6)
|
||||
}
|
||||
|
||||
tags-input[disabled] .host:focus {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
tags-input[disabled] .tags {
|
||||
background-color: #eee;
|
||||
cursor: default
|
||||
}
|
||||
|
||||
tags-input[disabled] .tags .tag-item {
|
||||
opacity: .65;
|
||||
background: -webkit-linear-gradient(top, #f0f9ff 0, rgba(203, 235, 255, .75) 47%, rgba(161, 219, 255, .62) 100%);
|
||||
background: linear-gradient(to bottom, #f0f9ff 0, rgba(203, 235, 255, .75) 47%, rgba(161, 219, 255, .62) 100%)
|
||||
}
|
||||
|
||||
tags-input[disabled] .tags .tag-item .remove-button {
|
||||
cursor: default
|
||||
}
|
||||
|
||||
tags-input[disabled] .tags .tag-item .remove-button:active {
|
||||
color: #585858
|
||||
}
|
||||
|
||||
tags-input[disabled] .tags .input {
|
||||
background-color: #eee;
|
||||
cursor: default
|
||||
}
|
||||
|
||||
tags-input .autocomplete {
|
||||
margin-top: 5px;
|
||||
position: absolute;
|
||||
padding: 5px 0;
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, .2);
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
|
||||
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, .2)
|
||||
}
|
||||
|
||||
tags-input .autocomplete .suggestion-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
max-height: 280px;
|
||||
overflow-y: auto;
|
||||
position: relative
|
||||
}
|
||||
|
||||
tags-input .autocomplete .suggestion-item {
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font: 16px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #000;
|
||||
background-color: #fff
|
||||
}
|
||||
|
||||
tags-input .autocomplete .suggestion-item.selected, tags-input .autocomplete .suggestion-item.selected em {
|
||||
color: #fff;
|
||||
background-color: #0097cf
|
||||
}
|
||||
|
||||
tags-input .autocomplete .suggestion-item em {
|
||||
font: normal 700 16px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #000;
|
||||
background-color: #fff
|
||||
}
|
|
@ -22,6 +22,7 @@ angular
|
|||
'ngPasswordMeter',
|
||||
'ngclipboard',
|
||||
'xeditable',
|
||||
'ngTagsInput'
|
||||
])
|
||||
.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Controller of the passmanApp
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.controller('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService', '$rootScope','EncryptService', function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, EncryptService) {
|
||||
.controller('CredentialCtrl', ['$scope', 'VaultService', 'SettingsService', '$location', 'CredentialService', '$rootScope', 'FileService', 'EncryptService', function ($scope, VaultService, SettingsService, $location, CredentialService, $rootScope, FileService, EncryptService) {
|
||||
$scope.active_vault = VaultService.getActiveVault();
|
||||
if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
|
||||
if (!$scope.active_vault) {
|
||||
|
@ -73,7 +73,19 @@ angular.module('passmanApp')
|
|||
});
|
||||
};
|
||||
|
||||
//@TODO Download files
|
||||
$scope.downloadFile = function (file) {
|
||||
FileService.getFile(file).then(function (result) {
|
||||
var file_data = EncryptService.decryptString(result.file_data);
|
||||
var uriContent = FileService.dataURItoBlob(file_data, file.mimetype), a = document.createElement("a");
|
||||
a.style = "display: none";
|
||||
a.href = uriContent;
|
||||
a.download = escapeHTML(file.filename);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(uriContent);
|
||||
});
|
||||
};
|
||||
|
||||
//@TODO TagService which holds all the tags
|
||||
//@TODO Show otp field
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Controller of the passmanApp
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService) {
|
||||
.controller('CredentialEditCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'FileService', 'EncryptService', 'TagService', function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, FileService, EncryptService, TagService) {
|
||||
$scope.active_vault = VaultService.getActiveVault();
|
||||
|
||||
|
||||
|
@ -70,6 +70,10 @@ angular.module('passmanApp')
|
|||
$scope.storedCredential.password_repeat = angular.copy($scope.storedCredential.password);
|
||||
}
|
||||
|
||||
$scope.getTags = function ($query) {
|
||||
console.log($query)
|
||||
return TagService.searchTag($query);
|
||||
};
|
||||
|
||||
$scope.currentTab = {
|
||||
title: 'General',
|
||||
|
|
22
js/app/directives/ngenter.js
Normal file
22
js/app/directives/ngenter.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name passmanApp.directive:passwordGen
|
||||
* @description
|
||||
* # passwordGen
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.directive('ngEnter', function () {
|
||||
return function (scope, element, attrs) {
|
||||
element.bind("keydown keypress", function (event) {
|
||||
if (event.which === 13) {
|
||||
scope.$apply(function () {
|
||||
scope.$eval(attrs.ngEnter);
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name passmanApp.VaultService
|
||||
* @name passmanApp.CacheService
|
||||
* @description
|
||||
* # VaultService
|
||||
* # CacheService
|
||||
* Service in the passmanApp.
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name passmanApp.VaultService
|
||||
* @name passmanApp.EncryptService
|
||||
* @description
|
||||
* # VaultService
|
||||
* # EncryptService
|
||||
* Service in the passmanApp.
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name passmanApp.CredentialService
|
||||
* @name passmanApp.FileService
|
||||
* @description
|
||||
* # CredentialService
|
||||
* # FileService
|
||||
* Service in the passmanApp.
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
|
@ -17,7 +17,7 @@ angular.module('passmanApp')
|
|||
var data = EncryptService.encryptString(angular.copy(file.data));
|
||||
_file.data = data;
|
||||
return $http.post(queryUrl, _file).then(function (response) {
|
||||
if(response.data){
|
||||
if (response.data) {
|
||||
return response.data;
|
||||
} else {
|
||||
return response;
|
||||
|
@ -25,15 +25,54 @@ angular.module('passmanApp')
|
|||
});
|
||||
},
|
||||
deleteFile: function (file) {
|
||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/'+ file.file_id);
|
||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/' + file.file_id);
|
||||
var _file = angular.copy(file);
|
||||
return $http.delete(queryUrl, _file).then(function (response) {
|
||||
if(response.data){
|
||||
if (response.data) {
|
||||
return response.data;
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
getFile: function (file) {
|
||||
var queryUrl = OC.generateUrl('apps/passman/api/v2/file/' + file.file_id);
|
||||
var _file = angular.copy(file);
|
||||
return $http.get(queryUrl, _file).then(function (response) {
|
||||
if (response.data) {
|
||||
if (Object.prototype.toString.call(response.data) === '[object Array]') {
|
||||
return response.data.pop()
|
||||
} else {
|
||||
return response.data;
|
||||
}
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
});
|
||||
},
|
||||
dataURItoBlob: function (dataURI, ftype) {
|
||||
var byteString, mimeString, ab, ia, bb, i;
|
||||
// convert base64 to raw binary data held in a string
|
||||
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
|
||||
byteString = atob(dataURI.split(',')[1]);
|
||||
|
||||
// separate out the mime component
|
||||
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||
|
||||
// write the bytes of the string to an ArrayBuffer
|
||||
ab = new ArrayBuffer(byteString.length);
|
||||
ia = new Uint8Array(ab);
|
||||
for (i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
|
||||
// write the ArrayBuffer to a blob, and you're done
|
||||
bb = new Blob([ab], {
|
||||
type: ftype
|
||||
});
|
||||
|
||||
return URL.createObjectURL(bb);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
var saveAs=saveAs||typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator)||function(view){"use strict";if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var doc=view.document,get_URL=function(){return view.URL||view.webkitURL||view},save_link=doc.createElementNS("http://www.w3.org/1999/xhtml","a"),can_use_save_link="download"in save_link,click=function(node){var event=doc.createEvent("MouseEvents");event.initMouseEvent("click",true,false,view,0,0,0,0,0,false,false,false,false,0,null);node.dispatchEvent(event)},webkit_req_fs=view.webkitRequestFileSystem,req_fs=view.requestFileSystem||webkit_req_fs||view.mozRequestFileSystem,throw_outside=function(ex){(view.setImmediate||view.setTimeout)(function(){throw ex},0)},force_saveable_type="application/octet-stream",fs_min_size=0,arbitrary_revoke_timeout=500,revoke=function(file){var revoker=function(){if(typeof file==="string"){get_URL().revokeObjectURL(file)}else{file.remove()}};if(view.chrome){revoker()}else{setTimeout(revoker,arbitrary_revoke_timeout)}},dispatch=function(filesaver,event_types,event){event_types=[].concat(event_types);var i=event_types.length;while(i--){var listener=filesaver["on"+event_types[i]];if(typeof listener==="function"){try{listener.call(filesaver,event||filesaver)}catch(ex){throw_outside(ex)}}}},FileSaver=function(blob,name){var filesaver=this,type=blob.type,blob_changed=false,object_url,target_view,dispatch_all=function(){dispatch(filesaver,"writestart progress write writeend".split(" "))},fs_error=function(){if(blob_changed||!object_url){object_url=get_URL().createObjectURL(blob)}if(target_view){target_view.location.href=object_url}else{var new_tab=view.open(object_url,"_blank");if(new_tab==undefined&&typeof safari!=="undefined"){view.location.href=object_url}}filesaver.readyState=filesaver.DONE;dispatch_all();revoke(object_url)},abortable=function(func){return function(){if(filesaver.readyState!==filesaver.DONE){return func.apply(this,arguments)}}},create_if_not_found={create:true,exclusive:false},slice;filesaver.readyState=filesaver.INIT;if(!name){name="download"}if(can_use_save_link){object_url=get_URL().createObjectURL(blob);save_link.href=object_url;save_link.download=name;click(save_link);filesaver.readyState=filesaver.DONE;dispatch_all();revoke(object_url);return}if(view.chrome&&type&&type!==force_saveable_type){slice=blob.slice||blob.webkitSlice;blob=slice.call(blob,0,blob.size,force_saveable_type);blob_changed=true}if(webkit_req_fs&&name!=="download"){name+=".download"}if(type===force_saveable_type||webkit_req_fs){target_view=view}if(!req_fs){fs_error();return}fs_min_size+=blob.size;req_fs(view.TEMPORARY,fs_min_size,abortable(function(fs){fs.root.getDirectory("saved",create_if_not_found,abortable(function(dir){var save=function(){dir.getFile(name,create_if_not_found,abortable(function(file){file.createWriter(abortable(function(writer){writer.onwriteend=function(event){target_view.location.href=file.toURL();filesaver.readyState=filesaver.DONE;dispatch(filesaver,"writeend",event);revoke(file)};writer.onerror=function(){var error=writer.error;if(error.code!==error.ABORT_ERR){fs_error()}};"writestart progress write abort".split(" ").forEach(function(event){writer["on"+event]=filesaver["on"+event]});writer.write(blob);filesaver.abort=function(){writer.abort();filesaver.readyState=filesaver.DONE};filesaver.readyState=filesaver.WRITING}),fs_error)}),fs_error)};dir.getFile(name,{create:false},abortable(function(file){file.remove();save()}),abortable(function(ex){if(ex.code===ex.NOT_FOUND_ERR){save()}else{fs_error()}}))}),fs_error)}),fs_error)},FS_proto=FileSaver.prototype,saveAs=function(blob,name){return new FileSaver(blob,name)};FS_proto.abort=function(){var filesaver=this;filesaver.readyState=filesaver.DONE;dispatch(filesaver,"abort")};FS_proto.readyState=FS_proto.INIT=0;FS_proto.WRITING=1;FS_proto.DONE=2;FS_proto.error=FS_proto.onwritestart=FS_proto.onprogress=FS_proto.onwrite=FS_proto.onabort=FS_proto.onerror=FS_proto.onwriteend=null;return saveAs}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!=null){define([],function(){return saveAs})}
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name passmanApp.VaultService
|
||||
* @name passmanApp.SettingsService
|
||||
* @description
|
||||
* # VaultService
|
||||
* # SettingsService
|
||||
* Service in the passmanApp.
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
|
|
32
js/app/services/tagservice.js
Normal file
32
js/app/services/tagservice.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name passmanApp.TagService
|
||||
* @description
|
||||
* # TagService
|
||||
* Service in the passmanApp.
|
||||
*/
|
||||
angular.module('passmanApp')
|
||||
.service('TagService', ['$filter', function ($filter) {
|
||||
var tags = [
|
||||
{text: 'test'},
|
||||
{text: 'test 1'},
|
||||
{text: 'example'},
|
||||
];
|
||||
return {
|
||||
getTags: function () {
|
||||
return tags;
|
||||
},
|
||||
searchTag: function(string){
|
||||
console.log(string)
|
||||
return $filter('filter')(tags,{text: string });
|
||||
},
|
||||
addTags: function (tags) {
|
||||
|
||||
},
|
||||
removeTag: function (tag) {
|
||||
|
||||
}
|
||||
}
|
||||
}]);
|
|
@ -11,7 +11,7 @@ angular.module('views/edit_credential.html', []).run(['$templateCache', function
|
|||
angular.module('views/partials/forms/edit_credential/basics.html', []).run(['$templateCache', function($templateCache) {
|
||||
'use strict';
|
||||
$templateCache.put('views/partials/forms/edit_credential/basics.html',
|
||||
'<div class="row"><div class="col-xs-12 col-md-6"><label>Label</label><div><input type="text" ng-model="storedCredential.label"></div><label>Usermame</label><div><input type="text" ng-model="storedCredential.username"></div><label>E-mail</label><div><input type="text" ng-model="storedCredential.email"></div><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><div><label>Repeat password</label><input type="password" ng-model="storedCredential.password_repeat"></div><label>URL</label><div><input type="text" ng-model="storedCredential.url"></div></div><div class="col-xs-12 col-md-6"><label>Description</label><div><textarea class="credential_textarea" ng-model="storedCredential.description"></textarea></div><label>Add Tag</label><div><input type="text" placeholder="Add a tag"></div><label>Tags</label><div><div class="tags"><div class="tag">test</div></div></div></div></div>');
|
||||
'<div class="row"><div class="col-xs-12 col-md-6"><label>Label</label><div><input type="text" ng-model="storedCredential.label"></div><label>Usermame</label><div><input type="text" ng-model="storedCredential.username"></div><label>E-mail</label><div><input type="text" ng-model="storedCredential.email"></div><label>Password</label><div><password-gen ng-model="storedCredential.password" settings="pwSettings" callback="pwGenerated"></password-gen><ng-password-meter password="storedCredential.password"></ng-password-meter></div><div><label>Repeat password</label><input type="password" ng-model="storedCredential.password_repeat"></div><label>URL</label><div><input type="text" ng-model="storedCredential.url"></div></div><div class="col-xs-12 col-md-6"><label>Description</label><div><textarea class="credential_textarea" ng-model="storedCredential.description"></textarea></div><label>Add Tag</label><div class="tags_input"><tags-input ng-model="storedCredential.tags" replace-spaces-with-dashes="false"><auto-complete source="getTags($query)" min-length="0"></auto-complete></tags-input></div></div></div>');
|
||||
}]);
|
||||
|
||||
angular.module('views/partials/forms/edit_credential/custom_fields.html', []).run(['$templateCache', function($templateCache) {
|
||||
|
@ -47,7 +47,7 @@ angular.module('views/partials/password-meter.html', []).run(['$templateCache',
|
|||
angular.module('views/show_vault.html', []).run(['$templateCache', function($templateCache) {
|
||||
'use strict';
|
||||
$templateCache.put('views/show_vault.html',
|
||||
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div></div></div><div off-click="closeSelected()"><table class="credential-table" ng-init="menuOpen = false;"><tr ng-repeat="credential in credentials" ng-if="credential.hidden == 0 && credential.delete_time == 0" ng-click="selectCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="label">{{credential.label}}</span> <span class="tags"><span class="tag">Tag 1</span> <span class="tag">Tag 2</span> <span class="tag">Tag 4</span> <span class="tag">Tag 4</span> <span class="tag">Long tag xD</span></span></td></tr></table><div id="app-sidebar" class="detailsView scroll-container app_sidebar" ng-show="selectedCredential"><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><table><tr ng-show="selectedCredential.label"><td>Label</td><td>{{selectedCredential.label}}</td></tr><tr ng-show="selectedCredential.username"><td>Account</td><td><span credential-field value="selectedCredential.username"></span></td></tr><tr ng-show="selectedCredential.password"><td>Password</td><td><span credential-field value="selectedCredential.password" secret="\'true\'"></span></td></tr><tr ng-show="selectedCredential.email"><td>E-mail</td><td><span credential-field value="selectedCredential.email"></span></td></tr><tr ng-show="selectedCredential.url"><td>URL</td><td><span credential-field value="selectedCredential.url"></span></td></tr><tr ng-show="selectedCredential.files.length > 0"><td>Files</td><td><div ng-repeat="file in selectedCredential.files" class="link">{{file.filename}} ({{file.size | bytes}})</div></td></tr><tr ng-repeat="field in selectedCredential.custom_fields"><td>{{field.label}}</td><td><span credential-field value="field.value" secret="field.secret"></span></td></tr><tr ng-show="selectedCredential.changed"><td>Changed</td><td>{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr><tr ng-show="selectedCredential.created"><td>Created</td><td>{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr></table><div ng-show="selectedCredential"><span class="button" ng-click="editCredential(selectedCredential)"><span class="fa fa-edit"></span> Edit</span> <span class="button"><span class="fa fa-trash"></span> Delete</span> <span class="button"><span class="fa fa-share"></span> Share</span></div></div></div>');
|
||||
'<div id="controls"><div class="breadcrumb"></div><div class="actions creatable"><span ng-click="menuOpen = !menuOpen" class="button new" ng-init="menuOpen = false" off-click="menuOpen = false;"><span>New</span></span><div class="actionList popovermenu bubble menu" ng-show="menuOpen"><ul><li><span ng-click="addCredential()" class="menuitem action"><span class="icon icon-rename"></span> <span>New credential</span></span></li><li><span href="#" class="menuitem action"><span class="icon icon-shared"></span> <span>New shared credential</span></span></li></ul></div></div></div><div off-click="closeSelected()"><table class="credential-table" ng-init="menuOpen = false;"><tr ng-repeat="credential in credentials" ng-if="credential.hidden == 0 && credential.delete_time == 0" ng-click="selectCredential(credential)" ng-class="{\'selected\': selectedCredential.credential_id == credential.credential_id}"><td><span class="label">{{credential.label}}</span> <span class="tags"><span class="tag">Tag 1</span> <span class="tag">Tag 2</span> <span class="tag">Tag 4</span> <span class="tag">Tag 4</span> <span class="tag">Long tag xD</span></span></td></tr></table><div id="app-sidebar" class="detailsView scroll-container app_sidebar" ng-show="selectedCredential"><span class="close icon-close" ng-click="closeSelected()" alt="Close"></span><table><tr ng-show="selectedCredential.label"><td>Label</td><td>{{selectedCredential.label}}</td></tr><tr ng-show="selectedCredential.username"><td>Account</td><td><span credential-field value="selectedCredential.username"></span></td></tr><tr ng-show="selectedCredential.password"><td>Password</td><td><span credential-field value="selectedCredential.password" secret="\'true\'"></span></td></tr><tr ng-show="selectedCredential.email"><td>E-mail</td><td><span credential-field value="selectedCredential.email"></span></td></tr><tr ng-show="selectedCredential.url"><td>URL</td><td><span credential-field value="selectedCredential.url"></span></td></tr><tr ng-show="selectedCredential.files.length > 0"><td>Files</td><td><div ng-repeat="file in selectedCredential.files" class="link" ng-click="downloadFile(file)">{{file.filename}} ({{file.size | bytes}})</div></td></tr><tr ng-repeat="field in selectedCredential.custom_fields"><td>{{field.label}}</td><td><span credential-field value="field.value" secret="field.secret"></span></td></tr><tr ng-show="selectedCredential.changed"><td>Changed</td><td>{{selectedCredential.changed * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr><tr ng-show="selectedCredential.created"><td>Created</td><td>{{selectedCredential.created * 1000 | date:\'dd-MM-yyyy @ HH:mm:ss\'}}</td></tr></table><div ng-show="selectedCredential"><span class="button" ng-click="editCredential(selectedCredential)"><span class="fa fa-edit"></span> Edit</span> <span class="button"><span class="fa fa-trash"></span> Delete</span> <span class="button"><span class="fa fa-share"></span> Share</span></div></div></div>');
|
||||
}]);
|
||||
|
||||
angular.module('views/vaults.html', []).run(['$templateCache', function($templateCache) {
|
||||
|
|
1
js/vendor/ng-tags-input/ng-tags-input.min.js
vendored
Normal file
1
js/vendor/ng-tags-input/ng-tags-input.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -26,10 +26,10 @@ class FileMapper extends Mapper {
|
|||
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result
|
||||
*/
|
||||
public function getFile($itemId, $fileId) {
|
||||
public function getFile($file_id, $user_id) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*passman_files` ' .
|
||||
'WHERE `id` = ? and `item_id` = ? ';
|
||||
return $this->findEntities($sql, [$fileId, $itemId]);
|
||||
'WHERE `id` = ? and `user_id` = ? ';
|
||||
return $this->findEntities($sql, [$file_id, $user_id]);
|
||||
}
|
||||
|
||||
public function create($file_raw, $userId){
|
||||
|
|
|
@ -106,6 +106,13 @@
|
|||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
tags-input {
|
||||
.tags {
|
||||
width: 100%;
|
||||
.input {
|
||||
}
|
||||
}
|
||||
}
|
||||
.credential_textarea {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
|
@ -137,7 +144,7 @@
|
|||
width: 15%;
|
||||
}
|
||||
}
|
||||
tr:hover{
|
||||
tr:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
tr {
|
||||
|
@ -189,7 +196,7 @@
|
|||
table {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
tr:hover{
|
||||
tr:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
tr {
|
||||
|
@ -219,7 +226,7 @@
|
|||
margin-left: 10px;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
.cell{
|
||||
.cell {
|
||||
cursor: pointer;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
.settings-container{
|
||||
div{
|
||||
padding-left: 15px;
|
||||
.link{
|
||||
color: rgb(0, 102, 255) !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.link:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -14,4 +14,11 @@
|
|||
.button-red:hover{
|
||||
background: lighten(#ce3702, 2%);
|
||||
color: #fff;
|
||||
}
|
||||
.link{
|
||||
color: rgb(0, 102, 255) !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.link:hover{
|
||||
text-decoration: underline;
|
||||
}
|
|
@ -16,6 +16,7 @@ script('passman', 'vendor/sjcl/sjcl');
|
|||
script('passman', 'vendor/zxcvbn/zxcvbn');
|
||||
script('passman', 'vendor/ng-clipboard/clipboard.min');
|
||||
script('passman', 'vendor/ng-clipboard/ngclipboard');
|
||||
script('passman', 'vendor/ng-tags-input/ng-tags-input.min');
|
||||
script('passman', 'vendor/angular-xeditable/xeditable.min');
|
||||
script('passman', 'vendor/sha/sha');
|
||||
script('passman', 'vendor/llqrcode/llqrcode');
|
||||
|
@ -37,6 +38,7 @@ script('passman', 'app/services/credentialservice');
|
|||
script('passman', 'app/services/settingsservice');
|
||||
script('passman', 'app/services/fileservice');
|
||||
script('passman', 'app/services/encryptservice');
|
||||
script('passman', 'app/services/tagservice');
|
||||
script('passman', 'app/directives/passwordgen');
|
||||
script('passman', 'app/directives/fileselect');
|
||||
script('passman', 'app/directives/progressbar');
|
||||
|
@ -45,17 +47,19 @@ script('passman', 'app/directives/qrreader');
|
|||
script('passman', 'app/directives/tooltip');
|
||||
script('passman', 'app/directives/use-theme');
|
||||
script('passman', 'app/directives/credentialfield');
|
||||
script('passman', 'app/directives/ngenter');
|
||||
|
||||
|
||||
/*
|
||||
* Styles
|
||||
*/
|
||||
style('passman', 'app');
|
||||
style('passman', 'vendor/ng-password-meter/ng-password-meter');
|
||||
style('passman', 'vendor/bootstrap/bootstrap.min');
|
||||
style('passman', 'vendor/bootstrap/bootstrap-theme.min');
|
||||
style('passman', 'vendor/font-awesome/font-awesome.min');
|
||||
style('passman', 'vendor/angular-xeditable/xeditable.min');
|
||||
style('passman', 'vendor/ng-tags-input/ng-tags-input.min');
|
||||
style('passman', 'app');
|
||||
?>
|
||||
|
||||
<div id="app" ng-app="passmanApp" ng-controller="MainCtrl">
|
||||
|
|
|
@ -33,17 +33,10 @@
|
|||
<textarea class="credential_textarea" ng-model="storedCredential.description"></textarea>
|
||||
</div>
|
||||
<label>Add Tag</label>
|
||||
<div>
|
||||
<input type="text" placeholder="Add a tag">
|
||||
<div class="tags_input">
|
||||
<tags-input ng-model="storedCredential.tags" replace-spaces-with-dashes="false">
|
||||
<auto-complete source="getTags($query)" min-length="0"></auto-complete>
|
||||
</tags-input>
|
||||
</div>
|
||||
<label>Tags</label>
|
||||
<div>
|
||||
<div class="tags">
|
||||
<div class="tag">
|
||||
test
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<div ng-repeat="file in selectedCredential.files"
|
||||
class="link">
|
||||
class="link" ng-click="downloadFile(file)">
|
||||
{{file.filename}} ({{file.size | bytes}})
|
||||
</div>
|
||||
</td>
|
||||
|
|
Loading…
Add table
Reference in a new issue