V3-1033 Implement AppState module for DropDown lists (#1008)

* V3-1033 Implement AppState module for DropDown lists

* commentig unused items
This commit is contained in:
Yehor Butko 2019-01-09 17:40:21 +02:00 committed by GitHub
parent 756f49fea1
commit 7090a31ef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 414 additions and 239 deletions

View File

@ -2,7 +2,7 @@
// See LICENSE for copying information.
<template>
<div id="app">
<div id="app" v-on:click="onClick">
<router-view/>
<!-- Area for displaying notification -->
<NotificationArea/>
@ -12,15 +12,51 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import NotificationArea from '@/components/notifications/NotificationArea.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
@Component({
data: function() {
return {
ids: [
'newProjectPopup',
'newProjectButton',
'accountDropdown',
'accountDropdownButton',
'projectDropdown',
'projectDropdownButton',
'deleteProjectPopup',
'deleteProjectPopupButton',
'deleteAccountPopupButton',
'deleteAccountPopup',
'addTeamMemberPopupButton',
'addTeamMemberPopup',
'addTeamMemberPopupButtonSVG'
]
};
},
components: {
NotificationArea
},
methods: {
onClick: function(e) {
let target: any = e.target;
while (target) {
if (this.$data.ids.includes(target.id)) {
return;
}
target = target.parentNode;
}
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
}
}
})
export default class App extends Vue {
}
</script>
<style lang="scss">

View File

@ -30,7 +30,6 @@
placeholder="Enter Last Name"
width="100%"
ref="lastNameInput"
:error="lastNameError"
:initValue="user.lastName"
@setData="setLastName"/>
<HeaderedInput
@ -114,10 +113,10 @@
</div>
<!--end of Password area -->
</div>
<div class="account-area-button-area">
<div class="account-area-button-area" id="deleteAccountPopupButton">
<Button label="Delete account" width="205px" height="50px" :onPress="togglePopup" isDeletion/>
</div>
<DeleteAccountPopup v-if="isPopupShown" :onClose="togglePopup" />
<DeleteAccountPopup v-if="isPopupShown" />
</div>
</template>
@ -127,8 +126,8 @@ import Button from '@/components/common/Button.vue';
import HeaderedInput from '@/components/common/HeaderedInput.vue';
import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
import Checkbox from '@/components/common/Checkbox.vue';
import ROUTES from '@/utils/constants/routerConstants';
import DeleteAccountPopup from '@/components/dashboard/account/DeleteAccountPopup.vue';
import { USER_ACTIONS, NOTIFICATION_ACTIONS, APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import DeleteAccountPopup from '@/components/account/DeleteAccountPopup.vue';
import { validateEmail, validatePassword } from '@/utils/validation';
@Component(
@ -144,7 +143,6 @@ import { validateEmail, validatePassword } from '@/utils/validation';
email: this.$store.getters.user.email,
firstNameError: '',
lastNameError: '',
emailError: '',
isAccountSettingsEditing: false,
@ -157,8 +155,6 @@ import { validateEmail, validatePassword } from '@/utils/validation';
newPasswordError: '',
confirmationPasswordError: '',
isPasswordEditing: false,
isPopupShown: false
};
},
methods: {
@ -169,7 +165,6 @@ import { validateEmail, validatePassword } from '@/utils/validation';
},
setLastName: function (value: string) {
this.$data.lastName = value;
this.$data.lastNameError = '';
this.$data.isAccountSettingsEditing = true;
},
setEmail: function (value: string) {
@ -181,7 +176,6 @@ import { validateEmail, validatePassword } from '@/utils/validation';
this.$data.firstName = this.$data.originalFirstName;
this.$data.firstNameError = '';
this.$data.lastName = this.$data.originalLastName;
this.$data.lastNameError = '';
this.$data.email = this.$data.originalEmail;
this.$data.emailError = '';
@ -204,11 +198,6 @@ import { validateEmail, validatePassword } from '@/utils/validation';
hasError = true;
}
if (!this.$data.lastName) {
this.$data.lastNameError = 'Last name expected';
hasError = true;
}
if (!validateEmail(this.$data.email)) {
this.$data.emailError = 'Incorrect email';
hasError = true;
@ -224,14 +213,14 @@ import { validateEmail, validatePassword } from '@/utils/validation';
lastName: this.$data.lastName,
};
let response = await this.$store.dispatch('updateAccount', user);
let response = await this.$store.dispatch(USER_ACTIONS.UPDATE, user);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}
this.$store.dispatch('success', 'Account info successfully updated!');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Account info successfully updated!');
this.$data.originalFirstName = this.$store.getters.user.firstName;
this.$data.originalLastName = this.$store.getters.user.lastName;
@ -302,19 +291,19 @@ import { validateEmail, validatePassword } from '@/utils/validation';
return;
}
let response = await this.$store.dispatch('changePassword',
let response = await this.$store.dispatch(USER_ACTIONS.CHANGE_PASSWORD,
{
oldPassword: this.$data.oldPassword,
newPassword: this.$data.newPassword
}
);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}
this.$store.dispatch('success', 'Password successfully changed!');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Password successfully changed!');
this.$data.oldPassword = '';
this.$data.newPassword = '';
@ -336,7 +325,7 @@ import { validateEmail, validatePassword } from '@/utils/validation';
this.$data.isPasswordEditing = false;
},
togglePopup: function(): void {
this.$data.isPopupShown = ! this.$data.isPopupShown;
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_DEL_ACCOUNT);
},
},
computed: {
@ -351,6 +340,10 @@ import { validateEmail, validatePassword } from '@/utils/validation';
avatarLetter: function (): string {
return this.$store.getters.userName.slice(0, 1).toUpperCase();
},
isPopupShown: function (): boolean {
return this.$store.state.appStateModule.appState.isDeleteAccountPopupShown;
}
},
components: {
Button,

View File

@ -3,7 +3,7 @@
<template>
<div class='delete-account-container'>
<div class='delete-account' >
<div class='delete-account' id="deleteAccountPopup">
<div class='delete-account__info-panel-container'>
<h2 class='delete-account__info-panel-container__main-label-text'>Delete account</h2>
<div v-html='imageSource'></div>
@ -20,12 +20,12 @@
@setData='setPassword'>
</HeaderedInput>
<div class='delete-account__form-container__button-container'>
<Button label='Cancel' width='205px' height='48px' :onPress='onClose' isWhite/>
<Button label='Cancel' width='205px' height='48px' :onPress='onCloseClick' isWhite/>
<Button label='Delete' width='205px' height='48px' class='red' :onPress='onDeleteAccountClick'/>
</div>
</div>
<div class='delete-account__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='onClose'>
<svg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg' v-on:click='onCloseClick'>
<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>
@ -39,12 +39,10 @@ import HeaderedInput from '@/components/common/HeaderedInput.vue';
import Button from '@/components/common/Button.vue';
import { removeToken } from '@/utils/tokenManager';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import { APP_STATE_ACTIONS, USER_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
props: {
onClose: Function
},
data: function() {
return {
password: '',
@ -57,18 +55,21 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
this.$data.password = value;
},
onDeleteAccountClick: async function() {
let response = await this.$store.dispatch('deleteAccount', this.$data.password);
let response = await this.$store.dispatch(USER_ACTIONS.DELETE, this.$data.password);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}
this.$store.dispatch('success', 'Account was successfully deleted');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Account was successfully deleted');
removeToken();
this.$router.push('/login');
},
onCloseClick: function (): void {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_DEL_ACCOUNT);
}
},
components: {
HeaderedInput,

View File

@ -0,0 +1,36 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div>
<EmptyState
mainTitle="Choose or Create new project"
:imageSource="emptyImage" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import EmptyState from '@/components/common/EmptyStateArea.vue';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
@Component(
{
data: function () {
return {
emptyImage: EMPTY_STATE_IMAGES.PROJECT,
};
},
components: {
EmptyState,
}
}
)
export default class DashboardArea extends Vue {
}
</script>
<style scoped lang="scss">
</style>

View File

@ -2,7 +2,7 @@
// See LICENSE for copying information.
<template>
<div class="account-button-container" >
<div class="account-button-container" id="accountDropdownButton">
<div class="account-button-toggle-container" v-on:click="toggleSelection" >
<!-- background of this div generated and stores in store -->
<div class="account-button-toggle-container__avatar" :style="style">
@ -12,25 +12,21 @@
</div>
<h1 class="account-button-toggle-container__user-name">{{userName}}</h1>
<div class="account-button-toggle-container__expander-area">
<img v-if="!isChoiceShown" src="../../../../static/images/register/BlueExpand.svg" />
<img v-if="isChoiceShown" src="../../../../static/images/register/BlueHide.svg" />
<img v-if="!isDropdownShown" src="../../../static/images/register/BlueExpand.svg" />
<img v-if="isDropdownShown" src="../../../static/images/register/BlueHide.svg" />
</div>
</div>
<AccountDropdown v-if="isChoiceShown" @onClose="toggleSelection" />
<AccountDropdown v-if="isDropdownShown" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import AccountDropdown from './AccountDropdown.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
data: function () {
return {
isChoiceShown: false
};
},
computed: {
style: function (): object {
// Color from $store
@ -42,12 +38,14 @@ import AccountDropdown from './AccountDropdown.vue';
},
userName: function (): string {
return this.$store.getters.userName;
}
},
isDropdownShown: function (): boolean {
return this.$store.state.appStateModule.appState.isAccountDropdownShown;
},
},
methods: {
toggleSelection: function (): void {
this.$data.isChoiceShown = !this.$data.isChoiceShown;
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_ACCOUNT);
}
},
components: {

View File

@ -3,7 +3,7 @@
<template>
<!-- To close popup we need to use method onCloseClick -->
<div class="account-dropdown-choice-container" >
<div class="account-dropdown-choice-container" id="accountDropdown">
<div class="account-dropdown-overflow-container">
<!-- TODO: add selection logic onclick -->
<div class="account-dropdown-item-container settings" v-on:click="onAccountSettingsClick" >
@ -47,31 +47,27 @@
import { Component, Vue } from 'vue-property-decorator';
import { removeToken } from '@/utils/tokenManager';
import ROUTES from '@/utils/constants/routerConstants';
import { APP_STATE_ACTIONS, PROJETS_ACTIONS, PM_ACTIONS, USER_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
data: function () {
return {};
},
props: {
onClose: {
type: Function
}
},
methods: {
onCloseClick: function (): void {
this.$emit('onClose');
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_ACCOUNT);
},
onAccountSettingsClick: function (): void {
this.$router.push('/account-settings');
this.$emit('onClose');
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_ACCOUNT);
},
onLogoutClick: function () {
removeToken();
this.$router.push(ROUTES.LOGIN.path);
this.$store.dispatch('clearProjectMembers');
this.$store.dispatch('clearProjects');
this.$store.dispatch('clearUser');
this.$store.dispatch(PM_ACTIONS.CLEAR);
this.$store.dispatch(PROJETS_ACTIONS.CLEAR);
this.$store.dispatch(USER_ACTIONS.CLEAR);
}
},
}

