Satellite api keys frontend (#1039)
* api keys frontend * fix linter * fixes, copy to clipboard, disable account activation * activation is removed in https://github.com/storj/storj/pull/1143
This commit is contained in:
parent
7a85c5c1c6
commit
ba07f337c0
3
package-lock.json
generated
Normal file
3
package-lock.json
generated
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
@ -82,7 +82,6 @@ func (s *Service) CreateUser(ctx context.Context, user CreateUser) (u *User, err
|
||||
})
|
||||
|
||||
// TODO: send "finish registration email" when email service will be ready
|
||||
|
||||
//activationToken, err := s.GenerateActivationToken(ctx, u.ID, email, u.CreatedAt.Add(tokenExpirationTime))
|
||||
|
||||
return u, err
|
||||
|
@ -21,6 +21,7 @@
|
||||
"vue": "^2.5.17",
|
||||
"vue-apollo": "^3.0.0-beta.25",
|
||||
"vue-class-component": "^6.0.0",
|
||||
"vue-clipboards": "^1.2.4",
|
||||
"vue-property-decorator": "^7.0.0",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.0.1"
|
||||
|
@ -31,6 +31,10 @@ import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
|
||||
'addTeamMemberPopupButton',
|
||||
'addTeamMemberPopup',
|
||||
'addTeamMemberPopupButtonSVG',
|
||||
'addApiKeyPopup',
|
||||
'addApiKeyPopupButton',
|
||||
'addApiKeysPopupEmptyButton',
|
||||
'addTeamMemberPopupButtonSVG',
|
||||
'sortTeamMemberByDropdown',
|
||||
'sortTeamMemberByDropdownButton',
|
||||
]
|
||||
|
119
web/satellite/src/api/apiKeys.ts
Normal file
119
web/satellite/src/api/apiKeys.ts
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import apollo from '@/utils/apolloManager';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export async function fetchAPIKeys(projectID: string) {
|
||||
let result: RequestResponse<any[]> = {
|
||||
errorMessage: '',
|
||||
isSuccess: false,
|
||||
data: []
|
||||
};
|
||||
|
||||
try {
|
||||
let response: any = await apollo.query({
|
||||
query: gql(
|
||||
`query {
|
||||
project(
|
||||
id: "${projectID}",
|
||||
) {
|
||||
apiKeys {
|
||||
id,
|
||||
name,
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}`
|
||||
),
|
||||
fetchPolicy: 'no-cache'
|
||||
});
|
||||
|
||||
if (response.errors) {
|
||||
result.errorMessage = response.errors[0].message;
|
||||
} else {
|
||||
result.isSuccess = true;
|
||||
result.data = response.data.project.apiKeys;
|
||||
}
|
||||
} catch (e) {
|
||||
result.errorMessage = e.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function createAPIKey(projectID: string, name: string) {
|
||||
let result: RequestResponse<any> = {
|
||||
errorMessage: '',
|
||||
isSuccess: false,
|
||||
data: null
|
||||
};
|
||||
|
||||
try {
|
||||
let response: any = await apollo.mutate({
|
||||
mutation: gql(
|
||||
`mutation {
|
||||
createAPIKey(
|
||||
projectID: "${projectID}",
|
||||
name: "${name}"
|
||||
) {
|
||||
key,
|
||||
keyInfo {
|
||||
id,
|
||||
name,
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}`
|
||||
),
|
||||
fetchPolicy: 'no-cache'
|
||||
});
|
||||
|
||||
if (response.errors) {
|
||||
result.errorMessage = response.errors[0].message;
|
||||
} else {
|
||||
console.log('response', response)
|
||||
result.isSuccess = true;
|
||||
result.data = {
|
||||
key: response.data.createAPIKey.key,
|
||||
keyInfo: response.data.createAPIKey.keyInfo
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
result.errorMessage = e.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function deleteAPIKey(id: string) {
|
||||
let result: RequestResponse<any> = {
|
||||
errorMessage: '',
|
||||
isSuccess: false,
|
||||
data: null
|
||||
};
|
||||
|
||||
try {
|
||||
let response: any = await apollo.mutate({
|
||||
mutation: gql(
|
||||
`mutation {
|
||||
deleteAPIKey(id: "${id}") {
|
||||
id
|
||||
}
|
||||
}`
|
||||
),
|
||||
fetchPolicy: 'no-cache'
|
||||
});
|
||||
|
||||
if (response.errors) {
|
||||
result.errorMessage = response.errors[0].message;
|
||||
} else {
|
||||
result.isSuccess = true;
|
||||
result.data = response.data.deleteAPIKey;
|
||||
}
|
||||
} catch (e) {
|
||||
result.errorMessage = e.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -3,13 +3,14 @@
|
||||
|
||||
<template>
|
||||
<div class="add-api-key-popup-container">
|
||||
<div v-if="true" class="add-api-key-popup">
|
||||
<div id="addApiKeyPopup" v-if="!key" class="add-api-key-popup">
|
||||
<div class="add-api-key-popup__info-panel-container">
|
||||
<div v-html="imageSource"></div>
|
||||
</div>
|
||||
<div class="add-api-key-popup__form-container">
|
||||
<h2 class="add-api-key-popup__form-container__main-label-text">New API Key</h2>
|
||||
<HeaderedInput
|
||||
@setData="onChangeName"
|
||||
label="Name"
|
||||
additionalLabel="Up To 20 Characters"
|
||||
placeholder="Enter API Key Name"
|
||||
@ -17,25 +18,29 @@
|
||||
width="100%" />
|
||||
<div class="add-api-key-popup__form-container__button-container">
|
||||
<Button label="Cancel" width="205px" height="48px" :onPress="onCloseClick" isWhite />
|
||||
<Button label="Create API Key" width="205px" height="48px" />
|
||||
<Button label="Create API Key" width="205px" height="48px" :onPress="onCreateClick" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="add-api-key-popup__close-cross-container">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" v-on:click="onCloseClick">
|
||||
<div class="add-api-key-popup__close-cross-container" v-on:click="onCloseClick">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<CopyApiKeyPopup v-if="false" />
|
||||
<CopyApiKeyPopup :apiKey="key" v-if="key" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import VueClipboards from 'vue-clipboards';
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import CopyApiKeyPopup from './CopyApiKeyPopup.vue';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, API_KEYS_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
Vue.use(VueClipboards);
|
||||
|
||||
@Component(
|
||||
{
|
||||
@ -47,12 +52,27 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
data: function () {
|
||||
return {
|
||||
imageSource: EMPTY_STATE_IMAGES.ADD_API_KEY,
|
||||
name: '',
|
||||
key: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onCloseClick: function (): void {
|
||||
// TODO: save popup states in store
|
||||
this.$emit('onClose');
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_API_KEY);
|
||||
},
|
||||
onCreateClick: async function (): Promise<any> {
|
||||
let result: any = await this.$store.dispatch(API_KEYS_ACTIONS.CREATE, this.$data.name);
|
||||
|
||||
if (!result.isSuccess) {
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, result.errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, "Successfully created new api key");
|
||||
this.$data.key = result.data.key;
|
||||
},
|
||||
onChangeName: function (value: string): void {
|
||||
this.$data.name = value;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
@ -3,24 +3,28 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="apiKeyItems" class="api-keys-header">
|
||||
<div v-if="!isEmpty" class="api-keys-header">
|
||||
<HeaderArea/>
|
||||
</div>
|
||||
<div v-if="apiKeyItems" class="api-keys-container">
|
||||
<div v-if="!isEmpty" class="api-keys-container">
|
||||
<div class="api-keys-container__content">
|
||||
<ApiKeysItem class="selected"/>
|
||||
<ApiKeysItem />
|
||||
<ApiKeysItem />
|
||||
<div v-for="apiKey in apiKeys" v-on:click="toggleSelection(apiKey.id)">
|
||||
<ApiKeysItem
|
||||
v-bind:class="[apiKey.isSelected ? 'selected': null]"
|
||||
:apiKey="apiKey" />
|
||||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
<Footer v-if="isSelected"/>
|
||||
</div>
|
||||
<EmptyState
|
||||
v-if="!apiKeyItems"
|
||||
:onButtonClick="togglePopup"
|
||||
v-if="isEmpty"
|
||||
mainTitle="You have no API Keys yet"
|
||||
additional-text="<p>We recommend you to create your first API Key for this project. API Keys allow developers to manage their project and build applications over Storj Network through our Uplink CLI.</p>"
|
||||
:imageSource="emptyImage"
|
||||
buttonLabel="New Api Key"
|
||||
isButtonShown />
|
||||
<AddAPIKeyPopup v-if="isPopupShown"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -30,23 +34,45 @@ import EmptyState from '@/components/common/EmptyStateArea.vue';
|
||||
import HeaderArea from '@/components/apiKeys/headerArea/HeaderArea.vue';
|
||||
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
import ApiKeysItem from '@/components/apiKeys/ApiKeysItem.vue';
|
||||
import AddAPIKeyPopup from '@/components/apiKeys/AddApiKeyPopup.vue';
|
||||
import Footer from '@/components/apiKeys/footerArea/Footer.vue';
|
||||
import { API_KEYS_ACTIONS, APP_STATE_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
@Component({
|
||||
data: function () {
|
||||
return {
|
||||
emptyImage: EMPTY_STATE_IMAGES.API_KEY,
|
||||
apiKeyItems: true,
|
||||
};
|
||||
},
|
||||
methods: {},
|
||||
computed: {},
|
||||
methods: {
|
||||
toggleSelection: function(id: string): void {
|
||||
this.$store.dispatch(API_KEYS_ACTIONS.TOGGLE_SELECTION, id);
|
||||
},
|
||||
togglePopup: function (): void {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_API_KEY);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
apiKeys: function (): any {
|
||||
return this.$store.state.apiKeysModule.apiKeys;
|
||||
},
|
||||
isEmpty: function (): boolean {
|
||||
return this.$store.state.apiKeysModule.apiKeys.length === 0;
|
||||
},
|
||||
isSelected: function (): boolean {
|
||||
return this.$store.getters.selectedAPIKeys.length > 0;
|
||||
},
|
||||
isPopupShown: function (): boolean {
|
||||
return this.$store.state.appStateModule.appState.isNewAPIKeyPopupShown;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
EmptyState,
|
||||
HeaderArea,
|
||||
ApiKeysItem,
|
||||
AddAPIKeyPopup,
|
||||
Footer
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
export default class ApiKeysArea extends Vue {
|
||||
|
@ -11,8 +11,8 @@
|
||||
<path d="M10.7756 14.334C10.4108 14.334 10.1226 14.6283 10.1226 15.0007C10.1226 15.3731 10.4108 15.6673 10.7756 15.6673C11.1404 15.6673 11.4287 15.3731 11.4287 15.0007C11.4287 14.6283 11.1404 14.334 10.7756 14.334Z" fill="#2683FF"/>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="apikey-item-container__name">test</p>
|
||||
<p class="apikey-item-container__date">date</p>
|
||||
<p class="apikey-item-container__name">{{ apiKey.name }}</p>
|
||||
<p class="apikey-item-container__date">{{ new Date(apiKey.createdAt).toLocaleDateString() }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -21,7 +21,9 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
@Component(
|
||||
{
|
||||
|
||||
props: {
|
||||
apiKey: Object,
|
||||
}
|
||||
}
|
||||
)
|
||||
export default class ApiKeysItem extends Vue {}
|
||||
|
@ -2,15 +2,15 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div id="addApiKeyPopup">
|
||||
<div class="save-api-popup" v-if="true">
|
||||
<div class="save-api-popup__content">
|
||||
<h1 class="save-api-popup__content__title">Save you API Key or download it in .txt file.</h1>
|
||||
<p class="save-api-popup__content__name">You will need this to share access to the project with your team members.</p>
|
||||
<div class="save-api-popup__content__copy-area">
|
||||
<p class="save-api-popup__content__copy-area__save-api">ab4923re124NSVDLkvdmsfv mwm45678gnhab4923rewm45678gn</p>
|
||||
<Button class="save-api-popup__content__copy-area__save-btn" label="Copy" width="140px" height="48px" />
|
||||
<Button label="Download" width="140px" height="48px" isWhite/>
|
||||
<p class="save-api-popup__content__copy-area__save-api">{{apiKey}}</p>
|
||||
<Button class="save-api-popup__content__copy-area__save-btn" v-clipboard="apiKey" label="Copy" width="140px" height="48px" :onPress="onCopyClick" />
|
||||
<!--<Button label="Download" width="140px" height="48px" isWhite/>-->
|
||||
</div>
|
||||
<div class="save-api-popup__content__info-area">
|
||||
<img src="../../../static/images/register/ErrorInfo.svg"/>
|
||||
@ -54,6 +54,7 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
@Component(
|
||||
{
|
||||
@ -61,6 +62,7 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
onClose: {
|
||||
type: Function
|
||||
},
|
||||
apiKey: String
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
@ -69,9 +71,12 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
|
||||
},
|
||||
methods: {
|
||||
onCloseClick: function (): void {
|
||||
// TODO: save popup states in store
|
||||
this.$emit('onClose');
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_API_KEY);
|
||||
},
|
||||
onCopyClick: function (): void {
|
||||
//TODO: save to clipboardt
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, "Key saved to clipboard");
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Button,
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="delete-api-key-container__wrap">
|
||||
<div class="delete-api-key-container__selected-api-keys-count">
|
||||
<span class="delete-api-key-container__selected-api-keys-count__button"></span>
|
||||
<p class="delete-api-key-container__selected-api-keys-count__count">1</p>
|
||||
<p class="delete-api-key-container__selected-api-keys-count__count">{{ count }}</p>
|
||||
<p class="delete-api-key-container__selected-api-keys-count__total-count"> of <span>X</span> API Keys Selected</p>
|
||||
</div>
|
||||
<div class="delete-api-key-container__buttons-group">
|
||||
@ -30,19 +30,25 @@
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import { API_KEYS_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
@Component({
|
||||
methods: {
|
||||
onDelete: async function () {
|
||||
let selectedKeys: any[] = this.$store.getters.selectedAPIKeys;
|
||||
|
||||
},
|
||||
onClearSelection: function () {
|
||||
|
||||
for (let i = 0; i < selectedKeys.length; i++) {
|
||||
this.$store.dispatch(API_KEYS_ACTIONS.DELETE, selectedKeys[i].id);
|
||||
}
|
||||
|
||||
},
|
||||
onClearSelection: function (): void {
|
||||
this.$store.dispatch(API_KEYS_ACTIONS.CLEAR_SELECTION);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
count: function (): number {
|
||||
return this.$store.getters.selectedAPIKeys.length;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Button
|
||||
|
@ -5,12 +5,13 @@
|
||||
<div class="api-keys-header-container">
|
||||
<div class="api-keys-header-container__item">
|
||||
<SearchArea />
|
||||
<Button label="New API Key" width="240px" height="54px" :onPress="toggleSelection" />
|
||||
<div id="addApiKeyPopupButton">
|
||||
<Button label="New API Key" width="240px" height="54px" :onPress="togglePopup" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="api-keys-header-container__item">
|
||||
<!-- <SortApiKeysHeader /> -->
|
||||
</div>
|
||||
<AddApiKeyPopup v-if="isPopupShown" @onClose="toggleSelection" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -19,25 +20,19 @@ import { Component, Vue } from 'vue-property-decorator';
|
||||
import SearchArea from './SearchArea.vue';
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import SortApiKeysHeader from '@/components/apiKeys/headerArea/SortApiKeysHeader.vue';
|
||||
import AddApiKeyPopup from '@/components/apiKeys/AddApiKeyPopup.vue';
|
||||
import { APP_STATE_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
@Component({
|
||||
data: function() {
|
||||
return {
|
||||
isPopupShown: false,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
SearchArea,
|
||||
Button,
|
||||
SortApiKeysHeader,
|
||||
AddApiKeyPopup,
|
||||
},
|
||||
methods: {
|
||||
toggleSelection: function () {
|
||||
this.$data.isPopupShown = !this.$data.isPopupShown;
|
||||
}
|
||||
}
|
||||
togglePopup: function () {
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_API_KEY);
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default class HeaderArea extends Vue {
|
||||
|
@ -5,13 +5,14 @@
|
||||
<div class="empty-state">
|
||||
<div class="empty-state__wrap">
|
||||
<h1>{{mainTitle}}</h1>
|
||||
<!--<p>{{additionalText}}</p>-->
|
||||
<div class="empty-state__wrap__additional-text" v-html="additionalText"/>
|
||||
<div id="addApiKeysPopupEmptyButton">
|
||||
<Button
|
||||
v-if="isButtonShown"
|
||||
@onPress="onButtonClick"
|
||||
:onPress="onButtonClick"
|
||||
:label="buttonLabel"
|
||||
width="170px" />
|
||||
</div>
|
||||
<div class="empty-state__wrap__img" v-html="imageSource"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,6 +60,8 @@ export default class EmptyStateProjectArea extends Vue {
|
||||
&__additional-text {
|
||||
font-family: 'montserrat_regular';
|
||||
font-size: 16px;
|
||||
width: 50%;
|
||||
margin-bottom: 10px;
|
||||
|
||||
b {
|
||||
font-family: 'montserrat_bold' !important;
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { APP_STATE_ACTIONS, PROJETS_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||
import { APP_STATE_ACTIONS, PROJETS_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS, API_KEYS_ACTIONS } from '@/utils/constants/actionNames';
|
||||
|
||||
@Component(
|
||||
{
|
||||
@ -33,16 +33,19 @@ import { APP_STATE_ACTIONS, PROJETS_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS }
|
||||
onProjectSelected: async function (projectID: string): Promise<void> {
|
||||
this.$store.dispatch(PROJETS_ACTIONS.SELECT, projectID);
|
||||
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_PROJECTS);
|
||||
|
||||
if (!this.$store.getters.selectedProject.id) return;
|
||||
|
||||
this.$store.dispatch(PM_ACTIONS.SET_SEARCH_QUERY, '');
|
||||
|
||||
const response = await this.$store.dispatch(PM_ACTIONS.FETCH);
|
||||
if (response.isSuccess) return;
|
||||
const pmResponse = await this.$store.dispatch(PM_ACTIONS.FETCH, {limit: 20, offset: 0});
|
||||
const keysResponse = await this.$store.dispatch(API_KEYS_ACTIONS.FETCH);
|
||||
|
||||
if (!pmResponse.isSuccess) {
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to fetch project members');
|
||||
}
|
||||
|
||||
if (!keysResponse.isSuccess) {
|
||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to fetch api keys');
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ import { projectsModule } from '@/store/modules/projects';
|
||||
import { projectMembersModule } from '@/store/modules/projectMembers';
|
||||
import { notificationsModule } from '@/store/modules/notifications';
|
||||
import { appStateModule } from '@/store/modules/appState';
|
||||
import { apiKeysModule } from '@/store/modules/apiKeys';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
@ -21,6 +22,7 @@ const store = new Vuex.Store({
|
||||
projectMembersModule,
|
||||
notificationsModule,
|
||||
appStateModule,
|
||||
apiKeysModule
|
||||
}
|
||||
});
|
||||
|
||||
|
98
web/satellite/src/store/modules/apiKeys.ts
Normal file
98
web/satellite/src/store/modules/apiKeys.ts
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { API_KEYS_MUTATIONS } from '../mutationConstants';
|
||||
import { createAPIKey, deleteAPIKey, fetchAPIKeys } from "@/api/apiKeys";
|
||||
import { API_KEYS_ACTIONS } from "@/utils/constants/actionNames";
|
||||
|
||||
export const apiKeysModule = {
|
||||
state: {
|
||||
apiKeys: [],
|
||||
},
|
||||
mutations: {
|
||||
[API_KEYS_MUTATIONS.FETCH](state: any, apiKeys: any[]) {
|
||||
state.apiKeys = apiKeys;
|
||||
},
|
||||
[API_KEYS_MUTATIONS.ADD](state: any, apiKey: any) {
|
||||
state.apiKeys.push(apiKey);
|
||||
},
|
||||
[API_KEYS_MUTATIONS.DELETE](state: any, id: string) {
|
||||
state.apiKeys = state.apiKeys.filter((key => key.id !== id))
|
||||
},
|
||||
[API_KEYS_MUTATIONS.TOGGLE_SELECTION](state: any, apiKeyID: string) {
|
||||
state.apiKeys = state.apiKeys.map((apiKey: any) => {
|
||||
if (apiKey.id === apiKeyID) {
|
||||
apiKey.isSelected = !apiKey.isSelected;
|
||||
}
|
||||
|
||||
return apiKey;
|
||||
});
|
||||
},
|
||||
[API_KEYS_MUTATIONS.CLEAR_SELECTION](state: any) {
|
||||
state.apiKeys = state.apiKeys.map((apiKey: any) => {
|
||||
apiKey.isSelected = false;
|
||||
|
||||
return apiKey;
|
||||
});
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
[API_KEYS_ACTIONS.FETCH]: async function ({commit, rootGetters}): Promise<RequestResponse<any>> {
|
||||
const projectId = rootGetters.selectedProject.id;
|
||||
|
||||
let fetchResult = await fetchAPIKeys(projectId);
|
||||
|
||||
if (fetchResult.isSuccess) {
|
||||
commit(API_KEYS_MUTATIONS.FETCH, fetchResult.data);
|
||||
}
|
||||
|
||||
return fetchResult;
|
||||
},
|
||||
[API_KEYS_ACTIONS.CREATE]: async function ({commit, rootGetters}: any, name: string): Promise<RequestResponse<any>> {
|
||||
const projectId = rootGetters.selectedProject.id;
|
||||
|
||||
let result = await createAPIKey(projectId, name);
|
||||
console.log(result);
|
||||
|
||||
if (result.isSuccess) {
|
||||
commit(API_KEYS_MUTATIONS.ADD, result.data.keyInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
[API_KEYS_ACTIONS.DELETE]: async function({commit}: any, id: string): Promise<RequestResponse<any>> {
|
||||
let result = await deleteAPIKey(id);
|
||||
|
||||
if (result.isSuccess) {
|
||||
commit(API_KEYS_MUTATIONS.DELETE, result.data.id);
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
|
||||
return result;
|
||||
},
|
||||
[API_KEYS_ACTIONS.TOGGLE_SELECTION]: function({commit}, apiKeyID: string): void {
|
||||
commit(API_KEYS_MUTATIONS.TOGGLE_SELECTION, apiKeyID);
|
||||
},
|
||||
[API_KEYS_ACTIONS.CLEAR_SELECTION]: function({commit}): void {
|
||||
commit(API_KEYS_MUTATIONS.CLEAR_SELECTION);
|
||||
},
|
||||
[API_KEYS_ACTIONS.CLEAR]: function ({commit}): void {
|
||||
commit(API_KEYS_MUTATIONS.FETCH, []);
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
selectedAPIKeys: function (state: any): any[] {
|
||||
let keys: any[] = state.apiKeys;
|
||||
let selectedKeys: any[] = [];
|
||||
|
||||
for (let i = 0; i < keys.length; i++ ) {
|
||||
if (keys[i].isSelected) {
|
||||
selectedKeys.push(keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return selectedKeys;
|
||||
}
|
||||
},
|
||||
};
|
@ -2,6 +2,7 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { APP_STATE_MUTATIONS } from '../mutationConstants';
|
||||
import {APP_STATE_ACTIONS} from "@/utils/constants/actionNames";
|
||||
|
||||
export const appStateModule = {
|
||||
state: {
|
||||
@ -13,6 +14,7 @@ export const appStateModule = {
|
||||
isAccountDropdownShown: false,
|
||||
isDeleteProjectPopupShown: false,
|
||||
isDeleteAccountPopupShown: false,
|
||||
isNewAPIKeyPopupShown: false,
|
||||
isSortProjectMembersByPopupShown: false,
|
||||
},
|
||||
},
|
||||
@ -41,7 +43,6 @@ export const appStateModule = {
|
||||
[APP_STATE_MUTATIONS.TOGGLE_DELETE_PROJECT_DROPDOWN](state: any): void {
|
||||
state.appState.isDeleteProjectPopupShown = !state.appState.isDeleteProjectPopupShown;
|
||||
},
|
||||
|
||||
// Mutation changing delete account popup visibility
|
||||
[APP_STATE_MUTATIONS.TOGGLE_DELETE_ACCOUNT_DROPDOWN](state: any): void {
|
||||
state.appState.isDeleteAccountPopupShown = !state.appState.isDeleteAccountPopupShown;
|
||||
@ -50,6 +51,10 @@ export const appStateModule = {
|
||||
[APP_STATE_MUTATIONS.TOGGLE_SORT_PM_BY_DROPDOWN](state: any): void {
|
||||
state.appState.isSortProjectMembersByPopupShown = !state.appState.isSortProjectMembersByPopupShown;
|
||||
},
|
||||
// Mutation changing new api key popup visibility
|
||||
[APP_STATE_MUTATIONS.TOGGLE_NEW_API_KEY_POPUP](state: any): void {
|
||||
state.appState.isNewAPIKeyPopupShown = !state.appState.isNewAPIKeyPopupShown;
|
||||
},
|
||||
|
||||
// Mutation that closes each popup/dropdown
|
||||
[APP_STATE_MUTATIONS.CLOSE_ALL](state: any): void {
|
||||
@ -60,6 +65,7 @@ export const appStateModule = {
|
||||
state.appState.isDeleteProjectPopupShown = false;
|
||||
state.appState.isDeleteAccountPopupShown = false;
|
||||
state.appState.isSortProjectMembersByPopupShown = false;
|
||||
state.appState.isNewAPIKeyPopupShown = false;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
@ -113,6 +119,13 @@ export const appStateModule = {
|
||||
|
||||
commit(APP_STATE_MUTATIONS.TOGGLE_SORT_PM_BY_DROPDOWN);
|
||||
},
|
||||
[APP_STATE_ACTIONS.TOGGLE_NEW_API_KEY]: function ({commit, state}: any): void {
|
||||
if (!state.appState.isNewAPIKeyPopupShown) {
|
||||
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
|
||||
}
|
||||
|
||||
commit(APP_STATE_MUTATIONS.TOGGLE_NEW_API_KEY_POPUP);
|
||||
},
|
||||
closePopups: function ({commit}: any): void {
|
||||
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
|
||||
},
|
||||
|
@ -30,6 +30,15 @@ export const PROJECT_MEMBER_MUTATIONS = {
|
||||
ADD_OFFSET:'ADD_OFFSET',
|
||||
};
|
||||
|
||||
export const API_KEYS_MUTATIONS = {
|
||||
FETCH: 'FETCH_API_KEYS',
|
||||
ADD: 'ADD_API_KEY',
|
||||
DELETE: 'DELETE_API_KEY',
|
||||
TOGGLE_SELECTION: "TOGGLE_SELECTION",
|
||||
CLEAR_SELECTION: "CLEAR_SELECTION",
|
||||
CLEAR: 'CLEAR_API_KEYS',
|
||||
}
|
||||
|
||||
export const NOTIFICATION_MUTATIONS = {
|
||||
ADD: 'ADD_NOTIFICATION',
|
||||
DELETE: 'DELETE_NOTIFICATION',
|
||||
@ -45,5 +54,6 @@ export const APP_STATE_MUTATIONS = {
|
||||
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',
|
||||
TOGGLE_NEW_API_KEY_POPUP: "TOGGLE_NEW_API_KEY_POPUP",
|
||||
CLOSE_ALL: 'CLOSE_ALL',
|
||||
};
|
||||
|
@ -3,11 +3,12 @@
|
||||
|
||||
export const APP_STATE_ACTIONS = {
|
||||
TOGGLE_TEAM_MEMBERS: 'toggleAddTeamMembersPopup',
|
||||
TOGGLE_NEW_PROJ: 'toggleNewProjectPopup',
|
||||
TOGGLE_NEW_PROJ : 'toggleNewProjectPopup',
|
||||
TOGGLE_PROJECTS: 'toggleProjectsDropdown',
|
||||
TOGGLE_ACCOUNT: 'toggleAccountDropdown',
|
||||
TOGGLE_DEL_PROJ: 'toggleDeleteProjectPopup',
|
||||
TOGGLE_DEL_ACCOUNT: 'toggleDeleteAccountPopup',
|
||||
TOGGLE_NEW_API_KEY: "toggleNewAPIKeyPopup",
|
||||
TOGGLE_SORT_PM_BY_DROPDOWN: 'toggleSortProjectMembersByPopup',
|
||||
CLOSE_POPUPS: 'closePopups',
|
||||
};
|
||||
@ -49,3 +50,12 @@ export const USER_ACTIONS = {
|
||||
GET: 'getUser',
|
||||
CLEAR: 'clearUser',
|
||||
};
|
||||
|
||||
export const API_KEYS_ACTIONS = {
|
||||
FETCH: 'fetchAPIKeys',
|
||||
CREATE: 'createAPIKey',
|
||||
DELETE: 'deleteAPIKey',
|
||||
CLEAR: 'clearAPIKeys',
|
||||
TOGGLE_SELECTION: 'toggleAPIKeySelection',
|
||||
CLEAR_SELECTION: 'clearAPIKeySelection'
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user