mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-23 02:31:26 +01:00
layouts and messaging
This commit is contained in:
parent
63a56b359b
commit
5098153fde
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit 4c083eeb92d599bd8b85fb88ec5d435079b79395
|
||||
Subproject commit fe3a8785422a8866dbcb91d31db6d3fd2aa2daaa
|
@ -4,6 +4,10 @@ import {
|
||||
Routes,
|
||||
} from '@angular/router';
|
||||
|
||||
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
|
||||
import { OrganizationLayoutComponent } from './layouts/organization-layout.component';
|
||||
import { UserLayoutComponent } from './layouts/user-layout.component';
|
||||
|
||||
import { HintComponent } from './accounts/hint.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
@ -12,15 +16,32 @@ import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { VaultComponent } from './vault/vault.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/vault', pathMatch: 'full' },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: '2fa', component: TwoFactorComponent },
|
||||
{ path: 'register', component: RegisterComponent },
|
||||
{ path: 'hint', component: HintComponent },
|
||||
{
|
||||
path: 'vault',
|
||||
component: VaultComponent,
|
||||
path: '',
|
||||
component: UserLayoutComponent,
|
||||
children: [
|
||||
{ path: '', redirectTo: 'vault', pathMatch: 'full' },
|
||||
{ path: 'vault', component: VaultComponent },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: FrontendLayoutComponent,
|
||||
children: [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: '2fa', component: TwoFactorComponent },
|
||||
{ path: 'register', component: RegisterComponent },
|
||||
{ path: 'hint', component: HintComponent },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'organization/:organizationId',
|
||||
component: OrganizationLayoutComponent,
|
||||
children: [
|
||||
{ path: 'vault', component: VaultComponent },
|
||||
],
|
||||
},
|
||||
{ path: '**', redirectTo: '' },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -1,19 +1,45 @@
|
||||
import {
|
||||
ToasterConfig,
|
||||
ToasterContainerComponent,
|
||||
ToasterService,
|
||||
} from 'angular2-toaster';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import {
|
||||
Component,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
import { StorageService } from 'jslib/abstractions/storage.service';
|
||||
|
||||
import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { CollectionService } from 'jslib/abstractions/collection.service';
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { LockService } from 'jslib/abstractions/lock.service';
|
||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
import { SettingsService } from 'jslib/abstractions/settings.service';
|
||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||
import { TokenService } from 'jslib/abstractions/token.service';
|
||||
import { UserService } from 'jslib/abstractions/user.service';
|
||||
|
||||
import { ConstantsService } from 'jslib/services/constants.service';
|
||||
|
||||
const BroadcasterSubscriptionId = 'AppComponent';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: 'app.component.html',
|
||||
})
|
||||
export class AppComponent {
|
||||
export class AppComponent implements OnDestroy, OnInit {
|
||||
toasterConfig: ToasterConfig = new ToasterConfig({
|
||||
showCloseButton: true,
|
||||
mouseoverTimerStop: true,
|
||||
@ -22,7 +48,90 @@ export class AppComponent {
|
||||
positionClass: 'toast-bottom-right',
|
||||
});
|
||||
|
||||
constructor() {
|
||||
//
|
||||
private lastActivity: number = null;
|
||||
|
||||
constructor(private broadcasterService: BroadcasterService, private userService: UserService,
|
||||
private tokenService: TokenService, private folderService: FolderService,
|
||||
private settingsService: SettingsService, private syncService: SyncService,
|
||||
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
|
||||
private authService: AuthService, private router: Router, private analytics: Angulartics2,
|
||||
private toasterService: ToasterService, private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
|
||||
private lockService: LockService, private storageService: StorageService,
|
||||
private cryptoService: CryptoService, private collectionService: CollectionService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
window.onmousemove = () => this.recordActivity();
|
||||
window.onmousedown = () => this.recordActivity();
|
||||
window.ontouchstart = () => this.recordActivity();
|
||||
window.onclick = () => this.recordActivity();
|
||||
window.onscroll = () => this.recordActivity();
|
||||
window.onkeypress = () => this.recordActivity();
|
||||
});
|
||||
|
||||
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
|
||||
this.ngZone.run(async () => {
|
||||
switch (message.command) {
|
||||
case 'loggedIn':
|
||||
case 'unlocked':
|
||||
case 'loggedOut':
|
||||
break;
|
||||
case 'logout':
|
||||
this.logOut(!!message.expired);
|
||||
break;
|
||||
case 'lockVault':
|
||||
//await this.lockService.lock();
|
||||
break;
|
||||
case 'locked':
|
||||
//this.router.navigate(['lock']);
|
||||
break;
|
||||
case 'syncStarted':
|
||||
break;
|
||||
case 'syncCompleted':
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||
}
|
||||
|
||||
private async logOut(expired: boolean) {
|
||||
const userId = await this.userService.getUserId();
|
||||
|
||||
await Promise.all([
|
||||
this.syncService.setLastSync(new Date(0)),
|
||||
this.tokenService.clearToken(),
|
||||
this.cryptoService.clearKeys(),
|
||||
this.userService.clear(),
|
||||
this.settingsService.clear(userId),
|
||||
this.cipherService.clear(userId),
|
||||
this.folderService.clear(userId),
|
||||
this.collectionService.clear(userId),
|
||||
this.passwordGenerationService.clear(),
|
||||
]);
|
||||
|
||||
this.authService.logOut(async () => {
|
||||
this.analytics.eventTrack.next({ action: 'Logged Out' });
|
||||
if (expired) {
|
||||
this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'),
|
||||
this.i18nService.t('loginExpired'));
|
||||
}
|
||||
this.router.navigate(['login']);
|
||||
});
|
||||
}
|
||||
|
||||
private async recordActivity() {
|
||||
const now = (new Date()).getTime();
|
||||
if (this.lastActivity != null && now - this.lastActivity < 250) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastActivity = now;
|
||||
this.storageService.save(ConstantsService.lastActiveKey, now);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,12 @@ import { ServicesModule } from './services.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { ModalComponent } from './modal.component';
|
||||
|
||||
import { FooterComponent } from './layouts/footer.component';
|
||||
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
|
||||
import { NavbarComponent } from './layouts/navbar.component';
|
||||
import { OrganizationLayoutComponent } from './layouts/organization-layout.component';
|
||||
import { UserLayoutComponent } from './layouts/user-layout.component';
|
||||
|
||||
import { HintComponent } from './accounts/hint.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
@ -69,6 +75,8 @@ import { Folder } from 'jslib/models/domain';
|
||||
CiphersComponent,
|
||||
FallbackSrcDirective,
|
||||
FolderAddEditComponent,
|
||||
FooterComponent,
|
||||
FrontendLayoutComponent,
|
||||
GroupingsComponent,
|
||||
HintComponent,
|
||||
IconComponent,
|
||||
@ -76,12 +84,15 @@ import { Folder } from 'jslib/models/domain';
|
||||
InputVerbatimDirective,
|
||||
LoginComponent,
|
||||
ModalComponent,
|
||||
NavbarComponent,
|
||||
OrganizationLayoutComponent,
|
||||
RegisterComponent,
|
||||
SearchCiphersPipe,
|
||||
StopClickDirective,
|
||||
StopPropDirective,
|
||||
TwoFactorComponent,
|
||||
TwoFactorOptionsComponent,
|
||||
UserLayoutComponent,
|
||||
VaultComponent,
|
||||
],
|
||||
entryComponents: [
|
||||
|
13
src/app/layouts/footer.component.html
Normal file
13
src/app/layouts/footer.component.html
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="container footer text-muted">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
© 2018, 8bit Solutions LLC
|
||||
</div>
|
||||
<div class="col text-center">
|
||||
|
||||
</div>
|
||||
<div class="col text-right">
|
||||
Version 2.0.0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
9
src/app/layouts/footer.component.ts
Normal file
9
src/app/layouts/footer.component.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer',
|
||||
templateUrl: 'footer.component.html',
|
||||
})
|
||||
export class FooterComponent { }
|
2
src/app/layouts/frontend-layout.component.html
Normal file
2
src/app/layouts/frontend-layout.component.html
Normal file
@ -0,0 +1,2 @@
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer></app-footer>
|
9
src/app/layouts/frontend-layout.component.ts
Normal file
9
src/app/layouts/frontend-layout.component.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-frontend-layout',
|
||||
templateUrl: 'frontend-layout.component.html',
|
||||
})
|
||||
export class FrontendLayoutComponent { }
|
33
src/app/layouts/navbar.component.html
Normal file
33
src/app/layouts/navbar.component.html
Normal file
@ -0,0 +1,33 @@
|
||||
<nav class="navbar navbar-expand navbar-dark bg-primary">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" routerLink="/">
|
||||
<i class="fa fa-shield"></i>
|
||||
</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/vault">My Vault</a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/tools">Tools</a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/settings">Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-item nav-link dropdown-toggle" href="#" id="nav-profile" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-user fa-lg"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="nav-profile">
|
||||
<a class="dropdown-item" href="#">Help</a>
|
||||
<a class="dropdown-item" href="#">Get the Apps</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" appStopClick (click)="logOut()">Log Out</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
17
src/app/layouts/navbar.component.ts
Normal file
17
src/app/layouts/navbar.component.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
templateUrl: 'navbar.component.html',
|
||||
})
|
||||
export class NavbarComponent {
|
||||
constructor(private messagingService: MessagingService) { }
|
||||
|
||||
logOut() {
|
||||
this.messagingService.send('logout');
|
||||
}
|
||||
}
|
3
src/app/layouts/organization-layout.component.html
Normal file
3
src/app/layouts/organization-layout.component.html
Normal file
@ -0,0 +1,3 @@
|
||||
<app-navbar></app-navbar>
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer></app-footer>
|
9
src/app/layouts/organization-layout.component.ts
Normal file
9
src/app/layouts/organization-layout.component.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-organization-layout',
|
||||
templateUrl: 'organization-layout.component.html',
|
||||
})
|
||||
export class OrganizationLayoutComponent { }
|
3
src/app/layouts/user-layout.component.html
Normal file
3
src/app/layouts/user-layout.component.html
Normal file
@ -0,0 +1,3 @@
|
||||
<app-navbar></app-navbar>
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer></app-footer>
|
9
src/app/layouts/user-layout.component.ts
Normal file
9
src/app/layouts/user-layout.component.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-layout',
|
||||
templateUrl: 'user-layout.component.html',
|
||||
})
|
||||
export class UserLayoutComponent { }
|
@ -5,8 +5,8 @@ import {
|
||||
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
|
||||
import { BroadcasterMessagingService } from '../services/broadcasterMessaging.service';
|
||||
import { I18nService } from '../services/i18n.service';
|
||||
import { WebMessagingService } from '../services/webMessaging.service';
|
||||
import { WebPlatformUtilsService } from '../services/webPlatformUtils.service';
|
||||
import { WebStorageService } from '../services/webStorage.service';
|
||||
|
||||
@ -68,7 +68,7 @@ import { UserService as UserServiceAbstraction } from 'jslib/abstractions/user.s
|
||||
const i18nService = new I18nService(window.navigator.language, 'locales');
|
||||
const stateService = new StateService();
|
||||
const broadcasterService = new BroadcasterService();
|
||||
const messagingService = new WebMessagingService();
|
||||
const messagingService = new BroadcasterMessagingService(broadcasterService);
|
||||
const platformUtilsService = new WebPlatformUtilsService(messagingService, i18nService);
|
||||
const storageService: StorageServiceAbstraction = new WebStorageService();
|
||||
const cryptoFunctionService: CryptoFunctionServiceAbstraction = new WebCryptoFunctionService(window,
|
||||
|
@ -1,32 +1,3 @@
|
||||
<nav class="navbar navbar-expand navbar-dark bg-primary">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">
|
||||
<i class="fa fa-shield"></i>
|
||||
</a>
|
||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">My Vault</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-item nav-link dropdown-toggle" href="#" id="nav-profile" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-user fa-lg"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="nav-profile">
|
||||
<a class="dropdown-item" href="#">Option 1</a>
|
||||
<a class="dropdown-item" href="#">Option 2</a>
|
||||
<a class="dropdown-item" href="#">Option 3</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container page-content">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
@ -93,19 +64,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container footer text-muted">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
© 2018, 8bit Solutions LLC
|
||||
</div>
|
||||
<div class="col text-center">
|
||||
|
||||
</div>
|
||||
<div class="col text-right">
|
||||
Version 2.0.0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #attachments></ng-template>
|
||||
<ng-template #folderAddEdit></ng-template>
|
||||
<ng-template #cipherAddEdit></ng-template>
|
||||
|
12
src/services/broadcasterMessaging.service.ts
Normal file
12
src/services/broadcasterMessaging.service.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
|
||||
|
||||
export class BroadcasterMessagingService implements MessagingService {
|
||||
constructor(private broadcasterService: BroadcasterService) { }
|
||||
|
||||
send(subscriber: string, arg: any = {}) {
|
||||
const message = Object.assign({}, { command: subscriber }, arg);
|
||||
this.broadcasterService.send(message);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
|
||||
export class WebMessagingService implements MessagingService {
|
||||
send(subscriber: string, arg: any = {}) {
|
||||
//
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user