refactor: add import buttons in empty state for collections & environments (#3438)

This commit is contained in:
Nivedin
2023-10-11 11:08:51 +05:30
committed by GitHub
parent cabee0ecc8
commit 51510566bc
7 changed files with 160 additions and 80 deletions

View File

@@ -125,6 +125,7 @@
"created": "Collection created", "created": "Collection created",
"different_parent": "Cannot reorder collection with different parent", "different_parent": "Cannot reorder collection with different parent",
"edit": "Edit Collection", "edit": "Edit Collection",
"import_or_create": "Import or create a collection",
"invalid_name": "Please provide a name for the collection", "invalid_name": "Please provide a name for the collection",
"invalid_root_move": "Collection already in the root", "invalid_root_move": "Collection already in the root",
"moved": "Moved Successfully", "moved": "Moved Successfully",
@@ -210,6 +211,7 @@
"empty_variables": "No variables", "empty_variables": "No variables",
"global": "Global", "global": "Global",
"global_variables": "Global variables", "global_variables": "Global variables",
"import_or_create": "Import or create a environment",
"invalid_name": "Please provide a name for the environment", "invalid_name": "Please provide a name for the environment",
"list": "Environment variables", "list": "Environment variables",
"my_environments": "My Environments", "my_environments": "My Environments",
@@ -459,6 +461,7 @@
"enter_curl": "Enter cURL command", "enter_curl": "Enter cURL command",
"generate_code": "Generate code", "generate_code": "Generate code",
"generated_code": "Generated code", "generated_code": "Generated code",
"go_to_authorization_tab": "Go to Authorization",
"header_list": "Header List", "header_list": "Header List",
"invalid_name": "Please provide a name for the request", "invalid_name": "Please provide a name for the request",
"method": "Method", "method": "Method",
@@ -750,6 +753,7 @@
"enabled": "Enabled", "enabled": "Enabled",
"file_imported": "File imported", "file_imported": "File imported",
"finished_in": "Finished in {duration} ms", "finished_in": "Finished in {duration} ms",
"hide": "Hide",
"history_deleted": "History deleted", "history_deleted": "History deleted",
"linewrap": "Wrap lines", "linewrap": "Wrap lines",
"loading": "Loading...", "loading": "Loading...",
@@ -760,6 +764,7 @@
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}", "published_error": "Something went wrong while publishing msg: {topic} to topic: {message}",
"published_message": "Published message: {message} to topic: {topic}", "published_message": "Published message: {message} to topic: {topic}",
"reconnection_error": "Failed to reconnect", "reconnection_error": "Failed to reconnect",
"show":"Show",
"subscribed_failed": "Failed to subscribe to topic: {topic}", "subscribed_failed": "Failed to subscribe to topic: {topic}",
"subscribed_success": "Successfully subscribed to topic: {topic}", "subscribed_success": "Successfully subscribed to topic: {topic}",
"unsubscribed_failed": "Failed to unsubscribe from topic: {topic}", "unsubscribed_failed": "Failed to unsubscribe from topic: {topic}",
@@ -841,7 +846,7 @@
"new": "New Team", "new": "New Team",
"new_created": "New team created", "new_created": "New team created",
"new_name": "My New Team", "new_name": "My New Team",
"no_access": "You do not have edit access to these collections", "no_access": "You do not have edit access to this team",
"no_invite_found": "Invitation not found. Contact your team owner.", "no_invite_found": "Invitation not found. Contact your team owner.",
"no_request_found": "Request not found.", "no_request_found": "Request not found.",
"not_found": "Team not found. Contact your team owner.", "not_found": "Team not found. Contact your team owner.",

View File

