refactor: iterations
This commit is contained in:
@@ -22,20 +22,28 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!collectionReadonly" class="flex">
|
<div class="flex">
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:icon="IconFilePlus"
|
:icon="IconFilePlus"
|
||||||
:title="t('request.new')"
|
:title="t('request.new')"
|
||||||
class="hidden group-hover:inline-flex"
|
class="hidden group-hover:inline-flex"
|
||||||
@click="emit('add-request')"
|
@click="
|
||||||
|
emit('add-request', {
|
||||||
|
path: collection.collectionID,
|
||||||
|
})
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:icon="IconFolderPlus"
|
:icon="IconFolderPlus"
|
||||||
:title="t('folder.new')"
|
:title="t('folder.new')"
|
||||||
class="hidden group-hover:inline-flex"
|
class="hidden group-hover:inline-flex"
|
||||||
@click="emit('add-folder')"
|
@click="
|
||||||
|
emit('add-folder', {
|
||||||
|
path: collection.collectionID,
|
||||||
|
})
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
<tippy
|
<tippy
|
||||||
@@ -69,7 +77,9 @@
|
|||||||
:shortcut="['R']"
|
:shortcut="['R']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('add-request')
|
emit('add-request', {
|
||||||
|
path: collection.collectionID,
|
||||||
|
})
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@@ -81,7 +91,9 @@
|
|||||||
:shortcut="['N']"
|
:shortcut="['N']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('add-folder')
|
emit('add-folder', {
|
||||||
|
path: collection.collectionID,
|
||||||
|
})
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@@ -105,8 +117,7 @@
|
|||||||
:shortcut="['X']"
|
:shortcut="['X']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('export-data'),
|
emit('export-data'), hide()
|
||||||
collectionsType === 'my-collections' ? hide() : null
|
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
@@ -117,7 +128,9 @@
|
|||||||
:shortcut="['⌫']"
|
:shortcut="['⌫']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('remove-collection')
|
emit('remove-collection', {
|
||||||
|
path: collection.collectionID,
|
||||||
|
})
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@@ -150,17 +163,31 @@ const t = useI18n()
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
collection: RESTCollectionViewCollection
|
collection: RESTCollectionViewCollection
|
||||||
collectionReadonly: boolean
|
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: "toggle-children"): void
|
(event: "toggle-children"): void
|
||||||
(event: "add-request"): void
|
(
|
||||||
(event: "add-folder"): void
|
event: "add-request",
|
||||||
|
payload: {
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
): void
|
||||||
|
(
|
||||||
|
event: "add-folder",
|
||||||
|
payload: {
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
): void
|
||||||
(event: "edit-collection"): void
|
(event: "edit-collection"): void
|
||||||
(event: "export-data"): void
|
(event: "export-data"): void
|
||||||
(event: "remove-collection"): void
|
(
|
||||||
|
event: "remove-collection",
|
||||||
|
payload: {
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="pointer-events-auto flex min-w-0 flex-1 cursor-pointer items-center justify-center"
|
class="pointer-events-auto flex min-w-0 flex-1 cursor-pointer items-center justify-center"
|
||||||
|
@click="selectRequest(request.requestID, request.request)"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="pointer-events-none flex w-16 items-center justify-center truncate px-2"
|
class="pointer-events-none flex w-16 items-center justify-center truncate px-2"
|
||||||
@@ -38,12 +39,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!collectionReadonly" class="flex">
|
<div class="flex">
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:icon="IconRotateCCW"
|
:icon="IconRotateCCW"
|
||||||
:title="t('action.restore')"
|
:title="t('action.restore')"
|
||||||
class="hidden group-hover:inline-flex"
|
class="hidden group-hover:inline-flex"
|
||||||
|
@click="selectRequest(request.requestID, request.request)"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
<tippy
|
<tippy
|
||||||
@@ -75,7 +77,10 @@
|
|||||||
:shortcut="['E']"
|
:shortcut="['E']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('edit-request')
|
emit('edit-request', {
|
||||||
|
requestPath: request.requestID,
|
||||||
|
request: request.request,
|
||||||
|
})
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@@ -87,7 +92,10 @@
|
|||||||
:shortcut="['D']"
|
:shortcut="['D']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('duplicate-request')
|
emit('duplicate-request', {
|
||||||
|
requestPath: request.requestID,
|
||||||
|
request: request.request,
|
||||||
|
})
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@@ -124,12 +132,37 @@ import { RESTCollectionViewRequest } from "~/services/new-workspace/view"
|
|||||||
import { computed, ref } from "vue"
|
import { computed, ref } from "vue"
|
||||||
import { TippyComponent } from "vue-tippy"
|
import { TippyComponent } from "vue-tippy"
|
||||||
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
|
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
request: RESTCollectionViewRequest
|
request: RESTCollectionViewRequest
|
||||||
collectionReadonly: boolean
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(
|
||||||
|
event: "duplicate-request",
|
||||||
|
payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}
|
||||||
|
): void
|
||||||
|
(
|
||||||
|
event: "edit-request",
|
||||||
|
payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}
|
||||||
|
): void
|
||||||
|
(event: "remove-request"): void
|
||||||
|
(
|
||||||
|
event: "select-request",
|
||||||
|
payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}
|
||||||
|
): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tippyActions = ref<TippyComponent | null>(null)
|
const tippyActions = ref<TippyComponent | null>(null)
|
||||||
@@ -141,4 +174,10 @@ const isActive = ref(true)
|
|||||||
const requestLabelColor = computed(() =>
|
const requestLabelColor = computed(() =>
|
||||||
getMethodLabelColorClassOf(props.request)
|
getMethodLabelColorClassOf(props.request)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const selectRequest = (requestPath: string, request: HoppRESTRequest) =>
|
||||||
|
emit("select-request", {
|
||||||
|
requestPath,
|
||||||
|
request,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="collectionsAreReadonly !== undefined" 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="'top: var(--upper-primary-sticky-fold)'"
|
||||||
>
|
>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-if="collectionsAreReadonly"
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
disabled
|
|
||||||
class="!rounded-none"
|
|
||||||
:icon="IconPlus"
|
|
||||||
:title="t('team.no_access')"
|
|
||||||
:label="t('add.new')"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-else
|
|
||||||
:icon="IconPlus"
|
:icon="IconPlus"
|
||||||
:label="t('add.new')"
|
:label="t('add.new')"
|
||||||
class="!rounded-none"
|
class="!rounded-none"
|
||||||
@@ -36,59 +26,114 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-1 flex-col">
|
<div class="flex flex-1 flex-col">
|
||||||
<HoppSmartTree :adapter="treeAdapter">
|
<HoppSmartTree :adapter="treeAdapter">
|
||||||
<template
|
<template #content="{ node, toggleChildren, isOpen }">
|
||||||
#content="{ node, toggleChildren, isOpen, highlightChildren }"
|
|
||||||
>
|
|
||||||
<!-- TODO: Implement -->
|
<!-- TODO: Implement -->
|
||||||
<NewCollectionsRestCollection
|
<NewCollectionsRestCollection
|
||||||
v-if="node.data.type === 'collection'"
|
v-if="node.data.type === 'collection'"
|
||||||
:collection="node.data.value"
|
:collection="node.data.value"
|
||||||
:collection-readonly="collectionsAreReadonly"
|
|
||||||
:is-open="isOpen"
|
:is-open="isOpen"
|
||||||
|
@add-request="addRequest"
|
||||||
|
@add-folder="addFolder"
|
||||||
|
@remove-collection="removeFolder"
|
||||||
@toggle-children="toggleChildren"
|
@toggle-children="toggleChildren"
|
||||||
/>
|
/>
|
||||||
|
<NewCollectionsRestRequest
|
||||||
|
v-else-if="node.data.type === 'request'"
|
||||||
|
:request="node.data.value"
|
||||||
|
@duplicate-request="duplicateRequest"
|
||||||
|
@edit-request="editRequest"
|
||||||
|
@remove-request="removeRequest(node.data.value.requestID)"
|
||||||
|
@select-request="selectRequest"
|
||||||
|
/>
|
||||||
<div v-else @click="toggleChildren">
|
<div v-else @click="toggleChildren">
|
||||||
{{ node.data.value }}
|
{{ node.data.value }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #emptyNode="{ node }">
|
<template #emptyNode>
|
||||||
<!-- TODO: Implement -->
|
<!-- TODO: Implement -->
|
||||||
<div>Empty Node!</div>
|
<div>Empty Node!</div>
|
||||||
</template>
|
</template>
|
||||||
</HoppSmartTree>
|
</HoppSmartTree>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CollectionsAdd
|
<CollectionsAdd
|
||||||
:show="showModalAdd"
|
:show="showModalAdd"
|
||||||
:loading-state="modalLoadingState"
|
:loading-state="modalLoadingState"
|
||||||
@submit="addNewRootCollection"
|
@submit="addNewRootCollection"
|
||||||
@hide-modal="showModalAdd = false"
|
@hide-modal="showModalAdd = false"
|
||||||
/>
|
/>
|
||||||
|
<CollectionsAddRequest
|
||||||
|
:show="showModalAddRequest"
|
||||||
|
:loading-state="modalLoadingState"
|
||||||
|
@add-request="onAddRequest"
|
||||||
|
@hide-modal="displayModalAddRequest(false)"
|
||||||
|
/>
|
||||||
|
<CollectionsAddFolder
|
||||||
|
:show="showModalAddFolder"
|
||||||
|
:loading-state="modalLoadingState"
|
||||||
|
@add-folder="onAddFolder"
|
||||||
|
@hide-modal="displayModalAddFolder(false)"
|
||||||
|
/>
|
||||||
|
<CollectionsEditRequest
|
||||||
|
v-model="editingRequestName"
|
||||||
|
:show="showModalEditRequest"
|
||||||
|
:loading-state="modalLoadingState"
|
||||||
|
@submit="onEditRequest"
|
||||||
|
@hide-modal="displayModalEditRequest(false)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HoppSmartConfirmModal
|
||||||
|
:show="showConfirmModal"
|
||||||
|
:title="confirmModalTitle"
|
||||||
|
:loading-state="modalLoadingState"
|
||||||
|
@hide-modal="showConfirmModal = false"
|
||||||
|
@resolve="resolveConfirmModal"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import * as E from "fp-ts/lib/Either"
|
import * as E from "fp-ts/lib/Either"
|
||||||
|
|
||||||
|
import { useService } from "dioc/vue"
|
||||||
|
import { markRaw, ref } from "vue"
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import IconPlus from "~icons/lucide/plus"
|
import { useToast } from "~/composables/toast"
|
||||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
|
||||||
import IconImport from "~icons/lucide/folder-down"
|
|
||||||
import { HandleRef } from "~/services/new-workspace/handle"
|
|
||||||
import { Workspace } from "~/services/new-workspace/workspace"
|
|
||||||
import { computed, markRaw, ref } from "vue"
|
|
||||||
import { WorkspaceRESTCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionTreeAdapter"
|
import { WorkspaceRESTCollectionTreeAdapter } from "~/helpers/adapters/WorkspaceRESTCollectionTreeAdapter"
|
||||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||||
import { useService } from "dioc/vue"
|
import { HandleRef } from "~/services/new-workspace/handle"
|
||||||
|
import { Workspace } from "~/services/new-workspace/workspace"
|
||||||
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
|
import IconImport from "~icons/lucide/folder-down"
|
||||||
|
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||||
|
import IconPlus from "~icons/lucide/plus"
|
||||||
|
import {
|
||||||
|
resolveSaveContextOnCollectionReorder,
|
||||||
|
getFoldersByPath,
|
||||||
|
} from "~/helpers/collection/collection"
|
||||||
|
import {
|
||||||
|
navigateToFolderWithIndexPath,
|
||||||
|
restCollectionStore,
|
||||||
|
removeRESTFolder,
|
||||||
|
restCollections$,
|
||||||
|
} from "~/newstore/collections"
|
||||||
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
|
import { cloneDeep } from "lodash-es"
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
const toast = useToast()
|
||||||
|
const tabs = useService(RESTTabService)
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
workspaceHandle: HandleRef<Workspace>
|
workspaceHandle: HandleRef<Workspace>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
defineEmits<{
|
||||||
(e: "display-modal-add"): void
|
(e: "display-modal-add"): void
|
||||||
(e: "display-modal-import-export"): void
|
(e: "display-modal-import-export"): void
|
||||||
}>()
|
}>()
|
||||||
@@ -101,18 +146,48 @@ const treeAdapter = markRaw(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const collectionsAreReadonly = computed(() => {
|
|
||||||
if (props.workspaceHandle.value.type === "ok") {
|
|
||||||
return props.workspaceHandle.value.data.collectionsAreReadonly
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
const showModalAdd = ref(false)
|
|
||||||
const modalLoadingState = ref(false)
|
const modalLoadingState = ref(false)
|
||||||
|
|
||||||
async function addNewRootCollection(name: string) {
|
const showModalAdd = ref(false)
|
||||||
|
const showModalAddRequest = ref(false)
|
||||||
|
const showModalAddFolder = ref(false)
|
||||||
|
const showModalEditRequest = ref(false)
|
||||||
|
const showConfirmModal = ref(false)
|
||||||
|
|
||||||
|
const editingFolderPath = ref<string | null>(null)
|
||||||
|
const editingRequest = ref<HoppRESTRequest | null>(null)
|
||||||
|
const editingRequestName = ref("")
|
||||||
|
const editingRequestIndex = ref<number | null>(null)
|
||||||
|
|
||||||
|
const confirmModalTitle = ref<string | null>(null)
|
||||||
|
|
||||||
|
const myCollections = useReadonlyStream(restCollections$, [], "deep")
|
||||||
|
|
||||||
|
const displayModalAddRequest = (show: boolean) => {
|
||||||
|
showModalAddRequest.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayModalAddFolder = (show: boolean) => {
|
||||||
|
showModalAddFolder.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayModalEditRequest = (show: boolean) => {
|
||||||
|
showModalEditRequest.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayConfirmModal = (show: boolean) => {
|
||||||
|
showConfirmModal.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const addNewRootCollection = async (name: string) => {
|
||||||
modalLoadingState.value = true
|
modalLoadingState.value = true
|
||||||
|
|
||||||
const result = await workspaceService.createRESTRootCollection(
|
const result = await workspaceService.createRESTRootCollection(
|
||||||
@@ -135,7 +210,379 @@ async function addNewRootCollection(name: string) {
|
|||||||
showModalAdd.value = false
|
showModalAdd.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addRequest = (payload: { path: string }) => {
|
||||||
|
const { path } = payload
|
||||||
|
editingFolderPath.value = path
|
||||||
|
displayModalAddRequest(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAddRequest = async (requestName: string) => {
|
||||||
|
const path = editingFolderPath.value
|
||||||
|
if (!path) return
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.createRESTRequest(
|
||||||
|
collHandle,
|
||||||
|
requestName,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
displayModalAddRequest(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addFolder = (payload: { path: string }) => {
|
||||||
|
const { path } = payload
|
||||||
|
editingFolderPath.value = path
|
||||||
|
displayModalAddFolder(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAddFolder = async (folderName: string) => {
|
||||||
|
const path = editingFolderPath.value
|
||||||
|
|
||||||
|
if (!path) return
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.createRESTChildCollection(
|
||||||
|
collHandle,
|
||||||
|
folderName,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
displayModalAddFolder(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeFolder = (payload: { path: string }) => {
|
||||||
|
const { path } = payload
|
||||||
|
editingFolderPath.value = path
|
||||||
|
|
||||||
|
confirmModalTitle.value = `${t("confirm.remove_folder")}`
|
||||||
|
displayConfirmModal(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRemoveFolder = () => {
|
||||||
|
const path = editingFolderPath.value
|
||||||
|
|
||||||
|
if (!path) return
|
||||||
|
|
||||||
|
const folderToRemove = path
|
||||||
|
? navigateToFolderWithIndexPath(
|
||||||
|
restCollectionStore.value.state,
|
||||||
|
path.split("/").map((i) => parseInt(i))
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
removeRESTFolder(path, folderToRemove ? folderToRemove.id : undefined)
|
||||||
|
|
||||||
|
const parentFolder = path.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
|
||||||
|
resolveSaveContextOnCollectionReorder({
|
||||||
|
lastIndex: pathToLastIndex(path),
|
||||||
|
newIndex: -1,
|
||||||
|
folderPath: parentFolder,
|
||||||
|
length: getFoldersByPath(myCollections.value, parentFolder).length,
|
||||||
|
})
|
||||||
|
|
||||||
|
toast.success(t("state.deleted"))
|
||||||
|
displayConfirmModal(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeRequest = (requestIndex: string) => {
|
||||||
|
const folderPath = requestIndex.slice(0, -2)
|
||||||
|
const requestID = requestIndex[requestIndex.length - 1]
|
||||||
|
|
||||||
|
editingFolderPath.value = folderPath
|
||||||
|
editingRequestIndex.value = parseInt(requestID)
|
||||||
|
|
||||||
|
confirmModalTitle.value = `${t("confirm.remove_request")}`
|
||||||
|
displayConfirmModal(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRemoveRequest = async () => {
|
||||||
|
const path = editingFolderPath.value
|
||||||
|
const requestIndex = editingRequestIndex.value
|
||||||
|
|
||||||
|
if (path === null || requestIndex === null) return
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.removeRESTRequest(
|
||||||
|
collHandle,
|
||||||
|
path,
|
||||||
|
requestIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success(t("state.deleted"))
|
||||||
|
displayConfirmModal(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectRequest = async (payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}) => {
|
||||||
|
const { requestPath, request } = payload
|
||||||
|
|
||||||
|
const collPath = requestPath.slice(0, -2)
|
||||||
|
const requestIndex = requestPath[requestPath.length - 1]
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
collPath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.selectRESTRequest(
|
||||||
|
collHandle,
|
||||||
|
collPath,
|
||||||
|
requestIndex,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const duplicateRequest = async (payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}) => {
|
||||||
|
const { requestPath, request } = payload
|
||||||
|
|
||||||
|
const collPath = requestPath.slice(0, -2)
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
collPath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const newRequest = {
|
||||||
|
...cloneDeep(request),
|
||||||
|
name: `${request.name} - ${t("action.duplicate")}`,
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.duplicateRESTRequest(
|
||||||
|
collHandle,
|
||||||
|
collPath,
|
||||||
|
newRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success(t("request.duplicated"))
|
||||||
|
}
|
||||||
|
|
||||||
|
const editRequest = (payload: {
|
||||||
|
requestPath: string
|
||||||
|
request: HoppRESTRequest
|
||||||
|
}) => {
|
||||||
|
const { requestPath, request } = payload
|
||||||
|
const collPath = requestPath.slice(0, -2)
|
||||||
|
const requestIndex = requestPath[requestPath.length - 1]
|
||||||
|
|
||||||
|
editingRequest.value = request
|
||||||
|
editingRequestName.value = request.name ?? ""
|
||||||
|
editingFolderPath.value = collPath
|
||||||
|
editingRequestIndex.value = parseInt(requestIndex)
|
||||||
|
|
||||||
|
displayModalEditRequest(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEditRequest = async (newReqName: string) => {
|
||||||
|
const collPath = editingFolderPath.value
|
||||||
|
const requestIndex = editingRequestIndex.value
|
||||||
|
const request = editingRequest.value
|
||||||
|
|
||||||
|
if (collPath === null || requestIndex === null || !request) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
collPath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collHandle = collHandleResult.right
|
||||||
|
|
||||||
|
if (collHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedRequest = {
|
||||||
|
...request,
|
||||||
|
name: newReqName || request.name,
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await workspaceService.editRESTRequest(
|
||||||
|
collHandle,
|
||||||
|
collPath,
|
||||||
|
requestIndex,
|
||||||
|
updatedRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.right.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
displayModalEditRequest(false)
|
||||||
|
toast.success(t("request.renamed"))
|
||||||
|
}
|
||||||
|
|
||||||
function onImportExportClick() {
|
function onImportExportClick() {
|
||||||
// TODO: Implement
|
// TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolveConfirmModal = (title: string | null) => {
|
||||||
|
if (title === `${t("confirm.remove_collection")}`) {
|
||||||
|
// onRemoveCollection()
|
||||||
|
} else if (title === `${t("confirm.remove_request")}`) {
|
||||||
|
onRemoveRequest()
|
||||||
|
} else if (title === `${t("confirm.remove_folder")}`) {
|
||||||
|
onRemoveFolder()
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`Confirm modal title ${title} is not handled by the component`
|
||||||
|
)
|
||||||
|
toast.error(t("error.something_went_wrong"))
|
||||||
|
displayConfirmModal(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetSelectedData = () => {
|
||||||
|
editingFolderPath.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get the index of the request from the path
|
||||||
|
* @param path The path of the request
|
||||||
|
* @returns The index of the request
|
||||||
|
*/
|
||||||
|
const pathToLastIndex = (path: string) => {
|
||||||
|
const pathArr = path.split("/")
|
||||||
|
return parseInt(pathArr[pathArr.length - 1])
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
ChildrenResult,
|
ChildrenResult,
|
||||||
SmartTreeAdapter,
|
SmartTreeAdapter,
|
||||||
} from "@hoppscotch/ui/dist/src/helpers/treeAdapter"
|
} from "@hoppscotch/ui/dist/src/helpers/treeAdapter"
|
||||||
import { Ref, computed, ref, watchEffect } from "vue"
|
import { Ref, ref, watchEffect } from "vue"
|
||||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||||
import { HandleRef } from "~/services/new-workspace/handle"
|
import { HandleRef } from "~/services/new-workspace/handle"
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { pipe } from "fp-ts/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import * as RR from "fp-ts/ReadonlyRecord"
|
import * as RR from "fp-ts/ReadonlyRecord"
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
export const REQUEST_METHOD_LABEL_COLORS = {
|
export const REQUEST_METHOD_LABEL_COLORS = {
|
||||||
get: "var(--success-color)",
|
get: "var(--method-get-color)",
|
||||||
post: "var(--warning-color)",
|
post: "var(--method-post-color)",
|
||||||
put: "var(--blue-color)",
|
put: "var(--method-put-color)",
|
||||||
delete: "var(--cl-error-color)",
|
patch: "var(--method-patch-color)",
|
||||||
default: "#6b7280",
|
delete: "var(--method-delete-color)",
|
||||||
|
head: "var(--method-head-color)",
|
||||||
|
options: "var(--method-options-color)",
|
||||||
|
default: "var(--method-default-color)",
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,10 +19,18 @@ export const REQUEST_METHOD_LABEL_COLORS = {
|
|||||||
* @param request The HoppRESTRequest object to get the value for
|
* @param request The HoppRESTRequest object to get the value for
|
||||||
* @returns The class value for the given HTTP VERB, if not, a generic verb class
|
* @returns The class value for the given HTTP VERB, if not, a generic verb class
|
||||||
*/
|
*/
|
||||||
export function getMethodLabelColorClassOf(request: { method: string }) {
|
export function getMethodLabelColorClassOf(request: HoppRESTRequest) {
|
||||||
return pipe(
|
return pipe(
|
||||||
REQUEST_METHOD_LABEL_COLORS,
|
REQUEST_METHOD_LABEL_COLORS,
|
||||||
RR.lookup(request.method.toLowerCase()),
|
RR.lookup(request.method.toLowerCase()),
|
||||||
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
|
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMethodLabelColor(method: string) {
|
||||||
|
return pipe(
|
||||||
|
REQUEST_METHOD_LABEL_COLORS,
|
||||||
|
RR.lookup(method.toLowerCase()),
|
||||||
|
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export function createHoppApp(el: string | Element, platformDef: PlatformDef) {
|
|||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app))
|
||||||
|
platformDef.addedHoppModules?.forEach((mod) => mod.onVueAppInit?.(app))
|
||||||
|
|
||||||
// Some basic work that needs to be done before module inits even
|
// Some basic work that needs to be done before module inits even
|
||||||
initBackendGQLClient()
|
initBackendGQLClient()
|
||||||
initializeApp()
|
initializeApp()
|
||||||
@@ -37,9 +40,6 @@ export function createHoppApp(el: string | Element, platformDef: PlatformDef) {
|
|||||||
getService(TestWorkspaceProviderService)
|
getService(TestWorkspaceProviderService)
|
||||||
getService(PersonalWorkspaceProviderService)
|
getService(PersonalWorkspaceProviderService)
|
||||||
|
|
||||||
HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app))
|
|
||||||
platformDef.addedHoppModules?.forEach((mod) => mod.onVueAppInit?.(app))
|
|
||||||
|
|
||||||
app.mount(el)
|
app.mount(el)
|
||||||
|
|
||||||
console.info(
|
console.info(
|
||||||
|
|||||||
@@ -319,6 +319,7 @@ const restCollectionDispatchers = defineDispatchers({
|
|||||||
)
|
)
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We get the index path to the folder itself,
|
// We get the index path to the folder itself,
|
||||||
// we have to find the folder containing the target folder,
|
// we have to find the folder containing the target folder,
|
||||||
// so we pop the last path index
|
// so we pop the last path index
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { HandleRef } from "./handle"
|
|||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { Workspace, WorkspaceCollection } from "./workspace"
|
import { Workspace, WorkspaceCollection } from "./workspace"
|
||||||
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
|
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
export type WorkspaceError<ServiceErr> =
|
export type WorkspaceError<ServiceErr> =
|
||||||
| { type: "SERVICE_ERROR"; error: ServiceErr }
|
| { type: "SERVICE_ERROR"; error: ServiceErr }
|
||||||
@@ -172,7 +173,8 @@ export class NewWorkspaceService extends Service {
|
|||||||
|
|
||||||
public async createRESTChildCollection(
|
public async createRESTChildCollection(
|
||||||
parentCollHandle: HandleRef<WorkspaceCollection>,
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
collectionName: string
|
collectionName: string,
|
||||||
|
path: string
|
||||||
): Promise<
|
): Promise<
|
||||||
E.Either<
|
E.Either<
|
||||||
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
@@ -193,7 +195,8 @@ export class NewWorkspaceService extends Service {
|
|||||||
|
|
||||||
const result = await provider.createRESTChildCollection(
|
const result = await provider.createRESTChildCollection(
|
||||||
parentCollHandle,
|
parentCollHandle,
|
||||||
collectionName
|
collectionName,
|
||||||
|
path
|
||||||
)
|
)
|
||||||
|
|
||||||
if (E.isLeft(result)) {
|
if (E.isLeft(result)) {
|
||||||
@@ -203,6 +206,186 @@ export class NewWorkspaceService extends Service {
|
|||||||
return E.right(result.right)
|
return E.right(result.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async createRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
requestName: string,
|
||||||
|
path: string
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (parentCollHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
parentCollHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.createRESTRequest(
|
||||||
|
parentCollHandle,
|
||||||
|
requestName,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async removeRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
path: string,
|
||||||
|
requestIndex: number
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (parentCollHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
parentCollHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.removeRESTRequest(
|
||||||
|
parentCollHandle,
|
||||||
|
path,
|
||||||
|
requestIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async selectRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (parentCollHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
parentCollHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.selectRESTRequest(
|
||||||
|
parentCollHandle,
|
||||||
|
collPath,
|
||||||
|
requestIndex,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async duplicateRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (parentCollHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
parentCollHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.duplicateRESTRequest(
|
||||||
|
parentCollHandle,
|
||||||
|
collPath,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async editRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: number,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (parentCollHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
parentCollHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.editRESTRequest(
|
||||||
|
parentCollHandle,
|
||||||
|
collPath,
|
||||||
|
requestIndex,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async getRESTCollectionChildrenView(
|
public async getRESTCollectionChildrenView(
|
||||||
collectionHandle: HandleRef<WorkspaceCollection>
|
collectionHandle: HandleRef<WorkspaceCollection>
|
||||||
): Promise<
|
): Promise<
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as E from "fp-ts/Either"
|
|||||||
import { HandleRef } from "./handle"
|
import { HandleRef } from "./handle"
|
||||||
import { Workspace, WorkspaceCollection, WorkspaceDecor } from "./workspace"
|
import { Workspace, WorkspaceCollection, WorkspaceDecor } from "./workspace"
|
||||||
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
|
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
export interface WorkspaceProvider {
|
export interface WorkspaceProvider {
|
||||||
providerID: string
|
providerID: string
|
||||||
@@ -30,6 +31,34 @@ export interface WorkspaceProvider {
|
|||||||
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
createRESTChildCollection(
|
createRESTChildCollection(
|
||||||
parentCollHandle: HandleRef<WorkspaceCollection>,
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
collectionName: string
|
collectionName: string,
|
||||||
|
path: string
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
createRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
requestName: string,
|
||||||
|
path: string
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
removeRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
path: string,
|
||||||
|
requestIndex: number
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
selectRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
duplicateRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
editRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: number,
|
||||||
|
request: HoppRESTRequest
|
||||||
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import {
|
import { HoppCollection, makeCollection } from "@hoppscotch/data"
|
||||||
HoppCollection,
|
|
||||||
HoppRESTRequest,
|
|
||||||
makeCollection,
|
|
||||||
} from "@hoppscotch/data"
|
|
||||||
import { Service } from "dioc"
|
import { Service } from "dioc"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { get } from "lodash-es"
|
import { Ref, computed, markRaw, nextTick, ref, shallowRef } from "vue"
|
||||||
import { v4 as uuid } from "uuid"
|
|
||||||
import { Ref, computed, markRaw, ref, shallowReactive, shallowRef } from "vue"
|
|
||||||
|
|
||||||
import PersonalWorkspaceSelector from "~/components/workspace/PersonalWorkspaceSelector.vue"
|
import PersonalWorkspaceSelector from "~/components/workspace/PersonalWorkspaceSelector.vue"
|
||||||
import { useStreamStatic } from "~/composables/stream"
|
import { useStreamStatic } from "~/composables/stream"
|
||||||
|
|
||||||
import { addRESTCollection, restCollectionStore } from "~/newstore/collections"
|
import {
|
||||||
|
addRESTCollection,
|
||||||
|
addRESTFolder,
|
||||||
|
cascadeParentCollectionForHeaderAuth,
|
||||||
|
editRESTRequest,
|
||||||
|
navigateToFolderWithIndexPath,
|
||||||
|
removeRESTRequest,
|
||||||
|
restCollectionStore,
|
||||||
|
saveRESTRequestAs,
|
||||||
|
} from "~/newstore/collections"
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
import { HandleRef } from "~/services/new-workspace/handle"
|
import { HandleRef } from "~/services/new-workspace/handle"
|
||||||
@@ -28,8 +31,15 @@ import {
|
|||||||
WorkspaceDecor,
|
WorkspaceDecor,
|
||||||
} from "~/services/new-workspace/workspace"
|
} from "~/services/new-workspace/workspace"
|
||||||
|
|
||||||
|
import { cloneDeep } from "lodash-es"
|
||||||
|
import {
|
||||||
|
getRequestsByPath,
|
||||||
|
resolveSaveContextOnRequestReorder,
|
||||||
|
} from "~/helpers/collection/request"
|
||||||
|
import { RESTTabService } from "~/services/tab/rest"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { NewWorkspaceService } from ".."
|
import { NewWorkspaceService } from ".."
|
||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
|
||||||
export class PersonalWorkspaceProviderService
|
export class PersonalWorkspaceProviderService
|
||||||
extends Service
|
extends Service
|
||||||
@@ -40,6 +50,7 @@ export class PersonalWorkspaceProviderService
|
|||||||
public readonly providerID = "PERSONAL_WORKSPACE_PROVIDER"
|
public readonly providerID = "PERSONAL_WORKSPACE_PROVIDER"
|
||||||
|
|
||||||
private workspaceService = this.bind(NewWorkspaceService)
|
private workspaceService = this.bind(NewWorkspaceService)
|
||||||
|
private tabs = this.bind(RESTTabService)
|
||||||
|
|
||||||
public workspaceDecor: Ref<WorkspaceDecor> = ref({
|
public workspaceDecor: Ref<WorkspaceDecor> = ref({
|
||||||
headerCurrentIcon: IconUser,
|
headerCurrentIcon: IconUser,
|
||||||
@@ -63,77 +74,68 @@ export class PersonalWorkspaceProviderService
|
|||||||
this.workspaceService.registerWorkspaceProvider(this)
|
this.workspaceService.registerWorkspaceProvider(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private collectionIDMap = shallowReactive(
|
private navigateToFolderWithIndexPath(
|
||||||
new WeakMap<HoppCollection, string>()
|
collections: HoppCollection[],
|
||||||
)
|
indexPaths: number[]
|
||||||
|
|
||||||
private reqIDMap = shallowReactive(new WeakMap<HoppRESTRequest, string>())
|
|
||||||
|
|
||||||
private collectionIDPathMap = shallowReactive(new Map<string, number[]>())
|
|
||||||
|
|
||||||
private generatedUUIDs = new Set<string>()
|
|
||||||
|
|
||||||
private generateUniqueUUID() {
|
|
||||||
let id = uuid()
|
|
||||||
|
|
||||||
while (this.generatedUUIDs.has(id)) {
|
|
||||||
id = uuid()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.generatedUUIDs.add(id)
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
private resolvePathFromCollectionID(id: string): number[] | undefined {
|
|
||||||
return this.collectionIDPathMap.get(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
private resolveCollectionFromCollectionID(
|
|
||||||
id: string
|
|
||||||
): HoppCollection | undefined {
|
|
||||||
const path = this.resolvePathFromCollectionID(id)
|
|
||||||
|
|
||||||
if (path === undefined) return
|
|
||||||
|
|
||||||
const collPath = path.flatMap((x, i) =>
|
|
||||||
i === 0 ? [x.toString()] : ["folders", x.toString()]
|
|
||||||
)
|
|
||||||
|
|
||||||
const coll = get(this.restCollectionState.value.state, collPath) as
|
|
||||||
| HoppCollection
|
|
||||||
| undefined
|
|
||||||
|
|
||||||
return coll
|
|
||||||
}
|
|
||||||
|
|
||||||
private getIssuedInstanceIDForCollection(
|
|
||||||
coll: HoppCollection,
|
|
||||||
location: number[]
|
|
||||||
) {
|
) {
|
||||||
const id = this.collectionIDMap.has(coll)
|
if (indexPaths.length === 0) return null
|
||||||
? this.collectionIDMap.get(coll)!
|
|
||||||
: this.generateUniqueUUID()
|
|
||||||
|
|
||||||
this.collectionIDPathMap.set(id, location)
|
let target = collections[indexPaths.shift() as number]
|
||||||
this.collectionIDMap.set(coll, id)
|
|
||||||
|
|
||||||
return id
|
while (indexPaths.length > 0)
|
||||||
}
|
target = target?.folders[indexPaths.shift() as number]
|
||||||
|
|
||||||
private getIssuedInstanceIDForRequest(req: HoppRESTRequest) {
|
return target !== undefined ? target : null
|
||||||
const id = this.reqIDMap.get(req) ?? this.generateUniqueUUID()
|
|
||||||
|
|
||||||
this.reqIDMap.set(req, id)
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createRESTChildCollection(
|
public createRESTChildCollection(
|
||||||
parentCollHandle: HandleRef<WorkspaceCollection>,
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
collectionName: string
|
collectionName: string,
|
||||||
|
path: string
|
||||||
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
throw new Error("TODO: Method not implemented.")
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRESTFolder(collectionName, path)
|
||||||
|
|
||||||
|
platform.analytics?.logEvent({
|
||||||
|
type: "HOPP_CREATE_COLLECTION",
|
||||||
|
workspaceType: "personal",
|
||||||
|
isRootCollection: false,
|
||||||
|
platform: "rest",
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.collectionID,
|
||||||
|
name: collectionName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public createRESTRootCollection(
|
public createRESTRootCollection(
|
||||||
@@ -157,7 +159,7 @@ export class PersonalWorkspaceProviderService
|
|||||||
workspaceHandle.value.data.workspaceID !== "personal"
|
workspaceHandle.value.data.workspaceID !== "personal"
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
type: "invalid",
|
type: "invalid" as const,
|
||||||
reason: "WORKSPACE_INVALIDATED" as const,
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,6 +198,329 @@ export class PersonalWorkspaceProviderService
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
requestName: string,
|
||||||
|
path: string
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const newRequest = {
|
||||||
|
...cloneDeep(this.tabs.currentActiveTab.value.document.request),
|
||||||
|
name: requestName,
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertionIndex = saveRESTRequestAs(path, newRequest)
|
||||||
|
|
||||||
|
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||||
|
path,
|
||||||
|
"rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
this.tabs.createNewTab({
|
||||||
|
request: newRequest,
|
||||||
|
isDirty: false,
|
||||||
|
saveContext: {
|
||||||
|
originLocation: "user-collection",
|
||||||
|
folderPath: path,
|
||||||
|
requestIndex: insertionIndex,
|
||||||
|
},
|
||||||
|
inheritedProperties: {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
platform.analytics?.logEvent({
|
||||||
|
type: "HOPP_SAVE_REQUEST",
|
||||||
|
workspaceType: "personal",
|
||||||
|
createdNow: true,
|
||||||
|
platform: "rest",
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.collectionID,
|
||||||
|
name: requestName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
path: string,
|
||||||
|
requestIndex: number
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const possibleTab = this.tabs.getTabRefWithSaveContext({
|
||||||
|
originLocation: "user-collection",
|
||||||
|
folderPath: path,
|
||||||
|
requestIndex,
|
||||||
|
})
|
||||||
|
|
||||||
|
// If there is a tab attached to this request, dissociate its state and mark it dirty
|
||||||
|
if (possibleTab) {
|
||||||
|
possibleTab.value.document.saveContext = null
|
||||||
|
possibleTab.value.document.isDirty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`REST collection store state is `,
|
||||||
|
restCollectionStore.value.state
|
||||||
|
)
|
||||||
|
|
||||||
|
const requestToRemove = navigateToFolderWithIndexPath(
|
||||||
|
restCollectionStore.value.state,
|
||||||
|
path.split("/").map((i) => parseInt(i))
|
||||||
|
)?.requests[requestIndex]
|
||||||
|
|
||||||
|
removeRESTRequest(path, requestIndex, requestToRemove?.id)
|
||||||
|
|
||||||
|
// the same function is used to reorder requests since after removing, it's basically doing reorder
|
||||||
|
resolveSaveContextOnRequestReorder({
|
||||||
|
lastIndex: requestIndex,
|
||||||
|
newIndex: -1,
|
||||||
|
folderPath: path,
|
||||||
|
length: getRequestsByPath(
|
||||||
|
this.restCollectionState.value.state,
|
||||||
|
path
|
||||||
|
).length,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.workspaceID,
|
||||||
|
name: "" as const,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a request with this save context, switch into it
|
||||||
|
let possibleTab = null
|
||||||
|
|
||||||
|
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||||
|
collPath,
|
||||||
|
"rest"
|
||||||
|
)
|
||||||
|
possibleTab = this.tabs.getTabRefWithSaveContext({
|
||||||
|
originLocation: "user-collection",
|
||||||
|
requestIndex: parseInt(requestIndex),
|
||||||
|
folderPath: collPath!,
|
||||||
|
})
|
||||||
|
if (possibleTab) {
|
||||||
|
this.tabs.setActiveTab(possibleTab.value.id)
|
||||||
|
} else {
|
||||||
|
// If not, open the request in a new tab
|
||||||
|
this.tabs.createNewTab({
|
||||||
|
request: cloneDeep(request),
|
||||||
|
isDirty: false,
|
||||||
|
saveContext: {
|
||||||
|
originLocation: "user-collection",
|
||||||
|
folderPath: collPath!,
|
||||||
|
requestIndex: parseInt(requestIndex),
|
||||||
|
},
|
||||||
|
inheritedProperties: {
|
||||||
|
auth,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.workspaceID,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public duplicateRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveRESTRequestAs(collPath, request)
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.workspaceID,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public editRESTRequest(
|
||||||
|
parentCollHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collPath: string,
|
||||||
|
requestIndex: number,
|
||||||
|
request: HoppRESTRequest
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
parentCollHandle.value.type !== "ok" ||
|
||||||
|
parentCollHandle.value.data.providerID !== this.providerID ||
|
||||||
|
parentCollHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const possibleActiveTab = this.tabs.getTabRefWithSaveContext({
|
||||||
|
originLocation: "user-collection",
|
||||||
|
requestIndex,
|
||||||
|
collPath,
|
||||||
|
})
|
||||||
|
|
||||||
|
editRESTRequest(collPath, requestIndex, request)
|
||||||
|
|
||||||
|
if (possibleActiveTab) {
|
||||||
|
possibleActiveTab.value.document.request.name = request.name
|
||||||
|
nextTick(() => {
|
||||||
|
possibleActiveTab.value.document.isDirty = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: parentCollHandle.value.data.workspaceID,
|
||||||
|
collectionID: parentCollHandle.value.data.workspaceID,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
public getCollectionHandle(
|
public getCollectionHandle(
|
||||||
workspaceHandle: HandleRef<Workspace>,
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
collectionID: string
|
collectionID: string
|
||||||
@@ -224,24 +549,13 @@ export class PersonalWorkspaceProviderService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: The way the IDs are issued, this will make it so we need a view
|
|
||||||
// before the ID is issued correctly
|
|
||||||
const coll = this.resolveCollectionFromCollectionID(collectionID)
|
|
||||||
|
|
||||||
if (coll === undefined) {
|
|
||||||
return {
|
|
||||||
type: "invalid",
|
|
||||||
reason: "INVALID_COLL_ID" as const,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "ok",
|
type: "ok",
|
||||||
data: {
|
data: {
|
||||||
providerID: this.providerID,
|
providerID: this.providerID,
|
||||||
workspaceID: workspaceHandle.value.data.workspaceID,
|
workspaceID: workspaceHandle.value.data.workspaceID,
|
||||||
collectionID,
|
collectionID,
|
||||||
name: coll.name,
|
name: "" as const,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -279,45 +593,41 @@ export class PersonalWorkspaceProviderService
|
|||||||
mayHaveMoreContent: ref(false),
|
mayHaveMoreContent: ref(false),
|
||||||
|
|
||||||
content: computed(() => {
|
content: computed(() => {
|
||||||
const path = this.resolvePathFromCollectionID(collectionID)
|
const indexPath = collectionID
|
||||||
const coll =
|
.split("/")
|
||||||
this.resolveCollectionFromCollectionID(collectionID)
|
.map((x) => parseInt(x))
|
||||||
|
|
||||||
if (coll === undefined || path === undefined) {
|
const item = this.navigateToFolderWithIndexPath(
|
||||||
console.warn("Collection against ID was not resolvable")
|
this.restCollectionState.value.state,
|
||||||
|
indexPath
|
||||||
|
)
|
||||||
|
|
||||||
return []
|
if (item) {
|
||||||
|
const collections = item.folders.map((childColl, id) => {
|
||||||
|
return <RESTCollectionViewItem>{
|
||||||
|
type: "collection",
|
||||||
|
value: {
|
||||||
|
collectionID: `${collectionID}/${id}`,
|
||||||
|
name: childColl.name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const requests = item.requests.map((req, id) => {
|
||||||
|
return <RESTCollectionViewItem>{
|
||||||
|
type: "request",
|
||||||
|
value: {
|
||||||
|
requestID: `${collectionID}/${id}`,
|
||||||
|
name: req.name,
|
||||||
|
method: req.method,
|
||||||
|
request: req,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return [...collections, ...requests]
|
||||||
}
|
}
|
||||||
|
return []
|
||||||
const collections = coll.folders.map((childColl, i) => {
|
|
||||||
const id = this.getIssuedInstanceIDForCollection(childColl, [
|
|
||||||
...path,
|
|
||||||
i,
|
|
||||||
])
|
|
||||||
|
|
||||||
return <RESTCollectionViewItem>{
|
|
||||||
type: "collection",
|
|
||||||
value: {
|
|
||||||
collectionID: id,
|
|
||||||
name: coll.name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const requests = coll.requests.map((req, i) => {
|
|
||||||
const id = this.getIssuedInstanceIDForRequest(req)
|
|
||||||
|
|
||||||
return <RESTCollectionViewItem>{
|
|
||||||
type: "request",
|
|
||||||
value: {
|
|
||||||
requestID: id,
|
|
||||||
name: req.name,
|
|
||||||
method: req.method,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return [...collections, ...requests]
|
|
||||||
}),
|
}),
|
||||||
loadMore() {
|
loadMore() {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
@@ -356,11 +666,9 @@ export class PersonalWorkspaceProviderService
|
|||||||
mayHaveMoreContent: ref(false),
|
mayHaveMoreContent: ref(false),
|
||||||
|
|
||||||
collections: computed(() => {
|
collections: computed(() => {
|
||||||
return this.restCollectionState.value.state.map((coll, i) => {
|
return this.restCollectionState.value.state.map((coll, id) => {
|
||||||
const id = this.getIssuedInstanceIDForCollection(coll, [i])
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
collectionID: id,
|
collectionID: id.toString(),
|
||||||
name: coll.name,
|
name: coll.name,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||||
import { Ref } from "vue"
|
import { Ref } from "vue"
|
||||||
|
|
||||||
export type RESTCollectionViewCollection = {
|
export type RESTCollectionViewCollection = {
|
||||||
@@ -10,6 +11,7 @@ export type RESTCollectionViewRequest = {
|
|||||||
|
|
||||||
name: string
|
name: string
|
||||||
method: string
|
method: string
|
||||||
|
request: HoppRESTRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RESTCollectionViewItem =
|
export type RESTCollectionViewItem =
|
||||||
|
|||||||
Reference in New Issue
Block a user