Methods
|
Public
download
|
download(id: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| id |
any
|
No
|
|
|
Public
getApprIndex
|
getApprIndex(historyItem: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| historyItem |
any
|
No
|
|
|
Public
getBaseTable
|
getBaseTable(baseTable: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| baseTable |
any
|
No
|
|
|
Public
getEditTable
|
getEditTable(editTable: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| editTable |
any
|
No
|
|
|
Public
getTable
|
getTable(table_id: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| table_id |
any
|
No
|
|
|
Async
loadData
|
loadData()
|
|
|
|
|
|
Async
ngOnInit
|
ngOnInit()
|
|
|
|
|
|
Public
approveData
|
Type : any
|
Default value : {}
|
|
|
|
Public
baseTableFilter
|
Type : unknown
|
Default value : new BaseTableFilter()
|
|
|
|
Public
history
|
Type : Array<any>
|
Default value : []
|
|
|
|
Public
historyArr
|
Type : Array<any>
|
Default value : []
|
|
|
|
Public
histParams
|
Type : { HIST: number; STARTROW: number; NOBS: number }
|
Default value : {
HIST: 0,
STARTROW: 1,
NOBS: -1
}
|
|
|
|
Public
Infinity
|
Type : unknown
|
Default value : Infinity
|
|
|
|
Public
itemsNum
|
Type : number
|
Default value : 10
|
|
|
|
Public
licenceState
|
Type : unknown
|
Default value : this.licenceService.licenceState
|
|
|
|
Public
loaded
|
Type : boolean
|
Default value : false
|
|
|
|
Public
loadingMore
|
Type : boolean
|
Default value : false
|
|
|
|
Public
noData
|
Type : boolean
|
Default value : false
|
|
|
|
Public
openModal
|
Type : boolean
|
Default value : false
|
|
|
|
Public
reviewedFilter
|
Type : unknown
|
Default value : new ReviewedFilter()
|
|
|
|
Public
sasjsConfig
|
Type : SASjsConfig
|
Default value : new SASjsConfig()
|
|
|
|
Public
statusFilter
|
Type : unknown
|
Default value : new StatusFilter()
|
|
|
|
Public
submitReasonFilter
|
Type : unknown
|
Default value : new SubmitReasonFilter()
|
|
|
|
Public
submittedFilter
|
Type : unknown
|
Default value : new SubmittedFilter()
|
|
|
|
Public
submitterFilter
|
Type : unknown
|
Default value : new SubmitterFilter()
|
|
|
|
Public
tableTitles
|
Type : Array<any>
|
Default value : []
|
|
|
Accessors
|
rowsLeftToLoad
|
getrowsLeftToLoad()
|
|
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
import { Router } from '@angular/router'
import { SASjsConfig } from '@sasjs/adapter'
import {
LicenceService,
SasStoreService,
EventService,
SasService
} from 'src/app/services'
import { ClrDatagridStringFilterInterface } from '@clr/angular'
interface HistoryData {
tableId: string
basetable: string
status: string
submitter: string
submittedReason: string
submitted: string
reviewed: string
}
class BaseTableFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.basetable.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
class StatusFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.status.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
class SubmitterFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.submitter.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
class SubmitReasonFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.submittedReason.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
class SubmittedFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.submitted.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
class ReviewedFilter implements ClrDatagridStringFilterInterface<HistoryData> {
accepts(data: HistoryData, search: string): boolean {
return data.reviewed.toLowerCase().indexOf(search.toLowerCase()) >= 0
}
}
@Component({
selector: 'app-history',
templateUrl: './history.component.html',
styleUrls: ['./history.component.scss'],
host: {
class: 'content-container'
},
encapsulation: ViewEncapsulation.None,
standalone: false
})
export class HistoryComponent implements OnInit {
public history: Array<any> = []
public tableTitles: Array<any> = []
public historyArr: Array<any> = []
public loaded: boolean = false
public itemsNum: number = 10
public openModal: boolean = false
public noData: boolean = false
public approveData: any = {}
public sasjsConfig: SASjsConfig = new SASjsConfig()
// Filter instances for datagrid accessibility
public baseTableFilter = new BaseTableFilter()
public statusFilter = new StatusFilter()
public submitterFilter = new SubmitterFilter()
public submitReasonFilter = new SubmitReasonFilter()
public submittedFilter = new SubmittedFilter()
public reviewedFilter = new ReviewedFilter()
public histParams: { HIST: number; STARTROW: number; NOBS: number } = {
HIST: 0,
STARTROW: 1,
NOBS: -1
}
public loadingMore: boolean = false
public licenceState = this.licenceService.licenceState
public Infinity = Infinity
constructor(
private licenceService: LicenceService,
private sasStoreService: SasStoreService,
private eventService: EventService,
private router: Router,
private sasService: SasService
) {
this.sasjsConfig = this.sasService.getSasjsConfig()
}
public getTable(table_id: any) {
this.router.navigateByUrl('/stage/' + table_id)
}
public getBaseTable(baseTable: any) {
this.router.navigateByUrl('/view/data/' + baseTable)
}
public getEditTable(editTable: any) {
this.router.navigateByUrl('/editor/' + editTable)
}
public getApprIndex(historyItem: any) {
const historyItemIndex = this.historyArr.findIndex(
(itm: any) => itm.TABLE_ID === historyItem.tableId
)
if (historyItemIndex > -1) {
this.approveData = this.historyArr[historyItemIndex]
this.openModal = true
}
}
public get rowsLeftToLoad() {
const rowsLeft = this.histParams.NOBS - this.history.length
const rowsInStep = this.histParams.HIST
if (rowsLeft <= 0) return 0
if (rowsLeft > rowsInStep) return rowsInStep
return rowsLeft
}
public download(id: any) {
let sasjsConfig = this.sasService.getSasjsConfig()
let storage = sasjsConfig.serverUrl
let metaData = sasjsConfig.appLoc
let path = this.sasService.getExecutionPath()
let downUrl =
storage +
path +
'/?_program=' +
metaData +
'/services/auditors/getauditfile&table=' +
id +
'&_contextname=' +
this.sasjsConfig.contextName
window.open(downUrl)
}
async loadData() {
let histParams = {
STARTROW: this.histParams.HIST + this.histParams.STARTROW
}
this.loadingMore = true
try {
let res = await this.sasStoreService.getHistory(
histParams,
'BrowserParams',
'approvers/gethistory'
)
this.loadingMore = false
this.histParams = res.histparams[0]
let tableTitles: Array<any>
const fromsas = res.fromsas.slice(
0,
this.licenceState.value.history_rows_allowed
)
if (fromsas.length > 0) {
const arr = fromsas
this.historyArr = fromsas
tableTitles = Object.keys(arr[0])
this.tableTitles = tableTitles
let historyTable = fromsas.map(function (item: any) {
return {
tableId: item.TABLE_ID,
submitter: item.SUBMITTER,
submittedReason: item.SUBMITTED_REASON_TXT,
submitted: item.SUBMITTED,
status: item.STATUS,
reviewReason: item.REVIEW_REASON_TXT,
reviewer: item.REVIEWER,
reviewed: item.REVIEWED,
numOfApprovals: item.NUM_OF_APPROVALS_REQUIRED,
basetable: item.BASE_TABLE
}
})
this.history.push(...historyTable)
this.loaded = true
} else {
this.loaded = true
if (this.history.length === 0) this.noData = true
}
} catch (error) {
this.eventService.catchResponseError('approvers/gethistory', error)
this.loadingMore = false
}
}
async ngOnInit() {
this.loadData()
}
}
<div class="content-area">
@if (noData) {
<div
id="noDataContainer"
class="card-block d-flex justify-content-center flex-column align-items-center"
>
<clr-icon shape="warning-standard" size="60" class="is-info"></clr-icon>
<h3 class="text-center color-gray">There is no history to show</h3>
</div>
}
<clr-modal [(clrModalOpen)]="openModal" [clrModalSize]="'xl'">
<h4 class="modal-title">Approval details</h4>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th class="left">Name</th>
<th class="left">Value</th>
</tr>
</thead>
<tbody>
@for (col of tableTitles; track col; let ind = $index) {
<tr>
<td class="left">{{ col }}</td>
<td class="left">
@if (ind < 1) {
<a
(click)="getTable(approveData[col])"
class="cursor-pointer table-link"
>{{ approveData[col] }}</a
>
}
@if (ind < 2 && ind >= 1) {
<div>
<a
(click)="getBaseTable(approveData[col])"
class="cursor-pointer table-link"
>VIEW</a
>
<span> / </span>
<a
(click)="getEditTable(approveData[col])"
class="cursor-pointer table-link"
>EDIT</a
>
</div>
}
@if (ind >= 2) {
<span>{{ approveData[col] }}</span>
}
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
<button
type="button"
aria-label="Close modal"
class="btn btn-outline"
(click)="openModal = false"
>
OK
</button>
</div>
</clr-modal>
@if (!loaded) {
<div
class="h-70vh d-flex justify-content-center flex-column align-items-center"
>
@if (!loaded) {
<span class="spinner"> Loading... </span>
}
@if (!loaded) {
<div>
<h3>Loading history</h3>
</div>
}
</div>
}
@if (!noData && loaded) {
<div class="card">
<div class="card-header">
@if (loaded) {
<h3 class="center clr-col-md-12 text-center">HISTORY</h3>
}
@if (licenceState.value.history_rows_allowed !== Infinity) {
<p class="text-center font-weight-700 color-dark-gray">
To unlock more than
{{ licenceState.value.history_rows_allowed }} records, contact
support@datacontroller.io
</p>
}
</div>
@if (loaded) {
<clr-datagrid class="datagrid-history datagrid-custom-footer">
<clr-dg-column [clrDgField]="'basetable'">
BASE_TABLE
<clr-dg-string-filter
[clrDgStringFilter]="baseTableFilter"
aria-label="Filter base table"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column [clrDgField]="'status'">
STATUS
<clr-dg-string-filter
[clrDgStringFilter]="statusFilter"
aria-label="Filter status"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column [clrDgField]="'submitter'">
SUBMITTER
<clr-dg-string-filter
[clrDgStringFilter]="submitterFilter"
aria-label="Filter submitter"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column [clrDgField]="'submittedReason'">
SUBMIT REASON
<clr-dg-string-filter
[clrDgStringFilter]="submitReasonFilter"
aria-label="Filter submit reason"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column [clrDgField]="'submitted'">
SUBMITTED
<clr-dg-string-filter
[clrDgStringFilter]="submittedFilter"
aria-label="Filter submitted date"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column [clrDgField]="'reviewed'">
APPROVED / REJECTED
<clr-dg-string-filter
[clrDgStringFilter]="reviewedFilter"
aria-label="Filter reviewed date"
></clr-dg-string-filter>
</clr-dg-column>
<clr-dg-column>DOWNLOAD</clr-dg-column>
<clr-dg-row
*clrDgItems="let historyItem of history"
(click)="getApprIndex(historyItem)"
>
<clr-dg-cell class="verCenter">
<a
class="btn btn-sm btn-link m-0"
(click)="getBaseTable(historyItem.basetable)"
>{{ historyItem.basetable }}</a
>
</clr-dg-cell>
<clr-dg-cell
class="verCenter"
[ngClass]="{
rejected: historyItem.status === 'REJECTED',
accepted: historyItem.status === 'APPROVED'
}"
>{{ historyItem.status }}</clr-dg-cell
>
<clr-dg-cell class="verCenter">{{
historyItem.submitter
}}</clr-dg-cell>
<clr-dg-cell class="verCenter">{{
historyItem.submittedReason
}}</clr-dg-cell>
<clr-dg-cell class="verCenter">{{
historyItem.submitted
}}</clr-dg-cell>
<clr-dg-cell class="verCenter">{{
historyItem.reviewed
}}</clr-dg-cell>
<clr-dg-cell class="verCenter p-0 d-flex justify-content-center">
<button
aria-label="Download audit file"
class="btn btn-success"
(click)="
download(historyItem.tableId); $event.stopPropagation()
"
>
<clr-icon shape="download"></clr-icon>
</button>
</clr-dg-cell>
</clr-dg-row>
<!-- Let's keep this part if in future we decide to do the paging instead of `load more` approach -->
<!-- <clr-dg-footer class="d-flex justify-content-start">
<span>items per page</span>
<select class="mx-5" [(ngModel)]="itemsNum">
<option [ngValue]="3">3</option>
<option [ngValue]="5">5</option>
<option [ngValue]="10">10</option>
<option [ngValue]="15">15</option>
</select>
<clr-dg-pagination
#pagination
[clrDgPageSize]="itemsNum"
class="center"
>
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }} of
{{ pagination.totalItems }} updates
</clr-dg-pagination>
</clr-dg-footer> -->
</clr-datagrid>
}
<div
class="load-more d-flex clr-justify-content-center clr-align-items-center"
>
@if (
this.licenceState.value.history_rows_allowed === Infinity &&
rowsLeftToLoad > 0
) {
<button
(click)="loadData()"
[clrLoading]="loadingMore"
class="btn btn-success"
>
Load {{ rowsLeftToLoad }} more
</button>
}
</div>
</div>
}
</div>
Legend
Html element with directive