web/satellite: new project popup reworked

Change-Id: I90c14bed222824231a5f41bc7029d38cb405863e
This commit is contained in:
VitaliiShpital 2020-03-11 19:23:55 +02:00 committed by Vitalii Shpital
parent dedb87a6dd
commit 97df9b5704
7 changed files with 210 additions and 38 deletions

View File

@ -2,13 +2,15 @@
// See LICENSE for copying information.
<template>
<div class="new-project-popup-container" @keyup.enter="createProjectClick" @keyup.esc="onCloseClick">
<div v-if="isPopupShown" class="new-project-popup-container" @keyup.enter="createProjectClick" @keyup.esc="onCloseClick">
<div class="new-project-popup" id="newProjectPopup" >
<div class="new-project-popup__info-panel-container">
<h2 class="new-project-popup__info-panel-container__main-label-text">Create New Project</h2>
<img src="@/../static/images/project/createProject.jpg" alt="create project image">
</div>
<img class="new-project-popup__image" src="@/../static/images/project/createProject.jpg" alt="create project image">
<div class="new-project-popup__form-container">
<div class="new-project-popup__form-container__success-title-area">
<SuccessIcon/>
<p class="new-project-popup__form-container__success-title-area__title">Payment Method Added</p>
</div>
<h2 class="new-project-popup__form-container__main-title">Next, lets create a project.</h2>
<HeaderedInput
label="Project Name"
additional-label="Up To 20 Characters"
@ -31,7 +33,7 @@
/>
<div class="new-project-popup__form-container__button-container">
<VButton
label="Cancel"
label="Back to Billing"
width="205px"
height="48px"
:on-press="onCloseClick"
@ -59,6 +61,7 @@ import HeaderedInput from '@/components/common/HeaderedInput.vue';
import VButton from '@/components/common/VButton.vue';
import CloseCrossIcon from '@/../static/images/common/closeCross.svg';
import SuccessIcon from '@/../static/images/project/success.svg';
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
@ -77,6 +80,7 @@ import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
HeaderedInput,
VButton,
CloseCrossIcon,
SuccessIcon,
},
})
export default class NewProjectPopup extends Vue {
@ -86,21 +90,37 @@ export default class NewProjectPopup extends Vue {
private createdProjectId: string = '';
private isLoading: boolean = false;
/**
* Indicates if popup is shown.
*/
public get isPopupShown(): boolean {
return this.$store.state.appStateModule.appState.isNewProjectPopupShown;
}
/**
* Sets project name from input value.
*/
public setProjectName(value: string): void {
this.projectName = value;
this.nameError = '';
}
/**
* Sets project description from input value.
*/
public setProjectDescription(value: string): void {
this.description = value;
}
/**
* Closes popup.
*/
public onCloseClick(): void {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
}
/**
* Creates project.
* Creates project and refreshes store.
*/
public async createProjectClick(): Promise<void> {
if (this.isLoading) {
@ -158,6 +178,9 @@ export default class NewProjectPopup extends Vue {
this.isLoading = false;
}
/**
* Validates input value to satisfy project name rules.
*/
private validateProjectName(): boolean {
this.projectName = this.projectName.trim();
@ -177,6 +200,9 @@ export default class NewProjectPopup extends Vue {
return true;
}
/**
* Makes create project request.
*/
private async createProject(): Promise<Project> {
const project: CreateProjectModel = {
name: this.projectName,
@ -187,6 +213,9 @@ export default class NewProjectPopup extends Vue {
return await this.$store.dispatch(PROJECTS_ACTIONS.CREATE, project);
}
/**
* Selects just created project.
*/
private selectCreatedProject(): void {
this.$store.dispatch(PROJECTS_ACTIONS.SELECT, this.createdProjectId);
@ -202,31 +231,39 @@ export default class NewProjectPopup extends Vue {
isUsersFirstProject
? this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP)
: this.notifySuccess('Project created successfully!');
: this.$notify.success('Project created successfully!');
}
/**
* Clears project members store and fetches new.
*/
private async fetchProjectMembers(): Promise<void> {
await this.$store.dispatch(PM_ACTIONS.CLEAR);
const fistPage = 1;
await this.$store.dispatch(PM_ACTIONS.FETCH, fistPage);
}
/**
* Clears api keys store.
*/
private clearApiKeys(): void {
this.$store.dispatch(API_KEYS_ACTIONS.CLEAR);
}
/**
* Clears project usage store.
*/
private clearUsage(): void {
this.$store.dispatch(PROJECT_USAGE_ACTIONS.CLEAR);
}
/**
* Clears bucket usage store.
*/
private clearBucketUsage(): void {
this.$store.dispatch(BUCKET_ACTIONS.SET_SEARCH, '');
this.$store.dispatch(BUCKET_ACTIONS.CLEAR);
}
private async notifySuccess(message: string): Promise<void> {
await this.$notify.success(message);
}
}
</script>
@ -249,9 +286,8 @@ export default class NewProjectPopup extends Vue {
}
.new-project-popup {
width: 100%;
max-width: 845px;
height: 400px;
max-width: 970px;
height: auto;
background-color: #fff;
border-radius: 6px;
display: flex;
@ -259,7 +295,12 @@ export default class NewProjectPopup extends Vue {
align-items: center;
position: relative;
justify-content: center;
padding: 100px 100px 100px 80px;
padding: 70px 80px 70px 50px;
&__image {
min-height: 400px;
min-width: 500px;
}
&__info-panel-container {
display: flex;
@ -283,6 +324,25 @@ export default class NewProjectPopup extends Vue {
width: 100%;
max-width: 520px;
&__success-title-area {
display: flex;
align-items: center;
justify-content: flex-start;
&__title {
font-size: 20px;
line-height: 24px;
color: #34bf89;
margin: 0 0 0 5px;
}
}
&__main-title {
font-size: 32px;
line-height: 39px;
color: #384b65;
}
&__button-container {
width: 100%;
display: flex;

View File

@ -0,0 +1,4 @@
<svg width="18" height="13" viewBox="0 0 18 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.375 7.375C0.615609 6.61561 0.615609 5.38439 1.375 4.625C2.13439 3.86561 3.36561 3.86561 4.12501 4.625L8.70834 9.20834C9.46774 9.96773 9.46774 11.1989 8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583L1.375 7.375Z" fill="#34BF89"/>
<path d="M8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583C5.19895 11.1989 5.19895 9.96773 5.95834 9.20834L14.2084 0.958327C14.9677 0.198935 16.199 0.198935 16.9584 0.958327C17.7177 1.71772 17.7177 2.94894 16.9584 3.70833L8.70834 11.9583Z" fill="#34BF89"/>
</svg>

After

Width:  |  Height:  |  Size: 640 B

View File

@ -17,11 +17,15 @@ exports[`NewProjectArea renders correctly without projects and with credit card
<h1 class="new-project-button-container__label">+ Create Project</h1>
</div>
<div class="new-project-popup-container">
<div id="newProjectPopup" class="new-project-popup">
<div class="new-project-popup__info-panel-container">
<h2 class="new-project-popup__info-panel-container__main-label-text">Create New Project</h2> <img src="@/../static/images/project/createProject.jpg" alt="create project image">
</div>
<div id="newProjectPopup" class="new-project-popup"><img src="@/../static/images/project/createProject.jpg" alt="create project image" class="new-project-popup__image">
<div class="new-project-popup__form-container">
<div class="new-project-popup__form-container__success-title-area"><svg width="18" height="13" viewBox="0 0 18 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.375 7.375C0.615609 6.61561 0.615609 5.38439 1.375 4.625C2.13439 3.86561 3.36561 3.86561 4.12501 4.625L8.70834 9.20834C9.46774 9.96773 9.46774 11.1989 8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583L1.375 7.375Z" fill="#34BF89"></path>
<path d="M8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583C5.19895 11.1989 5.19895 9.96773 5.95834 9.20834L14.2084 0.958327C14.9677 0.198935 16.199 0.198935 16.9584 0.958327C17.7177 1.71772 17.7177 2.94894 16.9584 3.70833L8.70834 11.9583Z" fill="#34BF89"></path>
</svg>
<p class="new-project-popup__form-container__success-title-area__title">Payment Method Added</p>
</div>
<h2 class="new-project-popup__form-container__main-title">Next, lets create a project.</h2>
<div class="input-container full-input">
<div class="label-container">
<!---->
@ -44,7 +48,7 @@ exports[`NewProjectArea renders correctly without projects and with credit card
</div>
<div class="new-project-popup__form-container__button-container">
<div class="container white" style="width: 205px; height: 48px;">
<h1 class="label">Cancel</h1>
<h1 class="label">Back to Billing</h1>
</div>
<div class="container" style="width: 205px; height: 48px;">
<h1 class="label">Next</h1>

View File

@ -0,0 +1,54 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
import Vuex from 'vuex';
import NewProjectPopup from '@/components/project/NewProjectPopup.vue';
import { appStateModule } from '@/store/modules/appState';
import { makeProjectsModule } from '@/store/modules/projects';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { NotificatorPlugin } from '@/utils/plugins/notificator';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import { ProjectsApiMock } from '../mock/api/projects';
const notificationPlugin = new NotificatorPlugin();
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(notificationPlugin);
const projectsApi = new ProjectsApiMock();
const projectsModule = makeProjectsModule(projectsApi);
const store = new Vuex.Store({ modules: { appStateModule, projectsModule }});
describe('NewProjectPopup.vue', () => {
it('renders correctly', async (): Promise<void> => {
await store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
const wrapper = mount(NewProjectPopup, {
store,
localVue,
});
expect(wrapper).toMatchSnapshot();
await wrapper.vm.setProjectName('testName');
await wrapper.vm.createProjectClick();
expect(wrapper).toMatchSnapshot();
});
it('closes correctly', async (): Promise<void> => {
await store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
const wrapper = shallowMount(NewProjectPopup, {
store,
localVue,
});
await wrapper.find('.new-project-popup__close-cross-container').trigger('click');
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -7,7 +7,10 @@ import ProjectCreationSuccessPopup from '@/components/project/ProjectCreationSuc
import { appStateModule } from '@/store/modules/appState';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { mount } from '@vue/test-utils';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
const localVue = createLocalVue();
localVue.use(Vuex);
const store = new Vuex.Store({ modules: { appStateModule }});
@ -15,16 +18,18 @@ describe('ProjectCreationSuccessPopup.vue', () => {
it('renders correctly', async (): Promise<void> => {
await store.dispatch(APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PROJECT_CREATION_POPUP);
const wrapper = mount(ProjectCreationSuccessPopup, {
const wrapper = shallowMount(ProjectCreationSuccessPopup, {
store,
localVue,
});
expect(wrapper).toMatchSnapshot();
});
it('closes correctly', async (): Promise<void> => {
const wrapper = mount(ProjectCreationSuccessPopup, {
const wrapper = shallowMount(ProjectCreationSuccessPopup, {
store,
localVue,
});
await wrapper.find('.project-creation-success-popup__close-cross-container').trigger('click');

View File

@ -0,0 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NewProjectPopup.vue closes correctly 1`] = ``;
exports[`NewProjectPopup.vue renders correctly 1`] = `
<div class="new-project-popup-container">
<div id="newProjectPopup" class="new-project-popup"><img src="@/../static/images/project/createProject.jpg" alt="create project image" class="new-project-popup__image">
<div class="new-project-popup__form-container">
<div class="new-project-popup__form-container__success-title-area"><svg width="18" height="13" viewBox="0 0 18 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.375 7.375C0.615609 6.61561 0.615609 5.38439 1.375 4.625C2.13439 3.86561 3.36561 3.86561 4.12501 4.625L8.70834 9.20834C9.46774 9.96773 9.46774 11.1989 8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583L1.375 7.375Z" fill="#34BF89"></path>
<path d="M8.70834 11.9583C7.94895 12.7177 6.71773 12.7177 5.95834 11.9583C5.19895 11.1989 5.19895 9.96773 5.95834 9.20834L14.2084 0.958327C14.9677 0.198935 16.199 0.198935 16.9584 0.958327C17.7177 1.71772 17.7177 2.94894 16.9584 3.70833L8.70834 11.9583Z" fill="#34BF89"></path>
</svg>
<p class="new-project-popup__form-container__success-title-area__title">Payment Method Added</p>
</div>
<h2 class="new-project-popup__form-container__main-title">Next, lets create a project.</h2>
<div class="input-container full-input">
<div class="label-container">
<!---->
<h3 class="label-container__label">Project Name</h3>
<h3 class="label-container__label add-label">Up To 20 Characters</h3>
<!---->
</div>
<!---->
<!----> <input id="Project Name" placeholder="Enter Project Name" type="text" class="headered-input" style="width: 100%; height: 48px;">
</div>
<div class="input-container full-input">
<div class="label-container">
<!---->
<h3 class="label-container__label">Description</h3>
<h3 class="label-container__label add-label">Optional</h3>
<!---->
</div>
<!----> <textarea id="Description" placeholder="Enter Project Description" rows="5" cols="40" wrap="hard" class="headered-textarea" style="width: 100%; height: 100px;"></textarea>
<!---->
</div>
<div class="new-project-popup__form-container__button-container">
<div class="container white" style="width: 205px; height: 48px;">
<h1 class="label">Back to Billing</h1>
</div>
<div class="container" style="width: 205px; height: 48px;">
<h1 class="label">Next</h1>
</div>
</div>
</div>
<div class="new-project-popup__close-cross-container"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65" class="close-cross-svg-path"></path>
</svg></div>
</div>
</div>
`;
exports[`NewProjectPopup.vue renders correctly 2`] = ``;

View File

@ -5,11 +5,8 @@ exports[`ProjectCreationSuccessPopup.vue closes correctly 1`] = ``;
exports[`ProjectCreationSuccessPopup.vue renders correctly 1`] = `
<div class="project-creation-success-popup-container">
<div id="successfulProjectCreationPopup" class="project-creation-success-popup">
<div class="project-creation-success-popup__info-panel-container"><svg width="123" height="123" viewBox="0 0 123 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="61.5" cy="61.5" r="59.5" fill="white" stroke="#34BF89" stroke-width="4"></circle>
<path d="M28.9292 66.1529C25.9126 63.1363 25.9126 58.2453 28.9292 55.2287C31.9459 52.212 36.8368 52.212 39.8535 55.2287L58.0606 73.4358C61.0773 76.4524 61.0773 81.3434 58.0606 84.3601C55.044 87.3767 50.153 87.3767 47.1363 84.3601L28.9292 66.1529Z" fill="#34BF89"></path>
<path d="M58.0606 84.3601C55.044 87.3767 50.153 87.3767 47.1363 84.3601C44.1197 81.3434 44.1197 76.4524 47.1363 73.4358L79.9092 40.663C82.9258 37.6463 87.8168 37.6463 90.8334 40.663C93.8501 43.6796 93.8501 48.5706 90.8334 51.5872L58.0606 84.3601Z" fill="#34BF89"></path>
</svg>
<div class="project-creation-success-popup__info-panel-container">
<projectcreationsuccessicon-stub></projectcreationsuccessicon-stub>
<p class="project-creation-success-popup__info-panel-container__title">Project Created!</p>
</div>
<div class="project-creation-success-popup__form-container">
@ -17,17 +14,13 @@ exports[`ProjectCreationSuccessPopup.vue renders correctly 1`] = `
<p class="project-creation-success-popup__form-container__confirmation-text">You just created your project. Next, we recommend you create your first API Key for this project. API Keys allow developers to manage their projects and build applications on top of the Storj network through our
<a href="https://documentation.tardigrade.io/api-reference/uplink-cli" target="_blank" class="project-creation-success-popup__form-container__confirmation-text__link">Uplink CLI.</a></p>
<div class="project-creation-success-popup__form-container__button-container">
<div class="container white" style="width: 214px; height: 50px;">
<h1 class="label">I will do it later</h1>
</div>
<div class="container" style="width: 214px; height: 50px;">
<h1 class="label">Create API Key</h1>
</div>
<vbutton-stub label="I will do it later" width="214px" height="50px" iswhite="true" onpress="function () { [native code] }"></vbutton-stub>
<vbutton-stub label="Create API Key" width="214px" height="50px" onpress="function () { [native code] }"></vbutton-stub>
</div>
</div>
<div class="project-creation-success-popup__close-cross-container"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.7071 1.70711C16.0976 1.31658 16.0976 0.683417 15.7071 0.292893C15.3166 -0.0976311 14.6834 -0.0976311 14.2929 0.292893L15.7071 1.70711ZM0.292893 14.2929C-0.0976311 14.6834 -0.0976311 15.3166 0.292893 15.7071C0.683417 16.0976 1.31658 16.0976 1.70711 15.7071L0.292893 14.2929ZM1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L1.70711 0.292893ZM14.2929 15.7071C14.6834 16.0976 15.3166 16.0976 15.7071 15.7071C16.0976 15.3166 16.0976 14.6834 15.7071 14.2929L14.2929 15.7071ZM14.2929 0.292893L0.292893 14.2929L1.70711 15.7071L15.7071 1.70711L14.2929 0.292893ZM0.292893 1.70711L14.2929 15.7071L15.7071 14.2929L1.70711 0.292893L0.292893 1.70711Z" fill="#384B65" class="close-cross-svg-path"></path>
</svg></div>
<div class="project-creation-success-popup__close-cross-container">
<closecrossicon-stub></closecrossicon-stub>
</div>
</div>
</div>
`;