pages + typography + some scss tweaks

This commit is contained in:
Sercan Yemen 2017-07-28 16:03:32 +03:00
parent 0b3a7ef919
commit cdbae74d6c
46 changed files with 1876 additions and 103 deletions

5
package-lock.json generated
View File

@ -5728,6 +5728,11 @@
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
"integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",

View File

@ -31,6 +31,7 @@
"core-js": "^2.4.1",
"firebase": "^4.1.3",
"hammerjs": "^2.0.8",
"moment": "^2.18.1",
"ngx-color-picker": "^4.2.0",
"ngx-perfect-scrollbar": "^4.5.2",
"rxjs": "^5.4.2",

View File

@ -0,0 +1,39 @@
<div class="fuse-countdown">
<div class="time days">
<div class="value">
{{countdown.days}}
</div>
<div class="title">
days
</div>
</div>
<div class="time hours">
<div class="value">
{{countdown.hours}}
</div>
<div class="title">
hours
</div>
</div>
<div class="time minutes">
<div class="value">
{{countdown.minutes}}
</div>
<div class="title">
minutes
</div>
</div>
<div class="time seconds">
<div class="value">
{{countdown.seconds}}
</div>
<div class="title">
seconds
</div>
</div>
</div>

View File

@ -0,0 +1,29 @@
:host {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.fuse-countdown {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.time {
display: flex;
flex-direction: column;
padding: 0 12px;
.value {
font-size: 34px;
line-height: 34px;
padding-bottom: 8px;
}
.title {
color: rgba(0, 0, 0, 0.54);
}
}
}
}

View File

@ -0,0 +1,53 @@
import { Component, Input, OnInit } from '@angular/core';
import * as moment from 'moment';
import { Observable } from 'rxjs/Observable';
@Component({
selector : 'fuse-countdown',
templateUrl: './countdown.component.html',
styleUrls : ['./countdown.component.scss']
})
export class FuseCountdownComponent implements OnInit
{
@Input('eventDate') eventDate;
countdown: any;
constructor()
{
this.countdown = {
days : '',
hours : '',
minutes: '',
seconds: ''
};
}
ngOnInit()
{
const currDate = moment();
const eventDate = moment(this.eventDate);
let diff = eventDate.diff(currDate, 'seconds');
const countDown =
Observable
.interval(1000)
.map(value => {
return diff = diff - 1;
})
.map(value => {
const timeLeft = moment.duration(value, 'seconds');
return {
days : timeLeft.asDays().toFixed(0),
hours : timeLeft.hours(),
minutes: timeLeft.minutes(),
seconds: timeLeft.seconds()
};
});
countDown.subscribe(value => {
this.countdown = value;
});
}
}

View File

@ -13,6 +13,7 @@
</button>
</div>
<div class="navbar-content" perfect-scrollbar>
<fuse-navigation></fuse-navigation>
</div>

View File

