web/satellite: confirm saving API key modal implemented
WHAT: modal with saving API key confirmation implemented for onboarding tour WHY: ensure user saved API key Change-Id: I9bc000cf5a19a9d6fc9eb3a4bfb9156d6b4bc78f
This commit is contained in:
parent
00f9882ad5
commit
c921710247
@ -70,6 +70,10 @@
|
||||
:on-press="onDoneClick"
|
||||
:is-disabled="isCreatingState"
|
||||
/>
|
||||
<SaveApiKeyModal
|
||||
v-if="isSaveApiKeyModalShown"
|
||||
@confirmSave="onConfirmClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -78,11 +82,13 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
import SaveApiKeyModal from '@/components/onboardingTour/steps/SaveApiKeyModal.vue';
|
||||
|
||||
import InfoImage from '@/../static/images/onboardingTour/info.svg';
|
||||
|
||||
import { API_KEYS_ACTIONS } from '@/store/modules/apiKeys';
|
||||
import { ApiKey } from '@/types/apiKeys';
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { SegmentEvent } from '@/utils/constants/analyticsEventNames';
|
||||
import { AddingApiKeyState } from '@/utils/constants/onboardingTourEnums';
|
||||
|
||||
@ -95,6 +101,7 @@ const {
|
||||
components: {
|
||||
VButton,
|
||||
HeaderedInput,
|
||||
SaveApiKeyModal,
|
||||
InfoImage,
|
||||
},
|
||||
})
|
||||
@ -107,6 +114,13 @@ export default class CreateApiKeyStep extends Vue {
|
||||
public errorMessage: string = '';
|
||||
public isLoading: boolean = false;
|
||||
|
||||
/**
|
||||
* Indicates if save API key modal is shown.
|
||||
*/
|
||||
public get isSaveApiKeyModalShown(): boolean {
|
||||
return this.$store.state.appStateModule.appState.isSaveApiKeyModalShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if view is in creating state.
|
||||
*/
|
||||
@ -190,9 +204,17 @@ export default class CreateApiKeyStep extends Vue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tour state to last step.
|
||||
* Toggles save API key modal visibility.
|
||||
*/
|
||||
public onDoneClick(): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SAVE_API_KEY_MODAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tour state to last step.
|
||||
*/
|
||||
public onConfirmClick(): void {
|
||||
this.onDoneClick();
|
||||
this.$emit('setUploadDataState');
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,116 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div class="save-api-modal">
|
||||
<div class="save-api-modal__container">
|
||||
<OrangeExclamation/>
|
||||
<h1 class="save-api-modal__container__title">Is Your API Key Saved?</h1>
|
||||
<p class="save-api-modal__container__message">
|
||||
API Keys are only displayed once when generated. If you haven’t saved your key, go back to copy and
|
||||
paste the API key to your preferred method of storing secrets (i.e. TextEdit, Keybase, etc.)
|
||||
</p>
|
||||
<div class="save-api-modal__container__buttons-area">
|
||||
<VButton
|
||||
class="back-button"
|
||||
width="186px"
|
||||
height="45px"
|
||||
label="Go Back"
|
||||
:on-press="onBackClick"
|
||||
:is-blue-white="true"
|
||||
/>
|
||||
<VButton
|
||||
width="186px"
|
||||
height="45px"
|
||||
label="Yes, it's Saved!"
|
||||
:on-press="onConfirmClick"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
import VButton from '@/components/common/VButton.vue';
|
||||
|
||||
import OrangeExclamation from '@/../static/images/onboardingTour/orange-exclamation.svg';
|
||||
|
||||
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
OrangeExclamation,
|
||||
VButton,
|
||||
},
|
||||
})
|
||||
|
||||
export default class SaveApiKeyModal extends Vue {
|
||||
/**
|
||||
* Toggles modal visibility.
|
||||
*/
|
||||
public onBackClick(): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_SAVE_API_KEY_MODAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proceeds to tour's last step.
|
||||
*/
|
||||
public onConfirmClick(): void {
|
||||
this.$emit('confirmSave');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.save-api-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(9, 21, 35, 0.85);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'font_regular', sans-serif;
|
||||
|
||||
&__container {
|
||||
background-color: #fff;
|
||||
z-index: 1;
|
||||
padding: 35px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
max-width: 460px;
|
||||
|
||||
&__title {
|
||||
font-family: 'font_bold', sans-serif;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
color: #000;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #000;
|
||||
word-break: break-word;
|
||||
text-align: center;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
&__buttons-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back-button {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
@ -24,6 +24,7 @@ export const appStateModule = {
|
||||
isChangePasswordPopupShown: false,
|
||||
isPaymentSelectionShown: false,
|
||||
isCreateProjectButtonShown: false,
|
||||
isSaveApiKeyModalShown: false,
|
||||
},
|
||||
satelliteName: '',
|
||||
},
|
||||
@ -38,6 +39,11 @@ export const appStateModule = {
|
||||
state.appState.isNewProjectPopupShown = !state.appState.isNewProjectPopupShown;
|
||||
},
|
||||
|
||||
// Mutation changing save api key modal visibility
|
||||
[APP_STATE_MUTATIONS.TOGGLE_SAVE_API_KEY_MODAL](state: any): void {
|
||||
state.appState.isSaveApiKeyModalShown = !state.appState.isSaveApiKeyModalShown;
|
||||
},
|
||||
|
||||
// Mutation changing project dropdown visibility
|
||||
[APP_STATE_MUTATIONS.TOGGLE_PROJECT_DROPDOWN](state: any): void {
|
||||
state.appState.isProjectsDropdownShown = !state.appState.isProjectsDropdownShown;
|
||||
@ -120,6 +126,13 @@ export const appStateModule = {
|
||||
|
||||
commit(APP_STATE_MUTATIONS.TOGGLE_NEW_PROJECT_POPUP);
|
||||
},
|
||||
[APP_STATE_ACTIONS.TOGGLE_SAVE_API_KEY_MODAL]: function ({commit, state}: any): void {
|
||||
if (!state.appState.isSaveApiKeyModalShown) {
|
||||
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
|
||||
}
|
||||
|
||||
commit(APP_STATE_MUTATIONS.TOGGLE_SAVE_API_KEY_MODAL);
|
||||
},
|
||||
[APP_STATE_ACTIONS.TOGGLE_PROJECTS]: function ({commit, state}: any): void {
|
||||
if (!state.appState.isProjectsDropdownShown) {
|
||||
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
|
||||
|
@ -14,6 +14,7 @@ export const APP_STATE_MUTATIONS = {
|
||||
TOGGLE_NEW_PROJECT_POPUP: 'TOGGLE_NEW_PROJECT_POPUP',
|
||||
TOGGLE_PROJECT_DROPDOWN: 'TOGGLE_PROJECT_DROPDOWN',
|
||||
TOGGLE_ACCOUNT_DROPDOWN: 'TOGGLE_ACCOUNT_DROPDOWN',
|
||||
TOGGLE_SAVE_API_KEY_MODAL: 'TOGGLE_SAVE_API_KEY_MODAL',
|
||||
TOGGLE_DELETE_PROJECT_DROPDOWN: 'TOGGLE_DELETE_PROJECT_DROPDOWN',
|
||||
TOGGLE_DELETE_ACCOUNT_DROPDOWN: 'TOGGLE_DELETE_ACCOUNT_DROPDOWN',
|
||||
TOGGLE_SORT_PM_BY_DROPDOWN: 'TOGGLE_SORT_PM_BY_DROPDOWN',
|
||||
|
@ -4,6 +4,7 @@
|
||||
export const APP_STATE_ACTIONS = {
|
||||
TOGGLE_TEAM_MEMBERS: 'toggleAddTeamMembersPopup',
|
||||
TOGGLE_NEW_PROJ : 'toggleNewProjectPopup',
|
||||
TOGGLE_SAVE_API_KEY_MODAL: 'toggleSaveApiKeyModal',
|
||||
TOGGLE_PROJECTS: 'toggleProjectsDropdown',
|
||||
TOGGLE_ACCOUNT: 'toggleAccountDropdown',
|
||||
TOGGLE_DEL_PROJ: 'toggleDeleteProjectPopup',
|
||||
|
@ -0,0 +1,3 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 24C1.15877e-06 10.7452 10.7452 -1.15877e-06 24 0C37.2548 2.09815e-06 48 10.7452 48 24C48 37.2548 37.2548 48 24 48C10.7452 48 -2.09815e-06 37.2548 0 24ZM26.6669 24.0003C26.6669 25.473 25.473 26.6669 24.0003 26.6669C22.5275 26.6669 21.3336 25.473 21.3336 24.0003L21.3336 13.3336C21.3336 11.8609 22.5275 10.6669 24.0003 10.6669C25.473 10.6669 26.6669 11.8609 26.6669 13.3336L26.6669 24.0003ZM24.0003 37.3335C25.473 37.3335 26.6669 36.1396 26.6669 34.6668C26.6669 33.194 25.473 32.0001 24.0003 32.0001C22.5275 32.0001 21.3336 33.194 21.3336 34.6668C21.3336 36.1396 22.5275 37.3335 24.0003 37.3335Z" fill="#F4B000"/>
|
||||
</svg>
|
After Width: | Height: | Size: 771 B |
@ -2,6 +2,7 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import Vuex from 'vuex';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import CreateApiKeyStep from '@/components/onboardingTour/steps/CreateApiKeyStep.vue';
|
||||
|
||||
@ -15,6 +16,7 @@ import { createLocalVue, mount } from '@vue/test-utils';
|
||||
|
||||
import { ApiKeysMock } from '../../mock/api/apiKeys';
|
||||
import { ProjectsApiMock } from '../../mock/api/projects';
|
||||
import {appStateModule} from "@/store/modules/appState";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
const notificationPlugin = new NotificatorPlugin();
|
||||
@ -31,7 +33,7 @@ localVue.use(Vuex);
|
||||
localVue.use(notificationPlugin);
|
||||
localVue.use(segmentioPlugin);
|
||||
|
||||
const store = new Vuex.Store({ modules: { projectsModule, apiKeysModule }});
|
||||
const store = new Vuex.Store({ modules: { projectsModule, apiKeysModule, appStateModule }});
|
||||
|
||||
describe('CreateApiKeyStep.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
@ -58,13 +60,17 @@ describe('CreateApiKeyStep.vue', () => {
|
||||
});
|
||||
|
||||
it('done click works correctly correctly', async (): Promise<void> => {
|
||||
const spy = sinon.spy();
|
||||
const wrapper = mount(CreateApiKeyStep, {
|
||||
store,
|
||||
localVue,
|
||||
methods: {
|
||||
onDoneClick: spy,
|
||||
},
|
||||
});
|
||||
|
||||
await wrapper.find('.done-button').trigger('click');
|
||||
|
||||
expect(wrapper.emitted()).toHaveProperty('setUploadDataState');
|
||||
expect(spy.callCount).toBe(1);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2020 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import SaveApiKeyModal from '@/components/onboardingTour/steps/SaveApiKeyModal.vue';
|
||||
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
describe('SaveApiKeyModal.vue', () => {
|
||||
it('renders correctly', (): void => {
|
||||
const wrapper = mount(SaveApiKeyModal);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -44,6 +44,7 @@ exports[`CreateApiKeyStep.vue create api key works correctly correctly 1`] = `
|
||||
<!---->
|
||||
</div>
|
||||
<div class="done-button container" style="width: 156px; height: 48px;"><span class="label">Done</span></div>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -79,5 +80,6 @@ exports[`CreateApiKeyStep.vue renders correctly 1`] = `
|
||||
<!---->
|
||||
</div>
|
||||
<div class="done-button container disabled" style="width: 156px; height: 48px;"><span class="label">Done</span></div>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
@ -0,0 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SaveApiKeyModal.vue renders correctly 1`] = `
|
||||
<div class="save-api-modal">
|
||||
<div class="save-api-modal__container"><svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 24C1.15877e-06 10.7452 10.7452 -1.15877e-06 24 0C37.2548 2.09815e-06 48 10.7452 48 24C48 37.2548 37.2548 48 24 48C10.7452 48 -2.09815e-06 37.2548 0 24ZM26.6669 24.0003C26.6669 25.473 25.473 26.6669 24.0003 26.6669C22.5275 26.6669 21.3336 25.473 21.3336 24.0003L21.3336 13.3336C21.3336 11.8609 22.5275 10.6669 24.0003 10.6669C25.473 10.6669 26.6669 11.8609 26.6669 13.3336L26.6669 24.0003ZM24.0003 37.3335C25.473 37.3335 26.6669 36.1396 26.6669 34.6668C26.6669 33.194 25.473 32.0001 24.0003 32.0001C22.5275 32.0001 21.3336 33.194 21.3336 34.6668C21.3336 36.1396 22.5275 37.3335 24.0003 37.3335Z" fill="#F4B000"></path>
|
||||
</svg>
|
||||
<h1 class="save-api-modal__container__title">Is Your API Key Saved?</h1>
|
||||
<p class="save-api-modal__container__message">
|
||||
API Keys are only displayed once when generated. If you haven’t saved your key, go back to copy and
|
||||
paste the API key to your preferred method of storing secrets (i.e. TextEdit, Keybase, etc.)
|
||||
</p>
|
||||
<div class="save-api-modal__container__buttons-area">
|
||||
<div class="back-button container blue-white" style="width: 186px; height: 45px;"><span class="label">Go Back</span></div>
|
||||
<div class="container" style="width: 186px; height: 45px;"><span class="label">Yes, it's Saved!</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user