@@ -25,7 +25,7 @@
<HoppButtonSecondary <HoppButtonSecondary
v-if="!saveRequest" v-if="!saveRequest"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:icon="IconArchive" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
@click="emit('display-modal-import-export')" @click="emit('display-modal-import-export')"
/> />
@@ -251,19 +251,35 @@
<icon-lucide-search class="pb-2 opacity-75 svg-icons" /> <icon-lucide-search class="pb-2 opacity-75 svg-icons" />
</template> </template>
</HoppSmartPlaceholder> </HoppSmartPlaceholder>
<HoppSmartPlaceholder <div v-else-if="node === null" class="flex flex-col space-y-25 py-5">
v-else-if="node === null" <div class="flex flex-col items-center space-y-4">
:src="`/images/states/${colorMode.value}/pack.svg`" <span class="text-secondaryLight text-center">
:alt="`${t('empty.collections')}`" {{ t("collection.import_or_create") }}
:text="t('empty.collections')" </span>
> <div class="flex gap-4 flex-col items-center">
<HoppButtonPrimary
:icon="IconImport"
:label="t('import.title')"
filled
outline
@click="emit('display-modal-import-export')"
/>
<HoppButtonSecondary <HoppButtonSecondary
:icon="IconPlus"
:label="t('add.new')" :label="t('add.new')"
filled filled
outline outline
@click="emit('display-modal-add')" @click="emit('display-modal-add')"
/> />
</HoppSmartPlaceholder> </div>
</div>
<HoppSmartPlaceholder
:src="`/images/states/${colorMode.value}/pack.svg`"
:alt="`${t('empty.collections')}`"
:text="t('empty.collections')"
/>
</div>
<HoppSmartPlaceholder <HoppSmartPlaceholder
v-else-if="node.data.type === 'collections'" v-else-if="node.data.type === 'collections'"
:src="`/images/states/${colorMode.value}/pack.svg`" :src="`/images/states/${colorMode.value}/pack.svg`"
@@ -288,8 +304,7 @@
:src="`/images/states/${colorMode.value}/pack.svg`" :src="`/images/states/${colorMode.value}/pack.svg`"
:alt="`${t('empty.folder')}`" :alt="`${t('empty.folder')}`"
:text="t('empty.folder')" :text="t('empty.folder')"
> />
</HoppSmartPlaceholder>
</template> </template>
</HoppSmartTree> </HoppSmartTree>
</div> </div>
@@ -297,9 +312,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import IconArchive from "~icons/lucide/archive"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import IconImport from "~icons/lucide/folder-down"
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data" import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
import { computed, PropType, Ref, toRef } from "vue" import { computed, PropType, Ref, toRef } from "vue"
import { GetMyTeamsQuery } from "~/helpers/backend/graphql" import { GetMyTeamsQuery } from "~/helpers/backend/graphql"

View File

@@ -15,12 +15,12 @@
class="!rounded-none" class="!rounded-none"
:icon="IconPlus" :icon="IconPlus"
:title="t('team.no_access')" :title="t('team.no_access')"
:label="t('action.new')" :label="t('add.new')"
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-else v-else
:icon="IconPlus" :icon="IconPlus"
:label="t('action.new')" :label="t('add.new')"
class="!rounded-none" class="!rounded-none"
@click="emit('display-modal-add')" @click="emit('display-modal-add')"
/> />
@@ -39,7 +39,7 @@
collectionsType.type === 'team-collections' && collectionsType.type === 'team-collections' &&
collectionsType.selectedTeam === undefined collectionsType.selectedTeam === undefined
" "
:icon="IconArchive" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
@click="emit('display-modal-import-export')" @click="emit('display-modal-import-export')"
/> />
@@ -261,32 +261,43 @@
/> />
</template> </template>
<template #emptyNode="{ node }"> <template #emptyNode="{ node }">
<div v-if="node === null"> <div
<div @drop="(e) => e.stopPropagation()"> v-if="node === null"
class="flex flex-col space-y-25 py-5"
@drop="(e) => e.stopPropagation()"
>
<div class="flex flex-col items-center space-y-4">
<span class="text-secondaryLight text-center">
{{ t("collection.import_or_create") }}
</span>
<div class="flex gap-4 flex-col items-center">
<HoppButtonPrimary
:icon="IconImport"
:label="t('import.title')"
filled
outline
:disabled="hasNoTeamAccess"
:title="hasNoTeamAccess ? t('team.no_access') : ''"
@click="
hasNoTeamAccess ? null : emit('display-modal-import-export')
"
/>
<HoppButtonSecondary
:icon="IconPlus"
:label="t('add.new')"
filled
outline
:disabled="hasNoTeamAccess"
:title="hasNoTeamAccess ? t('team.no_access') : ''"
@click="hasNoTeamAccess ? null : emit('display-modal-add')"
/>
</div>
</div>
<HoppSmartPlaceholder <HoppSmartPlaceholder
:src="`/images/states/${colorMode.value}/pack.svg`" :src="`/images/states/${colorMode.value}/pack.svg`"
:alt="`${t('empty.collections')}`" :alt="`${t('empty.collections')}`"
:text="t('empty.collections')" :text="t('empty.collections')"
>
<HoppButtonSecondary
v-if="hasNoTeamAccess"
v-tippy="{ theme: 'tooltip' }"
disabled
filled
outline
:title="t('team.no_access')"
:label="t('action.new')"
/> />
<HoppButtonSecondary
v-else
:icon="IconPlus"
:label="t('action.new')"
filled
outline
@click="emit('display-modal-add')"
/>
</HoppSmartPlaceholder>
</div>
</div> </div>
<div <div
v-else-if="node.data.type === 'collections'" v-else-if="node.data.type === 'collections'"
@@ -297,6 +308,18 @@
:alt="`${t('empty.collections')}`" :alt="`${t('empty.collections')}`"
:text="t('empty.collections')" :text="t('empty.collections')"
> >
<HoppButtonSecondary
:label="t('add.new')"
filled
outline
@click="
node.data.type === 'collections' &&
emit('add-folder', {
path: node.id,
folder: node.data.data.data,
})
"
/>
</HoppSmartPlaceholder> </HoppSmartPlaceholder>
</div> </div>
<div <div
@@ -307,8 +330,7 @@
:src="`/images/states/${colorMode.value}/pack.svg`" :src="`/images/states/${colorMode.value}/pack.svg`"
:alt="`${t('empty.folder')}`" :alt="`${t('empty.folder')}`"
:text="t('empty.folder')" :text="t('empty.folder')"
> />
</HoppSmartPlaceholder>
</div> </div>
</template> </template>
</HoppSmartTree> </HoppSmartTree>
@@ -317,9 +339,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import IconArchive from "~icons/lucide/archive"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import IconImport from "~icons/lucide/folder-down"
import { computed, PropType, Ref, toRef } from "vue" import { computed, PropType, Ref, toRef } from "vue"
import { GetMyTeamsQuery } from "~/helpers/backend/graphql" import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
import { useI18n } from "@composables/i18n" import { useI18n } from "@composables/i18n"

