From a2616afa4a27509f681f772f31341edd0f183c7a Mon Sep 17 00:00:00 2001
From: Robert Patrick
Date: Mon, 7 Feb 2022 17:56:47 -0600
Subject: [PATCH 01/99] moving version to 1.2.0
---
electron/package-lock.json | 4 ++--
electron/package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/electron/package-lock.json b/electron/package-lock.json
index e027d40fa..cbd5c4287 100644
--- a/electron/package-lock.json
+++ b/electron/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "wktui",
- "version": "1.1.1",
+ "version": "1.2.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wktui",
- "version": "1.1.1",
+ "version": "1.2.0",
"license": "UPL-1.0",
"dependencies": {
"electron-updater": "^4.6.5",
diff --git a/electron/package.json b/electron/package.json
index decf2e8d6..062d5a402 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -1,7 +1,7 @@
{
"name": "wktui",
"productName": "WebLogic Kubernetes Toolkit UI",
- "version": "1.1.1",
+ "version": "1.2.0",
"description": "WebLogic Kubernetes Toolkit UI",
"copyright": "Copyright (c) 2021, 2022, Oracle and/or its affiliates.",
"homepage": "https://github.com/oracle/weblogic-toolkit-ui",
From edb5a6bab3c8d40e021eee760a2c39fbeb7e679b Mon Sep 17 00:00:00 2001
From: Robert Patrick <31662131+robertpatrick@users.noreply.github.com>
Date: Thu, 10 Feb 2022 18:36:41 -0600
Subject: [PATCH 02/99] initial commit for RC integration scaffolding (#93)
* initial commit for RC integration scaffolding
* adding version checking code
* rearranging version checking
* removing extra spaces
* fixing typo
---
electron/app/js/childProcessExecutor.js | 24 +-
electron/app/js/ipcRendererPreload.js | 7 +-
electron/app/js/userSettings.js | 20 +-
electron/app/js/wlRemoteConsoleUtils.js | 488 ++++++++++++++++++
electron/app/locales/en/electron.json | 25 +-
electron/app/locales/en/webui.json | 15 +
electron/app/main.js | 40 ++
url-catalog.json | 3 +
webui/src/js/models/wdt-model-definition.js | 2 +
webui/src/js/viewModels/model-design-view.js | 91 +++-
.../src/js/viewModels/user-settings-dialog.js | 37 +-
webui/src/js/views/model-design-view.html | 44 +-
webui/src/js/views/user-settings-dialog.html | 19 +
webui/src/js/windowStateUtils.js | 6 +-
14 files changed, 791 insertions(+), 30 deletions(-)
create mode 100644 electron/app/js/wlRemoteConsoleUtils.js
diff --git a/electron/app/js/childProcessExecutor.js b/electron/app/js/childProcessExecutor.js
index c0c44296d..209af5d80 100644
--- a/electron/app/js/childProcessExecutor.js
+++ b/electron/app/js/childProcessExecutor.js
@@ -1,6 +1,6 @@
/**
* @license
- * Copyright (c) 2021, Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022, Oracle and/or its affiliates.
* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
*/
const { exec, execFile, spawn } = require('child_process');
@@ -45,7 +45,20 @@ async function executeChildProcess(currentWindow, executable, argList, env, stdo
return child.exitCode;
}
-function getSpawnOptions(env, shell, detached, windowsHide) {
+function spawnDaemonChildProcess(executable, argList, env, extraOptions = {}, {
+ shell = false,
+ detached = false,
+ windowHide = true,
+} = {}) {
+ const command = workaroundNodeJsIssue38490(shell, executable, argList);
+ const options = getSpawnOptions(env, shell, detached, windowHide, extraOptions);
+
+ getLogger().debug('Spawning daemon process %s with arguments %s and options %s',
+ command.executable, command.argList, JSON.stringify(options));
+ return spawn(command.executable, command.argList, options);
+}
+
+function getSpawnOptions(env, shell, detached, windowsHide, extraOptions = {}) {
const options = {
stdio: [ 'pipe', 'pipe', 'pipe' ],
shell: shell,
@@ -56,6 +69,10 @@ function getSpawnOptions(env, shell, detached, windowsHide) {
if (envIsNotEmpty(env)) {
options['env'] = env;
}
+
+ for (const [key, value] of Object.entries(extraOptions)) {
+ options[key] = value;
+ }
return options;
}
@@ -199,5 +216,6 @@ module.exports = {
executeChildProcess,
executeChildShellScript,
executeFileCommand,
- executeScriptCommand
+ executeScriptCommand,
+ spawnDaemonChildProcess
};
diff --git a/electron/app/js/ipcRendererPreload.js b/electron/app/js/ipcRendererPreload.js
index be76317f6..051f186a2 100644
--- a/electron/app/js/ipcRendererPreload.js
+++ b/electron/app/js/ipcRendererPreload.js
@@ -50,6 +50,7 @@ contextBridge.exposeInMainWorld(
'project-created',
'project-opened',
'project-saved',
+ 'set-wrc-backend-port',
'start-add-model-file',
'start-add-variable-file',
'start-add-archive-file',
@@ -198,7 +199,11 @@ contextBridge.exposeInMainWorld(
'k8s-delete-object',
'openssl-generate-certs',
'validate-k8s-namespaces-exist',
- 'validate-wko-domain-exist'
+ 'validate-wko-domain-exist',
+ 'get-wrc-home-directory',
+ 'get-wrc-app-image',
+ 'wrc-get-home-default-value',
+ 'wrc-set-home-and-start'
];
return new Promise((resolve, reject) => {
if (validChannels.includes(channel)) {
diff --git a/electron/app/js/userSettings.js b/electron/app/js/userSettings.js
index b3e293e3f..ca302ddc3 100644
--- a/electron/app/js/userSettings.js
+++ b/electron/app/js/userSettings.js
@@ -11,6 +11,7 @@ const { getErrorMessage } = require('./errorUtils');
// eslint-disable-next-line no-unused-vars
const userSettableFieldNames = [
+ 'webLogicRemoteConsoleHome',
'proxy',
'logging',
'skipQuickstartAtStartup',
@@ -31,6 +32,7 @@ let _userSettingsFileName;
// Here is an example with every possible field specified:
//
// {
+// "webLogicRemoteConsoleHome": "The path to the WebLogic Remote Console installation",
// "proxy": {
// "httpsProxyUrl": "The proxy to use for the application's all https outbound communication",
// "bypassProxyHosts: "The value to use to set the NO_PROXY environment variable for child processes"
@@ -89,6 +91,20 @@ function applyUserSettingsFromRemote(remoteUserSettingsJson) {
logger.debug('user settings saved...restart the application to pick up logger settings changes');
}
+function getWebLogicRemoteConsoleHome() {
+ let wlRemoteConsoleHome;
+ const userSettingsObj = _getUserSettings();
+ if ('webLogicRemoteConsoleHome' in userSettingsObj) {
+ wlRemoteConsoleHome = userSettingsObj['webLogicRemoteConsoleHome'];
+ }
+ return wlRemoteConsoleHome;
+}
+
+function setWebLogicRemoteConsoleHome(wlRemoteConsoleHome) {
+ const settings = _getUserSettings();
+ settings['webLogicRemoteConsoleHome'] = wlRemoteConsoleHome;
+}
+
function getHttpsProxyUrl() {
let httpsProxyUrl;
const userSettingsObj = _getUserSettings();
@@ -413,5 +429,7 @@ module.exports = {
setWindowSize,
getLoggingConfiguration,
getUserSettingsForRemote,
- saveUserSettings
+ saveUserSettings,
+ getWebLogicRemoteConsoleHome,
+ setWebLogicRemoteConsoleHome
};
diff --git a/electron/app/js/wlRemoteConsoleUtils.js b/electron/app/js/wlRemoteConsoleUtils.js
new file mode 100644
index 000000000..c7021da6a
--- /dev/null
+++ b/electron/app/js/wlRemoteConsoleUtils.js
@@ -0,0 +1,488 @@
+/**
+ * @license
+ * Copyright (c) 2021, 2022, Oracle and/or its affiliates.
+ * Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+ */
+'use strict';
+
+const path = require('path');
+const readline = require('readline');
+const { app, dialog } = require('electron');
+const fsPromises = require('fs/promises');
+
+const userSettings = require('./userSettings');
+const fsUtils = require('./fsUtils');
+const i18n = require('./i18next.config');
+const { getErrorMessage } = require('./errorUtils');
+const { getLogger } = require('./wktLogging');
+const osUtils = require('./osUtils');
+const { sendToWindow } = require('./windowUtils');
+const { spawnDaemonChildProcess } = require('./childProcessExecutor');
+
+// TODO - Change this to the correct version once the RC version changes to 2.3.0...
+const MIN_VERSION = '2.2.0';
+const MIN_VERSION_COMPONENTS = MIN_VERSION.split('.').map((item) => { return Number(item); });
+let _wlRemoteConsoleChildProcess;
+
+
+async function startWebLogicRemoteConsoleBackend(currentWindow, skipVersionCheck = false) {
+ if (_wlRemoteConsoleChildProcess) {
+ return Promise.resolve();
+ }
+
+ return new Promise((resolve) => {
+ _getWebLogicRemoteConsoleHome(skipVersionCheck).then(rcHome => {
+ if (!rcHome) {
+ return resolve();
+ }
+ _getWebLogicRemoteConsoleExecutableData(rcHome).then(result => {
+ const executable = result['executable'];
+ const argList = result['arguments'];
+ const options = result['options'];
+
+ _wlRemoteConsoleChildProcess = spawnDaemonChildProcess(executable, argList, null, options);
+ _wlRemoteConsoleChildProcess.on('error', (err) => {
+ const title = i18n.t('wrc-spawn-error-title');
+ dialog.showErrorBox(title, getErrorMessage(err));
+ });
+ _wlRemoteConsoleChildProcess.on('exit', (code) => {
+ getLogger().info('WebLogic Remote Console backend process exited with code %s', code);
+ });
+
+ const stdoutLines = readline.createInterface({ input: _wlRemoteConsoleChildProcess.stdout });
+ const stderrLines = readline.createInterface({ input: _wlRemoteConsoleChildProcess.stderr });
+
+ let foundPort = false;
+ const portRegex = /^Port=(\d+)\s?$/;
+ stdoutLines.on('line', (line) => {
+ getLogger().debug('WebLogic Remote Console stdout: %s', line.trim());
+ if (!foundPort) {
+ const matcher = line.match(portRegex);
+ if (matcher) {
+ foundPort = true;
+ sendToWindow(currentWindow, 'set-wrc-backend-port', matcher[1]);
+ }
+ }
+ });
+ stderrLines.on('line', (line) => {
+ getLogger().debug('WebLogic Remote Console stderr: %s', line.trim());
+ });
+ resolve();
+ }).catch(err => {
+ const title = i18n.t('wrc-init-error-title');
+ dialog.showErrorBox(title, getErrorMessage(err));
+ resolve();
+ });
+ }).catch(err => {
+ const title = i18n.t('wrc-home-error-title');
+ dialog.showErrorBox(title, getErrorMessage(err));
+ resolve();
+ });
+ });
+}
+
+async function setWebLogicRemoteConsoleHomeAndStart(currentWindow, rcHome) {
+ const title = i18n.t('wrc-set-and-start-error-title');
+ return new Promise(resolve => {
+ fsUtils.exists(rcHome).then(doesExist => {
+ if (!doesExist) {
+ const message = i18n.t('wrc-set-home-not-exists', { rcHome: rcHome });
+ dialog.showErrorBox(title, message);
+ return resolve();
+ }
+
+ _isCompatibleVersion(rcHome).then(isCompatibleResult => {
+ getLogger().debug('_isCompatibleVersion() returned %s', JSON.stringify(isCompatibleResult));
+ if (isCompatibleResult.isCompatible) {
+ userSettings.setWebLogicRemoteConsoleHome(rcHome);
+ startWebLogicRemoteConsoleBackend(currentWindow, true).then(() => resolve() );
+ } else {
+ const message = i18n.t('wrc-version-incompatible-message',
+ { rcVersion: isCompatibleResult['version'], minVersion: MIN_VERSION });
+ dialog.showErrorBox(title, message);
+ return resolve();
+ }
+ }).catch(err => {
+ dialog.showErrorBox(title, getErrorMessage(err));
+ return resolve();
+ });
+ }).catch(err => {
+ const message = i18n.t('wrc-set-home-existence-check-failed', { rcHome: rcHome, error: getErrorMessage(err) });
+ dialog.showErrorBox(title, message);
+ resolve();
+ });
+ });
+}
+
+async function getDefaultWebLogicRemoteConsoleHome() {
+ let rcHome = userSettings.getWebLogicRemoteConsoleHome();
+ if (rcHome) {
+ return Promise.resolve(rcHome);
+ }
+
+ // This only works if the WebLogic Remote Console is installed and has been run at least once.
+ //
+ rcHome = await _getLocationFromPreferencesFile();
+ if (rcHome) {
+ return Promise.resolve(rcHome);
+ }
+
+ // Just in case the WebLogic Remote Console is installed but has never been run...
+ //
+ if (osUtils.isMac()) {
+ return _getDefaultLocationForMacOS();
+ } else if (osUtils.isWindows()) {
+ return _getDefaultLocationForWindows();
+ } else {
+ return _getDefaultLocationForLinux();
+ }
+}
+
+function getDefaultDirectoryForOpenDialog(isAppImage = false) {
+ let result;
+ if (osUtils.isMac()) {
+ result = '/Applications';
+ } else if (osUtils.isWindows()) {
+ result = path.normalize(path.join(path.dirname(app.getPath('exe')), '..'));
+ } else if (isAppImage) {
+ result = app.getPath('home');
+ } else {
+ result = '/opt';
+ }
+ return result;
+}
+
+async function _getWebLogicRemoteConsoleHome(skipVersionCheck = false) {
+ const rcHome = userSettings.getWebLogicRemoteConsoleHome();
+ if (!rcHome) {
+ return Promise.resolve();
+ }
+
+ return new Promise((resolve, reject) => {
+ fsUtils.exists(rcHome).then(doesExist => {
+ if (doesExist) {
+ if (!skipVersionCheck) {
+ _isCompatibleVersion(rcHome).then(isCompatibleResult => {
+ if (isCompatibleResult['isCompatible']) {
+ resolve(rcHome);
+ } else {
+ const message = i18n.t('wrc-version-incompatible-message',
+ { rcVersion: isCompatibleResult['version'], minVersion: MIN_VERSION });
+ reject(new Error(message));
+ }
+ }).catch(err => reject(err));
+ } else {
+ resolve(rcHome);
+ }
+ } else {
+ const message = i18n.t('wrc-home-not-exist', { rcHome: rcHome });
+ reject(new Error(message));
+ }
+ }).catch(err => {
+ const message = i18n.t('wrc-location-existence-check-failed', { location: rcHome, error: getErrorMessage(err) });
+ reject(new Error(message));
+ });
+ });
+}
+
+async function _isCompatibleVersion(rcHome) {
+ let packageJsonFile;
+ if (osUtils.isMac()) {
+ packageJsonFile = path.join(rcHome, 'Contents', 'MacOS', 'package.json');
+ } else if (osUtils.isWindows()) {
+ packageJsonFile = path.join(rcHome, 'package.json');
+ } else {
+ // For Linux, the rcHome is either a directory or a path to an AppImage file.
+ //
+ let isDirectory;
+ try {
+ isDirectory = await fsUtils.isDirectory(rcHome);
+ } catch (err) {
+ const message = i18n.t('wrc-linux-executable-directory-check-failed',
+ { rcHome: rcHome, error: getErrorMessage(err) });
+ return Promise.reject(new Error(message));
+ }
+
+ if (isDirectory) {
+ packageJsonFile = path.join(rcHome, 'package.json');
+ }
+ }
+
+ return new Promise((resolve, reject) => {
+ _verifyVersionCompatibility(packageJsonFile, rcHome).then(versionResult => {
+ resolve(versionResult);
+ }).catch(err => {
+ const message = i18n.t('wrc-version-verification-failed', { error: getErrorMessage(err) });
+ reject(new Error(message));
+ });
+ });
+}
+
+async function _getWebLogicRemoteConsoleExecutableData(rcHome) {
+ // The first thing we need to do is to determine if the Remote Console "home"
+ // is a dev install or not.
+ //
+ // In a dev install, the assumption is that the home is set to /electron.
+ //
+ const results = { };
+ if (rcHome.endsWith('electron')) {
+ const pathToDirectoryWithExecutable = path.join(rcHome, 'node_modules', 'electron', 'dist');
+ return new Promise((resolve, reject) => {
+ fsUtils.isDirectory(pathToDirectoryWithExecutable).then(doesExist => {
+ if (!doesExist) {
+ const message = i18n.t('wrc-dev-executable-directory-not-exists',
+ { rcHome: rcHome, location: pathToDirectoryWithExecutable });
+ return reject(new Error(message));
+ }
+
+ _getDevExecutablePath(rcHome, pathToDirectoryWithExecutable).then(exeResult => {
+ if (exeResult.exists) {
+ results['executable'] = exeResult.executable;
+ results['arguments'] = ['.', 'dev', '--showPort', '--stdin', '--quiet', '--headless'];
+ results['options'] = { cwd: rcHome };
+ } else {
+ const message = i18n.t('wrc-dev-executable-existence-check-failed',
+ { rcHome: rcHome, executable: exeResult['executable'] });
+ reject(new Error(message));
+ }
+ }).catch(err => reject(err));
+ }).catch(err => reject(err));
+ });
+ }
+
+ // If we get here, this is an (installed) executable environment.
+ //
+ return new Promise((resolve, reject) => {
+ _getInstalledExecutablePath(rcHome).then(exeResult => {
+ if (exeResult['exists']) {
+ results['executable'] = exeResult['executable'];
+ results['arguments'] = ['--showPort', '--stdin', '--quiet', '--headless'];
+ resolve(results);
+ } else {
+ const message = i18n.t('wrc-executable-not-exists', { rcHome: rcHome, executable: results['executable'] });
+ reject(new Error(message));
+ }
+ }).catch(err => reject(err));
+ });
+}
+
+async function _getDevExecutablePath(rcHome, pathToDirectoryWithExecutable) {
+ const result = {
+ exists: true
+ };
+
+ if (osUtils.isMac()) {
+ result['executable'] = path.join(pathToDirectoryWithExecutable, 'Electron.app', 'Contents', 'MacOS', 'Electron');
+ } else {
+ result['executable'] = path.join(pathToDirectoryWithExecutable, `electron${osUtils.isWindows() ? '.exe' : ''}`);
+ }
+
+ return new Promise((resolve, reject) => {
+ fsUtils.exists(result['executable']).then(doesExist => {
+ if (!doesExist) {
+ result['exists'] = false;
+ }
+ resolve(result);
+ }).catch(err => {
+ const message = i18n.t('wrc-dev-executable-existence-check-failed',
+ { rcHome: rcHome, executable: result['executable'], error: getErrorMessage(err) });
+ reject(new Error(message));
+ });
+ });
+}
+
+async function _getInstalledExecutablePath(rcHome) {
+ const result = {
+ exists: true
+ };
+
+ if (osUtils.isMac()) {
+ result['executable'] = path.join(rcHome, 'Contents', 'MacOS', 'WebLogic Remote Console');
+ } else if (osUtils.isWindows()) {
+ result['executable'] = path.join(rcHome, 'WebLogic Remote Console.exe');
+ } else {
+ // For Linux, the rcHome is either a directory or a path to an AppImage file.
+ //
+ let isDirectory;
+ try {
+ isDirectory = await fsUtils.isDirectory(rcHome);
+ } catch (err) {
+ const message = i18n.t('wrc-linux-executable-directory-check-failed',
+ { rcHome: rcHome, error: getErrorMessage(err) });
+ return Promise.reject(new Error(message));
+ }
+
+ if (isDirectory) {
+ result['executable'] = path.join(rcHome, 'weblogic-remote-console');
+ } else {
+ result['executable'] = rcHome;
+ }
+ }
+
+ return new Promise((resolve, reject) => {
+ fsUtils.exists(result['executable']).then(doesExist => {
+ result['exists'] = doesExist;
+ resolve(result);
+ }).catch(err => {
+ const message = i18n.t('wrc-executable-existence-check-failed',
+ {rcHome: rcHome, executable: result['executable'], error: getErrorMessage(err) });
+ reject(new Error(message));
+ });
+ });
+}
+
+async function _verifyVersionCompatibility(packageJsonFile, executablePath) {
+ const result = {
+ isCompatible: false
+ };
+
+ if (packageJsonFile) {
+ return new Promise((resolve, reject) => {
+ fsUtils.exists(packageJsonFile).then(doesExist => {
+ if (doesExist) {
+ const packageJson = require(packageJsonFile);
+ if (packageJson.version) {
+ result['version'] = packageJson.version;
+ result['isCompatible'] = _verifyVersionNumberCompatibility(packageJson.version);
+ resolve(result);
+ } else {
+ const message = i18n.t('wrc-package-json-missing-version', { packageJsonFile: packageJsonFile });
+ reject(new Error(message));
+ }
+ } else {
+ const message = i18n.t('wrc-package-json-file-missing', { packageJsonFile: packageJsonFile });
+ reject(new Error(message));
+ }
+ }).catch(err => {
+ const message = i18n.t('wrc-package-json-existence-check-failed',
+ {packageJsonFile: packageJsonFile, error: getErrorMessage(err)});
+ reject(new Error(message));
+ });
+ });
+ }
+
+ // If we get here, that means the user is using the AppImage file.
+ // All we can really do is try to look at the file name for the
+ // version number and hope that they didn't change the file name...
+ //
+ const appImageRegex = /^WebLogic.Remote.Console-(\d+\.\d+\.\d+)\.AppImage$/;
+ const executableFileName = path.basename(executablePath);
+ const matcher = executableFileName.match(appImageRegex);
+ if (matcher) {
+ result['version'] = matcher[1];
+ result['isCompatible'] = _verifyVersionNumberCompatibility(matcher[1]);
+ return Promise.resolve(result);
+ } else {
+ const message = i18n.t('wrc-app-image-file-version-no-match',
+ { rcHone: executablePath, filename: executableFileName });
+ return Promise.reject(new Error(message));
+ }
+}
+
+function _verifyVersionNumberCompatibility(actualVersion) {
+ const versionComponents = actualVersion.split('.').map((item) => { return Number(item); });
+
+ let versionIsCompatible = true;
+ for (let i = 0; i < 3; i++) {
+ if (versionComponents[i] < MIN_VERSION_COMPONENTS[i]) {
+ versionIsCompatible = false;
+ break;
+ }
+ }
+ return versionIsCompatible;
+}
+
+async function _getLocationFromPreferencesFile() {
+ const autoPrefsLocation = path.join(app.getPath('appData'), 'weblogic-remote-console', 'auto-prefs.json');
+
+ return new Promise(resolve => {
+ fsUtils.exists(autoPrefsLocation).then(doesExist => {
+ if (!doesExist) {
+ return resolve();
+ }
+
+ fsPromises.readFile(autoPrefsLocation, { encoding: 'utf8' }).then(contents => {
+ try {
+ const props = JSON.parse(contents);
+ resolve(props.location);
+ } catch (err) {
+ getLogger().debug('Failed to parse file %s: %s', autoPrefsLocation, getErrorMessage(err));
+ resolve();
+ }
+ }).catch(err => {
+ getLogger().debug('Failed to read file %s: %s', autoPrefsLocation, getErrorMessage(err));
+ resolve();
+ });
+ }).catch(err => {
+ getLogger().debug('Failed to determine whether the file %s exists: %s', autoPrefsLocation, getErrorMessage(err));
+ resolve();
+ });
+ });
+}
+
+async function _getDefaultLocationForMacOS() {
+ const defaultLocation = '/Applications/WebLogic Remote Console.app';
+ return new Promise(resolve => {
+ fsUtils.exists(defaultLocation).then(doesExist => {
+ if (doesExist) {
+ resolve(defaultLocation);
+ } else {
+ resolve();
+ }
+ }).catch(err => {
+ getLogger().debug('Existence check for default WebLogic Remote Console Home location %s failed: %s',
+ defaultLocation, getErrorMessage(err));
+ resolve();
+ });
+ });
+}
+
+async function _getDefaultLocationForWindows() {
+ const defaultAllUsersLocation = 'c:\\Program Files\\WebLogic Remote Console';
+ fsUtils.exists(defaultAllUsersLocation).then(doesExist => {
+ if (doesExist) {
+ return Promise.resolve(defaultAllUsersLocation);
+ }
+ // fall through to check the alternate location...
+ }).catch(err => {
+ getLogger().debug('Existence check for default WebLogic Remote Console Home location %s failed: %s',
+ defaultAllUsersLocation, getErrorMessage(err));
+ return Promise.resolve();
+ });
+
+ const defaultLocation = path.join(app.getPath('appData'), 'Local', 'Programs', 'WebLogic Remote Console');
+ fsUtils.exists(defaultLocation).then(doesExist => {
+ if (doesExist) {
+ return Promise.resolve(defaultLocation);
+ }
+ return Promise.resolve();
+ }).catch(err => {
+ getLogger().debug('Existence check for default WebLogic Remote Console Home location %s failed: %s',
+ defaultAllUsersLocation, getErrorMessage(err));
+ return Promise.resolve();
+ });
+}
+
+async function _getDefaultLocationForLinux() {
+ const defaultLocation = '/opt/WebLogic Remote Console';
+ return new Promise(resolve => {
+ fsUtils.exists(defaultLocation).then(doesExist => {
+ if (doesExist) {
+ resolve(defaultLocation);
+ } else {
+ resolve();
+ }
+ }).catch(err => {
+ getLogger().debug('Existence check for default WebLogic Remote Console Home location %s failed: %s',
+ defaultLocation, getErrorMessage(err));
+ resolve();
+ });
+ });
+}
+
+module.exports = {
+ getDefaultDirectoryForOpenDialog,
+ getDefaultWebLogicRemoteConsoleHome,
+ setWebLogicRemoteConsoleHomeAndStart,
+ startWebLogicRemoteConsoleBackend
+};
diff --git a/electron/app/locales/en/electron.json b/electron/app/locales/en/electron.json
index 51b23c4fd..4d068d3db 100644
--- a/electron/app/locales/en/electron.json
+++ b/electron/app/locales/en/electron.json
@@ -180,6 +180,8 @@
"dialog-chooseArchiveEntry": "Choose {{entryType}} for Archive",
"dialog-archiveEntryFilter": "{{entryType}}",
+ "dialog-getWebLogicRemoteConsoleHome": "Select the WebLogic Remote Console Installation",
+ "dialog-getWebLogicRemoteConsoleAppImage": "Select the WebLogic Remote Console AppImage file",
"title-edited": "edited",
@@ -363,5 +365,26 @@
"wkt-tools-wdt-version-not-compatible-error": "The installed WebLogic Deploy Tooling version {{version}} does not meet the minimum compatible version {{minimumVersion}} required by WebLogic Kubernetes Toolkit UI version {{wktuiVersion}}",
"project-save-file-already-open-title": "Project File Already Open",
- "project-save-file-already-open-message": "The project file {{projectFile}} is already open in another window. Please either close the existing window or select a different project file and try again."
+ "project-save-file-already-open-message": "The project file {{projectFile}} is already open in another window. Please either close the existing window or select a different project file and try again.",
+
+ "wrc-home-error-title": "Invalid WebLogic Remote Console Location",
+ "wrc-init-error-title": "Initializing WebLogic Remote Console Backend Failed",
+ "wrc-location-existence-check-failed": "Unable to start the WebLogic Remote Console backend at {{location}} due to an error while trying to determine its existence: {{error}}.",
+ "wrc-dev-executable-directory-not-exists": "Unable to start the WebLogic Remote Console backend in development mode at {{rcHome}} because the expected directory {{location}} does not exist.",
+ "wrc-dev-executable-not-exists": "Unable to start the WebLogic Remote Console backend in development mode at {{rcHome}} because the executable file {{executable}} does not exist.",
+ "wrc-dev-executable-existence-check-failed": "Unable to start the WebLogic Remote Console backend in development mode at {{rcHome}} because the existence check for the executable file {{executable}} failed: {{error}}.",
+ "wrc-linux-executable-directory-check-failed": "Unable to start the WebLogic Remote Console backend at {{rcHome}} because the check to determine if {{rcHome}} is a Linux directory or an AppImage file failed: {{error}}.",
+ "wrc-executable-existence-check-failed": "Unable to start the WebLogic Remote Console backend at {{rcHome}} because existence check for the executable file {{executable}} failed: {{error}}.",
+ "wrc-executable-not-exists": "Unable to start the WebLogic Remote Console backend at {{rcHome}} because the executable file {{executable}} does not exist.",
+ "wrc-spawn-error-title": "Starting WebLogic Remote Console Backend Failed",
+ "wrc-set-home-not-exists": "Unable to set the WebLogic Remote Console Home because {{rcHome}} does not exist.",
+ "wrc-set-home-existence-check-failed": "Unable to set the WebLogic Remote Console Home because the existence check for {{rcHome}} failed: {{error}}.",
+ "wrc-set-and-start-error-title": "Starting WebLogic Remote Console Backend Failed",
+ "wrc-package-json-file-missing": "Unable to determine the WebLogic Remote Console version because the {{packageJsonFile}} file was missing.",
+ "wrc-package-json-missing-version": "Unable to determine the WebLogic Remote Console version because the {{packageJsonFile}} file was missing the version element.",
+ "wrc-package-json-existence-check-failed": "Unable to determine the WebLogic Remote Console version because the existence check for {{packageJsonFile}} failed: {{error}}.",
+ "wrc-app-image-file-version-no-match": "Unable to determine the WebLogic Remote Console version because the location {{rcHome}} AppImage file name {{filename}} does not match the expected filename pattern needed to extract the version number.",
+ "wrc-version-incompatible-message": "The WebLogic Remote Console version {{rcVersion}} does not meet the minimum version requirement of {{minVersion}}.",
+ "wrc-version-verification-failed": "Unable to start the WebLogic Remote Console backend because an error occurred while trying to determine the version compatibility: {{error}}",
+ "wrc-home-not-exist": "Unable to start the WebLogic Remote Console backend because the configured location {{rcHome}} does not exist."
}
diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json
index 30de76d27..95126758a 100644
--- a/electron/app/locales/en/webui.json
+++ b/electron/app/locales/en/webui.json
@@ -160,6 +160,12 @@
"user-settings-dialog-https-proxy-url-help": "The proxy server URL to use for all outbound HTTPS requests (e.g., http://myproxy:80)",
"user-settings-dialog-bypass-proxy-hosts-label": "Bypass Proxy Hosts",
"user-settings-dialog-bypass-proxy-hosts-help": "The list of hostnames or patterns to use to set the NO_PROXY environment variable. Please see NO_PROXY documentation for legal values.",
+ "user-settings-dialog-wrc-section-title": "WebLogic Remote Console Configuration",
+ "user-settings-dialog-wrc-home-label": "WebLogic Remote Console Install Location",
+ "user-settings-dialog-wrc-home-macos-help": "The location of the WebLogic Remote Console.app, typically /Applications/WebLogic Remote Console.app.",
+ "user-settings-dialog-wrc-home-windows-help": "The location of the WebLogic Remote Console installation directory.",
+ "user-settings-dialog-wrc-home-linux-help": "The location of the WebLogic Remote Console installation. For RPM or DEB installers, this will typically be /opt/WebLogic Remote Console. If using the AppImage, simply point to the AppImage file directly.",
+
"user-settings-dialog-logging-section-title": "Logging Configuration",
"user-settings-dialog-console-level-label": "Console Transport Log Level",
"user-settings-dialog-console-level-help": "The log level to use to filter output to the console.",
@@ -181,6 +187,15 @@
"model-design-form-name": "Model",
"model-design-coming-soon": "Coming Soon...",
+ "model-design-wrc-form-title": "WebLogic Remote Console Integration",
+ "model-design-wrc-home-label": "WebLogic Remote Console Install Location",
+ "model-design-wrc-install-description": "The Model Design View is provided through integration with the WebLogic Remote Console. Install the WebLogic Remote Console on the local machine and use the form below to provide its location and start the daemon process with which the UI will communicate. Note that this integration required WebLogic Remote Console version 2.3.0 or newer.",
+ "model-design-wrc-install-location-prefix": "Download and run the appropriate installer for your machine from the GitHub",
+ "model-design-wrc-link-text": "WebLogic Remote Console Releases",
+ "model-design-wrc-install-location-postfix": "page.",
+ "model-design-wrc-start-description": "Once the WebLogic Remote Console is installed, set the WebLogic Remote Console Install Location field below accordingly and press the Start WebLogic Remote Console button.",
+ "model-design-button-startWebLogicRemoteConsole": "Start WebLogic Remote Console",
+ "model-design-hints-startWebLogicRemoteConsole": "Start the WebLogic Remote Console backend process",
"image-page-hints-createImage": "Create Primary Image",
"image-page-button-createImage": "Create Primary Image",
diff --git a/electron/app/main.js b/electron/app/main.js
index c706330d7..cdeab6917 100644
--- a/electron/app/main.js
+++ b/electron/app/main.js
@@ -34,6 +34,8 @@ const helmUtils = require('./js/helmUtils');
const openSSLUtils = require('./js/openSSLUtils');
const osUtils = require('./js/osUtils');
const { initializeAutoUpdater, registerAutoUpdateListeners, installUpdates, getUpdateInformation } = require('./js/appUpdater');
+const { startWebLogicRemoteConsoleBackend, getDefaultDirectoryForOpenDialog, setWebLogicRemoteConsoleHomeAndStart,
+ getDefaultWebLogicRemoteConsoleHome } = require('./js/wlRemoteConsoleUtils');
const { getHttpsProxyUrl, getBypassProxyHosts } = require('./js/userSettings');
const { sendToWindow } = require('./js/windowUtils');
@@ -153,6 +155,8 @@ class Main {
}
createWindow(this._isJetDevMode, this._wktApp).then(win => {
+ startWebLogicRemoteConsoleBackend(win).then();
+
if (filePath) {
win.once('ready-to-show', () => {
this.openProjectFileInWindow(win, filePath);
@@ -206,6 +210,7 @@ class Main {
this._logger.debug('Received window-is-ready for window %d', event.sender.getOwnerBrowserWindow().id);
const currentWindow = event.sender.getOwnerBrowserWindow();
currentWindow.isReady = true;
+
project.sendProjectOpened(currentWindow).then(async () => {
if (!this._startupDialogsShownAlready) {
const startupInformation = {
@@ -891,6 +896,41 @@ class Main {
// called before any projects opened, no need for extra checks
app.quit();
});
+
+ ipcMain.handle('get-wrc-home-directory', async (event) => {
+ const title = i18n.t('dialog-getWebLogicRemoteConsoleHome');
+ const properties = osUtils.isMac() ? [ 'openFile', 'dontAddToRecent' ] : [ 'openDirectory', 'dontAddToRecent' ];
+ return chooseFromFileSystem(event.sender.getOwnerBrowserWindow(), {
+ title: title,
+ defaultPath: getDefaultDirectoryForOpenDialog(),
+ message: title,
+ buttonLabel: i18n.t('button-select'),
+ properties: properties
+ });
+ });
+
+ ipcMain.handle('get-wrc-app-image', async (event) => {
+ const title = i18n.t('dialog-getWebLogicRemoteConsoleAppImage');
+ return chooseFromFileSystem(event.sender.getOwnerBrowserWindow(), {
+ title: title,
+ defaultPath: getDefaultDirectoryForOpenDialog(true),
+ message: title,
+ buttonLabel: i18n.t('button-select'),
+ properties: [ 'openFile', 'dontAddToRecent' ],
+ filters: [
+ { name: 'AppImage Files', extensions: ['AppImage'] }
+ ]
+ });
+ });
+
+ ipcMain.handle('wrc-set-home-and-start', async (event, wlRemoteConsoleHome) => {
+ return setWebLogicRemoteConsoleHomeAndStart(event.sender.getOwnerBrowserWindow(), wlRemoteConsoleHome);
+ });
+
+ // eslint-disable-next-line no-unused-vars
+ ipcMain.handle('wrc-get-home-default-value', async (event) => {
+ return getDefaultWebLogicRemoteConsoleHome();
+ });
}
async getLatestWdtInstaller(targetWindow) {
diff --git a/url-catalog.json b/url-catalog.json
index d29596c32..7441ebb53 100644
--- a/url-catalog.json
+++ b/url-catalog.json
@@ -1,4 +1,7 @@
{
+ "model": {
+ "weblogicRemoteConsoleLatestRelease": "https://github.com/oracle/weblogic-remote-console/releases/latest"
+ },
"image": {
"imageTagFormat": "https://docs.docker.com/engine/reference/commandline/tag/#extended-description"
},
diff --git a/webui/src/js/models/wdt-model-definition.js b/webui/src/js/models/wdt-model-definition.js
index e6c566cf8..c0650163d 100644
--- a/webui/src/js/models/wdt-model-definition.js
+++ b/webui/src/js/models/wdt-model-definition.js
@@ -40,6 +40,8 @@ define(['knockout', 'utils/observable-properties', 'js-yaml', 'utils/validation-
// internal values that are implemented as properties, but are excluded from default serialization
this.internal = {
+ wlRemoteConsolePort: ko.observable(),
+ wlRemoteConsoleHome: props.createProperty(window.api.ipc.invoke('wrc-get-home-default-value')),
propertiesContent: createPropertiesObject({})
};
diff --git a/webui/src/js/viewModels/model-design-view.js b/webui/src/js/viewModels/model-design-view.js
index 43c07f0df..5cac655ba 100644
--- a/webui/src/js/viewModels/model-design-view.js
+++ b/webui/src/js/viewModels/model-design-view.js
@@ -1,26 +1,83 @@
/**
* @license
- * Copyright (c) 2021, Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022, Oracle and/or its affiliates.
* Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
*/
-define(['accUtils', 'utils/i18n'],
- function(accUtils, i18n) {
- function ModelDesignViewModel() {
+define(['accUtils', 'utils/i18n', 'knockout', 'models/wkt-project', 'utils/url-catalog', 'utils/wkt-logger',
+ 'ojs/ojinputtext', 'ojs/ojlabel', 'ojs/ojbutton', 'ojs/ojformlayout' ],
+function(accUtils, i18n, ko, project, urlCatalog) {
+ function ModelDesignViewModel() {
- this.connected = () => {
- accUtils.announce('Model design view loaded.', 'assertive');
- // Implement further logic if needed
- };
+ this.connected = () => {
+ accUtils.announce('Model design view loaded.', 'assertive');
+ // Implement further logic if needed
+ };
- this.labelMapper = (labelId, payload) => {
- return i18n.t(`model-design-${labelId}`, payload);
- };
+ this.labelMapper = (labelId, payload) => {
+ return i18n.t(`model-design-${labelId}`, payload);
+ };
- }
+ this.isLinux = () => {
+ return window.api.process.isLinux();
+ };
- /*
- * Returns a constructor for the ViewModel.
- */
- return ModelDesignViewModel;
+ this.project = project;
+ this.i18n = i18n;
+
+ this.disableStartButton = ko.observable(false);
+
+ const wrcInitialText = this.labelMapper('wrc-install-description');
+ const wrcInstallLocation = '' +
+ this.labelMapper('wrc-link-text') + '';
+ const wrcInstallParagraph = this.labelMapper('wrc-install-location-prefix') + ' ' + wrcInstallLocation +
+ ' ' + this.labelMapper('wrc-install-location-postfix');
+ const wrcStartParagraph = this.labelMapper('wrc-start-description');
+ this.wrcInstallInstructions = wrcInitialText + '
' + wrcInstallParagraph + '
' + wrcStartParagraph;
+
+ this.showRemoteConsoleConfigForm = () => {
+ return !project.wdtModel.internal.wlRemoteConsolePort();
+ };
+
+ this.showRemoteConsoleComponent = () => {
+ return !!project.wdtModel.internal.wlRemoteConsolePort();
+ };
+
+ this.getWebLogicRemoteConsoleHomeHelpText = () => {
+ let helpKey;
+ if (window.api.process.isMac()) {
+ helpKey = 'user-settings-dialog-wrc-home-macos-help';
+ } else if (window.api.process.isWindows()) {
+ helpKey = 'user-settings-dialog-wrc-home-windows-help';
+ } else {
+ helpKey = 'user-settings-dialog-wrc-home-linux-help';
+ }
+ return i18n.t(helpKey);
+ };
+
+ this.chooseWebLogicRemoteConsoleHomeDirectory = async () => {
+ const rcHome = await window.api.ipc.invoke('get-wrc-home-directory');
+ if (rcHome) {
+ this.project.wdtModel.internal.wlRemoteConsoleHome.observable(rcHome);
+ }
+ };
+
+ this.chooseWebLogicRemoteConsoleAppImage = async () => {
+ const rcHome = await window.api.ipc.invoke('get-wrc-app-image');
+ if (rcHome) {
+ this.project.wdtModel.internal.wlRemoteConsoleHome.observable(rcHome);
+ }
+ };
+
+ this.startWebLogicRemoteConsole = async () => {
+ const rcHome = this.project.wdtModel.internal.wlRemoteConsoleHome.observable();
+ // TODO - do we need a busy dialog?
+ return window.api.ipc.invoke('wrc-set-home-and-start', rcHome);
+ };
}
-);
+
+ /*
+ * Returns a constructor for the ViewModel.
+ */
+ return ModelDesignViewModel;
+});
diff --git a/webui/src/js/viewModels/user-settings-dialog.js b/webui/src/js/viewModels/user-settings-dialog.js
index 50ed22c37..734b34ea6 100644
--- a/webui/src/js/viewModels/user-settings-dialog.js
+++ b/webui/src/js/viewModels/user-settings-dialog.js
@@ -22,6 +22,10 @@ function(accUtils, ko, utils, i18n, ArrayDataProvider, project, wktLogger) {
return i18n.t(`user-settings-dialog-${labelId}`);
};
+ this.isLinux = () => {
+ return window.api.process.isLinux();
+ };
+
this.userSettings = {};
try {
this.userSettings = JSON.parse(payload['userSettingsJson']);
@@ -49,6 +53,7 @@ function(accUtils, ko, utils, i18n, ArrayDataProvider, project, wktLogger) {
this.connectivityTestTimeoutSeconds = ko.observable(payload.defaults.connectivityTestTimeoutMilliseconds / 1000);
this.internalConnectivityTestTimeoutMilliseconds = ko.observable(payload.defaults.connectivityTestTimeoutMilliseconds);
this.skipQuickstart = ko.observable(false);
+ this.wlRemoteConsoleHome = ko.observable();
this.loadUserSettings = () => {
if ('proxy' in this.userSettings) {
@@ -87,12 +92,42 @@ function(accUtils, ko, utils, i18n, ArrayDataProvider, project, wktLogger) {
if ('skipQuickstartAtStartup' in this.userSettings) {
this.skipQuickstart(this.userSettings.skipQuickstartAtStartup);
}
+
+ if ('webLogicRemoteConsoleHome' in this.userSettings) {
+ this.wlRemoteConsoleHome(this.userSettings.webLogicRemoteConsoleHome);
+ }
};
this.chooseLogFileDir = async () => {
this.fileLogDir(await window.api.ipc.invoke('get-log-file-directory-location'));
};
+ this.chooseWebLogicRemoteConsoleHomeDirectory = async () => {
+ const rcHome = await window.api.ipc.invoke('get-wrc-home-directory');
+ if (rcHome) {
+ this.wlRemoteConsoleHome(rcHome);
+ }
+ };
+
+ this.chooseWebLogicRemoteConsoleAppImage = async () => {
+ const rcHome = await window.api.ipc.invoke('get-wrc-app-image');
+ if (rcHome) {
+ this.wlRemoteConsoleHome(rcHome);
+ }
+ };
+
+ this.getWebLogicRemoteConsoleHomeHelp = () => {
+ let helpKey;
+ if (window.api.process.isMac()) {
+ helpKey = 'wrc-home-macos-help';
+ } else if (window.api.process.isWindows()) {
+ helpKey = 'wrc-home-windows-help';
+ } else {
+ helpKey = 'wrc-home-linux-help';
+ }
+ return this.labelMapper(helpKey);
+ };
+
this.storeUserSettings = () => {
project.setHttpsProxyUrl(this.proxyUrl());
project.setBypassProxyHosts(this.bypassProxyHosts());
@@ -107,12 +142,12 @@ function(accUtils, ko, utils, i18n, ArrayDataProvider, project, wktLogger) {
this.internalConnectivityTestTimeoutMilliseconds, payload.defaults.connectivityTestTimeoutMilliseconds);
}
this._storeSetting('skipQuickstartAtStartup', this.skipQuickstart, false);
+ this._storeSetting('webLogicRemoteConsoleHome', this.wlRemoteConsoleHome);
};
this._storeSetting = (key, observable, defaultValue) => {
const keyPath = key.split('.');
if (defaultValue === undefined || defaultValue !== observable()) {
-
let currentObj = this.userSettings;
for (let i = 0; i < keyPath.length - 1; i++) {
if (!(keyPath[i] in currentObj)) {
diff --git a/webui/src/js/views/model-design-view.html b/webui/src/js/views/model-design-view.html
index c6495f68e..bcac442b9 100644
--- a/webui/src/js/views/model-design-view.html
+++ b/webui/src/js/views/model-design-view.html
@@ -1,9 +1,43 @@
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webui/src/js/views/user-settings-dialog.html b/webui/src/js/views/user-settings-dialog.html
index 2cec6588f..43a501b16 100644
--- a/webui/src/js/views/user-settings-dialog.html
+++ b/webui/src/js/views/user-settings-dialog.html
@@ -21,6 +21,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webui/src/js/windowStateUtils.js b/webui/src/js/windowStateUtils.js
index 0ffe338ac..9cafe0300 100644
--- a/webui/src/js/windowStateUtils.js
+++ b/webui/src/js/windowStateUtils.js
@@ -247,7 +247,7 @@ function(wktProject, wktConsole, wdtDiscoverer, dialogHelper, projectIO,
return doDirtyCheck('window-app-quit');
});
- window.api.ipc.receive('show-quickstart', async() => {
+ window.api.ipc.receive('show-quickstart', async () => {
dialogHelper.openDialog('quickstart-dialog');
});
@@ -255,6 +255,10 @@ function(wktProject, wktConsole, wdtDiscoverer, dialogHelper, projectIO,
return appUpdater.showStartupDialogs(startupInformation);
});
+ window.api.ipc.receive('set-wrc-backend-port', (port) => {
+ wktProject.wdtModel.internal.wlRemoteConsolePort(port);
+ });
+
async function doDirtyCheck(responseChannel) {
return new Promise(resolve => {
if (wktProject.isDirty()) {
From 6081eda2d083880c69d1ec97e737e06593473d05 Mon Sep 17 00:00:00 2001
From: Robert Patrick <31662131+robertpatrick@users.noreply.github.com>
Date: Fri, 11 Feb 2022 18:49:11 -0600
Subject: [PATCH 03/99] converting all aria-label attributes to use i18n
resource bundle (#94)
---
electron/app/locales/en/webui.json | 14 ++++++++++++++
webui/src/js/views/app-main.html | 2 +-
webui/src/js/views/domain-design-view.html | 4 ++--
webui/src/js/views/ingress-design-view.html | 2 +-
.../views/macos-environment-variables-dialog.html | 2 +-
.../js/views/macos-path-directories-dialog.html | 2 +-
webui/src/js/views/model-archive-view.html | 4 ++--
webui/src/js/views/model-properties-view.html | 2 +-
webui/src/js/views/project-settings-page.html | 4 ++--
webui/src/js/views/quickstart-dialog.html | 2 +-
webui/src/js/views/route-edit-dialog.html | 2 +-
11 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json
index 95126758a..0fde7d43a 100644
--- a/electron/app/locales/en/webui.json
+++ b/electron/app/locales/en/webui.json
@@ -1,6 +1,7 @@
{
"copyright-footer-text": "Copyright (c) 2021, {{currentYear}}, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0, as shown at",
+ "nav-aria-label": "Choose a navigation item",
"nav-model": "Model",
"nav-project-settings": "Project Settings",
"nav-image": "Image",
@@ -81,12 +82,14 @@
"project-settings-form-name": "Project Settings",
"project-settings-title": "Project Settings",
"project-settings-mac-environment-question": "For macOS, do you need to add directories to the PATH or define other environment variables for Docker/Podman or Kubernetes?",
+ "project-settings-mac-path-table-aria-label": "macOS Extra Path Directories Table",
"project-settings-add-path-row-icon-text": "Add Extra Path Directory",
"project-settings-choose-path-icon-text": "Choose Extra Path Directory",
"project-settings-delete-path-row-icon-text": "Remove Extra Path Directory",
"project-settings-extra-path-directory-header": "Extra Path Directory",
"project-settings-hints-macos-path-directories": "Show System Path Directories",
"project-settings-button-macos-path-directories": "Show System Path",
+ "project-settings-mac-env-var-table-aria-label": "macOS Extra Environment Variables Table",
"project-settings-add-env-var-row-icon-text": "Add Extra Environment Variable",
"project-settings-delete-env-var-row-icon-text": "Remove Extra Environment Variable",
"project-settings-extra-environment-variable-name-header": "Extra Environment Variable Name",
@@ -144,9 +147,11 @@
"project-settings-credential-store-policy-answer-message": "The Credential Store Policy controls how credentials are handled when the project is saved and loaded. The options are to store them in the machine's native credential store, store them in the project file encrypted with a passphrase, or not store them at all.",
"macos-path-directories-dialog-title": "System Path",
+ "macos-path-directories-dialog-table-aria-label": "System Path Environment Variable Directories",
"macos-path-directories-dialog-name-header": "Path Directory",
"macos-environment-variables-dialog-title": "System Environment Variables",
+ "macos-environment-variables-dialog-table-aria-label": "System Environment Variables Table",
"macos-environment-variables-dialog-name-header": "Environment Variable Name",
"macos-environment-variables-dialog-value-header": "Environment Variable Value",
@@ -578,6 +583,7 @@
"domain-design-cluster-additional-java-options-label": "Additional Java Options",
"domain-design-cluster-additional-java-options-help": "A list of additional Java runtime options, separated by spaces, tabs, or commas.",
+ "domain-design-configmap-table-aria-label": "ConfigMap Properties Table",
"domain-design-configmap-title": "Model Variables Overrides",
"domain-design-configmap-label": "Kubernetes ConfigMap Name",
"domain-design-configmap-help": "The name of the Kubernetes ConfigMap that holds the model variable overrides.",
@@ -614,6 +620,7 @@
"domain-design-propname-header": "Model Variable Name",
"domain-design-propvalue-header": "Model Variable File Value",
"domain-design-propoverride-header": "Model Variable Override Value",
+ "domain-design-secrets-table-aria-label": "Secrets Table",
"domain-design-secretname-header": "Secret Name",
"domain-design-username-header": "Username",
"domain-design-password-header": "Password",
@@ -678,6 +685,7 @@
"ingress-design-ingress-route-is-console-svc-help": "For SSL terminating at ingress and accessing WebLogic Console Service, turn on this option. Your domain must have 'WeblogicPluginEnabled: true' in the 'resources->WebAppContainer' section",
"ingress-design-ingress-route-name-label": "Name",
"ingress-design-ingress-route-dialog-title": "Edit Ingress Route",
+ "ingress-design-ingress-route-annotations-table-aria-label": "Ingress Route Annotations Table",
"ingress-design-ingress-route-annotation-label": "Annotation",
"ingress-design-ingress-route-annotationValue-label": "Value",
"ingress-design-ingress-annotations": "Optional Annotations",
@@ -720,6 +728,7 @@
"ingress-design-generate-tls-subject-label": "Subject to Use for the Generated TLS Certificate",
"ingress-design-generate-tls-subject-help": "The Subject (e.g., /CN=www.mydomain.org) to use when generating TLS certificate. The format must be /type0=value0/type1=value1/type2=...",
+ "ingress-design-routes-table-aria-label": "Ingress Routes Table",
"ingress-design-add-route-label": "Add Route",
"ingress-design-edit-route-label": "Edit Route",
"ingress-design-delete-route-label": "Delete Route",
@@ -1004,10 +1013,14 @@
"model-page-hints-prepareModel": "Prepare Model for Kubernetes",
"model-page-model-editor-contents": "Model Editor Contents",
+ "model-properties-table-aria-label": "Model Variables Editable Table",
"model-properties-name-header": "Variable Name",
"model-properties-value-header": "Variable Value",
"model-properties-add-label": "Add Variable",
"model-properties-delete-label": "Delete",
+
+ "model-archive-toolbar-aria-label": "Archive Editing Toolbar",
+ "model-archive-tree-view-aria-label": "Archive Editor Tree View",
"model-archive-add-label": "Add",
"model-archive-delete-label": "Delete",
"model-archive-no-archive-label": "(no archive)",
@@ -1299,6 +1312,7 @@
"quickstart-dialog-title": "WebLogic Kubernetes Toolkit (WKT) UI Introduction",
"quickstart-dialog-stop-showing-quickstart-message": "Stop showing this introduction at startup.",
+ "quickstart-dialog-filmstrip-aria-label": "WebLogic Kubernetes Toolkit UI Tutorial",
"quickstart-page1-title": "Introduction",
"quickstart-page1-paragraph-1": "Ready to get your WebLogic Server domain running in Kubernetes?",
"quickstart-page1-paragraph-2": "This application will guide you through the process of creating a WebLogic Server domain in Kubernetes.",
diff --git a/webui/src/js/views/app-main.html b/webui/src/js/views/app-main.html
index a8a01308d..684da44ba 100644
--- a/webui/src/js/views/app-main.html
+++ b/webui/src/js/views/app-main.html
@@ -16,7 +16,7 @@
-
-
@@ -27,7 +27,7 @@
data="[[archiveDataProvider]]"
selection-mode="single"
on-selected-changed="[[selectionChanged]]"
- aria-label="Tree View with JSON Data">
+ :aria-label="[[labelMapper('tree-view-aria-label')]]">
diff --git a/webui/src/js/views/model-properties-view.html b/webui/src/js/views/model-properties-view.html
index 8b97f888b..0554cc8ca 100644
--- a/webui/src/js/views/model-properties-view.html
+++ b/webui/src/js/views/model-properties-view.html
@@ -4,7 +4,7 @@
-->
+
+
+
+
+
+
+
+
+
+
-
+ readonly="[[isAuxImageTagReadOnly]]"
+ help.instruction="[[auxImageTagHelp]]">
-
+
@@ -28,27 +28,31 @@
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -361,22 +365,15 @@
+
-
-
-
-
-
+ help.instruction="[[labelMapper('aux-image-tag-create-help')]]">
-
-
-
-
+
+
+
+
+
-
-
+
+ value="{{project.image.auxImageRegistryPushUser.observable}}"
+ help.instruction="[[labelMapper('aux-image-registry-push-username-help')]]">
-
-
+
+ value="{{project.image.auxImageRegistryPushPassword.observable}}"
+ help.instruction="[[labelMapper('aux-image-registry-push-password-help')]]">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
+ value="{{project.image.auxDefaultBaseImagePullUsername.observable}}"
+ help.instruction="[[labelMapper('aux-default-base-image-pull-username-help')]]">
-
-
+
+ value="{{project.image.auxDefaultBaseImagePullPassword.observable}}"
+ help.instruction="[[labelMapper('aux-default-base-image-pull-password-help')]]">
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From a6311b5d4f9896dcc6ac2d0fc0a8264000d2e7d0 Mon Sep 17 00:00:00 2001
From: Robert Patrick
Date: Thu, 17 Feb 2022 17:30:12 -0600
Subject: [PATCH 09/99] adding doc config required to format two images
positined side-by-side
---
documentation/1.1/config.toml | 1 +
documentation/1.1/static/css/theme-wktui.css | 8 ++++++++
.../1.1/static/images/auxiliary-image.png | Bin 0 -> 40160 bytes
.../1.1/static/images/primary-image.png | Bin 0 -> 36601 bytes
.../themes/learn/layouts/shortcodes/himg.html | 8 ++++++++
5 files changed, 17 insertions(+)
create mode 100644 documentation/1.1/static/css/theme-wktui.css
create mode 100644 documentation/1.1/static/images/auxiliary-image.png
create mode 100644 documentation/1.1/static/images/primary-image.png
create mode 100644 documentation/1.1/themes/learn/layouts/shortcodes/himg.html
diff --git a/documentation/1.1/config.toml b/documentation/1.1/config.toml
index 0e02910d9..2533e829e 100644
--- a/documentation/1.1/config.toml
+++ b/documentation/1.1/config.toml
@@ -17,3 +17,4 @@ publishDir = "docs"
[params]
# disable the copy to clipboard links
disableInlineCopyToClipBoard = true
+ custom_css = [ "css/theme-wktui.css" ]
diff --git a/documentation/1.1/static/css/theme-wktui.css b/documentation/1.1/static/css/theme-wktui.css
new file mode 100644
index 000000000..fa0468255
--- /dev/null
+++ b/documentation/1.1/static/css/theme-wktui.css
@@ -0,0 +1,8 @@
+.wktui-two-images-column {
+ flex: 50%;
+ padding: 5px;
+}
+
+.wktui-row {
+ display: flex;
+}
diff --git a/documentation/1.1/static/images/auxiliary-image.png b/documentation/1.1/static/images/auxiliary-image.png
new file mode 100644
index 0000000000000000000000000000000000000000..c12a2c5777afafe925ba91772197489f5021e6ad
GIT binary patch
literal 40160
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
literal 0
HcmV?d00001
diff --git a/documentation/1.1/static/images/primary-image.png b/documentation/1.1/static/images/primary-image.png
new file mode 100644
index 0000000000000000000000000000000000000000..71e281efd7621b5c1814ece4bb31d7d3a6affc28
GIT binary patch
literal 36601
zcmZ_0WmFtp5G@J}uEU_gU4pyY;F4eo4DRmkGDvU<77`$kU;zdh++7kpKyW9x1t&;&
z!*^xf``&s#SO>aix=&Z1Q?;vhZQ`_EE8}5PU?U+R;i;-9=pZ4XP$D5AXJVowj_CUc
z#3BYPcNGIKBqSW7=O1LGPr2lXgUDVw%3!3bajJd9AERkMl5s-@IKMTr)3X`4*doilYN^o+;o~d8=I>A3?0xt%!=|>ktn^Y5m4AfR^!9
z9j=8+yzk4vRt5S5QDLKPRRpeH0MHY571%38V;$xlWH7
zZ&C%%Nia1!3ej(j?MDRvwYZS*wEpGfd6mmdOcezLN4zt$WVAYmh_U|lRNb4BSFt`@
zBdPv=mRP+VUv`1`045eX$%Dh?MWbNZLT6#>cK}N5x>gC|IDJnq4;*Z{pcb8$Y+l
zB{DG=*m_Whs65v~o~Nt;ptoA!)(>u0vxjmR(V1$?^DAz->>bNU`LKQQJA#k6f60X(X4kJbgA
z@vepe@od96KqAVs#d2uR!dqGLiosO5$lOKEe6hM%QD{N7piMlL-K-{Zp|NS1
zL0!LU(uK}*hYPZP-7LDh3P3-Yi)@teJ)YvGHgjc0JRs8ymY9gznrX)+Qi9F*g5G9y
zh>&@bN-e5xFKDXL%Z_@_!6m2BreZZ~vEJbQKfct+qJE~7U8Dr%olv`q?>m)7+XD*|
z71B8eyT?XNStkdCD2^~zmra#~R`0Z|eVs{crFq4GbI6rVyJ2HrPA2E<{yajB);IJi3rB@l`H_jJZKvLyf@V+?%!>?!j-M~-rV
z^D~Mpy-FI0D0kLC5lL3^yBX~Zo`7OM6+2uwZO2zo;?Ub5qaKqaQH=c1?RuH87&KL8L_i;f`dTF(ufm71MGnA4^BE%4
zV-++_dV&ohu92x#UH++cg<;OMzhi+EgENqB(~tB8I-mT5h{gw#(7HAQ6~ezx>d9Oz
z7ZPXNDG{t<*wm(t$?jC;JfqOL+NO+2&&+7e5qsUxMhi^cXZPx#G&T@1e-X}sMvCtS
zrf&%aaDlR5#v8s8mQ0f$N|AJs4zW1NVwY+RC1G-vW5?Xox#=?NLIq|JM`JSm3N=CS
z92PslOFbA<>1#fv*wi#ot))C!rw%u9Gn>}0X-e``K8U>ikyfOHLb!+$2M#8TtVTf=
zcdr?zAv;4CliIJR7~LAS{-B}8xy=1-?0ud|b~(0OdUk3-|CFw{4e4GYF#%fNA_o)|
z2cJ`Lj{xUdVCdNs^=77e7n1Yt-CPNDgJx6q9lJ3;8?&Lu5?N;zJU;ftNX$|~tzK1M
z_3yoBwD}i-Hg$BT*SN)TgE3p#lz?@4HFYsDvK~V-#a{RBn#P#fKd&aSyO!T&7S=mg
zyx4fNF@^BHVDQIm0c^9Re<5BtEw0-^po4B5yW;=+&U8qTaJjsOT!ra=GFp02)#1_1(xQ9J(Fl1>Oc@o0Zb2`sRVg678uW#G^sOh8M4QShY~q31
zaioN@4L&1|W&Uhe8i%qmpW^Xe22%;&)3l-})HvOH3nc?7{df@Sx3vxN{P+gidR3R%
z8CA*k+s4j`y^mH#f(ybeN^zuNyK>u
ztst+hQD+A!>JPgzpF`k8dnWMbJ=voB=uGbbhFzK2T`rbgr(n))F?eX?b2q^rnl0
z>3FL$P@*3_i}cke9cP4L<5Uoa?GE7&>j8hfogtR$wpvX)$&%Me1u83N!I!}u=5T$Hy!FNH(rVF1SADH5
zP<2k?G($B-`k+BjoPOhb0jr(LEP)KEQ~n}ZE)Nb3<=dC{L||}2Y98f4d>M8;XsgE4
z{Ljf(bVuB4Xt>9kyaUcrg}^qxJ7sy%2%t$^0$G1-tGMngd2E-tAs1|i91zDq-Ch1k>Z7)Z=G;*
z*ka!^ibY!jh-wKzF7?fl2JaRCg85XQ)udR|Iys`7;-jr62V%2rmWzY>73E7P)1-%k
zE7Q~PD#cjT5)gQqNYAnli30#5tRc^sg?$TXY0)u0Uye=RY6h9qU8}NB#OgA
zw~C6rVix&Dq*yIj<0a>&n6n2J&Skh8-fF+OD;j&XuH9IMc1rTx1ihfGi3
zdoXpZWBB196~WSbbcx$9F}aKLwXf0Rct-zj1b?V9rl-`avOM5G0JB&oXB{&|7W)cx
zR19<*zv&vQ)YGMkQvB7#l#~lmK1yRcE2U)bX36EN=#ZgA@-KH(dvKZlWM|0LyT)LD
zM*!glmeJx7T?oyFp=TaY)A@--*Dfdg{-_K_TXH(vleZ2J;8Az|hZW#59V6b>Pckhm
z(j|LJfLInm*S|88efB7ON}^IHnP9ddugyO+8}Ke^H!?!y`slchFjM$_e$m@_f0ch{;Z4fJ{2CRvr*qcBF}k#r5^IGhONo
z*$-(Qb1eE*tfFQAG|vz1QeJBR<8*K9I66I(x7^zak4Klc(q#W!GDrd6Fda)mL=I0n
zizAm7EMG0%mcR8jGGDY@kx|C;fgPqULNMvSBp^U_qhWh4w>fpJ%5QIJ8GR5H9TSCV
zAUrg2e|M~vDX6>D;DgTd9+`WD(=iS-aLo#}Uos4dqsM?ii?__e<+JKpxmOj@3N%Ag
ztC
zxQ(V)Kjeo>vXs95OswPk98SO=6))`COu|(2T0LDxgh6Dq{)^)D{W1?AN<{K-fV{ud
zBJlgqS21ueZS$ZxymvQ#LL?VD3Aq^bY&kDy@suCp)`9CV)Az5x#+6H@`99C;q{o$R
zbb2J;Bd3yjCP9e?&^a$E1MO?%-NF7z_#TPUZ}iwLHL6YT%ng(13#jmB$ofof{cY?u
zX2~SUl<_(~BYAyzj30>dLk7&ROT;M
zHsq&TSCSC!jKJ?`7N^;!ANBF3p-INuS>#Y-!DEh2+s&niE(ps@^ZvdsGwIX!xu6>a
zaBbFdPK^z(N}t?3l|RYcwA|5PPkMYTwj5CNJRr6TMu15~a7xt~Dk{&KdtOTsmXSc6
z15_R4`Xck*MzoY95LjhT4laku?gMO(V_%af5`JHcH2srSOs{eC9dJ|T`RfJY2VY7A
z18SfoHuoYQpF^pr2sS;_Q8@F~g1#QH#C9f7M_LOJ3wo1V++cHM@TIO*LabpGdfIlbj*7y1zFrNW46c#F%oO~bL!qLfIkY+-$^V({L3<1fgp;g&=Ji{3^a5}y>8@+uVuV@%#%XT$78dX(?y?L@@
zQ&`o#f|=Ez)K{9JHmMK3)UK0DB~tf^MJ0`s6A50D;NCos#~{S=Bu6+`^GVtY^!wlM
zJ{&?r|54>MXY+YACQ^tQCqO@tcEXlyt&hAGCt^YJt|uM~@Q}8-Ej$`Q*+sv-f_sJg
z#E|<-4|+r637dVVYVmQjV_5It+7=jFR-QXx#vZF5K6t%nw(M!
z6@7XJ5)`Mfh>7`EmNhfCIp2%>KmMwh^ro;~uu6Tn+Lv!3aNChm(94XsS32NWw_ZJG
zYg#b|12xR>053E5W@Q$R_i*1aBmOhD6t%=V5$nAghN|>UeybhMk1~GA4*`=MX>ZyZ
zbrWL`TQ~!*Y>qwYnLc%QkN4yOH{)tZC^6@W8~QoOl-jOE_PRCY{g_c}WW8l$>0W<5
zU3n}H4EFgU5xQJP3t<3`?&Cp3SY*T$WrRae7)4>bQ^p3mgKRj6FaZQRM^(;eU*41k
zx2n>K(($H}pupdMgMns82~&$JtQYvR&r=+&NSUwXdTe6r|}ltAB%o;*ebJ_eZ3P9c<1YK
z{0HsMq?D6>c8lJKxp-syIjAb&5bDq1z)4iNk`hv;xzjSi1%UKBr>0-TR`Q
z7BX!5qKA!THd09}JkUQ`dr9ft>Zw*miI&}Qs7^6x_h;;z*SVaj6F0%-GN-KXq?8fP
z4io5s{57iCYJU)I3hraq((+0lI|&mb-)+gsb+Q+f#R*pVD-W0Z8j*J|olcrmO$3sv
z*Ny;i3;fUH=!Sw{6JBOk@CwJI0-*?xgRrDrv}GR#5p7NZj@R>|XX5>8=?1+Ap
z*+o-bdiY{(NB#36&0I(L%|)=s2~`I*H%Mdroli$*@mAp&?Ovm;t$vNd@y*x3&t?5s
z$yUoR_phxiq>}mkCy}`LokJF8bGAT;ng3MlC%)>l0PjTxoiJmAB2LpqRyV)JtQCr|z!pc;C_tXpn`(}94Q{x(
zS#cQRP6ZMRPP>kCzPHaw%oClhz7Fy|dha*aRk1`nD#_-?9W?C_WNa+tFw+jNcbqH#
z&e#4E?xgGhyS^CA8ClDSe1T!J_w7sI>-?$pK~fR5r=G{+r^iRB#sIrViSvPE9<{6H
zsMJ5KmX^Z2A?;sUKr|ok`7f<7u_06^`XfbMul_X47&9F&`MI}^9SFzio`5v?s&BM6
zZH^a(46V(fLTFh@*9ae((zZIKUEMTJq2BwUy3N7W&yv}4
zBy+0@8}PK(m6(d>*2NJw%wWMuc@kS~YSP5R4P^U)=W<5A;@U6XY7Rs
z?F>XGkT((T)H^Pzm6V4838n5X-C-gCaTxjR6-H+Ew+}iKWhpcrL81oCbjC^qFSrV6
z$+@a416~=4!LpK9R{RdH{~78cp{ju`BN{(-_gWnD%=^~`0>NKD#KN7A=Kr;9@mapq
zp)jrL@AHuQ(^qMM0O_boYHIPdI_+<*J4DQT!o#84eVp!f#McX2nojw!JA8%jsgo!u
zje3?`tQ@E(n+@Mos#t@3Nev0jO~Nr978;A^q<^km{+;#-(ic%LXm7cE#U<#fcS4#Q
zSuudN>x>He2bMILpd@{-ZyKz~bHd4Je=%4qa_Q@L?}(Een7EZaR5j#ha(bAJc%Lkm
z{Ypwo?;7dM<+OGH@-h3+uBFPRL*ltr@i8H#79-~chDMhr2Yn0__50NoGpzK3yOzp)
z8tIgUo0A}K+46Ax%^ZN}N
zuV7@ArI(5y2f05X@B2B)xC}s>BPhQg5dhsHLe4MFnYp=N%QRwx!f&vK+@)Axl6yqE
zs0q0AOrEjiBG~Am5Ri9#1+xu_KnuQhFQ9vvPvM0<=+4tzz|i^at~C)eVe
z?AzQRXvi=Z%Qonc>xtK
z>^)*mIIQ}y`E`v~@SrtDc?7j@abxFrxvBL}TApZz#J(oQDV{M2BHcA&vk?(&vUig(
z^gEux4NbeDiIIjdgA^=_i0jXHOi@v^g!IBRH-M2u#3pl;80?8zNGY5^g9td=5+k>gWmT&Emzz2McK#R+2T3C_kW}hZspb
z4Gcm@0Xi}Re!(#!>r=?F0q$tMfZ2$1cXc|z5bDHch?md)`eS>c-%oP(uuT(8`VG1M
zl1>na^MC`VzfDc6+s1-gH0jsYFETSOy>@gMJ`k|QlAJEf_kyKQ36CS~0Q)_ZPJ`NL
zgIlb7k
zbOmHmh^%?EEH9HKr5gV_!~Aq^4xyB7Ps?rkF$xZ9gjkZzV1HmUDIW*-&aL=f-Qn2l
zvllES05Iw)WpdmWA7ymv_lPV!aC{sb#T@8^SJH1@jpNYZW2Q1v6pS(*BgDw0MF&ir
zbjKLS;HGgC;xxbNHcx?3q@Txo_5TgPp}4}JT0@;S>^Xe59uA2h_o&yeE>?D1+uucO
zaJrpDa4dj`O5E3ZoyA3`mGhH~5jy@0nm@k0>t{>WgHbKu;K(;`boDxl7z#znaj*}(
z-X!qk$^O#TeK)+xx_Z7?B3Q)(j`g!&poDuwdfx$c8hLI1SAhOsqdYwL
zujk)`5uOCtlTKxyFe21Nq2dp`+bplBN((wYK4lW66GUGQN?G(Reva)-?&NeYh2ikq
zZTWJIq)lJ7{2J}N^7
z4y15eg>dVe{!(z=n^%0PSI!hA>-~S^dPLU|g$U4e0JTGapYz!^j%WpL_m4ek(G!&U
z5(p#}_vpN&=dk!-*s|&PI!XZ>y4U_y+e$3pK;PynP*dCo=V|IExxdmSH4g%c3}<1l
zQA;yjrBh^^(XJq}Ud!*U%TxEc|4g#8zk#S~C
ziKnEcU2nwjUoDhgZM_h%Q&+>DPKo?6u6aFtS4{i88m$XE4u8BNAbHt+>1ql_Qc6u%
z)Xwe)e-C%dKT=uaHZV}mMgPm)i!ZARrdSrNbsu#Il-?C6};b8;gz~A7`
z!yq;ZIodfApXZ5@imlRbgV
zJzi^DYx^(AQ<*>ySW`XUeKf~PX2HVW0sTOzP&Dd?C+hoXFynCd?xPd3Q$G-dozZ5)
zD0D?(aJN`-cOuPbmG8@1#XGOD$}&Kqs?hZqQ11cdo+6a%5)iQI3{QPyV@@
z{fE2pGur0uSHJ$LqRGOEO&Ys~k^;O-C}!p=4Y)#nh38l_IWsL)Qn**((g=22pdkZM
zR2|n%8_)5iv?!-C?N!&LyUR?fJZ%ch!p?l#Kag_!Vxshi$;!3>c2PaxddGIlY-0_O
zvdUr#7VS@v6H6pdI1W(BeQoEr(d_!R&q_*xd!K
zubs0J8k}7CNXWlgB-vM?8{wWi9m7eH0KDif0yTXu&;hm2WC@CC%>R1KM&7+uAcq&;
zmz$6~c__3fy1VY=-e0!Mx5d>aQ+Z%!GO0Vi;~11m@4v-G>?cA6l~_Eh1*96FtTnkl
z7AJ`W44QY{7VIR6&WSu`!Y{tL0>Q@(XbDIjiffP}_(yXi6S{opiwU%fgMapGI%x{P
zQ;W7izvm^%LZos`gdj^sG3EjONg92n(n|ZusKwx@cU&1=p>oXRUS5h*$9(wV!(A9XtOv
zZHkzSGA-Ugu}U2a7ZW}GkA3o0`<3#J`j*ue{}mY7=S;`)uKN?}1K)fu+AuaFnFUx=
zjupv==z|99iaEiJ4c14;l({gw{MYAueVQt}My@_fw(IMrwNJ9|=7ghCzcX7S(st5)
zPrTUrEas+0dF=fn)>2V^@KnY?52<RzNf(agFehe@=|Hv3TeN#%fm(V
z{fT>uGq
zQ
B
zYSko*VKhMI`L)HN3_F_i+``UEtd5hTQZ9m=j6d*ew`BO$))@cZDn=1gVz507F<%D|
zzhz<3JZjW#n;4OwwxR#Qh;>gvEIA8Q-WY54qccUAz^mX68jvv^Djfr?`zx|GTrn=0
zkRZtm7Q^PSDEiAO49E)v`JJ2;4fGzd;4lH{?A=}6dz$0%Adqkm-R?WMQKf)hYRPbt
z6^ZB|N`y3h0mY2lH`>$Mo9Q2$C*9)Ba_1R2AeZ%34?8J239G+70k^d^kfp5-m*Y+0
zT32N=J$+(?pI9fpDAo`$30%Imik(kZRdYwo#Sas;A6I0cU1jfQy$8X47mZg(^ap9T8X=MeE9@gi9&jkVcFGTC2N
zL^2cI><443tg7wuGoP`4n3M)`fe;z#1DZg=W7_eh&RBA0WFkEW4vBxc2aA;0z4-
z>>491O4je;?Bk(m0L`?!HG6{H5ByEizc<`60p?q-ByVv;B=r%{Q@I}^3`T=!t*1eA
z6x+Z@4z;l>>w@PS@&avW=A{&qOU7%f8{!UMNt@;Vw9n=Facr3Le5pPeenj>=4RHJI
z2u~wlrxqXYgD@r*_r|6ubGc?W&4nEOUNmU-|6E%>I=y>re{pTNUxW&TF_pOF=p8pm
z3?ey2{u)O9iAImSVcGDk^Hif=$j(Em=tqr2A{5zqEV}e1?Ju034q*+2I?q8>OgoUqUm{&
zBEc#2PQVe4jjlNa0IKLYDOIVP;TfZnje88A46R^uTyz?&h`%}p<5v;I6zH7Rv3|fq
zECDtzI21|E+QYg6S)hGD$)bnb&D-naPa&<=7L8S<2m*BZ?9-%*-#=qqszA&8Rs}=d
zc!WA#pTqR<%$Ir2JeYCr2E@7*BjhLn7i!!1P;&lWq+Q{E@UFdM+X6oliXEXl6h8JE
zQ6#6QP8F3JlN&MDe)LuS_EPsN2;6poZV;`C7@}Px15;yG-Di%%a
znyf-+=BG2}Rgt-K|59PKvDp%sYS!SKZso3Y6fH#BXGUk}stq1IVDKQp8esmSmlmo?
z>ysX06{YHAQ{02n6Ls?tzJVA};;355Q68@;t3^YC1#_Z$|vUMzF
zp;vaCgei9hoFimFc_1Z@broaYEYb+F!n?t*G5QcNPotx8oF#b9q;&
z4I1kVXUhH`1vmPm6sQ%jH-64c+~fj56j8DB*@dUed_;~VHjR33&YeGhdU-fo