@ -1,6 +1,16 @@
@import "../../../scss/fuse";
:host {
body {
&.fuse-nav-bar-folded {
.content-wrapper {
padding-left: 64px !important;
}
}
}
fuse-navbar {
display: flex;
flex-direction: column;
width: 256px;
@ -76,16 +86,6 @@
font-size: 16px;
}
}
.toggle-button-navbar {
/* border-radius: 50%;
position: relative;
cursor: pointer;
width: 32px;
height: 32px;
padding: 4px;
box-sizing: border-box;*/
}
}
.nav-bar-content {

View File

@ -1,13 +1,14 @@
import {Component, HostBinding, HostListener, OnDestroy, OnInit, ViewEncapsulation} from '@angular/core';
import { Component, HostBinding, HostListener, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { AppComponent } from '../../../../app.component';
import { Subscription } from 'rxjs/Subscription';
import { FuseMatchMedia } from '../../../services/match-media.service';
import { FuseNavbarService } from './navbar.service';
@Component({
selector : 'fuse-navbar',
templateUrl: './navbar.component.html',
styleUrls : ['./navbar.component.scss']
selector : 'fuse-navbar',
templateUrl : './navbar.component.html',
styleUrls : ['./navbar.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FuseNavbarComponent implements OnInit, OnDestroy
{
@ -31,17 +32,18 @@ export class FuseNavbarComponent implements OnInit, OnDestroy
this.isFoldedOpen = false;
this.updateCssClasses();
this.matchMediaWatcher = this.fuseMatchMedia.onMediaChange.subscribe((mediaStep) =>
{
if ( mediaStep === 'xs' )
{
this.closeBar();
}
else
{
this.openBar();
}
});
this.matchMediaWatcher =
this.fuseMatchMedia.onMediaChange
.subscribe((mediaStep) => {
if ( mediaStep === 'xs' )
{
this.closeBar();
}
else
{
this.openBar();
}
});
}
openBar()

View File

@ -101,7 +101,7 @@ export class FuseNavigation
{
'title': 'Login v2',
'type' : 'nav-item',
'url' : '/pages/auth/login-v2'
'url' : '/pages/auth/login-2'
},
{
'title': 'Register',
@ -111,7 +111,7 @@ export class FuseNavigation
{
'title': 'Register v2',
'type' : 'nav-item',
'url' : '/pages/auth/register-v2'
'url' : '/pages/auth/register-2'
},
{
'title': 'Forgot Password',
@ -126,7 +126,7 @@ export class FuseNavigation
{
'title': 'Lock Screen',
'type' : 'nav-item',
'url' : '/pages/auth/lock-screen'
'url' : '/pages/auth/lock'
}
]
},
@ -144,12 +144,12 @@ export class FuseNavigation
{
'title': '404',
'type' : 'nav-item',
'url' : '/pages/errors/404'
'url' : '/pages/errors/error-404'
},
{
'title': '500',
'type' : 'nav-item',
'url' : '/pages/errors/500'
'url' : '/pages/errors/error-500'
}
]
},

View File

@ -16,12 +16,14 @@ import { FusePipesModule } from '../pipes/pipes.module';
import { ColorPickerModule } from 'ngx-color-picker';
import { FuseConfirmDialogComponent } from '../components/confirm-dialog/confirm-dialog.component';
import { NgxDnDModule } from '@swimlane/ngx-dnd';
import { FuseCountdownComponent } from '../components/countdown/countdown.component';
@NgModule({
declarations : [
FuseMdSidenavHelperDirective,
FuseMdSidenavTogglerDirective,
FuseConfirmDialogComponent
FuseConfirmDialogComponent,
FuseCountdownComponent
],
imports : [
FlexLayoutModule,
@ -47,7 +49,8 @@ import { NgxDnDModule } from '@swimlane/ngx-dnd';
PerfectScrollbarModule,
ReactiveFormsModule,
ColorPickerModule,
NgxDnDModule
NgxDnDModule,
FuseCountdownComponent
],
entryComponents: [FuseConfirmDialogComponent]
})

View File

@ -27,6 +27,7 @@
@include angular-material-typography($custom-typography);
// Partials
@import "partials/reset";
@import "partials/normalize";
@import "partials/spacing";
@import "partials/global";

View File

@ -1,5 +1,5 @@
// Variables
@import "variables/theme-variables";
@import "variables/theme";
// Mixins
@import "mixins/breakpoints";

View File

@ -1,27 +1,5 @@
* {
box-sizing: border-box;
}
html {
}
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
body {
&.fuse-nav-bar-folded {
.content-wrapper {
padding-left: 64px;
}
}
> md-sidenav-container {
height: 100%;
}

View File

@ -0,0 +1,74 @@
/*----------------------------------------------------------------*/
/* Reset
/*----------------------------------------------------------------*/
* {
text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-webkit-text-rendering: optimizeLegibility;
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
&:before, &:after {
box-sizing: border-box;
}
// Remove focus outline
&:focus {
outline: none;
}
}
html, body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
// Reset non angular-material input's default browser/os styles
*:not(md-input-container) {
> input,
> input[type="text"],
> input[type="tel"],
> input[type="email"],
> input[type="search"],
> input[type="password"],
> input[type="button"],
> button,
> input[type="submit"],
> input[type="image"],
> textarea {
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
border: none;
padding: 0;
margin: 0;
}
}
*:not(md-input-container) {
> input[type="button"],
> button,
> input[type="submit"] {
background: none;
}
}
button {
border-radius: 0;
font-family: inherit;
font-size: inherit;
padding: 0;
margin: 0;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
}

View File

@ -1,3 +1,248 @@
html {
font-size: 62.5%;
font-family: 'Roboto', 'Helvetica Neue', 'Arial', sans-serif;
line-height: 1.4 !important;
letter-spacing: -0.1px !important;
}
body {
font-size: 14px;
}
html, body {
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
}
// Headings
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
font-weight: normal;
}
h1, .h1 {
font-size: 24px;
}
h2, .h2 {
font-size: 20px;
}
h3, .h3 {
font-size: 16px;
}
h4, .h4 {
font-size: 15px;
}
h5, .h5 {
font-size: 13px;
}
h6, .h6 {
font-size: 12px;
}
// Links
a {
text-decoration: none;
&:hover, &:active {
text-decoration: underline;
}
}
// Abbr
abbr {
cursor: help;
border-bottom: 1px dotted rgba(0, 0, 0, 0.54);
}
// Blockquote
blockquote {
border-left: 3px solid rgba(0, 0, 0, 0.12);
font-style: italic;
margin: 1em 0;
padding-left: 16px;
footer {
font-style: normal;
&:before {
content: '\2014 \00A0';
}
}
&.reverse {
border-left: none;
border-right: 3px solid rgba(0, 0, 0, 0.12);
text-align: right;
padding-left: 0;
padding-right: 16px;
footer {
&:before {
content: '';
}
&:after {
content: '\2014 \00A0';
}
}
}
}
// Code
code {
font-family: 'Monaco', 'Menlo', 'Consolas', 'Ubuntu Mono', monospace;;
&:not(.highlight) {
background: rgba(0, 0, 0, 0.065);
color: #106CC8;
margin: 0 1px;
padding: 2px 3px;
border-radius: 2px;
}
}
// Definition lists
dl {
dt {
font-weight: bold;
}
dd {
margin: 4px 0 16px 0;
}
}
// Mark
mark {
background: #F7F49A;
}
// Pre
pre {
line-height: 1.6;
margin: 8px 16px;
white-space: pre-wrap;
}
// Small
small {
font-size: 80%;
}
// Table
table {
thead {
tr {
th {
text-align: left;
}
}
}
}
// Text format helpers
.text-italic {
font-style: italic;
}
.text-semibold {
font-weight: 600;
}
.text-bold,
strong {
font-weight: 700;
}
.text-strike {
text-decoration: line-through;
}
.text-super {
vertical-align: super;
}
.text-sub {
vertical-align: sub;
}
.text-capitalize {
text-transform: capitalize;
}
.text-lowercase {
text-transform: lowercase;
}
.text-uppercase {
text-transform: uppercase;
}
// Text align helpers
.text-left {
text-align: left;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
// Font weight helpers
@for $weight from 1 through 9 {
.font-weight-#{$weight * 100} {
font-weight: #{$weight * 100};
}
}
// Font size helpers
@for $size from 1 through 60 {
.font-size-#{$size * 2} {
font-size: #{$size * 2}px;
}
}
// Line height helpers
@for $lineHeight from 1 through 60 {
.line-height-#{$lineHeight * 2} {
line-height: #{$lineHeight * 2}px;
}
}
// Boxed text
.text-boxed {
border-radius: 2px;
padding: 4px 8px;
margin: 0 8px;
font-size: 11px;
font-weight: 500;
color: rgba(0, 0, 0, 0.54);
background-color: rgba(0, 0, 0, 0.12);
white-space: nowrap;
}
// Boxed text light
.text-boxed-light {
@extend .text-boxed;
background-color: rgba(255, 255, 255, 0.7);
}
// Truncate
.text-truncate {
display: block;

View File

@ -24,8 +24,10 @@ export class FuseLayoutService
footer : 'none' // 'above', 'below', none
};
// Create the behavior subject
this.onSettingsChanged = new BehaviorSubject(this.defaultSettings);
// Reload the default settings on every navigation start
router.events.subscribe(
(event) => {
if ( event instanceof NavigationStart )

View File

@ -0,0 +1,39 @@
<div id="forgot-password" fxLayout="column" perfect-scrollbar>
<div id="forgot-password-form-wrapper" fxLayout="column" fxLayoutAlign="center center">
<div id="forgot-password-form">
<div class="logo">
<span>F</span>
</div>
<div class="title">RECOVER YOUR PASSWORD</div>
<form name="forgotPasswordForm" [formGroup]="forgotPasswordForm" novalidate>
<md-input-container>
<input mdInput placeholder="Email" formControlName="email">
<md-error *ngIf="forgotPasswordFormErrors.email.required">
Email is required
</md-error>
<md-error *ngIf="!forgotPasswordFormErrors.email.required && forgotPasswordFormErrors.email.email">
Please enter a valid email address
</md-error>
</md-input-container>
<button md-raised-button class="submit-button" color="primary"
aria-label="SEND RESET LINK" [disabled]="forgotPasswordForm.invalid">
SEND RESET LINK
</button>
</form>
<div class="login" fxLayout="row" fxLayoutAlign="center center">
<a class="link" [routerLink]="'/pages/auth/login'">Go back to login</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,79 @@
@import "src/app/core/scss/fuse";
:host {
#forgot-password {
height: 100%;
background: url('/assets/images/backgrounds/march.jpg') no-repeat;
background-size: cover;
#forgot-password-form-wrapper {
flex: 1 0 auto;
padding: 32px;
@include media-breakpoint('xs') {
padding: 16px;
}
#forgot-password-form {
width: 384px;
max-width: 384px;
padding: 32px;
text-align: center;
background: #FFFFFF;
@include mat-elevation(7);
@include media-breakpoint('xs') {
padding: 24px;
width: 100%;
}
.logo {
width: 128px;
height: 128px;
line-height: 128px;
font-size: 86px;
font-weight: 500;
margin: 32px auto;
color: #FFFFFF;
border-radius: 2px;
background: mat-color($accent);
}
.title {
font-size: 17px;
margin: 16px 0 32px 0;
}
form {
width: 100%;
text-align: left;
md-input-container {
width: 100%;
}
.submit-button {
width: 220px;
margin: 16px auto;
display: block;
@include media-breakpoint('xs') {
width: 90%;
}
}
}
.login {
margin: 32px auto 24px auto;
width: 250px;
font-weight: 500;
.text {
margin-right: 8px;
}
}
}
}
}
}

