222 lines
5.7 KiB
JavaScript
222 lines
5.7 KiB
JavaScript
/**
|
|
* Copyright IBM Corp. 2021, 2026
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import Controller from '@ember/controller';
|
|
import { service } from '@ember/service';
|
|
import { getOwner } from '@ember/application';
|
|
import { action } from '@ember/object';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { defaultValidator } from 'ember-a11y-refocus';
|
|
import { paramValueFinder } from 'core/utils/param-value-finder';
|
|
|
|
export default class ApplicationController extends Controller {
|
|
// =services
|
|
|
|
@service clusterUrl;
|
|
@service flashMessages;
|
|
@service session;
|
|
@service('browser/window') window;
|
|
@service router;
|
|
@service scope;
|
|
@service intl;
|
|
@service terminal;
|
|
|
|
// =attributes
|
|
|
|
@tracked isLoggingOut = false;
|
|
@tracked isAppQuitting = false;
|
|
|
|
removeOnAppQuitListener;
|
|
|
|
constructor() {
|
|
super(...arguments);
|
|
// Listen for when user attempts to quit app
|
|
// Setup removeOnAppQuitListener to destroy the listener afterwards
|
|
this.removeOnAppQuitListener = this.window.desktop?.app.onAppQuit(() => {
|
|
this.isAppQuitting = true;
|
|
this.hideTerminalViewForModal();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Returns display name and icon for current scope.
|
|
* @type {object}
|
|
*/
|
|
get currentScope() {
|
|
if (this.scope.org?.isOrg) {
|
|
return { name: this.scope.org.displayName, icon: 'org' };
|
|
} else {
|
|
return { name: this.intl.t('titles.global'), icon: 'globe' };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows side navigation only for routes nested under a scope
|
|
* and if user has been authenticated.
|
|
* @type {boolean}
|
|
*/
|
|
get showSideNav() {
|
|
return (
|
|
this.router.currentRouteName.startsWith('scopes.scope') &&
|
|
this.session.isAuthenticated
|
|
);
|
|
}
|
|
|
|
// =actions
|
|
|
|
/**
|
|
* Stop all active/pending target sessions
|
|
* Logout or close app
|
|
*/
|
|
@action
|
|
async confirmCloseSessions() {
|
|
await window.desktop.session.stopAllSessions();
|
|
if (this.isAppQuitting) {
|
|
this.isAppQuitting = false;
|
|
this.close();
|
|
} else {
|
|
// this.session.invalidate() comes from Ember Simple Auth BaseSessionService
|
|
this.session.invalidate();
|
|
}
|
|
|
|
this.isLoggingOut = false;
|
|
}
|
|
|
|
/**
|
|
* Only renders the signout modal if target sessions are running
|
|
*/
|
|
@action
|
|
async showModalOrLogout() {
|
|
const hasRunningSessions =
|
|
await window.desktop.session.hasRunningSessions();
|
|
if (hasRunningSessions) {
|
|
this.isLoggingOut = true;
|
|
this.hideTerminalViewForModal();
|
|
} else {
|
|
this.session.invalidate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invalidates the session and navigates to the cluster-url route.
|
|
* The cluster URL is preserved so that upon reload the user is directed
|
|
* back to the authentication screen for the same cluster.
|
|
*/
|
|
@action
|
|
disconnect() {
|
|
this.session.invalidate();
|
|
this.router.replaceWith('cluster-url');
|
|
}
|
|
|
|
@action
|
|
minimize() {
|
|
window.desktop.windowAction.minimizeWindow();
|
|
}
|
|
|
|
@action
|
|
toggleFullScreen() {
|
|
window.desktop.windowAction.toggleFullscreenWindow();
|
|
}
|
|
|
|
@action
|
|
close() {
|
|
window.desktop.windowAction.closeWindow();
|
|
}
|
|
|
|
/**
|
|
* Applies the specified color theme to the root ember element.
|
|
* @param {string} theme - "light", "dark", or nullish (system default)
|
|
*/
|
|
@action
|
|
toggleTheme(theme) {
|
|
const rootElementSelector = getOwner(this).rootElement;
|
|
const rootEl = getOwner(this)
|
|
.lookup('service:-document')
|
|
.querySelector(rootElementSelector);
|
|
this.session.set('data.theme', theme);
|
|
switch (theme) {
|
|
case 'light':
|
|
rootEl.classList.add('rose-theme-light');
|
|
rootEl.classList.remove('rose-theme-dark');
|
|
break;
|
|
case 'dark':
|
|
rootEl.classList.add('rose-theme-dark');
|
|
rootEl.classList.remove('rose-theme-light');
|
|
break;
|
|
default:
|
|
rootEl.classList.remove('rose-theme-dark');
|
|
rootEl.classList.remove('rose-theme-light');
|
|
}
|
|
}
|
|
|
|
@action
|
|
cancel() {
|
|
this.isLoggingOut = false;
|
|
this.isAppQuitting = false;
|
|
if (this.terminal.isTerminalTabActive) {
|
|
this.terminal.displayTerminalView();
|
|
}
|
|
}
|
|
|
|
willDestroy() {
|
|
super.willDestroy(...arguments);
|
|
this.removeOnAppQuitListener?.();
|
|
}
|
|
|
|
/**
|
|
* Add custom route change validation to prevent refocus when
|
|
* user is attempting to search, filter, or sort.
|
|
* @param {object} transition
|
|
* @returns {boolean}
|
|
*/
|
|
customRouteChangeValidator(transition) {
|
|
if (!transition.to || !transition.from) {
|
|
return true;
|
|
}
|
|
if (transition.to.name === transition.from.name) {
|
|
const toParams = paramValueFinder(
|
|
transition.to.localName,
|
|
transition.to.parent,
|
|
);
|
|
const fromParams = paramValueFinder(
|
|
transition.from.localName,
|
|
transition.from.parent,
|
|
);
|
|
// Return false to prevent refocus when routes have equivalent dynamic segments (params).
|
|
return JSON.stringify(toParams) !== JSON.stringify(fromParams);
|
|
}
|
|
return defaultValidator(transition);
|
|
}
|
|
|
|
/**
|
|
* Hides terminal if open and on terminal tab of Session details page for logout/app quit modal
|
|
*/
|
|
hideTerminalViewForModal() {
|
|
if (this.terminal.isTerminalTabActive) {
|
|
this.terminal.hideTerminalView();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles side nav toggle to hide/show terminal based on side nav state
|
|
* @param {boolean} isMinimized - Whether the side nav is minimized i.e. collapsed
|
|
*/
|
|
@action
|
|
handleSideNavToggle(isMinimized) {
|
|
this.terminal.setSideNavMinimized(isMinimized);
|
|
|
|
// update terminal view if we're on the terminal tab
|
|
if (this.terminal.isTerminalTabActive) {
|
|
if (isMinimized) {
|
|
// Side nav is collapsed, display terminal view
|
|
this.terminal.displayTerminalView();
|
|
} else {
|
|
// Side nav is expanded, hide terminal view
|
|
this.terminal.hideTerminalView();
|
|
}
|
|
}
|
|
}
|
|
}
|