Files
dc/client/src/app/services/event.service.ts
T
dc 40f61331aa
Build / Build-and-ng-test (pull_request) Failing after 1m56s
Build / Build-and-test-development (pull_request) Skipped
Lighthouse Checks / lighthouse (pull_request) Successful in 19m25s
feat: run startupservice in a new window from its error modal
When the startupservice fails, the modal is a dead end: the adapter returned
no log, so there is nothing to act on. The modal now offers a button that runs
the same service through the JES / STP web app in a new browser window, where
the SAS log is returned as the page body.

`_debug=131` is always added (the log is the point), and `_executionTasks` is
never included, so on Viya the run is not submitted as a Compute task and
cannot hit the execution-task timeout. The URL is built by `buildServiceUrl`,
which works for SAS 9, Viya and SASjs Server, and is the same shape the deploy
configurator already uses to open makedata.

The startup failure modals now carry the service name, which is what shows the
button: all three failure branches (malformed response, missing properties,
request rejected) pass `public/startupservice`.
2026-10-23 01:15:31 +00:00

143 lines
3.6 KiB
TypeScript

import { Injectable, Output, EventEmitter } from '@angular/core'
import { InfoModal, AbortDetails } from '../models/InfoModal'
import { AlertsService } from '../shared/alerts/alerts.service'
import { BehaviorSubject } from 'rxjs'
import { AppSettingsService } from './app-settings.service'
import { AppThemes } from '../models/AppSettings'
@Injectable({
providedIn: 'root'
})
export class EventService {
@Output() onSidebarToggle: EventEmitter<any> = new EventEmitter()
@Output() onStartupDataLoaded: EventEmitter<any> = new EventEmitter()
@Output()
onShowAbortModal: EventEmitter<InfoModal> = new EventEmitter<InfoModal>()
@Output() onRequestsModalOpen: EventEmitter<boolean> = new EventEmitter()
@Output() onDemoLimitModalShow: EventEmitter<string> =
new EventEmitter<string>()
public viewLastUrl: string | null = null
public sidebarCloseLimit = 1280
public darkMode: BehaviorSubject<boolean> = new BehaviorSubject(false)
constructor(private appSettingsService: AppSettingsService) {}
toggleDarkMode(value: boolean) {
this.darkMode.next(value)
if (value) {
document.body.setAttribute('cds-theme', 'dark')
} else {
document.body.setAttribute('cds-theme', 'light')
}
this.appSettingsService.setAppSettings({
selectedTheme: value ? AppThemes.dark : AppThemes.light
})
}
public showDemoLimitModal(featureName: string) {
this.onDemoLimitModalShow.emit(featureName)
}
public showInfoModal(
modalTitle: string = 'Info',
message: string,
sasService: string | null = null
) {
let infoModal: InfoModal = {
modalTitle,
message,
sasService,
details: null
}
this.onShowAbortModal.emit(infoModal)
}
public showAbortModal(
sasService: string | null,
message: string,
details?: AbortDetails | null,
modalTitle: string | undefined = undefined
) {
if (!details) details = null
let infoModalObject: InfoModal = {
sasService,
message,
details
}
if (modalTitle) {
infoModalObject.modalTitle = modalTitle
}
this.onShowAbortModal.emit(infoModalObject)
}
public openRequestsModal() {
this.onRequestsModalOpen.emit(true)
}
public catchResponseError(sasService: string | null, err: any) {
let errorMessage: string = 'SAS Service error ocurred'
if (err.error) {
errorMessage = err.error.message
let log: string | undefined
if (err.error.details && err.error.details.log) {
log = err.error.details.log
}
// If not a single useful info is returned from adapter
// We display that it's `unknown` SAS service error
if (!errorMessage || errorMessage.trim().length < 1) {
errorMessage = 'SAS Service error ocurred'
}
// Otherwise we display error message from adapter
this.showAbortModal(
sasService,
errorMessage,
{ LOG: log },
'Request error'
)
} else {
this.showAbortModal(sasService, errorMessage)
}
}
public toggleSidebar() {
this.onSidebarToggle.emit()
}
public closeSidebar() {
if (window.innerWidth < this.sidebarCloseLimit) {
this.onSidebarToggle.emit({ open: false })
}
}
public openSidebar() {
this.onSidebarToggle.emit({ open: true })
}
public startupDataLoaded() {
this.onStartupDataLoaded.emit()
}
public dispatchEvent(eventName: string) {
let event
if (typeof Event === 'function') {
event = new Event(eventName)
} else {
event = document.createEvent('Event')
event.initEvent(eventName, true, true)
}
window.dispatchEvent(event)
}
}