View File

@ -0,0 +1,64 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector : 'fuse-forgot-password',
templateUrl: './forgot-password.component.html',
styleUrls : ['./forgot-password.component.scss']
})
export class ForgotPasswordComponent implements OnInit
{
forgotPasswordForm: FormGroup;
forgotPasswordFormErrors: any;
constructor(
private layoutService: FuseLayoutService,
private formBuilder: FormBuilder
)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
this.forgotPasswordFormErrors = {
email: {}
};
}
ngOnInit()
{
this.forgotPasswordForm = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]]
});
this.forgotPasswordForm.valueChanges.subscribe(() => {
this.onForgotPasswordFormValuesChanged();
});
}
onForgotPasswordFormValuesChanged()
{
for ( const field in this.forgotPasswordFormErrors )
{
if ( !this.forgotPasswordFormErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.forgotPasswordFormErrors[field] = {};
// Get the control
const control = this.forgotPasswordFormErrors.get(field);
if ( control && control.dirty && !control.valid )
{
this.forgotPasswordFormErrors[field] = control.errors;
}
}
}
}

View File

@ -0,0 +1,48 @@
<div id="lock" fxLayout="column" perfect-scrollbar>
<div id="lock-form-wrapper" fxLayout="column" fxLayoutAlign="center center">
<div id="lock-form">
<div fxLayout="row" fxLayoutAlign="start center" fxLayout.sm="column" fxLayoutAlign.sm="center center">
<div class="avatar-container">
<img class="avatar big" src="assets/images/avatars/katherine.jpg">
<md-icon class="s-36">lock</md-icon>
</div>
<div fxLayout="column" fxLayoutAlign="start" fxLayoutAlign.sm="center center" fxFlex>
<div class="title">YOUR SESSION IS LOCKED</div>
<div class="subtitle">
Due to inactivity, your session is locked. Enter your password to continue.
</div>
</div>
</div>
<form name="lockForm" [formGroup]="lockForm" novalidate>
<md-input-container>
<input mdInput placeholder="Username" formControlName="username">
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password" formControlName="password">
<md-error *ngIf="lockFormErrors.password.required">
Password is required
</md-error>
</md-input-container>
<button md-raised-button class="submit-button" color="primary"
aria-label="UNLOCK" [disabled]="lockForm.invalid">
UNLOCK
</button>
</form>
<div class="message">
<a class="link" [routerLink]="'/pages/auth/login'">Are you not Katherine?</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,77 @@
@import "src/app/core/scss/fuse";
:host {
#lock {
height: 100%;
background: url('/assets/images/backgrounds/march.jpg') no-repeat;
background-size: cover;
#lock-form-wrapper {
flex: 1 0 auto;
padding: 32px;
@include media-breakpoint('xs') {
padding: 16px;
}
#lock-form {
width: 384px;
max-width: 384px;
padding: 48px 32px 32px 32px;
background: #FFFFFF;
@include mat-elevation(7);
@include media-breakpoint('xs') {
padding: 24px;
width: 100%;
}
.title {
font-size: 17px;
margin-bottom: 8px;
}
.subtitle {
color: rgba(0, 0, 0, 0.54);
}
.avatar-container {
position: relative;
margin-right: 16px;
md-icon {
position: absolute;
bottom: 0;
right: 0;
color: mat-color($mat-red, 500);
}
}
form {
width: 100%;
margin: 32px 0 0 0;
md-input-container {
width: 100%;
}
.submit-button {
width: 220px;
margin: 16px auto;
display: block;
@include media-breakpoint('xs') {
width: 90%;
}
}
}
.message {
font-weight: 500;
text-align: center;
}
}
}
}
}

