src/app/review/approve-details/approve-details.component.ts
| encapsulation | ViewEncapsulation.None |
| host | { |
| selector | app-approve-details |
| styleUrls | ./approve-details.component.scss |
| templateUrl | ./approve-details.component.html |
Properties |
|
Methods |
|
Accessors |
constructor(sasStoreService: SasStoreService, sasService: SasService, eventService: EventService, router: ActivatedRoute, route: Router)
|
||||||||||||||||||
|
Parameters :
|
| Public Async approveTable |
approveTable()
|
|
Returns :
any
|
| Public calcDiff |
calcDiff()
|
|
Returns :
void
|
| Public Async callChangesInfo | ||||||
callChangesInfo(tableId: any)
|
||||||
|
Parameters :
Returns :
any
|
| Public formattingChanged |
formattingChanged()
|
|
Returns :
void
|
| Public getDetails |
getDetails()
|
|
Returns :
void
|
| Public getTable | ||||||
getTable(tableId: any)
|
||||||
|
Parameters :
Returns :
void
|
| Public goBack | ||||||
goBack(base: any)
|
||||||
|
Parameters :
Returns :
void
|
| Public goToApprovalsList |
goToApprovalsList()
|
|
Returns :
void
|
| Public goToBase | ||||||
goToBase(base: any)
|
||||||
|
Parameters :
Returns :
void
|
| Public goToSubmitList |
goToSubmitList()
|
|
Returns :
void
|
| Public goToViewer |
goToViewer()
|
|
Returns :
void
|
| Async ngAfterViewInit |
ngAfterViewInit()
|
|
Returns :
any
|
| ngOnDestroy |
ngOnDestroy()
|
|
Returns :
void
|
| Public onHotDeselect |
onHotDeselect()
|
|
Returns :
void
|
| Public onHotSelection | ||||||
onHotSelection(evt: any)
|
||||||
|
Parameters :
Returns :
void
|
| Public Async rejecting |
rejecting()
|
|
Returns :
any
|
| Private setFocus |
setFocus()
|
|
Returns :
void
|
| Public showDetailsSelect | ||||||
showDetailsSelect($event: Event)
|
||||||
|
Parameters :
Returns :
void
|
| Private _detailsSub |
Type : Subscription | undefined
|
| Public acceptLoading |
Type : boolean
|
Default value : false
|
| Public addCount |
Type : number | undefined
|
| Public arrChanged |
Type : Array<any>
|
| Public arrOfChanges |
Type : Array<any>
|
| Public changesArr |
Type : Array<ChangesObj>
|
Default value : []
|
| Public chArr |
Type : Array<any>
|
Default value : []
|
| Public detailsOpen |
Type : any
|
Default value : false
|
| Public diffsLimit |
Type : boolean
|
Default value : false
|
| Public diffTable |
Type : any
|
Default value : {
data: []
}
|
| Public formattedValues |
Type : boolean
|
Default value : true
|
| Public hotSelection |
Type : any
|
| Public instance |
Type : string
|
Default value : 'hotInstance'
|
| Public jsParams |
Type : any
|
| Public keysArray |
Type : Array<string>
|
| Public lens |
Type : { new: number; updated: number; deleted: number }
|
Default value : {
new: 0,
updated: 0,
deleted: 0
}
|
| Public loaded |
Type : boolean
|
Default value : false
|
| Public loadingTable |
Type : boolean
|
Default value : false
|
| Public originals |
Type : any
|
| Public params |
Type : Param | undefined
|
| Public recordsLimit |
Type : number
|
Default value : 100
|
| Public refreshStartupserviceAfterApprove |
Type : boolean
|
Default value : false
|
| Public rejectLoading |
Type : boolean
|
Default value : false
|
| Public rejectOpen |
Type : any
|
Default value : false
|
| Private response |
Type : AuditorsPostdataSASResponse | undefined
|
| Public rowHeader |
Type : Array<any>
|
| Public rowKeys |
Type : any
|
Default value : []
|
| Public secondOpen |
Type : boolean
|
Default value : false
|
| Public submitArr |
Type : Array<string>
|
| Public submitDetails |
Type : any
|
| Public submitReason |
Type : string
|
Default value : ''
|
| Public submitted |
Type : boolean
|
Default value : false
|
| Public subObj |
Type : any
|
| Public tableDescription |
Type : string | undefined
|
| Public tableDetails |
Type : any
|
| Public tableFlag |
Type : boolean
|
Default value : false
|
| Public tableId |
Type : any
|
| noChanges |
getnoChanges()
|
import { ActivatedRoute } from '@angular/router'
import { sanitiseForSas } from '../../shared/utils/sanitise'
import { SasStoreService } from '../../services/sas-store.service'
import {
Component,
AfterViewInit,
OnDestroy,
ViewEncapsulation
} from '@angular/core'
import { Subscription } from 'rxjs'
import { Router } from '@angular/router'
import { EventService } from '../../services/event.service'
import {
AuditorsPostdataSASResponse,
Param
} from '../../models/sas/auditors-postdata.model'
import { PublicGetChangeinfo } from 'src/app/models/sas/public-getchangeinfo.model'
import { SasService } from 'src/app/services'
interface ChangesObj {
ind: any
field: any
prop: any
original: any
}
@Component({
selector: 'app-approve-details',
templateUrl: './approve-details.component.html',
styleUrls: ['./approve-details.component.scss'],
host: {
class: 'content-container'
},
encapsulation: ViewEncapsulation.None,
standalone: false
})
export class ApproveDetailsComponent implements AfterViewInit, OnDestroy {
private _detailsSub: Subscription | undefined
public tableId: any
public detailsOpen: any = false
public rejectOpen: any = false
public jsParams: any
public keysArray!: Array<string>
public submitArr!: Array<string>
public hotSelection: any
public lens: { new: number; updated: number; deleted: number } = {
new: 0,
updated: 0,
deleted: 0
}
public loaded: boolean = false
public loadingTable: boolean = false
public submitReason: string = ''
public instance: string = 'hotInstance'
public params: Param | undefined
public subObj: any
public submitDetails: any
public acceptLoading: boolean = false
public rejectLoading: boolean = false
public submitted: boolean = false
public tableFlag: boolean = false
public originals: any
public rowKeys: any = []
public rowHeader!: Array<any>
public arrChanged!: Array<any>
public arrOfChanges!: Array<any>
public chArr: Array<any> = []
public tableDetails: any
public secondOpen: boolean = false
public addCount: number | undefined
public tableDescription: string | undefined
public formattedValues: boolean = true
private response: AuditorsPostdataSASResponse | undefined
public changesArr: Array<ChangesObj> = []
public diffTable: any = {
data: []
}
public diffsLimit: boolean = false
public recordsLimit: number = 100
public refreshStartupserviceAfterApprove: boolean = false
constructor(
private sasStoreService: SasStoreService,
private sasService: SasService,
private eventService: EventService,
private router: ActivatedRoute,
private route: Router
) {}
get noChanges() {
return (
this.lens.new === 0 && this.lens.updated === 0 && this.lens.deleted === 0
)
}
public goToBase(base: any) {
this.route.navigateByUrl('/view/data/' + base)
}
public goToApprovalsList() {
this.route.navigateByUrl('/review/approve')
}
public getTable(tableId: any) {
this.route.navigateByUrl('/stage/' + tableId)
}
public goBack(base: any) {
this.route.navigateByUrl('/editor/' + base)
}
public goToViewer() {
this.route.navigateByUrl('/view/data')
}
public showDetailsSelect($event: Event) {
$event.preventDefault()
this.tableFlag = !this.tableFlag
}
public getDetails() {
this.detailsOpen = true
}
public onHotSelection(evt: any) {
this.hotSelection = evt.slice(0, 4)
}
public onHotDeselect() {
setTimeout(() => {
this.hotSelection = null
}, 100)
}
public async rejecting() {
this.rejectLoading = true
this.submitReason = sanitiseForSas(this.submitReason.replace(/\n/g, '. '))
let rejParams = {
STP_ACTION: 'REJECT_TABLE',
TABLE: this.tableId,
STP_REASON: this.submitReason
}
await this.sasStoreService
.rejecting(rejParams, 'BrowserParams', 'approvers/rejection')
.then((res: any) => {
this.route.navigateByUrl('/review/history')
})
.catch((err: any) => {
this.acceptLoading = false
this.rejectLoading = false
})
}
public async approveTable() {
this.acceptLoading = true
let approveParams = {
ACTION: 'APPROVE_TABLE',
TABLE: this.tableId,
DIFFTIME: this.params?.DIFFTIME,
LIBDS: this.params?.LIBDS
}
await this.sasStoreService
.approveTable(approveParams, 'SASControlTable', 'auditors/postdata')
.then((res: any) => {
// If we are approving MPE_TABLES we will arm the trigger for the reload of startup data to se the updated tables
if (this.refreshStartupserviceAfterApprove)
this.sasService.reloadStartupData()
this.route.navigateByUrl('/review/history')
})
.catch((err: any) => {
this.acceptLoading = false
})
}
public goToSubmitList() {
this.route.navigateByUrl('/review/submitted')
}
public async callChangesInfo(tableId: any) {
await this.sasStoreService
.getChangeInfo(tableId)
.then((res: PublicGetChangeinfo) => {
this.tableDetails = res.jsparams[0]
this.jsParams = res.jsparams[0]
let keysArray: Array<string> = []
for (const key in this.jsParams) {
if (this.jsParams.hasOwnProperty(key)) {
keysArray.push(key)
}
}
this.keysArray = keysArray
// If we are approving MPE_TABLES we will arm the trigger for the reload of startup data to se the updated tables
// After user approved if armed, reload will be triggered
if (res.jsparams[0].BASE_DS === 'MPE_TABLES')
this.refreshStartupserviceAfterApprove = true
})
.catch((err: any) => {
this.acceptLoading = false
})
.finally(() => {
this.loaded = true
})
}
public formattingChanged() {
this.calcDiff()
}
public calcDiff() {
// params-only responses (e.g. already reviewed submissions) carry no diff
// tables - nothing to calculate, the details header still renders
if (!this.response || !this.response.cols) return
let news = this.response.new
let updates = this.response.updates
let deleted = this.response.deleted
let originals = this.response.originals
if (this.formattedValues) {
news = this.response.fmt_new
updates = this.response.fmt_updates
deleted = this.response.fmt_deleted
originals = this.response.fmt_originals
}
let delLen = deleted.length
let upLen = updates.length
let newLen = news.length
this.originals = originals
this.rowKeys = []
for (let index = 0; index < updates.length; index++) {
let keys = Object.keys(updates[index])
for (let ind = 0; ind < keys.length; ind++) {
if (updates[index][keys[ind]] !== originals[index][keys[ind]]) {
this.changesArr.push({
ind: index,
field: keys[ind],
prop: updates[index][keys[ind]],
original: originals[index][keys[ind]]
})
}
}
}
this.lens = {
new: this.params?.NUM_ADDED || 0,
updated: this.params?.NUM_UPDATED || 0,
deleted: this.params?.NUM_DELETED || 0
}
let columns: Array<string> = []
let all = updates.concat(news, deleted)
for (let index = 0; index < this.response.cols.length; index++) {
const element = this.response.cols[index].NAME
columns.push(element)
}
// We need to limit lens in following calculation
// since actual data returned is limited to 100 rows
let added =
this.lens.new > this.recordsLimit ? this.recordsLimit : this.lens.new
let changed =
this.lens.updated > this.recordsLimit
? this.recordsLimit
: this.lens.updated
let del =
this.lens.deleted > this.recordsLimit
? this.recordsLimit
: this.lens.deleted
if (
this.lens.new > this.recordsLimit ||
this.lens.updated > this.recordsLimit ||
this.lens.deleted > this.recordsLimit
) {
this.diffsLimit = true
} else {
this.diffsLimit = false
}
this.addCount = added
let chArr: Array<any> = []
let cols: Array<any> = []
for (let ind = 0; ind < columns.length; ind++) {
const element = columns[ind]
cols.push({
data: element,
readOnly: true
// implement custom rendering
})
}
this.diffTable.data = all
for (let index = 0; index < all.length; index++) {
const element = all[index]
let rowKey = Object.keys(element)
this.rowKeys.push(rowKey)
}
let arrChanged: Array<any> = []
let arrOfChanges: Array<any> = []
for (let index = 0; index < this.diffTable.data.length; index++) {
if (index < changed && changed !== 0) {
arrChanged.push([])
arrOfChanges.push([])
// if (index >= added && index < added + changed) {
chArr.push('updated')
let diffTableKeys = Object.keys(this.diffTable.data[index])
for (let j = 0; j < diffTableKeys.length; j++) {
let currColumn = diffTableKeys[j]
if (originals[index][currColumn] !== updates[index][currColumn]) {
arrChanged[index].push(true)
arrOfChanges[index].push(originals[index][currColumn])
} else {
arrChanged[index].push(false)
arrOfChanges[index].push(null)
}
}
this.arrChanged = arrChanged
this.arrOfChanges = arrOfChanges
}
if (index >= changed && index < changed + added) {
chArr.push('added')
}
if (index > added + changed - 1) {
chArr.push('deleted')
}
}
this.chArr = chArr
this.rowHeader = this.rowKeys[0]
this.diffTable.data = all
}
async ngAfterViewInit() {
// submitted page
this._detailsSub = this.sasStoreService.submittDetail.subscribe(
async (allData: any) => {
this.subObj = allData.viewData
this.tableId = allData.viewData.tableId
this.submitted = allData.viewData.sub
this.submitDetails = allData.data
this.submitArr = []
for (let item in this.submitDetails) {
if (item !== 'sub') {
this.submitArr.push(item)
}
}
}
)
if (typeof this.router.snapshot.params['tableId'] === 'undefined') {
return
} else {
this.tableId = this.router.snapshot.params['tableId']
}
let params = {
ACTION: 'SHOW_DIFFS',
TABLE: this.tableId,
DIFFTIME: new Date().toUTCString()
}
// show diffs call and changes info both
this.sasStoreService
.showDiffs(params, 'SASControlTable', 'auditors/postdata')
.then((res: AuditorsPostdataSASResponse) => {
let param = res.params[0]
this.params = param
this.response = res
this.calcDiff()
this.callChangesInfo(this.tableId)
})
.catch((err: any) => {
this.acceptLoading = false
})
.finally(() => {
this.loadingTable = true
this.setFocus()
})
}
ngOnDestroy() {
if (this._detailsSub) {
this._detailsSub.unsubscribe()
}
}
private setFocus() {
setTimeout(() => {
let acceptBtn: any = window.document.getElementById('acceptBtn')
if (!!acceptBtn) {
acceptBtn.focus()
}
}, 200)
}
}
<clr-modal [(clrModalOpen)]="detailsOpen">
<h3 class="modal-title">Approval Details</h3>
<div class="modal-body">
<table class="table">
<thead>
<tr>
<th class="left">Name</th>
<th class="left">Value</th>
</tr>
</thead>
<tbody>
@for (key of keysArray; track key) {
<tr>
<td class="left">{{ key }}</td>
@if (key.includes('TABLE_ID')) {
<td class="left link-it" [routerLink]="'/stage/' + jsParams[key]">
{{ jsParams[key] }}
</td>
}
@if (!key.includes('TABLE_ID')) {
<td class="left">
{{ jsParams[key] }}
</td>
}
</tr>
}
</tbody>
</table>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-sm btn-primary"
(click)="detailsOpen = false"
>
Ok
</button>
</div>
</clr-modal>
<clr-modal [(clrModalOpen)]="tableFlag">
<h3 class="modal-title">All Details</h3>
<div class="modal-body">
@if (tableFlag) {
<clr-tabs>
<clr-tab>
<button clrTabLink>Submitted Table Details</button>
<clr-tab-content *clrIfActive="true">
<div class="overflow-auto">
<table class="table">
<thead>
<tr>
<th class="left">Name</th>
<th class="left">Value</th>
</tr>
</thead>
<tbody>
@for (detail of submitArr; track detail) {
<tr>
<td class="left">{{ detail }}</td>
<td class="left">{{ submitDetails[detail] }}</td>
</tr>
}
</tbody>
</table>
</div>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button clrTabLink>Base Table Details</button>
<clr-tab-content>
<div class="overflow-auto">
<table class="table">
<thead>
<tr>
<th class="left">Name</th>
<th class="left">Value</th>
</tr>
</thead>
<tbody>
@for (key of keysArray; track key) {
<tr>
<td class="left">{{ key }}</td>
<td class="left">{{ jsParams[key] }}</td>
</tr>
}
</tbody>
</table>
</div>
</clr-tab-content>
</clr-tab>
</clr-tabs>
}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-sm btn-primary"
(click)="tableFlag = false"
>
Ok
</button>
</div>
</clr-modal>
<clr-modal [(clrModalOpen)]="rejectOpen">
<h3 class="modal-title">Reason Message</h3>
<div class="modal-body">
<form>
<section class="form-block">
<div class="form-group">
<label for="formFields_8">Reason for rejecting?</label>
<textarea
class="w-100"
id="formFields_8"
rows="5"
[(ngModel)]="submitReason"
[ngModelOptions]="{ standalone: true }"
[innerHTML]="submitReason"
></textarea>
</div>
</section>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="rejectOpen = false">
Cancel
</button>
<button
[clrLoading]="rejectLoading"
type="submit"
class="btn btn-success-outline"
(click)="rejecting()"
>
OK
</button>
</div>
</clr-modal>
<div class="content-area">
@if (!submitted) {
<div class="card">
@if (loaded) {
<div class="card-header d-flex flex-column justify-content-center">
@if (loaded) {
<div class="card" class="mt-0">
<div class="card-header p-0">
<div class="clr-row">
<div class="clr-col-md-4 approvalBack">
<span
class="btn btn-outline m-0"
(click)="goToApprovalsList()"
>
<clr-icon shape="caret" dir="left" size="20"></clr-icon
>Back to approvals list
</span>
</div>
<div class="clr-col-md-4 d-flex justify-content-center">
<h3 class="mt-0 font-weight-300">
{{ jsParams?.TABLE_NM }}
</h3>
</div>
<div class="clr-col-md-4 approvalInfo">
<a
(click)="getDetails()"
class="tooltip tooltip-sm tooltip-top-left"
>
<clr-icon shape="info-standard" size="28"></clr-icon>
<!-- <span *ngIf="!detailsOpen" class="tooltip-content">Approval Details</span> -->
</a>
</div>
</div>
<p class="text-center mt-10">
{{ jsParams?.TABLE_DESC }}
</p>
</div>
<div class="card-block p-0">
@if (loaded) {
<div class="card-text">
<div class="clr-row font-size-15">
<div class="clr-col-md-5">
@if (!tableDetails) {
<p class="text-center font-size-18">
There are no details to show
</p>
}
@if (tableDetails) {
<div class="mt-15">
<span>Table Id:</span>
<strong
class="link-it"
[routerLink]="'/stage/' + tableDetails?.TABLE_ID"
>
{{ tableDetails?.TABLE_ID }}
</strong>
</div>
<div>
<span>Submitter:</span>
<span class="mt-10">
{{ tableDetails?.SUBMITTED_BY_NM }}
</span>
</div>
<div>
<span>Submitted on:</span>
<span class="mt-10">
{{ tableDetails?.SUBMITTED_ON_DTTM }}
</span>
</div>
<div>
<span>Submitted Reason:</span>
<span class="mt-10">
{{ tableDetails?.SUBMITTED_REASON_TXT }}
</span>
</div>
}
</div>
<div class="clr-col-md-7">
<div class="card-block d-flex justify-content-center">
<div class="d-flex justify-content-center mt-0">
<div class="clr-row clr-gap-5 clr-gap-sm-0">
<button
class="btn btn-sm btn-outline text-center mt-5 mr-5i"
(click)="goToBase(jsParams?.TABLE_NM)"
>
View base table
</button>
<button
class="btn btn-sm btn-success-outline text-center mt-5 mr-5i"
(click)="getTable(tableId)"
>
View staged data
</button>
<button
class="btn btn-sm btn-info-outline text-center mt-5"
(click)="goBack(jsParams?.TABLE_NM)"
>
Edit base table
</button>
</div>
</div>
</div>
<div
class="card-block d-flex justify-content-center clr-flex-column clr-gap-5 clr-flex-sm-row clr-gap-sm-0 clr-align-items-center"
>
<button
id="acceptBtn"
[clrLoading]="acceptLoading"
type="submit"
class="btn btn-sm btn-success mr-5i"
(click)="approveTable()"
[disabled]="
!loadingTable ||
params?.ISAPPROVER === 'NO' ||
noChanges
"
>
ACCEPT
</button>
<button
id="rejectBtn"
class="btn btn-sm btn btn-danger mr-5i"
(click)="rejectOpen = true"
[disabled]="
!loadingTable ||
params?.ISAPPROVER === 'NO' ||
noChanges
"
>
REJECT
</button>
<clr-toggle-container class="m-0 ml-20i">
<clr-toggle-wrapper>
<input
type="checkbox"
clrToggle
checked
[(ngModel)]="formattedValues"
(change)="formattingChanged()"
/>
<label class="formatted-values-toggle">{{
formattedValues ? 'Formatted' : 'Unformatted'
}}</label>
</clr-toggle-wrapper>
</clr-toggle-container>
</div>
<div
class="card-block d-flex clr-align-items-center clr-flex-column"
>
@if (diffsLimit) {
<span class="rows-notice">
<clr-icon
class="mb-5 color-orange"
shape="exclamation-triangle"
></clr-icon>
Only the first 100 inserts, updates or deletes are
displayed
</span>
}
<div class="clr-row">
<div
class="d-flex clr-flex-column clr-gap-5 clr-flex-sm-row clr-gap-sm-0"
>
<span class="label label-warning">
Changed Rows
<span class="badge">{{ lens.updated }}</span>
</span>
<span class="label label-success">
Added Rows
<span class="badge">{{ lens.new }}</span>
</span>
<span class="label label-danger">
Deleted Rows
<span class="badge">{{ lens.deleted }}</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
@if (!loadingTable) {
<div
class="h-24vh d-flex flex-column justify-content-center align-items-center"
>
<span class="spinner"> Loading... </span>
@if (!loadingTable) {
<div class="mt-10">
<p cds-text="section">Loading table</p>
</div>
}
</div>
}
<div class="tableCont mt-0">
@if (loadingTable && noChanges) {
<p class="text-center font-size-18">
There are no changes to show
</p>
}
<table class="table">
<thead>
<tr class="d-flex">
@for (col of rowHeader; track col) {
<th class="left">{{ col }}</th>
}
</tr>
</thead>
<tbody>
@for (key of rowKeys; track key; let i = $index) {
<tr
class="d-flex"
[ngClass]="{
addedRow: chArr[i] == 'added',
deletedRow: chArr[i] == 'deleted',
updatedRow: chArr[i] == 'updated'
}"
>
@if (chArr[i] === 'updated') {
@for (
col of rowKeys[i];
track col;
let chIndex = $index
) {
<td
class="left"
[ngClass]="{
'ch tooltip tooltip-md tooltip-top-right':
arrChanged[i][chIndex] == true &&
chArr[i] == 'updated'
}"
>
{{ diffTable.data[i][col] }}
@if (
arrChanged[i][chIndex] == true &&
chArr[i] == 'updated'
) {
<span class="tooltip-content"
>Original value is:
{{ arrOfChanges[i][chIndex] }}</span
>
}
</td>
}
}
@if (chArr[i] !== 'updated') {
@for (
col of rowKeys[i];
track col;
let chIndex = $index
) {
<td class="left">
{{ diffTable.data[i][col] }}
</td>
}
}
</tr>
}
</tbody>
</table>
</div>
</div>
}
</div>
}
<div class="overflow-auto mr-12">
@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 preview</h3>
</div>
}
</div>
}
</div>
</div>
}
<!-- submitted page layout -->
@if (submitted) {
<div>
@if (loaded) {
<div class="d-flex flex-column justify-content-center">
@if (loaded) {
<div class="card m-0">
<div class="card-header">
<div class="clr-row">
<div class="clr-col-md-4 approvalBack">
<span class="btn btn-outline" (click)="goToSubmitList()">
<cds-icon
shape="angle"
direction="left"
size="20"
></cds-icon
>Back to submitted list
</span>
</div>
<div class="clr-col-md-4">
<h3 class="mt-0 font-weight-300 text-center">
{{ subObj.base }}
</h3>
</div>
<div class="clr-col-md-4 approvalInfo">
<a
(click)="tableFlag = true"
class="tooltip tooltip-sm tooltip-top-left"
>
<clr-icon shape="info-standard" size="28"></clr-icon>
</a>
</div>
</div>
<p class="m-0 text-center color-darker-gray">
{{ tableDescription }}
</p>
</div>
<div class="clr-row font-size-15">
<div class="clr-col-md-5">
<div class="mt-15">
<span>Table Id:</span>
<strong
class="link-it"
[routerLink]="'/stage/' + subObj.tableId"
>
<span> {{ subObj.tableId }}</span>
</strong>
</div>
<div>
<span>Submitted on:</span>
<span class="mt-10">
{{ subObj.submitted }}
</span>
</div>
<div>
<span>Submit Message:</span>
<span>
{{ subObj.submitReason }}
</span>
</div>
</div>
<div class="clr-col-md-7">
<div class="card-block d-flex justify-content-center">
<div class="d-flex justify-content-center mt-0">
<div class="clr-row clr-gap-5 clr-gap-sm-0">
<button
class="btn btn-sm btn-outline text-center mt-5 mr-5i"
(click)="goToBase(subObj.base)"
>
View base table
</button>
<button
class="btn btn-sm btn-success-outline text-center mt-5 mr-5i"
(click)="getTable(subObj.tableId)"
>
View staged data
</button>
<button
class="btn btn-sm btn-info-outline text-center mt-5"
(click)="goBack(subObj.base)"
>
Edit base table
</button>
</div>
</div>
</div>
<div
class="card-block d-flex clr-align-items-center clr-flex-column"
>
@if (diffsLimit) {
<span class="rows-notice">
<clr-icon
class="mb-5 color-orange"
shape="exclamation-triangle"
></clr-icon>
Only the first 100 inserts, updates or deletes are
displayed
</span>
}
<div class="clr-row">
<div
class="d-flex clr-flex-column clr-gap-5 clr-flex-sm-row clr-gap-sm-0"
>
<span class="label label-warning">
Changed Rows
<span class="badge">{{ lens.updated }}</span>
</span>
<span class="label label-success">
Added Rows
<span class="badge">{{ lens.new }}</span>
</span>
<span class="label label-danger">
Deleted Rows
<span class="badge">{{ lens.deleted }}</span>
</span>
</div>
</div>
</div>
<div class="card-block d-flex justify-content-center">
<clr-toggle-container class="m-0 ml-20-i">
<clr-toggle-wrapper>
<input
type="checkbox"
clrToggle
checked
[(ngModel)]="formattedValues"
(change)="formattingChanged()"
/>
<label>{{
formattedValues ? 'Formatted' : 'Unformatted'
}}</label>
</clr-toggle-wrapper>
</clr-toggle-container>
</div>
</div>
</div>
<div class="card-block p-0 overflow-auto mr-12">
@if (loaded) {
<div class="card-text"></div>
}
</div>
@if (!loadingTable) {
<div
class="h-25vh d-flex flex-column justify-content-center align-items-center"
>
<span class="spinner"> Loading... </span>
@if (!loadingTable) {
<div class="mt-10">
<p cds-text="section">Loading table</p>
</div>
}
</div>
}
<div class="tableCont">
<table class="table">
<thead>
<tr class="d-flex">
@for (col of rowHeader; track col) {
<th class="left">{{ col }}</th>
}
</tr>
</thead>
<tbody>
@for (key of rowKeys; track key; let i = $index) {
<tr
class="d-flex"
[ngClass]="{
addedRow: chArr[i] == 'added',
deletedRow: chArr[i] == 'deleted',
updatedRow: chArr[i] == 'updated'
}"
>
@if (chArr[i] === 'updated') {
@for (
col of rowKeys[i];
track col;
let chIndex = $index
) {
<td
class="left"
[ngClass]="{
'ch tooltip tooltip-md tooltip-top-right':
arrChanged[i][chIndex] == true &&
chArr[i] == 'updated'
}"
>
{{ diffTable.data[i][col] }}
@if (
arrChanged[i][chIndex] == true &&
chArr[i] == 'updated'
) {
<span class="tooltip-content"
>Original value is:
{{ arrOfChanges[i][chIndex] }}</span
>
}
</td>
}
}
@if (chArr[i] !== 'updated') {
@for (
col of rowKeys[i];
track col;
let chIndex = $index
) {
<td class="left">
{{ diffTable.data[i][col] }}
</td>
}
}
</tr>
}
</tbody>
</table>
</div>
</div>
}
</div>
}
@if (!loaded) {
<div class="card-block">
<div class="loader">
<span class="spinner"> Loading... </span>
@if (!loaded) {
<div>
<h3>Loading submitted table</h3>
</div>
}
</div>
</div>
}
</div>
}
</div>
./approve-details.component.scss