feat: duplicate REST/GraphQL collections (#4211)
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com> Co-authored-by: nivedin <nivedinp@gmail.com>
This commit is contained in:
@@ -73,7 +73,13 @@
|
||||
@keyup.r="requestAction.$el.click()"
|
||||
@keyup.n="folderAction.$el.click()"
|
||||
@keyup.e="edit.$el.click()"
|
||||
@keyup.d="
|
||||
showDuplicateCollectionAction
|
||||
? duplicateAction.$el.click()
|
||||
: null
|
||||
"
|
||||
@keyup.delete="deleteAction.$el.click()"
|
||||
@keyup.p="propertiesAction.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<HoppSmartItem
|
||||
@@ -116,6 +122,22 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
v-if="showDuplicateCollectionAction"
|
||||
ref="duplicateAction"
|
||||
:icon="IconCopy"
|
||||
:label="t('action.duplicate')"
|
||||
:shortcut="['D']"
|
||||
@click="
|
||||
() => {
|
||||
emit('duplicate-collection', {
|
||||
path: `${collectionIndex}`,
|
||||
collectionSyncID: collection.id,
|
||||
}),
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="deleteAction"
|
||||
:icon="IconTrash2"
|
||||
@@ -168,6 +190,7 @@
|
||||
@add-request="$emit('add-request', $event)"
|
||||
@add-folder="$emit('add-folder', $event)"
|
||||
@edit-folder="$emit('edit-folder', $event)"
|
||||
@duplicate-collection="$emit('duplicate-collection', $event)"
|
||||
@edit-request="$emit('edit-request', $event)"
|
||||
@duplicate-request="$emit('duplicate-request', $event)"
|
||||
@edit-properties="
|
||||
@@ -229,24 +252,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconFilePlus from "~icons/lucide/file-plus"
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { removeGraphqlCollection } from "~/newstore/collections"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { useService } from "dioc/vue"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { HoppCollection } from "@hoppscotch/data"
|
||||
import { useService } from "dioc/vue"
|
||||
import { computed, ref } from "vue"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { removeGraphqlCollection } from "~/newstore/collections"
|
||||
import { platform } from "~/platform"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconFilePlus from "~icons/lucide/file-plus"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
|
||||
const props = defineProps<{
|
||||
picked: Picked | null
|
||||
@@ -271,6 +297,13 @@ const emit = defineEmits<{
|
||||
(e: "add-request", i: any): void
|
||||
(e: "add-folder", i: any): void
|
||||
(e: "edit-folder", i: any): void
|
||||
(
|
||||
e: "duplicate-collection",
|
||||
payload: {
|
||||
path: string
|
||||
collectionSyncID?: string
|
||||
}
|
||||
): void
|
||||
(
|
||||
e: "edit-properties",
|
||||
payload: {
|
||||
@@ -296,13 +329,20 @@ const options = ref<any | null>(null)
|
||||
const requestAction = ref<any | null>(null)
|
||||
const folderAction = ref<any | null>(null)
|
||||
const edit = ref<any | null>(null)
|
||||
const duplicateAction = ref<any | null>(null)
|
||||
const deleteAction = ref<any | null>(null)
|
||||
const propertiesAction = ref<any | null>(null)
|
||||
|
||||
const showChildren = ref(false)
|
||||
const dragging = ref(false)
|
||||
|
||||
const confirmRemove = ref(false)
|
||||
|
||||
const currentUser = useReadonlyStream(
|
||||
platform.auth.getCurrentUserStream(),
|
||||
platform.auth.getCurrentUser()
|
||||
)
|
||||
|
||||
const isSelected = computed(
|
||||
() =>
|
||||
props.picked?.pickedType === "gql-my-collection" &&
|
||||
@@ -315,6 +355,17 @@ const collectionIcon = computed(() => {
|
||||
return IconFolder
|
||||
})
|
||||
|
||||
const showDuplicateCollectionAction = computed(() => {
|
||||
// Show if the user is not logged in
|
||||
if (!currentUser.value) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Duplicate collection action is disabled on SH until the issue with syncing is resolved
|
||||
return !platform.platformFeatureFlags
|
||||
.duplicateCollectionDisabledInPersonalWorkspace
|
||||
})
|
||||
|
||||
const pick = () => {
|
||||
emit("select", {
|
||||
pickedType: "gql-my-collection",
|
||||
|
||||
@@ -70,7 +70,13 @@
|
||||
@keyup.r="requestAction.$el.click()"
|
||||
@keyup.n="folderAction.$el.click()"
|
||||
@keyup.e="edit.$el.click()"
|
||||
@keyup.d="
|
||||
showDuplicateCollectionAction
|
||||
? duplicateAction.$el.click()
|
||||
: null
|
||||
"
|
||||
@keyup.delete="deleteAction.$el.click()"
|
||||
@keyup.p="propertiesAction.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<HoppSmartItem
|
||||
@@ -109,6 +115,22 @@
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
v-if="showDuplicateCollectionAction"
|
||||
ref="duplicateAction"
|
||||
:icon="IconCopy"
|
||||
:label="t('action.duplicate')"
|
||||
:shortcut="['D']"
|
||||
@click="
|
||||
() => {
|
||||
emit('duplicate-collection', {
|
||||
path: folderPath,
|
||||
collectionSyncID: folder.id,
|
||||
}),
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="deleteAction"
|
||||
:icon="IconTrash2"
|
||||
@@ -162,6 +184,7 @@
|
||||
@add-request="emit('add-request', $event)"
|
||||
@add-folder="emit('add-folder', $event)"
|
||||
@edit-folder="emit('edit-folder', $event)"
|
||||
@duplicate-collection="emit('duplicate-collection', $event)"
|
||||
@edit-request="emit('edit-request', $event)"
|
||||
@duplicate-request="emit('duplicate-request', $event)"
|
||||
@edit-properties="
|
||||
@@ -213,24 +236,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconFilePlus from "~icons/lucide/file-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { removeGraphqlFolder } from "~/newstore/collections"
|
||||
import { computed, ref } from "vue"
|
||||
import { useService } from "dioc/vue"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { HoppCollection } from "@hoppscotch/data"
|
||||
import { useService } from "dioc/vue"
|
||||
import { computed, ref } from "vue"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { removeGraphqlFolder } from "~/newstore/collections"
|
||||
import { platform } from "~/platform"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconFilePlus from "~icons/lucide/file-plus"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
|
||||
const toast = useToast()
|
||||
const t = useI18n()
|
||||
@@ -255,6 +281,7 @@ const emit = defineEmits([
|
||||
"edit-request",
|
||||
"add-folder",
|
||||
"edit-folder",
|
||||
"duplicate-collection",
|
||||
"duplicate-request",
|
||||
"edit-properties",
|
||||
"select-request",
|
||||
@@ -267,12 +294,19 @@ const options = ref<any | null>(null)
|
||||
const requestAction = ref<any | null>(null)
|
||||
const folderAction = ref<any | null>(null)
|
||||
const edit = ref<any | null>(null)
|
||||
const duplicateAction = ref<any | null>(null)
|
||||
const deleteAction = ref<any | null>(null)
|
||||
const propertiesAction = ref<any | null>(null)
|
||||
|
||||
const showChildren = ref(false)
|
||||
const dragging = ref(false)
|
||||
const confirmRemove = ref(false)
|
||||
|
||||
const currentUser = useReadonlyStream(
|
||||
platform.auth.getCurrentUserStream(),
|
||||
platform.auth.getCurrentUser()
|
||||
)
|
||||
|
||||
const isSelected = computed(
|
||||
() =>
|
||||
props.picked?.pickedType === "gql-my-folder" &&
|
||||
@@ -285,6 +319,17 @@ const collectionIcon = computed(() => {
|
||||
return IconFolder
|
||||
})
|
||||
|
||||
const showDuplicateCollectionAction = computed(() => {
|
||||
// Show if the user is not logged in
|
||||
if (!currentUser.value) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Duplicate collection action is disabled on SH until the issue with syncing is resolved
|
||||
return !platform.platformFeatureFlags
|
||||
.duplicateCollectionDisabledInPersonalWorkspace
|
||||
})
|
||||
|
||||
const pick = () => {
|
||||
emit("select", {
|
||||
pickedType: "gql-my-folder",
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
@add-request="addRequest($event)"
|
||||
@add-folder="addFolder($event)"
|
||||
@edit-folder="editFolder($event)"
|
||||
@duplicate-collection="duplicateCollection($event)"
|
||||
@edit-request="editRequest($event)"
|
||||
@duplicate-request="duplicateRequest($event)"
|
||||
@select-collection="$emit('use-collection', collection)"
|
||||
@@ -167,6 +168,7 @@ import {
|
||||
editGraphqlCollection,
|
||||
editGraphqlFolder,
|
||||
moveGraphqlRequest,
|
||||
duplicateGraphQLCollection,
|
||||
} from "~/newstore/collections"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||
@@ -380,6 +382,14 @@ const editCollection = (
|
||||
displayModalEdit(true)
|
||||
}
|
||||
|
||||
const duplicateCollection = ({
|
||||
path,
|
||||
collectionSyncID,
|
||||
}: {
|
||||
path: string
|
||||
collectionSyncID?: string
|
||||
}) => duplicateGraphQLCollection(path, collectionSyncID)
|
||||
|
||||
const onAddRequest = ({
|
||||
name,
|
||||
path,
|
||||
|
||||
Reference in New Issue
Block a user