View File

@ -0,0 +1,66 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector : 'fuse-lock',
templateUrl: './lock.component.html',
styleUrls : ['./lock.component.scss']
})
export class LockComponent implements OnInit
{
lockForm: FormGroup;
lockFormErrors: any;
constructor(
private layoutService: FuseLayoutService,
private formBuilder: FormBuilder
)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
this.lockFormErrors = {
username: {},
password: {}
};
}
ngOnInit()
{
this.lockForm = this.formBuilder.group({
username: [{value: 'Katherine', disabled: true}, Validators.required],
password: ['', Validators.required]
});
this.lockForm.valueChanges.subscribe(() => {
this.onLockFormValuesChanged();
});
}
onLockFormValuesChanged()
{
for ( const field in this.lockFormErrors )
{
if ( this.lockFormErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.lockFormErrors[field] = {};
// Get the control
const control = this.lockForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.lockFormErrors[field] = control.errors;
}
}
}
}

View File

@ -51,13 +51,16 @@
Remember Me
</md-checkbox>
<a class="forgot-password">Forgot Password?</a>
<a class="forgot-password" [routerLink]="'/pages/auth/forgot-password'">
Forgot Password?
</a>
</div>
<button md-raised-button color="primary" class="submit-button" aria-label="LOG IN"
[disabled]="loginForm.invalid" type="submit">
<button md-raised-button color="primary" class="submit-button" aria-label="LOGIN"
[disabled]="loginForm.invalid">
LOGIN
</button>
</form>
<div class="separator">
@ -78,7 +81,7 @@
<div class="register" fxLayout="column" fxLayoutAlign="center center">
<span class="text">Don't have an account?</span>
<a class="link">Create an account</a>
<a class="link" [routerLink]="'/pages/auth/register-2'">Create an account</a>
</div>
</div>
</div>

View File

@ -43,18 +43,20 @@ export class Login2Component implements OnInit
{
for ( const field in this.loginFormErrors )
{
if ( this.loginFormErrors.hasOwnProperty(field) )
if ( !this.loginFormErrors.hasOwnProperty(field) )
{
// Clear previous errors
this.loginFormErrors[field] = {};
continue;
}
// Get the control
const control = this.loginForm.get(field);
// Clear previous errors
this.loginFormErrors[field] = {};
if ( control && control.dirty && !control.valid )
{
this.loginFormErrors[field] = control.errors;
}
// Get the control
const control = this.loginForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.loginFormErrors[field] = control.errors;
}
}
}

View File

@ -34,11 +34,13 @@
Remember Me
</md-checkbox>
<a class="forgot-password">Forgot Password?</a>
<a class="forgot-password" [routerLink]="'/pages/auth/forgot-password'">
Forgot Password?
</a>
</div>
<button md-raised-button color="primary" class="submit-button" aria-label="LOG IN"
[disabled]="loginForm.invalid" type="submit">
[disabled]="loginForm.invalid">
LOGIN
</button>

View File

