Browse Source

Add custom fields

brantje 2 years ago
parent
commit
f5e5f04c4a
No account linked to committer's email address

+ 12
- 0
_locales/en/messages.json View File

@@ -283,6 +283,18 @@
283 283
     "message": "Done",
284 284
     "description": "Done"
285 285
   },
286
+  "custom_fields": {
287
+    "message": "Custom Fields",
288
+    "description": "Custom fields"
289
+  },
290
+  "general": {
291
+    "message": "General",
292
+    "description": "Custom fields"
293
+  },
294
+  "value": {
295
+    "message": "Value",
296
+    "description": "Custom fields"
297
+  },
286 298
   "list": {
287 299
     "message": "List",
288 300
     "description": "List"

+ 105
- 8
css/browser_action.css View File

@@ -78,7 +78,8 @@ input:focus, select.input-md:focus {
78 78
 
79 79
 select.input-md {
80 80
   background-color: #fff;
81
-  cursor: pointer; }
81
+  cursor: pointer;
82
+  margin-top: -3px; }
82 83
 
83 84
 /* LABEL ======================================= */
84 85
 .group label {
@@ -101,6 +102,14 @@ select.ng-valid:not(.ng-empty) ~ label {
101 102
   font-size: 14px;
102 103
   color: #1565c0; }
103 104
 
105
+.col33 {
106
+  width: 29%;
107
+  float: left; }
108
+  .col33:first-child {
109
+    padding-right: 10px; }
110
+  .col33:not(:first-child) {
111
+    padding-left: 10px; }
112
+
104 113
 /* BOTTOM BARS ================================= */
105 114
 .bar {
106 115
   position: relative;
@@ -138,7 +147,7 @@ input:focus ~ .bar:before, input:focus ~ .bar:after {
138 147
   pointer-events: none;
139 148
   opacity: 0.5; }
140 149
 
141
-.group .mdi-content-copy, .pwField .mdi {
150
+.group .mdi-content-copy, .pwField .mdi, .group .mdi-delete {
142 151
   /*position: absolute;
143 152
   right: 0;*/
144 153
   margin-top: 5px;
@@ -157,7 +166,7 @@ input:focus ~ .bar:before, input:focus ~ .bar:after {
157 166
   border-bottom-right-radius: 16px;
158 167
   border-bottom-left-radius: 16px;
159 168
   border-top-left-radius: 16px; }
160
-  .group .mdi-content-copy:hover, .pwField .mdi:hover {
169
+  .group .mdi-content-copy:hover, .pwField .mdi:hover, .group .mdi-delete:hover {
161 170
     text-decoration: none;
162 171
     background-color: #e4e4e4; }
163 172
 
@@ -167,9 +176,15 @@ input:focus ~ .bar:before, input:focus ~ .bar:after {
167 176
 .mdi-content-copy ~ input {
168 177
   width: calc(100% - 32px); }
169 178
 
179
+.mdi-delete ~ input {
180
+  width: calc(100% - 32px); }
181
+
170 182
 .mdi-content-copy ~ .bar {
171 183
   width: calc(100% - 32px); }
172 184
 
185
+.mdi-delete ~ .bar {
186
+  width: calc(100% - 32px); }
187
+
173 188
 /* active state */
174 189
 input:focus ~ .highlight, select.input-md ~ .highlight {
175 190
   -webkit-animation: inputHighlighter 0.3s ease;
@@ -431,6 +446,75 @@ input:focus ~ .highlight, select.input-md ~ .highlight {
431 446
 .md-btn.red:hover, .btn.red:focus {
432 447
   background-color: #f4511e; }
433 448
 
449
+.tab-wrap {
450
+  width: 100%;
451
+  height: 600px;
452
+  /*position: absolute;*/ }
453
+  .tab-wrap label:not(.ng-binding) {
454
+    cursor: pointer;
455
+    color: rgba(0, 0, 0, 0.8);
456
+    background-color: #fff;
457
+    box-sizing: border-box;
458
+    display: inline-flex !important;
459
+    align-items: center;
460
+    justify-content: center;
461
+    text-align: center;
462
+    height: 56px;
463
+    transition: color 0.2s ease;
464
+    width: 100%;
465
+    border-bottom: 1px solid #c9c9c9; }
466
+  .tab-wrap .slide {
467
+    background: #1565c0;
468
+    width: calc(100% / 2);
469
+    height: 4px;
470
+    position: relative;
471
+    left: 0;
472
+    top: 52px;
473
+    transition: left 0.3s ease-out; }
474
+  .tab-wrap .tab-label-content {
475
+    width: calc(100% / 2);
476
+    float: left; }
477
+    .tab-wrap .tab-label-content .tab-content {
478
+      position: absolute;
479
+      top: 100px;
480
+      left: 16px;
481
+      line-height: 130%;
482
+      display: none;
483
+      width: 100%;
484
+      padding-right: 20px; }
485
+      .tab-wrap .tab-label-content .tab-content .custom_field {
486
+        float: left;
487
+        margin-bottom: 15px; }
488
+        .tab-wrap .tab-label-content .tab-content .custom_field .field {
489
+          float: left;
490
+          width: 50%; }
491
+          .tab-wrap .tab-label-content .tab-content .custom_field .field:first-child {
492
+            padding-right: 10px; }
493
+          .tab-wrap .tab-label-content .tab-content .custom_field .field:not(:first-child) {
494
+            padding-left: 10px; }
495
+  @media screen and (max-width: 800px) {
496
+    .tab-wrap h1 {
497
+      padding: 40px 0 90px 10%; }
498
+    .tab-wrap .tab-wrap {
499
+      width: 80%;
500
+      margin-left: 10%;
501
+      top: -106px; } }
502
+
503
+input[type="radio"][name="tabs"] {
504
+  position: absolute;
505
+  z-index: -1; }
506
+  input[type="radio"][name="tabs"]:checked + .tab-label-content label:not(.ng-binding) {
507
+    color: rgba(0, 0, 0, 0.8); }
508
+  input[type="radio"][name="tabs"]:checked + .tab-label-content .tab-content {
509
+    display: block;
510
+    margin-top: 40px; }
511
+  input[type="radio"][name="tabs"]:nth-of-type(1):checked ~ .slide {
512
+    left: calc((100% / 2) * 0); }
513
+  input[type="radio"][name="tabs"]:nth-of-type(2):checked ~ .slide {
514
+    left: calc((100% / 2) * 1); }
515
+  input[type="radio"][name="tabs"]:first-of-type:checked ~ .slide {
516
+    left: 0; }
517
+
434 518
 body {
435 519
   width: 450px;
436 520
   min-height: 350px;
@@ -485,7 +569,7 @@ body.toggled {
485 569
   overflow-y: auto; }
486 570
 
487 571
 #wrapper.toggled #page-content-wrapper {
488
-  position: absolute;
572
+  /*position: absolute;*/
489 573
   margin-right: -250px;
490 574
   /*  width: calc(100% - 250px);*/ }
491 575
 
@@ -499,7 +583,8 @@ body.toggled {
499 583
   width: 250px;
500 584
   margin: 0;
501 585
   padding: 0;
502
-  list-style: none; }
586
+  list-style: none;
587
+  height: 100%; }
503 588
   .sidebar-nav li {
504 589
     line-height: 55px; }
505 590
     .sidebar-nav li a {
@@ -517,17 +602,28 @@ body.toggled {
517 602
         background-color: #e4e4e4; }
518 603
       .sidebar-nav li a:active, .sidebar-nav li a:focus {
519 604
         text-decoration: none; }
605
+    .sidebar-nav li.bottom {
606
+      position: absolute;
607
+      bottom: 0;
608
+      font-size: 12px;
609
+      text-align: center;
610
+      width: 100%;
611
+      margin-bottom: 15px;
612
+      line-height: 0; }
520 613
   .sidebar-nav > .sidebar-brand {
521 614
     height: 50px;
522 615
     font-size: 18px;
523 616
     line-height: 50px;
524
-    text-indent: 20px;
617
+    text-align: center;
525 618
     background-color: #1565c0;
526 619
     border-right: 1px solid #104d92; }
527 620
     .sidebar-nav > .sidebar-brand span {
528 621
       display: block;
529 622
       text-decoration: none;
530 623
       color: #fff; }
624
+      .sidebar-nav > .sidebar-brand span img {
625
+        height: 32px;
626
+        margin-right: 10px; }
531 627
       .sidebar-nav > .sidebar-brand span:hover {
532 628
         color: #fff;
533 629
         background: none; }
@@ -542,9 +638,10 @@ body.toggled {
542 638
   position: absolute;
543 639
   background-color: transparent;
544 640
   width: calc(100% - 250px);
545
-  height: 350px;
641
+  height: 100%;
546 642
   z-index: 9999999;
547
-  right: 0; }
643
+  right: 0;
644
+  top: 0; }
548 645
 
549 646
 .edit_credential {
550 647
   padding-top: 30px;

+ 2
- 1
html/browser_action/browser_action.html View File

@@ -63,7 +63,7 @@
63 63
             <ul class="sidebar-nav">
64 64
                 <li class="sidebar-brand">
65 65
                     <span>
66
-                        Passman
66
+                        <img src="/icons/icon_white.svg" /> Passman
67 67
                         <i class="mdi mdi-close" ng-click="toggleMenu()"></i>
68 68
                     </span>
69 69
                 </li>
@@ -81,6 +81,7 @@
81 81
                        title="{{'donate_button_title' | translate}}"
82 82
                        rel="nofollow noopener noreferrer"><i class="mdi mdi-credit-card"></i> Donate</a>
83 83
                 </li>
84
+                <li class="bottom">{{'credentials_in_db' | translate:credential_amount}}</li>
84 85
             </ul>
85 86
         </div>
86 87
         <!-- /#sidebar-wrapper -->

+ 135
- 63
html/browser_action/views/edit_credential.html View File

@@ -1,48 +1,139 @@
1
-<div class="edit_credential">
2
-    <div class="group">
3
-        <copy-text text="credential.label"></copy-text>
4
-        <input type="text" ng-model="credential.label" required>
5
-        <span class="highlight"></span>
6
-        <span class="bar"></span>
7
-        <label>{{'label' | translate}}</label>
8
-    </div>
9
-    <div class="group">
10
-        <copy-text text="credential.username"></copy-text>
11
-        <input type="text" ng-model="credential.username">
12
-        <span class="highlight"></span>
13
-        <span class="bar"></span>
14
-        <label>{{'username' | translate}}</label>
15
-    </div>
16
-    <div class="group">
17
-        <copy-text text="credential.email"></copy-text>
18
-        <input type="text" ng-model="credential.email">
19
-        <span class="highlight"></span>
20
-        <span class="bar"></span>
21
-        <label>{{ 'email' | translate}}</label>
22
-    </div>
23
-    <div class="group pwField">
24
-        <copy-text text="credential.password"></copy-text>
25
-        <i class="mdi mdi-refresh pointer"  ng-click="generatePassword()"></i>
26
-        <i class="pointer mdi" ng-class="{'mdi-eye': !pwFieldShown, 'mdi-eye-off': pwFieldShown}" ng-click="togglePwField()"></i>
27
-        <input type="text" ng-model="credential.password" ng-if="pwFieldShown">
28
-        <input type="password" ng-model="credential.password" ng-if="!pwFieldShown">
29
-        <span class="highlight"></span>
30
-        <span class="bar"></span>
31
-        <label>{{'password' | translate}}</label>
32
-    </div>
33
-    <div class="group">
34
-        <input type="password" ng-model="credential.password_repeat">
35
-        <span class="highlight"></span>
36
-        <span class="bar"></span>
37
-        <label>{{'password_repeat' | translate}}</label>
1
+<div class="tab-wrap">
2
+
3
+    <input type="radio" name="tabs" id="tab1" checked>
4
+    <div class="tab-label-content" id="tab1-content">
5
+        <label for="tab1">General</label>
6
+        <div class="tab-content">
7
+            <div class="group">
8
+                <copy-text text="credential.label"></copy-text>
9
+                <input type="text" ng-model="credential.label" required>
10
+                <span class="highlight"></span>
11
+                <span class="bar"></span>
12
+                <label>{{'label' | translate}}</label>
13
+            </div>
14
+            <div class="group">
15
+                <copy-text text="credential.username"></copy-text>
16
+                <input type="text" ng-model="credential.username">
17
+                <span class="highlight"></span>
18
+                <span class="bar"></span>
19
+                <label>{{'username' | translate}}</label>
20
+            </div>
21
+            <div class="group">
22
+                <copy-text text="credential.email"></copy-text>
23
+                <input type="text" ng-model="credential.email">
24
+                <span class="highlight"></span>
25
+                <span class="bar"></span>
26
+                <label>{{ 'email' | translate}}</label>
27
+            </div>
28
+            <div class="group pwField">
29
+                <copy-text text="credential.password"></copy-text>
30
+                <i class="mdi mdi-refresh pointer" ng-click="generatePassword()"></i>
31
+                <i class="pointer mdi" ng-class="{'mdi-eye': !pwFieldShown, 'mdi-eye-off': pwFieldShown}"
32
+                   ng-click="togglePwField()"></i>
33
+                <input type="text" ng-model="credential.password" ng-if="pwFieldShown">
34
+                <input type="password" ng-model="credential.password" ng-if="!pwFieldShown">
35
+                <span class="highlight"></span>
36
+                <span class="bar"></span>
37
+                <label>{{'password' | translate}}</label>
38
+            </div>
39
+            <div class="group">
40
+                <input type="password" ng-model="credential.password_repeat">
41
+                <span class="highlight"></span>
42
+                <span class="bar"></span>
43
+                <label>{{'password_repeat' | translate}}</label>
44
+            </div>
45
+            <div class="group">
46
+                <copy-text text="credential.url"></copy-text>
47
+                <input type="text" ng-model="credential.url">
48
+                <span class="highlight"></span>
49
+                <span class="bar"></span>
50
+                <label>{{'url' | translate}}</label>
51
+            </div>
52
+            <div  style="margin-left: -15px;" ng-include="'save_btn.html'"></div>
53
+        </div>
38 54
     </div>
39
-    <div class="group">
40
-        <copy-text text="credential.url"></copy-text>
41
-        <input type="text" ng-model="credential.url">
42
-        <span class="highlight"></span>
43
-        <span class="bar"></span>
44
-        <label>{{'url' | translate}}</label>
55
+
56
+    <input type="radio" name="tabs" id="tab2">
57
+    <div class="tab-label-content" id="tab2-content">
58
+        <label for="tab2">Custom fields</label>
59
+        <div class="tab-content">
60
+            <div class="custom_field" ng-repeat="custom_field in credential.custom_fields" ng-if="custom_field.field_type !== 'file'">
61
+                <div class="field">
62
+                    <div class="group">
63
+                        <input type="text" ng-model="custom_field.label">
64
+                        <span class="highlight"></span>
65
+                        <span class="bar"></span>
66
+                    </div>
67
+                </div>
68
+                <div class="field">
69
+                    <div class="group">
70
+                        <i class="mdi mdi-delete"></i>
71
+                        <input type="password" ng-model="custom_field.value" ng-if="custom_field.field_type === 'password'">
72
+                        <input type="text" ng-model="custom_field.value" ng-if="custom_field.field_type === 'text'">
73
+                        <span class="highlight"></span>
74
+                        <span class="bar"></span>
75
+                    </div>
76
+                </div>
77
+            </div>
78
+            <h4 style="margin-left: 5px; margin-bottom: 30px;">Add custom field</h4>
79
+            <div class="col33" style="padding-left: 0">
80
+                <div class="group">
81
+                    <input type="text" ng-model="new_custom_field.label" placeholder="Label">
82
+                    <span class="highlight"></span>
83
+                    <span class="bar"></span>
84
+                    <label>{{'label' | translate}}</label>
85
+                </div>
86
+            </div>
87
+            <div class="col33">
88
+                <div class="group">
89
+                    <input type="password" ng-model="new_custom_field.value" ng-if="new_custom_field.field_type === 'password'">
90
+                    <input type="text" ng-model="new_custom_field.value" ng-if="new_custom_field.field_type === 'text'" placeholder="Value">
91
+                    <span class="highlight"></span>
92
+                    <span class="bar"></span>
93
+                    <label>{{'value' | translate}}</label>
94
+                </div>
95
+            </div>
96
+            <div class="col33">
97
+                <div class="group">
98
+                <select class="input-md" name="type" ng-model="new_custom_field.field_type">
99
+                    <option value="text">Text</option>
100
+                    <option value="password">Password</option>
101
+                </select>
102
+                    <span class="highlight"></span>
103
+                    <span class="bar"></span>
104
+
105
+                </div>
106
+            </div>
107
+
108
+            <span><i class="mdi mdi-plus" style="font-size: 30px; padding-top: 10px; display: inline-block; float: left; padding-left: 25px;" ng-click="addCustomField(new_custom_field)"></i></span>
109
+
110
+            <div class="clearfix" style="margin-bottom: 30px;"></div>
111
+            <div style="margin-left: -15px;" ng-include="'save_btn.html'"></div>
112
+        </div>
45 113
     </div>
114
+
115
+
116
+    <div class="slide"></div>
117
+
118
+</div>
119
+<div class="clearfix"></div>
120
+
121
+<script type="text/ng-template" id="save_btn.html">
122
+    <button class="md-btn default" ng-click="saveCredential()" ng-disabled="saving">
123
+        <span>
124
+            <i ng-show="saving"
125
+               ng-class="{'fa-spinner fa-spin': saving}"
126
+               class="fa"></i>
127
+            {{'save' | translate}}
128
+        </span>
129
+    </button>
130
+    <button class="md-btn" ng-click="cancel()">
131
+        <span>{{'cancel' | translate}}</span>
132
+    </button>
133
+</script>
134
+<!--
135
+<div class="edit_credential">
136
+
46 137
     <button class="md-btn default" ng-click="saveCredential()" ng-disabled="saving">
47 138
         <span>{{'save' | translate}}</span>
48 139
     </button>
@@ -107,26 +198,7 @@
107 198
         </td>
108 199
     </tr>
109 200
 </table>
110
-<h4>Add custom field</h4>
111
-<div class="col-xs-3 pad5">
112
-    <input class="form-control" type="text" ng-model="new_custom_field.label" placeholder="Label">
113
-</div>
114
-<div class="col-xs-3 pad5">
115
-    <input class="form-control" type="password" ng-model="new_custom_field.value" ng-if="new_custom_field.field_type === 'password'">
116
-    <input class="form-control" type="text" ng-model="new_custom_field.value" ng-if="new_custom_field.field_type === 'text'" placeholder="Value">
117
-</div>
118
-<div class="col-xs-3 pad5">
119
-    <select class="form-control" name="type" ng-model="new_custom_field.field_type">
120
-        <option value="text">Text</option>
121
-        <option value="password">Password</option>
122
-    </select>
123
-</div>
124
-<div class="col-xs-3 pad5">
125
-    <button class="btn btn-default" ng-click="addCustomField(new_custom_field)">
126
-        <i class="fa fa-plus"></i>
127
-    </button>
128
-</div>
129
-<div class="clearfix"></div>
201
+
130 202
 
131 203
 <button class="btn btn-success" ng-click="saveCredential()" ng-disabled="saving">{{'save' |
132 204
     translate}}

+ 10
- 0
html/browser_action/views/settings.html View File

@@ -34,6 +34,13 @@
34 34
         <span class="bar"></span>
35 35
         <label>{{'vault_password' | translate}}</label>
36 36
     </div>
37
+    <div class="group">
38
+        <input type="text" ng-model="settings.refreshTime"
39
+               required ng-debounce="1000">
40
+        <span class="highlight"></span>
41
+        <span class="bar"></span>
42
+        <label>{{'refresh_timer' | translate}}</label>
43
+    </div>
37 44
     <div class="ignored_sites">
38 45
         <label>{{'ignored_sites' | translate}}</label>
39 46
         <ul class="ignored_sites">
@@ -88,6 +95,9 @@
88 95
     <button class="md-btn" ng-click="cancel()">
89 96
         <span>{{'cancel' | translate}}</span>
90 97
     </button>
98
+    <div class="version">
99
+        {{extension}}
100
+    </div>
91 101
     <!--
92 102
     <h4 align="center">{{'please_enter_nextcloud_credentials' | translate}}:</h4>
93 103
     <div class="alerts alert alert-warning" ng-if="errors.length > 0">

+ 12
- 0
icons/icon_white.svg View File

@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
3
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+	 viewBox="0 0 68 68" enable-background="new 0 0 68 68" xml:space="preserve">
6
+<g>
7
+	<path fill="#FFFFFF" d="M0,34c0,21.9,30,34,34,34c4,0,34-12.1,34-34V0H0V34z M45.4,50.3H22.6v-6.5h22.8V50.3z M21.6,16.2
8
+		c0,0,6.5,2.4,9.2,4.1c-0.6-2.6-1.2-10-1.2-10h8.6c0,0-0.6,7.8-1.2,10c1.2-0.6,9.4-4.1,9.4-4.1l2.7,8.3c0,0-7.5,1.8-10.1,1.9
9
+		c1.8,1.4,6.7,7.4,6.7,7.4l-7,5.3c0,0-3.8-6.3-5-8.9c-1.2,2.9-5,8.9-5,8.9l-7.2-5.3c0,0,5.7-6.3,7.1-7.4c-1.4-0.1-9.9-1.9-9.9-1.9
10
+		L21.6,16.2z"/>
11
+</g>
12
+</svg>

+ 1
- 28
js/ui/popup/controllers/list.js View File

@@ -35,27 +35,12 @@
35 35
     angular.module('passmanExtension')
36 36
         .controller('ListCtrl', ['$scope', 'Settings', '$location', '$rootScope', function ($scope, Settings, $window, $rootScope) {
37 37
             $scope.app = 'passman';
38
-            var port = API.runtime.connect(null, {
39
-                name: "PassmanCommunication"
40
-            });
41 38
 
42
-            var messageParser = function (message) {
43
-                var e = message.split(':');
44
-
45
-                switch (e[0]) {
46
-                    case "credential_amount":
47
-                        $scope.credential_amount = e[1];
48
-                        $scope.refreshing_credentials = false;
49
-                }
50
-
51
-                $scope.$apply();
52
-            };
53 39
 
54 40
             /**
55 41
              * Connect to the background service
56 42
              */
57 43
             var initApp = function () {
58
-                port.onMessage.addListener(messageParser);
59 44
                 API.runtime.sendMessage(API.runtime.id, {method: "getMasterPasswordSet"}).then(function (isPasswordSet) {
60 45
                     //First check attributes
61 46
                     if (!isPasswordSet) {
@@ -63,22 +48,10 @@
63 48
                     }
64 49
 
65 50
                     getActiveTab();
66
-                    $scope.refreshing_credentials = true;
67
-                    setTimeout(function () {
68
-                        port.postMessage("credential_amount");
69
-                    }, 500);
70 51
                 });
71 52
             };
72 53
 
73
-            $scope.refreshing_credentials = false;
74
-            $scope.refresh = function () {
75
-                $scope.refreshing_credentials = true;
76
-                API.runtime.sendMessage(API.runtime.id, {method: "getCredentials"}).then(function () {
77
-                    setTimeout(function () {
78
-                        port.postMessage("credential_amount");
79
-                    }, 2000);
80
-                });
81
-            };
54
+
82 55
 
83 56
             var getActiveTab = function () {
84 57
                 API.tabs.query({currentWindow: true, active: true}).then(function (tab) {

+ 44
- 1
js/ui/popup/controllers/main.js View File

@@ -35,6 +35,49 @@
35 35
     angular.module('passmanExtension')
36 36
         .controller('MainCtrl', ['$scope', 'Settings', '$location', '$rootScope', '$timeout', function ($scope, Settings, $window, $rootScope, $timeout) {
37 37
 
38
+            var port = API.runtime.connect(null, {
39
+                name: "PassmanCommunication"
40
+            });
41
+
42
+            var messageParser = function (message) {
43
+                var e = message.split(':');
44
+
45
+                switch (e[0]) {
46
+                    case "credential_amount":
47
+                        $scope.credential_amount = e[1];
48
+                        $scope.refreshing_credentials = false;
49
+                }
50
+
51
+                $scope.$apply();
52
+            };
53
+
54
+            /**
55
+             * Connect to the background service
56
+             */
57
+            var initApp = function () {
58
+                port.onMessage.addListener(messageParser);
59
+                API.runtime.sendMessage(API.runtime.id, {method: "getMasterPasswordSet"}).then(function (isPasswordSet) {
60
+                    //First check attributes
61
+                    if (!isPasswordSet) {
62
+                        return;
63
+                    }
64
+                    $scope.refreshing_credentials = true;
65
+                    setTimeout(function () {
66
+                        port.postMessage("credential_amount");
67
+                    }, 500);
68
+                });
69
+            };
70
+
71
+
72
+            $scope.refreshing_credentials = false;
73
+            $scope.refresh = function () {
74
+                $scope.refreshing_credentials = true;
75
+                API.runtime.sendMessage(API.runtime.id, {method: "getCredentials"}).then(function () {
76
+                    setTimeout(function () {
77
+                        port.postMessage("credential_amount");
78
+                    }, 2000);
79
+                });
80
+            };
38 81
 
39 82
             $scope.menuIsOpen = false;
40 83
             $scope.bodyOverflow = false;
@@ -65,7 +108,7 @@
65 108
                 } else if (settings.hasOwnProperty('isInstalled')) {
66 109
                     window.location = '#!/locked';
67 110
                 } else {
68
-                    //  initApp();
111
+                    initApp();
69 112
                 }
70 113
             });
71 114
 

+ 28
- 9
style/browser_action.scss View File

@@ -5,6 +5,7 @@
5 5
 @import "partials/material-switch";
6 6
 @import "partials/material-checkbox";
7 7
 @import "partials/material-buttons";
8
+@import "partials/material-tabs";
8 9
 
9 10
 $sidebarWidth: 250px;
10 11
 body {
@@ -71,7 +72,7 @@ body.toggled {
71 72
 }
72 73
 
73 74
 #wrapper.toggled #page-content-wrapper {
74
-  position: absolute;
75
+  /*position: absolute;*/
75 76
   margin-right: -$sidebarWidth;
76 77
   /*  width: calc(100% - 250px);*/
77 78
 }
@@ -89,6 +90,7 @@ body.toggled {
89 90
   margin: 0;
90 91
   padding: 0;
91 92
   list-style: none;
93
+  height: 100%;
92 94
   li {
93 95
     line-height: 55px;
94 96
     a {
@@ -112,19 +114,31 @@ body.toggled {
112 114
         text-decoration: none;
113 115
       }
114 116
     }
117
+    &.bottom {
118
+      position: absolute;
119
+      bottom: 0;
120
+      font-size: 12px;
121
+      text-align: center;
122
+      width: 100%;
123
+      margin-bottom: 15px;
124
+      line-height: 0;
125
+    }
115 126
   }
116 127
   > .sidebar-brand {
117 128
     height: 50px;
118 129
     font-size: 18px;
119 130
     line-height: 50px;
120
-    text-indent: 20px;
131
+    text-align: center;
121 132
     background-color: #1565c0;
122 133
     border-right: 1px solid darken(#1565c0, 10%);
123 134
     span {
124
-
125 135
       display: block;
126 136
       text-decoration: none;
127 137
       color: #fff;
138
+      img {
139
+        height: 32px;
140
+        margin-right: 10px;
141
+      }
128 142
       &:hover {
129 143
         color: #fff;
130 144
         background: none;
@@ -144,9 +158,10 @@ body.toggled {
144 158
   position: absolute;
145 159
   background-color: transparent;
146 160
   width: calc(100% - 250px);
147
-  height: 350px;
161
+  height: 100%;
148 162
   z-index: 9999999;
149 163
   right: 0;
164
+  top: 0;
150 165
 }
151 166
 
152 167
 .edit_credential {
@@ -189,26 +204,30 @@ label, .switch-label, label:not(.input-checkbox):not(.label) {
189 204
     margin-bottom: 45px;
190 205
   }
191 206
 }
192
-.invisible{
207
+
208
+.invisible {
193 209
   visibility: hidden;
194 210
 }
195
-.master_pw_warning{
211
+
212
+.master_pw_warning {
196 213
   padding-left: 6px;
197 214
   font-size: 10px;
198 215
   color: #a94442;
199 216
   margin-bottom: 15px;
200 217
 }
201
-.master_pw_warning.big{
218
+
219
+.master_pw_warning.big {
202 220
   font-size: 14px;
203 221
   text-align: center;
204 222
 
205 223
 }
224
+
206 225
 .unlock {
207 226
   width: 350px;
208
-  box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
227
+  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
209 228
   margin: -20px auto 10px;
210 229
   padding: 20px;
211
-  .group{
230
+  .group {
212 231
     margin-bottom: 25px;
213 232
   }
214 233
   img {

+ 59
- 0
style/css/material-tabs.css View File

@@ -0,0 +1,59 @@
1
+.tab-wrap {
2
+  width: 50%;
3
+  margin-left: 20%;
4
+  position: relative;
5
+  display: flex;
6
+  top: -106px; }
7
+  .tab-wrap label {
8
+    cursor: pointer;
9
+    color: rgba(255, 255, 255, 0.8);
10
+    background-color: #00bcd4;
11
+    box-sizing: border-box;
12
+    display: inline-flex;
13
+    align-items: center;
14
+    justify-content: center;
15
+    text-align: center;
16
+    height: 56px;
17
+    transition: color 0.2s ease;
18
+    width: 100%; }
19
+  .tab-wrap .slide {
20
+    background: #ffeb3b;
21
+    width: calc(100% / 4);
22
+    height: 4px;
23
+    position: absolute;
24
+    left: 0;
25
+    top: calc(100% - 4px);
26
+    transition: left 0.3s ease-out; }
27
+  .tab-wrap .tab-label-content {
28
+    width: 100%; }
29
+    .tab-wrap .tab-label-content .tab-content {
30
+      position: absolute;
31
+      top: 100px;
32
+      left: 16px;
33
+      line-height: 130%;
34
+      display: none; }
35
+  @media screen and (max-width: 800px) {
36
+    .tab-wrap h1 {
37
+      padding: 40px 0 90px 10%; }
38
+    .tab-wrap .tab-wrap {
39
+      width: 80%;
40
+      margin-left: 10%;
41
+      top: -106px; } }
42
+
43
+input[type="radio"][name="tabs"] {
44
+  position: absolute;
45
+  z-index: -1; }
46
+  input[type="radio"][name="tabs"]:checked + .tab-label-content label {
47
+    color: white; }
48
+  input[type="radio"][name="tabs"]:checked + .tab-label-content .tab-content {
49
+    display: block; }
50
+  input[type="radio"][name="tabs"]:nth-of-type(1):checked ~ .slide {
51
+    left: calc((100% / 4) * 0); }
52
+  input[type="radio"][name="tabs"]:nth-of-type(2):checked ~ .slide {
53
+    left: calc((100% / 4) * 1); }
54
+  input[type="radio"][name="tabs"]:nth-of-type(3):checked ~ .slide {
55
+    left: calc((100% / 4) * 2); }
56
+  input[type="radio"][name="tabs"]:nth-of-type(4):checked ~ .slide {
57
+    left: calc((100% / 4) * 3); }
58
+  input[type="radio"][name="tabs"]:first-of-type:checked ~ .slide {
59
+    left: 0; }

+ 18
- 2
style/partials/material-input.scss View File

@@ -27,6 +27,7 @@ input:focus, select.input-md:focus {
27 27
 select.input-md{
28 28
   background-color: #fff;
29 29
   cursor: pointer;
30
+  margin-top: -3px;
30 31
 }
31 32
 /* LABEL ======================================= */
32 33
 .group label {
@@ -51,7 +52,16 @@ select.ng-valid:not(.ng-empty) ~ label {
51 52
   font-size: 14px;
52 53
   color: #1565c0;
53 54
 }
54
-
55
+.col33{
56
+  width: 29%;
57
+  float: left;
58
+  &:first-child{
59
+    padding-right: 10px;
60
+  }
61
+  &:not(:first-child){
62
+    padding-left: 10px;
63
+  }
64
+}
55 65
 /* BOTTOM BARS ================================= */
56 66
 .bar {
57 67
   position: relative;
@@ -95,7 +105,7 @@ input:focus ~ .bar:before, input:focus ~ .bar:after  {
95 105
   opacity: 0.5;
96 106
 
97 107
 }
98
-.group .mdi-content-copy, .pwField .mdi{
108
+.group .mdi-content-copy, .pwField .mdi, .group .mdi-delete{
99 109
   /*position: absolute;
100 110
   right: 0;*/
101 111
   margin-top:5px;
@@ -128,9 +138,15 @@ input:focus ~ .bar:before, input:focus ~ .bar:after  {
128 138
 .mdi-content-copy ~ input{
129 139
   width: calc(100% - 32px);
130 140
 }
141
+.mdi-delete ~ input{
142
+  width: calc(100% - 32px);
143
+}
131 144
 .mdi-content-copy ~ .bar{
132 145
   width: calc(100% - 32px);
133 146
 }
147
+.mdi-delete ~ .bar{
148
+  width: calc(100% - 32px);
149
+}
134 150
 /* active state */
135 151
 input:focus ~ .highlight, select.input-md ~ .highlight {
136 152
   -webkit-animation: inputHighlighter 0.3s ease;

+ 112
- 0
style/partials/material-tabs.scss View File

@@ -0,0 +1,112 @@
1
+$headerBgColor: #fff;
2
+$sliderColor: #1565c0;
3
+$grey: #9e9e9e;
4
+
5
+$num-of-tabs: 2;
6
+
7
+@mixin tabs {
8
+  @for $i from 1 through $num-of-tabs {
9
+    &:nth-of-type(#{$i}) {
10
+      &:checked {
11
+        ~ .slide {
12
+          left: calc((100% / #{$num-of-tabs}) * #{$i - 1});
13
+        }
14
+      }
15
+    }
16
+  }
17
+}
18
+
19
+.tab-wrap {
20
+  width: 100%;
21
+  height: 600px;
22
+  /*position: absolute;*/
23
+  label:not(.ng-binding) {
24
+    cursor: pointer;
25
+    color: rgba(0,0,0,0.8);
26
+    background-color: $headerBgColor;
27
+    box-sizing: border-box;
28
+    display: inline-flex !important;
29
+    align-items: center;
30
+    justify-content: center;
31
+    text-align: center;
32
+    height: 56px;
33
+    transition: color 0.2s ease;
34
+    width: 100%;
35
+    border-bottom: 1px solid #c9c9c9;
36
+  }
37
+
38
+  .slide {
39
+    background: $sliderColor;
40
+    width: calc(100% / #{$num-of-tabs});
41
+    height: 4px;
42
+    position: relative;
43
+    left: 0;
44
+    top: 52px;
45
+    transition: left 0.3s ease-out;
46
+  }
47
+
48
+  .tab-label-content {
49
+    width: calc(100% / #{$num-of-tabs});
50
+    float: left;
51
+    .tab-content {
52
+      position: absolute;
53
+      top: 100px;
54
+      left: 16px;
55
+      line-height: 130%;
56
+      display: none;
57
+      width: 100%;
58
+      padding-right: 20px;
59
+      .custom_field{
60
+        .field{
61
+          &:first-child{
62
+            padding-right: 10px;
63
+          }
64
+          &:not(:first-child){
65
+            padding-left: 10px;
66
+          }
67
+          float: left;
68
+          width: 50%;
69
+        }
70
+        float: left;
71
+        margin-bottom: 15px;
72
+      }
73
+    }
74
+  }
75
+
76
+  @media screen and (max-width: 800px) {
77
+    h1 {
78
+      padding: 40px 0 90px 10%;
79
+    }
80
+    .tab-wrap {
81
+      width: 80%;
82
+      margin-left: 10%;
83
+      top: -106px;
84
+    }
85
+  }
86
+}
87
+
88
+input[type="radio"][name="tabs"] {
89
+  position: absolute;
90
+  z-index: -1;
91
+  &:checked {
92
+    + .tab-label-content {
93
+      label:not(.ng-binding) {
94
+        color: rgba(0,0,0,0.8);
95
+      }
96
+      .tab-content {
97
+        display: block;
98
+        margin-top: 40px;
99
+      }
100
+    }
101
+  }
102
+  @include tabs;
103
+  &:first-of-type {
104
+    &:checked {
105
+      ~ .slide {
106
+        left: 0;
107
+      }
108
+    }
109
+  }
110
+}
111
+
112
+