Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat new namespace #174

Merged
merged 14 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions components/centraldashboard/cypress/e2e/landing-page.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Landing Page', () => {
cy.mockDashboardLinksRequest();
cy.intercept('GET', `/api/workgroup/exists`, {
"hasAuth":true,
"user":"user.name",
"user":"user.name@email.com",
"hasWorkgroup":false,
"registrationFlowAllowed":true
}).as('mockWorkgroupRequest');
Expand All @@ -16,7 +16,8 @@ describe('Landing Page', () => {
it('should access the landing page', ()=>{
cy.get('main-page').shadow().find('landing-page').should('exist');
cy.get('main-page').shadow().find('landing-page').shadow().find('#MainCard > neon-animatable > h2').should('have.text', 'Welcome');
cy.get('main-page').shadow().find('landing-page').shadow().find('#MainCard > neon-animatable > aside').should('have.text', 'It seems like you have not been assigned to a workspace, please refer to your project owner or join us on our Slack support channel at https://statcan-aaw.slack.com');
cy.get('main-page').shadow().find('landing-page').shadow().find('#MainCard > neon-animatable > aside').find('a').should('exist').and('have.prop', 'href', 'https://statcan-aaw.slack.com/');
cy.get('main-page').shadow().find('landing-page').shadow().find('#MainCard > neon-animatable').find('md2-input#Email').should('exist').and('have.prop', 'value', '[email protected]');
cy.get('main-page').shadow().find('landing-page').shadow().find('#MainCard > neon-animatable').find('md2-input#Namespace').should('exist').and('have.prop', 'value', 'user-name');
});
});
15 changes: 12 additions & 3 deletions components/centraldashboard/public/assets/i18n/languages.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@
"notebookCard.txtAccessed": "Accessed ",
"registrationPage.lblWelcome": "Welcome",
"registrationPage.registrationDesc": "In order to use Kubeflow, a namespace for your account must be created. Follow the steps to get started",
"landingPage.landingDesc": "It seems like you have not been assigned to a workspace, please refer to your project owner or join us on our Slack support channel at",
"landingPage.landingDesc": "If you have questions or issues, please contact our Slack support channel at",
"landingPage.slackLink": "https://statcan-aaw.slack.com",
"registrationPage.btnStartSetup": "Start Setup",
"landingPage.firstTime": "This seems to be the first time you access Kubeflow, we are happy to see you!",
"landingPage.autoNamespace": "Your namespace is automatically generated.",
"landingPage.yourNamespace": "Your namespace will be",
"landingPage.email": "Your email is",
"registrationPage.btnNext": "Next",
"registrationPage.lblNamespace": "Namespace",
"registrationPage.lblNamespaceDesc": "A namespace is a collection of Kubeflow services. Resources created within a namespace are isolated to that namespace. By default, a namespace will be created for you.",
"registrationPage.lblNamespaceName": "Namespace Name",
Expand Down Expand Up @@ -167,8 +171,13 @@
"notebookCard.txtAccessed": "Accédé ",
"registrationPage.lblWelcome": "Bienvenue",
"registrationPage.registrationDesc": "Afin d'utiliser Kubeflow, un espace de noms doit être créé pour votre compte. Suiver les étapes pour commencer",
"landingPage.landingDesc": "Il semble que vous n'avez pas été assigné à un espace de travail, veuillez référer au propriétaire de votre projet ou rejoignez-nous sur notre canal d'assistance Slack à",
"landingPage.landingDesc": "Si vous avez des questions ou des problèmes, joignez-nous sur notre canal d'assistance Slack à",
"landingPage.slackLink": "https://statcan-aaw.slack.com",
"landingPage.firstTime": "Ceci semble être la première fois que vous accédez à Kubeflow, nous sommes heureux de vous voir !",
"landingPage.autoNamespace": "Votre espace de noms est automatiquement généré.",
"landingPage.yourNamespace": "Votre espace de noms sera",
"landingPage.email": "Votre courriel est",
"registrationPage.btnNext": "Suivant",
"registrationPage.btnStartSetup": "Commencer",
"registrationPage.lblNamespace": "Espace de nom",
"registrationPage.lblNamespaceDesc": "Un espace de nom est une collection de services Kubeflow. Les ressources créées dans cet espace sont isolés à cette espace de nom. Par défault, un espace de nom sera créé pour vous.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ h2+aside {
}

#MainCard .Main-Content {
height: 275px;
}