@ -46,18 +46,20 @@ export class LoginComponent implements OnInit
{
for ( const field in this.loginFormErrors )
{
if ( this.loginFormErrors.hasOwnProperty(field) )
if ( !this.loginFormErrors.hasOwnProperty(field) )
{
// Clear previous errors
this.loginFormErrors[field] = {};
continue;
}
// Get the control
const control = this.loginForm.get(field);
// Clear previous errors
this.loginFormErrors[field] = {};
if ( control && control.dirty && !control.valid )
{
this.loginFormErrors[field] = control.errors;
}
// Get the control
const control = this.loginForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.loginFormErrors[field] = control.errors;
}
}
}

View File

@ -0,0 +1,82 @@
<div id="register" fxLayout="row" fxLayoutAlign="start">
<div id="register-intro" fxFlex fxHide fxShow.gt-xs>
<div class="logo">
<span>F</span>
</div>
<div class="title">
Welcome to the FUSE!
</div>
<div class="description">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ullamcorper nisl erat,
vel convallis elit fermentum pellentesque. Sed mollis velit facilisis facilisis viverra.
</div>
</div>
<div id="register-form-wrapper" perfect-scrollbar>
<div id="register-form">
<div class="logo" fxHide.gt-xs>
<span>F</span>
</div>
<div class="title">CREATE AN ACCOUNT</div>
<div class="description">Sed mollis velit facilisis facilisis viverra</div>
<form name="registerForm" [formGroup]="registerForm" novalidate>
<md-input-container>
<input mdInput placeholder="Name" formControlName="name">
<md-error *ngIf="registerFormErrors.name.required">
Name is required
</md-error>
</md-input-container>
<md-input-container>
<input mdInput placeholder="Email" formControlName="email">
<md-error *ngIf="registerFormErrors.email.required">
Email is required
</md-error>
<md-error *ngIf="!registerFormErrors.email.required && registerFormErrors.email.email">
Please enter a valid email address
</md-error>
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password" formControlName="password">
<md-error *ngIf="registerFormErrors.password.required">
Password is required
</md-error>
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password (Confirm)" formControlName="passwordConfirm">
<md-error *ngIf="registerFormErrors.passwordConfirm.required">
Password confirmation is required
</md-error>
</md-input-container>
<div class="terms" fxLayout="row" fxLayoutAlign="center center">
<md-checkbox name="terms" aria-label="I read and accept" required>
<span>I read and accept</span>
</md-checkbox>
<a href="#">terms and conditions</a>
</div>
<button md-raised-button color="primary" class="submit-button" aria-label="CREATE AN ACCOUNT"
[disabled]="registerForm.invalid">
CREATE AN ACCOUNT
</button>
</form>
<div class="register" fxLayout="column" fxLayoutAlign="center center">
<span class="text">Already have an account?</span>
<a class="link" [routerLink]="'/pages/auth/login-2'">Login</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,195 @@
@import "src/app/core/scss/fuse";
:host {
#register {
height: 100%;
overflow: hidden;
background: url('/assets/images/backgrounds/march.jpg') no-repeat;
background-size: cover;
#register-intro {
padding: 128px;
@include media-breakpoint('sm') {
padding: 128px 64px;
}
.logo {
width: 128px;
height: 128px;
line-height: 128px;
font-size: 86px;
font-weight: 500;
margin-bottom: 32px;
color: #FFFFFF;
border-radius: 2px;
text-align: center;
background: mat-color($accent);
}
.title {
font-size: 42px;
font-weight: 300;
line-height: 1;
}
.description {
padding-top: 8px;
font-size: 14px;
max-width: 600px;
}
}
#register-form-wrapper {
width: 400px;
min-width: 400px;
max-width: 400px;
height: 100%;
background: #FFFFFF;
@include mat-elevation(7);
@include media-breakpoint('sm') {
width: 360px;
min-width: 360px;
max-width: 360px;
}
@include media-breakpoint('xs') {
width: 100%;
min-width: 100%;
max-width: 100%;
}
#register-form {
padding: 128px 48px 48px 48px;
@include media-breakpoint('xs') {
text-align: center;
padding: 24px;
}
.logo {
width: 128px;
height: 128px;
line-height: 128px;
font-size: 86px;
font-weight: 500;
text-align: center;
margin: 32px auto;
color: #FFFFFF;
border-radius: 2px;
background: mat-color($accent);
}
.title {
font-size: 21px;
}
.description {
padding-top: 8px;
}
form {
width: 100%;
padding-top: 32px;
md-input-container {
width: 100%;
@include media-breakpoint('xs') {
width: 80%;
}
}
md-checkbox {
margin: 0;
}
.terms {
font-size: 13px;
margin: 16px 0 32px 0;
a {
margin-left: 4px;
}
}
.submit-button {
width: 100%;
margin: 16px auto;
display: block;
@include media-breakpoint('xs') {
width: 80%;
}
}
}
.separator {
font-size: 15px;
font-weight: 600;
margin: 24px auto;
position: relative;
overflow: hidden;
width: 100px;
text-align: center;
color: rgba(0, 0, 0, 0.54);
.text {
display: inline-flex;
position: relative;
padding: 0 8px;
z-index: 9999;
&:before, &:after {
content: '';
display: block;
width: 30px;
position: absolute;
top: 10px;
border-top: 1px solid rgba(0, 0, 0, 0.12);
}
&:before {
right: 100%;
}
&:after {
left: 100%;
}
}
}
button {
&.google,
&.facebook {
width: 70%;
text-transform: none;
color: #FFFFFF;
font-size: 13px;
@include media-breakpoint('xs') {
width: 60%;
}
md-icon {
color: #FFFFFF;
margin: 0 8px 0 0;
}
}
&.google {
background-color: #D73D32;
margin-bottom: 8px;
}
&.facebook {
background-color: rgb(63, 92, 154);
}
}
}
}
}
}

