"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "packages/hoppscotch-app/components/teams/Edit.vue" between
hoppscotch-2.2.1.tar.gz and hoppscotch-3.0.0.tar.gz

About: Hoppscotch is a light-weight, web based API development suite.

Edit.vue  (hoppscotch-2.2.1):Edit.vue  (hoppscotch-3.0.0)
<template> <template>
<SmartModal v-if="show" :title="t('team.edit')" @close="hideModal"> <SmartModal v-if="show" dialog :title="t('team.edit')" @close="hideModal">
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col">
<div class="relative flex"> <div class="relative flex">
<input <input
id="selectLabelTeamEdit" id="selectLabelTeamEdit"
v-model="name" v-model="name"
v-focus v-focus
class="input floating-input" class="input floating-input"
placeholder=" " placeholder=" "
type="text" type="text"
autocomplete="off" autocomplete="off"
@keyup.enter="saveTeam" @keyup.enter="saveTeam"
skipping to change at line 26 skipping to change at line 26
<label for="selectLabelTeamEdit"> <label for="selectLabelTeamEdit">
{{ t("action.label") }} {{ t("action.label") }}
</label> </label>
</div> </div>
<div class="flex items-center justify-between flex-1 pt-4"> <div class="flex items-center justify-between flex-1 pt-4">
<label for="memberList" class="p-4"> <label for="memberList" class="p-4">
{{ t("team.members") }} {{ t("team.members") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
svg="user-plus" :icon="IconUserPlus"
:label="t('team.invite')" :label="t('team.invite')"
filled filled
@click.native=" @click="
() => { () => {
$emit('invite-team') emit('invite-team')
} }
" "
/> />
</div> </div>
</div> </div>
<div <div
v-if="teamDetails.loading" v-if="teamDetails.loading"
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
<SmartSpinner class="mb-4" /> <SmartSpinner class="mb-4" />
<span class="text-secondaryLight">{{ t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
<div <div
v-if=" v-if="
!teamDetails.loading && !teamDetails.loading &&
E.isRight(teamDetails.data) && E.isRight(teamDetails.data) &&
teamDetails.data.right.team.teamMembers teamDetails.data.right.team.teamMembers
" "
class="border divide-y rounded divide-dividerLight border-divider" class="border rounded divide-y divide-dividerLight border-divider"
> >
<div <div
v-if="teamDetails.data.right.team.teamMembers === 0" v-if="teamDetails.data.right.team.teamMembers === 0"
class="flex flex-col items-center justify-center p-4 text-secondaryL ight" class="flex flex-col items-center justify-center p-4 text-secondaryL ight"
> >
<img <img
:src="`/images/states/${$colorMode.value}/add_group.svg`" :src="`/images/states/${colorMode.value}/add_group.svg`"
loading="lazy" loading="lazy"
class="inline-flex flex-col object-contain object-center w-16 h-16 my-4" class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
:alt="`${t('empty.members')}`" :alt="`${t('empty.members')}`"
/> />
<span class="pb-4 text-center"> <span class="pb-4 text-center">
{{ t("empty.members") }} {{ t("empty.members") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
svg="user-plus" :icon="IconUserPlus"
:label="t('team.invite')" :label="t('team.invite')"
@click.native=" @click="
() => { () => {
emit('invite-team') emit('invite-team')
} }
" "
/> />
</div> </div>
<div v-else> <div v-else>
<div <div
v-for="(member, index) in membersList" v-for="(member, index) in membersList"
:key="`member-${index}`" :key="`member-${index}`"
skipping to change at line 96 skipping to change at line 96
readonly readonly
/> />
<span> <span>
<tippy <tippy
ref="memberOptions" ref="memberOptions"
interactive interactive
trigger="click" trigger="click"
theme="popover" theme="popover"
arrow arrow
> >
<template #trigger> <span class="select-wrapper">
<span class="select-wrapper"> <input
<input class="flex flex-1 px-4 py-2 bg-transparent cursor-pointer
class="flex flex-1 px-4 py-2 bg-transparent cursor-point "
er" :placeholder="`${t('team.permissions')}`"
:placeholder="`${t('team.permissions')}`" :name="'value' + index"
:name="'value' + index" :value="member.role"
:value="member.role" readonly
readonly />
</span>
<template #content="{ hide }">
<div
class="flex flex-col"
tabindex="0"
role="menu"
@keyup.escape="hide()"
>
<SmartItem
label="OWNER"
:icon="
member.role === 'OWNER' ? IconCircleDot : IconCircle
"
:active="member.role === 'OWNER'"
@click="
() => {
updateMemberRole(member.userID, 'OWNER')
hide()
}
"
/>
<SmartItem
label="EDITOR"
:icon="
member.role === 'EDITOR' ? IconCircleDot : IconCircle
"
:active="member.role === 'EDITOR'"
@click="
() => {
updateMemberRole(member.userID, 'EDITOR')
hide()
}
"
/>
<SmartItem
label="VIEWER"
:icon="
member.role === 'VIEWER' ? IconCircleDot : IconCircle
"
:active="member.role === 'VIEWER'"
@click="
() => {
updateMemberRole(member.userID, 'VIEWER')
hide()
}
"
/> />
</span> </div>
</template> </template>
<SmartItem
label="OWNER"
:icon="
member.role === 'OWNER'
? 'radio_button_checked'
: 'radio_button_unchecked'
"
:active="member.role === 'OWNER'"
@click.native="
() => {
updateMemberRole(member.userID, 'OWNER')
memberOptions[index].tippy().hide()
}
"
/>
<SmartItem
label="EDITOR"
:icon="
member.role === 'EDITOR'
? 'radio_button_checked'
: 'radio_button_unchecked'
"
:active="member.role === 'EDITOR'"
@click.native="
() => {
updateMemberRole(member.userID, 'EDITOR')
memberOptions[index].tippy().hide()
}
"
/>
<SmartItem
label="VIEWER"
:icon="
member.role === 'VIEWER'
? 'radio_button_checked'
: 'radio_button_unchecked'
"
:active="member.role === 'VIEWER'"
@click.native="
() => {
updateMemberRole(member.userID, 'VIEWER')
memberOptions[index].tippy().hide()
}
"
/>
</tippy> </tippy>
</span> </span>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
id="member" id="member"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="t('action.remove')" :title="t('action.remove')"
svg="user-minus" :icon="IconUserMinus"
color="red" color="red"
@click.native="removeExistingTeamMember(member.userID)" :loading="isLoadingIndex === index"
@click="removeExistingTeamMember(member.userID, index)"
/> />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div <div
v-if="!teamDetails.loading && E.isLeft(teamDetails.data)" v-if="!teamDetails.loading && E.isLeft(teamDetails.data)"
class="flex flex-col items-center" class="flex flex-col items-center"
> >
<i class="mb-4 material-icons">help_outline</i> <component :is="IconHelpCircle" class="mb-4 svg-icons" />
{{ t("error.something_went_wrong") }} {{ t("error.something_went_wrong") }}
</div> </div>
</div> </div>
</template> </template>
<template #footer> <template #footer>
<span> <span class="flex">
<ButtonPrimary :label="t('action.save')" @click.native="saveTeam" /> <ButtonPrimary
<ButtonSecondary :label="t('action.save')"
:label="t('action.cancel')" :loading="isLoading"
@click.native="hideModal" @click="saveTeam"
/> />
<ButtonSecondary :label="t('action.cancel')" @click="hideModal" />
</span> </span>
</template> </template>
</SmartModal> </SmartModal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, toRef, watch } from "@nuxtjs/composition-api" import { computed, ref, toRef, watch } from "vue"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import { import {
GetTeamDocument, GetTeamDocument,
GetTeamQuery, GetTeamQuery,
GetTeamQueryVariables, GetTeamQueryVariables,
TeamMemberAddedDocument, TeamMemberAddedDocument,
TeamMemberRemovedDocument, TeamMemberRemovedDocument,
TeamMemberRole, TeamMemberRole,
TeamMemberUpdatedDocument, TeamMemberUpdatedDocument,
} from "~/helpers/backend/graphql" } from "~/helpers/backend/graphql"
import { import {
removeTeamMember, removeTeamMember,
renameTeam, renameTeam,
updateTeamMemberRole, updateTeamMemberRole,
} from "~/helpers/backend/mutations/Team" } from "~/helpers/backend/mutations/Team"
import { TeamNameCodec } from "~/helpers/backend/types/TeamName" import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
import { useGQLQuery } from "~/helpers/backend/GQLClient"
import { useI18n, useToast } from "~/helpers/utils/composables" import { useGQLQuery } from "~/composables/graphql"
import { useI18n } from "@composables/i18n"
import { useToast } from "@composables/toast"
import { useColorMode } from "@composables/theming"
import IconCircleDot from "~icons/lucide/circle-dot"
import IconCircle from "~icons/lucide/circle"
import IconUserPlus from "~icons/lucide/user-plus"
import IconUserMinus from "~icons/lucide/user-minus"
import IconHelpCircle from "~icons/lucide/help-circle"
const t = useI18n() const t = useI18n()
const colorMode = useColorMode()
const emit = defineEmits<{ const emit = defineEmits<{
(e: "hide-modal"): void (e: "hide-modal"): void
(e: "refetch-teams"): void
(e: "invite-team"): void
}>() }>()
const memberOptions = ref<any | null>(null) const memberOptions = ref<any | null>(null)
const props = defineProps<{ const props = defineProps<{
show: boolean show: boolean
editingTeam: { editingTeam: {
name: string name: string
} }
editingTeamID: string editingTeamID: string
skipping to change at line 248 skipping to change at line 263
(teamID: string) => { (teamID: string) => {
teamDetails.execute({ teamID }) teamDetails.execute({ teamID })
} }
) )
const teamDetails = useGQLQuery<GetTeamQuery, GetTeamQueryVariables, "">({ const teamDetails = useGQLQuery<GetTeamQuery, GetTeamQueryVariables, "">({
query: GetTeamDocument, query: GetTeamDocument,
variables: { variables: {
teamID: props.editingTeamID, teamID: props.editingTeamID,
}, },
pollDuration: 10000,
defer: true, defer: true,
updateSubs: computed(() => { updateSubs: computed(() => {
if (props.editingTeamID) { if (props.editingTeamID) {
return [ return [
{ {
key: 1, key: 1,
query: TeamMemberAddedDocument, query: TeamMemberAddedDocument,
variables: { variables: {
teamID: props.editingTeamID, teamID: props.editingTeamID,
}, },
skipping to change at line 278 skipping to change at line 294
query: TeamMemberRemovedDocument, query: TeamMemberRemovedDocument,
variables: { variables: {
teamID: props.editingTeamID, teamID: props.editingTeamID,
}, },
}, },
] ]
} else return [] } else return []
}), }),
}) })
watch(
() => props.show,
(show) => {
if (!show) {
teamDetails.pause()
} else {
teamDetails.unpause()
}
}
)
const roleUpdates = ref< const roleUpdates = ref<
{ {
userID: string userID: string
role: TeamMemberRole role: TeamMemberRole
}[] }[]
>([]) >([])
watch( watch(
() => teamDetails, () => teamDetails,
() => { () => {
skipping to change at line 346 skipping to change at line 373
role: updatedRole?.role ?? member.role, role: updatedRole?.role ?? member.role,
} }
}) })
return members return members
} }
return [] return []
}) })
const removeExistingTeamMember = async (userID: string) => { const isLoadingIndex = ref<null | number>(null)
const removeExistingTeamMember = async (userID: string, index: number) => {
isLoadingIndex.value = index
const removeTeamMemberResult = await removeTeamMember( const removeTeamMemberResult = await removeTeamMember(
userID, userID,
props.editingTeamID props.editingTeamID
)() )()
if (E.isLeft(removeTeamMemberResult)) { if (E.isLeft(removeTeamMemberResult)) {
toast.error(`${t("error.something_went_wrong")}`) toast.error(`${t("error.something_went_wrong")}`)
} else { } else {
toast.success(`${t("team.member_removed")}`) toast.success(`${t("team.member_removed")}`)
emit("refetch-teams")
teamDetails.execute({ teamID: props.editingTeamID })
} }
isLoadingIndex.value = null
} }
const isLoading = ref(false)
const saveTeam = async () => { const saveTeam = async () => {
isLoading.value = true
if (name.value !== "") { if (name.value !== "") {
if (TeamNameCodec.is(name.value)) { if (TeamNameCodec.is(name.value)) {
const updateTeamNameResult = await renameTeam( const updateTeamNameResult = await renameTeam(
props.editingTeamID, props.editingTeamID,
name.value name.value
)() )()
if (E.isLeft(updateTeamNameResult)) { if (E.isLeft(updateTeamNameResult)) {
toast.error(`${t("error.something_went_wrong")}`) toast.error(`${t("error.something_went_wrong")}`)
} else { } else {
roleUpdates.value.forEach(async (update) => { roleUpdates.value.forEach(async (update) => {
skipping to change at line 383 skipping to change at line 419
)() )()
if (E.isLeft(updateMemberRoleResult)) { if (E.isLeft(updateMemberRoleResult)) {
toast.error(`${t("error.something_went_wrong")}`) toast.error(`${t("error.something_went_wrong")}`)
console.error(updateMemberRoleResult.left.error) console.error(updateMemberRoleResult.left.error)
} }
}) })
} }
hideModal() hideModal()
toast.success(`${t("team.saved")}`) toast.success(`${t("team.saved")}`)
} else { } else {
return toast.error(`${t("team.name_length_insufficient")}`) toast.error(`${t("team.name_length_insufficient")}`)
} }
} else { } else {
return toast.error(`${t("empty.team_name")}`) toast.error(`${t("empty.team_name")}`)
} }
isLoading.value = false
} }
const hideModal = () => { const hideModal = () => {
emit("hide-modal") emit("hide-modal")
} }
</script> </script>
 End of changes. 31 change blocks. 
78 lines changed or deleted 115 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)