mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-27 04:03:00 +02:00
implement all register/login flow components
This commit is contained in:
parent
4e20efdee1
commit
167acd1929
14
gulpfile.js
14
gulpfile.js
@ -17,7 +17,8 @@ const paths = {
|
||||
coverage: './coverage/',
|
||||
npmDir: './node_modules/',
|
||||
popupDir: './src/popup/',
|
||||
cssDir: './src/popup/css/'
|
||||
cssDir: './src/popup/css/',
|
||||
cssDir2: './src/css/'
|
||||
};
|
||||
|
||||
const filters = {
|
||||
@ -181,6 +182,8 @@ function safariZip(buildPath) {
|
||||
|
||||
gulp.task('build', ['lint', 'webfonts']);
|
||||
|
||||
gulp.task('build2', ['webfonts2']);
|
||||
|
||||
gulp.task('webfonts', () => {
|
||||
return gulp.src('./webfonts.list')
|
||||
.pipe(googleWebFonts({
|
||||
@ -190,6 +193,15 @@ gulp.task('webfonts', () => {
|
||||
.pipe(gulp.dest(paths.cssDir));
|
||||
});
|
||||
|
||||
gulp.task('webfonts2', () => {
|
||||
return gulp.src('./webfonts.list')
|
||||
.pipe(googleWebFonts({
|
||||
fontsDir: 'webfonts',
|
||||
cssFilename: 'webfonts.css'
|
||||
}))
|
||||
.pipe(gulp.dest(paths.cssDir2));
|
||||
});
|
||||
|
||||
gulp.task('ci', ['ci:coverage']);
|
||||
|
||||
gulp.task('ci:coverage', (cb) => {
|
||||
|
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit f855a8272c7dc3c3099643cf34e49d3089e6575e
|
||||
Subproject commit f673bd62d7abb773fa5a6abfb5307b7c3feca59b
|
@ -9,8 +9,8 @@
|
||||
"start:firefox": "web-ext run --source-dir ./dist/",
|
||||
"dev": "gulp build && webpack --config webpack.dev.js",
|
||||
"dev:watch": "gulp build && webpack --config webpack.dev.js --watch",
|
||||
"dev2": "webpack --config webpack2.js",
|
||||
"dev2:watch": "webpack --config webpack2.js --watch",
|
||||
"dev2": "gulp build2 && webpack --config webpack2.js",
|
||||
"dev2:watch": "gulp build2 && webpack --config webpack2.js --watch",
|
||||
"prod": "gulp build && webpack --config webpack.prod.js",
|
||||
"dist": "npm run prod && gulp dist",
|
||||
"dist:firefox": "npm run prod && gulp dist:firefox",
|
||||
|
@ -668,7 +668,22 @@
|
||||
"message": "Enter the 6 digit verification code from your authenticator app."
|
||||
},
|
||||
"enterVerificationCodeEmail": {
|
||||
"message": "Enter the 6 digit verification code that was emailed to"
|
||||
"message": "Enter the 6 digit verification code that was emailed to $EMAIL$.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
"example": "example@gmail.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"verificationCodeEmailSent": {
|
||||
"message": "Verification email sent to $EMAIL$.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
"example": "example@gmail.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rememberMe": {
|
||||
"message": "Remember me"
|
||||
|
@ -1,59 +1,57 @@
|
||||
<div class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<form class="modal-content" (ngSubmit)="submit()">
|
||||
<div class="modal-body">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{'selfHostedEnvironment' | i18n}}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="baseUrl">{{'baseUrl' | i18n}}</label>
|
||||
<input id="baseUrl" type="text" name="BaseUrl" [(ngModel)]="baseUrl"
|
||||
placeholder="ex. https://bitwarden.company.com">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'selfHostedEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<button type="button" (click)="toggleCustom()">
|
||||
<i class="fa fa-plus-square-o" [hidden]="showCustom"></i>
|
||||
<i class="fa fa-minus-square-o" [hidden]="!showCustom"></i>
|
||||
{{'customEnvironment' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-content" [hidden]="!showCustom">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="webVaultUrl">{{'webVaultUrl' | i18n}}</label>
|
||||
<input id="webVaultUrl" type="text" name="WebVaultUrl" [(ngModel)]="webVaultUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="apiUrl">{{'apiUrl' | i18n}}</label>
|
||||
<input id="apiUrl" type="text" name="ApiUrl" [(ngModel)]="apiUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="identityUrl">{{'identityUrl' | i18n}}</label>
|
||||
<input id="identityUrl" type="text" name="IdentityUrl" [(ngModel)]="identityUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="iconsUrl">{{'iconsUrl' | i18n}}</label>
|
||||
<input id="iconsUrl" type="text" name="IconsUrl" [(ngModel)]="iconsUrl">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer" [hidden]="!showCustom">
|
||||
{{'customEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
<form #form class="modal-content" (ngSubmit)="submit()">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/">{{'close' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'appName' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'save' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{'selfHostedEnvironment' | i18n}}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="baseUrl">{{'baseUrl' | i18n}}</label>
|
||||
<input id="baseUrl" type="text" name="BaseUrl" [(ngModel)]="baseUrl"
|
||||
placeholder="ex. https://bitwarden.company.com">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button appBlurClick type="submit" class="primary" title="{{'save' | i18n}}">
|
||||
<i class="fa fa-save fa-lg fa-fw"></i>
|
||||
</button>
|
||||
<button type="button" data-dismiss="modal">{{'close' | i18n}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'selfHostedEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{'customEnvironment' | i18n}}
|
||||
</div>
|
||||
<div class="box-content" [hidden]="!showCustom">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="webVaultUrl">{{'webVaultUrl' | i18n}}</label>
|
||||
<input id="webVaultUrl" type="text" name="WebVaultUrl" [(ngModel)]="webVaultUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="apiUrl">{{'apiUrl' | i18n}}</label>
|
||||
<input id="apiUrl" type="text" name="ApiUrl" [(ngModel)]="apiUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="identityUrl">{{'identityUrl' | i18n}}</label>
|
||||
<input id="identityUrl" type="text" name="IdentityUrl" [(ngModel)]="identityUrl">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="iconsUrl">{{'iconsUrl' | i18n}}</label>
|
||||
<input id="iconsUrl" type="text" name="IconsUrl" [(ngModel)]="iconsUrl">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer" [hidden]="!showCustom">
|
||||
{{'customEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -20,10 +20,11 @@ export class EnvironmentComponent extends BaseEnvironmentComponent {
|
||||
environmentService: EnvironmentService, i18nService: I18nService,
|
||||
private router: Router) {
|
||||
super(analytics, toasterService, environmentService, i18nService);
|
||||
this.showCustom = true;
|
||||
}
|
||||
|
||||
saved() {
|
||||
super.saved();
|
||||
this.router.navigate(['login']);
|
||||
this.router.navigate(['']);
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,27 @@
|
||||
<form id="hint-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<div class="content">
|
||||
<h1>{{'passwordHint' | i18n}}</h1>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required appAutofocus>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'enterEmailToGetHint' | i18n}}
|
||||
</div>
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<b [hidden]="form.loading">{{'submit' | i18n}}</b>
|
||||
<div class="center">
|
||||
<span class="title">{{'passwordHint' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required appAutofocus>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'enterEmailToGetHint' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
15
src/popup2/accounts/home.component.html
Normal file
15
src/popup2/accounts/home.component.html
Normal file
@ -0,0 +1,15 @@
|
||||
<div class="home-page">
|
||||
<a routerLink="/environment" class="settings-icon">
|
||||
<i class="fa fa-cog fa-lg"></i><span> {{'settings' | i18n}}</span>
|
||||
</a>
|
||||
<img src="../images/logo@2x.png" alt="bitwarden" />
|
||||
<p>{{'loginOrCreateNewAccount' | i18n}}</p>
|
||||
<div class="bottom-buttons">
|
||||
<a class="btn btn-lg btn-primary btn-block" routerLink="/register">
|
||||
<strong>{{'createAccount' | i18n}}</strong>
|
||||
</a>
|
||||
<a class="btn btn-lg btn-link btn-block" routerLink="/login">
|
||||
{{'login' | i18n}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
18
src/popup2/accounts/home.component.ts
Normal file
18
src/popup2/accounts/home.component.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import * as template from './home.component.html';
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
template: template,
|
||||
})
|
||||
export class HomeComponent {
|
||||
constructor(private router: Router, i18nService: I18nService,
|
||||
analytics: Angulartics2, toasterService: ToasterService) { }
|
||||
}
|
@ -1,43 +1,42 @@
|
||||
<form id="login-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<div class="content">
|
||||
<p class="lead">{{'loginOrCreateNewAccount' | i18n}}</p>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required
|
||||
[appAutofocus]="email === ''">
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'appName' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'login' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required
|
||||
[appAutofocus]="email === ''">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required [appAutofocus]="email !== ''">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required [appAutofocus]="email !== ''">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<span [hidden]="form.loading"><i class="fa fa-sign-in"></i> {{'logIn' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
<a routerLink="/register" class="btn block">
|
||||
<i class="fa fa-pencil-square-o"></i> {{'createAccount' | i18n}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
<a routerLink="/hint">{{'getMasterPasswordHint' | i18n}}</a>
|
||||
</div>
|
||||
<a href="#" appStopClick (click)="settings()" class="settings-icon">
|
||||
<i class="fa fa-cog fa-lg"></i><span> {{'settings' | i18n}}</span>
|
||||
</a>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<a routerLink="/hint">{{'getMasterPasswordHint' | i18n}}</a>
|
||||
</p>
|
||||
</form>
|
||||
|
@ -1,64 +1,68 @@
|
||||
<form id="register-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<div class="content">
|
||||
<h1>{{'createAccount' | i18n}}</h1>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required
|
||||
[appAutofocus]="email === ''">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required [appAutofocus]="email !== ''">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassDesc' | i18n}}
|
||||
</div>
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="confirmMasterPassword"
|
||||
required>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'createAccount' | i18n}}</span>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
|
||||
<b [hidden]="form.loading">{{'submit' | i18n}}</b>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required
|
||||
[appAutofocus]="email === ''">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required [appAutofocus]="email !== ''">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="confirmMasterPassword"
|
||||
required>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
title="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,28 +1,22 @@
|
||||
<div class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{'twoStepOptions' | i18n}}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<a href="#" appStopClick *ngFor="let p of providers" class="box-content-row"
|
||||
(click)="choose(p)">
|
||||
<img [src]="'images/two-factor/' + p.type + '.png'" alt="" class="img-right">
|
||||
<span class="text">{{p.name}}</span>
|
||||
<span class="detail">{{p.description}}</span>
|
||||
</a>
|
||||
<a href="#" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{'recoveryCodeTitle' | i18n}}</span>
|
||||
<span class="detail">{{'recoveryCodeDesc' | i18n}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" data-dismiss="modal">{{'close' | i18n}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/2fa">{{'close' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'twoStepOptions' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<a href="#" appStopClick *ngFor="let p of providers" class="box-content-row"
|
||||
(click)="choose(p)">
|
||||
<span class="text">{{p.name}}</span>
|
||||
<span class="detail">{{p.description}}</span>
|
||||
</a>
|
||||
<a href="#" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{'recoveryCodeTitle' | i18n}}</span>
|
||||
<span class="detail">{{'recoveryCodeDesc' | i18n}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,4 +24,10 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
|
||||
i18nService: I18nService, platformUtilsService: PlatformUtilsService) {
|
||||
super(authService, router, analytics, toasterService, i18nService, platformUtilsService);
|
||||
}
|
||||
|
||||
choose(p: any) {
|
||||
super.choose(p);
|
||||
this.authService.selectedTwoFactorProviderType = p.type;
|
||||
this.router.navigate(['2fa']);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,29 @@
|
||||
<form id="two-factor-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<div class="content">
|
||||
<h1>{{title}}</h1>
|
||||
<p *ngIf="selectedProviderType === providerType.Authenticator">{{'enterVerificationCodeApp' | i18n}}</p>
|
||||
<p *ngIf="selectedProviderType === providerType.Email">
|
||||
{{'enterVerificationCodeEmail' | i18n : twoFactorEmail}}
|
||||
</p>
|
||||
<div class="box last"
|
||||
*ngIf="selectedProviderType === providerType.Email || selectedProviderType === providerType.Authenticator">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{title}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading"
|
||||
*ngIf="selectedProviderType != null && selectedProviderType !== providerType.Duo &&
|
||||
selectedProviderType !== providerType.OrganizationDuo">
|
||||
<span [hidden]="form.loading">{{'continue' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Authenticator ||
|
||||
selectedProviderType === providerType.Email">
|
||||
<div class="content">
|
||||
<p *ngIf="selectedProviderType === providerType.Authenticator">{{'enterVerificationCodeApp' | i18n}}</p>
|
||||
<p *ngIf="selectedProviderType === providerType.Email">
|
||||
{{'enterVerificationCodeEmail' | i18n : twoFactorEmail}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code">{{'verificationCode' | i18n}}</label>
|
||||
@ -18,57 +35,49 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Yubikey">
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Yubikey">
|
||||
<div class="content">
|
||||
<p>{{'insertYubiKey' | i18n}}</p>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code" class="sr-only">{{'verificationCode' | i18n}}</label>
|
||||
<input id="code" type="password" name="Code" [(ngModel)]="token" required appAutofocus>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Duo ||
|
||||
selectedProviderType === providerType.OrganizationDuo">
|
||||
<div id="duo-frame"><iframe id="duo_iframe"></iframe></div>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="box last" *ngIf="selectedProviderType == null">
|
||||
<img src="../images/yubikey.jpg" class="img-rounded img-responsive" alt="">
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row">
|
||||
<p>{{'noTwoStepProviders' | i18n}}</p>
|
||||
<p>{{'noTwoStepProviders2' | i18n}}</p>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code" class="sr-only">{{'verificationCode' | i18n}}</label>
|
||||
<input id="code" type="password" name="Code" [(ngModel)]="token" required appAutofocus>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick
|
||||
*ngIf="selectedProviderType != null && selectedProviderType !== providerType.Duo &&
|
||||
selectedProviderType !== providerType.OrganizationDuo">
|
||||
<span [hidden]="form.loading"><i class="fa fa-sign-in"></i> {{'continue' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{'cancel' | i18n}}</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Duo ||
|
||||
selectedProviderType === providerType.OrganizationDuo">
|
||||
<div id="duo-frame"><iframe id="duo_iframe"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
</ng-container>
|
||||
<div class="content" *ngIf="selectedProviderType == null">
|
||||
<p>{{'noTwoStepProviders' | i18n}}</p>
|
||||
<p>{{'noTwoStepProviders2' | i18n}}</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p class="text-center">
|
||||
<a href="#" appStopClick (click)="anotherMethod()">{{'useAnotherTwoStepMethod' | i18n}}</a>
|
||||
<a href="#" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise"
|
||||
*ngIf="selectedProviderType === providerType.Email">
|
||||
</p>
|
||||
<p class="text-center" *ngIf="selectedProviderType === providerType.Email">
|
||||
<a href="#" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise">
|
||||
{{'sendVerificationCodeEmailAgain' | i18n}}
|
||||
</a>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
<ng-template #twoFactorOptions></ng-template>
|
||||
|
@ -6,13 +6,14 @@ import {
|
||||
|
||||
import { EnvironmentComponent } from './accounts/environment.component';
|
||||
import { HintComponent } from './accounts/hint.component';
|
||||
import { HomeComponent } from './accounts/home.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/login', pathMatch: 'full' },
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: 'login', component: LoginComponent },
|
||||
{ path: '2fa', component: TwoFactorComponent },
|
||||
{ path: '2fa-options', component: TwoFactorOptionsComponent },
|
||||
|
@ -30,8 +30,10 @@ export class AppComponent {
|
||||
toasterConfig: ToasterConfig = new ToasterConfig({
|
||||
showCloseButton: true,
|
||||
mouseoverTimerStop: true,
|
||||
animation: 'flyRight',
|
||||
limit: 5,
|
||||
animation: 'slideUp',
|
||||
limit: 2,
|
||||
positionClass: 'toast-bottom-full-width',
|
||||
newestOnTop: false
|
||||
});
|
||||
|
||||
constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics, private analytics: Angulartics2,
|
||||
|
@ -17,6 +17,7 @@ import { AppComponent } from './app.component';
|
||||
|
||||
import { EnvironmentComponent } from './accounts/environment.component';
|
||||
import { HintComponent } from './accounts/hint.component';
|
||||
import { HomeComponent } from './accounts/home.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
@ -25,6 +26,7 @@ import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
||||
import { AutofocusDirective } from 'jslib/angular/directives/autofocus.directive';
|
||||
import { BlurClickDirective } from 'jslib/angular/directives/blur-click.directive';
|
||||
import { BoxRowDirective } from 'jslib/angular/directives/box-row.directive';
|
||||
import { FallbackSrcDirective } from 'jslib/angular/directives/fallback-src.directive';
|
||||
import { StopClickDirective } from 'jslib/angular/directives/stop-click.directive';
|
||||
import { StopPropDirective } from 'jslib/angular/directives/stop-prop.directive';
|
||||
@ -50,8 +52,10 @@ import { I18nPipe } from 'jslib/angular/pipes/i18n.pipe';
|
||||
AppComponent,
|
||||
AutofocusDirective,
|
||||
BlurClickDirective,
|
||||
BoxRowDirective,
|
||||
EnvironmentComponent,
|
||||
FallbackSrcDirective,
|
||||
HomeComponent,
|
||||
HintComponent,
|
||||
I18nPipe,
|
||||
LoginComponent,
|
||||
|
6
src/popup2/images/loading.svg
Normal file
6
src/popup2/images/loading.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100% 100%">
|
||||
<text fill="%23333333" x="50%" y="50%" font-family="\'Open Sans\', \'Helvetica Neue\', Helvetica, Arial, sans-serif"
|
||||
font-size="18" text-anchor="middle">
|
||||
Loading...
|
||||
</text>
|
||||
</svg>
|
BIN
src/popup2/images/logo.png
Normal file
BIN
src/popup2/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
BIN
src/popup2/images/logo@2x.png
Normal file
BIN
src/popup2/images/logo@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
src/popup2/images/logo@3x.png
Normal file
BIN
src/popup2/images/logo@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
BIN
src/popup2/images/u2fkey.jpg
Normal file
BIN
src/popup2/images/u2fkey.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
BIN
src/popup2/images/yubikey.jpg
Normal file
BIN
src/popup2/images/yubikey.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
143
src/scss/base.scss
Normal file
143
src/scss/base.scss
Normal file
@ -0,0 +1,143 @@
|
||||
@import "variables.scss";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
background-color: $background-color-alt2;
|
||||
font-family: $font-family-sans-serif;
|
||||
font-size: $font-size-base;
|
||||
color: $text-color;
|
||||
line-height: $line-height-base;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 375px !important;
|
||||
height: 600px !important;
|
||||
overflow: hidden;
|
||||
|
||||
&.sm {
|
||||
width: 375px !important;
|
||||
height: 500px !important;
|
||||
}
|
||||
|
||||
&.xs {
|
||||
width: 375px !important;
|
||||
height: 300px !important;
|
||||
}
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: $font-family-sans-serif;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $brand-primary;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: darken($brand-primary, 6%);
|
||||
}
|
||||
}
|
||||
|
||||
input, select, textarea, button {
|
||||
font-size: $font-size-base;
|
||||
font-family: $font-family-sans-serif;
|
||||
}
|
||||
|
||||
button {
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
div::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
div::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
div::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(100,100,100,.2);
|
||||
border-radius: 10px;
|
||||
margin-right: 1px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(100,100,100,.4);
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: $brand-primary;
|
||||
min-height: 44px;
|
||||
max-height: 44px;
|
||||
color: white;
|
||||
display: flex;
|
||||
|
||||
.left, .right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
min-width: -webkit-min-content; /* Workaround to Chrome bug */
|
||||
}
|
||||
|
||||
.right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button, a {
|
||||
background: $brand-primary;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 15px;
|
||||
}
|
254
src/scss/box.scss
Normal file
254
src/scss/box.scss
Normal file
@ -0,0 +1,254 @@
|
||||
@import "variables.scss";
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
|
||||
.box-header {
|
||||
margin: 0 10px 5px 10px;
|
||||
color: $gray-light;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
background: $box-background-color;
|
||||
border-top: 1px solid $border-color-dark;
|
||||
border-bottom: 1px solid $border-color-dark;
|
||||
|
||||
&.box-content-padded {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.box-content-row {
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
&: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;
|
||||
}
|
||||
|
||||
.row-label, label {
|
||||
font-size: $font-size-small;
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.text, .detail {
|
||||
display: block;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.detail {
|
||||
font-size: $font-size-small;
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
.img-right {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.row-main {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.box-content-row-flex, &.box-content-row-checkbox, &.box-content-row-input,
|
||||
&.box-content-row-slider, &.box-content-row-multi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
&.box-content-row-multi {
|
||||
width: 100%;
|
||||
|
||||
input:not([type="checkbox"]) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input + label.sr-only + select {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
> a {
|
||||
padding: 8px 8px 8px 4px;
|
||||
color: $brand-danger;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.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;
|
||||
}
|
||||
|
||||
> span {
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
> input {
|
||||
margin: 0 0 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> * {
|
||||
margin-right: 15px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.box-content-row-input {
|
||||
label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&.box-content-row-slider {
|
||||
input[type="range"] {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]), textarea {
|
||||
border: none;
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
color: lighten($gray-light, 35%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
border: 1px solid darken($border-color-dark, 7%);
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
margin-left: 5px;
|
||||
|
||||
.row-btn {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-pad .row-btn {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
select.field-type {
|
||||
margin: 5px 0 0 25px;
|
||||
width: calc(100% - 25px);
|
||||
}
|
||||
|
||||
.row-sub-icon {
|
||||
color: $list-icon-color;
|
||||
}
|
||||
|
||||
.row-sub-label {
|
||||
margin: 0 15px;
|
||||
color: $gray-light;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&.condensed .box-content-row, .box-content-row.condensed {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
&.no-hover .box-content-row, .box-content-row.no-hover {
|
||||
&:hover, &:focus {
|
||||
background-color: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box-footer {
|
||||
margin: 5px 10px;
|
||||
font-size: $font-size-small;
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
8
src/scss/environment.scss
Normal file
8
src/scss/environment.scss
Normal file
@ -0,0 +1,8 @@
|
||||
@import "variables.scss";
|
||||
|
||||
html.browser_firefox, html.browser_edge {
|
||||
body {
|
||||
width: 320px !important;
|
||||
height: 568px !important;
|
||||
}
|
||||
}
|
76
src/scss/misc.scss
Normal file
76
src/scss/misc.scss
Normal file
@ -0,0 +1,76 @@
|
||||
@import "variables.scss";
|
||||
|
||||
small {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: $brand-primary !important;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: $brand-success !important;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: $text-muted !important;
|
||||
}
|
||||
|
||||
.text-default {
|
||||
color: $text-color !important;
|
||||
}
|
||||
|
||||
.text-accent {
|
||||
color: $brand-primary-accent;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.monospaced {
|
||||
font-family: $font-family-monospace;
|
||||
}
|
||||
|
||||
.img-responsive {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.img-rounded {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
padding: 0 !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
clip: rect(0, 0, 0, 0) !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
#duo-frame {
|
||||
// TODO
|
||||
}
|
||||
|
||||
app-root > #loading {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: $text-muted;
|
||||
}
|
81
src/scss/plugins.scss
Normal file
81
src/scss/plugins.scss
Normal file
@ -0,0 +1,81 @@
|
||||
$fa-font-path: "~font-awesome/fonts";
|
||||
@import "~font-awesome/scss/font-awesome.scss";
|
||||
@import "~angular2-toaster/toaster";
|
||||
|
||||
@import "variables.scss";
|
||||
|
||||
#toast-container {
|
||||
.toast-close-button {
|
||||
right: -0.15em;
|
||||
}
|
||||
|
||||
&.toast-bottom-full-width div.toast {
|
||||
margin: 0 10px 10px;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
body {
|
||||
color: black;
|
||||
}
|
||||
@import "../css/webfonts.css";
|
||||
@import "variables.scss";
|
||||
@import "base.scss";
|
||||
@import "box.scss";
|
||||
@import "misc.scss";
|
||||
@import "plugins.scss";
|
||||
@import "environment.scss";
|
||||
|
38
src/scss/variables.scss
Normal file
38
src/scss/variables.scss
Normal file
@ -0,0 +1,38 @@
|
||||
$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;
|
||||
$line-height-base: 1.42857143;
|
||||
|
||||
$gray: #555;
|
||||
$gray-light: #777;
|
||||
$text-muted: $gray-light;
|
||||
|
||||
$brand-primary: #3c8dbc;
|
||||
$brand-danger: #dd4b39;
|
||||
$brand-success: #00a65a;
|
||||
$brand-info: #555555;
|
||||
$brand-warning: #bf7e16;
|
||||
$brand-primary-accent: #286090;
|
||||
|
||||
$background-color: white;
|
||||
$background-color-alt: #f9fafc;
|
||||
$background-color-alt2: #ecf0f5;
|
||||
|
||||
$box-background-color: $background-color;
|
||||
$box-background-hover-color: $list-item-hover;
|
||||
$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%);
|
Loading…
Reference in New Issue
Block a user