View File

@ -0,0 +1,67 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector : 'fuse-register-2',
templateUrl: './register-2.component.html',
styleUrls : ['./register-2.component.scss']
})
export class Register2Component implements OnInit
{
registerForm: FormGroup;
registerFormErrors: any;
constructor(private layoutService: FuseLayoutService, private formBuilder: FormBuilder)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
this.registerFormErrors = {
name : {},
email : {},
password : {},
passwordConfirm: {}
};
}
ngOnInit()
{
this.registerForm = this.formBuilder.group({
name : ['', Validators.required],
email : ['', [Validators.required, Validators.email]],
password : ['', Validators.required],
passwordConfirm: ['', Validators.required]
});
this.registerForm.valueChanges.subscribe(() => {
this.onRegisterFormValuesChanged();
});
}
onRegisterFormValuesChanged()
{
for ( const field in this.registerFormErrors )
{
if ( !this.registerFormErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.registerFormErrors[field] = {};
// Get the control
const control = this.registerForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.registerFormErrors[field] = control.errors;
}
}
}
}

View File

@ -36,7 +36,7 @@
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password Confirm" formControlName="passwordConfirm">
<input mdInput placeholder="Password (Confirm)" formControlName="passwordConfirm">
<md-error *ngIf="registerFormErrors.passwordConfirm.required">
Password confirmation is required
</md-error>
@ -50,7 +50,7 @@
</div>
<button md-raised-button color="primary" class="submit-button" aria-label="CREATE AN ACCOUNT"
[disabled]="registerForm.invalid" type="submit">
[disabled]="registerForm.invalid">
CREATE AN ACCOUNT
</button>

View File

@ -48,18 +48,20 @@ export class RegisterComponent implements OnInit
{
for ( const field in this.registerFormErrors )
{
if ( this.registerFormErrors.hasOwnProperty(field) )
if ( !this.registerFormErrors.hasOwnProperty(field) )
{
// Clear previous errors
this.registerFormErrors[field] = {};
continue;
}
// Get the control
const control = this.registerForm.get(field);
// Clear previous errors
this.registerFormErrors[field] = {};
if ( control && control.dirty && !control.valid )
{
this.registerFormErrors[field] = control.errors;
}
// Get the control
const control = this.registerForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.registerFormErrors[field] = control.errors;
}
}
}

View File

@ -0,0 +1,53 @@
<div id="reset-password" fxLayout="column" perfect-scrollbar>
<div id="reset-password-form-wrapper" fxLayout="column" fxLayoutAlign="center center">
<div id="reset-password-form">
<div class="logo">
<span>F</span>
</div>
<div class="title">RESET YOUR PASSWORD</div>
<form name="resetPasswordForm" [formGroup]="resetPasswordForm" novalidate>
<md-input-container>
<input mdInput placeholder="Email" formControlName="email">
<md-error *ngIf="resetPasswordFormErrors.email.required">
Email is required
</md-error>
<md-error *ngIf="!resetPasswordFormErrors.email.required && resetPasswordFormErrors.email.email">
Please enter a valid email address
</md-error>
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password" formControlName="password">
<md-error *ngIf="resetPasswordFormErrors.password.required">
Password is required
</md-error>
</md-input-container>
<md-input-container>
<input mdInput placeholder="Password (Confirm)" formControlName="passwordConfirm">
<md-error *ngIf="resetPasswordFormErrors.passwordConfirm.required">
Password confirmation is required
</md-error>
</md-input-container>
<button md-raised-button class="submit-button" color="primary"
aria-label="RESET MY PASSWORD" [disabled]="resetPasswordForm.invalid">
RESET MY PASSWORD
</button>
</form>
<div class="login" fxLayout="row" fxLayoutAlign="center center">
<a class="link" [routerLink]="'/pages/auth/login'">Go back to login</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,79 @@
@import "src/app/core/scss/fuse";
:host {
#reset-password {
height: 100%;
background: url('/assets/images/backgrounds/march.jpg') no-repeat;
background-size: cover;
#reset-password-form-wrapper {
flex: 1 0 auto;
padding: 32px;
@include media-breakpoint('xs') {
padding: 16px;
}
#reset-password-form {
width: 384px;
max-width: 384px;
padding: 32px;
text-align: center;
background: #FFFFFF;
@include mat-elevation(7);
@include media-breakpoint('xs') {
padding: 24px;
width: 100%;
}
.logo {
width: 128px;
height: 128px;
line-height: 128px;
font-size: 86px;
font-weight: 500;
margin: 32px auto;
color: #FFFFFF;
border-radius: 2px;
background: mat-color($accent);
}
.title {
font-size: 17px;
margin: 16px 0 32px 0;
}
form {
width: 100%;
text-align: left;
md-input-container {
width: 100%;
}
.submit-button {
width: 220px;
margin: 16px auto;
display: block;
@include media-breakpoint('xs') {
width: 90%;
}
}
}
.login {
margin: 32px auto 24px auto;
width: 250px;
font-weight: 500;
.text {
margin-right: 8px;
}
}
}
}
}
}

