Skip to content

Commit

Permalink
Merge pull request #172 from StatCan/language-button
Browse files Browse the repository at this point in the history
added language button to centraldash
  • Loading branch information
mathis-marcotte authored Oct 31, 2023
2 parents bfa497f + 8129f1e commit 4ef3200
Show file tree
Hide file tree
Showing 26 changed files with 171 additions and 63 deletions.
8 changes: 1 addition & 7 deletions components/centraldashboard/app/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,11 @@ export class Api {
.get(
'/dashboard-links',
async (req: Request, res: Response) => {
const acceptlanguage = req.header('accept-language');
const cm = await this.k8sService.getConfigMap();
let langLinks = {};
try {
const links = JSON.parse(cm.data["links"]);
const lang = this.resolveLanguage (
this.getBrowserLanguages(acceptlanguage),
Object.getOwnPropertyNames(links),
cm.data["defaultLanguage"]
);
langLinks = links[lang];
langLinks = links[req.query.lang];
}catch(e){
return apiError({
res, code: 500,
Expand Down
16 changes: 8 additions & 8 deletions components/centraldashboard/cypress/e2e/main-page.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ describe('Main Page', () => {
cy.get('main-page').shadow().find('a[href="https://grafana.aaw-dev.cloud.statcan.ca/d/ZLp774O4z/namespace-metrics?orgId=1&var-namespace=test-namespace&kiosk=tv"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://grafana.aaw-dev.cloud.statcan.ca/d/ZLp774O4z/namespace-metrics?orgId=1&var-namespace=test-namespace&kiosk=tv"]').find('paper-item').should('have.text', 'Metrics');

cy.get('main-page').shadow().find('a[href="https://github.com/kubeflow/kubeflow"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://github.com/kubeflow/kubeflow"]').find('paper-item').should('have.text', 'GitHub');
cy.get('main-page').shadow().find('a[href="https://github.com/StatCan/kubeflow"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://github.com/StatCan/kubeflow"]').find('paper-item').should('have.text', 'GitHub');

cy.get('main-page').shadow().find('a[href="https://www.kubeflow.org/docs/about/kubeflow/"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://www.kubeflow.org/docs/about/kubeflow/"]').find('paper-item').should('have.text', 'Documentation');
cy.get('main-page').shadow().find('a[href="https://statcan.github.io/aaw/"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://statcan.github.io/aaw/"]').find('paper-item').should('have.text', 'Documentation');

//mock env info to hide manage contributors link
cy.intercept('GET', `/api/workgroup/env-info`, {
Expand Down Expand Up @@ -174,10 +174,10 @@ describe('Main Page', () => {
cy.get('main-page').shadow().find('a[href="https://grafana.aaw-dev.cloud.statcan.ca/d/ZLp774O4z/namespace-metrics?orgId=1&var-namespace=test-namespace-2&kiosk=tv"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://grafana.aaw-dev.cloud.statcan.ca/d/ZLp774O4z/namespace-metrics?orgId=1&var-namespace=test-namespace-2&kiosk=tv"]').find('paper-item').should('have.text', 'Metrics');

cy.get('main-page').shadow().find('a[href="https://github.com/kubeflow/kubeflow"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://github.com/kubeflow/kubeflow"]').find('paper-item').should('have.text', 'GitHub');
cy.get('main-page').shadow().find('a[href="https://github.com/StatCan/kubeflow"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://github.com/StatCan/kubeflow"]').find('paper-item').should('have.text', 'GitHub');

cy.get('main-page').shadow().find('a[href="https://www.kubeflow.org/docs/about/kubeflow/"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://www.kubeflow.org/docs/about/kubeflow/"]').find('paper-item').should('have.text', 'Documentation');
cy.get('main-page').shadow().find('a[href="https://statcan.github.io/aaw/"]').should('exist');
cy.get('main-page').shadow().find('a[href="https://statcan.github.io/aaw/"]').find('paper-item').should('have.text', 'Documentation');
});
})
2 changes: 1 addition & 1 deletion components/centraldashboard/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Cypress.Commands.add('mockWorkgroupRequest', () => {
});

Cypress.Commands.add('mockDashboardLinksRequest', () => {
cy.intercept('GET', `/api/dashboard-links`, {
cy.intercept('GET', `/api/dashboard-links?lang=*`, {
fixture: 'dashboard-links',
}).as('mockDashboardLinksRequest');
});
Expand Down
2 changes: 2 additions & 0 deletions components/centraldashboard/public/assets/i18n/languages.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"mainPage.tabActivity": "Activity",
"mainPage.footerBuildVersion": "Build: {buildVersion} | Dashboard: v {dashVersion} | Isolation-Mode: {isolationMode}",
"mainPage.errGeneric": "An error occured.",
"mainPage.languageButton": "Français",
"notFound.invalidPagePart1": "Sorry, ",
"notFound.invalidPagePart2": " is not a valid page",
"pipelinesCard.txtCreated": "Created ",
Expand Down Expand Up @@ -152,6 +153,7 @@
"mainPage.tabActivity": "Activité",
"mainPage.footerBuildVersion": "Version: {buildVersion} | Dashboard: v {dashVersion} | Mode d'isolation: {isolationMode}",
"mainPage.errGeneric": "Une erreur est survenue.",
"mainPage.languageButton": "English",
"notFound.invalidPagePart1": "Désolé, ",
"notFound.invalidPagePart2": " n'est pas une page valide",
"pipelinesCard.txtCreated": "Créé",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import '@polymer/iron-ajax/iron-ajax.js';
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/paper-progress/paper-progress.js';
import localizationMixin from './localization-mixin.js';
// eslint-disable-next-line max-len
import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {html, PolymerElement} from '@polymer/polymer';
import './activities-list.js';

// eslint-disable-next-line max-len
export class ActivityView extends localizationMixin(PolymerElement) {
export class ActivityView extends mixinBehaviors([AppLocalizeBehavior], PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex iron-flex-alignment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {flush} from '@polymer/polymer/lib/utils/flush.js';

import './activity-view';
import {mockRequest} from '../ajax_test_helper';
import {languages} from '../assets/i18n/languages.json';

const FIXTURE_ID = 'activity-view-fixture';
const ACTIVITY_VIEW_SELECTOR_ID = 'test-activity-view';
Expand All @@ -28,6 +29,8 @@ describe('Activity View', () => {
jasmine.Ajax.install();
document.getElementById(FIXTURE_ID).create();
activityView = document.getElementById(ACTIVITY_VIEW_SELECTOR_ID);
activityView.language = 'en';
activityView.resources = languages;

// Prevents the activitiesList component from trying to render
spyOn(activityView.shadowRoot.querySelector('activities-list'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-ripple/paper-ripple.js';
import '@polymer/paper-item/paper-icon-item.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import localizationMixin from './localization-mixin.js';
// eslint-disable-next-line max-len
import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';

import {html, PolymerElement} from '@polymer/polymer';

Expand All @@ -20,7 +22,7 @@ import {getGCPData} from './resources/cloud-platform-data.js';
import utilitiesMixin from './utilities-mixin.js';

// eslint-disable-next-line max-len
export class DashboardView extends utilitiesMixin(localizationMixin(PolymerElement)) {
export class DashboardView extends mixinBehaviors([AppLocalizeBehavior], utilitiesMixin(PolymerElement)) {
static get template() {
return html([`
<style include="card-styles">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ div#grid
external-link='[[platformDetails.resourceChartsLink]]'
external-link-text='[[platformDetails.resourceChartsLinkText]]')
.column
notebooks-card(namespace='[[namespace]]')
notebooks-card(namespace='[[namespace]]', language='[[language]]', resources='[[resources]]')
.column
template(is='dom-if', if='[[platformDetails.links]]')
paper-card#Platform-Links(class$='[[platformDetails.name]]',
Expand Down
6 changes: 4 additions & 2 deletions components/centraldashboard/public/components/landing-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import '@polymer/neon-animation/neon-animatable.js';
import '@polymer/neon-animation/neon-animated-pages.js';
import '@polymer/neon-animation/animations/fade-in-animation.js';
import '@polymer/neon-animation/animations/fade-out-animation.js';
import localizationMixin from './localization-mixin.js';
// eslint-disable-next-line max-len
import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

Expand All @@ -26,7 +28,7 @@ import utilitiesMixin from './utilities-mixin.js';
* Replaces registration-page
*/
// eslint-disable-next-line max-len
export class LandingPage extends utilitiesMixin(localizationMixin(PolymerElement)) {
export class LandingPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMixin(PolymerElement)) {
static get template() {
const vars = {logo};

Expand Down
6 changes: 6 additions & 0 deletions components/centraldashboard/public/components/main-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,9 @@ a[href]:hover, iframe-link:hover {
color: var(--paper-blue-700);
text-decoration: underline;
}

.language-button {
font-size: 14px;
color: #3c4043;
text-transform: none;
}
73 changes: 69 additions & 4 deletions components/centraldashboard/public/components/main-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import '@polymer/neon-animation/neon-animatable.js';
import '@polymer/neon-animation/neon-animated-pages.js';
import '@polymer/neon-animation/animations/fade-in-animation.js';
import '@polymer/neon-animation/animations/fade-out-animation.js';
import localizationMixin from './localization-mixin.js';

// eslint-disable-next-line max-len
import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

import css from './main-page.css';
Expand All @@ -44,12 +45,13 @@ import './iframe-container.js';
import './logout-button.js';
import utilitiesMixin from './utilities-mixin.js';
import {IFRAME_LINK_PREFIX} from './iframe-link.js';
import {languages} from '../assets/i18n/languages.json';

/**
* Entry point for application UI.
*/
// eslint-disable-next-line max-len
export class MainPage extends utilitiesMixin(localizationMixin(PolymerElement)) {
export class MainPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMixin(PolymerElement)) {
static get template() {
const vars = {logo};
return html([
Expand Down Expand Up @@ -118,6 +120,14 @@ export class MainPage extends utilitiesMixin(localizationMixin(PolymerElement))
},
matchingIndex: Number,
namespacedItemTemplete: String,
// for translations
language: {type: String, notify: 'true', value: function() {
const currentLanguage = this.getBrowserLang();
// eslint-disable-next-line max-len
const lang = (currentLanguage != undefined && currentLanguage.match(/en|fr/)) ? currentLanguage : 'en';
return lang;
}},
resources: {value: languages},
};
}

Expand All @@ -133,6 +143,39 @@ export class MainPage extends utilitiesMixin(localizationMixin(PolymerElement))
];
}

// Get the language based on the browser
getBrowserLang() {
// localStorage stores the last language used by user
if (localStorage.getItem('lang')) {
return localStorage.getItem('lang');
}

if (typeof window === 'undefined' ||
typeof window.navigator === 'undefined') {
return undefined;
}

let browserLang = window.navigator.languages ?
window.navigator.languages[0] : null;
browserLang = browserLang || window.navigator.language ||
window.navigator.browserLanguage || window.navigator.userLanguage;

if (typeof browserLang === 'undefined') {
return undefined;
}

if (browserLang.indexOf('-') !== -1) {
browserLang = browserLang.split('-')[0];
}

if (browserLang.indexOf('_') !== -1) {
browserLang = browserLang.split('_')[0];
}

localStorage.setItem('lang', browserLang);
return browserLang;
}

/**
* Return a username without the @example.com
* @param {string} user User email
Expand Down Expand Up @@ -283,7 +326,6 @@ export class MainPage extends utilitiesMixin(localizationMixin(PolymerElement))
if (path && path.includes('{ns}')) {
this.page = 'namespace_needed';
} else if (newPage === 's3') { // AAW Customization
// eslint-disable-next-line no-console
this.page = 's3proxy';
} else {
this.page = 'not_found';
Expand Down Expand Up @@ -529,6 +571,29 @@ export class MainPage extends utilitiesMixin(localizationMixin(PolymerElement))
return isolationMode==='multi-user'
&& ownedNamespace!==undefined;
}

_changeLanguage() {
if (this.language === 'en') {
this.language = 'fr';
} else {
this.language = 'en';
}
localStorage.setItem('lang', this.language);
this.$['ajax-dashboard-links'].params = this._getLanguageParams();
// update language in url
// eslint-disable-next-line max-len
if (location.href.match(/\/(en|fr)\//) || location.pathname.startsWith(`/${IFRAME_LINK_PREFIX}/`)) {
// eslint-disable-next-line max-len
const newUrl = location.href.replace(/\/(en|fr)\//, `/${this.language}/`);
window.location = newUrl;
}
}

_getLanguageParams() {
return {
'lang': this.language,
};
}
}

window.customElements.define('main-page', MainPage);
21 changes: 12 additions & 9 deletions components/centraldashboard/public/components/main-page.pug
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
iron-ajax(auto, url='/api/workgroup/exists', handle-as='json',
on-response='_onHasWorkgroupResponse', on-error='_onHasWorkgroupError', loading='{{pageLoading}}')
iron-ajax(auto, url='/api/dashboard-links', handle-as='json',
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',
on-response='_onEnvInfoResponse')
Expand Down Expand Up @@ -83,8 +83,9 @@ app-drawer-layout.flex(narrow='{{narrowMode}}',
namespaces='[[namespaces]]', selected='{{namespace}}',
hides, hidden$='[[hideNamespaces]]'
all-namespaces='[[allNamespaces]]',
user='[[user]]')
user='[[user]]', language='[[language]]', resources='[[resources]]')
footer#User-Badge
paper-button.language-button(on-click='_changeLanguage') {{localize('mainPage.languageButton')}}
a(target="_top", href="/logout")
iron-icon.icon(icon='kubeflow:logout' title="Logout")
main#Content
Expand All @@ -99,25 +100,27 @@ 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]]', security-messages='[[securityMessages]]')
platform-info='[[platformInfo]]', quick-links='[[quickLinks]]', documentation-items='[[documentationItems]]',
security-messages='[[securityMessages]]', language='[[language]]', resources='[[resources]]')
neon-animatable(page='activity')
activity-view(namespace='[[queryParams.ns]]')
activity-view(namespace='[[queryParams.ns]]', language='[[language]]', resources='[[resources]]')
neon-animatable(page='manage-users')
manage-users-view(user='[[user]]', namespaces='[[namespaces]]', multi-owned-namespaces='[[multiOwnedNamespaces]]', is-cluster-admin='[[isClusterAdmin]]')
manage-users-view(user='[[user]]', namespaces='[[namespaces]]', multi-owned-namespaces='[[multiOwnedNamespaces]]',
is-cluster-admin='[[isClusterAdmin]]', language='[[language]]', resources='[[resources]]')
neon-animatable(page='s3proxy')
s3proxy-view()
s3proxy-view(language='[[language]]', resources='[[resources]]')
neon-animatable(page='iframe')
iframe-container(namespace='[[namespace]]',
src='[[iframeSrc]]', page="{{iframePage}}"
namespaces='[[namespaces]]')
neon-animatable(page='not_found')
not-found-view(path="[[route.path]]")
not-found-view(path="[[route.path]]", language='[[language]]', resources='[[resources]]')
neon-animatable(page='namespace_needed')
namespace-needed-view()
namespace-needed-view(language='[[language]]', resources='[[resources]]')
iron-media-query(query='(max-width: 900px)', query-matches='{{sidebarBleed}}')
iron-media-query(query='(max-width: 1270px)', query-matches='{{thinView}}')
paper-toast#welcomeUser(duration=5000) Welcome, [[_extractLdap(user)]]!
paper-toast#ErrorToast(duration=0, opened='[[!empty(errorText)]]', on-click='closeError') {{localize(errorText)}}
paper-icon-button(icon='close')
template(is='dom-if', if='[[registrationFlow]]')
landing-page(user-details='[[_extractLdap(user)]]' on-flowcomplete='resyncApp')
landing-page(user-details='[[_extractLdap(user)]]' on-flowcomplete='resyncApp', language='[[language]]', resources='[[resources]]')
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import './resources/paper-chip.js';
import './resources/md2-input/md2-input.js';
import css from './manage-users-view-contributor.css';
import template from './manage-users-view-contributor.pug';
import utilitiesMixin from './utilities-mixin.js';
import localizationMixin from './localization-mixin.js';
// eslint-disable-next-line max-len
import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';

// eslint-disable-next-line max-len
export class ManageUsersViewContributor extends utilitiesMixin(localizationMixin(PolymerElement)) {
export class ManageUsersViewContributor extends mixinBehaviors([AppLocalizeBehavior], PolymerElement) {
static get template() {
return html([`
<style>${css.toString()}</style>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {mockIronAjax, yieldForRequests} from '../ajax_test_helper';
import {flush} from '@polymer/polymer/lib/utils/flush.js';

import './dashboard-view';
import {languages} from '../assets/i18n/languages.json';

const FIXTURE_ID = 'manage-users-view-contributor-fixture';
const MU_VIEW_SELECTOR_ID = 'test-manage-users-contributor-view';
Expand Down Expand Up @@ -32,6 +33,8 @@ describe('Manage Users View Contributor', () => {
beforeEach(() => {
document.getElementById(FIXTURE_ID).create();
manageUsersView = document.getElementById(MU_VIEW_SELECTOR_ID);
manageUsersView.language = 'en';
manageUsersView.resources = languages;
});

afterEach(() => {
Expand Down
Loading

0 comments on commit 4ef3200

Please sign in to comment.