refactor: switch workspace after creation (#4015)
Co-authored-by: amk-dev <akash.k.mohan98@gmail.com>
This commit is contained in:
@@ -32,7 +32,6 @@ import { useI18n } from "~/composables/i18n"
|
|||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
||||||
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
|
||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
import IconOpenAPI from "~icons/lucide/file"
|
import IconOpenAPI from "~icons/lucide/file"
|
||||||
@@ -55,16 +54,15 @@ import { teamCollectionsExporter } from "~/helpers/import-export/export/teamColl
|
|||||||
|
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
type CollectionType =
|
type CollectionType =
|
||||||
| {
|
| {
|
||||||
type: "team-collections"
|
type: "team-collections"
|
||||||
selectedTeam: SelectedTeam
|
selectedTeam: TeamWorkspace
|
||||||
}
|
}
|
||||||
| { type: "my-collections" }
|
| { type: "my-collections" }
|
||||||
|
|
||||||
@@ -433,7 +431,7 @@ const HoppTeamCollectionsExporter: ImporterOrExporter = {
|
|||||||
props.collectionsType.selectedTeam
|
props.collectionsType.selectedTeam
|
||||||
) {
|
) {
|
||||||
const res = await teamCollectionsExporter(
|
const res = await teamCollectionsExporter(
|
||||||
props.collectionsType.selectedTeam.id
|
props.collectionsType.selectedTeam.teamID
|
||||||
)
|
)
|
||||||
|
|
||||||
if (E.isRight(res)) {
|
if (E.isRight(res)) {
|
||||||
@@ -569,8 +567,8 @@ const hasTeamWriteAccess = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
collectionsType.selectedTeam.myRole === "EDITOR" ||
|
collectionsType.selectedTeam.role === "EDITOR" ||
|
||||||
collectionsType.selectedTeam.myRole === "OWNER"
|
collectionsType.selectedTeam.role === "OWNER"
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -578,17 +576,17 @@ const selectedTeamID = computed(() => {
|
|||||||
const { collectionsType } = props
|
const { collectionsType } = props
|
||||||
|
|
||||||
return collectionsType.type === "team-collections"
|
return collectionsType.type === "team-collections"
|
||||||
? collectionsType.selectedTeam?.id
|
? collectionsType.selectedTeam?.teamID
|
||||||
: undefined
|
: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const getCollectionJSON = async () => {
|
const getCollectionJSON = async () => {
|
||||||
if (
|
if (
|
||||||
props.collectionsType.type === "team-collections" &&
|
props.collectionsType.type === "team-collections" &&
|
||||||
props.collectionsType.selectedTeam?.id
|
props.collectionsType.selectedTeam?.teamID
|
||||||
) {
|
) {
|
||||||
const res = await getTeamCollectionJSON(
|
const res = await getTeamCollectionJSON(
|
||||||
props.collectionsType.selectedTeam?.id
|
props.collectionsType.selectedTeam?.teamID
|
||||||
)
|
)
|
||||||
|
|
||||||
return E.isRight(res)
|
return E.isRight(res)
|
||||||
|
|||||||
@@ -56,23 +56,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, reactive, ref, watch } from "vue"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { cloneDeep } from "lodash-es"
|
import { useToast } from "@composables/toast"
|
||||||
import {
|
import {
|
||||||
HoppGQLRequest,
|
HoppGQLRequest,
|
||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
isHoppRESTRequest,
|
isHoppRESTRequest,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { pipe } from "fp-ts/function"
|
import { computedWithControl } from "@vueuse/core"
|
||||||
|
import { useService } from "dioc/vue"
|
||||||
import * as TE from "fp-ts/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
import { pipe } from "fp-ts/function"
|
||||||
|
import { cloneDeep } from "lodash-es"
|
||||||
|
import { computed, nextTick, reactive, ref, watch } from "vue"
|
||||||
|
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||||
import {
|
import {
|
||||||
createRequestInCollection,
|
createRequestInCollection,
|
||||||
updateTeamRequest,
|
updateTeamRequest,
|
||||||
} from "~/helpers/backend/mutations/TeamRequest"
|
} from "~/helpers/backend/mutations/TeamRequest"
|
||||||
import { Picked } from "~/helpers/types/HoppPicked"
|
import { Picked } from "~/helpers/types/HoppPicked"
|
||||||
import { useI18n } from "@composables/i18n"
|
|
||||||
import { useToast } from "@composables/toast"
|
|
||||||
import {
|
import {
|
||||||
cascadeParentCollectionForHeaderAuth,
|
cascadeParentCollectionForHeaderAuth,
|
||||||
editGraphqlRequest,
|
editGraphqlRequest,
|
||||||
@@ -80,12 +82,10 @@ import {
|
|||||||
saveGraphqlRequestAs,
|
saveGraphqlRequestAs,
|
||||||
saveRESTRequestAs,
|
saveRESTRequestAs,
|
||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
|
||||||
import { computedWithControl } from "@vueuse/core"
|
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
import { useService } from "dioc/vue"
|
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
|
||||||
import { GQLTabService } from "~/services/tab/graphql"
|
import { GQLTabService } from "~/services/tab/graphql"
|
||||||
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
@@ -93,12 +93,10 @@ const toast = useToast()
|
|||||||
const RESTTabs = useService(RESTTabService)
|
const RESTTabs = useService(RESTTabService)
|
||||||
const GQLTabs = useService(GQLTabService)
|
const GQLTabs = useService(GQLTabService)
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
type CollectionType =
|
type CollectionType =
|
||||||
| {
|
| {
|
||||||
type: "team-collections"
|
type: "team-collections"
|
||||||
selectedTeam: SelectedTeam
|
selectedTeam: TeamWorkspace
|
||||||
}
|
}
|
||||||
| { type: "my-collections"; selectedTeam: undefined }
|
| { type: "my-collections"; selectedTeam: undefined }
|
||||||
|
|
||||||
@@ -192,7 +190,7 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const updateTeam = (newTeam: SelectedTeam) => {
|
const updateTeam = (newTeam: TeamWorkspace) => {
|
||||||
collectionsType.value.selectedTeam = newTeam
|
collectionsType.value.selectedTeam = newTeam
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,7 +491,7 @@ const updateTeamCollectionOrFolder = (
|
|||||||
const data = {
|
const data = {
|
||||||
title: requestUpdated.name,
|
title: requestUpdated.name,
|
||||||
request: JSON.stringify(requestUpdated),
|
request: JSON.stringify(requestUpdated),
|
||||||
teamID: collectionsType.value.selectedTeam.id,
|
teamID: collectionsType.value.selectedTeam.teamID,
|
||||||
}
|
}
|
||||||
pipe(
|
pipe(
|
||||||
createRequestInCollection(collectionID, data),
|
createRequestInCollection(collectionID, data),
|
||||||
|
|||||||
@@ -387,7 +387,6 @@ import IconPlus from "~icons/lucide/plus"
|
|||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||||
import IconImport from "~icons/lucide/folder-down"
|
import IconImport from "~icons/lucide/folder-down"
|
||||||
import { computed, PropType, Ref, toRef } from "vue"
|
import { computed, PropType, Ref, toRef } from "vue"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
|
||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useColorMode } from "@composables/theming"
|
import { useColorMode } from "@composables/theming"
|
||||||
import { TeamCollection } from "~/helpers/teams/TeamCollection"
|
import { TeamCollection } from "~/helpers/teams/TeamCollection"
|
||||||
@@ -400,17 +399,16 @@ import * as O from "fp-ts/Option"
|
|||||||
import { Picked } from "~/helpers/types/HoppPicked.js"
|
import { Picked } from "~/helpers/types/HoppPicked.js"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
const tabs = useService(RESTTabService)
|
const tabs = useService(RESTTabService)
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
type CollectionType =
|
type CollectionType =
|
||||||
| {
|
| {
|
||||||
type: "team-collections"
|
type: "team-collections"
|
||||||
selectedTeam: SelectedTeam
|
selectedTeam: TeamWorkspace
|
||||||
}
|
}
|
||||||
| { type: "my-collections"; selectedTeam: undefined }
|
| { type: "my-collections"; selectedTeam: undefined }
|
||||||
|
|
||||||
@@ -614,7 +612,7 @@ const hasNoTeamAccess = computed(
|
|||||||
() =>
|
() =>
|
||||||
props.collectionsType.type === "team-collections" &&
|
props.collectionsType.type === "team-collections" &&
|
||||||
(props.collectionsType.selectedTeam === undefined ||
|
(props.collectionsType.selectedTeam === undefined ||
|
||||||
props.collectionsType.selectedTeam.myRole === "VIEWER")
|
props.collectionsType.selectedTeam.role === "VIEWER")
|
||||||
)
|
)
|
||||||
|
|
||||||
const isSelected = ({
|
const isSelected = ({
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ const toast = useToast()
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
// Whether to activate the ability to pick items (activates 'select' events)
|
// Whether to activate the ability to pick items (activates 'select' events)
|
||||||
saveRequest: boolean
|
saveRequest: boolean
|
||||||
picked: Picked
|
picked: Picked | null
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const collections = useReadonlyStream(graphqlCollections$, [], "deep")
|
const collections = useReadonlyStream(graphqlCollections$, [], "deep")
|
||||||
|
|||||||
@@ -178,7 +178,6 @@ import { useI18n } from "@composables/i18n"
|
|||||||
import { Picked } from "~/helpers/types/HoppPicked"
|
import { Picked } from "~/helpers/types/HoppPicked"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
import { useLocalState } from "~/newstore/localstate"
|
import { useLocalState } from "~/newstore/localstate"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
|
||||||
import { pipe } from "fp-ts/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import * as TE from "fp-ts/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
import {
|
import {
|
||||||
@@ -245,7 +244,7 @@ import {
|
|||||||
} from "~/helpers/collection/collection"
|
} from "~/helpers/collection/collection"
|
||||||
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
||||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||||
import { WorkspaceService } from "~/services/workspace.service"
|
import { TeamWorkspace, WorkspaceService } from "~/services/workspace.service"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { RESTTabService } from "~/services/tab/rest"
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
@@ -274,16 +273,14 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: "select", payload: Picked | null): void
|
(event: "select", payload: Picked | null): void
|
||||||
(event: "update-team", team: SelectedTeam): void
|
(event: "update-team", team: TeamWorkspace): void
|
||||||
(event: "update-collection-type", type: CollectionType["type"]): void
|
(event: "update-collection-type", type: CollectionType["type"]): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
type CollectionType =
|
type CollectionType =
|
||||||
| {
|
| {
|
||||||
type: "team-collections"
|
type: "team-collections"
|
||||||
selectedTeam: SelectedTeam
|
selectedTeam: TeamWorkspace
|
||||||
}
|
}
|
||||||
| { type: "my-collections"; selectedTeam: undefined }
|
| { type: "my-collections"; selectedTeam: undefined }
|
||||||
|
|
||||||
@@ -330,9 +327,7 @@ const requestMoveLoading = ref<string[]>([])
|
|||||||
// TeamList-Adapter
|
// TeamList-Adapter
|
||||||
const workspaceService = useService(WorkspaceService)
|
const workspaceService = useService(WorkspaceService)
|
||||||
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
|
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
|
||||||
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
|
||||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||||
const teamListFetched = ref(false)
|
|
||||||
|
|
||||||
// Team Collection Adapter
|
// Team Collection Adapter
|
||||||
const teamCollectionAdapter = new TeamCollectionAdapter(null)
|
const teamCollectionAdapter = new TeamCollectionAdapter(null)
|
||||||
@@ -378,7 +373,7 @@ watch(
|
|||||||
filterTexts,
|
filterTexts,
|
||||||
(newFilterText) => {
|
(newFilterText) => {
|
||||||
if (collectionsType.value.type === "team-collections") {
|
if (collectionsType.value.type === "team-collections") {
|
||||||
const selectedTeamID = collectionsType.value.selectedTeam?.id
|
const selectedTeamID = collectionsType.value.selectedTeam?.teamID
|
||||||
|
|
||||||
selectedTeamID &&
|
selectedTeamID &&
|
||||||
debouncedSearch(newFilterText, selectedTeamID)?.catch(() => {})
|
debouncedSearch(newFilterText, selectedTeamID)?.catch(() => {})
|
||||||
@@ -435,28 +430,6 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
|
||||||
() => myTeams.value,
|
|
||||||
(newTeams) => {
|
|
||||||
if (newTeams && !teamListFetched.value) {
|
|
||||||
teamListFetched.value = true
|
|
||||||
if (REMEMBERED_TEAM_ID.value && currentUser.value) {
|
|
||||||
const team = newTeams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
|
||||||
if (team) updateSelectedTeam(team)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => collectionsType.value.selectedTeam,
|
|
||||||
(newTeam) => {
|
|
||||||
if (newTeam) {
|
|
||||||
teamCollectionAdapter.changeTeamID(newTeam.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const switchToMyCollections = () => {
|
const switchToMyCollections = () => {
|
||||||
collectionsType.value.type = "my-collections"
|
collectionsType.value.type = "my-collections"
|
||||||
collectionsType.value.selectedTeam = undefined
|
collectionsType.value.selectedTeam = undefined
|
||||||
@@ -488,11 +461,12 @@ const expandTeamCollection = (collectionID: string) => {
|
|||||||
teamCollectionAdapter.expandCollection(collectionID)
|
teamCollectionAdapter.expandCollection(collectionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateSelectedTeam = (team: SelectedTeam) => {
|
const updateSelectedTeam = (team: TeamWorkspace) => {
|
||||||
if (team) {
|
if (team) {
|
||||||
collectionsType.value.type = "team-collections"
|
collectionsType.value.type = "team-collections"
|
||||||
|
teamCollectionAdapter.changeTeamID(team.teamID)
|
||||||
collectionsType.value.selectedTeam = team
|
collectionsType.value.selectedTeam = team
|
||||||
REMEMBERED_TEAM_ID.value = team.id
|
REMEMBERED_TEAM_ID.value = team.teamID
|
||||||
emit("update-team", team)
|
emit("update-team", team)
|
||||||
emit("update-collection-type", "team-collections")
|
emit("update-collection-type", "team-collections")
|
||||||
}
|
}
|
||||||
@@ -501,23 +475,14 @@ const updateSelectedTeam = (team: SelectedTeam) => {
|
|||||||
const workspace = workspaceService.currentWorkspace
|
const workspace = workspaceService.currentWorkspace
|
||||||
|
|
||||||
// Used to switch collection type and team when user switch workspace in the global workspace switcher
|
// Used to switch collection type and team when user switch workspace in the global workspace switcher
|
||||||
// Check if there is a teamID in the workspace, if yes, switch to team collections and select the team
|
|
||||||
// If there is no teamID, switch to my collections
|
|
||||||
watch(
|
watch(
|
||||||
() => {
|
workspace,
|
||||||
const space = workspace.value
|
(newWorkspace) => {
|
||||||
return space.type === "personal" ? undefined : space.teamID
|
if (newWorkspace.type === "personal") {
|
||||||
},
|
switchToMyCollections()
|
||||||
(teamID) => {
|
} else if (newWorkspace.type === "team") {
|
||||||
if (teamID) {
|
updateSelectedTeam(newWorkspace)
|
||||||
const team = myTeams.value?.find((t) => t.id === teamID)
|
|
||||||
if (team) {
|
|
||||||
updateSelectedTeam(team)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return switchToMyCollections()
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
@@ -545,7 +510,7 @@ const hasTeamWriteAccess = computed(() => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = collectionsType.value.selectedTeam?.myRole
|
const role = collectionsType.value.selectedTeam?.role
|
||||||
return role === "OWNER" || role === "EDITOR"
|
return role === "OWNER" || role === "EDITOR"
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -760,7 +725,7 @@ const addNewRootCollection = (name: string) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
pipe(
|
pipe(
|
||||||
createNewRootCollection(name, collectionsType.value.selectedTeam.id),
|
createNewRootCollection(name, collectionsType.value.selectedTeam.teamID),
|
||||||
TE.match(
|
TE.match(
|
||||||
(err: GQLError<string>) => {
|
(err: GQLError<string>) => {
|
||||||
toast.error(`${getErrorMessage(err)}`)
|
toast.error(`${getErrorMessage(err)}`)
|
||||||
@@ -831,7 +796,7 @@ const onAddRequest = (requestName: string) => {
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
request: JSON.stringify(newRequest),
|
request: JSON.stringify(newRequest),
|
||||||
teamID: collectionsType.value.selectedTeam.id,
|
teamID: collectionsType.value.selectedTeam.teamID,
|
||||||
title: requestName,
|
title: requestName,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1123,7 @@ const duplicateRequest = (payload: {
|
|||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
request: JSON.stringify(newRequest),
|
request: JSON.stringify(newRequest),
|
||||||
teamID: collectionsType.value.selectedTeam.id,
|
teamID: collectionsType.value.selectedTeam.teamID,
|
||||||
title: `${request.name} - ${t("action.duplicate")}`,
|
title: `${request.name} - ${t("action.duplicate")}`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,6 +364,7 @@ const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
|||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
teamName: team.name,
|
teamName: team.name,
|
||||||
type: "team",
|
type: "team",
|
||||||
|
role: team.myRole,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -46,41 +46,38 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from "vue"
|
|
||||||
import { isEqual } from "lodash-es"
|
|
||||||
import { platform } from "~/platform"
|
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
|
||||||
import { useReadonlyStream, useStream } from "@composables/stream"
|
import { useReadonlyStream, useStream } from "@composables/stream"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
|
import { useService } from "dioc/vue"
|
||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
|
import { isEqual } from "lodash-es"
|
||||||
|
import { computed, ref, watch } from "vue"
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
|
import { useToast } from "~/composables/toast"
|
||||||
|
import { defineActionHandler } from "~/helpers/actions"
|
||||||
|
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||||
|
import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
||||||
|
import TeamEnvironmentAdapter from "~/helpers/teams/TeamEnvironmentAdapter"
|
||||||
import {
|
import {
|
||||||
|
deleteEnvironment,
|
||||||
getSelectedEnvironmentIndex,
|
getSelectedEnvironmentIndex,
|
||||||
globalEnv$,
|
globalEnv$,
|
||||||
selectedEnvironmentIndex$,
|
selectedEnvironmentIndex$,
|
||||||
setSelectedEnvironmentIndex,
|
setSelectedEnvironmentIndex,
|
||||||
} from "~/newstore/environments"
|
} from "~/newstore/environments"
|
||||||
import TeamEnvironmentAdapter from "~/helpers/teams/TeamEnvironmentAdapter"
|
|
||||||
import { defineActionHandler } from "~/helpers/actions"
|
|
||||||
import { useLocalState } from "~/newstore/localstate"
|
import { useLocalState } from "~/newstore/localstate"
|
||||||
import { pipe } from "fp-ts/function"
|
import { platform } from "~/platform"
|
||||||
import * as TE from "fp-ts/TaskEither"
|
import { TeamWorkspace, WorkspaceService } from "~/services/workspace.service"
|
||||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
|
||||||
import { deleteEnvironment } from "~/newstore/environments"
|
|
||||||
import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
|
||||||
import { useToast } from "~/composables/toast"
|
|
||||||
import { WorkspaceService } from "~/services/workspace.service"
|
|
||||||
import { useService } from "dioc/vue"
|
|
||||||
import { Environment } from "@hoppscotch/data"
|
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
type EnvironmentType = "my-environments" | "team-environments"
|
type EnvironmentType = "my-environments" | "team-environments"
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
type EnvironmentsChooseType = {
|
type EnvironmentsChooseType = {
|
||||||
type: EnvironmentType
|
type: EnvironmentType
|
||||||
selectedTeam: SelectedTeam
|
selectedTeam: TeamWorkspace | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const environmentType = ref<EnvironmentsChooseType>({
|
const environmentType = ref<EnvironmentsChooseType>({
|
||||||
@@ -102,11 +99,7 @@ const currentUser = useReadonlyStream(
|
|||||||
platform.auth.getCurrentUser()
|
platform.auth.getCurrentUser()
|
||||||
)
|
)
|
||||||
|
|
||||||
// TeamList-Adapter
|
|
||||||
const workspaceService = useService(WorkspaceService)
|
const workspaceService = useService(WorkspaceService)
|
||||||
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
|
|
||||||
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
|
||||||
const teamListFetched = ref(false)
|
|
||||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||||
|
|
||||||
const adapter = new TeamEnvironmentAdapter(undefined)
|
const adapter = new TeamEnvironmentAdapter(undefined)
|
||||||
@@ -118,29 +111,17 @@ const loading = computed(
|
|||||||
() => adapterLoading.value && teamEnvironmentList.value.length === 0
|
() => adapterLoading.value && teamEnvironmentList.value.length === 0
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(
|
|
||||||
() => myTeams.value,
|
|
||||||
(newTeams) => {
|
|
||||||
if (newTeams && !teamListFetched.value) {
|
|
||||||
teamListFetched.value = true
|
|
||||||
if (REMEMBERED_TEAM_ID.value && currentUser.value) {
|
|
||||||
const team = newTeams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
|
||||||
if (team) updateSelectedTeam(team)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const switchToMyEnvironments = () => {
|
const switchToMyEnvironments = () => {
|
||||||
environmentType.value.selectedTeam = undefined
|
environmentType.value.selectedTeam = undefined
|
||||||
updateEnvironmentType("my-environments")
|
updateEnvironmentType("my-environments")
|
||||||
adapter.changeTeamID(undefined)
|
adapter.changeTeamID(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateSelectedTeam = (newSelectedTeam: SelectedTeam | undefined) => {
|
const updateSelectedTeam = (newSelectedTeam: TeamWorkspace | undefined) => {
|
||||||
if (newSelectedTeam) {
|
if (newSelectedTeam) {
|
||||||
|
adapter.changeTeamID(newSelectedTeam.teamID)
|
||||||
environmentType.value.selectedTeam = newSelectedTeam
|
environmentType.value.selectedTeam = newSelectedTeam
|
||||||
REMEMBERED_TEAM_ID.value = newSelectedTeam.id
|
REMEMBERED_TEAM_ID.value = newSelectedTeam.teamID
|
||||||
updateEnvironmentType("team-environments")
|
updateEnvironmentType("team-environments")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,15 +129,6 @@ const updateEnvironmentType = (newEnvironmentType: EnvironmentType) => {
|
|||||||
environmentType.value.type = newEnvironmentType
|
environmentType.value.type = newEnvironmentType
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
|
||||||
() => environmentType.value.selectedTeam,
|
|
||||||
(newTeam) => {
|
|
||||||
if (newTeam) {
|
|
||||||
adapter.changeTeamID(newTeam.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const workspace = workspaceService.currentWorkspace
|
const workspace = workspaceService.currentWorkspace
|
||||||
|
|
||||||
// Switch to my environments if workspace is personal and to team environments if workspace is team
|
// Switch to my environments if workspace is personal and to team environments if workspace is team
|
||||||
@@ -170,8 +142,7 @@ watch(workspace, (newWorkspace) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (newWorkspace.type === "team") {
|
} else if (newWorkspace.type === "team") {
|
||||||
const team = myTeams.value?.find((t) => t.id === newWorkspace.teamID)
|
updateSelectedTeam(newWorkspace)
|
||||||
updateSelectedTeam(team)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class="sticky top-upperPrimaryStickyFold z-10 flex flex-1 flex-shrink-0 justify-between overflow-x-auto border-b border-dividerLight bg-primary"
|
class="sticky top-upperPrimaryStickyFold z-10 flex flex-1 flex-shrink-0 justify-between overflow-x-auto border-b border-dividerLight bg-primary"
|
||||||
>
|
>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="team === undefined || team.myRole === 'VIEWER'"
|
v-if="team === undefined || team.role === 'VIEWER'"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
disabled
|
disabled
|
||||||
class="!rounded-none"
|
class="!rounded-none"
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
:icon="IconHelpCircle"
|
:icon="IconHelpCircle"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="team !== undefined && team.myRole === 'VIEWER'"
|
v-if="team !== undefined && team.role === 'VIEWER'"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
disabled
|
disabled
|
||||||
:icon="IconImport"
|
:icon="IconImport"
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
)"
|
)"
|
||||||
:key="`environment-${index}`"
|
:key="`environment-${index}`"
|
||||||
:environment="environment"
|
:environment="environment"
|
||||||
:is-viewer="team?.myRole === 'VIEWER'"
|
:is-viewer="team?.role === 'VIEWER'"
|
||||||
@edit-environment="editEnvironment(environment)"
|
@edit-environment="editEnvironment(environment)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,16 +103,16 @@
|
|||||||
:show="showModalDetails"
|
:show="showModalDetails"
|
||||||
:action="action"
|
:action="action"
|
||||||
:editing-environment="editingEnvironment"
|
:editing-environment="editingEnvironment"
|
||||||
:editing-team-id="team?.id"
|
:editing-team-id="team?.teamID"
|
||||||
:editing-variable-name="editingVariableName"
|
:editing-variable-name="editingVariableName"
|
||||||
:is-secret-option-selected="secretOptionSelected"
|
:is-secret-option-selected="secretOptionSelected"
|
||||||
:is-viewer="team?.myRole === 'VIEWER'"
|
:is-viewer="team?.role === 'VIEWER'"
|
||||||
@hide-modal="displayModalEdit(false)"
|
@hide-modal="displayModalEdit(false)"
|
||||||
/>
|
/>
|
||||||
<EnvironmentsImportExport
|
<EnvironmentsImportExport
|
||||||
v-if="showModalImportExport"
|
v-if="showModalImportExport"
|
||||||
:team-environments="teamEnvironments"
|
:team-environments="teamEnvironments"
|
||||||
:team-id="team?.id"
|
:team-id="team?.teamID"
|
||||||
environment-type="TEAM_ENV"
|
environment-type="TEAM_ENV"
|
||||||
@hide-modal="displayModalImportExport(false)"
|
@hide-modal="displayModalImportExport(false)"
|
||||||
/>
|
/>
|
||||||
@@ -129,16 +129,14 @@ import IconPlus from "~icons/lucide/plus"
|
|||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||||
import IconImport from "~icons/lucide/folder-down"
|
import IconImport from "~icons/lucide/folder-down"
|
||||||
import { defineActionHandler } from "~/helpers/actions"
|
import { defineActionHandler } from "~/helpers/actions"
|
||||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
team: SelectedTeam
|
team: TeamWorkspace | undefined
|
||||||
teamEnvironments: TeamEnvironment[]
|
teamEnvironments: TeamEnvironment[]
|
||||||
adapterError: GQLError<string> | null
|
adapterError: GQLError<string> | null
|
||||||
loading: boolean
|
loading: boolean
|
||||||
@@ -151,7 +149,7 @@ const editingEnvironment = ref<TeamEnvironment | null>(null)
|
|||||||
const editingVariableName = ref("")
|
const editingVariableName = ref("")
|
||||||
const secretOptionSelected = ref(false)
|
const secretOptionSelected = ref(false)
|
||||||
|
|
||||||
const isTeamViewer = computed(() => props.team?.myRole === "VIEWER")
|
const isTeamViewer = computed(() => props.team?.role === "VIEWER")
|
||||||
|
|
||||||
const displayModalAdd = (shouldDisplay: boolean) => {
|
const displayModalAdd = (shouldDisplay: boolean) => {
|
||||||
action.value = "new"
|
action.value = "new"
|
||||||
|
|||||||
@@ -37,13 +37,17 @@ import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
|
|||||||
import { useI18n } from "@composables/i18n"
|
import { useI18n } from "@composables/i18n"
|
||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
import { useService } from "dioc/vue"
|
||||||
|
import { WorkspaceService } from "~/services/workspace.service"
|
||||||
|
import { useLocalState } from "~/newstore/localstate"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
show: boolean
|
show: boolean
|
||||||
|
switchWorkspaceAfterCreation?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -52,8 +56,12 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const editingName = ref<string | null>(null)
|
const editingName = ref<string | null>(null)
|
||||||
|
|
||||||
|
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
|
|
||||||
|
const workspaceService = useService(WorkspaceService)
|
||||||
|
|
||||||
const addNewTeam = async () => {
|
const addNewTeam = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
await pipe(
|
await pipe(
|
||||||
@@ -76,8 +84,19 @@ const addNewTeam = async () => {
|
|||||||
// Handle GQL errors (use err obj)
|
// Handle GQL errors (use err obj)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => {
|
(team) => {
|
||||||
toast.success(`${t("team.new_created")}`)
|
toast.success(`${t("team.new_created")}`)
|
||||||
|
|
||||||
|
if (props.switchWorkspaceAfterCreation) {
|
||||||
|
REMEMBERED_TEAM_ID.value = team.id
|
||||||
|
workspaceService.changeWorkspace({
|
||||||
|
teamID: team.id,
|
||||||
|
teamName: team.name,
|
||||||
|
type: "team",
|
||||||
|
role: team.myRole,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
hideModal()
|
hideModal()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -66,7 +66,11 @@
|
|||||||
{{ t("error.something_went_wrong") }}
|
{{ t("error.something_went_wrong") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
|
<TeamsAdd
|
||||||
|
:show="showModalAdd"
|
||||||
|
:switch-workspace-after-creation="true"
|
||||||
|
@hide-modal="displayModalAdd(false)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -153,6 +157,7 @@ const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
|||||||
workspaceService.changeWorkspace({
|
workspaceService.changeWorkspace({
|
||||||
teamID: team.id,
|
teamID: team.id,
|
||||||
teamName: team.name,
|
teamName: team.name,
|
||||||
|
role: team.myRole,
|
||||||
type: "team",
|
type: "team",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -175,7 +180,6 @@ watch(
|
|||||||
|
|
||||||
const displayModalAdd = (shouldDisplay: boolean) => {
|
const displayModalAdd = (shouldDisplay: boolean) => {
|
||||||
showModalAdd.value = shouldDisplay
|
showModalAdd.value = shouldDisplay
|
||||||
teamListadapter.fetchList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defineActionHandler("modals.team.new", () => {
|
defineActionHandler("modals.team.new", () => {
|
||||||
|
|||||||
@@ -5,13 +5,24 @@ import { useStreamStatic } from "~/composables/stream"
|
|||||||
import TeamListAdapter from "~/helpers/teams/TeamListAdapter"
|
import TeamListAdapter from "~/helpers/teams/TeamListAdapter"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
import { min } from "lodash-es"
|
import { min } from "lodash-es"
|
||||||
|
import { TeamMemberRole } from "~/helpers/backend/graphql"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a workspace and its information
|
* Defines a workspace and its information
|
||||||
*/
|
*/
|
||||||
export type Workspace =
|
|
||||||
| { type: "personal" }
|
export type PersonalWorkspace = {
|
||||||
| { type: "team"; teamID: string; teamName: string }
|
type: "personal"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TeamWorkspace = {
|
||||||
|
type: "team"
|
||||||
|
teamID: string
|
||||||
|
teamName: string
|
||||||
|
role: TeamMemberRole | null | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Workspace = PersonalWorkspace | TeamWorkspace
|
||||||
|
|
||||||
export type WorkspaceServiceEvent = {
|
export type WorkspaceServiceEvent = {
|
||||||
type: "managed-team-list-adapter-polled"
|
type: "managed-team-list-adapter-polled"
|
||||||
|
|||||||
Reference in New Issue
Block a user