Skip to content

Commit 83b137f

Browse files
Add bootstrap and font-awesome.
Implement top level components: - app - home - login - welcome
1 parent 81fceec commit 83b137f

8 files changed

+562
-33
lines changed

angular-cli.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
"tsconfig": "tsconfig.json",
1919
"prefix": "app",
2020
"styles": [
21-
"styles.css"
21+
"styles.css",
22+
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
23+
"../node_modules/font-awesome/css/font-awesome.css"
2224
],
2325
"scripts": [],
2426
"environments": {
@@ -28,6 +30,9 @@
2830
}
2931
}
3032
],
33+
"addons": [
34+
"../node_modules/font-awesome/fonts/*.+(otf|eot|svg|ttf|woff|woff2)"
35+
],
3136
"e2e": {
3237
"protractor": {
3338
"config": "./protractor.conf.js"

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"@angular/platform-browser": "^2.3.1",
2121
"@angular/platform-browser-dynamic": "^2.3.1",
2222
"@angular/router": "^3.3.1",
23+
"bootstrap": "^3.3.7",
2324
"core-js": "^2.4.1",
25+
"font-awesome": "^4.7.0",
2426
"rxjs": "^5.0.1",
2527
"ts-helpers": "^1.1.1",
2628
"ui-router-core": "^4.0.0",

src/app/app.component.ts

+72-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,79 @@
1-
import { Component } from '@angular/core';
1+
import { Component, ViewChild, ViewContainerRef, OnInit } from '@angular/core';
2+
import { DialogService } from './global/dialog.service';
3+
import { StateService } from 'ui-router-core';
4+
import { AuthService } from './global/auth.service';
5+
import { AppConfigService } from './global/app-config.service';
26

7+
/**
8+
* This is the main app component for an authenticated user.
9+
*
10+
* This component renders the outermost chrome
11+
* (application header and tabs, the compose and logout button)
12+
* It has a `ui-view` viewport for nested states to fill in.
13+
*/
314
@Component({
415
selector: 'app-root',
516
template: `
6-
<h1>
7-
{{title}}
8-
</h1>
9-
`,
17+
<div #dialogdiv></div>
18+
<div class="navheader">
19+
<ul *ngIf="isAuthenticated" class="nav nav-tabs">
20+
21+
<li uiSrefActive="active"> <a uiSref="mymessages" role="button"> Messages </a> </li>
22+
<li uiSrefActive="active"> <a uiSref="contacts" role="button"> Contacts </a> </li>
23+
<li uiSrefActive="active"> <a uiSref="prefs" role="button"> Preferences </a> </li>
24+
25+
<li class="navbar-right">
26+
<button class="btn btn-primary fa fa-home" uiSref="home"></button>
27+
<button style="margin-right: 15px;" class="btn btn-primary" uiSref="mymessages.compose">
28+
<i class="fa fa-envelope"></i> New Message
29+
</button>
30+
</li>
31+
32+
<li class="navbar-text navbar-right logged-in-user" style="margin: 0.5em 1.5em;">
33+
<div>
34+
{{emailAddress}} <i class="fa fa-chevron-down"></i>
35+
<div class="hoverdrop">
36+
<button class="btn btn-primary" (click)="logout()">Log Out</button>
37+
</div>
38+
</div>
39+
</li>
40+
41+
</ul>
42+
</div>
43+
44+
<ui-view></ui-view>
45+
`
46+
,
1047
styles: []
1148
})
12-
export class AppComponent {
13-
title = 'app works!';
49+
export class AppComponent implements OnInit {
50+
@ViewChild('dialogdiv', {read: ViewContainerRef}) dialogdiv;
51+
52+
// data
53+
emailAddress;
54+
isAuthenticated;
55+
56+
constructor(appConfig: AppConfigService,
57+
public authService: AuthService,
58+
public $state: StateService,
59+
private dialog: DialogService
60+
) {
61+
this.emailAddress = appConfig.emailAddress;
62+
this.isAuthenticated = authService.isAuthenticated();
63+
}
64+
65+
ngOnInit() {
66+
this.dialog.vcRef = this.dialogdiv;
67+
}
68+
69+
show() {
70+
this.dialog.confirm('foo');
71+
}
72+
73+
logout() {
74+
const { authService, $state } = this;
75+
authService.logout();
76+
// Reload states after authentication change
77+
return $state.go('welcome', {}, { reload: true });
78+
}
1479
}

src/app/home.component.ts

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
import { Component, OnInit } from '@angular/core';
2-
2+
// This is a home component for authenticated users.
3+
// It shows giant buttons which activate their respective submodules: Messages, Contacts, Preferences
34
@Component({
45
selector: 'app-home',
56
template: `
6-
<p>
7-
home Works!
8-
</p>
9-
`,
7+
<div class="home buttons">
8+
<button uiSref="mymessages" class="btn btn-primary">
9+
<h1><i class="fa fa-envelope"></i></h1>
10+
<h1>Messages</h1>
11+
</button>
12+
13+
<button uiSref="contacts" class="btn btn-primary">
14+
<h1><i class="fa fa-users"></i></h1>
15+
<h1>Contacts</h1>
16+
</button>
17+
18+
<button uiSref="prefs" class="btn btn-primary">
19+
<h1><i class="fa fa-cogs"></i></h1>
20+
<h1>Preferences</h1>
21+
</button>
22+
</div>
23+
`,
1024
styles: []
1125
})
12-
export class HomeComponent implements OnInit {
13-
26+
export class HomeComponent {
1427
constructor() { }
15-
16-
ngOnInit() {
17-
}
18-
1928
}

src/app/login.component.ts

+94-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,105 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, Input } from '@angular/core';
2+
import { TargetState, StateService } from 'ui-router-core';
3+
import { AuthService } from './global/auth.service';
4+
import { AppConfigService } from './global/app-config.service';
25

6+
/**
7+
* This component renders a faux authentication UI
8+
*
9+
* It prompts for the username/password (and gives hints with bouncy arrows)
10+
* It shows errors if the authentication failed for any reason.
11+
*/
312
@Component({
413
selector: 'app-login',
514
template: `
6-
<p>
7-
login Works!
8-
</p>
9-
`,
15+
<div class="container">
16+
<div class="col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
17+
<h3>Log In</h3>
18+
<p>
19+
(This login screen is for demonstration only...
20+
just pick a username, enter 'password' and click <b>"Log in"</b>)</p>
21+
<hr>
22+
23+
<div>
24+
<label for="username">Username:</label>
25+
<select class="form-control" name="username" id="username"
26+
[(ngModel)]="credentials.username" ng-options="username for username in $ctrl.usernames">
27+
<option *ngFor="let username of usernames" [value]="username">{{username}}</option>
28+
</select>
29+
30+
<i style="position: relative; bottom: 1.8em; margin-left: 10em; height: 0"
31+
[hidden]="credentials.username" class="fa fa-arrow-left bounce-horizontal"> Choose </i>
32+
</div>
33+
<br>
34+
35+
<div>
36+
<label for="password">Password:</label>
37+
<input class="form-control" type="password" name="password" [(ngModel)]="credentials.password">
38+
<i style="position: relative; bottom: 1.8em; margin-left: 5em; height: 0"
39+
[hidden]="!credentials.username || credentials.password == 'password'" class="fa fa-arrow-left bounce-horizontal">
40+
Enter '<b>password</b>' here
41+
</i>
42+
</div>
43+
44+
<div [hidden]="!errorMessage" class="well error">{{ errorMessage }}</div>
45+
46+
<hr>
47+
<div>
48+
<button class="btn btn-primary" type="button" [disabled]="authenticating" (click)="login(credentials)">
49+
<i class="fa fa-spin fa-spinner" [hidden]="!authenticating"></i> <span>Log in</span>
50+
</button>
51+
<i [hidden]="!credentials.username && credentials.password == 'password'"
52+
style="position: relative;" class="fa fa-arrow-left bounce-horizontal"> Click Me!</i>
53+
</div>
54+
</div>
55+
</div>
56+
`,
1057
styles: []
1158
})
12-
export class LoginComponent implements OnInit {
59+
export class LoginComponent {
60+
@Input() returnTo: TargetState;
1361

14-
constructor() { }
62+
usernames: string[];
63+
credentials = { username: null, password: null };
64+
authenticating: boolean;
65+
errorMessage: string;
1566

16-
ngOnInit() {
67+
constructor(appConfig: AppConfigService,
68+
private authService: AuthService,
69+
private $state: StateService
70+
) {
71+
this.usernames = authService.usernames;
72+
73+
this.credentials = {
74+
username: appConfig.emailAddress,
75+
password: 'password'
76+
};
77+
}
78+
79+
/**
80+
* The controller for the `login` component
81+
*
82+
* The `login` method validates the credentials.
83+
* Then it sends the user back to the `returnTo` state, which is provided as a resolve data.
84+
*/
85+
login(credentials) {
86+
this.authenticating = true;
87+
88+
const returnToOriginalState = () => {
89+
const state = this.returnTo.state();
90+
const params = this.returnTo.params();
91+
const options = Object.assign({}, this.returnTo.options(), { reload: true });
92+
this.$state.go(state, params, options);
93+
};
94+
95+
const showError = (errorMessage) =>
96+
this.errorMessage = errorMessage;
97+
98+
const stop = () => this.authenticating = false;
99+
this.authService.authenticate(credentials.username, credentials.password)
100+
.then(returnToOriginalState)
101+
.catch(showError)
102+
.then(stop, stop);
17103
}
18104

19105
}

src/app/welcome.component.ts

+30-6
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,41 @@ import { Component, OnInit } from '@angular/core';
33
@Component({
44
selector: 'app-welcome',
55
template: `
6-
<p>
7-
welcome Works!
8-
</p>
9-
`,
6+
<div class="container-fluid">
7+
8+
<h3>UI-Router Sample App</h3>
9+
10+
<p>Welcome to the sample app!</p>
11+
<p>This is a demonstration app intended to highlight some patterns that can be used within UI-Router.
12+
These patterns should help you to to build cohesive, robust apps. Additionally, this app uses state-vis
13+
to show the tree of states, and a transition log visualizer.</p>
14+
15+
<h4>App Overview</h4>
16+
<p>
17+
First, start exploring the application's functionality at a high level by activating
18+
one of the three submodules: Messages, Contacts, or Preferences. If you are not already logged in,
19+
you will be taken to an authentication screen (the authentication is fake; the password is "password")
20+
</p>
21+
<div>
22+
<button class="btn btn-primary" uiSref="mymessages"><i class="fa fa-envelope"></i><span>Messages</span></button>
23+
<button class="btn btn-primary" uiSref="contacts"><i class="fa fa-users"></i><span>Contacts</span></button>
24+
<button class="btn btn-primary" uiSref="prefs"><i class="fa fa-cogs"></i><span>Preferences</span></button>
25+
</div>
26+
27+
<h4>Patterns and Recipes</h4>
28+
<ul>
29+
<li>Require Authentication</li>
30+
<li>Previous State</li>
31+
<li>Redirect Hook</li>
32+
<li>Default Param Values</li>
33+
</ul>
34+
</div>
35+
`,
1036
styles: []
1137
})
1238
export class WelcomeComponent implements OnInit {
13-
1439
constructor() { }
1540

1641
ngOnInit() {
1742
}
18-
1943
}

0 commit comments

Comments
 (0)