View File

@ -34,9 +34,9 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import ProjectSelectionArea from './projectSelection/ProjectSelectionArea.vue';
import NewProjectArea from './newProject/NewProjectArea.vue';
import AccountButton from './account/AccountButton.vue';
import ProjectSelectionArea from '@/components/header/projectSelection/ProjectSelectionArea.vue';
import NewProjectArea from '@/components/header/NewProjectArea.vue';
import AccountButton from './AccountButton.vue';
@Component(
{

View File

@ -3,33 +3,33 @@
<template>
<div class="new-project-container">
<div class="new-project-button-container" v-on:click="toggleSelection">
<div class="new-project-button-container" v-on:click="toggleSelection" id="newProjectButton">
<h1>New Project +</h1>
</div>
<NewProjectPopup v-if="isPopupShown" @onClose="toggleSelection"/>
<NewProjectPopup v-if="isPopupShown"/>
</div>
</template>
<script lang="ts">
import { mapState } from 'vuex';
import { Component, Vue } from 'vue-property-decorator';
import NewProjectPopup from './NewProjectPopup.vue';
import NewProjectPopup from '@/components/project/NewProjectPopup.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
// Button and popup for adding new Project
@Component(
{
data: function () {
return {
isPopupShown: false
};
},
methods: {
toggleSelection: function () {
this.$data.isPopupShown = !this.$data.isPopupShown;
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
}
},
components: {
NewProjectPopup
}
},
computed: mapState({
isPopupShown: (state: any) => state.appStateModule.appState.isNewProjectPopupShown,
}),
}
)

View File

@ -2,48 +2,46 @@
// See LICENSE for copying information.
<template>
<div class="project-selection-container">
<div class="project-selection-container" id="projectDropdownButton">
<div class="project-selection-toggle-container" v-on:click="toggleSelection">
<h1>{{name}}</h1>
<div class="project-selection-toggle-container__expander-area">
<img v-if="!isChoiceShown" src="../../../../static/images/register/BlueExpand.svg"/>
<img v-if="isChoiceShown" src="../../../../static/images/register/BlueHide.svg"/>
<img v-if="!isDropdownShown" src="../../../../static/images/register/BlueExpand.svg"/>
<img v-if="isDropdownShown" src="../../../../static/images/register/BlueHide.svg"/>
</div>
</div>
<ProjectSelectionDropdown v-if="isChoiceShown" @onClose="toggleSelection"/>
<ProjectSelectionDropdown v-if="isDropdownShown"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { mapState } from 'vuex';
import ProjectSelectionDropdown from './ProjectSelectionDropdown.vue';
import { APP_STATE_ACTIONS, PROJETS_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
data: function () {
return {
isChoiceShown: false,
};
},
methods: {
toggleSelection: async function (): Promise<any> {
const response = await this.$store.dispatch('fetchProjects');
const response = await this.$store.dispatch(PROJETS_ACTIONS.FETCH);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}
this.$data.isChoiceShown = !this.$data.isChoiceShown;
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_PROJECTS);
}
},
computed: {
name: function (): string {
let selectedProject = this.$store.getters.selectedProject;
computed: mapState({
name: (state: any): string => {
let selectedProject = state.projectsModule.selectedProject;
return selectedProject.id ? selectedProject.name : 'Choose project';
}
},
},
isDropdownShown: (state: any) => state.appStateModule.appState.isProjectsDropdownShown
}),
components: {
ProjectSelectionDropdown
}

