fix: teams edit modal + race conditions on currentUser

This commit is contained in:
Liyas Thomas
2021-05-14 03:40:53 +00:00
committed by GitHub
parent e7dd67deaa
commit 4656d67fcf
8 changed files with 59 additions and 151 deletions

View File

@@ -33,7 +33,7 @@
</div> </div>
</li> </li>
</ul> </ul>
<ul v-for="(member, index) in teamMembers" :key="`new-${index}`"> <ul v-for="(member, index) in members" :key="`new-${index}`">
<li> <li>
<input <input
:placeholder="$t('email')" :placeholder="$t('email')"
@@ -84,7 +84,7 @@
</li> </li>
</div> </div>
</ul> </ul>
<ul v-for="(member, index) in members" :key="index"> <ul v-for="(member, index) in newMembers" :key="index">
<li> <li>
<input <input
:placeholder="$t('email')" :placeholder="$t('email')"
@@ -164,122 +164,9 @@
<script> <script>
import * as team_utils from "~/helpers/teams/utils" import * as team_utils from "~/helpers/teams/utils"
import gql from "graphql-tag" import cloneDeep from "lodash/cloneDeep"
export default { export default {
apollo: {
teamMembers: {
query: gql`
query GetMyTeams {
myTeams {
id
members {
user {
displayName
email
uid
}
role
}
}
}
`,
subscribeToMore: [
{
document: gql`
subscription teamMemberAdded($teamID: String!) {
teamMemberAdded(teamID: $teamID) {
role
user {
displayName
email
uid
}
}
}
`,
variables() {
return { teamID: this.$props.editingteamID }
},
skip() {
return this.$props.editingteamID === ""
},
updateQuery(previousResult, { subscriptionData }) {
const teamIdx = previousResult.myTeams.findIndex(
(x) => x.id === this.$props.editingteamID
)
previousResult.myTeams[teamIdx].members.push(subscriptionData.data.teamMemberAdded)
return previousResult
},
},
{
document: gql`
subscription teamMemberUpdated($teamID: String!) {
teamMemberUpdated(teamID: $teamID) {
role
user {
displayName
email
uid
}
}
}
`,
variables() {
return { teamID: this.$props.editingteamID }
},
skip() {
return this.$props.editingteamID === ""
},
updateQuery(previousResult, { subscriptionData }) {
const teamIdx = previousResult.myTeams.findIndex(
(x) => x.id === this.$props.editingteamID
)
const memberIdx = previousResult.myTeams[teamIdx].members.findIndex(
(x) => x.user.uid === subscriptionData.data.teamMemberUpdated.user.uid
)
previousResult.myTeams[teamIdx].members[memberIdx].user =
subscriptionData.data.teamMemberUpdated.user
previousResult.myTeams[teamIdx].members[memberIdx].role =
subscriptionData.data.teamMemberUpdated.role
return previousResult
},
},
{
document: gql`
subscription teamMemberRemoved($teamID: String!) {
teamMemberRemoved(teamID: $teamID)
}
`,
variables() {
return { teamID: this.$props.editingteamID }
},
skip() {
return this.$props.editingteamID === ""
},
updateQuery(previousResult, { subscriptionData }) {
const teamIdx = previousResult.myTeams.findIndex(
(x) => x.id === this.$props.editingteamID
)
const memberIdx = previousResult.myTeams[teamIdx].members.findIndex(
(x) => x.user.id === subscriptionData.data.teamMemberRemoved.id
)
if (memberIdx !== -1) previousResult.myTeams[teamIdx].members.splice(memberIdx, 1)
return previousResult
},
},
],
update(response) {
const teamIdx = response.myTeams.findIndex((x) => x.id === this.$props.editingteamID)
return response.myTeams[teamIdx].members
},
skip() {
return this.$props.editingteamID === ""
},
},
},
props: { props: {
show: Boolean, show: Boolean,
editingTeam: Object, editingTeam: Object,
@@ -292,6 +179,7 @@ export default {
members: [], members: [],
membersSubject: null, membersSubject: null,
membersSubscription: null, membersSubscription: null,
newMembers: [],
} }
}, },
watch: { watch: {
@@ -301,7 +189,7 @@ export default {
this.membersSubscription = this.membersSubject.subscribe((memberList) => { this.membersSubscription = this.membersSubject.subscribe((memberList) => {
console.log(memberList) console.log(memberList)
this.members = memberList this.members = cloneDeep(memberList)
}) })
}) })
}, },
@@ -321,11 +209,12 @@ export default {
}, },
methods: { methods: {
updateRole(id, role) { updateRole(id, role) {
this.teamMembers[id].role = role console.log(this.members, id)
this.members[id].role = role
}, },
addTeamMember() { addTeamMember() {
let value = { key: "", value: "" } let value = { key: "", value: "" }
this.members.push(value) this.newMembers.push(value)
console.log("addTeamMember") console.log("addTeamMember")
}, },
removeExistingTeamMember(userID) { removeExistingTeamMember(userID) {
@@ -347,7 +236,7 @@ export default {
}) })
}, },
removeTeamMember(index) { removeTeamMember(index) {
this.members.splice(index, 1) this.newMembers.splice(index, 1)
console.log("removeTeamMember") console.log("removeTeamMember")
}, },
validateEmail(emailID) { validateEmail(emailID) {
@@ -364,8 +253,7 @@ export default {
console.log("String length less than 6") console.log("String length less than 6")
return return
} }
console.log("saveTeam", this.members) this.$data.newMembers.forEach((element) => {
this.$data.members.forEach((element) => {
if (!this.validateEmail(element.key)) { if (!this.validateEmail(element.key)) {
this.$toast.error(this.$t("invalid_emailID_format"), { this.$toast.error(this.$t("invalid_emailID_format"), {
icon: "error", icon: "error",
@@ -374,7 +262,7 @@ export default {
return return
} }
}) })
this.$data.members.forEach((element) => { this.$data.newMembers.forEach((element) => {
// Call to the graphql mutation // Call to the graphql mutation
team_utils team_utils
.addTeamMemberByEmail(this.$apollo, element.value, element.key, this.editingteamID) .addTeamMemberByEmail(this.$apollo, element.value, element.key, this.editingteamID)
@@ -394,7 +282,7 @@ export default {
}) })
}) })
let messageShown = true let messageShown = true
this.teamMembers.forEach((element) => { this.members.forEach((element) => {
team_utils team_utils
.updateTeamMemberRole(this.$apollo, element.user.uid, element.role, this.editingteamID) .updateTeamMemberRole(this.$apollo, element.user.uid, element.role, this.editingteamID)
.then((data) => { .then((data) => {
@@ -444,7 +332,7 @@ export default {
}) })
} }
this.hideModal() this.hideModal()
this.members = [] this.newMembers = []
}, },
hideModal() { hideModal() {
this.$emit("hide-modal") this.$emit("hide-modal")

View File

@@ -4,7 +4,7 @@
<button <button
class="icon" class="icon"
@click="team.myRole === 'OWNER' ? $emit('edit-team') : ''" @click="team.myRole === 'OWNER' ? $emit('edit-team') : ''"
v-tooltip.right="$t('edit')" v-tooltip.right="team.myRole === 'OWNER' ? $t('edit') : ''"
> >
<i class="material-icons">group</i> <i class="material-icons">group</i>
<span>{{ team.name }}</span> <span>{{ team.name }}</span>

View File

@@ -1,9 +1,5 @@
<template> <template>
<AppSection class="green" icon="history" :label="$t('teams')" ref="teams" no-legend> <AppSection class="green" icon="history" :label="$t('teams')" ref="teams" no-legend>
<!-- debug start -->
<pre>me: {{ me }}</pre>
<pre>myTeams: {{ myTeams }}</pre>
<!-- debug end -->
<TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" /> <TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
<TeamsEdit <TeamsEdit
:team="myTeams[0]" :team="myTeams[0]"
@@ -12,11 +8,11 @@
:editingteamID="editingteamID" :editingteamID="editingteamID"
@hide-modal="displayModalEdit(false)" @hide-modal="displayModalEdit(false)"
/> />
<TeamsImportExport <!-- <TeamsImportExport
:show="showModalImportExport" :show="showModalImportExport"
:teams="myTeams" :teams="myTeams"
@hide-modal="displayModalImportExport(false)" @hide-modal="displayModalImportExport(false)"
/> /> -->
<div class="row-wrapper"> <div class="row-wrapper">
<div> <div>
<button class="icon" @click="displayModalAdd(true)"> <button class="icon" @click="displayModalAdd(true)">
@@ -24,11 +20,11 @@
<span>{{ $t("new") }}</span> <span>{{ $t("new") }}</span>
</button> </button>
</div> </div>
<div> <!-- <div>
<button class="icon" @click="displayModalImportExport(true)"> <button class="icon" @click="displayModalImportExport(true)">
{{ $t("import_export") }} {{ $t("import_export") }}
</button> </button>
</div> </div> -->
</div> </div>
<p v-if="$apollo.queries.myTeams.loading" class="info">{{ $t("loading") }}</p> <p v-if="$apollo.queries.myTeams.loading" class="info">{{ $t("loading") }}</p>
<p v-if="myTeams.length === 0" class="info"> <p v-if="myTeams.length === 0" class="info">
@@ -76,6 +72,7 @@ export default {
query GetMe { query GetMe {
me { me {
uid uid
eaInvited
} }
} }
`, `,

View File

@@ -4,15 +4,27 @@ import { setContext } from "@apollo/client/link/context"
import { fb } from "./fb" import { fb } from "./fb"
import { getMainDefinition } from "@apollo/client/utilities" import { getMainDefinition } from "@apollo/client/utilities"
let authToken: String | null = null
export function registerApolloAuthUpdate() {
fb.idToken$.subscribe((token: String | null) => {
console.log(token, "from sub")
authToken = token
})
}
/** /**
* Injects auth token if available * Injects auth token if available
*/ */
const authLink = setContext((_, { headers }) => { const authLink = setContext((_, { headers }) => {
if (fb.idToken) { console.log(authToken)
if (authToken) {
return { return {
headers: { headers: {
...headers, ...headers,
authorization: `Bearer ${fb.idToken}`, authorization: `Bearer ${authToken}`,
}, },
} }
} else { } else {
@@ -38,11 +50,11 @@ const wsLink = new WebSocketLink({
reconnect: true, reconnect: true,
lazy: true, lazy: true,
connectionParams: () => { connectionParams: () => {
if (fb.idToken) { if (authToken) {
return {} return {}
} else { } else {
return { return {
authorization: `Bearer ${fb.idToken}`, authorization: `Bearer ${authToken}`,
} }
} }
}, },

View File

@@ -42,12 +42,14 @@ export const currentUserInfo$ = new BehaviorSubject<UserInfo | null>(null)
/** /**
* Initializes the currenUserInfo$ view and sets up its update mechanism * Initializes the currenUserInfo$ view and sets up its update mechanism
*/ */
export function initUserInfo() { export async function initUserInfo() {
updateUserInfo() await updateUserInfo()
console.log("updated")
fb.idToken$.subscribe(token => { fb.idToken$.subscribe((token) => {
if (token) { if (token) {
updateUserInfo() updateUserInfo()
console.log(token, "updateUserInfo")
} else { } else {
currentUserInfo$.next(null) currentUserInfo$.next(null)
} }
@@ -63,22 +65,24 @@ async function updateUserInfo() {
query: gql` query: gql`
query GetUserInfo { query GetUserInfo {
me { me {
uid, uid
displayName, displayName
email, email
photoURL, photoURL
eaInvited eaInvited
} }
} }
` `,
}) })
console.log(data)
currentUserInfo$.next({ currentUserInfo$.next({
uid: data.me.uid, uid: data.me.uid,
displayName: data.me.displayName, displayName: data.me.displayName,
email: data.me.email, email: data.me.email,
photoURL : data.me.photoURL, photoURL: data.me.photoURL,
eaInvited: data.me.eaInvited eaInvited: data.me.eaInvited,
}) })
} catch (e) { } catch (e) {
currentUserInfo$.next(null) currentUserInfo$.next(null)

View File

@@ -32,7 +32,6 @@ export async function getLiveTeamMembersList(apollo, teamID) {
}, },
}) })
debugger
subject.next(data.team.members) subject.next(data.team.members)
const addedSub = apollo const addedSub = apollo
@@ -53,6 +52,7 @@ export async function getLiveTeamMembersList(apollo, teamID) {
}, },
}) })
.subscribe(({ data }) => { .subscribe(({ data }) => {
console.log(data)
subject.next([...subject.value, data.teamMemberAdded]) subject.next([...subject.value, data.teamMemberAdded])
}) })

View File

@@ -17,9 +17,12 @@
import { setupLocalPersistence } from "~/newstore/localpersistence" import { setupLocalPersistence } from "~/newstore/localpersistence"
import { performMigrations } from "~/helpers/migrations" import { performMigrations } from "~/helpers/migrations"
import { initUserInfo } from "~/helpers/teams/BackendUserInfo" import { initUserInfo } from "~/helpers/teams/BackendUserInfo"
import { registerApolloAuthUpdate } from "~/helpers/apollo"
export default { export default {
beforeMount() { beforeMount() {
registerApolloAuthUpdate()
let color = localStorage.getItem("THEME_COLOR") || "green" let color = localStorage.getItem("THEME_COLOR") || "green"
document.documentElement.setAttribute("data-accent", color) document.documentElement.setAttribute("data-accent", color)
}, },

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="page"> <div class="page">
<div v-if="fb.currentUser"> <div v-if="currentUser && currentUser.eaInvited">
<Teams /> <Teams />
</div> </div>
@@ -202,6 +202,7 @@ import {
defaultSettings, defaultSettings,
} from "~/newstore/settings" } from "~/newstore/settings"
import type { KeysMatching } from "~/types/ts-utils" import type { KeysMatching } from "~/types/ts-utils"
import { currentUserInfo$ } from "~/helpers/teams/BackendUserInfo"
import Vue from "vue" import Vue from "vue"
@@ -243,6 +244,9 @@ export default Vue.extend({
SYNC_COLLECTIONS: getSettingSubject("syncCollections"), SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"), SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
SYNC_HISTORY: getSettingSubject("syncHistory"), SYNC_HISTORY: getSettingSubject("syncHistory"),
// Teams feature flag
currentUser: currentUserInfo$,
} }
}, },
watch: { watch: {