first chrome implementation
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
<div class="sam-text-header">
|
||||
<span>Gooti</span>
|
||||
</div>
|
||||
|
||||
<div class="vertically-centered">
|
||||
<div class="sam-flex-column center">
|
||||
<div class="sam-flex-column gap" style="align-items: center">
|
||||
<div class="logo-frame">
|
||||
<img src="gooti.svg" height="120" width="120" alt=""/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="sam-mt-2 btn btn-primary"
|
||||
(click)="router.navigateByUrl('/vault-create/new')"
|
||||
>
|
||||
<div class="sam-flex-row gap-h">
|
||||
<i class="bi bi-plus-circle" style="height: 22px"></i>
|
||||
<span>Create a new vault</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<span class="sam-text-muted">or</span>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
(click)="fileInput.click()"
|
||||
>
|
||||
<span>Import a vault</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
#fileInput
|
||||
class="file-input"
|
||||
type="file"
|
||||
(change)="onImportFileChange($event)"
|
||||
accept=".json"
|
||||
/>
|
||||
@@ -0,0 +1,17 @@
|
||||
:host {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.vertically-centered {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.file-input {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HomeComponent } from './home.component';
|
||||
|
||||
describe('HomeComponent', () => {
|
||||
let component: HomeComponent;
|
||||
let fixture: ComponentFixture<HomeComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HomeComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { BrowserSyncData, StorageService } from '@common';
|
||||
import { StartupService } from '../../../services/startup/startup.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss',
|
||||
})
|
||||
export class HomeComponent {
|
||||
readonly router = inject(Router);
|
||||
readonly #storage = inject(StorageService);
|
||||
readonly #startup = inject(StartupService);
|
||||
|
||||
async onImportFileChange(event: Event) {
|
||||
try {
|
||||
const element = event.currentTarget as HTMLInputElement;
|
||||
const file = element.files !== null ? element.files[0] : undefined;
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const text = await file.text();
|
||||
const vault = JSON.parse(text) as BrowserSyncData;
|
||||
console.log(vault);
|
||||
|
||||
await this.#storage.importVault(vault);
|
||||
this.#startup.startOver();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<div class="sam-text-header">
|
||||
<span>Gooti</span>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="sam-flex-column gap" style="align-items: center">
|
||||
<div class="logo-frame">
|
||||
<img src="gooti.svg" height="120" width="120" alt=""/>
|
||||
</div>
|
||||
|
||||
<span class="sam-mt-2"> Please define a password for your vault. </span>
|
||||
|
||||
<small class="sam-text-muted">
|
||||
Sensitive data is encypted before it is stored.
|
||||
</small>
|
||||
|
||||
<div class="sam-mt input-group">
|
||||
<input
|
||||
#passwordInputElement
|
||||
type="password"
|
||||
class="form-control form-control-lg"
|
||||
style="font-size: 1rem"
|
||||
placeholder="vault password"
|
||||
[(ngModel)]="password"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-outline-secondary"
|
||||
type="button"
|
||||
(click)="toggleType(passwordInputElement)"
|
||||
>
|
||||
<i
|
||||
class="bi bi-eye"
|
||||
[class.bi-eye]="passwordInputElement.type === 'password'"
|
||||
[class.bi-eye-slash]="passwordInputElement.type === 'text'"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
[disabled]="!password || password.length < 4"
|
||||
type="button"
|
||||
class="sam-mt btn btn-primary"
|
||||
(click)="createVault()"
|
||||
>
|
||||
Create vault
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
:host {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
color-scheme: dark;
|
||||
|
||||
.custom-header {
|
||||
padding-top: var(--size);
|
||||
padding-bottom: var(--size);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto;
|
||||
align-items: center;
|
||||
|
||||
.back {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 2;
|
||||
grid-row-start: 1;
|
||||
grid-row-end: 2;
|
||||
justify-self: start;
|
||||
padding-left: var(--size);
|
||||
}
|
||||
|
||||
.text {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 2;
|
||||
grid-row-start: 1;
|
||||
grid-row-end: 2;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
padding: 0 var(--size) var(--size) var(--size);
|
||||
}
|
||||
|
||||
.logo-frame {
|
||||
border: 2px solid #0d6efd;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NewComponent } from './new.component';
|
||||
|
||||
describe('NewComponent', () => {
|
||||
let component: NewComponent;
|
||||
let fixture: ComponentFixture<NewComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [NewComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(NewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavComponent, StorageService } from '@common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-new',
|
||||
imports: [FormsModule],
|
||||
templateUrl: './new.component.html',
|
||||
styleUrl: './new.component.scss',
|
||||
})
|
||||
export class NewComponent extends NavComponent {
|
||||
password = '';
|
||||
|
||||
readonly #router = inject(Router);
|
||||
readonly #storage = inject(StorageService);
|
||||
|
||||
toggleType(element: HTMLInputElement) {
|
||||
if (element.type === 'password') {
|
||||
element.type = 'text';
|
||||
} else {
|
||||
element.type = 'password';
|
||||
}
|
||||
}
|
||||
|
||||
async createVault() {
|
||||
if (!this.password) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.#storage.createNewVault(this.password);
|
||||
this.#router.navigateByUrl('/home/identities');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<router-outlet></router-outlet>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VaultCreateComponent } from './vault-create.component';
|
||||
|
||||
describe('VaultCreateComponent', () => {
|
||||
let component: VaultCreateComponent;
|
||||
let fixture: ComponentFixture<VaultCreateComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VaultCreateComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(VaultCreateComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-vault-create',
|
||||
imports: [RouterOutlet],
|
||||
templateUrl: './vault-create.component.html',
|
||||
styleUrl: './vault-create.component.scss'
|
||||
})
|
||||
export class VaultCreateComponent {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user