neon-animatable {
Expand All @@ -67,9 +66,7 @@ neon-animatable {

#Links {
bottom: 0;
left: 50%;
transform: translateX(-50%);
position: absolute;
position: relative;
padding: 3em;
font-size: .8em;
width: 100%;
Expand Down
108 changes: 107 additions & 1 deletion components/centraldashboard/public/components/landing-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,116 @@ import utilitiesMixin from './utilities-mixin.js';
export class LandingPage extends mixinBehaviors([AppLocalizeBehavior], utilitiesMixin(PolymerElement)) {
static get template() {
const vars = {logo};

return html([
`<style>${css.toString()}</style>${template(vars)}`]);
}

static get properties() {
return {
userDetails: {type: Object, observer: '_onUserDetails'},
namespaceName: String,
emailAddress: String,
error: Object,
flowComplete: {type: Boolean, value: false},
waitForRedirect: {type: Boolean, value: false},
showAPIText: {type: Boolean, value: false},
};
}

ready() {
super.ready();
}

_onUserDetails(d) {
this.emailAddress = this.userDetails;
this.generateNamespace(this.userDetails);
}

async generateNamespace(email) {
// Since email includes an @ , we split to the left side of it'
const name = email.split('@', 1);
let ns = name[0];
ns = ns
.replace(/[^\w]|\./g, '-')
.replace(/^-+|-+$|_/g, '')
.toLowerCase();

this.getNamespaces(ns);
}

async getNamespaces(ns) {
await fetch(
`/api/namespaces/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}
)
.then((res) => res.json())
.then((data) => {
const namespaceNames = [];
data.forEach((element) => {
namespaceNames.push(element.metadata.name);
});
let counter = 1;
const originalNs = ns;
if (namespaceNames.includes(originalNs)) {
while (namespaceNames.includes(originalNs + counter)) {
counter++;
}
ns = originalNs + counter;
}
this.namespaceName = ns;
}).catch((e)=> {
this.set('error', {response: {
error: e,
namespace: this.namespaceName,
}});
});
}

async nextPage() {
const API = this.$.MakeNamespace;
API.body = {namespace: this.namespaceName};
this.waitForRedirect = true;
await API.generateRequest().completes.catch((e) => e);
await this.sleep(1); // So the errors and callbacks can schedule
if (this.error && this.error.response) {
if (this.error.response.error) {
this.set('error', {response: {
error: 'registrationPage.errDuplicate',
namespace: this.namespaceName,
}});
}
return this.waitForRedirect = false;
}
/*
* Poll for profile over a span of 20 seconds (every 300ms)
* if still not there, let the user click next again!
*/
const success = await this.pollProfile(66, 300);
if (success) this._successSetup();
this.waitForRedirect = false;
}

async pollProfile(times, delay) {
const profileAPI = this.$.GetMyNamespace;
if (times < 1) throw Error('Cannot poll profile < 1 times!');
for (let i = 0; i < times; i++) {
const req = profileAPI.generateRequest();
await req.completes.catch(() => 0);
if (req.response && req.response.hasWorkgroup) return true;
await this.sleep(delay);
}
}

_successSetup() {
this.flowComplete = true;
this.set('error', {});
this.fireEvent('flowcomplete');
}
}


window.customElements.define('landing-page', LandingPage);
16 changes: 13 additions & 3 deletions components/centraldashboard/public/components/landing-page.pug
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
iron-ajax#MakeNamespace(method='POST', url='/api/workgroup/create', handle-as='json', last-error='{{error}}', last-response='{{resp}}',
content-type='application/json', loading='{{submittingWorkgroup}}')
paper-card#MainCard
figure#Logo !{logo}
neon-animatable.Main-Content
h2 {{localize('registrationPage.lblWelcome')}}
aside {{localize('landingPage.landingDesc')}}
a(href='https://statcan-aaw.slack.com', tabindex='-1', target="_blank") {{localize('landingPage.slackLink')}}
h2 {{localize('registrationPage.lblWelcome')}}

p {{localize('landingPage.firstTime')}}
p {{localize('landingPage.autoNamespace')}}

md2-input#Email(label="{{localize('landingPage.email')}}", value='{{emailAddress}}', disabled="true")
md2-input#Namespace(label="{{localize('landingPage.yourNamespace')}}", value='{{namespaceName}}', disabled='true')
aside {{localize('landingPage.landingDesc')}}
a(href='https://statcan-aaw.slack.com', tabindex='-1', target="_blank") {{localize('landingPage.slackLink')}}
.actions
paper-button(on-click='nextPage') {{localize('registrationPage.btnNext')}}

nav#Links
a(href='https://github.com/kubeflow/kubeflow', tabindex='-1', target="_blank") {{localize('registrationPage.linkGitHub')}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,4 @@ 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', language='[[language]]', resources='[[resources]]')
landing-page(user-details='[[user]]' on-flowcomplete='resyncApp', language='[[language]]', resources='[[resources]]')
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
slot(name='prefix', slot='prefix')
iron-input#ironInput(allowed-pattern='[[allowedPattern]]', bind-value='{{value}}')
input#inputElement(placeholder='[[placeholder]]', maxlength$='[[maxlength]]'
on-focus='inputFocused', on-blur='inputBlurred', on-keydown='validateRange')
on-focus='inputFocused', on-blur='inputBlurred', on-keydown='validateRange', disabled='[[disabled]]')
slot(name='suffix', slot='suffix')
iron-a11y-keys#keys(target='[[inputElement]]', keys='enter', on-keys-pressed='fireEnter')
aside.Error [[error]]
Loading