Links

Part 4: The Inbox

Overview

With the core services and components in place, we'll now interface with the ProcessMaker API.
Completed code: live example / download example

Step 1: Environment Details

Ensure you have the subsequent details ready for this section:
  • Client ID
  • Client Secret
  • FQDN for your ProcessMaker installation
  • OAuth Token URL
  • OAuth Redirect URI
  • OAuth Authorization URL
You can see what a sample environment.ts file looks like below. This is where you will add the above information.
environment.ts
export const environment = {
production: false,
apiDomain: 'localhost',
apiPath: '/api/1.0',
apiProtocol: 'http://',
clientId: '19',
clientSecret: 'Psn9cxcGFKO1GO4ZZ9TgOhQtAjt0Wmzjc58vw8Lq',
oauthUrl: 'http://localhost/oauth/token',
redirectUri: 'http://localhost:4200/#/oauth/callback',
oauthAuthorizeUrl: 'http://localhost/oauth/authorize',
customCss: false,
calcProps: true,
};

Step 2: TasksComponent

The TasksComponent relies on the ScreenComponent, which we'll address in the subsequent section. We'll omit it for now and reintroduce it when we're set to render the form.

Template

app-tasks.component.html
<div class="container-fluid">
<div class="table-container mt-4">
<div class="mb-2">
<h2>Your pending tasks</h2>
<h5 class="text-secondary">View your assigned tasks.</h5>
</div>
<table id="mytable" class="table align-middle mb-0 bg-white">
<thead class="bg-light">
<tr class="header-row">
<th>ID #</th>
<th>Task Name</th>
<th>Status</th>
<th>Assignee</th>
<th>Process</th>
<th>Due</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngIf="!userTasks.length">
<td colspan="6">
<p>Loading...</p>
</td>
</tr>
<tr *ngFor="let task of userTasks">
<td>
<p class="fw-bold fw-normal mb-1">{{ task.process_request_id }}</p>
</td>
<td>
<p class="fw-bold fw-normal mb-1">{{ task.element_name }}</p>
</td>
<td>
<div [ngSwitch]="task.advanceStatus">
<span
*ngSwitchCase="'overdue'"
class="badge badge-danger rounded-pill d-inline"
style="text-transform: capitalize"
>{{ task.advanceStatus }}</span
>
<span
*ngSwitchCase="'completed'"
class="badge badge-primary rounded-pill d-inline"
style="text-transform: capitalize"
>{{ task.advanceStatus }}</span
>
<span
*ngSwitchCase="'open'"
class="badge badge-success rounded-pill d-inline"
style="text-transform: capitalize"
>{{ task.advanceStatus }}</span
>
</div>
</td>
<td>{{ task.user.firstname }} {{ task.user.lastname }}</td>
<td>{{ task.process_request.name }}</td>
<td>
<div>
<span>{{ task.due_at }}</span>
</div>
</td>
<td>
<button
(click)="openScreen(task.process_request_id, task.id)"
type="button"
class="btn btn-link btn-sm btn-rounded text-primary">
<i class="me-1 bi-window-sidebar text-primary"></i>
View Task
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>

Typescript

app-tasks.component.ts
// Import necessary Angular core modules
import { Component, OnInit } from '@angular/core';
// Import Angular routing modules
import { ActivatedRoute, Router } from '@angular/router';
// Import services related to ProcessRequests and Tasks
import { ProcessRequestsService, TasksService } from 'api';
// Import local database service
import { DbService } from 'src/app/services/db.service';
// Define the Task interface to represent the structure of a task
interface Task {
process_request_id: string; // ID of the associated process request
element_name: string; // Name of the element
advanceStatus: string; // Status of the task advancement
user: { firstname: string; lastname: string }; // User information
process_request: { name: string }; // Process request information
due_at: string; // Due date for the task
id: string; // Unique ID for the task
}
// Component metadata
@Component({
selector: 'app-tasks', // Selector used in templates
templateUrl: './app-tasks.component.html', // Path to the HTML template
})
// TasksComponent class definition
export class TasksComponent implements OnInit {
// Pagination properties
pagination = {
currentPage: 1, // Current page number
itemsPerPage: 10, // Number of items per page
lastPage: null, // Last page number
totalItems: null, // Total number of items
};
// Selected request and task properties
selectedRequest: Request | null = null;
selectedTask: Task | null = null;
userTasks: Task[] = []; // Array to hold user tasks
color = 'green'; // Color property (usage not shown in provided code)
// Constructor with dependency injection
constructor(
private requestApi: ProcessRequestsService, // Process request service
private tasksApi: TasksService, // Task service
private route: ActivatedRoute, // Activated route information
private router: Router, // Router service for navigation
private db: DbService // Database service
) {}
// ngOnInit lifecycle hook
ngOnInit() {
// Load access token from the database
const accessToken = this.db.load('access_token') as string | undefined;
// If access token exists, set it in the task API configuration
if (accessToken) {
this.tasksApi.configuration.credentials['pm_api_bearer'] = accessToken;
}
// Call getTasks method from tasksApi with parameters null and 'ACTIVE'
this.tasksApi.getTasks(undefined, 'ACTIVE').subscribe(
(response: any) => {
// Handle successful response
this.userTasks = response.data; // Assign user tasks from response data
// Create a new ScreenComponent instance
console.log(this.userTasks);
},
(error) => {
// Handle error response
console.log(error); // Log the error to the console
}
);
}
// Method to open a form with given processRequestId and taskId
openScreen(processRequestId: string, taskId: string) {
// Navigate to the 'form' route with parameters
this.router.navigate([
'screen',
{
processRequestId: processRequestId,
taskId: taskId,
},
]);
}
// Placeholder method for getting a user task by ID
getUserTask(id: string) {}
// Placeholder method for getting user tasks by ID
getUserTasks(id: string) {}
}

Step 3: Update the Router

Integrate the new components and their respective paths into the router. The following code demonstrates how to import these components and establish a route for the inbox view.
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from '../components/login/login.component';
import { TasksComponent } from '../components/tasks/app-tasks.component';
import { AuthGuard } from '../guards/auth.guard';
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
runGuardsAndResolvers: 'always',
title: 'Login',
},
{
path: 'oauth/callback',
component: LoginComponent,
runGuardsAndResolvers: 'always',
},
{
path: 'tasks',
component: TasksComponent,
canActivate: [AuthGuard],
runGuardsAndResolvers: 'always',
title: 'Inbox',
},
{
path: '',
redirectTo: 'tasks',
pathMatch: 'full',
runGuardsAndResolvers: 'always',
},
{
path: '**',
redirectTo: 'tasks',
runGuardsAndResolvers: 'always',
},
];
@NgModule({
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule],
})
export class AppRoutingModule {}

Step 4: Update AppModule

Now we just need to incorporate the TasksComponent into the AppModule declaration.
app.module.ts
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';
import { TasksComponent } from './components/tasks/app-tasks.component';
@NgModule({
declarations: [
RootComponent,
LoginComponent,
NavigationComponent,
AppBreadcrumbsComponent,
TasksComponent,
],
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
CommonModule,
AppRoutingModule,
],
providers: [],
bootstrap: [RootComponent],
})
export class AppModule {}

Review

If you are following along with the tutorial, you should now be able to see your tasks, in your new Angular Inbox!
Angular Inbox for ProcessMaker

Next Steps

Last modified 5mo ago