From e120feca0d116958d5910b152ea3b2691fc22f3f Mon Sep 17 00:00:00 2001 From: Wendy Gaultier Date: Thu, 19 Dec 2024 21:20:47 +0000 Subject: [PATCH 1/2] update(centraldash):a to m --- .../public/components/dashboard-view.js | 1 + .../public/components/dashboard-view.pug | 10 +-- .../public/components/dashboard-view_test.js | 5 ++ .../public/components/logout-button.css | 3 + .../public/components/logout-button.js | 77 ++++--------------- .../public/components/main-page.css | 21 +++-- .../public/components/main-page.js | 52 ++++++++++++- .../public/components/main-page.pug | 9 ++- 8 files changed, 98 insertions(+), 80 deletions(-) create mode 100644 components/centraldashboard/public/components/logout-button.css diff --git a/components/centraldashboard/public/components/dashboard-view.js b/components/centraldashboard/public/components/dashboard-view.js index c9453c32e70..a2bbb55a448 100644 --- a/components/centraldashboard/public/components/dashboard-view.js +++ b/components/centraldashboard/public/components/dashboard-view.js @@ -45,6 +45,7 @@ export class DashboardView extends mixinBehaviors([AppLocalizeBehavior], utiliti observer: '_namespaceChanged', }, platformDetails: Object, + metrics: Object, platformInfo: { type: Object, observer: '_platformInfoChanged', diff --git a/components/centraldashboard/public/components/dashboard-view.pug b/components/centraldashboard/public/components/dashboard-view.pug index 8c1226acddb..5a00060a078 100644 --- a/components/centraldashboard/public/components/dashboard-view.pug +++ b/components/centraldashboard/public/components/dashboard-view.pug @@ -24,15 +24,15 @@ div#grid aside(secondary) [[item.desc]] paper-icon-button.button(icon='open-in-new', slot='item-icon', alt='[[item.text]]', tabindex=-1) - template(is='dom-if', if='[[platformDetails.resourceChartsLink]]') + template(is='dom-if', if='[[metrics.resourceChartsLinkText]]') resource-chart(header-text='Cluster CPU Utilization', metric='cpu', interval='Last60m', - external-link='[[platformDetails.resourceChartsLink]]', - external-link-text='[[platformDetails.resourceChartsLinkText]]') + external-link='[[metrics.resourceChartsLink]]', + external-link-text='[[metrics.resourceChartsLinkText]]') resource-chart(header-text='Pod CPU Utilization', metric='podcpu', interval='Last60m', - external-link='[[platformDetails.resourceChartsLink]]' - external-link-text='[[platformDetails.resourceChartsLinkText]]') + external-link='[[metrics.resourceChartsLink]]' + external-link-text='[[metrics.resourceChartsLinkText]]') .column template(is='dom-if', if='[[platformDetails.links]]') paper-card#Platform-Links(class$='[[platformDetails.name]]', diff --git a/components/centraldashboard/public/components/dashboard-view_test.js b/components/centraldashboard/public/components/dashboard-view_test.js index fff80451461..a24a0e21d3e 100644 --- a/components/centraldashboard/public/components/dashboard-view_test.js +++ b/components/centraldashboard/public/components/dashboard-view_test.js @@ -78,6 +78,11 @@ describe('Dashboard View', () => { 'https://console.cloud.google.com/dm/deployments?project=test-project', 'https://console.cloud.google.com/kubernetes/list?project=test-project', ]); + }); + + it('Show charts when metrics not empty', () => { + dashboardView.metrics = {resourceChartsLinkText: 'dummy'}; + flush(); expect(dashboardView.shadowRoot.querySelectorAll('resource-chart') .length).toBe(2); }); diff --git a/components/centraldashboard/public/components/logout-button.css b/components/centraldashboard/public/components/logout-button.css new file mode 100644 index 00000000000..cca9eb22449 --- /dev/null +++ b/components/centraldashboard/public/components/logout-button.css @@ -0,0 +1,3 @@ +a { + color: unset; +} \ No newline at end of file diff --git a/components/centraldashboard/public/components/logout-button.js b/components/centraldashboard/public/components/logout-button.js index e4ccca2f831..c01aaf420c9 100644 --- a/components/centraldashboard/public/components/logout-button.js +++ b/components/centraldashboard/public/components/logout-button.js @@ -1,7 +1,6 @@ -import {html, PolymerElement} from '@polymer/polymer/polymer-element.js'; - -import '@polymer/iron-ajax/iron-ajax.js'; +import { html, PolymerElement } from '@polymer/polymer/polymer-element.js'; import '@polymer/paper-button/paper-button.js'; +import css from './logout-button.css'; /** * Logout button component. @@ -10,72 +9,26 @@ import '@polymer/paper-button/paper-button.js'; * AAW: Not using this compoent and the logoutURL env param. Doesn't work. * https://github.com/StatCan/kubeflow/issues/152 */ - export class LogoutButton extends PolymerElement { static get template() { - return html` - - - - - - - `; - } - - static get properties() { - return { - headers: { - type: Object, - computed: '_setHeaders()', - }, - logoutUrl: { - type: String, - }, - }; - } - - /** - * After successful logout, redirects user to `afterLogoutURL`, - * received from the backend. - * - * @param {{Event}} event - * @private - */ - _postLogout(event) { - window.location.replace(event.detail.response['afterLogoutURL']); + return html([` + + + + + + + + `]); + ; } /** - * Call logout endpoint. + * Set current page to logoutURL. */ logout() { - // call iron-ajax - this.$.logout.generateRequest(); - } - - /** - * Set 'Authorization' header based on the existing cookie. - * Currently, the logout method only accepts authorization header, see: - * https://github.com/arrikto/oidc-authservice/blob/master/server.go#L386 - * - * @return {{Object}} headers - * @private - */ - _setHeaders() { - const cookie = ('; ' + document.cookie) - .split(`; authservice_session=`) - .pop() - .split(';')[0]; - return { - 'Authorization': `Bearer ${cookie}`, - }; + window.top.location.href = this.logoutUrl; } } diff --git a/components/centraldashboard/public/components/main-page.css b/components/centraldashboard/public/components/main-page.css index ecc8d137718..7eac8186797 100644 --- a/components/centraldashboard/public/components/main-page.css +++ b/components/centraldashboard/public/components/main-page.css @@ -27,6 +27,18 @@ overflow: auto; } +.scrollable::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; + height: 7px; +} + +.scrollable::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: rgba(238, 238, 239, 0.5); + box-shadow: 0 0 1px rgba(255,255,255,.5); +} + #MainDrawer { color: white; --app-drawer-content-container: { @@ -46,13 +58,6 @@ app-drawer-layout[narrow] #MainDrawer { } } -app-drawer-layout[bleed] #MainDrawer { - background: var(--primary-background-color); - --app-drawer-content-container: { - background: transparent !important; - } -} - #PageLoader { @apply --layout-fullbleed; @apply --layout-center-center; @@ -95,7 +100,7 @@ app-drawer-layout[bleed] #MainDrawer { } #MainDrawer .inner-menu-item { - padding-left: 65px; + padding-left: 60px; margin: 0; font-size: 13px; min-height: 30px; diff --git a/components/centraldashboard/public/components/main-page.js b/components/centraldashboard/public/components/main-page.js index 1fc3d3a309e..c27e92f907e 100644 --- a/components/centraldashboard/public/components/main-page.js +++ b/components/centraldashboard/public/components/main-page.js @@ -97,6 +97,7 @@ export class MainPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMix dashVersion: {type: String, value: VERSION}, logoutUrl: {type: String, value: '/logout'}, platformInfo: Object, + metrics: Object, inIframe: {type: Boolean, value: false, readOnly: true}, hideTabs: {type: Boolean, value: false, readOnly: true}, hideSidebar: {type: Boolean, value: false, readOnly: true}, @@ -423,6 +424,26 @@ export class MainPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMix queryParams); } + + /** + * Parse namespace in external links + * @param {string} href - external link + * @param {Object} queryParamsChange - queryParams updated on-the-fly + * @return {string} + */ + _buildExternalHref(href, queryParamsChange) { + // The "queryParams" value from "queryParamsChange" is not updated as + // expected in the "iframe-link", but it works in anchor element. + // A temporary workaround is to use "this.queryParams" as an input + // instead of "queryParamsChange.base". + // const queryParams = queryParamsChange.base; + const queryParams = this.queryParams; + if (!queryParams || !queryParams['ns']) { + return href.replace('{ns}', ''); + } + return href.replace('{ns}', queryParams['ns']); + } + /** * Builds the new iframeSrc string based on the subroute path, current * hash fragment, and the query string parameters other than ns. @@ -531,7 +552,16 @@ export class MainPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMix } _toggleMenuSection(e) { - e.target.nextElementSibling.toggle(); + // look upwards until we find + let el = e.target; + while (el && el.tagName !== 'PAPER-ITEM') { + el = el.parentElement; + } + + // if we found paper-item, the next sibling is the section + if (el) { + el.nextElementSibling.toggle(); + } } /** @@ -572,7 +602,25 @@ export class MainPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMix // This case is for non-identity networks, that have no namespaces this._setRegistrationFlow(true); } - this.ownedNamespace = namespaces.find((n) => n.role == 'owner'); + // this.ownedNamespace = namespaces.find((n) => n.role == 'owner'); + const ownedNamespaces = []; + const editNamespaces = []; + const viewNamespaces = []; + if (this.namespaces.length) { + this.namespaces.forEach((ns) => { + if (ns.role === 'owner') { + ownedNamespaces.push(ns); + } else if (ns.role === 'contributor') { + editNamespaces.push(ns); + } else if (ns.role === 'viewer') { + viewNamespaces.push(ns); + } + }); + this.ownedNamespaces = ownedNamespaces; + this.editNamespaces = editNamespaces; + this.viewNamespaces = viewNamespaces; + this.hasNamespaces = true; + } this.multiOwnedNamespaces = ownerRoleNamespaces; this.platformInfo = platform; const kVer = this.platformInfo.kubeflowVersion; diff --git a/components/centraldashboard/public/components/main-page.pug b/components/centraldashboard/public/components/main-page.pug index 3f8138520ac..0ff9a575348 100644 --- a/components/centraldashboard/public/components/main-page.pug +++ b/components/centraldashboard/public/components/main-page.pug @@ -1,5 +1,7 @@ iron-ajax(auto, url='/api/workgroup/exists', handle-as='json', on-response='_onHasWorkgroupResponse', on-error='_onHasWorkgroupError', loading='{{pageLoading}}') +iron-ajax(auto, url='/api/metrics', handle-as='json', + last-response='{{metrics}}', loading='{{pageLoading}}') iron-ajax(auto, id='ajax-dashboard-links', url='/api/dashboard-links', handle-as='json', params='[[_getLanguageParams()]]', on-response='_onHasDashboardLinksResponse', on-error='_onHasDashboardLinksError', loading='{{pageLoading}}') iron-ajax#envInfo(auto='[[_shouldFetchEnv]]', url='/api/workgroup/env-info', handle-as='json', @@ -31,7 +33,8 @@ app-drawer-layout.flex(narrow='{{narrowMode}}', iron-collapse template(is='dom-repeat', items='[[item.items]]') iframe-link(href$="[[_buildHref(item.link, queryParams.*)]]") - paper-item.menu-item.inner-menu-item [[item.text]] + paper-item.menu-item.inner-menu-item + | [[item.text]] template(is='dom-if', if='[[!equals(item.type, "section")]]') iframe-link(href$="[[_buildHref(item.link, queryParams.*)]]") paper-item.menu-item @@ -44,7 +47,7 @@ app-drawer-layout.flex(narrow='{{narrowMode}}', iron-icon(icon='[[item.icon]]') | [[item.text]] template(is='dom-if', if='[[!item.iframe]]') - a(href$="[[replaceNamespacedLink(item.link)]]",tabindex='-1', target="_blank") + a(href$="[[_buildExternalHref(item.link, queryParams.*)]]", tabindex='-1', target="_blank") paper-item.menu-item iron-icon(icon='[[item.icon]]') | [[item.text]] @@ -89,7 +92,7 @@ app-drawer-layout.flex(narrow='{{narrowMode}}', exit-animation='fade-out-animation') neon-animatable(page='dashboard') dashboard-view(namespace='[[queryParams.ns]]', - platform-info='[[platformInfo]]', quick-links='[[quickLinks]]', documentation-items='[[documentationItems]]', + platform-info='[[platformInfo]]', quick-links='[[quickLinks]]', documentation-items='[[documentationItems]]', metrics='[[metrics]]'), security-messages='[[securityMessages]]', language='[[language]]', resources='[[resources]]') neon-animatable(page='activity') activity-view(namespace='[[queryParams.ns]]', language='[[language]]', resources='[[resources]]') From 7169ad8ad4dfd750e7c944938c608d9711a3f9f1 Mon Sep 17 00:00:00 2001 From: Wendy Gaultier Date: Tue, 24 Dec 2024 13:54:26 +0000 Subject: [PATCH 2/2] iframe-container --- .../public/components/iframe-container.js | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/components/centraldashboard/public/components/iframe-container.js b/components/centraldashboard/public/components/iframe-container.js index 719f692f374..dc400cf245e 100644 --- a/components/centraldashboard/public/components/iframe-container.js +++ b/components/centraldashboard/public/components/iframe-container.js @@ -8,8 +8,11 @@ import { MESSAGE, NAMESPACE_SELECTED_EVENT, PARENT_CONNECTED_EVENT, + ALL_NAMESPACES_EVENT, } from '../library.js'; +import {ALL_NAMESPACES} from './namespace-selector'; + export class IframeContainer extends PolymerElement { static get template() { return html` @@ -91,11 +94,18 @@ export class IframeContainer extends PolymerElement { */ _sendNamespaceMessage() { if (!(this._iframeOrigin && this.namespace)) return; - - this.$.iframe.contentWindow.postMessage({ - type: NAMESPACE_SELECTED_EVENT, - value: this.namespace, - }, this._iframeOrigin); + if (this.namespace === ALL_NAMESPACES) { + this.$.iframe.contentWindow.postMessage({ + type: ALL_NAMESPACES_EVENT, + value: this.namespaces.map((n) => n.namespace) + .filter((n) => n !== ALL_NAMESPACES), + }, this._iframeOrigin); + } else { + this.$.iframe.contentWindow.postMessage({ + type: NAMESPACE_SELECTED_EVENT, + value: this.namespace, + }, this._iframeOrigin); + } } /**