View File

@ -0,0 +1,68 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector : 'fuse-reset-password',
templateUrl: './reset-password.component.html',
styleUrls : ['./reset-password.component.scss']
})
export class ResetPasswordComponent implements OnInit
{
resetPasswordForm: FormGroup;
resetPasswordFormErrors: any;
constructor(
private layoutService: FuseLayoutService,
private formBuilder: FormBuilder
)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
this.resetPasswordFormErrors = {
email : {},
password : {},
passwordConfirm: {}
};
}
ngOnInit()
{
this.resetPasswordForm = this.formBuilder.group({
email : ['', [Validators.required, Validators.email]],
password : ['', Validators.required],
passwordConfirm: ['', Validators.required]
});
this.resetPasswordForm.valueChanges.subscribe(() => {
this.onResetPasswordFormValuesChanged();
});
}
onResetPasswordFormValuesChanged()
{
for ( const field in this.resetPasswordFormErrors )
{
if ( this.resetPasswordFormErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.resetPasswordFormErrors[field] = {};
// Get the control
const control = this.resetPasswordForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.resetPasswordFormErrors[field] = control.errors;
}
}
}
}

View File

@ -0,0 +1,49 @@
<div id="coming-soon" fxLayout="column" perfect-scrollbar>
<div id="coming-soon-form-wrapper" fxLayout="column" fxLayoutAlign="center center">
<div id="coming-soon-form">
<div class="top">
<div class="logo md-accent-bg">
<span>F</span>
</div>
<div class="title">Hey! Thank you for checking out our app.</div>
<div class="subtitle">Its not quite ready yet, but we are working hard and it will be ready in
approximately:
</div>
<fuse-countdown eventDate="2019-07-28"></fuse-countdown>
</div>
<form name="comingSoonForm" [formGroup]="comingSoonForm" novalidate>
<div class="message">
If you would like to be notified when the app is ready, you can subscribe to our e-mail list.
</div>
<md-input-container>
<input mdInput placeholder="Email" formControlName="email">
<md-error *ngIf="comingSoonFormErrors.email.required">
Email is required
</md-error>
<md-error *ngIf="!comingSoonFormErrors.email.required && comingSoonFormErrors.email.email">
Please enter a valid email address
</md-error>
</md-input-container>
<button md-raised-button color="primary" class="subscribe-button" aria-label="SUBSCRIBE"
[disabled]="comingSoonForm.invalid">
SUBSCRIBE
</button>
</form>
</div>
</div>
</div>

View File

@ -0,0 +1,95 @@
@import "src/app/core/scss/fuse";
:host {
#coming-soon {
height: 100%;
background: url('/assets/images/backgrounds/march.jpg') no-repeat;
background-size: cover;
#coming-soon-form-wrapper {
flex: 1 0 auto;
padding: 32px;
@include media-breakpoint('xs') {
padding: 16px;
}
#coming-soon-form {
width: 384px;
max-width: 384px;
background: #FFFFFF;
text-align: center;
@include mat-elevation(7);
@include media-breakpoint('xs') {
width: 100%;
}
.top {
width: 100%;
padding: 32px;
@include media-breakpoint('xs') {
padding: 24px;
}
.logo {
width: 128px;
height: 128px;
line-height: 128px;
font-size: 86px;
font-weight: 500;
margin: 32px auto;
color: #FFFFFF;
border-radius: 2px;
background: mat-color($accent);
}
.title {
font-size: 17px;
margin-top: 16px;
}
.subtitle {
margin: 16px auto 0 auto;
text-align: center;
max-width: 300px;
color: rgba(0, 0, 0, 0.54);
font-size: 15px;
}
fuse-countdown {
margin: 48px auto 16px auto;
}
}
form {
width: 100%;
padding: 32px;
text-align: center;
background: mat-color($mat-grey, 100);
.message {
font-weight: 500;
margin: 8px auto 32px auto;
}
md-input-container {
width: 320px;
margin: 8px auto 16px auto;
}
.subscribe-button {
width: 220px;
margin: 16px auto;
@include media-breakpoint('xs') {
width: 90%;
}
}
}
}
}
}
}

View File

@ -0,0 +1,61 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FuseLayoutService } from '../../../core/services/layout.service';
@Component({
selector : 'fuse-coming-soon',
templateUrl: './coming-soon.component.html',
styleUrls : ['./coming-soon.component.scss']
})
export class ComingSoonComponent implements OnInit
{
comingSoonForm: FormGroup;
comingSoonFormErrors: any;
constructor(private layoutService: FuseLayoutService, private formBuilder: FormBuilder)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
this.comingSoonFormErrors = {
email: {}
};
}
ngOnInit()
{
this.comingSoonForm = this.formBuilder.group({
email: ['', [Validators.required, Validators.email]]
});
this.comingSoonForm.valueChanges.subscribe(() => {
this.onRegisterFormValuesChanged();
});
}
onRegisterFormValuesChanged()
{
for ( const field in this.comingSoonFormErrors )
{
if ( !this.comingSoonFormErrors.hasOwnProperty(field) )
{
continue;
}
// Clear previous errors
this.comingSoonFormErrors[field] = {};
// Get the control
const control = this.comingSoonForm.get(field);
if ( control && control.dirty && !control.valid )
{
this.comingSoonFormErrors[field] = control.errors;
}
}
}
}

