From a7c05970a6a141385499ecc824fc700db21c5e0e Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Sun, 13 Feb 2022 10:25:46 -0600 Subject: [PATCH 1/3] adding placeholders for target service and port combo boxes --- electron/app/locales/en/webui.json | 4 ++ .../js/viewModels/ingress-design-view-impl.js | 42 ++++++++----------- webui/src/js/viewModels/route-edit-dialog.js | 31 ++++++++++---- webui/src/js/views/route-edit-dialog.html | 5 ++- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json index 0fde7d43a..59ad07aa1 100644 --- a/electron/app/locales/en/webui.json +++ b/electron/app/locales/en/webui.json @@ -674,7 +674,11 @@ "ingress-design-ingress-route-targetservicenamespace-help": "The target service namespace value points to the namespace where the domain is running.", "ingress-design-ingress-route-accesspoint-label": "Access Point", "ingress-design-ingress-route-targetservice-label": "Target Service", + "ingress-design-ingress-route-targetservice-placeholder": "Select Domain Service", + "ingress-design-ingress-route-targetservice-placeholder-empty": "No Domain Services Available", "ingress-design-ingress-route-targetport-label": "Target Port", + "ingress-design-ingress-route-targetport-placeholder": "Select Target Service Port", + "ingress-design-ingress-route-targetport-placeholder-empty": "No Target Service Selected", "ingress-design-ingress-route-path-label": "Path Expression", "ingress-design-ingress-route-tls-label": "Transport Options", "ingress-design-ingress-route-tls-help": "Select the transport option for this ingress route", diff --git a/webui/src/js/viewModels/ingress-design-view-impl.js b/webui/src/js/viewModels/ingress-design-view-impl.js index 570be273c..45c2abbca 100644 --- a/webui/src/js/viewModels/ingress-design-view-impl.js +++ b/webui/src/js/viewModels/ingress-design-view-impl.js @@ -209,12 +209,11 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, window.api.ipc.invoke('show-error-message', title, message); }; - async function getTargetServiceDetails (project) { - + async function getTargetServiceDetails(myProject) { const kubectlExe = k8sHelper.getKubectlExe(); const kubectlOptions = k8sHelper.getKubectlOptions(); const results = await window.api.ipc.invoke('k8s-get-service-details', - kubectlExe, project.k8sDomain.kubernetesNamespace.value, '', kubectlOptions); + kubectlExe, myProject.k8sDomain.kubernetesNamespace.value, '', kubectlOptions); let serviceLists = {}; if (results.isSuccess) { for (const item of results.serviceDetails.items) { @@ -230,7 +229,7 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, return Promise.resolve(false); } return Promise.resolve( { serviceList: serviceLists}); - }; + } this.handleEditRoute = async (event, context) => { // using context.item.data directly was causing problems @@ -239,28 +238,23 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, let route = this.routes.observable()[index]; getTargetServiceDetails(this.project).then( svc => { const options = {route: route, serviceList: svc.serviceList}; - dialogHelper.promptDialog('route-edit-dialog', options) - .then(result => { - - // no result indicates operation was cancelled - if (result) { - let changed = false; - project.ingress.ingressRouteKeys.forEach(key => { - if ((key !== 'uid') && result.hasOwnProperty(key)) { - route[key] = result[key]; - changed = true; - } - }); - - if (changed) { - this.routes.observable.replace(route, route); + dialogHelper.promptDialog('route-edit-dialog', options).then(result => { + // no result indicates operation was cancelled + if (result) { + let changed = false; + project.ingress.ingressRouteKeys.forEach(key => { + if ((key !== 'uid') && result.hasOwnProperty(key)) { + route[key] = result[key]; + changed = true; } - } - }); - } - ); - + }); + if (changed) { + this.routes.observable.replace(route, route); + } + } + }); + }); }; this.handleCancel = () => { diff --git a/webui/src/js/viewModels/route-edit-dialog.js b/webui/src/js/viewModels/route-edit-dialog.js index 1fdd2847f..d9c344e9d 100644 --- a/webui/src/js/viewModels/route-edit-dialog.js +++ b/webui/src/js/viewModels/route-edit-dialog.js @@ -12,7 +12,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa function RouteEditDialogModel(args) { const DIALOG_SELECTOR = '#routeEditDialog'; - const DEFAULT_ROUTE_PORT = 0; + const DEFAULT_ROUTE_PORT = undefined; // SIMPLE_PROPERTIES - names matching simple route fields let EXCLUDE_PROPERTIES = ['uid', 'annotations']; @@ -42,7 +42,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa this.buildTargetSvcNames = () => { let options = []; - for(var name in this.serviceList){ + for (const name in this.serviceList) { options.push( { id : name, value: name, text: name}); } return options; @@ -52,7 +52,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa let options = []; if (this.serviceList[svcName]) { for (const port of this.serviceList[svcName].ports) { - options.push( { id : port.port, value: port.port, text: port.port}); + options.push( { id : port.port, value: port.port, text: port.port} ); } } @@ -64,7 +64,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa this.targetSvcPorts = ko.observableArray([] ); if (this.route.targetService) { - this.targetSvcPorts = this.buildTargetSvcPorts(this.route.targetService); + this.buildTargetSvcPorts(this.route.targetService).forEach(port => this.targetSvcPorts.push(port)); } this.savedAnnotations = args.route.annotations || {}; @@ -144,6 +144,24 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa this[propertyName] = props.createProperty(defaultValue); }); + this.getTargetServicePlaceholder = ko.computed(() => { + if (Array.isArray(this.targetSvcNames) && this.targetSvcNames.length > 0) { + return this.labelMapper('route-targetservice-placeholder'); + } else { + return this.labelMapper('route-targetservice-placeholder-empty'); + } + }); + + this.getTargetPortPlaceholder = ko.computed(() => { + console.log('targetSvcPorts is a ' + typeof(this.targetSvcPorts)); + const ports = this.targetSvcPorts(); + if (Array.isArray(ports) && ports.length > 0) { + return this.labelMapper('route-targetport-placeholder'); + } else { + return this.labelMapper('route-targetport-placeholder-empty'); + } + }); + this.handleAddAnnotation = () => { const nextIndex = this.nextAnnotationIndex(); const annotation = {uid: getAnnotationUid(nextIndex), key: `annotation-${nextIndex}`}; @@ -186,10 +204,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa this.targetSvcNameChanged = (event) => { this.targetSvcPorts.removeAll(); - const list = this.buildTargetSvcPorts(event.detail.value); - for (const item of list) { - this.targetSvcPorts.push(item); - } + this.buildTargetSvcPorts(event.detail.value).forEach(port => this.targetSvcPorts.push(port)); }; this.okInput = () => { diff --git a/webui/src/js/views/route-edit-dialog.html b/webui/src/js/views/route-edit-dialog.html index 98dd8ad17..3d4f05afd 100644 --- a/webui/src/js/views/route-edit-dialog.html +++ b/webui/src/js/views/route-edit-dialog.html @@ -36,6 +36,7 @@ + options="[[targetServicePorts]]"> Date: Sun, 13 Feb 2022 17:09:28 -0600 Subject: [PATCH 2/3] adding busy dialog while fetching service details --- electron/app/locales/en/webui.json | 1 + .../js/viewModels/ingress-design-view-impl.js | 11 ++++++++--- webui/src/js/viewModels/route-edit-dialog.js | 19 ++++++++++--------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/electron/app/locales/en/webui.json b/electron/app/locales/en/webui.json index 59ad07aa1..37c2b3a39 100644 --- a/electron/app/locales/en/webui.json +++ b/electron/app/locales/en/webui.json @@ -667,6 +667,7 @@ "ingress-design-ingress-docker-reg-secret-userpwd-help": "The password used to log in to Docker Hub.", "ingress-design-ingress-docker-reg-secret-useremail": "Docker Hub Email Address", "ingress-design-ingress-docker-reg-secret-useremail-help": "The email address of the user logging in to Docker Hub.", + "ingress-design-route-get-services-title": "Getting services for namespace {{namespace}}", "ingress-design-ingress-routes-title": "Ingress Routes Configuration", "ingress-design-ingress-route-virtualhost-label": "Virtual Host", diff --git a/webui/src/js/viewModels/ingress-design-view-impl.js b/webui/src/js/viewModels/ingress-design-view-impl.js index 45c2abbca..a11bf91db 100644 --- a/webui/src/js/viewModels/ingress-design-view-impl.js +++ b/webui/src/js/viewModels/ingress-design-view-impl.js @@ -236,8 +236,13 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, // when project data was reloaded with matching UIDs. const index = context.item.index; let route = this.routes.observable()[index]; - getTargetServiceDetails(this.project).then( svc => { - const options = {route: route, serviceList: svc.serviceList}; + + dialogHelper.openBusyDialog(this.labelMapper('route-get-services-title', + { namespace: this.project.k8sDomain.kubernetesNamespace.value })); + const targetServiceDetails = await getTargetServiceDetails(this.project); + dialogHelper.closeBusyDialog(); + if (targetServiceDetails) { + const options = {route: route, serviceList: targetServiceDetails.serviceList}; dialogHelper.promptDialog('route-edit-dialog', options).then(result => { // no result indicates operation was cancelled if (result) { @@ -254,7 +259,7 @@ function(i18n, accUtils, ko, ArrayDataProvider, BufferingDataProvider, project, } } }); - }); + } }; this.handleCancel = () => { diff --git a/webui/src/js/viewModels/route-edit-dialog.js b/webui/src/js/viewModels/route-edit-dialog.js index d9c344e9d..8a66d7458 100644 --- a/webui/src/js/viewModels/route-edit-dialog.js +++ b/webui/src/js/viewModels/route-edit-dialog.js @@ -6,9 +6,11 @@ 'use strict'; define(['accUtils', 'knockout', 'utils/i18n', 'models/wkt-project', 'utils/view-helper', 'ojs/ojarraydataprovider', - 'ojs/ojbufferingdataprovider', 'utils/observable-properties', 'ojs/ojconverter-number', 'ojs/ojinputtext', - 'ojs/ojlabel', 'ojs/ojbutton', 'ojs/ojdialog', 'ojs/ojformlayout', 'ojs/ojvalidationgroup', 'ojs/ojselectcombobox'], -function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDataProvider, props, ojConverterNumber) { + 'ojs/ojbufferingdataprovider', 'utils/observable-properties', 'ojs/ojconverter-number', 'utils/wkt-logger', + 'ojs/ojinputtext', 'ojs/ojlabel', 'ojs/ojbutton', 'ojs/ojdialog', 'ojs/ojformlayout', 'ojs/ojvalidationgroup', + 'ojs/ojselectcombobox'], +function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDataProvider, props, + ojConverterNumber, wktLogger) { function RouteEditDialogModel(args) { const DIALOG_SELECTOR = '#routeEditDialog'; @@ -18,9 +20,12 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa let EXCLUDE_PROPERTIES = ['uid', 'annotations']; let SIMPLE_PROPERTIES = project.ingress.ingressRouteKeys.filter(key => !EXCLUDE_PROPERTIES.includes(key)); - this.connected = () => { - accUtils.announce('Route edit dialog loaded.', 'assertive'); + this.project = project; + this.route = args.route; + this.serviceList = args.serviceList; + this.connected = async () => { + accUtils.announce('Route edit dialog loaded.', 'assertive'); // open the dialog after the current thread, which is loading this view model. // using oj-dialog initial-visibility="show" causes vertical centering issues. setTimeout(function() { @@ -36,10 +41,6 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa return i18n.t(labelId, arg); }; - this.project = project; - this.route = args.route; - this.serviceList = args.serviceList; - this.buildTargetSvcNames = () => { let options = []; for (const name in this.serviceList) { From da978aafcfc191930780db9dc658036537e9ba9d Mon Sep 17 00:00:00 2001 From: Robert Patrick Date: Sun, 13 Feb 2022 17:12:13 -0600 Subject: [PATCH 3/3] eslint warning --- webui/src/js/viewModels/route-edit-dialog.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webui/src/js/viewModels/route-edit-dialog.js b/webui/src/js/viewModels/route-edit-dialog.js index 8a66d7458..50c99f22f 100644 --- a/webui/src/js/viewModels/route-edit-dialog.js +++ b/webui/src/js/viewModels/route-edit-dialog.js @@ -10,7 +10,7 @@ define(['accUtils', 'knockout', 'utils/i18n', 'models/wkt-project', 'utils/view 'ojs/ojinputtext', 'ojs/ojlabel', 'ojs/ojbutton', 'ojs/ojdialog', 'ojs/ojformlayout', 'ojs/ojvalidationgroup', 'ojs/ojselectcombobox'], function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDataProvider, props, - ojConverterNumber, wktLogger) { + ojConverterNumber) { function RouteEditDialogModel(args) { const DIALOG_SELECTOR = '#routeEditDialog'; @@ -24,7 +24,7 @@ function(accUtils, ko, i18n, project, viewHelper, ArrayDataProvider, BufferingDa this.route = args.route; this.serviceList = args.serviceList; - this.connected = async () => { + this.connected = () => { accUtils.announce('Route edit dialog loaded.', 'assertive'); // open the dialog after the current thread, which is loading this view model. // using oj-dialog initial-visibility="show" causes vertical centering issues.