User account settings (#738)
* User account settings. * Change basic user info. * Change company info. * Change password. * Delete user account
This commit is contained in:
parent
3e461df470
commit
6b68b0c368
204
web/satellite/src/api/users.ts
Normal file
204
web/satellite/src/api/users.ts
Normal file
@ -0,0 +1,204 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import apolloManager from "../utils/apolloManager";
|
||||
import gql from "graphql-tag";
|
||||
|
||||
// Performs update user info graphQL mutation request.
|
||||
// Returns User object if succeed, null otherwise
|
||||
export async function updateBasicUserInfo(user: User) {
|
||||
let response = await apolloManager.mutate(
|
||||
{
|
||||
mutation: gql(`
|
||||
mutation {
|
||||
updateUser (
|
||||
id: "${user.id}",
|
||||
input: {
|
||||
email: "${user.email}",
|
||||
firstName: "${user.firstName}",
|
||||
lastName: "${user.lastName}"
|
||||
}
|
||||
) {
|
||||
email,
|
||||
firstName,
|
||||
lastName
|
||||
}
|
||||
}
|
||||
`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Performs update company info graphQL mutation request.
|
||||
// Returns Company object if succeed, null otherwise
|
||||
export async function updateCompanyInfo(userId: string, company: Company) {
|
||||
let response = await apolloManager.mutate(
|
||||
{
|
||||
mutation:gql(`
|
||||
mutation {
|
||||
updateCompany(
|
||||
userID:"${userId}",
|
||||
input:{
|
||||
name:"${company.name}",
|
||||
address:"${company.address}",
|
||||
country:"${company.country}",
|
||||
city:"${company.city}",
|
||||
state:"${company.state}",
|
||||
postalCode:"${company.postalCode}"
|
||||
}
|
||||
){
|
||||
name,
|
||||
address,
|
||||
country,
|
||||
city,
|
||||
state,
|
||||
postalCode
|
||||
}
|
||||
}
|
||||
`)
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Performs change password graphQL mutation
|
||||
// Returns base user fields
|
||||
export async function updatePassword(userId: string, password: string) {
|
||||
let response = await apolloManager.mutate(
|
||||
{
|
||||
mutation: gql(`
|
||||
mutation {
|
||||
updateUser (
|
||||
id: "${userId}",
|
||||
input: {
|
||||
password: "${password}"
|
||||
}
|
||||
) {
|
||||
email,
|
||||
firstName,
|
||||
lastName
|
||||
}
|
||||
}
|
||||
`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Performs Create user graqhQL request.
|
||||
// Throws an exception if error occurs
|
||||
// Returns object with newly created user
|
||||
export async function createUser(user: User, password: string): Promise<any> {
|
||||
let response = await apolloManager.mutate(
|
||||
{
|
||||
mutation: gql(`
|
||||
mutation {
|
||||
createUser(
|
||||
input:{
|
||||
email: "${user.email}",
|
||||
password: "${password}",
|
||||
firstName: "${user.firstName}",
|
||||
lastName: "${user.lastName}",
|
||||
company: {
|
||||
name: "${user.company.name}",
|
||||
address: "${user.company.address}",
|
||||
country: "${user.company.country}",
|
||||
city: "${user.company.city}",
|
||||
state: "${user.company.state}",
|
||||
postalCode: "${user.company.postalCode}"
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
// Performs graqhQL request.
|
||||
// Returns Token, User objects.
|
||||
// Throws an exception if error occurs
|
||||
export async function login(email: string, password: string): Promise<any> {
|
||||
let response = await apolloManager.query(
|
||||
{
|
||||
query: gql(`
|
||||
query {
|
||||
token(email: "${email}",
|
||||
password: "${password}") {
|
||||
token,
|
||||
user{
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
company{
|
||||
name,
|
||||
address,
|
||||
country,
|
||||
city,
|
||||
state,
|
||||
postalCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Performs graqhQL request.
|
||||
// User object.
|
||||
// Throws an exception if error occurs
|
||||
export async function deleteUserAccount(userId: string): Promise<any> {
|
||||
let response = await apolloManager.mutate(
|
||||
{
|
||||
mutation: gql(`
|
||||
mutation {
|
||||
deleteUser(id: "${userId}") {
|
||||
id
|
||||
}
|
||||
}
|
||||
`),
|
||||
fetchPolicy: "no-cache"
|
||||
}
|
||||
);
|
||||
|
||||
if(!response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
@ -14,133 +14,160 @@
|
||||
<h4>Optional</h4>
|
||||
</div>
|
||||
<textarea
|
||||
v-if="isMultiline"
|
||||
:id="this.$props.label"
|
||||
:placeholder="this.$props.placeholder"
|
||||
v-model="value"
|
||||
:style="style"
|
||||
:rows="5"
|
||||
:cols="40"
|
||||
wrap="hard"
|
||||
@input="onInput" >
|
||||
v-if="isMultiline"
|
||||
:id="this.$props.label"
|
||||
:placeholder="this.$props.placeholder"
|
||||
:style="style"
|
||||
:rows="5"
|
||||
:cols="40"
|
||||
wrap="hard"
|
||||
v-model.lazy="value"
|
||||
@input="onInput">
|
||||
</textarea>
|
||||
<input
|
||||
v-if="!isMultiline"
|
||||
@input="onInput"
|
||||
:id="this.$props.label"
|
||||
:placeholder="this.$props.placeholder"
|
||||
v-model="value"
|
||||
v-bind:type="[isPassword ? passwordType : textType]"
|
||||
:style="style" />
|
||||
</div>
|
||||
<input
|
||||
v-if="!isMultiline"
|
||||
:id="this.$props.label"
|
||||
:placeholder="this.$props.placeholder"
|
||||
v-bind:type="[isPassword ? 'password': 'text']"
|
||||
v-model.lazy="value"
|
||||
@change="onInput"
|
||||
@input="onInput"
|
||||
:style="style"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
// Custom input component with labeled header
|
||||
@Component(
|
||||
{
|
||||
data: () => {
|
||||
return {
|
||||
value: "",
|
||||
textType: "text",
|
||||
passwordType: "password"
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//emits data to parent component
|
||||
onInput () {
|
||||
this.$emit('setData', this.$data.value)
|
||||
}
|
||||
},
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
additionalLabel: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
error: {
|
||||
type: String
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "default"
|
||||
},
|
||||
isOptional: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isMultiline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isPassword: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: "48px"
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: "100%"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
style: function() {
|
||||
return { width: this.$props.width, height: this.$props.height }
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
export default class HeaderedInput extends Vue { }
|
||||
// Custom input component with labeled header
|
||||
@Component(
|
||||
{
|
||||
data: function() {
|
||||
return {
|
||||
value: this.$props.initValue ? this.$props.initValue : "",
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//emits data to parent component
|
||||
onInput () {
|
||||
this.$emit('setData', this.$data.value)
|
||||
},
|
||||
setValue(value: string) {
|
||||
this.$data.value = value
|
||||
}
|
||||
},
|
||||
props: {
|
||||
initValue: {
|
||||
type: String,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
additionalLabel: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
error: {
|
||||
type: String
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "default"
|
||||
},
|
||||
isOptional: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isMultiline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isPassword: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: "48px"
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: "100%"
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
style: function() {
|
||||
return { width: this.$props.width, height: this.$props.height }
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
export default class HeaderedInput extends Vue { }
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-top: 10px;
|
||||
width: 48%;
|
||||
}
|
||||
.label-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-top: 10px;
|
||||
width: 48%;
|
||||
}
|
||||
.label-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
|
||||
&__add-label {
|
||||
margin-left: 5px;
|
||||
&__add-label {
|
||||
margin-left: 5px;
|
||||
font-family: 'montserrat_regular';
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: rgba(56, 75, 101, 0.4);
|
||||
}
|
||||
|
||||
&__error {
|
||||
color: #FF5560;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.optional-label-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
h4 {
|
||||
font-family: 'montserrat_regular';
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #AFB7C1;
|
||||
}
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
font-family: 'montserrat_regular';
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: rgba(56, 75, 101, 0.4);
|
||||
resize: none;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
text-indent: 20px;
|
||||
border-color: rgba(56, 75, 101, 0.4);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
&__error {
|
||||
color: #FF5560;
|
||||
margin-left: 10px;
|
||||
textarea {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
.optional-label-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
h4 {
|
||||
h3 {
|
||||
font-family: 'montserrat_regular';
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
color: #AFB7C1;
|
||||
color: #354049;
|
||||
}
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
font-family: 'montserrat_regular';
|
||||
|
@ -3,45 +3,54 @@
|
||||
|
||||
<template>
|
||||
<div class="account-area-container">
|
||||
<!-- TODO: Get info for this area placeholders from store -->
|
||||
<!-- TODO: change isDisabled for save buttons for each area when data imputed -->
|
||||
<!--start of Account settings area -->
|
||||
<div class="account-area-settings-container">
|
||||
<h1>Account Settings</h1>
|
||||
<h2>This information will be visible to all users</h2>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
label="First name"
|
||||
placeholder ="Enter First Name"
|
||||
<HeaderedInput
|
||||
label="First name"
|
||||
placeholder ="Enter First Name"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
<HeaderedInput
|
||||
label="Last Name"
|
||||
ref="firstNameInput"
|
||||
:error="firstNameError"
|
||||
:init-value="originalFirstName"
|
||||
@setData="setFirstName" />
|
||||
<HeaderedInput
|
||||
label="Last Name"
|
||||
placeholder="LastNameEdit"
|
||||
width="100%"
|
||||
placeholder ="Enter Last Name"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="lastNameInput"
|
||||
:error="lastNameError"
|
||||
:initValue="originalLastName"
|
||||
@setData="setLastName"/>
|
||||
</div>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
class="full-input"
|
||||
label="Email"
|
||||
placeholder ="Enter Email"
|
||||
placeholder ="Enter Email"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="emailInput"
|
||||
:error="emailError"
|
||||
:initValue="originalEmail"
|
||||
@setData="setEmail" />
|
||||
</div>
|
||||
<div class="account-area-save-button-area">
|
||||
<!-- v-if we are editing this area -->
|
||||
<div v-if="isAccountSettingsEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__terms-area">
|
||||
<Checkbox class="checkbox" @setData="setTermsAccepted"/>
|
||||
<Checkbox class="checkbox"
|
||||
@setData="setTermsAccepted"
|
||||
:isCheckboxError="isTermsAcceptedError"/>
|
||||
<h2>I agree to the Storj Bridge Hosting <a>Terms & Conditions</a></h2>
|
||||
</div>
|
||||
<!-- v-if are editing this area -->
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancel" isWhite/>
|
||||
<Button class="account-area-save-button-area__save-button" label="Save" width="140px" height="50px" :onPress="onSave" isDisabled/>
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancelAccountSettingsButtonClick" isWhite/>
|
||||
<Button class="account-area-save-button-area__save-button" label="Save" width="140px" height="50px" :onPress="onSaveAccountSettingsButtonClick"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isAccountSettingsEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<Button class="account-area-save-button-area__save-button" label="Save" width="140px" height="50px" :onPress="onSaveAccountSettingsButtonClick" isDisabled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -53,54 +62,64 @@
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
class="full-input"
|
||||
label="Company Name"
|
||||
placeholder ="Enter Company Name"
|
||||
label="Company Name"
|
||||
placeholder ="Enter Company Name"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="companyNameInput"
|
||||
:initValue="originalCompanyName"
|
||||
@setData="setCompanyName" />
|
||||
</div>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
class="full-input"
|
||||
label="Company Address"
|
||||
placeholder ="Enter Company Address"
|
||||
label="Company Address"
|
||||
placeholder ="Enter Company Address"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="companyAddressInput"
|
||||
:initValue="originalCompanyAddress"
|
||||
@setData="setCompanyAddress" />
|
||||
</div>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
label="Country"
|
||||
placeholder ="Enter Country"
|
||||
<HeaderedInput
|
||||
label="Country"
|
||||
placeholder ="Enter Country"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
<HeaderedInput
|
||||
label="City"
|
||||
placeholder ="Enter City"
|
||||
ref="companyCountryInput"
|
||||
:initValue="originalCompanyCountry"
|
||||
@setData="setCompanyCountry" />
|
||||
<HeaderedInput
|
||||
label="City"
|
||||
placeholder ="Enter City"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="companyCityInput"
|
||||
:initValue="originalCompanyCity"
|
||||
@setData="setCompanyCity" />
|
||||
</div>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
label="State"
|
||||
placeholder ="Enter State"
|
||||
<HeaderedInput
|
||||
label="State"
|
||||
placeholder ="Enter State"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
<HeaderedInput
|
||||
label="Postal Code"
|
||||
placeholder ="Enter Postal Code"
|
||||
ref="companyStateInput"
|
||||
:initValue="originalCompanyState"
|
||||
@setData="setCompanyState" />
|
||||
<HeaderedInput
|
||||
label="Postal Code"
|
||||
placeholder ="Enter Postal Code"
|
||||
width="100%"
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
ref="companyPostalCodeInput"
|
||||
:initValue="originalCompanyPostalCode"
|
||||
@setData="setCompanyPostalCode" />
|
||||
</div>
|
||||
<div class="account-area-save-button-area">
|
||||
<div v-if="isCompanyEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<!-- v-if we are editing this area -->
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancel" isWhite/>
|
||||
<Button label="Save" width="140px" height="50px" :onPress="onSave" isWhite isDisabled/>
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancelCompanyButtonClick" isWhite/>
|
||||
<Button label="Save" width="140px" height="50px" :onPress="onSaveCompanySettingsButtonClick"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isCompanyEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<Button label="Save" width="140px" height="50px" :onPress="onSaveCompanySettingsButtonClick" isWhite isDisabled/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -110,42 +129,49 @@
|
||||
<h1>Change Password</h1>
|
||||
<h2>Please choose a password which is longer than 6 characters.</h2>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
label="Old Password"
|
||||
placeholder ="Enter Old Password"
|
||||
<HeaderedInput
|
||||
label="Old Password"
|
||||
placeholder ="Enter Old Password"
|
||||
width="100%"
|
||||
isPassword
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
<HeaderedInput
|
||||
label="New Password"
|
||||
placeholder ="Enter New Password"
|
||||
ref="oldPasswordInput"
|
||||
:error="oldPasswordError"
|
||||
@setData="setOldPassword" />
|
||||
<HeaderedInput
|
||||
label="New Password"
|
||||
placeholder ="Enter New Password"
|
||||
width="100%"
|
||||
ref="newPasswordInput"
|
||||
isPassword
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
:error="newPasswordError"
|
||||
@setData="setNewPassword" />
|
||||
</div>
|
||||
<div class="account-area-row-container">
|
||||
<HeaderedInput
|
||||
<HeaderedInput
|
||||
class="full-input"
|
||||
label="Confirm password"
|
||||
placeholder ="Confirm password"
|
||||
label="Confirm password"
|
||||
placeholder ="Confirm password"
|
||||
width="100%"
|
||||
ref="confirmationPasswordInput"
|
||||
isPassword
|
||||
:error="inputError"
|
||||
@setData="setInputValue" />
|
||||
:error="confirmationPasswordError"
|
||||
@setData="setPasswordConfirmation" />
|
||||
</div>
|
||||
<div class="account-area-save-button-area">
|
||||
<div v-if="isPasswordEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<!-- v-if we are editing this area -->
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancel" isWhite/>
|
||||
<Button label="Save" width="140px" height="50px" :onPress="onSave" isWhite isDisabled/>
|
||||
<Button class="account-area-save-button-area__cancel-button" label="Cancel" width="140px" height="50px" :onPress="onCancelPasswordEditButtonClick" isWhite/>
|
||||
<Button label="Save" width="140px" height="50px" :onPress="onSavePasswordButtonClick"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isPasswordEditing" class="account-area-save-button-area" >
|
||||
<div class="account-area-save-button-area__btn">
|
||||
<Button label="Save" width="140px" height="50px" isWhite isDisabled/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--end of Password area -->
|
||||
<div class="account-area-button-area">
|
||||
<Button label="Delete account" width="140px" height="50px" :onPress="onDeleteAccountClick" isWhite/>
|
||||
<Button label="Delete account" width="140px" height="50px" :onPress="onDeleteAccountClick" isWhite/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -157,21 +183,290 @@ import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||
import Checkbox from '@/components/common/Checkbox.vue';
|
||||
|
||||
@Component(
|
||||
{
|
||||
{
|
||||
data: function() {
|
||||
return {
|
||||
originalFirstName: this.$store.getters.user.firstName,
|
||||
originalLastName: this.$store.getters.user.lastName,
|
||||
originalEmail:this.$store.getters.user.email,
|
||||
|
||||
firstName: this.$store.getters.user.firstName,
|
||||
lastName: this.$store.getters.user.lastName,
|
||||
email: this.$store.getters.user.email,
|
||||
isTermsAccepted: false,
|
||||
|
||||
firstNameError: "",
|
||||
lastNameError: "",
|
||||
emailError: "",
|
||||
isTermsAcceptedError: false,
|
||||
|
||||
newLastName: "",
|
||||
newEmail: "",
|
||||
isAccountSettingsEditing: false,
|
||||
|
||||
originalCompanyName: this.$store.getters.user.company.name,
|
||||
originalCompanyAddress: this.$store.getters.user.company.address,
|
||||
originalCompanyCountry: this.$store.getters.user.company.country,
|
||||
originalCompanyCity: this.$store.getters.user.company.city,
|
||||
originalCompanyState: this.$store.getters.user.company.state,
|
||||
originalCompanyPostalCode: this.$store.getters.user.company.postalCode,
|
||||
|
||||
companyName: this.$store.getters.user.company.name,
|
||||
companyAddress: this.$store.getters.user.company.address,
|
||||
companyCountry: this.$store.getters.user.company.country,
|
||||
companyCity: this.$store.getters.user.company.city,
|
||||
companyState: this.$store.getters.user.company.state,
|
||||
companyPostalCode: this.$store.getters.user.company.postalCode,
|
||||
|
||||
isCompanyEditing: false,
|
||||
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
confirmationPassword: "",
|
||||
|
||||
oldPasswordError: "",
|
||||
newPasswordError: "",
|
||||
confirmationPasswordError: "",
|
||||
isPasswordEditing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setFirstName: function (value: string) {
|
||||
this.$data.firstName = value;
|
||||
this.$data.firstNameError = "";
|
||||
this.$data.isAccountSettingsEditing = true;
|
||||
},
|
||||
setLastName: function (value: string) {
|
||||
this.$data.lastName = value;
|
||||
this.$data.lastNameError = "";
|
||||
this.$data.isAccountSettingsEditing = true;
|
||||
},
|
||||
setEmail: function (value: string) {
|
||||
this.$data.email = value;
|
||||
this.$data.emailError = "";
|
||||
this.$data.isAccountSettingsEditing = true;
|
||||
},
|
||||
setTermsAccepted: function (value: boolean) {
|
||||
this.$data.isTermsAccepted = value;
|
||||
this.$data.isTermsAcceptedError = false;
|
||||
},
|
||||
onCancelAccountSettingsButtonClick: function () {
|
||||
this.$data.firstName = this.$data.originalFirstName;
|
||||
this.$data.firstNameError = "";
|
||||
this.$data.lastName = this.$store.getters.user.lastName;
|
||||
this.$data.lastNameError = "";
|
||||
this.$data.email = this.$data.originalEmail;
|
||||
this.$data.emailError = "";
|
||||
|
||||
this.$refs.firstNameInput.setValue(this.$data.originalFirstName);
|
||||
this.$refs.lastNameInput.setValue(this.$data.originalLastName);
|
||||
this.$refs.emailInput.setValue(this.$data.originalEmail);
|
||||
|
||||
this.$data.isAccountSettingsEditing = false;
|
||||
},
|
||||
onSaveAccountSettingsButtonClick: async function () {
|
||||
let hasError = false;
|
||||
|
||||
if (!this.$data.firstName) {
|
||||
this.$data.firstNameError = "First name expected";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (!this.$data.lastName) {
|
||||
this.$data.lastNameError = "Last name expected";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (!this.$data.email) {
|
||||
this.$data.emailError = "Email expected";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (!this.$data.isTermsAccepted) {
|
||||
this.$data.isTermsAcceptedError = true;
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
return;
|
||||
}
|
||||
|
||||
let user = {
|
||||
id: this.$store.getters.user.id,
|
||||
email: this.$data.email,
|
||||
firstName: this.$data.firstName,
|
||||
lastName: this.$data.lastName,
|
||||
};
|
||||
let isSuccess = await this.$store.dispatch("updateBasicUserInfo", user);
|
||||
if (!isSuccess) {
|
||||
//TODO Change to popup
|
||||
console.log("error while changing basic user info");
|
||||
|
||||
return;
|
||||
}
|
||||
this.$data.isAccountSettingsEditing = false;
|
||||
},
|
||||
|
||||
setCompanyName:function (value: string) {
|
||||
this.$data.companyName = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
setCompanyAddress:function (value: string) {
|
||||
this.$data.companyAddress = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
setCompanyCountry: function (value: string) {
|
||||
this.$data.companyCountry = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
setCompanyCity:function (value: string) {
|
||||
this.$data.companyCity = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
setCompanyState:function (value: string) {
|
||||
this.$data.companyState = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
setCompanyPostalCode:function (value: string) {
|
||||
this.$data.companyPostalCode = value;
|
||||
this.$data.isCompanyEditing = true;
|
||||
},
|
||||
onCancelCompanyButtonClick: function () {
|
||||
this.$data.companyName=this.$data.originalCompanyName;
|
||||
this.$data.companyAddress=this.$data.originalCompanyAddress;
|
||||
this.$data.companyCountry=this.$data.originalCompanyCountry;
|
||||
this.$data.companyCity=this.$data.originalCompanyCity;
|
||||
this.$data.companyState=this.$data.originalCompanyState;
|
||||
this.$data.companyPostalCode=this.$data.originalCompanyPostalCode;
|
||||
|
||||
this.$refs.companyNameInput.setValue(this.$data.originalCompanyName);
|
||||
this.$refs.companyAddressInput.setValue(this.$data.originalCompanyAddress);
|
||||
this.$refs.companyCountryInput.setValue(this.$data.originalCompanyCountry);
|
||||
this.$refs.companyCityInput.setValue(this.$data.originalCompanyCity);
|
||||
this.$refs.companyStateInput.setValue(this.$data.originalCompanyState);
|
||||
this.$refs.companyPostalCodeInput.setValue(this.$data.originalCompanyPostalCode);
|
||||
|
||||
this.$data.isCompanyEditing= false;
|
||||
},
|
||||
onSaveCompanySettingsButtonClick: async function () {
|
||||
let user = {
|
||||
id: this.$store.getters.user.id,
|
||||
company : {
|
||||
name: this.$data.companyName,
|
||||
address: this.$data.companyAddress,
|
||||
country: this.$data.companyCountry,
|
||||
city: this.$data.companyCity,
|
||||
state: this.$data.companyState,
|
||||
postalCode: this.$data.companyPostalCode
|
||||
}
|
||||
};
|
||||
|
||||
let isSuccess = await this.$store.dispatch("updateCompanyInfo", user)
|
||||
if (!isSuccess) {
|
||||
//TODO Change to popup
|
||||
console.log("error while changing company info");
|
||||
|
||||
return;
|
||||
}
|
||||
this.$data.isCompanyEditing = false;
|
||||
},
|
||||
|
||||
setOldPassword: function (value: string) {
|
||||
this.$data.oldPassword = value;
|
||||
this.$data.oldPasswordError = "";
|
||||
this.$data.isPasswordEditing = true;
|
||||
},
|
||||
setNewPassword: function (value: string) {
|
||||
this.$data.newPassword = value;
|
||||
this.$data.newPasswordError = "";
|
||||
this.$data.isPasswordEditing = true;
|
||||
},
|
||||
setPasswordConfirmation: function (value: string) {
|
||||
this.$data.confirmationPassword = value;
|
||||
this.$data.confirmationPasswordError = "";
|
||||
this.$data.isPasswordEditing = true;
|
||||
},
|
||||
onCancelPasswordEditButtonClick: function () {
|
||||
this.$data.oldPassword = "";
|
||||
this.$data.newPassword = "";
|
||||
this.$data.confirmationPassword = "";
|
||||
|
||||
this.$data.oldPasswordError = "";
|
||||
this.$data.newPasswordError = "";
|
||||
this.$data.confirmationPasswordError = "";
|
||||
|
||||
this.$refs.oldPasswordInput.setValue("");
|
||||
this.$refs.newPasswordInput.setValue("");
|
||||
this.$refs.confirmationPasswordInput.setValue("");
|
||||
|
||||
this.$data.isPasswordEditing = false;
|
||||
},
|
||||
onSavePasswordButtonClick: async function () {
|
||||
let hasError = false;
|
||||
|
||||
if (!this.$data.oldPassword) {
|
||||
this.$data.oldPasswordError = "Password required";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if(!this.$data.newPassword) {
|
||||
this.$data.newPasswordError = "Password required";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (!this.$data.confirmationPassword) {
|
||||
this.$data.confirmationPasswordError = "Password required";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if(this.$data.newPassword !== this.$data.confirmationPassword) {
|
||||
this.$data.confirmationPasswordError = "Password not match to new one";
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
return;
|
||||
}
|
||||
|
||||
let isSuccess = await this.$store.dispatch("updatePassword",this.$data.newPassword);
|
||||
if (!isSuccess) {
|
||||
//TODO Change to popup
|
||||
console.log("error while updating user password");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.$refs.oldPasswordInput.setValue("");
|
||||
this.$refs.newPasswordInput.setValue("");
|
||||
this.$refs.confirmationPasswordInput.setValue("");
|
||||
|
||||
this.$data.isPasswordEditing = false;
|
||||
},
|
||||
onDeleteAccountClick: async function () {
|
||||
// TODO show popup with user confirmation
|
||||
let isSuccess = await this.$store.dispatch("deleteUserAccount");
|
||||
if (!isSuccess) {
|
||||
//TODO Change to popup
|
||||
console.log("error while deleting user account");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO navigate to start route
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Button,
|
||||
HeaderedInput,
|
||||
Checkbox
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
export default class AccountArea extends Vue {}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -28,7 +28,6 @@ import AccountDropdown from "./AccountDropdown.vue";
|
||||
{
|
||||
data: function() {
|
||||
return {
|
||||
userName: this.$store.getters.userName,
|
||||
isChoiceShown: false
|
||||
}
|
||||
},
|
||||
@ -39,7 +38,11 @@ import AccountDropdown from "./AccountDropdown.vue";
|
||||
},
|
||||
// may change later
|
||||
avatarLetter: function() : string {
|
||||
return this.$data.userName.slice(0,1).toUpperCase();
|
||||
return this.$store.getters.userName.slice(0,1).toUpperCase();
|
||||
},
|
||||
userName: function (): string {
|
||||
return this.$store.getters.userName;
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -4,7 +4,7 @@
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import {authModule} from "@/store/modules/auth";
|
||||
import {authModule} from "@/store/modules/users";
|
||||
import {projectsModule} from "@/store/modules/projects";
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
@ -1,58 +0,0 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import {
|
||||
AUTH_MUTATIONS,
|
||||
} from "../mutationConstants";
|
||||
|
||||
export const authModule = {
|
||||
state: {
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "",
|
||||
id: "",
|
||||
companyName: "",
|
||||
companyAddress: "",
|
||||
companyCountry: "",
|
||||
companyCity: "",
|
||||
companyState: "",
|
||||
companyPostalCode: "",
|
||||
},
|
||||
mutations: {
|
||||
[AUTH_MUTATIONS.SET_USER_INFO](state: any, user: User): void {
|
||||
state.firstName = user.firstName;
|
||||
state.lastName = user.lastName;
|
||||
state.email = user.email;
|
||||
state.id = user.id;
|
||||
state.companyName = user.company.name;
|
||||
state.companyAddress = user.company.address;
|
||||
state.companyCountry = user.company.country;
|
||||
state.companyCity = user.company.city;
|
||||
state.companyState = user.company.state;
|
||||
state.companyPostalCode = user.company.postalCode;
|
||||
},
|
||||
|
||||
[AUTH_MUTATIONS.REVERT_TO_DEFAULT_USER_INFO](state: any): void {
|
||||
state.firstName = "";
|
||||
state.lastName = "";
|
||||
state.email = "";
|
||||
state.id = "";
|
||||
state.companyName = "";
|
||||
state.companyAddress = "";
|
||||
state.companyCountry = "";
|
||||
state.companyCity = "";
|
||||
state.companyState = "";
|
||||
state.companyPostalCode = "";
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setUserInfo: setUserInfo,
|
||||
},
|
||||
getters: {
|
||||
userName: (state: any) => `${state.firstName} ${state.lastName}`
|
||||
},
|
||||
};
|
||||
|
||||
function setUserInfo({commit}: any, userInfo: User): void {
|
||||
commit(AUTH_MUTATIONS.SET_USER_INFO, userInfo)
|
||||
}
|
126
web/satellite/src/store/modules/users.ts
Normal file
126
web/satellite/src/store/modules/users.ts
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import {
|
||||
USER_MUTATIONS,
|
||||
} from "../mutationConstants";
|
||||
import {updateCompanyInfo, updatePassword, updateBasicUserInfo, deleteUserAccount} from "@/api/users";
|
||||
|
||||
export const authModule = {
|
||||
state: {
|
||||
user: {
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "",
|
||||
id: "",
|
||||
company: {
|
||||
name: "",
|
||||
address: "",
|
||||
country: "",
|
||||
city: "",
|
||||
state: "",
|
||||
postalCode: "",
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
[USER_MUTATIONS.SET_USER_INFO](state: any, user: User): void {
|
||||
state.user.firstName = user.firstName;
|
||||
state.user.lastName = user.lastName;
|
||||
state.user.email = user.email;
|
||||
state.user.id = user.id;
|
||||
state.user.company.name = user.company.name;
|
||||
state.user.company.address = user.company.address;
|
||||
state.user.company.country = user.company.country;
|
||||
state.user.company.city = user.company.city;
|
||||
state.user.company.state = user.company.state;
|
||||
state.user.company.postalCode = user.company.postalCode;
|
||||
},
|
||||
|
||||
[USER_MUTATIONS.REVERT_TO_DEFAULT_USER_INFO](state: any): void {
|
||||
state.user.firstName = "";
|
||||
state.user.lastName = "";
|
||||
state.user.email = "";
|
||||
state.user.id = "";
|
||||
state.user.company.name = "";
|
||||
state.user.company.address = "";
|
||||
state.user.company.country = "";
|
||||
state.user.company.city = "";
|
||||
state.user.company.state = "";
|
||||
state.user.company.postalCode = "";
|
||||
},
|
||||
|
||||
[USER_MUTATIONS.UPDATE_USER_INFO](state: any, user: User): void {
|
||||
state.user.firstName = user.firstName;
|
||||
state.user.lastName = user.lastName;
|
||||
state.user.email = user.email;
|
||||
},
|
||||
|
||||
[USER_MUTATIONS.UPDATE_COMPANY_INFO](state: any, company: Company): void {
|
||||
state.user.company.name = company.name;
|
||||
state.user.company.address = company.address;
|
||||
state.user.company.country = company.country;
|
||||
state.user.company.city = company.city;
|
||||
state.user.company.state = company.state;
|
||||
state.user.company.postalCode = company.postalCode;
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
setUserInfo: setUserInfo,
|
||||
updateBasicUserInfo: async function ({commit}: any, userInfo: User): Promise<boolean>{
|
||||
let response = await updateBasicUserInfo(userInfo);
|
||||
|
||||
if (!response || !response.data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
commit(USER_MUTATIONS.UPDATE_USER_INFO, userInfo)
|
||||
|
||||
return true;
|
||||
},
|
||||
updateCompanyInfo: async function ({commit}: any, userInfo: User): Promise<boolean>{
|
||||
let response = await updateCompanyInfo(userInfo.id, userInfo.company);
|
||||
|
||||
if (!response || !response.data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
commit(USER_MUTATIONS.UPDATE_COMPANY_INFO, response.data.updateCompany)
|
||||
|
||||
return true;
|
||||
},
|
||||
updatePassword: async function ({state}: any, password: string): Promise<boolean> {
|
||||
let response = await updatePassword(state.user.id, password);
|
||||
|
||||
if (!response) {
|
||||
console.log("error during password change");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
deleteUserAccount: async function ({commit, state}: any):Promise<boolean> {
|
||||
let response = await deleteUserAccount(state.user.id);
|
||||
|
||||
if (!response) {
|
||||
console.log("error during account delete");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
getters: {
|
||||
user: (state: any) => {
|
||||
return state.user;
|
||||
},
|
||||
userName: (state: any) => `${state.user.firstName} ${state.user.lastName}`
|
||||
},
|
||||
};
|
||||
|
||||
function setUserInfo({commit}: any, userInfo: User): void {
|
||||
commit(USER_MUTATIONS.SET_USER_INFO, userInfo)
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
export const AUTH_MUTATIONS = {
|
||||
export const USER_MUTATIONS = {
|
||||
SET_USER_INFO: "SET_USER_INFO",
|
||||
REVERT_TO_DEFAULT_USER_INFO: "REVERT_TO_DEFAULT_USER_INFO",
|
||||
UPDATE_USER_INFO: "UPDATE_USER_INFO",
|
||||
UPDATE_COMPANY_INFO: "UPDATE_COMPANY_INFO",
|
||||
};
|
||||
|
||||
export const PROJECTS_MUTATIONS = {
|
||||
|
@ -9,7 +9,7 @@ import { getToken } from "../utils/tokenManager"
|
||||
|
||||
// Satellite url
|
||||
const satelliteUrl = new HttpLink({
|
||||
uri: 'http://localhost:8081/api/graphql/v0',
|
||||
uri: 'http://192.168.1.90:8081/api/graphql/v0',
|
||||
});
|
||||
|
||||
// Adding auth headers
|
||||
|
@ -1,45 +0,0 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import apolloManager from '../apolloManager';
|
||||
import gql from "graphql-tag";
|
||||
|
||||
// Performs graqhQL request.
|
||||
// Throws an exception if error occurs
|
||||
export async function createUser(user: User, password: string): Promise<any> {
|
||||
|
||||
let response = apolloManager.mutate(
|
||||
{
|
||||
mutation: gql(`
|
||||
mutation {
|
||||
createUser(
|
||||
input:{
|
||||
email: "${user.email}",
|
||||
password: "${password}",
|
||||
firstName: "${user.firstName}",
|
||||
lastName: "${user.lastName}",
|
||||
company: {
|
||||
name: "${user.company.name}",
|
||||
address: "${user.company.address}",
|
||||
country: "${user.company.country}",
|
||||
city: "${user.company.city}",
|
||||
state: "${user.company.state}",
|
||||
postalCode: "${user.company.postalCode}"
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response) {
|
||||
console.log("cannot create user")
|
||||
// TODO: Change with popup
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import apolloManager from '../apolloManager';
|
||||
import gql from "graphql-tag";
|
||||
|
||||
// Performs graqhQL request.
|
||||
// Returns Token, User objects.
|
||||
// Throws an exception if error occurs
|
||||
export async function login(email: string, password: string): Promise<any> {
|
||||
let response = await apolloManager.query(
|
||||
{
|
||||
query: gql(`
|
||||
query {
|
||||
token(email: "${email}",
|
||||
password: "${password}") {
|
||||
token,
|
||||
user{
|
||||
id,
|
||||
firstName,
|
||||
lastName,
|
||||
email,
|
||||
company{
|
||||
name,
|
||||
address,
|
||||
country,
|
||||
city,
|
||||
state,
|
||||
postalCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}`),
|
||||
fetchPolicy: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
console.log(response);
|
||||
if (!response) {
|
||||
console.error("No token received");
|
||||
// TODO: Change with popup
|
||||
return null;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
@ -45,7 +45,7 @@
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import {setToken} from "../utils/tokenManager";
|
||||
import ROUTES from "../utils/constants/routerConstants";
|
||||
import {login} from "../utils/qraphql/loginQuery";
|
||||
import {login} from "@/api/users";
|
||||
|
||||
@Component({
|
||||
data: function () {
|
||||
@ -80,7 +80,6 @@
|
||||
}
|
||||
|
||||
},
|
||||
computed: {},
|
||||
components: {
|
||||
HeaderlessInput,
|
||||
Button
|
||||
|
@ -146,7 +146,7 @@
|
||||
import Button from '@/components/common/Button.vue';
|
||||
import {validateEmail} from "@/utils/validation"
|
||||
import ROUTES from "../utils/constants/routerConstants";
|
||||
import {createUser} from "../utils/qraphql/createUserQuery";
|
||||
import {createUser} from "@/api/users";
|
||||
|
||||
@Component(
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user