View File

@ -0,0 +1,18 @@
<div id="error-404" fxLayout="column" fxLayoutAlign="center center">
<div class="content" fxLayout="column" fxLayoutAlign="center center">
<div class="error-code">404</div>
<div class="message">Sorry but we could not find the page you are looking for</div>
<div class="search" fxLayout="row" fxLayoutAlign="start center">
<md-icon class="icon s-24">search</md-icon>
<input placeholder="Search for anything" fxFlex>
</div>
<a class="back-link" [routerLink]="'/apps/dashboards/project'">Go back to dashboard</a>
</div>
</div>

View File

@ -0,0 +1,46 @@
@import "../../../../core/scss/fuse";
:host {
#error-404 {
.content {
width: 90%;
max-width: 512px !important;
margin-top: 128px;
.error-code {
font-size: 112px;
text-align: center;
line-height: 1;
margin-bottom: 16px;
font-weight: 500;
}
.message {
font-size: 24px;
text-align: center;
color: rgba(0, 0, 0, 0.54);
}
.search {
width: 100%;
height: 56px;
line-height: 56px;
margin: 48px auto 16px auto;
padding: 16px;
background: #FFFFFF;
@include mat-elevation(1);
input {
padding: 0 0 0 16px;
}
}
.back-link {
font-size: 15px;
text-align: center;
}
}
}
}

View File

@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
@Component({
selector : 'fuse-error-404',
templateUrl: './error-404.component.html',
styleUrls : ['./error-404.component.scss']
})
export class Error404Component implements OnInit
{
constructor(private layoutService: FuseLayoutService)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
}
ngOnInit()
{
}
}

View File

@ -0,0 +1,17 @@
<div id="error-500" fxLayout="column" fxLayoutAlign="center center">
<div class="content" fxLayout="column" fxLayoutAlign="center center">
<div class="error-code">500</div>
<div class="message">Well, you broke the internet!</div>
<div class="sub-message">
Just kidding, looks like we have an internal issue, please try again in couple minutes
</div>
<a class="report-link" [routerLink]="'/apps/dashboards/project'">Report this problem</a>
</div>
</div>

View File

@ -0,0 +1,39 @@
@import "../../../../core/scss/fuse";
:host {
#error-500 {
.content {
width: 90%;
max-width: 512px !important;
margin-top: 128px;
.error-code {
font-size: 112px;
line-height: 1;
text-align: center;
margin-bottom: 16px;
font-weight: 500;
}
.message {
font-size: 24px;
text-align: center;
color: rgba(0, 0, 0, 0.54);
}
.sub-message {
font-size: 17px;
text-align: center;
color: rgba(0, 0, 0, 0.54);
margin: 16px auto 48px auto;
}
.report-link {
text-align: center;
font-size: 15px;
}
}
}
}

View File

@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { FuseLayoutService } from '../../../../core/services/layout.service';
@Component({
selector : 'fuse-error-500',
templateUrl: './error-500.component.html',
styleUrls : ['./error-500.component.scss']
})
export class Error500Component implements OnInit
{
constructor(private layoutService: FuseLayoutService)
{
this.layoutService.setSettings({
navigation: 'none',
toolbar : 'none',
footer : 'none'
});
}
ngOnInit()
{
}
}

View File

@ -5,19 +5,54 @@ import { RouterModule } from '@angular/router';
import { LoginComponent } from './authentication/login/login.component';
import { Login2Component } from './authentication/login-2/login-2.component';
import { RegisterComponent } from './authentication/register/register.component';
import { Register2Component } from './authentication/register-2/register-2.component';
import { ForgotPasswordComponent } from './authentication/forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './authentication/reset-password/reset-password.component';
import { LockComponent } from './authentication/lock/lock.component';
import { ComingSoonComponent } from './coming-soon/coming-soon.component';
import { Error404Component } from './errors/404/error-404.component';
import { Error500Component } from './errors/500/error-500.component';
const routes = [
{
path : 'pages/auth/login',
component : LoginComponent
path : 'pages/auth/login',
component: LoginComponent
},
{
path : 'pages/auth/login-2',
component : Login2Component
path : 'pages/auth/login-2',
component: Login2Component
},
{
path : 'pages/auth/register',
component : RegisterComponent
path : 'pages/auth/register',
component: RegisterComponent
},
{
path : 'pages/auth/register-2',
component: Register2Component
},
{
path : 'pages/auth/forgot-password',
component: ForgotPasswordComponent
},
{
path : 'pages/auth/reset-password',
component: ResetPasswordComponent
},
{
path : 'pages/auth/lock',
component: LockComponent
},
{
path : 'pages/coming-soon',
component: ComingSoonComponent
},
{
path : 'pages/errors/error-404',
component: Error404Component
},
{
path : 'pages/errors/error-500',
component: Error500Component
}
];
@ -29,7 +64,14 @@ const routes = [
declarations: [
LoginComponent,
Login2Component,
RegisterComponent
RegisterComponent,
Register2Component,
ForgotPasswordComponent,
ResetPasswordComponent,
LockComponent,
ComingSoonComponent,
Error404Component,
Error500Component
]
})
export class PagesModule

View File

@ -15,9 +15,6 @@
</head>
<body class="mat-body">
</body>
<body></body>
</html>