ProcessMaker Developers Documentation
processmaker.comKnowledge CenterProcessMaker University
Guides
Guides
  • Getting Started
    • Installing ProcessMaker
  • Authentication
    • Creating a Client Application
    • Getting an Access Token
    • Getting a Refresh Token
  • Working with the API
    • Starting a Request via REST API
    • Starting a Request via Web Hook
  • Embedding Forms
    • Starting a Request via Anonymous Web Entry
    • Participating in a Workflow via Intermediate Web Entry (Anonymous)
    • Participating in a workflow via Intermediate Web Entry (Authenticated)
    • Angular Inbox Tutorial
      • Part 0: Overview
      • Part 1: Hello World
      • Part 2: Services & Dependencies
      • Part 3: Components
      • Part 4: The Inbox
      • Part 5: The Screen & Form Elements
  • Script Task Examples
    • PHP
  • Packages
    • ProcessMaker Platform Packages
      • Actions By Email Package
      • Advanced Screens Package
      • Advanced User Package
      • Auth Package
      • C# Package
      • Collections Package
      • Comments Package
      • Conversational Forms Package
      • Data Connector Package
      • Decision Tables Package
      • Documentation Package
      • DocuSign Package
      • Dynamic UI Package
      • File Manager Package
      • Google Places Package
      • IDP Package
      • Java Package
      • PDF Generator Package
      • PM Blocks Package
      • Process Optimization Package
      • Python Package
      • R Package
      • Saved Searches Package
      • Send Email Package
      • Signature Package
      • Slack Notification Package
      • Translations Package
      • Versioning Package
      • Vocabularies Package
      • Web Entry Package
    • Custom Packages
      • The Package Skeleton
      • Creating Your First ProcessMaker Package
Powered by GitBook
On this page
  • Overview
  • Step 1: Environment Details
  • Step 2: TasksComponent
  • Template
  • Typescript
  • Step 3: Update the Router
  • Step 4: Update AppModule
  • Review
  • Next Steps
  1. Embedding Forms
  2. Angular Inbox Tutorial

Part 4: The Inbox

Last updated 1 year ago

Overview

With the core services and components in place, we'll now interface with the ProcessMaker API.

Completed code: /

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!

Next Steps

live example
download example
Part 5: The Screen & Form Elements
Angular Inbox for ProcessMaker