Skip to content

Commit

Permalink
[MS] Added back buttons after server choice on organization creation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ironicbay committed Sep 20, 2024
1 parent 0615faa commit c1d41d7
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 28 deletions.
3 changes: 2 additions & 1 deletion client/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1211,12 +1211,13 @@
},
"clientArea": {
"app": {
"titleLinkOrganization": "Link you customer account to your new organization",
"titleLinkOrganization": "Link your customer account to your new organization",
"titleLogin": "Log in to your customer account",
"emailLabel": "Email",
"password": "Password",
"forgottenPassword": "Forgot your password?",
"login": "Log in",
"backButton": "Back",
"saveLogin": "Remember me",
"loginFailed": "Cannot log in. Please check your email and password.",
"networkFailed": "Could not reach the server. Make sure that you are online and try again.",
Expand Down
1 change: 1 addition & 0 deletions client/src/locales/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,7 @@
"password": "Mot de passe",
"forgottenPassword": "Mot de passe oublié ?",
"login": "Se connecter",
"backButton": "Retour",
"saveLogin": "Se souvenir de moi",
"loginFailed": "Impossible de se connecter. Veuillez vérifier votre email et mot de passe.",
"networkFailed": "Impossible de contacter le serveur. Veuillez vérifier votre connexion à internet.",
Expand Down
22 changes: 20 additions & 2 deletions client/src/views/client-area/BmsLogin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,18 @@
</ion-text>
</div>

<!-- login button -->
<!-- back and login buttons -->
<div class="saas-login-button">
<ion-text
v-show="!hideBackButton"
:disabled="querying"
class="button-medium custom-button custom-button-ghost saas-login-button__item"
button
@click="$emit('goBackRequested')"
>
<ion-icon :icon="arrowBack" />
{{ $msTranslate('clientArea.app.backButton') }}
</ion-text>
<ion-button
v-if="!loading"
:disabled="!emailInputRef || emailInputRef.validity !== Validity.Valid || !password.length || querying"
Expand Down Expand Up @@ -182,7 +192,7 @@
import { IonButton, IonText, IonButtons, IonFooter, IonIcon, IonSkeletonText } from '@ionic/vue';
import { MsInput, MsPasswordInput, Translatable, Validity, MsSpinner, MsCheckbox } from 'megashark-lib';
import { emailValidator } from '@/common/validators';
import { warning, arrowForward, close } from 'ionicons/icons';
import { warning, arrowBack, arrowForward, close } from 'ionicons/icons';
import { onMounted, ref } from 'vue';
import { AuthenticationToken, BmsAccessInstance, PersonalInformationResultData } from '@/services/bms';
import CreateOrganizationModalHeader from '@/components/organizations/CreateOrganizationModalHeader.vue';
Expand All @@ -191,11 +201,13 @@ import { Env } from '@/services/environment';
const props = defineProps<{
email?: string;
hideHeader?: boolean;
hideBackButton?: boolean;
}>();
const emits = defineEmits<{
(e: 'loginSuccess', token: AuthenticationToken, personalInformation: PersonalInformationResultData): void;
(e: 'closeRequested'): void;
(e: 'goBackRequested'): void;
(e: 'forgottenPasswordClicked'): void;
}>();
Expand Down Expand Up @@ -343,12 +355,18 @@ async function onLoginClicked(): Promise<void> {
display: flex;
gap: 1rem;
align-items: center;
justify-content: end;
margin-top: 0.5rem;
width: 100%;
&__item {
height: 2.5rem;
border-radius: var(--parsec-radius-6);
border: 1px solid transparent;
&:hover {
border: 1px solid var(--parsec-color-light-secondary-contrast);
}
}
.skeleton-login-button {
Expand Down
1 change: 1 addition & 0 deletions client/src/views/client-area/ClientAreaLoginPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
v-if="section === Sections.BmsLogin"
@login-success="onLoginSuccess"
:hide-header="true"
:hide-back-button="true"
class="saas-login"
@forgotten-password-clicked="switchSection(Sections.BmsForgotPassword)"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
:disable-server-addr-field="bootstrapLink !== undefined"
:disable-organization-name-field="bootstrapLink !== undefined"
@organization-name-and-server-chosen="onOrganizationNameAndServerChosen"
@go-back-requested="$emit('backRequested')"
@close-requested="$emit('closeRequested')"
:hide-previous="true"
:hide-previous="bootstrapLink !== undefined"
/>
<organization-user-information-page
v-show="step === Steps.PersonalInformation"
Expand Down Expand Up @@ -107,6 +108,7 @@ const props = defineProps<{
const emits = defineEmits<{
(e: 'closeRequested'): void;
(e: 'backRequested'): void;
(e: 'organizationCreated', organizationName: OrganizationID, device: AvailableDevice, saveStrategy: DeviceSaveStrategy): void;
}>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@
:information-manager="informationManager"
@close-requested="onCloseRequested"
@organization-created="onOrganizationCreated"
@back-requested="onBackToServerChoice"
/>
<create-organization-custom-server
v-if="serverType === ServerType.Custom"
:bootstrap-link="bootstrapLink"
@close-requested="onCloseRequested"
@organization-created="onOrganizationCreated"
@back-requested="onBackToServerChoice"
/>
<create-organization-trial
v-if="serverType === ServerType.Trial"
:bootstrap-link="bootstrapLink"
@close-requested="onCloseRequested"
@organization-created="onOrganizationCreated"
@back-requested="onBackToServerChoice"
:information-manager="informationManager"
/>
</div>
Expand Down Expand Up @@ -103,6 +106,10 @@ async function onOrganizationCreated(
: AccessStrategy.usePassword(device, (saveStrategy as DeviceSaveStrategyPassword).password);
await modalController.dismiss({ device: device, access: accessStrategy }, MsModalResult.Confirm);
}
async function onBackToServerChoice(): Promise<void> {
serverType.value = undefined;
}
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
v-show="step === Steps.BmsLogin"
@login-success="onLoginSuccess"
@close-requested="$emit('closeRequested', false)"
@go-back-requested="$emit('backRequested')"
@forgotten-password-clicked="step = Steps.BmsForgotPassword"
/>
<bms-forgot-password
Expand All @@ -20,6 +21,8 @@
:organization-name="organizationName ?? ''"
@organization-name-chosen="onOrganizationNameChosen"
:error="currentError"
@go-back-requested="$emit('backRequested')"
:hide-previous="bootstrapLink !== undefined"
@close-requested="$emit('closeRequested', false)"
/>
<organization-authentication-page
Expand Down Expand Up @@ -107,6 +110,7 @@ const props = defineProps<{
const emits = defineEmits<{
(e: 'closeRequested', force: boolean): void;
(e: 'backRequested'): void;
(e: 'organizationCreated', organizationName: OrganizationID, device: AvailableDevice, saveStrategy: DeviceSaveStrategy): void;
}>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
v-show="step === Steps.PersonalInformation"
:class="step === Steps.PersonalInformation ? 'active' : ''"
@user-information-filled="onUserInformationFilled"
@go-back-requested="$emit('backRequested')"
@close-requested="$emit('closeRequested')"
:hide-previous="true"
:hide-previous="bootstrapLink !== undefined"
/>
<organization-authentication-page
v-show="step === Steps.Authentication"
Expand Down Expand Up @@ -71,6 +72,7 @@ const props = defineProps<{
const emits = defineEmits<{
(e: 'closeRequested'): void;
(e: 'backRequested'): void;
(e: 'organizationCreated', organizationName: OrganizationID, device: AvailableDevice, saveStrategy: DeviceSaveStrategy): void;
}>();
Expand Down
19 changes: 18 additions & 1 deletion client/src/views/organizations/creation/OrganizationNamePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@
slot="primary"
class="modal-footer-buttons"
>
<ion-button
fill="clear"
size="default"
id="previous-button"
@click="$emit('goBackRequested')"
v-show="!hidePrevious"
>
{{ $msTranslate('CreateOrganization.button.previous') }}
<ion-icon
slot="start"
:icon="chevronBack"
size="small"
/>
</ion-button>

<ion-button
fill="solid"
size="default"
Expand All @@ -65,7 +80,7 @@
import { OrganizationID } from '@/parsec';
import { IonPage, IonButton, IonText, IonButtons, IonFooter, IonIcon } from '@ionic/vue';
import { onMounted, ref } from 'vue';
import { chevronForward } from 'ionicons/icons';
import { chevronBack, chevronForward } from 'ionicons/icons';
import { organizationValidator } from '@/common/validators';
import { Translatable, Validity, MsInput } from 'megashark-lib';
import CreateOrganizationModalHeader from '@/components/organizations/CreateOrganizationModalHeader.vue';
Expand All @@ -75,10 +90,12 @@ const props = defineProps<{
organizationName?: OrganizationID;
error?: Translatable;
disableOrganizationNameField?: boolean;
hidePrevious?: boolean;
}>();
defineEmits<{
(e: 'organizationNameChosen', name: OrganizationID): void;
(e: 'goBackRequested'): void;
(e: 'closeRequested'): void;
}>();
Expand Down
6 changes: 3 additions & 3 deletions client/tests/pw/e2e/client_area_login.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ msTest('Log into the customer area', async ({ home }) => {
await expect(home.locator('.saas-login-container').locator('.saas-login__title')).toHaveText('Log in to your customer account');
await fillIonInput(home.locator('.input-container').nth(0).locator('ion-input'), DEFAULT_USER_INFORMATION.email);
await fillIonInput(home.locator('.input-container').nth(1).locator('ion-input'), DEFAULT_USER_INFORMATION.password);
await home.locator('.saas-login-button__item').click();
await home.locator('.saas-login-button__item').nth(1).click();
await expect(home.locator('.header-content').locator('.header-title')).toHaveText('Dashboard');
const logOutButton = home.locator('.header-content').locator('.custom-button').first();
await expect(logOutButton).toHaveText('Log out');
Expand All @@ -45,7 +45,7 @@ msTest('Log into the customer area failed', async ({ home }) => {
await expect(home).toHaveURL(/.+\/home$/);
await fillIonInput(home.locator('.input-container').nth(0).locator('ion-input'), DEFAULT_USER_INFORMATION.email);
await fillIonInput(home.locator('.input-container').nth(1).locator('ion-input'), 'invalid_password');
await home.locator('.saas-login-button__item').click();
await home.locator('.saas-login-button__item').nth(1).click();
const error = home.locator('.saas-login-container').locator('.login-button-error');
await expect(error).toBeVisible();
await expect(error).toHaveText('Cannot log in. Please check your email and password.');
Expand Down Expand Up @@ -140,7 +140,7 @@ for (const frozen of [false, true]) {
await button.click();
await fillIonInput(home.locator('.input-container').nth(0).locator('ion-input'), DEFAULT_USER_INFORMATION.email);
await fillIonInput(home.locator('.input-container').nth(1).locator('ion-input'), DEFAULT_USER_INFORMATION.password);
await home.locator('.saas-login-button__item').click();
await home.locator('.saas-login-button__item').nth(1).click();
const orgSwitchButton = home.locator('.sidebar-header').locator('.card-header-title');
await expect(orgSwitchButton).toHaveText('All organizations');
await orgSwitchButton.click();
Expand Down
49 changes: 49 additions & 0 deletions client/tests/pw/e2e/create_organization.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

import { expect } from '@tests/pw/helpers/assertions';
import { MockBms } from '@tests/pw/helpers/bms';
import { DEFAULT_USER_INFORMATION } from '@tests/pw/helpers/data';
import { msTest } from '@tests/pw/helpers/fixtures';
import { fillIonInput } from '@tests/pw/helpers/utils';

msTest('Opens the create organization modal', async ({ home }) => {
await expect(home.locator('#create-organization-button')).toHaveText('Create or join');
Expand Down Expand Up @@ -35,3 +38,49 @@ msTest('Opens the create organization modal', async ({ home }) => {
await modal.locator('.closeBtn').click();
await expect(modal).toBeHidden();
});

msTest('Return to server selection after selecting server type', async ({ home }) => {
await home.locator('#create-organization-button').click();
await home.locator('.popover-viewport').getByRole('listitem').nth(0).click();
const modal = home.locator('.create-organization-modal');
await expect(modal.locator('.server-modal')).toBeVisible();

// Go to saas and back
await modal.locator('.server-choice-item').nth(0).click();
await modal.locator('.server-modal-footer').locator('ion-button').nth(1).click();
await expect(modal.locator('.saas-login')).toBeVisible();
await modal.locator('.saas-login-button__item').nth(0).click();
await expect(modal.locator('.server-modal')).toBeVisible();

// Go to saas, login, and back
await modal.locator('.server-choice-item').nth(0).click();
await modal.locator('.server-modal-footer').locator('ion-button').nth(1).click();

await MockBms.mockLogin(home);
await MockBms.mockUserRoute(home);
const bmsContainer = modal.locator('.saas-login');
const bmsNext = bmsContainer.locator('.saas-login-button').locator('.saas-login-button__item').nth(1);

await fillIonInput(bmsContainer.locator('ion-input').nth(0), DEFAULT_USER_INFORMATION.email);
await expect(bmsNext).toHaveDisabledAttribute();
await fillIonInput(bmsContainer.locator('ion-input').nth(1), DEFAULT_USER_INFORMATION.password);
await expect(bmsNext).not.toHaveDisabledAttribute();
await bmsNext.click();
await expect(bmsContainer).toBeHidden();
await expect(modal.locator('.organization-name-page')).toBeVisible();
await modal.locator('.organization-name-page').locator('#previous-button').click();
await expect(modal.locator('.server-modal')).toBeVisible();

// To to trial and back
await modal.locator('.server-choice-item').nth(1).click();
await modal.locator('.server-modal-footer').locator('ion-button').nth(1).click();
await expect(modal.locator('.user-information-page')).toBeVisible();
await modal.locator('.user-information-page').locator('#previous-button').click();
await expect(modal.locator('.server-modal')).toBeVisible();

// Go to custom and back
await modal.locator('.server-modal-footer').locator('ion-button').nth(0).click();
await expect(modal.locator('.organization-name-and-server-page')).toBeVisible();
await modal.locator('.organization-name-and-server-page').locator('#previous-button').click();
await expect(modal.locator('.server-modal')).toBeVisible();
});
4 changes: 0 additions & 4 deletions client/tests/pw/e2e/create_organization_custom.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ msTest('Go through custom org creation process', async ({ home }) => {

const orgServerContainer = modal.locator('.organization-name-and-server-page');
await expect(orgServerContainer.locator('.modal-header-title__text')).toHaveText('Create organization on my Parsec server');
const orgPrevious = orgServerContainer.locator('.organization-name-and-server-page-footer').locator('ion-button').nth(0);
const orgNext = orgServerContainer.locator('.organization-name-and-server-page-footer').locator('ion-button').nth(1);
await expect(orgPrevious).toBeHidden();
await expect(orgNext).toHaveDisabledAttribute();
await fillIonInput(orgServerContainer.locator('ion-input').nth(0), DEFAULT_ORGANIZATION_INFORMATION.name);
await expect(orgNext).toHaveDisabledAttribute();
Expand Down Expand Up @@ -206,9 +204,7 @@ msTest('Go through custom org creation process from bootstrap link', async ({ ho

const orgServerContainer = modal.locator('.organization-name-and-server-page');
await expect(orgServerContainer.locator('.modal-header-title__text')).toHaveText('Create organization on my Parsec server');
const orgPrevious = orgServerContainer.locator('.organization-name-and-server-page-footer').locator('ion-button').nth(0);
const orgNext = orgServerContainer.locator('.organization-name-and-server-page-footer').locator('ion-button').nth(1);
await expect(orgPrevious).toBeHidden();
await expect(orgNext).not.toHaveDisabledAttribute();

await expect(orgServerContainer.locator('ion-input').nth(0)).toHaveTheClass('input-disabled');
Expand Down
Loading

0 comments on commit c1d41d7

Please sign in to comment.