refactor: port collection tree rendered in the save request modal to the new implementation

This commit is contained in:
jamesgeorge007
2024-02-13 20:10:02 +05:30
parent b0c72fd295
commit 68795a5017
6 changed files with 413 additions and 268 deletions

View File

@@ -20,19 +20,25 @@
<label class="p-4"> <label class="p-4">
{{ t("collection.select_location") }} {{ t("collection.select_location") }}
</label> </label>
<CollectionsGraphql <!-- <CollectionsGraphql
v-if="mode === 'graphql'" v-if="mode === 'graphql'"
:picked="picked" :picked="picked"
:save-request="true" :save-request="true"
@select="onSelect" @select="onSelect"
/> /> -->
<Collections <!-- <Collections
v-else v-else
:picked="picked" :picked="picked"
:save-request="true" :save-request="true"
@select="onSelect" @select="onSelect"
@update-team="updateTeam" @update-team="updateTeam"
@update-collection-type="updateCollectionType" @update-collection-type="updateCollectionType"
/> -->
<NewCollections
:picked="picked"
:save-request="true"
platform="rest"
@select="onSelect"
/> />
</div> </div>
</template> </template>
@@ -66,26 +72,14 @@ import {
import { computedWithControl } from "@vueuse/core" import { computedWithControl } from "@vueuse/core"
import { useService } from "dioc/vue" import { useService } from "dioc/vue"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { pipe } from "fp-ts/function"
import { cloneDeep } from "lodash-es" import { cloneDeep } from "lodash-es"
import { computed, nextTick, reactive, ref, watch } from "vue" import { computed, nextTick, reactive, ref, watch } from "vue"
import { GQLError } from "~/helpers/backend/GQLClient"
import {
createRequestInCollection,
updateTeamRequest,
} from "~/helpers/backend/mutations/TeamRequest"
import { Picked } from "~/helpers/types/HoppPicked" import { Picked } from "~/helpers/types/HoppPicked"
import { import { cascadeParentCollectionForHeaderAuth } from "~/newstore/collections"
cascadeParentCollectionForHeaderAuth,
editGraphqlRequest,
saveGraphqlRequestAs,
} from "~/newstore/collections"
import { platform } from "~/platform"
import { NewWorkspaceService } from "~/services/new-workspace" import { NewWorkspaceService } from "~/services/new-workspace"
import { GQLTabService } from "~/services/tab/graphql" import { GQLTabService } from "~/services/tab/graphql"
import { RESTTabService } from "~/services/tab/rest" import { RESTTabService } from "~/services/tab/rest"
import { TeamWorkspace } from "~/services/workspace.service"
const t = useI18n() const t = useI18n()
const toast = useToast() const toast = useToast()
@@ -94,12 +88,14 @@ const RESTTabs = useService(RESTTabService)
const GQLTabs = useService(GQLTabService) const GQLTabs = useService(GQLTabService)
const workspaceService = useService(NewWorkspaceService) const workspaceService = useService(NewWorkspaceService)
type CollectionType = // type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
| {
type: "team-collections" // type CollectionType =
selectedTeam: TeamWorkspace // | {
} // type: "team-collections"
| { type: "my-collections"; selectedTeam: undefined } // selectedTeam: SelectedTeam
// }
// | { type: "my-collections"; selectedTeam: undefined }
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@@ -167,10 +163,10 @@ const requestData = reactive({
requestIndex: undefined as number | undefined, requestIndex: undefined as number | undefined,
}) })
const collectionsType = ref<CollectionType>({ // const collectionsType = ref<CollectionType>({
type: "my-collections", // type: "my-collections",
selectedTeam: undefined, // selectedTeam: undefined,
}) // })
const picked = ref<Picked | null>(null) const picked = ref<Picked | null>(null)
@@ -191,13 +187,14 @@ watch(
} }
) )
const updateTeam = (newTeam: TeamWorkspace) => { // TODO: To be removed
collectionsType.value.selectedTeam = newTeam // const updateTeam = (newTeam: SelectedTeam) => {
} // collectionsType.value.selectedTeam = newTeam
// }
const updateCollectionType = (type: CollectionType["type"]) => { // const updateCollectionType = (type: CollectionType["type"]) => {
collectionsType.value.type = type // collectionsType.value.type = type
} // }
const onSelect = (pickedVal: Picked | null) => { const onSelect = (pickedVal: Picked | null) => {
picked.value = pickedVal picked.value = pickedVal
@@ -322,145 +319,147 @@ const saveRequestAs = async () => {
headers, headers,
} }
requestSaved()
} else if (picked.value.pickedType === "teams-collection") {
if (!isHoppRESTRequest(updatedRequest))
throw new Error("requestUpdated is not a REST Request")
updateTeamCollectionOrFolder(picked.value.collectionID, updatedRequest)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: true,
platform: "rest",
workspaceType: "team",
})
} else if (picked.value.pickedType === "teams-folder") {
if (!isHoppRESTRequest(updatedRequest))
throw new Error("requestUpdated is not a REST Request")
updateTeamCollectionOrFolder(picked.value.folderID, updatedRequest)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: true,
platform: "rest",
workspaceType: "team",
})
} else if (picked.value.pickedType === "teams-request") {
if (!isHoppRESTRequest(updatedRequest))
throw new Error("requestUpdated is not a REST Request")
if (
collectionsType.value.type !== "team-collections" ||
!collectionsType.value.selectedTeam
)
throw new Error("Collections Type mismatch")
modalLoadingState.value = true
const data = {
request: JSON.stringify(updatedRequest),
title: updatedRequest.name,
}
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: false,
platform: "rest",
workspaceType: "team",
})
pipe(
updateTeamRequest(picked.value.requestID, data),
TE.match(
(err: GQLError<string>) => {
toast.error(`${getErrorMessage(err)}`)
modalLoadingState.value = false
},
() => {
modalLoadingState.value = false
requestSaved()
}
)
)()
} else if (picked.value.pickedType === "gql-my-request") {
// TODO: Check for GQL request ?
editGraphqlRequest(
picked.value.folderPath,
picked.value.requestIndex,
updatedRequest as HoppGQLRequest
)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: false,
platform: "gql",
workspaceType: "team",
})
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
picked.value.folderPath,
"graphql"
)
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
auth,
headers,
}
requestSaved()
} else if (picked.value.pickedType === "gql-my-folder") {
// TODO: Check for GQL request ?
saveGraphqlRequestAs(
picked.value.folderPath,
updatedRequest as HoppGQLRequest
)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: true,
platform: "gql",
workspaceType: "team",
})
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
picked.value.folderPath,
"graphql"
)
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
auth,
headers,
}
requestSaved()
} else if (picked.value.pickedType === "gql-my-collection") {
// TODO: Check for GQL request ?
saveGraphqlRequestAs(
`${picked.value.collectionIndex}`,
updatedRequest as HoppGQLRequest
)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
createdNow: true,
platform: "gql",
workspaceType: "team",
})
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
`${picked.value.collectionIndex}`,
"graphql"
)
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
auth,
headers,
}
requestSaved() requestSaved()
} }
// TODO: To be removed
// else if (picked.value.pickedType === "teams-collection") {
// if (!isHoppRESTRequest(updatedRequest))
// throw new Error("requestUpdated is not a REST Request")
// updateTeamCollectionOrFolder(picked.value.collectionID, updatedRequest)
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: true,
// platform: "rest",
// workspaceType: "team",
// })
// } else if (picked.value.pickedType === "teams-folder") {
// if (!isHoppRESTRequest(updatedRequest))
// throw new Error("requestUpdated is not a REST Request")
// updateTeamCollectionOrFolder(picked.value.folderID, updatedRequest)
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: true,
// platform: "rest",
// workspaceType: "team",
// })
// } else if (picked.value.pickedType === "teams-request") {
// if (!isHoppRESTRequest(updatedRequest))
// throw new Error("requestUpdated is not a REST Request")
// if (
// collectionsType.value.type !== "team-collections" ||
// !collectionsType.value.selectedTeam
// )
// throw new Error("Collections Type mismatch")
// modalLoadingState.value = true
// const data = {
// request: JSON.stringify(updatedRequest),
// title: updatedRequest.name,
// }
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: false,
// platform: "rest",
// workspaceType: "team",
// })
// pipe(
// updateTeamRequest(picked.value.requestID, data),
// TE.match(
// (err: GQLError<string>) => {
// toast.error(`${getErrorMessage(err)}`)
// modalLoadingState.value = false
// },
// () => {
// modalLoadingState.value = false
// requestSaved()
// }
// )
// )()
// } else if (picked.value.pickedType === "gql-my-request") {
// // TODO: Check for GQL request ?
// editGraphqlRequest(
// picked.value.folderPath,
// picked.value.requestIndex,
// updatedRequest as HoppGQLRequest
// )
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: false,
// platform: "gql",
// workspaceType: "team",
// })
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// picked.value.folderPath,
// "graphql"
// )
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
// auth,
// headers,
// }
// requestSaved()
// } else if (picked.value.pickedType === "gql-my-folder") {
// // TODO: Check for GQL request ?
// saveGraphqlRequestAs(
// picked.value.folderPath,
// updatedRequest as HoppGQLRequest
// )
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: true,
// platform: "gql",
// workspaceType: "team",
// })
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// picked.value.folderPath,
// "graphql"
// )
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
// auth,
// headers,
// }
// requestSaved()
// } else if (picked.value.pickedType === "gql-my-collection") {
// // TODO: Check for GQL request ?
// saveGraphqlRequestAs(
// `${picked.value.collectionIndex}`,
// updatedRequest as HoppGQLRequest
// )
// platform.analytics?.logEvent({
// type: "HOPP_SAVE_REQUEST",
// createdNow: true,
// platform: "gql",
// workspaceType: "team",
// })
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
// `${picked.value.collectionIndex}`,
// "graphql"
// )
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
// auth,
// headers,
// }
// requestSaved()
// }
} }
/** /**
@@ -468,50 +467,50 @@ const saveRequestAs = async () => {
* @param collectionID - ID of the collection or folder * @param collectionID - ID of the collection or folder
* @param requestUpdated - Updated request * @param requestUpdated - Updated request
*/ */
const updateTeamCollectionOrFolder = ( // const updateTeamCollectionOrFolder = (
collectionID: string, // collectionID: string,
requestUpdated: HoppRESTRequest // requestUpdated: HoppRESTRequest
) => { // ) => {
if ( // if (
collectionsType.value.type !== "team-collections" || // collectionsType.value.type !== "team-collections" ||
!collectionsType.value.selectedTeam // !collectionsType.value.selectedTeam
) // )
throw new Error("Collections Type mismatch") // throw new Error("Collections Type mismatch")
modalLoadingState.value = true // modalLoadingState.value = true
const data = { // const data = {
title: requestUpdated.name, // title: requestUpdated.name,
request: JSON.stringify(requestUpdated), // request: JSON.stringify(requestUpdated),
teamID: collectionsType.value.selectedTeam.teamID, // teamID: collectionsType.value.selectedTeam.id,
} // }
pipe( // pipe(
createRequestInCollection(collectionID, data), // createRequestInCollection(collectionID, data),
TE.match( // TE.match(
(err: GQLError<string>) => { // (err: GQLError<string>) => {
toast.error(`${getErrorMessage(err)}`) // toast.error(`${getErrorMessage(err)}`)
modalLoadingState.value = false // modalLoadingState.value = false
}, // },
(result) => { // (result) => {
const { createRequestInCollection } = result // const { createRequestInCollection } = result
RESTTabs.currentActiveTab.value.document = { // RESTTabs.currentActiveTab.value.document = {
request: requestUpdated, // request: requestUpdated,
isDirty: false, // isDirty: false,
saveContext: { // saveContext: {
originLocation: "team-collection", // originLocation: "team-collection",
requestID: createRequestInCollection.id, // requestID: createRequestInCollection.id,
collectionID: createRequestInCollection.collection.id, // collectionID: createRequestInCollection.collection.id,
teamID: createRequestInCollection.collection.team.id, // teamID: createRequestInCollection.collection.team.id,
}, // },
} // }
modalLoadingState.value = false // modalLoadingState.value = false
requestSaved() // requestSaved()
} // }
) // )
)() // )()
} // }
const requestSaved = () => { const requestSaved = () => {
toast.success(`${t("request.added")}`) toast.success(`${t("request.added")}`)
@@ -526,24 +525,24 @@ const hideModal = () => {
emit("hide-modal") emit("hide-modal")
} }
const getErrorMessage = (err: GQLError<string>) => { // const getErrorMessage = (err: GQLError<string>) => {
console.error(err) // console.error(err)
if (err.type === "network_error") { // if (err.type === "network_error") {
return t("error.network_error") // return t("error.network_error")
} // }
switch (err.error) { // switch (err.error) {
case "team_coll/short_title": // case "team_coll/short_title":
return t("collection.name_length_insufficient") // return t("collection.name_length_insufficient")
case "team/invalid_coll_id": // case "team/invalid_coll_id":
return t("team.invalid_id") // return t("team.invalid_id")
case "team/not_required_role": // case "team/not_required_role":
return t("profile.no_permission") // return t("profile.no_permission")
case "team_req/not_required_role": // case "team_req/not_required_role":
return t("profile.no_permission") // return t("profile.no_permission")
case "Forbidden resource": // case "Forbidden resource":
return t("profile.no_permission") // return t("profile.no_permission")
default: // default:
return t("error.something_went_wrong") // return t("error.something_went_wrong")
} // }
} // }
</script> </script>

View File

@@ -18,7 +18,10 @@
</div> </div>
<NewCollectionsRest <NewCollectionsRest
v-if="platform === 'rest'" v-if="platform === 'rest'"
:picked="picked"
:save-request="saveRequest"
:workspace-handle="activeWorkspaceHandle" :workspace-handle="activeWorkspaceHandle"
@select="(payload) => emit('select', payload)"
/> />
</div> </div>
</template> </template>
@@ -27,10 +30,17 @@
import { useService } from "dioc/vue" import { useService } from "dioc/vue"
import { ref } from "vue" import { ref } from "vue"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
import { Picked } from "~/helpers/types/HoppPicked";
import { NewWorkspaceService } from "~/services/new-workspace" import { NewWorkspaceService } from "~/services/new-workspace"
defineProps<{ defineProps<{
picked: Picked | null
platform: "rest" | "gql" platform: "rest" | "gql"
saveRequest: boolean
}>()
const emit = defineEmits<{
(event: "select", payload: Picked | null): void
}>() }>()
const t = useI18n() const t = useI18n()
@@ -40,7 +50,4 @@ const searchText = ref("")
const workspaceService = useService(NewWorkspaceService) const workspaceService = useService(NewWorkspaceService)
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle
const showModalAdd = ref(false)
const showModalImportExport = ref(false)
</script> </script>

View File

@@ -12,12 +12,16 @@
<span <span
class="pointer-events-none flex items-center justify-center px-4" class="pointer-events-none flex items-center justify-center px-4"
> >
<component :is="collectionIcon" class="svg-icons" /> <component
:is="collectionIcon"
class="svg-icons"
:class="{ 'text-accent': isSelected }"
/>
</span> </span>
<span <span
class="pointer-events-none flex min-w-0 flex-1 py-2 pr-2 transition group-hover:text-secondaryDark" class="pointer-events-none flex min-w-0 flex-1 py-2 pr-2 transition group-hover:text-secondaryDark"
> >
<span class="truncate"> <span class="truncate" :class="{ 'text-accent': isSelected }">
{{ collectionView.name }} {{ collectionView.name }}
</span> </span>
</span> </span>
@@ -151,6 +155,7 @@ import { RESTCollectionViewCollection } from "~/services/new-workspace/view"
import { TippyComponent } from "vue-tippy" import { TippyComponent } from "vue-tippy"
import { ref, computed } from "vue" import { ref, computed } from "vue"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
import IconCheckCircle from "~icons/lucide/check-circle"
import IconFolderPlus from "~icons/lucide/folder-plus" import IconFolderPlus from "~icons/lucide/folder-plus"
import IconFilePlus from "~icons/lucide/file-plus" import IconFilePlus from "~icons/lucide/file-plus"
import IconMoreVertical from "~icons/lucide/more-vertical" import IconMoreVertical from "~icons/lucide/more-vertical"
@@ -166,6 +171,7 @@ const t = useI18n()
const props = defineProps<{ const props = defineProps<{
collectionView: RESTCollectionViewCollection collectionView: RESTCollectionViewCollection
isOpen: boolean isOpen: boolean
isSelected?: boolean | null
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
@@ -195,6 +201,9 @@ const exportAction = ref<HTMLButtonElement | null>(null)
const options = ref<TippyComponent | null>(null) const options = ref<TippyComponent | null>(null)
const collectionIcon = computed(() => { const collectionIcon = computed(() => {
if (props.isSelected) {
return IconCheckCircle
}
return !props.isOpen ? IconFolder : IconFolderOpen return !props.isOpen ? IconFolder : IconFolderOpen
}) })

View File

@@ -13,14 +13,20 @@
:class="requestLabelColor" :class="requestLabelColor"
:style="{ color: requestLabelColor }" :style="{ color: requestLabelColor }"
> >
<span class="truncate text-tiny font-semibold"> <component
:is="IconCheckCircle"
v-if="isSelected"
class="svg-icons"
:class="{ 'text-accent': isSelected }"
/>
<span v-else class="truncate text-tiny font-semibold">
{{ requestView.request.method }} {{ requestView.request.method }}
</span> </span>
</span> </span>
<span <span
class="pointer-events-none flex min-w-0 flex-1 items-center py-2 pr-2 transition group-hover:text-secondaryDark" class="pointer-events-none flex min-w-0 flex-1 items-center py-2 pr-2 transition group-hover:text-secondaryDark"
> >
<span class="truncate"> <span class="truncate" :class="{ 'text-accent': isSelected }">
{{ requestView.request.name }} {{ requestView.request.name }}
</span> </span>
<span <span
@@ -119,6 +125,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import IconCheckCircle from "~icons/lucide/check-circle"
import IconMoreVertical from "~icons/lucide/more-vertical" import IconMoreVertical from "~icons/lucide/more-vertical"
import IconEdit from "~icons/lucide/edit" import IconEdit from "~icons/lucide/edit"
import IconCopy from "~icons/lucide/copy" import IconCopy from "~icons/lucide/copy"
@@ -135,6 +142,7 @@ const t = useI18n()
const props = defineProps<{ const props = defineProps<{
isActive: boolean isActive: boolean
requestView: RESTCollectionViewRequest requestView: RESTCollectionViewRequest
isSelected: boolean | null | undefined
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{

View File

@@ -2,7 +2,11 @@
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<div <div
class="sticky z-10 flex flex-1 justify-between border-b border-dividerLight bg-primary" class="sticky z-10 flex flex-1 justify-between border-b border-dividerLight bg-primary"
:style="'top: var(--upper-primary-sticky-fold)'" :style="
saveRequest
? 'top: calc(var(--upper-primary-sticky-fold) - var(--line-height-body))'
: 'top: var(--upper-primary-sticky-fold)'
"
> >
<HoppButtonSecondary <HoppButtonSecondary
:icon="IconPlus" :icon="IconPlus"
@@ -19,6 +23,7 @@
:icon="IconHelpCircle" :icon="IconHelpCircle"
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-if="!saveRequest"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:icon="IconImport" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
@@ -30,27 +35,52 @@
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<HoppSmartTree :adapter="treeAdapter"> <HoppSmartTree :adapter="treeAdapter">
<template #content="{ node, toggleChildren, isOpen }"> <template #content="{ node, toggleChildren, isOpen }">
<!-- TODO: Implement -->
<NewCollectionsRestCollection <NewCollectionsRestCollection
v-if="node.data.type === 'collection'" v-if="node.data.type === 'collection'"
:collection-view="node.data.value" :collection-view="node.data.value"
:is-open="isOpen" :is-open="isOpen"
:is-selected="
isSelected(
getCollectionIndexPathArgs(node.data.value.collectionID)
)
"
:save-request="saveRequest"
@add-request="addRequest" @add-request="addRequest"
@add-child-collection="addChildCollection" @add-child-collection="addChildCollection"
@edit-root-collection="editRootCollection" @edit-root-collection="editRootCollection"
@edit-collection-properties="editCollectionProperties" @edit-collection-properties="editCollectionProperties"
@edit-child-collection="editChildCollection" @edit-child-collection="editChildCollection"
@select-pick="onSelectPick"
@remove-root-collection="removeRootCollection" @remove-root-collection="removeRootCollection"
@remove-child-collection="removeChildCollection" @remove-child-collection="removeChildCollection"
@toggle-children="toggleChildren" @toggle-children="
() => {
toggleChildren(),
saveRequest &&
onSelectPick({
pickedType: isAlreadyInRoot(node.data.value.collectionID)
? 'my-collection'
: 'my-folder',
...getCollectionIndexPathArgs(
node.data.value.collectionID
),
})
}
"
/> />
<NewCollectionsRestRequest <NewCollectionsRestRequest
v-else-if="node.data.type === 'request'" v-else-if="node.data.type === 'request'"
:is-active="isActiveRequest(node.data.value.request.id)" :is-active="isActiveRequest(node.data.value.request.id)"
:is-selected="
isSelected(getRequestIndexPathArgs(node.data.value.requestID))
"
:request-view="node.data.value" :request-view="node.data.value"
:save-request="saveRequest"
@duplicate-request="duplicateRequest" @duplicate-request="duplicateRequest"
@edit-request="editRequest" @edit-request="editRequest"
@remove-request="removeRequest" @remove-request="removeRequest"
@select-pick="onSelectPick"
@select-request="selectRequest" @select-request="selectRequest"
/> />
<div v-else @click="toggleChildren"> <div v-else @click="toggleChildren">
@@ -150,6 +180,7 @@ import { RESTTabService } from "~/services/tab/rest"
import IconImport from "~icons/lucide/folder-down" import IconImport from "~icons/lucide/folder-down"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import { Picked } from "~/helpers/types/HoppPicked"
const t = useI18n() const t = useI18n()
const toast = useToast() const toast = useToast()
@@ -157,9 +188,12 @@ const tabs = useService(RESTTabService)
const props = defineProps<{ const props = defineProps<{
workspaceHandle: HandleRef<Workspace> workspaceHandle: HandleRef<Workspace>
picked: Picked | null
saveRequest: boolean
}>() }>()
defineEmits<{ const emit = defineEmits<{
(event: "select", payload: Picked | null): void
(e: "display-modal-add"): void (e: "display-modal-add"): void
(e: "display-modal-import-export"): void (e: "display-modal-import-export"): void
}>() }>()
@@ -206,6 +240,37 @@ const editingProperties = ref<{
const confirmModalTitle = ref<string | null>(null) const confirmModalTitle = ref<string | null>(null)
const isSelected = ({
collectionIndex,
folderPath,
requestIndex,
}: {
collectionIndex?: number | undefined
folderPath?: string | undefined
requestIndex?: number | undefined
}) => {
if (collectionIndex !== undefined) {
return (
props.picked &&
props.picked.pickedType === "my-collection" &&
props.picked.collectionIndex === collectionIndex
)
} else if (requestIndex !== undefined && folderPath !== undefined) {
return (
props.picked &&
props.picked.pickedType === "my-request" &&
props.picked.folderPath === folderPath &&
props.picked.requestIndex === requestIndex
)
} else if (folderPath !== undefined) {
return (
props.picked &&
props.picked.pickedType === "my-folder" &&
props.picked.folderPath === folderPath
)
}
}
const displayModalAddRequest = (show: boolean) => { const displayModalAddRequest = (show: boolean) => {
showModalAddRequest.value = show showModalAddRequest.value = show
@@ -271,8 +336,8 @@ const addNewRootCollection = async (name: string) => {
showModalAdd.value = false showModalAdd.value = false
} }
const removeRootCollection = (collPathIndex: string) => { const removeRootCollection = (collectionIndexPath: string) => {
editingCollectionIndexPath.value = collPathIndex editingCollectionIndexPath.value = collectionIndexPath
confirmModalTitle.value = `${t("confirm.remove_collection")}` confirmModalTitle.value = `${t("confirm.remove_collection")}`
displayConfirmModal(true) displayConfirmModal(true)
@@ -298,6 +363,10 @@ const onRemoveRootCollection = async () => {
return return
} }
if (isSelected({ collectionIndex: parseInt(collectionIndexPath) })) {
emit("select", null)
}
const result = await workspaceService.removeRESTCollection(collectionHandle) const result = await workspaceService.removeRESTCollection(collectionHandle)
if (E.isLeft(result)) { if (E.isLeft(result)) {
@@ -552,6 +621,14 @@ const onRemoveChildCollection = async () => {
return return
} }
if (
isSelected({
folderPath: parentCollectionIndexPath.split("/").pop(),
})
) {
emit("select", null)
}
const result = await workspaceService.removeRESTCollection( const result = await workspaceService.removeRESTCollection(
parentCollectionHandle parentCollectionHandle
) )
@@ -600,6 +677,15 @@ const onRemoveRequest = async () => {
requestHandle, requestHandle,
}) })
if (
isSelected({
requestIndex: parseInt(requestIndexPath.split("/").pop() ?? ""),
folderPath: editingCollectionIndexPath.value,
})
) {
emit("select", null)
}
const result = await workspaceService.removeRESTRequest(requestHandle) const result = await workspaceService.removeRESTRequest(requestHandle)
if (E.isLeft(result)) { if (E.isLeft(result)) {
@@ -619,6 +705,15 @@ const onRemoveRequest = async () => {
const selectRequest = async (requestIndexPath: string) => { const selectRequest = async (requestIndexPath: string) => {
const collectionIndexPath = requestIndexPath.split("/").slice(0, -1).join("/") const collectionIndexPath = requestIndexPath.split("/").slice(0, -1).join("/")
const requestIndex = requestIndexPath.split("/").slice(-1)[0]
if (props.saveRequest) {
return emit("select", {
pickedType: "my-request",
folderPath: collectionIndexPath,
requestIndex: parseInt(requestIndex),
})
}
const collectionHandleResult = await workspaceService.getCollectionHandle( const collectionHandleResult = await workspaceService.getCollectionHandle(
props.workspaceHandle, props.workspaceHandle,
@@ -997,4 +1092,30 @@ const isActiveRequest = (requestID: string) => {
} }
return requestHandle.value.data.request.id === requestID return requestHandle.value.data.request.id === requestID
} }
const onSelectPick = (payload: Picked | null) => {
emit("select", payload)
}
const getCollectionIndexPathArgs = (
collectionIndexPath: string
): { collectionIndex: number } | { folderPath: string } => {
return isAlreadyInRoot(collectionIndexPath)
? {
collectionIndex: parseInt(collectionIndexPath),
}
: { folderPath: collectionIndexPath }
}
const getRequestIndexPathArgs = (requestIndexPath: string) => {
const requestIndexPathArr = pathToIndex(requestIndexPath)
const parentCollectionIndexPath = requestIndexPathArr.slice(0, -1).join("/")
const requestIndex = parseInt(requestIndexPathArr.slice(-1)[0])
return {
folderPath: parentCollectionIndexPath,
requestIndex,
}
}
</script> </script>

View File

@@ -20,28 +20,29 @@ export type Picked =
pickedType: "my-collection" pickedType: "my-collection"
collectionIndex: number collectionIndex: number
} }
| { // TODO: Enable this when rest of the implementation is in place
pickedType: "teams-request" // | {
requestID: string // pickedType: "teams-request"
} // requestID: string
| { // }
pickedType: "teams-folder" // | {
folderID: string // pickedType: "teams-folder"
} // folderID: string
| { // }
pickedType: "teams-collection" // | {
collectionID: string // pickedType: "teams-collection"
} // collectionID: string
| { // }
pickedType: "gql-my-request" // | {
folderPath: string // pickedType: "gql-my-request"
requestIndex: number // folderPath: string
} // requestIndex: number
| { // }
pickedType: "gql-my-folder" // | {
folderPath: string // pickedType: "gql-my-folder"
} // folderPath: string
| { // }
pickedType: "gql-my-collection" // | {
collectionIndex: number // pickedType: "gql-my-collection"
} // collectionIndex: number
// }