added toaster

This commit is contained in:
Kyle Spearrin 2018-01-26 14:12:41 -05:00
parent 2c08cd353e
commit 298b12bf0d
9 changed files with 350 additions and 240 deletions

View File

@ -1,13 +1,23 @@
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import { ToasterContainerComponent, ToasterConfig } from 'angular2-toaster';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
styles: [], styles: [],
template: '<router-outlet></router-outlet>', template: `
<toaster-container [toasterconfig]="toasterConfig"></toaster-container>
<router-outlet></router-outlet>`,
}) })
export class AppComponent { export class AppComponent {
toasterConfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
mouseoverTimerStop: true,
animation: 'flyRight',
limit: 5,
});
constructor(angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics) { constructor(angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics) {
} }
} }

View File

@ -4,10 +4,11 @@ import 'zone.js/dist/zone';
import { Angulartics2Module } from 'angulartics2'; import { Angulartics2Module } from 'angulartics2';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { ServicesModule } from './services/services.module'; import { ServicesModule } from './services/services.module';
import { ToasterModule } from 'angular2-toaster';
import { AddComponent } from './vault/add.component'; import { AddComponent } from './vault/add.component';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@ -25,7 +26,7 @@ import { ViewComponent } from './vault/view.component';
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserAnimationsModule,
FormsModule, FormsModule,
AppRoutingModule, AppRoutingModule,
ServicesModule, ServicesModule,
@ -34,6 +35,7 @@ import { ViewComponent } from './vault/view.component';
clearQueryParams: true, clearQueryParams: true,
}, },
}), }),
ToasterModule,
], ],
declarations: [ declarations: [
AddComponent, AddComponent,

View File

@ -77,7 +77,7 @@ const settingsService = new SettingsService(userService, storageService);
const cipherService = new CipherService(cryptoService, userService, settingsService, const cipherService = new CipherService(cryptoService, userService, settingsService,
apiService, storageService); apiService, storageService);
const folderService = new FolderService(cryptoService, userService, const folderService = new FolderService(cryptoService, userService,
() => i18nService.t('noFolder'), apiService, storageService); () => i18nService.t('noneFolder'), apiService, storageService);
const collectionService = new CollectionService(cryptoService, userService, storageService); const collectionService = new CollectionService(cryptoService, userService, storageService);
const lockService = new LockService(cipherService, folderService, collectionService, const lockService = new LockService(cipherService, folderService, collectionService,
cryptoService, platformUtilsService, storageService, cryptoService, platformUtilsService, storageService,

View File

@ -6,6 +6,9 @@ import {
OnChanges, OnChanges,
} from '@angular/core'; } from '@angular/core';
import { Angulartics2 } from 'angulartics2';
import { ToasterService } from 'angular2-toaster';
import { CipherType } from 'jslib/enums/cipherType'; import { CipherType } from 'jslib/enums/cipherType';
import { FieldType } from 'jslib/enums/fieldType'; import { FieldType } from 'jslib/enums/fieldType';
import { SecureNoteType } from 'jslib/enums/secureNoteType'; import { SecureNoteType } from 'jslib/enums/secureNoteType';
@ -41,7 +44,8 @@ export class AddComponent implements OnChanges {
addFieldTypeOptions: any[]; addFieldTypeOptions: any[];
constructor(private cipherService: CipherService, private folderService: FolderService, constructor(private cipherService: CipherService, private folderService: FolderService,
private i18nService: I18nService, private platformUtilsService: PlatformUtilsService) { private i18nService: I18nService, private platformUtilsService: PlatformUtilsService,
private analytics: Angulartics2, private toasterService: ToasterService) {
this.typeOptions = [ this.typeOptions = [
{ name: i18nService.t('typeLogin'), value: CipherType.Login }, { name: i18nService.t('typeLogin'), value: CipherType.Login },
{ name: i18nService.t('typeCard'), value: CipherType.Card }, { name: i18nService.t('typeCard'), value: CipherType.Card },
@ -104,15 +108,15 @@ export class AddComponent implements OnChanges {
async save() { async save() {
if (this.cipher.name == null || this.cipher.name === '') { if (this.cipher.name == null || this.cipher.name === '') {
this.platformUtilsService.alertError(this.i18nService.t('errorOccurred'), this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('nameRequired')); this.i18nService.t('nameRequired'));
return; return;
} }
const cipher = await this.cipherService.encrypt(this.cipher); const cipher = await this.cipherService.encrypt(this.cipher);
await this.cipherService.saveWithServer(cipher); await this.cipherService.saveWithServer(cipher);
//$analytics.eventTrack('Added Cipher'); this.analytics.eventTrack.next({ action: 'Added Cipher' });
// TODO: success message this.toasterService.popAsync('success', null, this.i18nService.t('addedItem'));
}; };
addField() { addField() {

View File

@ -29,9 +29,6 @@
"collections": { "collections": {
"message": "Collections" "message": "Collections"
}, },
"noFolder": {
"message": "No Folder"
},
"searchVault": { "searchVault": {
"message": "Search vault" "message": "Search vault"
}, },
@ -286,5 +283,24 @@
}, },
"nameRequired": { "nameRequired": {
"message": "Name is required." "message": "Name is required."
},
"addedItem": {
"message": "Added item"
},
"editedItem": {
"message": "Edited item"
},
"deleteItemConfirmation": {
"message": "Are you sure you want to delete this item?"
},
"deletedItem": {
"message": "Deleted item"
},
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
} }
} }

194
src/scss/box.scss Normal file
View File

@ -0,0 +1,194 @@
@import "variables.scss";
.box {
min-width: 400px;
max-width: 550px;
width: 100%;
margin: 30px auto 0 auto;
&:first-child {
margin-top: 10px;
}
&:last-child {
margin-bottom: 30px;
}
.box-header {
margin: 0 10px 5px 10px;
color: $gray-light;
text-transform: uppercase;
}
.box-content {
background: $box-background-color;
border-radius: $border-radius;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
.box-content-row {
padding: 10px 15px;
position: relative;
z-index: 1;
display: block;
color: $text-color;
overflow-wrap: break-word;
&:before {
content: "";
position: absolute;
right: 0;
bottom: 0;
height: 1px;
width: calc(100% - 10px);
border-bottom: 1px solid $box-border-color;
}
&:first-child, &:last-child {
border-radius: $border-radius;
}
&:last-child {
&:before {
border: none;
height: 0;
}
}
&:after {
content: "";
display: table;
clear: both;
}
&:hover, &:focus, &.active {
background-color: $box-background-hover-color;
}
&.pre {
white-space: pre;
overflow-x: auto;
}
.no-wrap {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&.box-content-row-cf {
display: flex;
align-items: center;
width: 100%;
> a {
padding: 8px 10px 8px 5px;
color: $brand-danger;
}
> div {
width: 100%;
}
}
.row-label, label {
font-size: $font-size-small;
color: $text-muted;
display: block;
width: 100%;
margin-bottom: 5px;
}
&.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider {
label, .row-label {
font-size: $font-size-base;
color: $text-color;
display: inline;
width: initial;
margin-bottom: 0;
float: left;
}
input.row-label {
width: calc(100% - 40px);
}
}
input:not([type="checkbox"]), select, textarea {
border: none;
width: 100%;
background-color: transparent;
&::-webkit-input-placeholder {
color: lighten($gray-light, 35%);
}
&:focus {
outline: none;
}
}
input[type="checkbox"] {
float: right;
display: inline-block;
}
.action-buttons {
float: right;
.row-btn {
float: left;
cursor: pointer;
padding: 10px 8px;
background: none;
border: none;
color: $brand-primary;
&:hover, &:focus {
color: darken($brand-primary, 10%);
}
&.disabled {
color: $list-icon-color;
&:hover {
color: $list-icon-color;
}
}
&:last-child {
padding-right: 2px !important;
}
}
}
select.field-type {
margin: 5px 0 0 25px;
width: calc(100% - 25px);
}
.right-icon, .fa-chevron-right {
float: right;
margin-top: 4px;
color: $list-icon-color;
}
.row-sub-label {
float: right;
display: block;
margin-right: 15px;
color: $gray-light;
}
small.row-sub-label {
margin-top: 2px;
}
}
}
.box-footer {
margin: 5px 10px;
font-size: $font-size-small;
color: $text-muted;
}
}

72
src/scss/plugins.scss Normal file
View File

@ -0,0 +1,72 @@
@import "variables.scss";
#toast-container {
.toast-close-button {
right: -0.15em;
}
.toast {
opacity: 1 !important;
background-image: none !important;
border-radius: $border-radius;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.35);
display: flex;
align-items: center;
&:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
}
&:before {
position: fixed;
font-family: FontAwesome;
font-size: 25px;
line-height: 20px;
float: left;
color: #ffffff;
padding-right: 0.5em;
margin: auto 0 auto -36px;
}
.toaster-icon {
display: none;
}
&.toast-danger, &.toast-error {
background-image: none !important;
background-color: $brand-danger;
&:before {
content: "\f0e7";
margin-left: -30px;
}
}
&.toast-warning {
background-image: none !important;
background-color: $brand-warning;
&:before {
content: "\f071";
}
}
&.toast-info {
background-image: none !important;
background-color: $brand-info;
&:before {
content: "\f05a";
}
}
&.toast-success {
background-image: none !important;
background-color: $brand-success;
&:before {
content: "\f00C";
}
}
}
}

View File

@ -1,43 +1,10 @@
$fa-font-path: "~font-awesome/fonts"; $fa-font-path: "~font-awesome/fonts";
@import "~font-awesome/scss/font-awesome.scss"; @import "~font-awesome/scss/font-awesome.scss";
@import "~angular2-toaster/toaster";
$font-family-sans-serif: 'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif; @import "variables.scss";
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; @import "box.scss";
$font-size-base: 14px; @import "plugins.scss";
$font-size-large: 18px;
$font-size-small: 12px;
$text-color: #000000;
$background-color: #efeff4;
$border-color: #f0f0f0;
$border-color-dark: #ddd;
$list-item-hover: #fbfbfb;
$list-icon-color: #c7c7cd;
$border-radius: 3px;
$gray: #555;
$gray-light: #777;
$text-muted: $gray-light;
$brand-primary: #3c8dbc;
$brand-danger: #dd4b39;
$brand-success: #00a65a;
$brand-info: #555555;
$brand-warning: #f39c12;
$brand-primary-accent: #286090;
$background-color: white;
$background-color-alt: #f9fafc;
$background-color-alt2: #ecf0f5;
$box-background-color: $background-color;
$box-background-hover-color: $background-color-alt;
$box-border-color: $border-color;
$button-border-color: darken($border-color-dark, 12%);
$button-backgound-color: white;
$button-color: lighten($text-color, 40%);
$button-color-primary: darken($brand-primary, 8%);
$button-color-danger: darken($brand-danger, 10%);
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -629,198 +596,6 @@ textarea {
} }
} }
.box {
min-width: 400px;
max-width: 550px;
width: 100%;
margin: 30px auto 0 auto;
&:first-child {
margin-top: 10px;
}
&:last-child {
margin-bottom: 30px;
}
.box-header {
margin: 0 10px 5px 10px;
color: $gray-light;
text-transform: uppercase;
}
.box-content {
background: $box-background-color;
border-radius: $border-radius;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
.box-content-row {
padding: 10px 15px;
position: relative;
z-index: 1;
display: block;
color: $text-color;
overflow-wrap: break-word;
&:before {
content: "";
position: absolute;
right: 0;
bottom: 0;
height: 1px;
width: calc(100% - 10px);
border-bottom: 1px solid $box-border-color;
}
&:first-child, &:last-child {
border-radius: $border-radius;
}
&:last-child {
&:before {
border: none;
height: 0;
}
}
&:after {
content: "";
display: table;
clear: both;
}
&:hover, &:focus, &.active {
background-color: $box-background-hover-color;
}
&.pre {
white-space: pre;
overflow-x: auto;
}
.no-wrap {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&.box-content-row-cf {
display: flex;
align-items: center;
width: 100%;
> a {
padding: 8px 10px 8px 5px;
color: $brand-danger;
}
> div {
width: 100%;
}
}
.row-label, label {
font-size: $font-size-small;
color: $text-muted;
display: block;
width: 100%;
margin-bottom: 5px;
}
&.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider {
label, .row-label {
font-size: $font-size-base;
color: $text-color;
display: inline;
width: initial;
margin-bottom: 0;
float: left;
}
input.row-label {
width: calc(100% - 40px);
}
}
input:not([type="checkbox"]), select, textarea {
border: none;
width: 100%;
background-color: transparent;
&::-webkit-input-placeholder {
color: lighten($gray-light, 35%);
}
&:focus {
outline: none;
}
}
input[type="checkbox"] {
float: right;
display: inline-block;
}
.action-buttons {
float: right;
.row-btn {
float: left;
cursor: pointer;
padding: 10px 8px;
background: none;
border: none;
color: $brand-primary;
&:hover, &:focus {
color: darken($brand-primary, 10%);
}
&.disabled {
color: $list-icon-color;
&:hover {
color: $list-icon-color;
}
}
&:last-child {
padding-right: 2px !important;
}
}
}
select.field-type {
margin: 5px 0 0 25px;
width: calc(100% - 25px);
}
.right-icon, .fa-chevron-right {
float: right;
margin-top: 4px;
color: $list-icon-color;
}
.row-sub-label {
float: right;
display: block;
margin-right: 15px;
color: $gray-light;
}
small.row-sub-label {
margin-top: 2px;
}
}
}
.box-footer {
margin: 5px 10px;
font-size: $font-size-small;
color: $text-muted;
}
}
.totp { .totp {
.totp-code { .totp-code {
font-family: $font-family-monospace; font-family: $font-family-monospace;

37
src/scss/variables.scss Normal file
View File

@ -0,0 +1,37 @@
$font-family-sans-serif: 'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-size-base: 14px;
$font-size-large: 18px;
$font-size-small: 12px;
$text-color: #000000;
$background-color: #efeff4;
$border-color: #f0f0f0;
$border-color-dark: #ddd;
$list-item-hover: #fbfbfb;
$list-icon-color: #c7c7cd;
$border-radius: 3px;
$gray: #555;
$gray-light: #777;
$text-muted: $gray-light;
$brand-primary: #3c8dbc;
$brand-danger: #dd4b39;
$brand-success: #00a65a;
$brand-info: #555555;
$brand-warning: #f39c12;
$brand-primary-accent: #286090;
$background-color: white;
$background-color-alt: #f9fafc;
$background-color-alt2: #ecf0f5;
$box-background-color: $background-color;
$box-background-hover-color: $background-color-alt;
$box-border-color: $border-color;
$button-border-color: darken($border-color-dark, 12%);
$button-backgound-color: white;
$button-color: lighten($text-color, 40%);
$button-color-primary: darken($brand-primary, 8%);
$button-color-danger: darken($brand-danger, 10%);