View File

@ -2,7 +2,7 @@
// See LICENSE for copying information.
<template>
<div class="project-selection-choice-container" >
<div class="project-selection-choice-container" id="projectDropdown">
<div class="project-selection-overflow-container">
<!-- loop for rendering projects -->
<!-- TODO: add selection logic onclick -->
@ -20,6 +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';
@Component(
{
@ -28,23 +29,18 @@ import { Component, Vue } from 'vue-property-decorator';
return this.$store.getters.projects;
}
},
props: {
onClose: {
type: Function
}
},
methods: {
onProjectSelected: async function (projectID: string): Promise<void> {
this.$store.dispatch('selectProject', projectID);
this.$emit('onClose');
this.$store.dispatch(PROJETS_ACTIONS.SELECT, projectID);
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_PROJECTS);
if (!this.$store.getters.selectedProject.id) return;
const response = await this.$store.dispatch('fetchProjectMembers', {limit: 20, offset: 0});
const response = await this.$store.dispatch(PM_ACTIONS.FETCH, {limit: 20, offset: 0});
if (response.isSuccess) return;
this.$store.dispatch('error', 'Unable to fetch project members');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to fetch project members');
}
},
}

View File

@ -7,7 +7,7 @@
<div class="navigation-area__item-container__link-container" >
<div v-html="navItem.svg"></div>
<h1>{{navItem.label}}</h1>
<div class="navigation-area__item-container__link-container__add-button" v-if="navItem.label == 'Team'">
<div class="navigation-area__item-container__link-container__add-button" id="addTeamMemberPopupButtonSVG" v-if="navItem.label == 'Team'">
<div v-on:click="togglePopup">
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="20" fill="#2683FF"/>
@ -25,7 +25,8 @@
import { Component, Vue } from 'vue-property-decorator';
import { mapState } from 'vuex';
import NAVIGATION_ITEMS from '@/utils/constants/navigationLinks';
import AddUserPopup from '@/components/dashboard/AddUserPopup.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import AddUserPopup from '@/components/team/AddUserPopup.vue';
@Component(
{
@ -42,11 +43,11 @@ import AddUserPopup from '@/components/dashboard/AddUserPopup.vue';
togglePopup: function(): void {
if (!this.$store.getters.selectedProject.id) return;
this.$store.dispatch('setAddTeamMembersPopup', true);
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_TEAM_MEMBERS);
},
},
computed: mapState({
isAddTeamMembersPopupShown: (state: any) => state.appStateModule.currentAppState.isAddTeamMembersPopupShown,
isAddTeamMembersPopupShown: (state: any) => state.appStateModule.appState.isAddTeamMembersPopupShown,
}),
}
)
@ -72,7 +73,6 @@ export default class NavigationArea extends Vue {
display: flex;
justify-content: flex-start;
align-items: center;
&.router-link-active,
&.router-link-exact-active,
&:hover {
border-left: 3px solid #2683FF;

View File

@ -16,6 +16,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { NOTIFICATION_IMAGES, NOTIFICATION_TYPES } from '@/utils/constants/notification';
import { NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
@Component({
props: {
@ -25,15 +26,15 @@ import { NOTIFICATION_IMAGES, NOTIFICATION_TYPES } from '@/utils/constants/notif
methods: {
// Force delete notification
onCloseClick: function (): void {
this.$store.dispatch('deleteNotification');
this.$store.dispatch(NOTIFICATION_ACTIONS.DELETE);
},
// Force notification to stay on page on mouse over it
onMouseOver: function (): void {
this.$store.dispatch('pauseNotification');
this.$store.dispatch(NOTIFICATION_ACTIONS.PAUSE);
},
// Resume notification flow when mouse leaves notification
onMouseLeave: function (): void {
this.$store.dispatch('resumeNotification');
this.$store.dispatch(NOTIFICATION_ACTIONS.RESUME);
},
},
computed: {

View File

@ -3,7 +3,7 @@
<template>
<div class="delete-project-popup-container">
<div class="delete-project-popup">
<div class="delete-project-popup" id="deleteProjectPopup">
<div class="delete-project-popup__info-panel-container">
<h2 class="delete-project-popup__info-panel-container__main-label-text">Delete Project</h2>
<div v-html="imageSource"></div>
@ -24,7 +24,7 @@
</div>
<div class="delete-project-popup__form-container__button-container">
<Button label="Cancel" width="205px" height="48px" :onPress="onClose" isWhite/>
<Button label="Cancel" width="205px" height="48px" :onPress="onCloseClick" isWhite/>
<Button
label="Delete Project"
width="205px"
@ -35,7 +35,7 @@
</div>
</div>
<div class="delete-project-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="onClose">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" v-on:click="onCloseClick">
<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>
@ -47,14 +47,10 @@
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import { PROJETS_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS, APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
props: {
onClose: {
type: Function
},
},
data: function () {
return {
projectName: '',
@ -74,20 +70,23 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
}
let response = await this.$store.dispatch(
'deleteProject',
PROJETS_ACTIONS.DELETE,
this.$store.getters.selectedProject.id,
);
if (!response.isSuccess) {
this.$store.dispatch('error', 'Error during project deletion');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Error during project deletion');
return;
}
this.$store.dispatch('clearProjectMembers');
this.$store.dispatch('success', 'Project was successfully deleted');
this.$store.dispatch('fetchProjects');
this.$store.dispatch(PM_ACTIONS.CLEAR);
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Project was successfully deleted');
this.$store.dispatch(PROJETS_ACTIONS.FETCH);
this.$router.push('/');
},
onCloseClick: function (): void {
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_DEL_PROJ);
}
},
computed: {

View File

@ -3,7 +3,7 @@
<template>
<div class="new-project-popup-container">
<div class="new-project-popup">
<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/dashboard/CreateNewProject.png" alt="">
@ -52,13 +52,11 @@ import { Component, Vue } from 'vue-property-decorator';
import HeaderedInput from '@/components/common/HeaderedInput.vue';
import Checkbox from '@/components/common/Checkbox.vue';
import Button from '@/components/common/Button.vue';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PROJETS_ACTIONS } from '@/utils/constants/actionNames';
@Component(
{
props: {
onClose: {
type: Function
},
onCreate: {
type: Function
}
@ -85,8 +83,7 @@ import Button from '@/components/common/Button.vue';
this.$data.termsAcceptedError = false;
},
onCloseClick: function (): void {
// TODO: save popup states in store
this.$emit('onClose');
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
},
createProject: async function (): Promise<any> {
if (!this.$data.isTermsAccepted) {
@ -105,20 +102,20 @@ import Button from '@/components/common/Button.vue';
return;
}
let response = await this.$store.dispatch('createProject', {
let response = await this.$store.dispatch(PROJETS_ACTIONS.CREATE, {
name: this.$data.name,
description: this.$data.description,
isTermsAccepted: this.$data.isTermsAccepted
});
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}
this.$store.dispatch('success', 'Project created successfully!');
this.$emit('onClose');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Project created successfully!');
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_NEW_PROJ);
}
},
components: {

View File

@ -51,7 +51,7 @@
</div>
</div>
</div>
<div class="project-details__button-area">
<div class="project-details__button-area" id="deleteProjectPopupButton">
<Button class="delete-project" label="Delete project" width="180px" height="48px" :onPress="toggleDeleteDialog" isDeletion/>
</div>
</div>
@ -59,9 +59,7 @@
v-if="!isProjectSelected"
mainTitle="Choose or Create new project"
:imageSource="emptyImage" />
<DeleteProjectPopup
v-if="isDeleteDialogShown"
:onClose="toggleDeleteDialog" />
<DeleteProjectPopup v-if="isPopupShown" />
</div>
</template>
@ -72,7 +70,8 @@ import HeaderedInput from '@/components/common/HeaderedInput.vue';
import Checkbox from '@/components/common/Checkbox.vue';
import EmptyState from '@/components/common/EmptyStateArea.vue';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import DeleteProjectPopup from '@/components/projectDetails/DeleteProjectPopup.vue';
import { PROJETS_ACTIONS, APP_STATE_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
import DeleteProjectPopup from '@/components/project/DeleteProjectPopup.vue';
@Component(
{
@ -81,7 +80,6 @@ import DeleteProjectPopup from '@/components/projectDetails/DeleteProjectPopup.v
isEditing: false,
newDescription: '',
emptyImage: EMPTY_STATE_IMAGES.PROJECT,
isDeleteDialogShown: false,
};
},
methods: {
@ -95,7 +93,7 @@ import DeleteProjectPopup from '@/components/projectDetails/DeleteProjectPopup.v
},
onSaveButtonClick: async function (): Promise<any> {
let response = await this.$store.dispatch(
'updateProjectDescription', {
PROJETS_ACTIONS.UPDATE, {
id: this.$store.getters.selectedProject.id,
description: this.$data.newDescription,
}
@ -106,19 +104,21 @@ import DeleteProjectPopup from '@/components/projectDetails/DeleteProjectPopup.v
? (() => {
this.$data.isEditing = !this.$data.isEditing;
this.$data.newDescription = '';
this.$store.dispatch('success', 'Project updated successfully!');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Project updated successfully!');
})()
: this.$store.dispatch('error', response.errorMessage);
: this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
},
toggleDeleteDialog: function (): void {
this.$data.isDeleteDialogShown = !this.$data.isDeleteDialogShown;
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_DEL_PROJ);
}
},
computed: {
name: function (): string {
return this.$store.getters.selectedProject.name;
},
description: function (): string {
return this.$store.getters.selectedProject.description ?
this.$store.getters.selectedProject.description :
'No description yet. Please enter some information about the project if any.';
@ -126,8 +126,13 @@ import DeleteProjectPopup from '@/components/projectDetails/DeleteProjectPopup.v
// this computed is used to indicate if project is selected.
// if false - we should change UI
isProjectSelected: function (): boolean {
return this.$store.getters.selectedProject.id !== '';
},
isPopupShown: function (): boolean {
return this.$store.state.appStateModule.appState.isDeleteProjectPopupShown;
}
},
components: {
Button,

View File

@ -3,7 +3,7 @@
<template>
<div class='add-user-container'>
<div class='add-user'>
<div class='add-user' id="addTeamMemberPopup">
<div class='add-user__info-panel-container'>
<h2 class='add-user__info-panel-container__main-label-text'>Add New User</h2>
<div v-html='imageSource'></div>
@ -59,14 +59,12 @@ import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { removeToken } from '@/utils/tokenManager';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import { EmailInput } from '@/utils/entities/EmailInput';
import { PM_ACTIONS, NOTIFICATION_ACTIONS, APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { EmailInput } from '@/types/EmailInput';
import { validateEmail } from '@/utils/validation';
@Component(
{
props: {
onClose: Function
},
data: function() {
return {
inputs: [new EmailInput(), new EmailInput(), new EmailInput()],
@ -117,24 +115,24 @@ import { validateEmail } from '@/utils/validation';
if (!areAllEmailsValid) return;
let result = await this.$store.dispatch('addProjectMembers', emailArray);
let result = await this.$store.dispatch(PM_ACTIONS.ADD, emailArray);
if (!result.isSuccess) {
this.$store.dispatch('error', 'Error during adding team members!');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Error during adding team members!');
return;
}
const response = await this.$store.dispatch('fetchProjectMembers', { limit: 20, offset: 0 });
const response = await this.$store.dispatch(PM_ACTIONS.FETCH, { limit: 20, offset: 0 });
if (!response.isSuccess) {
this.$store.dispatch('error', 'Unable to fetch project members');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to fetch project members');
return;
}
this.$store.dispatch('success', 'Members successfully added to project!');
this.$store.dispatch('setAddTeamMembersPopup', false);
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Members successfully added to project!');
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_TEAM_MEMBERS);
},
addInput: function(): void {
let inputsLength = this.$data.inputs.length;
@ -153,7 +151,7 @@ import { validateEmail } from '@/utils/validation';
this.$data.inputs[index].setError(false);
},
onClose: function(): void {
this.$store.dispatch('setAddTeamMembersPopup', false);
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_TEAM_MEMBERS);
},
},
computed: {

View File

@ -35,6 +35,7 @@ import HeaderArea from '@/components/team/headerArea/HeaderArea.vue';
import Footer from '@/components/team/footerArea/Footer.vue';
import EmptyState from '@/components/common/EmptyStateArea.vue';
import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
import { PM_ACTIONS } from '@/utils/constants/actionNames';
@Component({
data: function () {
@ -44,7 +45,7 @@ import { EMPTY_STATE_IMAGES } from '@/utils/constants/emptyStatesImages';
},
methods: {
onMemberClick: function (member: any) {
this.$store.dispatch('toggleProjectMemberSelection', member.user.id);
this.$store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, member.user.id);
},
},
computed: {

View File

@ -30,6 +30,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { PM_ACTIONS, NOTIFICATION_ACTIONS } from '@/utils/constants/actionNames';
@Component({
methods: {
@ -38,18 +39,18 @@ import Button from '@/components/common/Button.vue';
return member.user.email;
});
const isSuccess = await this.$store.dispatch('deleteProjectMembers', projectMemberEmails);
const isSuccess = await this.$store.dispatch(PM_ACTIONS.DELETE, projectMemberEmails);
if (!isSuccess) {
this.$store.dispatch('error', 'Error while deleting users from team');
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Error while deleting users from team');
return;
}
this.$store.dispatch('success', 'Members was successfully removed from project');
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Members was successfully removed from project');
},
onClearSelection: function () {
this.$store.dispatch('clearProjectMemberSelection');
this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION);
}
},

View File

@ -5,7 +5,7 @@
<div class="team-header-container">
<SortUsersDropdown />
<SearchArea />
<Button label="Add User" width="240px" height="58px" :onPress="onAddUsersClick" />
<Button label="Add User" width="240px" height="58px" :onPress="onAddUsersClick" id="addTeamMemberPopupButton" />
</div>
</template>
@ -14,11 +14,12 @@ import { Component, Vue } from 'vue-property-decorator';
import SortUsersDropdown from '@/components/team/headerArea/SortUsersDropdown.vue';
import SearchArea from './SearchArea.vue';
import Button from '@/components/common/Button.vue';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
@Component({
methods: {
onAddUsersClick: function(): void {
this.$store.dispatch('setAddTeamMembersPopup', true);
this.$store.dispatch(APP_STATE_ACTIONS.TOGGLE_TEAM_MEMBERS);
}
},
components: {

View File

@ -7,11 +7,12 @@ import ROUTES from '@/utils/constants/routerConstants';
import Login from '@/views/Login.vue';
import Register from '@/views/Register.vue';
import Dashboard from '@/views/Dashboard.vue';
import AccountArea from '@/components/dashboard/account/AccountArea.vue';
import ProjectDetails from '@/components/projectDetails/ProjectDetailsArea.vue';
import AccountArea from '@/components/account/AccountArea.vue';
import ProjectDetails from '@/components/project/ProjectDetailsArea.vue';
import TeamArea from '@/components/team/TeamArea.vue';
import Page404 from '@/components/errors/Page404.vue';
import ApiKeysArea from '@/components/apiKeys/ApiKeysArea.vue';
import DashboardArea from '@/components/dashboard/DashboardArea.vue';
import { getToken } from '@/utils/tokenManager';
Vue.use(Router);
@ -56,7 +57,12 @@ let router = new Router({
path: '/api-keys',
name: 'ApiKeys',
component: ApiKeysArea
}
},
// {
// path: '/',
// name: 'dashboardArea',
// component: DashboardArea
// },
]
},
{

View File

@ -6,21 +6,102 @@ import { APP_STATE_MUTATIONS } from '../mutationConstants';
export const appStateModule = {
state: {
// Object that contains all states of views
currentAppState: {
isAddTeamMembersPopupShown: false
appState: {
isAddTeamMembersPopupShown: false,
isNewProjectPopupShown: false,
isProjectsDropdownShown: false,
isAccountDropdownShown: false,
isDeleteProjectPopupShown: false,
isDeleteAccountPopupShown: false,
},
},
mutations: {
// Mutation changing add team members popup state
[APP_STATE_MUTATIONS.SET_ADD_TEAMMEMBER_POPUP_STATE](state: any, isShown: boolean): void {
state.currentAppState.isAddTeamMembersPopupShown = isShown;
},
// Mutation changing add team members popup visibility
[APP_STATE_MUTATIONS.TOGGLE_ADD_TEAMMEMBER_POPUP](state: any): void {
state.appState.isAddTeamMembersPopupShown = !state.appState.isAddTeamMembersPopupShown;
},
// Mutation changing new project popup visibility
[APP_STATE_MUTATIONS.TOGGLE_NEW_PROJECT_POPUP](state: any): void {
state.appState.isNewProjectPopupShown = !state.appState.isNewProjectPopupShown;
},
// Mutation changing project dropdown visibility
[APP_STATE_MUTATIONS.TOGGLE_PROJECT_DROPDOWN](state: any): void {
state.appState.isProjectsDropdownShown = !state.appState.isProjectsDropdownShown;
},
// Mutation changing account dropdown visibility
[APP_STATE_MUTATIONS.TOGGLE_ACCOUNT_DROPDOWN](state: any): void {
state.appState.isAccountDropdownShown = !state.appState.isAccountDropdownShown;
},
// Mutation changing delete project popup visibility
[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;
},
// Mutation that closes each popup/dropdown
[APP_STATE_MUTATIONS.CLOSE_ALL](state: any): void {
state.appState.isAddTeamMembersPopupShown = false;
state.appState.isNewProjectPopupShown = false;
state.appState.isProjectsDropdownShown = false;
state.appState.isAccountDropdownShown = false;
state.appState.isDeleteProjectPopupShown = false;
state.appState.isDeleteAccountPopupShown = false;
},
},
actions: {
// Commits muttation for changing add team members popup state
setAddTeamMembersPopup: function ({commit}: any, isShown: boolean): void {
commit(APP_STATE_MUTATIONS.SET_ADD_TEAMMEMBER_POPUP_STATE, isShown);
},
// Commits mutation for changing app popups and dropdowns visibility state
toggleAddTeamMembersPopup: function ({commit, state}: any): void {
if (!state.appState.isAddTeamMembersPopupShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_ADD_TEAMMEMBER_POPUP);
},
toggleNewProjectPopup: function ({commit, state}: any): void {
if (!state.appState.isNewProjectPopupShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_NEW_PROJECT_POPUP);
},
toggleProjectsDropdown: function ({commit, state}: any): void {
if (!state.appState.isProjectsDropdownShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_PROJECT_DROPDOWN);
},
toggleAccountDropdown: function ({commit, state}: any): void {
if (!state.appState.isAccountDropdownShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_ACCOUNT_DROPDOWN);
},
toggleDeleteProjectPopup: function ({commit, state}: any): void {
if (!state.appState.isDeleteProjectPopupShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_DELETE_PROJECT_DROPDOWN);
},
toggleDeleteAccountPopup: function ({commit, state}: any): void {
if (!state.appState.isDeleteAccountPopupShown) {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
}
commit(APP_STATE_MUTATIONS.TOGGLE_DELETE_ACCOUNT_DROPDOWN);
},
closePopups: function ({commit}: any): void {
commit(APP_STATE_MUTATIONS.CLOSE_ALL);
},
},
};

View File

@ -3,7 +3,7 @@
import { NOTIFICATION_MUTATIONS } from '../mutationConstants';
import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
import { DelayedNotification } from '@/utils/entities/DelayedNotification';
import { DelayedNotification } from '@/types/DelayedNotification';
export const notificationsModule = {
state: {

View File

@ -83,7 +83,7 @@ export const projectsModule = {
selectProject: function ({commit}: any, projectID: string) {
commit(PROJECTS_MUTATIONS.SELECT, projectID);
},
updateProjectDescription: async function ({commit}: any, updateProjectModel: UpdateProjectModel): Promise<RequestResponse<null>> {
updateProject: async function ({commit}: any, updateProjectModel: UpdateProjectModel): Promise<RequestResponse<null>> {
let response = await updateProjectRequest(updateProjectModel.id, updateProjectModel.description);
if (response.isSuccess) {

View File

@ -34,5 +34,11 @@ export const NOTIFICATION_MUTATIONS = {
};
export const APP_STATE_MUTATIONS = {
SET_ADD_TEAMMEMBER_POPUP_STATE: 'SET_ADD_TEAMMEMBER_POPUP_STATE',
TOGGLE_ADD_TEAMMEMBER_POPUP: 'TOGGLE_ADD_TEAMMEMBER_POPUP',
TOGGLE_NEW_PROJECT_POPUP: 'TOGGLE_NEW_PROJECT_POPUP',
TOGGLE_PROJECT_DROPDOWN: 'TOGGLE_PROJECT_DROPDOWN',
TOGGLE_ACCOUNT_DROPDOWN: 'TOGGLE_ACCOUNT_DROPDOWN',
TOGGLE_DELETE_PROJECT_DROPDOWN: 'TOGGLE_DELETE_PROJECT_DROPDOWN',
TOGGLE_DELETE_ACCOUNT_DROPDOWN: 'TOGGLE_DELETE_ACCOUNT_DROPDOWN',
CLOSE_ALL: 'CLOSE_ALL',
};

View File

@ -0,0 +1,47 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
export const APP_STATE_ACTIONS = {
TOGGLE_TEAM_MEMBERS: 'toggleAddTeamMembersPopup',
TOGGLE_NEW_PROJ : 'toggleNewProjectPopup',
TOGGLE_PROJECTS: 'toggleProjectsDropdown',
TOGGLE_ACCOUNT: 'toggleAccountDropdown',
TOGGLE_DEL_PROJ: 'toggleDeleteProjectPopup',
TOGGLE_DEL_ACCOUNT: 'toggleDeleteAccountPopup',
CLOSE_POPUPS: 'closePopups',
};
export const NOTIFICATION_ACTIONS = {
SUCCESS: 'success',
ERROR: 'error',
NOTIFY: 'notify',
DELETE: 'deleteNotification',
PAUSE: 'pauseNotification',
RESUME: 'resumeNotification',
};
export const PM_ACTIONS = {
ADD: 'addProjectMembers',
DELETE: 'deleteProjectMembers',
TOGGLE_SELECTION: 'toggleProjectMemberSelection',
CLEAR_SELECTION: 'clearProjectMemberSelection',
FETCH: 'fetchProjectMembers',
CLEAR: 'clearProjectMembers'
};
export const PROJETS_ACTIONS = {
FETCH: 'fetchProjects',
CREATE: 'createProject',
SELECT: 'selectProject',
UPDATE: 'updateProject',
DELETE: 'deleteProject',
CLEAR: 'clearProjects',
};
export const USER_ACTIONS = {
UPDATE: 'updateAccount',
CHANGE_PASSWORD: 'changePassword',
DELETE: 'deleteAccount',
GET: 'getUser',
CLEAR: 'clearUser',
};

View File

@ -2,20 +2,20 @@
// See LICENSE for copying information.
const NAVIGATION_ITEMS = {
DASHBOARD: {
label: 'Dashboard',
path: '/dashboard',
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.9535 4.1849C23.1974 3.94097 23.604 3.94097 23.8479 4.1849C24.0918 4.42882 24.0918 4.83536 23.8479 4.99798L19.8638 9.22602V7.43723L22.9535 4.1849ZM3.52035 14.0232C3.60165 14.1045 3.76427 14.1858 3.92689 14.1858C4.08951 14.1858 4.25212 14.1045 4.25212 14.0232L8.8867 9.38865C9.04932 9.22603 9.29324 9.14472 9.45586 9.14472C9.69979 9.14472 9.8624 9.22603 10.025 9.38865L13.3587 12.8849C13.7652 13.2914 14.2531 13.5354 14.8222 13.5354C15.3914 13.5354 15.8792 13.2914 16.2858 12.8849L19.7822 9.23804V15.4056C19.8636 16.1374 19.2131 16.7879 18.4813 16.7879H2.38224C1.56916 16.7879 1 16.1374 1 15.4056V5.6486C1 4.83552 1.65047 4.26636 2.38224 4.26636H18.4C19.2131 4.26636 19.7822 4.91682 19.7822 5.6486V7.51567L15.4727 12.1531C15.3101 12.3157 15.1474 12.3971 14.9035 12.3971C14.6596 12.3971 14.497 12.3157 14.3344 12.1531L11.0007 8.65687C10.5942 8.25033 10.1063 8.0064 9.53717 8.0064C9.04932 8.0064 8.48016 8.16902 8.15493 8.49425L3.52035 13.1288C3.27642 13.3728 3.27642 13.7793 3.52035 14.0232ZM15.5543 21.341H5.2281C4.90287 21.341 4.57764 21.097 4.57764 20.6905C4.57764 20.284 4.82156 20.04 5.2281 20.04H15.5543C15.8795 20.04 16.2047 20.284 16.2047 20.6905C16.2047 21.097 15.8795 21.341 15.5543 21.341Z" fill="#354049"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>`
},
// DASHBOARD: {
// label: 'Dashboard',
// path: '/',
// svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
// <g clip-path="url(#clip0)">
// <path fill-rule="evenodd" clip-rule="evenodd" d="M22.9535 4.1849C23.1974 3.94097 23.604 3.94097 23.8479 4.1849C24.0918 4.42882 24.0918 4.83536 23.8479 4.99798L19.8638 9.22602V7.43723L22.9535 4.1849ZM3.52035 14.0232C3.60165 14.1045 3.76427 14.1858 3.92689 14.1858C4.08951 14.1858 4.25212 14.1045 4.25212 14.0232L8.8867 9.38865C9.04932 9.22603 9.29324 9.14472 9.45586 9.14472C9.69979 9.14472 9.8624 9.22603 10.025 9.38865L13.3587 12.8849C13.7652 13.2914 14.2531 13.5354 14.8222 13.5354C15.3914 13.5354 15.8792 13.2914 16.2858 12.8849L19.7822 9.23804V15.4056C19.8636 16.1374 19.2131 16.7879 18.4813 16.7879H2.38224C1.56916 16.7879 1 16.1374 1 15.4056V5.6486C1 4.83552 1.65047 4.26636 2.38224 4.26636H18.4C19.2131 4.26636 19.7822 4.91682 19.7822 5.6486V7.51567L15.4727 12.1531C15.3101 12.3157 15.1474 12.3971 14.9035 12.3971C14.6596 12.3971 14.497 12.3157 14.3344 12.1531L11.0007 8.65687C10.5942 8.25033 10.1063 8.0064 9.53717 8.0064C9.04932 8.0064 8.48016 8.16902 8.15493 8.49425L3.52035 13.1288C3.27642 13.3728 3.27642 13.7793 3.52035 14.0232ZM15.5543 21.341H5.2281C4.90287 21.341 4.57764 21.097 4.57764 20.6905C4.57764 20.284 4.82156 20.04 5.2281 20.04H15.5543C15.8795 20.04 16.2047 20.284 16.2047 20.6905C16.2047 21.097 15.8795 21.341 15.5543 21.341Z" fill="#354049"/>
// </g>
// <defs>
// <clipPath id="clip0">
// <rect width="24" height="24" fill="white"/>
// </clipPath>
// </defs>
// </svg>`
// },
PROJECT_DETAILS: {
label: 'Project Details',
path: '/project-details',
@ -56,14 +56,14 @@ const NAVIGATION_ITEMS = {
</defs>
</svg>`
},
HELP: {
label: 'Help',
path: '/help',
svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18.8333 3.56068H7.0359C5.11538 3.56068 3.56068 5.11538 3.56068 7.0359V16.7299L1.91453 18.1932V6.85299C1.91453 4.1094 4.1094 2.00598 6.85299 2.00598H16.1812C16.7299 2.00598 17.1872 2.18889 17.6444 2.46325C17.8274 2.64615 18.1932 2.5547 18.3761 2.37179C18.559 2.18889 18.4675 1.82308 18.2846 1.64017C17.6444 1.18291 17.0043 1 16.2727 1H6.94444C3.65214 1 1 3.65214 1 6.85299V19.2906C1 19.4735 1.09145 19.6564 1.27436 19.7479C1.45726 19.8393 1.64017 19.7479 1.82308 19.6564L3.56068 18.1017V21.8513C3.56068 22.0342 3.65214 22.2171 3.83504 22.3085C3.9265 22.3085 3.9265 22.3085 4.01795 22.3085C4.1094 22.3085 4.29231 22.3085 4.38376 22.2171L7.31026 19.565C7.40171 19.4735 7.49316 19.3821 7.58462 19.3821C7.76752 19.2906 7.85897 19.1077 7.85897 19.1077C7.85897 19.1077 8.04188 19.1077 8.22479 19.1077C8.31624 19.1077 8.40769 19.1077 8.5906 19.1077H18.7419C20.6624 19.1077 22.2171 17.553 22.2171 15.6325V7.0359C22.2171 5.11538 20.7538 3.56068 18.8333 3.56068ZM17.7359 14.0778C17.2786 14.9009 16.6385 15.2667 16.1812 14.9923L15.541 14.7179C15.2667 14.9009 14.9923 15.0838 14.6265 15.2667L14.535 16.0897C14.535 16.6385 13.8949 16.9128 12.9803 16.9128C12.0658 16.9128 11.4256 16.547 11.4256 16.0897L11.3342 15.2667C10.9684 15.1752 10.694 14.9923 10.4197 14.7179L9.68803 15.0838C9.50513 15.1752 9.13932 15.2667 8.7735 14.9009C8.5906 14.7179 8.31624 14.4436 8.22479 14.1692C7.76752 13.3462 7.67607 12.6145 8.13333 12.3402L8.7735 11.8829C8.7735 11.7 8.7735 11.5171 8.7735 11.3342C8.7735 11.1513 8.7735 10.9684 8.7735 10.7855L8.13333 10.3282C7.67607 10.0538 7.76752 9.32222 8.22479 8.49915C8.40769 8.22479 8.5906 7.95043 8.7735 7.76752C9.23077 7.40171 9.50513 7.49316 9.68803 7.58462L10.4197 7.95043C10.694 7.76752 10.9684 7.58462 11.3342 7.40171L11.4256 6.57863C11.4256 6.02991 12.0658 5.75556 12.9803 5.75556C13.9863 5.75556 14.535 6.12137 14.535 6.57863L14.6265 7.40171C14.9923 7.58462 15.2667 7.67607 15.541 7.95043L16.2727 7.58462C16.7299 7.31026 17.2786 7.67607 17.8274 8.49915C18.0103 8.7735 18.1017 9.13932 18.1932 9.41368C18.2846 9.96239 18.1017 10.2368 17.9188 10.3282L17.2786 10.7855C17.2786 10.9684 17.2786 11.1513 17.2786 11.3342C17.2786 11.5171 17.2786 11.7 17.2786 11.8829L17.9188 12.3402C18.2846 12.6145 18.2846 13.2547 17.7359 14.0778Z" fill="#354049"/>
<path d="M12.8893 13.2551C13.9499 13.2551 14.8098 12.3952 14.8098 11.3346C14.8098 10.2739 13.9499 9.41406 12.8893 9.41406C11.8286 9.41406 10.9688 10.2739 10.9688 11.3346C10.9688 12.3952 11.8286 13.2551 12.8893 13.2551Z" fill="#354049"/>
</svg>`
}
// HELP: {
// label: 'Help',
// path: '/help',
// svg: `<svg class="svg" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
// <path d="M18.8333 3.56068H7.0359C5.11538 3.56068 3.56068 5.11538 3.56068 7.0359V16.7299L1.91453 18.1932V6.85299C1.91453 4.1094 4.1094 2.00598 6.85299 2.00598H16.1812C16.7299 2.00598 17.1872 2.18889 17.6444 2.46325C17.8274 2.64615 18.1932 2.5547 18.3761 2.37179C18.559 2.18889 18.4675 1.82308 18.2846 1.64017C17.6444 1.18291 17.0043 1 16.2727 1H6.94444C3.65214 1 1 3.65214 1 6.85299V19.2906C1 19.4735 1.09145 19.6564 1.27436 19.7479C1.45726 19.8393 1.64017 19.7479 1.82308 19.6564L3.56068 18.1017V21.8513C3.56068 22.0342 3.65214 22.2171 3.83504 22.3085C3.9265 22.3085 3.9265 22.3085 4.01795 22.3085C4.1094 22.3085 4.29231 22.3085 4.38376 22.2171L7.31026 19.565C7.40171 19.4735 7.49316 19.3821 7.58462 19.3821C7.76752 19.2906 7.85897 19.1077 7.85897 19.1077C7.85897 19.1077 8.04188 19.1077 8.22479 19.1077C8.31624 19.1077 8.40769 19.1077 8.5906 19.1077H18.7419C20.6624 19.1077 22.2171 17.553 22.2171 15.6325V7.0359C22.2171 5.11538 20.7538 3.56068 18.8333 3.56068ZM17.7359 14.0778C17.2786 14.9009 16.6385 15.2667 16.1812 14.9923L15.541 14.7179C15.2667 14.9009 14.9923 15.0838 14.6265 15.2667L14.535 16.0897C14.535 16.6385 13.8949 16.9128 12.9803 16.9128C12.0658 16.9128 11.4256 16.547 11.4256 16.0897L11.3342 15.2667C10.9684 15.1752 10.694 14.9923 10.4197 14.7179L9.68803 15.0838C9.50513 15.1752 9.13932 15.2667 8.7735 14.9009C8.5906 14.7179 8.31624 14.4436 8.22479 14.1692C7.76752 13.3462 7.67607 12.6145 8.13333 12.3402L8.7735 11.8829C8.7735 11.7 8.7735 11.5171 8.7735 11.3342C8.7735 11.1513 8.7735 10.9684 8.7735 10.7855L8.13333 10.3282C7.67607 10.0538 7.76752 9.32222 8.22479 8.49915C8.40769 8.22479 8.5906 7.95043 8.7735 7.76752C9.23077 7.40171 9.50513 7.49316 9.68803 7.58462L10.4197 7.95043C10.694 7.76752 10.9684 7.58462 11.3342 7.40171L11.4256 6.57863C11.4256 6.02991 12.0658 5.75556 12.9803 5.75556C13.9863 5.75556 14.535 6.12137 14.535 6.57863L14.6265 7.40171C14.9923 7.58462 15.2667 7.67607 15.541 7.95043L16.2727 7.58462C16.7299 7.31026 17.2786 7.67607 17.8274 8.49915C18.0103 8.7735 18.1017 9.13932 18.1932 9.41368C18.2846 9.96239 18.1017 10.2368 17.9188 10.3282L17.2786 10.7855C17.2786 10.9684 17.2786 11.1513 17.2786 11.3342C17.2786 11.5171 17.2786 11.7 17.2786 11.8829L17.9188 12.3402C18.2846 12.6145 18.2846 13.2547 17.7359 14.0778Z" fill="#354049"/>
// <path d="M12.8893 13.2551C13.9499 13.2551 14.8098 12.3952 14.8098 11.3346C14.8098 10.2739 13.9499 9.41406 12.8893 9.41406C11.8286 9.41406 10.9688 10.2739 10.9688 11.3346C10.9688 12.3952 11.8286 13.2551 12.8893 13.2551Z" fill="#354049"/>
// </svg>`
// }
};
export default NAVIGATION_ITEMS;

View File

@ -1,36 +0,0 @@
// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information.
import apollo from '../apolloManager';
import gql from 'graphql-tag';
// TODO: all graphql queries should be totally refactored
// Performs graqhQL request.
// Throws an exception if error occurs
export async function createProject(project: Project): Promise<any> {
let response = apollo.mutate(
{
mutation: gql(`
mutation {
createProject(
input: {
name: "${project.name}",
description: "${project.description}",
isTermsAccepted: ${project.isTermsAccepted},
}
)
}`
),
fetchPolicy: 'no-cache',
}
);
if (!response) {
// TODO: replace with popup in future
console.error('cannot create user');
return null;
}
return response;
}

View File

@ -15,28 +15,40 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import DashboardHeader from '@/components/dashboard/DashboardHeader.vue';
import DashboardHeader from '@/components/header/Header.vue';
import NavigationArea from '@/components/navigation/NavigationArea.vue';
import { removeToken } from '@/utils/tokenManager';
import { NOTIFICATION_ACTIONS, PROJETS_ACTIONS, PM_ACTIONS, USER_ACTIONS } from '@/utils/constants/actionNames';
@Component({
beforeMount: async function() {
// TODO: should place here some animation while all needed data is fetching
let response: RequestResponse<User> = await this.$store.dispatch('getUser');
let response: RequestResponse<User> = await this.$store.dispatch(USER_ACTIONS.GET);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
this.$router.push('/login');
removeToken();
return;
}
let getProjectsResponse: RequestResponse<Project[]> = await this.$store.dispatch('fetchProjects');
let getProjectsResponse: RequestResponse<Project[]> = await this.$store.dispatch(PROJETS_ACTIONS.FETCH);
if (getProjectsResponse.isSuccess && getProjectsResponse.data.length > 0) {
this.$store.dispatch('selectProject', getProjectsResponse.data[0].id);
if (!getProjectsResponse.isSuccess || getProjectsResponse.data.length < 1) {
return;
}
this.$store.dispatch(PROJETS_ACTIONS.SELECT, getProjectsResponse.data[0].id);
if (!this.$store.getters.selectedProject.id) return;
const projectMembersResponse = await this.$store.dispatch(PM_ACTIONS.FETCH, {limit: 20, offset: 0});
if (projectMembersResponse.isSuccess) return;
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, 'Unable to fetch project members');
},
components: {
NavigationArea,

View File

@ -45,6 +45,7 @@ import HeaderlessInput from '@/components/common/HeaderlessInput.vue';
import Button from '@/components/common/Button.vue';
import { setToken } from '@/utils/tokenManager';
import ROUTES from '../utils/constants/routerConstants';
import { NOTIFICATION_ACTIONS } from '../utils/constants/actionNames';
import { getTokenRequest } from '@/api/users';
@Component({
@ -66,7 +67,7 @@ import { getTokenRequest } from '@/api/users';
onLogin: async function () {
let loginResponse = await getTokenRequest(this.$data.email, this.$data.password);
if (!loginResponse.isSuccess) {
this.$store.dispatch('error', loginResponse.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, loginResponse.errorMessage);
return;
}

View File

@ -79,6 +79,7 @@ import Checkbox from '@/components/common/Checkbox.vue';
import Button from '@/components/common/Button.vue';
import { validateEmail, validatePassword } from '@/utils/validation';
import ROUTES from '../utils/constants/routerConstants';
import { NOTIFICATION_ACTIONS } from '../utils/constants/actionNames';
import { createUserRequest } from '@/api/users';
@Component(
@ -148,7 +149,7 @@ import { createUserRequest } from '@/api/users';
let response = await createUserRequest(user, this.$data.password);
if (!response.isSuccess) {
this.$store.dispatch('error', response.errorMessage);
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, response.errorMessage);
return;
}

View File

@ -4,7 +4,7 @@
import { shallowMount, mount } from '@vue/test-utils';
import NotificationArea from '@/components/notifications/NotificationArea.vue';
import { NOTIFICATION_TYPES } from '@/utils/constants/notification';
import { DelayedNotification } from '@/utils/entities/DelayedNotification';
import { DelayedNotification } from '@/types/DelayedNotification';
describe('Notification.vue', () => {