Skip to content

Commit

Permalink
Merge pull request #1 from karbasia/feature/reports
Browse files Browse the repository at this point in the history
Expose report API
  • Loading branch information
karbasia authored Mar 6, 2024
2 parents 5e419e0 + cda1276 commit c102c4b
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 42 deletions.
3 changes: 3 additions & 0 deletions src/Client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Auth from "@/services/Auth";
import Model from "@/services/Model";
import Report from "@/services/Report";
import AppConfig, { WebAppProperties } from "@/services/utils/AppConfig";

/**
Expand All @@ -10,6 +11,7 @@ export default class Client {

auth!: Auth;
model!: Model;
report!: Report;

/** @hidden */
constructor(appConfig: AppConfig) {
Expand Down Expand Up @@ -37,6 +39,7 @@ export default class Client {

client.auth = new Auth(appConfig, useCredentials);
client.model = new Model(appConfig, client.auth);
client.report = new Report(appConfig, client.auth);

if (useCredentials) {
await client.model.Init();
Expand Down
12 changes: 12 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ import {
MonthlyRecurrence,
YearlyRecurrence,
} from "@/services/utils/helpers/Recurrence";
import Report, {
ReportListResults,
ReportData,
ReportListFilters,
ReportDetails,
} from "@/services/Report";

import Client from "@/Client";

export {
Expand Down Expand Up @@ -57,6 +64,11 @@ export {
User,
UpdateRecordResponse,
CreateRecordResponse,
ReportListResults,
ReportData,
ReportDetails,
ReportListFilters,
Report,
};

export default Client;
18 changes: 17 additions & 1 deletion src/services/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,29 @@ export default class Auth {
}
}

/**
* Simple method for generating a redirect URL for the frontend.
*
* @remarks
* Used with frontend frameworks to redirect the user to the login URL. Once authenticated, they will return to their previous page.
* This flow is also supported by SSO-enabled environments.
*
* @param url The page that the user should be redirected to after a successful authentication.
* @returns The full URL that the user should be redirected for reauthentication.
*/
generateLoginUrl(url: string) {
return `${
this.appConfig.tririgaUrl
}/p/websignon?redirectUrl=${encodeURIComponent(url)}`;
}

/**
* A helper method for building the basic request options object.
*
* @remarks
* This method is used to append the required cookie and useCredentials values to the request options.
*
* @param additionalOptions Custom request options from the caller
* @param additionalOptions Custom request options from the caller.
* @returns A `RequestInit` object with the required headers and user specified options.
*/
generateRequestHeaders(additionalOptions?: RequestInit): RequestInit {
Expand Down
115 changes: 74 additions & 41 deletions src/services/Query.ts → src/services/Report.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Auth from "./Auth";
import AppConfig from "./utils/AppConfig";

interface QueryDetails {
export interface ReportDetails {
formId: number;
reportId: number;
moduleName: string;
Expand All @@ -13,8 +13,8 @@ interface QueryDetails {
boNames: string;
}

export interface QueryListResults {
data?: QueryDetails[];
export interface ReportListResults {
data?: ReportDetails[];
totalPageCount: number;
resultsPerPage: number;
hasNextPage: boolean;
Expand All @@ -23,17 +23,17 @@ export interface QueryListResults {
totalCount: number;
}

interface QueryColumnDefinitions {
interface ReportColumnDefinitions {
[key: string]: unknown;
}

export interface QueryMetadata {
columnDefinitions: QueryColumnDefinitions[];
export interface ReportMetadata {
columnDefinitions: ReportColumnDefinitions[];
}

export interface QueryData {
export interface ReportData {
data: { [key: string]: string }[];
headers: QueryColumnDefinitions[];
headers: ReportColumnDefinitions[];
hasNext: boolean;
hasPrevious: boolean;
pageNumber: number;
Expand All @@ -42,8 +42,20 @@ export interface QueryData {
totalSize: number;
}

/** Platform 4.2+.The Query class is used to retrieve and execute TRIRIGA queries. */
export default class Query {
export interface ReportListFilters {
title?: string;
name?: string;
tag?: string;
moduleId?: string;
moduleIdName?: string;
boId?: string;
boIdName?: string;
formId?: string;
formIdName?: string;
}

/** Platform 4.2+. The Report class is used to retrieve and execute TRIRIGA queries. */
export default class Report {
appConfig: AppConfig;
auth: Auth;

Expand All @@ -59,24 +71,29 @@ export default class Query {
* @remarks
* An async function that returns the results of system reports. The authenticated user must have access to system reports to view this data.
*
* @param pageNumber The current page number
* @param pageNumber The current page number as a zero-based value
* @param perPage The total number of reports per page
* @returns A `QueryListResults` object with the query details
* @param filters The object that is used to filter the result set
* @returns A `ReportListResults` object with the report details
*
* @throws Error if the query list could not be retrieved. This is caused by connectivity, session or user permission issues.
*/
async getQueryList(
pageNumber: number,
perPage: number
): Promise<QueryListResults> {
pageNumber: number = 0,
perPage: number = 50,
filters?: ReportListFilters
): Promise<ReportListResults> {
// Ensure that the CSRF Token is still valid
if (await this.auth.updateCsrfToken()) {
const queryParams = {
objectId: "1200000",
actionId: "1200501",
managerReportType: "SystemReport",
_: "",
reportType: "-1",
currentPageNumber: pageNumber.toString(),
noOfReports: perPage.toString(),
...filters,
};

const headers: HeadersInit = {};
Expand All @@ -97,36 +114,36 @@ export default class Query {
if (req.ok) {
const resp = await req.json();
if (resp.length > 1) {
const results: QueryListResults = {
const results: ReportListResults = {
totalPageCount: resp[1].TotalNumberOfPages,
resultsPerPage: resp[1].ResultsPerPage,
hasNextPage: resp[1].IsNext,
hasPreviousPage: resp[1].IsPrevious,
currentPageNumber: resp[1].currentPageNumber,
totalCount: resp[1].TotalResultCnt,
data: resp[0] as QueryDetails[],
data: resp[0] as ReportDetails[],
};
return results;
}
}
}

throw new Error("Could not retrieve query list");
throw new Error("Could not retrieve report list");
}

/**
* Retrieves the query metadata
* Retrieves the report metadata
*
* @remarks
* The query metadata will contain details surrounding the columns.
* The report metadata will contain details surrounding the columns.
*
* @param templateId The unique query ID
* @returns A `QueryMetadata` object
* @param templateId The unique report ID
* @returns A `ReportMetadata` object
*
* @throws Error if the query is not found or if the client encounters connectivity issues.
* @throws Error if the report is not found or if the client encounters connectivity issues.
*/
async getQueryDefinition(templateId: number): Promise<QueryMetadata> {
const queryMetadata: QueryMetadata = { columnDefinitions: [] };
async getReportDefinition(templateId: number): Promise<ReportMetadata> {
const reportMetadata: ReportMetadata = { columnDefinitions: [] };
const reqOptions = this.auth.generateRequestHeaders();
const urlParams = new URLSearchParams({
reportTemplId: templateId.toString(),
Expand All @@ -142,35 +159,35 @@ export default class Query {
throw new Error(resp["error_message"]);
}
if (resp["gridConfig"] && resp["gridConfig"]["columns"].length > 0) {
queryMetadata.columnDefinitions = resp["gridConfig"]["columns"];
reportMetadata.columnDefinitions = resp["gridConfig"]["columns"];
}
return queryMetadata;
return reportMetadata;
}

throw new Error("Could not determine query metadata");
throw new Error("Could not determine report metadata");
}

/**
* Returns the query data for a specific page.
* Returns the report data for a specific page.
*
* @remarks
* This method is used to retrieve data from a specific query. It will return an object that contains the data with the defined columns.
* This method is used to retrieve data from a specific report. It will return an object that contains the data with the defined columns.
*
* @param templateId The unique query ID
* @param templateId The unique report ID
* @param pageNumber The current page number
* @param pageSize The page size
* @returns A `QueryData` object containing record details for the current page.
* @returns A `ReportData` object containing record details for the current page.
*
* @throws Error if the input is invalid or if the client encounters connectivity issues.
*/
async getQueryData(
async getReportData(
templateId: number,
pageNumber = 0,
pageSize = 50
): Promise<QueryData> {
const queryMetadata = await this.getQueryDefinition(templateId);
): Promise<ReportData> {
const reportMetadata = await this.getReportDefinition(templateId);

if (queryMetadata.columnDefinitions.length > 0) {
if (reportMetadata.columnDefinitions.length > 0) {
const reqOptions = this.auth.generateRequestHeaders();
const urlParams = new URLSearchParams({
reportTemplId: templateId.toString(),
Expand All @@ -184,22 +201,38 @@ export default class Query {

if (req.ok) {
const resp = await req.json();
const queryData: QueryData = {
const reportData: ReportData = {
data: resp["data"],
headers: queryMetadata.columnDefinitions,
headers: reportMetadata.columnDefinitions,
hasNext: resp["result_has_next"],
hasPrevious: resp["result_has_previous"],
pageNumber: resp["result_page_number"],
totalPages: resp["result_total_pages"],
resultSize: resp["result_count"],
totalSize: resp["result_total_size"],
};
return queryData;
return reportData;
}

throw new Error("Could not retrieve query data");
throw new Error("Could not retrieve report data");
}

throw Error("Invalid query metadata");
throw Error("Invalid report metadata");
}

// private generateReportFilterObject(
// input: ReportListFilters = {}
// ): ReportListFilters {
// const filters = input;

// if (filters.formIdName && !filters.formId) {
// filters.formId = "-1";
// }

// if (filters.moduleIdName && !filters.moduleId) {
// filters.moduleId = "";
// }

// return filters;
// }
}

0 comments on commit c102c4b

Please sign in to comment.