src/app/system/system.component.ts
| encapsulation | ViewEncapsulation.None |
| host | { |
| selector | app-system |
| styleUrls | ./system.component.scss |
| templateUrl | ./system.component.html |
Properties |
Methods |
constructor(appService: AppService, sasService: SasService, licenceService: LicenceService, appSettingsService: AppSettingsService)
|
|||||||||||||||
|
Defined in src/app/system/system.component.ts:50
|
|||||||||||||||
|
Parameters :
|
| downloadConfiguration |
downloadConfiguration()
|
|
Defined in src/app/system/system.component.ts:84
|
|
Returns :
void
|
| exportDdl |
exportDdl()
|
|
Defined in src/app/system/system.component.ts:104
|
|
Returns :
void
|
| isValidLibref | ||||||
isValidLibref(value: string)
|
||||||
|
Defined in src/app/system/system.component.ts:80
|
||||||
|
Parameters :
Returns :
boolean
|
| ngOnInit |
ngOnInit()
|
|
Defined in src/app/system/system.component.ts:74
|
|
Returns :
void
|
| openDdlExport |
openDdlExport()
|
|
Defined in src/app/system/system.component.ts:98
|
|
Returns :
void
|
| Private parseResponse | ||||||
parseResponse(res: any)
|
||||||
|
Defined in src/app/system/system.component.ts:160
|
||||||
|
Parameters :
Returns :
any
|
| refreshDataCatalog |
refreshDataCatalog()
|
|
Defined in src/app/system/system.component.ts:124
|
|
Returns :
void
|
| refreshDataLineage |
refreshDataLineage()
|
|
Defined in src/app/system/system.component.ts:142
|
|
Returns :
void
|
| settingChange | ||||||
settingChange(event: Event)
|
||||||
|
Defined in src/app/system/system.component.ts:76
|
||||||
|
Parameters :
Returns :
void
|
| appInfo |
Type : AppInfo
|
Default value : {
adapterVersion: VERSION.adapterVersion || 'n/a',
appVersion: (VERSION.tag || '').replace('v', ''),
buildTimestamp: moment(parseInt(VERSION.timestamp)).format(
'DD-MMM-YYYY HH:MM'
)
}
|
|
Defined in src/app/system/system.component.ts:26
|
| dcLib |
Type : string
|
Default value : globals.dcLib
|
|
Defined in src/app/system/system.component.ts:43
|
| ddlFlavour |
Type : string
|
Default value : 'SAS'
|
|
Defined in src/app/system/system.component.ts:46
|
| ddlModal |
Type : boolean
|
Default value : false
|
|
Defined in src/app/system/system.component.ts:45
|
| ddlSchema |
Type : string
|
Default value : ''
|
|
Defined in src/app/system/system.component.ts:47
|
| environmentInfo |
Type : EnvironmentInfo | null
|
|
Defined in src/app/system/system.component.ts:34
|
| http |
Type : boolean
|
Default value : location.protocol === 'http:'
|
|
Defined in src/app/system/system.component.ts:36
|
| Infinity |
Type : unknown
|
Default value : Infinity
|
|
Defined in src/app/system/system.component.ts:42
|
| licenceInfo |
Type : LicenseKeyData | null
|
|
Defined in src/app/system/system.component.ts:35
|
| licenceState |
Type : unknown
|
Default value : this.licenceService.licenceState
|
|
Defined in src/app/system/system.component.ts:49
|
| refreshingDataCatalog |
Type : boolean
|
Default value : false
|
|
Defined in src/app/system/system.component.ts:37
|
| refreshingDataLineage |
Type : boolean
|
Default value : false
|
|
Defined in src/app/system/system.component.ts:38
|
| response |
Type : string
|
Default value : 'No response'
|
|
Defined in src/app/system/system.component.ts:39
|
| responseModal |
Type : boolean
|
Default value : false
|
|
Defined in src/app/system/system.component.ts:40
|
| serverType |
Type : string
|
|
Defined in src/app/system/system.component.ts:33
|
| settings |
Type : AppSettings
|
|
Defined in src/app/system/system.component.ts:50
|
| targetLibref |
Type : string
|
Default value : globals.dcLib
|
|
Defined in src/app/system/system.component.ts:44
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core'
import moment from 'moment'
import { VERSION } from 'src/environments/version'
import { LicenseKeyData } from '../models/LicenseKeyData'
import { AppService } from '../services/app.service'
import { LicenceService } from '../services/licence.service'
import { SasService } from '../services/sas.service'
import { AppInfo } from './models/app-info.model'
import { EnvironmentInfo } from './models/environment-info.model'
import { AppSettingsService } from '../services/app-settings.service'
import { AppSettings } from '../models/AppSettings'
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'
import { globals } from '../_globals'
@Component({
selector: 'app-system',
templateUrl: './system.component.html',
styleUrls: ['./system.component.scss'],
host: {
class: 'content-container'
},
encapsulation: ViewEncapsulation.None,
standalone: false
})
export class SystemComponent implements OnInit {
appInfo: AppInfo = {
adapterVersion: VERSION.adapterVersion || 'n/a',
appVersion: (VERSION.tag || '').replace('v', ''),
buildTimestamp: moment(parseInt(VERSION.timestamp)).format(
'DD-MMM-YYYY HH:MM'
)
}
serverType: string
environmentInfo: EnvironmentInfo | null
licenceInfo: LicenseKeyData | null
http: boolean = location.protocol === 'http:'
refreshingDataCatalog: boolean = false
refreshingDataLineage: boolean = false
response: string = 'No response'
responseModal: boolean = false
Infinity = Infinity
dcLib: string = globals.dcLib
targetLibref: string = globals.dcLib
ddlModal: boolean = false
ddlFlavour: string = 'SAS'
ddlSchema: string = ''
licenceState = this.licenceService.licenceState
settings: AppSettings
constructor(
private appService: AppService,
private sasService: SasService,
private licenceService: LicenceService,
private appSettingsService: AppSettingsService
) {
this.serverType = this.sasService.getServerType()
this.licenceInfo = this.licenceService.getLicenseKeyData()
this.environmentInfo = this.appService.getEnvironmentInfo()
this.settings = this.appSettingsService.settings.value
if (this.environmentInfo.AUTOEXEC) {
this.environmentInfo.AUTOEXEC = decodeURIComponent(
this.environmentInfo.AUTOEXEC
)
}
this.appSettingsService.settings.subscribe((settings: AppSettings) => {
this.settings = settings
})
}
ngOnInit(): void {}
settingChange(event: Event) {
this.appSettingsService.setAppSettings(this.settings)
}
isValidLibref(value: string): boolean {
return /^[A-Za-z_]\w{0,7}$/.test(value.trim())
}
downloadConfiguration() {
let sasjsConfig = this.sasService.getSasjsConfig()
let storage = sasjsConfig.serverUrl
let metaData = sasjsConfig.appLoc
let path = this.sasService.getExecutionPath()
let lib = this.targetLibref.toUpperCase().trim()
let downUrl =
storage + path + '/?_program=' + metaData + '/services/admin/exportconfig'
if (lib && lib !== this.dcLib && this.isValidLibref(lib)) {
downUrl += '&dclib=' + encodeURIComponent(lib)
}
window.open(downUrl)
}
openDdlExport() {
this.ddlFlavour = 'SAS'
this.ddlSchema = ''
this.ddlModal = true
}
exportDdl() {
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/admin/exportdb&flavour=' +
encodeURIComponent(this.ddlFlavour)
let schema = this.ddlSchema.trim()
if (this.ddlFlavour !== 'SAS' && schema) {
downUrl += '&schema=' + encodeURIComponent(schema)
}
window.open(downUrl)
this.ddlModal = false
}
refreshDataCatalog() {
this.refreshingDataCatalog = true
this.sasService
.request('admin/refreshcatalog', null)
.then((res: RequestWrapperResponse) => {
this.response = this.parseResponse(res.adapterResponse)
this.responseModal = true
})
.catch((err: any) => {
this.response = this.parseResponse(err.adapterResponse)
this.responseModal = true
})
.finally(() => {
this.refreshingDataCatalog = false
})
}
refreshDataLineage() {
this.refreshingDataLineage = true
this.sasService
.request('admin/refreshtablelineage', null)
.then((res: RequestWrapperResponse) => {
this.response = this.parseResponse(res.adapterResponse)
this.responseModal = true
})
.catch((err: any) => {
this.response = this.parseResponse(err.adapterResponse)
this.responseModal = true
})
.finally(() => {
this.refreshingDataLineage = false
})
}
private parseResponse(res: any) {
return typeof res === 'object' ? JSON.stringify(res) : res
}
}
<div class="content-area">
<div
class="card p-10 d-flex clr-flex-column clr-align-items-center clr-justify-content-center"
>
<h4 class="text-center m-0">System information</h4>
<hr class="w-100 light" />
<div class="content-box d-flex clr-flex-column">
<div
class="sys-info d-flex clr-justify-content-center clr-flex-column clr-flex-lg-row"
>
<div>
<h6 cds-text="subsection" class="mb-10">
Environment Details <span class="dark"></span>
</h6>
<p cds-text="label" class="m-0">
SYSSITE: <span class="dark">{{ environmentInfo?.SYSSITE }}</span>
</p>
<p cds-text="label" class="m-0">
SYSSCPL: <span class="dark">{{ environmentInfo?.SYSSCPL }}</span>
</p>
<p cds-text="label" class="m-0">
SYSTCPIPHOSTNAME:
<span class="dark">{{ environmentInfo?.SYSTCPIPHOSTNAME }}</span>
</p>
<p cds-text="label" class="m-0">
SYSVLONG: <span class="dark">{{ environmentInfo?.SYSVLONG }}</span>
</p>
<p cds-text="label" class="m-0">
MEMSIZE: <span class="dark">{{ environmentInfo?.MEMSIZE }}</span>
</p>
<p cds-text="label" class="m-0">
SYSPROCESSMODE:
<span class="dark">{{ environmentInfo?.SYSPROCESSMODE }}</span>
</p>
<p cds-text="label" class="m-0">
SYSHOSTNAME:
<span class="dark">{{ environmentInfo?.SYSHOSTNAME }}</span>
</p>
<p cds-text="label" class="m-0">
SYSUSERID:
<span class="dark">{{ environmentInfo?.SYSUSERID }}</span>
</p>
<p cds-text="label" class="m-0">
SYSHOSTINFOLONG:
<span class="dark">{{ environmentInfo?.SYSHOSTINFOLONG }}</span>
</p>
<p cds-text="label" class="m-0">
SYSENCODING:
<span class="dark">{{ environmentInfo?.SYSENCODING }}</span>
</p>
<p cds-text="label" class="m-0">
AUTOEXEC: <span class="dark">{{ environmentInfo?.AUTOEXEC }}</span>
</p>
<p cds-text="label" class="m-0">
TIMEZONE:
<span class="dark">{{
environmentInfo?.TIMEZONE || '(not set)'
}}</span>
</p>
<p cds-text="label" class="m-0">
SYSTIMEZONEIDENT:
<span class="dark">{{
environmentInfo?.SYSTIMEZONEIDENT || '(not set)'
}}</span>
</p>
<p cds-text="label" class="m-0">
SYSTIMEZONEOFFSET:
<span class="dark">{{
environmentInfo?.SYSTIMEZONEOFFSET || '0'
}}</span>
</p>
</div>
<div class="d-flex clr-justify-content-lg-center">
<div>
<h6 cds-text="subsection" class="mb-10">
Data Controller Details <span class="dark"></span>
</h6>
<p cds-text="label" class="m-0">
Application version:
<span class="dark">{{ appInfo.appVersion }}</span>
</p>
<p cds-text="label" class="m-0">
Build timestamp:
<span class="dark">{{ appInfo.buildTimestamp }}</span>
</p>
<p cds-text="label" class="m-0">
Adapter version:
<span class="dark">{{ appInfo.adapterVersion }}</span>
</p>
<p cds-text="label" class="m-0">
HTTP: <span class="dark">{{ http ? 'YES' : 'NO' }}</span>
</p>
<p cds-text="label" class="m-0">
DC Admin Group:
<span class="dark">{{ environmentInfo?.DC_ADMIN_GROUP }}</span>
</p>
<p cds-text="label" class="m-0">
App Location:
<span class="dark">{{ environmentInfo?.APP_LOC }}</span>
</p>
</div>
</div>
<div>
<h6 cds-text="subsection" class="mb-10">
Licence details <span class="dark"></span>
</h6>
<p cds-text="label" class="m-0">
Valid until:
<span class="dark">{{ licenceInfo?.valid_until }}</span>
</p>
<p cds-text="label" class="m-0">
Users allowed:
<span class="dark">{{ licenceInfo?.users_allowed }}</span>
</p>
<p cds-text="label" class="m-0">
Site IDs:
<span class="dark">{{ licenceInfo?.site_id_multiple }}</span>
</p>
<p cds-text="label" class="m-0">
Free Tier:
<span class="dark">{{ licenceInfo?.demo ? 'YES' : 'NO' }}</span>
</p>
@if (licenceState.value.viewer_rows_allowed !== Infinity) {
<p class="m-0">
Viewer rows limit:
<span class="dark">{{
licenceState.value.viewer_rows_allowed
}}</span>
</p>
}
@if (licenceState.value.editor_rows_allowed !== Infinity) {
<p class="m-0">
Editor rows limit:
<span class="dark">{{
licenceState.value.editor_rows_allowed
}}</span>
</p>
}
@if (licenceState.value.stage_rows_allowed !== Infinity) {
<p class="m-0">
Stage rows limit:
<span class="dark">{{
licenceState.value.stage_rows_allowed
}}</span>
</p>
}
@if (licenceState.value.history_rows_allowed !== Infinity) {
<p class="m-0">
History rows limit:
<span class="dark">{{
licenceState.value.history_rows_allowed
}}</span>
</p>
}
@if (licenceState.value.submit_rows_limit !== Infinity) {
<p class="m-0">
Submit rows limit:
<span class="dark">{{
licenceState.value.submit_rows_limit
}}</span>
</p>
}
@if (licenceState.value.tables_in_library_limit !== Infinity) {
<p class="m-0">
Tables in library limit:
<span class="dark">{{
licenceState.value.tables_in_library_limit
}}</span>
</p>
}
@if (licenceState.value.viewbox_limit !== Infinity) {
<p class="m-0">
Viewboxes limit:
<span class="dark">{{ licenceState.value.viewbox_limit }}</span>
</p>
}
@if (licenceState.value.lineage_daily_limit !== Infinity) {
<p class="m-0">
Lineage daily limit:
<span class="dark">{{
licenceState.value.lineage_daily_limit
}}</span>
</p>
}
<p cds-text="label" class="m-0">
Viewboxes:
<span class="dark">{{
licenceState.value.viewbox ? 'YES' : 'NO'
}}</span>
</p>
<p cds-text="label" class="m-0">
File Upload:
<span class="dark">{{
licenceState.value.fileUpload ? 'YES' : 'NO'
}}</span>
</p>
<p cds-text="label" class="m-0">
Edit record:
<span class="dark">{{
licenceState.value.editRecord ? 'YES' : 'NO'
}}</span>
</p>
<p cds-text="label" class="m-0">
Add record:
<span class="dark">{{
licenceState.value.addRecord ? 'YES' : 'NO'
}}</span>
</p>
</div>
</div>
<hr class="w-100 light" />
<!-- Keep the logic in case we in future have more then 2 themes (light, dark) -->
<!-- -->
<!-- <div class="user-action">
Keep selected theme after reload
<clr-checkbox-wrapper>
<input [(ngModel)]="settings.persistSelectedTheme" (change)="settingChange($event)" value="persistDarkMode" type="checkbox" clrToggle />
</clr-checkbox-wrapper>
</div> -->
@if (environmentInfo?.ISADMIN === 1) {
@if (serverType === 'SAS9') {
<div class="admin-action">
Refresh Data Lineage
<button
(click)="refreshDataLineage()"
[clrLoading]="refreshingDataLineage"
class="btn btn-info btn-sm"
>
REFRESH
</button>
</div>
}
<div class="admin-action">
Refresh Data Catalog
<button
(click)="refreshDataCatalog()"
[clrLoading]="refreshingDataCatalog"
class="btn btn-info btn-sm"
>
REFRESH
</button>
</div>
<div class="admin-action">
Download Configuration
<div class="libref-group">
<clr-tooltip class="libref-tooltip">
<label clrTooltipTrigger class="libref-label">
Target DC Library
<cds-icon shape="info-circle" size="16"></cds-icon>
</label>
<clr-tooltip-content
clrPosition="bottom-left"
clrSize="md"
*clrIfOpen
>
Enter the target DC library and the downloaded files will
contain this, instead of the original.
</clr-tooltip-content>
</clr-tooltip>
<input
type="text"
class="clr-input libref-input"
maxlength="8"
[ngModel]="dcLib"
(ngModelChange)="targetLibref = $event.toUpperCase()"
placeholder="e.g. MYLIB"
/>
</div>
<button
(click)="downloadConfiguration()"
[disabled]="targetLibref !== dcLib && !isValidLibref(targetLibref)"
class="btn btn-info btn-sm"
>
DOWNLOAD
</button>
</div>
<div class="admin-action">
Update Licence Key
<button routerLink="/licensing/update" class="btn btn-info btn-sm">
UPDATE
</button>
</div>
<div class="admin-action">
Export DC Library DDL
<button (click)="openDdlExport()" class="btn btn-info btn-sm">
EXPORT
</button>
</div>
}
</div>
</div>
</div>
<clr-modal [(clrModalOpen)]="responseModal">
<h3 class="modal-title">Response</h3>
<div class="modal-body">
{{ response }}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-sm btn-primary"
(click)="responseModal = false"
>
Ok
</button>
</div>
</clr-modal>
<clr-modal [(clrModalOpen)]="ddlModal">
<h3 class="modal-title">Export DC Library DDL</h3>
<div class="modal-body">
<clr-select-container>
<label>Flavour</label>
<select [(ngModel)]="ddlFlavour" clrSelect>
<option value="SAS">SAS</option>
<option value="PGSQL">PGSQL</option>
<option value="TSQL">TSQL</option>
</select>
</clr-select-container>
@if (ddlFlavour !== 'SAS') {
<clr-input-container>
<label>Schema (optional)</label>
<input
clrInput
type="text"
[(ngModel)]="ddlSchema"
placeholder="e.g. DC"
/>
</clr-input-container>
}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-sm btn-outline"
(click)="ddlModal = false"
>
Cancel
</button>
<button type="button" class="btn btn-sm btn-primary" (click)="exportDdl()">
Export
</button>
</div>
</clr-modal>
./system.component.scss
.libref-group {
display: inline-flex;
align-items: center;
gap: 4px;
margin: 0 8px;
}
.libref-label {
cursor: pointer;
font-size: 0.55rem;
font-weight: 600;
color: var(--clr-p4-color, #565656);
display: inline-flex;
align-items: center;
gap: 4px;
}
.libref-input {
width: 100px;
text-transform: uppercase;
}