View File

@@ -478,7 +478,8 @@ watch(
teamEnvListAdapter.changeTeamID(newVal.teamID) teamEnvListAdapter.changeTeamID(newVal.teamID)
} }
} }
} },
{ immediate: true }
) )
const selectedEnv = computed(() => { const selectedEnv = computed(() => {

View File

@@ -19,7 +19,7 @@
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:icon="IconArchive" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
@click="displayModalImportExport(true)" @click="displayModalImportExport(true)"
/> />
@@ -32,19 +32,35 @@
:environment="environment" :environment="environment"
@edit-environment="editEnvironment(index)" @edit-environment="editEnvironment(index)"
/> />
<HoppSmartPlaceholder <div v-if="!environments.length" class="p-5 space-y-25 flex flex-col">
v-if="environments.length === 0" <div class="flex flex-col items-center space-y-4">
:src="`/images/states/${colorMode.value}/blockchain.svg`" <span class="text-secondaryLight text-center">
:alt="`${t('empty.environments')}`" {{ t("environment.import_or_create") }}
:text="t('empty.environments')" </span>
> <div class="flex gap-4 flex-col items-center">
<HoppButtonPrimary
:icon="IconImport"
:label="t('import.title')"
filled
outline
@click="displayModalImportExport(true)"
/>
<HoppButtonSecondary <HoppButtonSecondary
:icon="IconPlus"
:label="`${t('add.new')}`" :label="`${t('add.new')}`"
filled filled
outline outline
@click="displayModalAdd(true)" @click="displayModalAdd(true)"
/> />
</HoppSmartPlaceholder> </div>
</div>
<HoppSmartPlaceholder
:src="`/images/states/${colorMode.value}/blockchain.svg`"
:alt="`${t('empty.environments')}`"
:text="t('empty.environments')"
/>
</div>
<EnvironmentsMyDetails <EnvironmentsMyDetails
:show="showModalDetails" :show="showModalDetails"
:action="action" :action="action"
@@ -66,8 +82,8 @@ import { environments$ } from "~/newstore/environments"
import { useColorMode } from "~/composables/theming" import { useColorMode } from "~/composables/theming"
import { useReadonlyStream } from "@composables/stream" import { useReadonlyStream } from "@composables/stream"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
import IconArchive from "~icons/lucide/archive"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import IconImport from "~icons/lucide/folder-down"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import { Environment } from "@hoppscotch/data" import { Environment } from "@hoppscotch/data"
import { defineActionHandler } from "~/helpers/actions" import { defineActionHandler } from "~/helpers/actions"

View File

@@ -31,41 +31,54 @@
v-if="team !== undefined && team.myRole === 'VIEWER'" v-if="team !== undefined && team.myRole === 'VIEWER'"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
disabled disabled
:icon="IconArchive" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-else v-else
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:icon="IconArchive" :icon="IconImport"
:title="t('modal.import_export')" :title="t('modal.import_export')"
@click="displayModalImportExport(true)" @click="displayModalImportExport(true)"
/> />
</div> </div>
</div> </div>
<HoppSmartPlaceholder <div
v-if="!loading && teamEnvironments.length === 0 && !adapterError" v-if="!loading && !teamEnvironments.length && !adapterError"
:src="`/images/states/${colorMode.value}/blockchain.svg`" class="p-5 space-y-25 flex flex-col"
:alt="`${t('empty.environments')}`"
:text="t('empty.environments')"
> >
<HoppButtonSecondary <div class="flex flex-col items-center space-y-4">
v-if="team === undefined || team.myRole === 'VIEWER'" <span class="text-secondaryLight text-center">
v-tippy="{ theme: 'tooltip' }" {{ t("environment.import_or_create") }}
disabled </span>
<div class="flex gap-4 flex-col items-center">
<HoppButtonPrimary
:icon="IconImport"
:label="t('import.title')"
filled filled
:icon="IconPlus" outline
:title="t('team.no_access')" :title="isTeamViewer ? t('team.no_access') : ''"
:label="t('action.new')" :disabled="isTeamViewer"
@click="isTeamViewer ? null : displayModalImportExport(true)"
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-else
:label="`${t('add.new')}`" :label="`${t('add.new')}`"
filled filled
outline outline
@click="displayModalAdd(true)" :icon="IconPlus"
:title="isTeamViewer ? t('team.no_access') : ''"
:disabled="isTeamViewer"
@click="isTeamViewer ? null : displayModalAdd(true)"
/> />
</HoppSmartPlaceholder> </div>
</div>
<HoppSmartPlaceholder
:src="`/images/states/${colorMode.value}/blockchain.svg`"
:alt="`${t('empty.environments')}`"
:text="t('empty.environments')"
/>
</div>
<div v-else-if="!loading"> <div v-else-if="!loading">
<EnvironmentsTeamsEnvironment <EnvironmentsTeamsEnvironment
v-for="(environment, index) in JSON.parse( v-for="(environment, index) in JSON.parse(
@@ -108,14 +121,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue" import { computed, ref } from "vue"
import { GQLError } from "~/helpers/backend/GQLClient" import { GQLError } from "~/helpers/backend/GQLClient"
import { TeamEnvironment } from "~/helpers/teams/TeamEnvironment" import { TeamEnvironment } from "~/helpers/teams/TeamEnvironment"
import { useI18n } from "~/composables/i18n" import { useI18n } from "~/composables/i18n"
import { useColorMode } from "~/composables/theming" import { useColorMode } from "~/composables/theming"
import IconPlus from "~icons/lucide/plus" import IconPlus from "~icons/lucide/plus"
import IconArchive from "~icons/lucide/archive"
import IconHelpCircle from "~icons/lucide/help-circle" import IconHelpCircle from "~icons/lucide/help-circle"
import IconImport from "~icons/lucide/folder-down"
import { defineActionHandler } from "~/helpers/actions" import { defineActionHandler } from "~/helpers/actions"
import { GetMyTeamsQuery } from "~/helpers/backend/graphql" import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
@@ -138,6 +151,8 @@ const action = ref<"new" | "edit">("edit")
const editingEnvironment = ref<TeamEnvironment | null>(null) const editingEnvironment = ref<TeamEnvironment | null>(null)
const editingVariableName = ref("") const editingVariableName = ref("")
const isTeamViewer = computed(() => props.team?.myRole === "VIEWER")
const displayModalAdd = (shouldDisplay: boolean) => { const displayModalAdd = (shouldDisplay: boolean) => {
action.value = "new" action.value = "new"
showModalDetails.value = shouldDisplay showModalDetails.value = shouldDisplay

View File

@@ -185,18 +185,24 @@
<span> <span>
<HoppButtonSecondary <HoppButtonSecondary
v-if="header.source === 'auth'" v-if="header.source === 'auth'"
v-tippy="{ theme: 'tooltip' }"
:title="t(masking ? 'state.show' : 'state.hide')"
:icon="masking ? IconEye : IconEyeOff" :icon="masking ? IconEye : IconEyeOff"
@click="toggleMask()" @click="toggleMask()"
/> />
<HoppButtonSecondary <HoppButtonSecondary
v-else v-else
v-tippy="{ theme: 'tooltip' }"
:icon="IconArrowUpRight" :icon="IconArrowUpRight"
:title="t('request.go_to_authorization_tab')"
class="cursor-auto text-primary hover:text-primary" class="cursor-auto text-primary hover:text-primary"
/> />
</span> </span>
<span> <span>
<HoppButtonSecondary <HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:icon="IconArrowUpRight" :icon="IconArrowUpRight"
:title="t('request.go_to_authorization_tab')"
@click="changeTab(header.source)" @click="changeTab(header.source)"
/> />
</span> </span>