# Part 3: Components

## Overview

In this section, we'll explore the essential components of our application.

Completed code: [live example](https://stackblitz.com/edit/stackblitz-starters-xl3eaa) / [download example](https://github.com/ProcessMaker/angular4pm/tree/part-3/src)

* [The Router](#step-1-the-router) _(not technically a component but necessary)_
* [RootComponent](#step-2-rootcomponent)
* [LoginComponent](#step-2-logincomponent)
* [NavigationComponent](#step-3-navigationcomponent)
* [AppBreadCrumbsComponent](#app-breadcrumbs.component.html)

## Step 1: The Router

Before adding our components, we must configure the router and verify user authentication using our Guard.

Here is the updated code for the router.

{% hint style="info" %}
The `oauth/callback` path is crucial for the OAuth 2.0 Authorization Flow.
{% endhint %}

### Typescript

<details>

<summary><code>app-routing.module.ts</code></summary>

{% code overflow="wrap" %}
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from '../components/login/login.component';

const routes: Routes = [
	{
		path: 'login',
		component: LoginComponent,
		runGuardsAndResolvers: 'always',
		title: 'Login',
	},
	{
		path: 'oauth/callback',
		component: LoginComponent,
		runGuardsAndResolvers: 'always',
	},
	{
		path: '',
		redirectTo: 'tasks',
		pathMatch: 'full',
		runGuardsAndResolvers: 'always',
	},
	{
		path: '**',
		redirectTo: 'tasks',
		runGuardsAndResolvers: 'always',
	},
];

@NgModule({
	imports: [RouterModule.forRoot(routes, { useHash: true })],
	exports: [RouterModule],
})
export class AppRoutingModule {}

```
{% endcode %}

</details>

The application will crash at this point, but that's ok! This is expected. We will fix it in a moment.

## Step 2: RootComponent

Until now, we've used the default `hello world` template at `src/app/components/app.component.ts`. We'll remove this file, replacing it with the root component.

{% hint style="info" %}
If you check the `index.html` file, you will see that there is an element `app-root` which is where the application will be embedded within.
{% endhint %}

Note how we have three new components in the root component.

* `app-navigation` is where the top nav bar will be inserted.
* `app-breadcrumbs` will show where you are in the application, right below the nav bar but above the main content section.
* `router-outlet` is where the Angular router will inject the rest of the components dynamically, based on the logic we implement.

### Template

<details>

<summary><code>app-root.component.html</code></summary>

```html
<div class="main container-fluid">
	<app-navigation></app-navigation>
	<app-breadcrumbs></app-breadcrumbs>
	<router-outlet></router-outlet>
</div>

```

</details>

### Typescript

<details>

<summary><code>app-root.component.ts</code></summary>

```typescript
import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	templateUrl: './app-root.component.html',
})
export class AppComponent {
	title = 'pm4Angular';

	constructor() {}
}

```

</details>

## Step 2: LoginComponent

Let's craft our inaugural component: the login page. The flow will use Authorization Code `grant_type`. This will redirect the user to the ProcessMaker installation you created the client application in, where they login and are then redirected back to the application with the authorization code.

{% hint style="info" %}
The components we will be creating will consist of two files: the template file and the typescript file.
{% endhint %}

### Template

<details>

<summary><code>login.component.html</code></summary>

{% code overflow="wrap" %}
```html
<div class="main">
	<div class="row g-0">
		<div class="col">
			<div class="leftside">
				<div class="left-main">
					<div class="logo-container d-flex">
						<img
							class="mb-4"
							alt="ProcessMaker"
							src="/assets/img/PMLogo-png.webp"
							alt="" />
					</div>
					<div
						class="header-container mt-5 d-flex justify-content-center flex-column">
						<div class="title mt-3">
							<h2>Quickly preview your form tasks and screens.</h2>
						</div>

						<div class="button-text-container">
							<div class="sub-title mt-4">
								<h5 class="sub text-secondary mt-1">
									Welcome! Please login with your ProcessMaker credentials.
								</h5>

								<div class="button-container mt-4">
									<button
										(click)="login()"
										class="btn btn-primary btn-login w-100">
										Login with ProcessMaker
									</button>
									<hr class="divider mt-4" />
								</div>
							</div>
							<div class="">
								<small class="sub"
									>👋 <a class="link" href="#">Learn more</a> about
									ProcessMaker.</small
								>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		<div class="col">
			<div class="rightside">
				<div class="right-main">
					<div class="text-block">
						<h1>Automate</h1>
						<h1>Complex</h1>
						<h1>Workflows</h1>
					</div>
					<div class="square"></div>
				</div>
			</div>
		</div>
	</div>
</div>

```
{% endcode %}

</details>

### Typescript

<details>

<summary><code>login.component.ts</code></summary>

{% code overflow="wrap" %}
```typescript
import { Component, OnInit } from '@angular/core';
import { AuthService } from 'src/app/services/auth.service';
import { ActivatedRoute } from '@angular/router';

@Component({
	selector: 'app-login',
	templateUrl: './login.component.html',
})
export class LoginComponent implements OnInit {
	// Injecting AuthService and ActivatedRoute to handle authentication and route parameters
	constructor(
		public authService: AuthService,
		private activatedRoute: ActivatedRoute
	) {}

	ngOnInit() {
		// Subscribing to query parameters to detect the authorization code
		this.activatedRoute.queryParams.subscribe((params) => {
			// Checking if the 'code' parameter is present
			if (params['code']) {
				// Calling getAccessToken method in AuthService to handle the OAuth token exchange
				// No need for then or catch here as the AuthService method takes care of the response handling
				this.authService.getAccessToken(params['code']);
			}
		});
	}

	// Method to initiate the login process by calling the login method in AuthService
	login() {
		this.authService.login();
	}

	// Method to initiate the logout process by calling the logout method in AuthService
	logout() {
		this.authService.logout();
	}
}

```
{% endcode %}

</details>

## Step 3: NavigationComponent

The navigation component houses the header logo and a logout button.

The `ngIf="authService.authenticated"` ensures the navbar displays only when the user is authenticated using our auth service.

### Template

<details>

<summary><code>navigation.component.html</code></summary>

{% code overflow="wrap" %}
```html
<nav
	*ngIf="authService.authenticated"
	class="header-container d-flex justify-content-between table-container navbar navbar-light bg-light">
	<a style="all: unset; cursor: pointer" routerLink="/tasks">
		<div class="header-text-container d-flex flex-row align-items-end">
			<img src="/assets/img/PMLOGO.png" alt="" style="height: 87px" />
			<h1 class="display-4">ProcessMaker</h1>
		</div>
	</a>
	<div class="header-text-container mt-6 d-flex align-items-end">
		<button (click)="logout()" class="btn btn-danger btn-login w-100">
			<i class="me-1 text-light bi bi-arrow-left-right"></i> Log Out
		</button>
	</div>
</nav>

```
{% endcode %}

</details>

### Typescript

<details>

<summary><code>navigation.component.ts</code></summary>

```typescript
import { Component } from '@angular/core';
import { AuthService } from 'src/app/services/auth.service';
import { DbService } from 'src/app/services/db.service';
import { ActivatedRoute, Router } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';

@Component({
	selector: 'app-navigation',
	templateUrl: './navigation.component.html',
})
export class NavigationComponent {
	title: any;
	homeCrumb: any;
	currentCrumb: any;
	constructor(
		public authService: AuthService,
		public db: DbService,
		public route: ActivatedRoute,
		public router: Router,
		public browserModule: BrowserModule
	) {}

	// Method to log out the user by calling the logout method from the AuthService
	logout() {
		this.authService.logout();
	}
}

```

</details>

## Step 4: AppBreadCrumbsComponent

### Template

<details>

<summary><code>app-breadcrumbs.component.html</code></summary>

```html
<nav
	class="pt-2 rounded-corners"
	*ngIf="authService.authenticated"
	aria-label="breadcrumb">
	<ol class="breadcrumb">
		<li class="breadcrumb-item">
			<a href="">{{ homePageTitle() }}</a>
		</li>
		<li class="breadcrumb-item active" aria-current="page">
			{{ currentPageTitle() }}
		</li>
	</ol>
</nav>

```

</details>

### Typescript

<details>

<summary><code>app-breadcrumbs.component.ts</code></summary>

```typescript
import { Component, OnInit } from '@angular/core';
import { AuthService } from 'src/app/services/auth.service';
import { DbService } from 'src/app/services/db.service';
import { ActivatedRoute, Router } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
@Component({
	selector: 'app-breadcrumbs',
	templateUrl: './app-breadcrumbs.component.html',
})
export class AppBreadcrumbsComponent implements OnInit {
	title: any;
	homeCrumb: any;
	currentCrumb: any;
	constructor(
		public authService: AuthService,
		public db: DbService,
		public route: ActivatedRoute,
		public router: Router,
		public browserModule: BrowserModule
	) {}

	ngOnInit(): void {}
	currentPageTitle() {
		return (this.title = window.document.title);
	}
	homePageTitle() {
		return (this.homeCrumb = 'Home');
	}
}

```

</details>

## Step 5: AppModule

The updated `app.module.ts` contains the dependencies:

* Router
* RootComponent
* LoginComponent
* NavigationComponent
* AppBreadCrumbsComponent

<details>

<summary><code>app.module.ts</code></summary>

```typescript
import { NgModule } from '@angular/core';
import '@angular/compiler';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { AppRoutingModule } from './routing/app-routing.module';
import { RootComponent } from './components/root/app-root.component';
import { LoginComponent } from './components/login/login.component';
import { NavigationComponent } from './components/nav/navigation.component';
import { AppBreadcrumbsComponent } from './components/breadcrumbs/app-breadcrumbs.component';

@NgModule({
	declarations: [
		RootComponent,
		LoginComponent,
		NavigationComponent,
		AppBreadcrumbsComponent,
	],
	imports: [
		BrowserModule,
		HttpClientModule,
		FormsModule,
		ReactiveFormsModule,
		CommonModule,
		AppRoutingModule,
	],
	providers: [],
	bootstrap: [RootComponent],
})
export class AppModule {}
```

</details>

## Review

By following the steps, navigating to `http://localhost:4200/#/login` should display the login page.

<figure><img src="https://1243566085-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPyTHGwZ0VereJkRNmGxE%2Fuploads%2FwSt4riFcJN0Nq3F8J0mL%2Fimage.png?alt=media&#x26;token=7063d322-a0fd-4de4-b213-4d68113f4238" alt=""><figcaption><p>Login</p></figcaption></figure>

With the correct OAuth credentials and Client Application setup, logging into ProcessMaker should redirect you back to the login page, now displaying the navbar and breadcrumbs, indicating a successful login.

<figure><img src="https://1243566085-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FPyTHGwZ0VereJkRNmGxE%2Fuploads%2FAZduOpycqtsNWAMnxBhy%2Fimage.png?alt=media&#x26;token=a0d22a86-3fc2-46a8-adab-00cb20d7e84d" alt=""><figcaption><p>navbar authenticated</p></figcaption></figure>

## Next Steps

{% content-ref url="part-4-the-inbox" %}
[part-4-the-inbox](part-4-the-inbox)
{% endcontent-ref %}
