refactor: port import/export functionality
This commit is contained in:
@@ -30,7 +30,7 @@ import { defineStep } from "~/composables/step-components"
|
|||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
import { restCollections$ } from "~/newstore/collections"
|
||||||
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
@@ -47,13 +47,14 @@ import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
|||||||
|
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { gistExporter } from "~/helpers/import-export/export/gist"
|
||||||
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
|
||||||
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
||||||
|
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
|
import { useService } from "dioc/vue"
|
||||||
|
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||||
import { TeamWorkspace } from "~/services/workspace.service"
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
@@ -84,15 +85,43 @@ const currentUser = useReadonlyStream(
|
|||||||
|
|
||||||
const myCollections = useReadonlyStream(restCollections$, [])
|
const myCollections = useReadonlyStream(restCollections$, [])
|
||||||
|
|
||||||
|
const workspaceService = useService(NewWorkspaceService)
|
||||||
|
|
||||||
|
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle
|
||||||
|
|
||||||
const showImportFailedError = () => {
|
const showImportFailedError = () => {
|
||||||
toast.error(t("import.failed"))
|
toast.error(t("import.failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleImportToStore = async (collections: HoppCollection[]) => {
|
const handleImportToStore = async (collections: HoppCollection[]) => {
|
||||||
const importResult =
|
if (props.collectionsType.type === "my-collections") {
|
||||||
props.collectionsType.type === "my-collections"
|
if (!activeWorkspaceHandle.value) {
|
||||||
? await importToPersonalWorkspace(collections)
|
return
|
||||||
: await importToTeamsWorkspace(collections)
|
}
|
||||||
|
|
||||||
|
const collectionHandleResult = await workspaceService.importRESTCollections(
|
||||||
|
activeWorkspaceHandle.value,
|
||||||
|
collections
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collectionHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
return toast.error(t("import.failed"))
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultHandle = collectionHandleResult.right
|
||||||
|
|
||||||
|
if (resultHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success(t("state.file_imported"))
|
||||||
|
emit("hide-modal")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const importResult = await importToTeamsWorkspace(collections)
|
||||||
|
|
||||||
if (E.isRight(importResult)) {
|
if (E.isRight(importResult)) {
|
||||||
toast.success(t("state.file_imported"))
|
toast.success(t("state.file_imported"))
|
||||||
@@ -102,13 +131,6 @@ const handleImportToStore = async (collections: HoppCollection[]) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const importToPersonalWorkspace = (collections: HoppCollection[]) => {
|
|
||||||
appendRESTCollections(collections)
|
|
||||||
return E.right({
|
|
||||||
success: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function translateToTeamCollectionFormat(x: HoppCollection) {
|
function translateToTeamCollectionFormat(x: HoppCollection) {
|
||||||
const folders: HoppCollection[] = (x.folders ?? []).map(
|
const folders: HoppCollection[] = (x.folders ?? []).map(
|
||||||
translateToTeamCollectionFormat
|
translateToTeamCollectionFormat
|
||||||
@@ -388,28 +410,34 @@ const HoppMyCollectionsExporter: ImporterOrExporter = {
|
|||||||
applicableTo: ["personal-workspace"],
|
applicableTo: ["personal-workspace"],
|
||||||
isLoading: isHoppMyCollectionExporterInProgress,
|
isLoading: isHoppMyCollectionExporterInProgress,
|
||||||
},
|
},
|
||||||
action: () => {
|
action: async () => {
|
||||||
if (!myCollections.value.length) {
|
if (!myCollections.value.length) {
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
return toast.error(t("error.no_collections_to_export"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!activeWorkspaceHandle.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isHoppMyCollectionExporterInProgress.value = true
|
isHoppMyCollectionExporterInProgress.value = true
|
||||||
|
|
||||||
const message = initializeDownloadCollection(
|
const result = await workspaceService.exportRESTCollections(
|
||||||
myCollectionsExporter(myCollections.value),
|
activeWorkspaceHandle.value,
|
||||||
"Collections"
|
myCollections.value
|
||||||
)
|
)
|
||||||
|
|
||||||
if (E.isRight(message)) {
|
if (E.isLeft(result)) {
|
||||||
toast.success(t(message.right))
|
// INVALID_WORKSPACE_HANDLE
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
|
||||||
exporter: "json",
|
|
||||||
platform: "rest",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toast.success(t("state.download_started"))
|
||||||
|
|
||||||
|
platform.analytics?.logEvent({
|
||||||
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
|
exporter: "json",
|
||||||
|
platform: "rest",
|
||||||
|
})
|
||||||
|
|
||||||
isHoppMyCollectionExporterInProgress.value = false
|
isHoppMyCollectionExporterInProgress.value = false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -443,10 +471,7 @@ const HoppTeamCollectionsExporter: ImporterOrExporter = {
|
|||||||
return toast.error(t("error.no_collections_to_export"))
|
return toast.error(t("error.no_collections_to_export"))
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeDownloadCollection(
|
initializeDownloadFile(exportCollectionsToJSON, "team-collections")
|
||||||
exportCollectionsToJSON,
|
|
||||||
"team-collections"
|
|
||||||
)
|
|
||||||
|
|
||||||
platform.analytics?.logEvent({
|
platform.analytics?.logEvent({
|
||||||
type: "HOPP_EXPORT_COLLECTION",
|
type: "HOPP_EXPORT_COLLECTION",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { GistSource } from "~/helpers/import-export/import/import-sources/GistSo
|
|||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
|
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
@@ -133,12 +133,12 @@ const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
},
|
},
|
||||||
action: () => {
|
action: async () => {
|
||||||
if (!gqlCollections.value.length) {
|
if (!gqlCollections.value.length) {
|
||||||
return toast.error(t("error.no_collections_to_export"))
|
return toast.error(t("error.no_collections_to_export"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = initializeDownloadCollection(
|
const message = await initializeDownloadFile(
|
||||||
gqlCollectionsExporter(gqlCollections.value),
|
gqlCollectionsExporter(gqlCollections.value),
|
||||||
"GQLCollections"
|
"GQLCollections"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import IconFolderPlus from "~icons/lucide/folder-plus"
|
|||||||
import IconPostman from "~icons/hopp/postman"
|
import IconPostman from "~icons/hopp/postman"
|
||||||
import IconInsomnia from "~icons/hopp/insomnia"
|
import IconInsomnia from "~icons/hopp/insomnia"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { useReadonlyStream } from "~/composables/stream"
|
import { useReadonlyStream } from "~/composables/stream"
|
||||||
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
||||||
@@ -230,12 +230,12 @@ const HoppEnvironmentsExport: ImporterOrExporter = {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
applicableTo: ["personal-workspace", "team-workspace"],
|
applicableTo: ["personal-workspace", "team-workspace"],
|
||||||
},
|
},
|
||||||
action: () => {
|
action: async () => {
|
||||||
if (!environmentJson.value.length) {
|
if (!environmentJson.value.length) {
|
||||||
return toast.error(t("error.no_environments_to_export"))
|
return toast.error(t("error.no_environments_to_export"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = initializeDownloadCollection(
|
const message = await initializeDownloadFile(
|
||||||
environmentsExporter(environmentJson.value),
|
environmentsExporter(environmentJson.value),
|
||||||
"Environments"
|
"Environments"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -110,7 +110,8 @@
|
|||||||
:shortcut="['X']"
|
:shortcut="['X']"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
emit('export-data'), hide()
|
emit('export-collection', collectionView.collectionID)
|
||||||
|
hide()
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
@@ -189,7 +190,7 @@ const emit = defineEmits<{
|
|||||||
event: "edit-root-collection",
|
event: "edit-root-collection",
|
||||||
payload: { collectionIndexPath: string; collectionName: string }
|
payload: { collectionIndexPath: string; collectionName: string }
|
||||||
): void
|
): void
|
||||||
(event: "export-data"): void
|
(event: "export-collection", collectionIndexPath: string): void
|
||||||
(event: "remove-child-collection", collectionIndexPath: string): void
|
(event: "remove-child-collection", collectionIndexPath: string): void
|
||||||
(event: "remove-root-collection", collectionIndexPath: string): void
|
(event: "remove-root-collection", collectionIndexPath: string): void
|
||||||
(event: "toggle-children"): void
|
(event: "toggle-children"): void
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:icon="IconImport"
|
:icon="IconImport"
|
||||||
:title="t('modal.import_export')"
|
:title="t('modal.import_export')"
|
||||||
@click="() => {}"
|
@click="displayModalImportExport(true)"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
@edit-child-collection="editChildCollection"
|
@edit-child-collection="editChildCollection"
|
||||||
@edit-root-collection="editRootCollection"
|
@edit-root-collection="editRootCollection"
|
||||||
@edit-collection-properties="editCollectionProperties"
|
@edit-collection-properties="editCollectionProperties"
|
||||||
|
@export-collection="exportCollection"
|
||||||
@remove-child-collection="removeChildCollection"
|
@remove-child-collection="removeChildCollection"
|
||||||
@remove-root-collection="removeRootCollection"
|
@remove-root-collection="removeRootCollection"
|
||||||
@select-pick="onSelectPick"
|
@select-pick="onSelectPick"
|
||||||
@@ -143,6 +144,13 @@
|
|||||||
@resolve="resolveConfirmModal"
|
@resolve="resolveConfirmModal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- TODO: Supply `collectionsType` once teams implementation is in place -->
|
||||||
|
<!-- Defaults to `my-collections` -->
|
||||||
|
<CollectionsImportExport
|
||||||
|
v-if="showImportExportModal"
|
||||||
|
@hide-modal="displayModalImportExport(false)"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- TODO: Remove the `emitWithFullCollection` prop after porting all usages of the below component -->
|
<!-- TODO: Remove the `emitWithFullCollection` prop after porting all usages of the below component -->
|
||||||
<CollectionsProperties
|
<CollectionsProperties
|
||||||
:show="showModalEditProperties"
|
:show="showModalEditProperties"
|
||||||
@@ -220,6 +228,7 @@ const showModalAddChildColl = ref(false)
|
|||||||
const showModalEditRootColl = ref(false)
|
const showModalEditRootColl = ref(false)
|
||||||
const showModalEditChildColl = ref(false)
|
const showModalEditChildColl = ref(false)
|
||||||
const showModalEditRequest = ref(false)
|
const showModalEditRequest = ref(false)
|
||||||
|
const showImportExportModal = ref(false)
|
||||||
const showModalEditProperties = ref(false)
|
const showModalEditProperties = ref(false)
|
||||||
const showConfirmModal = ref(false)
|
const showConfirmModal = ref(false)
|
||||||
|
|
||||||
@@ -309,6 +318,12 @@ const displayModalEditRequest = (show: boolean) => {
|
|||||||
if (!show) resetSelectedData()
|
if (!show) resetSelectedData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const displayModalImportExport = (show: boolean) => {
|
||||||
|
showImportExportModal.value = show
|
||||||
|
|
||||||
|
if (!show) resetSelectedData()
|
||||||
|
}
|
||||||
|
|
||||||
const displayModalEditProperties = (show: boolean) => {
|
const displayModalEditProperties = (show: boolean) => {
|
||||||
showModalEditProperties.value = show
|
showModalEditProperties.value = show
|
||||||
|
|
||||||
@@ -1102,6 +1117,40 @@ const setCollectionProperties = async (updatedCollectionProps: {
|
|||||||
displayModalEditProperties(false)
|
displayModalEditProperties(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exportCollection = async (collectionIndexPath: string) => {
|
||||||
|
const collectionHandleResult = await workspaceService.getCollectionHandle(
|
||||||
|
props.workspaceHandle,
|
||||||
|
collectionIndexPath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(collectionHandleResult)) {
|
||||||
|
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collectionHandle = collectionHandleResult.right
|
||||||
|
|
||||||
|
if (collectionHandle.value.type === "invalid") {
|
||||||
|
// WORKSPACE_INVALIDATED
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const collection = navigateToFolderWithIndexPath(
|
||||||
|
restCollectionState.value,
|
||||||
|
collectionIndexPath.split("/").map((id) => parseInt(id))
|
||||||
|
) as HoppCollection
|
||||||
|
|
||||||
|
const result = await workspaceService.exportRESTCollection(
|
||||||
|
collectionHandle,
|
||||||
|
collection
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
// INVALID_COLLECTION_HANDLE
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const shareRequest = (request: HoppRESTRequest) => {
|
const shareRequest = (request: HoppRESTRequest) => {
|
||||||
if (currentUser.value) {
|
if (currentUser.value) {
|
||||||
// Opens the share request modal if the user is logged in
|
// Opens the share request modal if the user is logged in
|
||||||
|
|||||||
@@ -1,32 +1,31 @@
|
|||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a downloadable file from a collection and prompts the user to download it.
|
* Create a downloadable file from a collection and prompts the user to download it.
|
||||||
* @param collectionJSON - JSON string of the collection
|
* @param collectionJSON - JSON string of the collection
|
||||||
* @param name - Name of the collection set as the file name
|
* @param name - Name of the collection set as the file name
|
||||||
*/
|
*/
|
||||||
export const initializeDownloadCollection = (
|
export const initializeDownloadFile = async (
|
||||||
collectionJSON: string,
|
collectionJSON: string,
|
||||||
name: string | null
|
name: string | null
|
||||||
) => {
|
) => {
|
||||||
const file = new Blob([collectionJSON], { type: "application/json" })
|
const result = await platform.io.saveFileWithDialog({
|
||||||
const a = document.createElement("a")
|
data: collectionJSON,
|
||||||
const url = URL.createObjectURL(file)
|
contentType: "application/json",
|
||||||
a.href = url
|
suggestedFilename: `${name ?? "collection"}.json`,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: "Hoppscotch Collection/Environment JSON file",
|
||||||
|
extensions: ["json"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (name) {
|
if (result.type === "unknown" || result.type === "saved") {
|
||||||
a.download = `${name}.json`
|
return E.right("state.download_started")
|
||||||
} else {
|
|
||||||
a.download = `${url.split("/").pop()!.split("#")[0].split("?")[0]}.json`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.appendChild(a)
|
return E.left("state.download_failed")
|
||||||
a.click()
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
document.body.removeChild(a)
|
|
||||||
URL.revokeObjectURL(url)
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
return E.right("state.download_started")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { HoppCollection } from "@hoppscotch/data"
|
|
||||||
|
|
||||||
export const myCollectionsExporter = (myCollections: HoppCollection[]) => {
|
|
||||||
return JSON.stringify(myCollections, null, 2)
|
|
||||||
}
|
|
||||||
@@ -13,15 +13,17 @@ export const browserIODef: IOPlatformDef = {
|
|||||||
const url = URL.createObjectURL(file)
|
const url = URL.createObjectURL(file)
|
||||||
|
|
||||||
a.href = url
|
a.href = url
|
||||||
a.download = pipe(
|
a.download =
|
||||||
url,
|
opts.suggestedFilename ??
|
||||||
S.split("/"),
|
pipe(
|
||||||
RNEA.last,
|
url,
|
||||||
S.split("#"),
|
S.split("/"),
|
||||||
RNEA.head,
|
RNEA.last,
|
||||||
S.split("?"),
|
S.split("#"),
|
||||||
RNEA.head
|
RNEA.head,
|
||||||
)
|
S.split("?"),
|
||||||
|
RNEA.head
|
||||||
|
)
|
||||||
|
|
||||||
document.body.appendChild(a)
|
document.body.appendChild(a)
|
||||||
a.click()
|
a.click()
|
||||||
|
|||||||
@@ -383,6 +383,99 @@ export class NewWorkspaceService extends Service {
|
|||||||
return E.right(result.right)
|
return E.right(result.right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async importRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<
|
||||||
|
E.Either<
|
||||||
|
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
|
||||||
|
HandleRef<WorkspaceCollection>
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
if (workspaceHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
workspaceHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.importRESTCollections(
|
||||||
|
workspaceHandle,
|
||||||
|
collections
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async exportRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<
|
||||||
|
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
|
||||||
|
> {
|
||||||
|
if (workspaceHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
workspaceHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.exportRESTCollections(
|
||||||
|
workspaceHandle,
|
||||||
|
collections
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isLeft(result)) {
|
||||||
|
return E.left({ type: "PROVIDER_ERROR", error: result.left })
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.right(result.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async exportRESTCollection(
|
||||||
|
collectionHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collection: HoppCollection
|
||||||
|
): Promise<
|
||||||
|
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
|
||||||
|
> {
|
||||||
|
if (collectionHandle.value.type === "invalid") {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const provider = this.registeredProviders.get(
|
||||||
|
collectionHandle.value.data.providerID
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await provider.exportRESTCollection(
|
||||||
|
collectionHandle,
|
||||||
|
collection
|
||||||
|
)
|
||||||
|
|
||||||
|
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<
|
||||||
|
|||||||
@@ -67,4 +67,17 @@ export interface WorkspaceProvider {
|
|||||||
removeRESTRequest(
|
removeRESTRequest(
|
||||||
requestHandle: HandleRef<WorkspaceRequest>
|
requestHandle: HandleRef<WorkspaceRequest>
|
||||||
): Promise<E.Either<unknown, void>>
|
): Promise<E.Either<unknown, void>>
|
||||||
|
|
||||||
|
importRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
|
||||||
|
exportRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<E.Either<unknown, void>>
|
||||||
|
exportRESTCollection(
|
||||||
|
collectionHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collection: HoppCollection
|
||||||
|
): Promise<E.Either<unknown, void>>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useStreamStatic } from "~/composables/stream"
|
|||||||
import {
|
import {
|
||||||
addRESTCollection,
|
addRESTCollection,
|
||||||
addRESTFolder,
|
addRESTFolder,
|
||||||
|
appendRESTCollections,
|
||||||
editRESTCollection,
|
editRESTCollection,
|
||||||
editRESTFolder,
|
editRESTFolder,
|
||||||
editRESTRequest,
|
editRESTRequest,
|
||||||
@@ -49,6 +50,7 @@ import { HoppGQLHeader } from "~/helpers/graphql"
|
|||||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
import { NewWorkspaceService } from ".."
|
import { NewWorkspaceService } from ".."
|
||||||
|
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||||
|
|
||||||
export class PersonalWorkspaceProviderService
|
export class PersonalWorkspaceProviderService
|
||||||
extends Service
|
extends Service
|
||||||
@@ -217,7 +219,7 @@ export class PersonalWorkspaceProviderService
|
|||||||
collectionHandle.value.data.providerID !== this.providerID ||
|
collectionHandle.value.data.providerID !== this.providerID ||
|
||||||
collectionHandle.value.data.workspaceID !== "personal"
|
collectionHandle.value.data.workspaceID !== "personal"
|
||||||
) {
|
) {
|
||||||
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
|
||||||
}
|
}
|
||||||
|
|
||||||
const { collectionID } = collectionHandle.value.data
|
const { collectionID } = collectionHandle.value.data
|
||||||
@@ -393,6 +395,86 @@ export class PersonalWorkspaceProviderService
|
|||||||
return Promise.resolve(E.right(undefined))
|
return Promise.resolve(E.right(undefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public importRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
|
||||||
|
if (
|
||||||
|
workspaceHandle.value.type !== "ok" ||
|
||||||
|
workspaceHandle.value.data.providerID !== this.providerID ||
|
||||||
|
workspaceHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
appendRESTCollections(collections)
|
||||||
|
|
||||||
|
const newCollectionName = collections[0].name
|
||||||
|
const newCollectionID =
|
||||||
|
this.restCollectionState.value.state.length.toString()
|
||||||
|
|
||||||
|
return Promise.resolve(
|
||||||
|
E.right(
|
||||||
|
computed(() => {
|
||||||
|
if (
|
||||||
|
workspaceHandle.value.type !== "ok" ||
|
||||||
|
workspaceHandle.value.data.providerID !== this.providerID ||
|
||||||
|
workspaceHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: "invalid" as const,
|
||||||
|
reason: "WORKSPACE_INVALIDATED" as const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "ok",
|
||||||
|
data: {
|
||||||
|
providerID: this.providerID,
|
||||||
|
workspaceID: workspaceHandle.value.data.workspaceID,
|
||||||
|
collectionID: newCollectionID,
|
||||||
|
name: newCollectionName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public exportRESTCollections(
|
||||||
|
workspaceHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collections: HoppCollection[]
|
||||||
|
): Promise<E.Either<unknown, void>> {
|
||||||
|
if (
|
||||||
|
workspaceHandle.value.type !== "ok" ||
|
||||||
|
workspaceHandle.value.data.providerID !== this.providerID ||
|
||||||
|
workspaceHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeDownloadFile(JSON.stringify(collections, null, 2), "Collections")
|
||||||
|
|
||||||
|
return Promise.resolve(E.right(undefined))
|
||||||
|
}
|
||||||
|
|
||||||
|
public exportRESTCollection(
|
||||||
|
collectionHandle: HandleRef<WorkspaceCollection>,
|
||||||
|
collection: HoppCollection
|
||||||
|
): Promise<E.Either<unknown, void>> {
|
||||||
|
if (
|
||||||
|
collectionHandle.value.type !== "ok" ||
|
||||||
|
collectionHandle.value.data.providerID !== this.providerID ||
|
||||||
|
collectionHandle.value.data.workspaceID !== "personal"
|
||||||
|
) {
|
||||||
|
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeDownloadFile(JSON.stringify(collection, null, 2), collection.name)
|
||||||
|
|
||||||
|
return Promise.resolve(E.right(undefined))
|
||||||
|
}
|
||||||
|
|
||||||
public getCollectionHandle(
|
public getCollectionHandle(
|
||||||
workspaceHandle: HandleRef<Workspace>,
|
workspaceHandle: HandleRef<Workspace>,
|
||||||
collectionID: string
|
collectionID: string
|
||||||
|
|||||||
Reference in New Issue
Block a user