Merge branch 'main' into feat/short-code

This commit is contained in:
liyasthomas
2021-11-22 11:35:16 +05:30
103 changed files with 2125 additions and 2203 deletions

View File

@@ -0,0 +1,57 @@
name: Bug report
description: Create a bug report to help us improve Hoppscotch
title: "[bug]: "
labels: [bug, need testing]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out this bug report.
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Current behavior
description: A concise description of what you're experiencing and what you expect
placeholder: |
When I do <X>, <Y> happens and I see the error message attached below:
```...```
What I expect is <Z>
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Add steps to reproduce this behaviour, include console or network logs and screenshots
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: dropdown
id: env
attributes:
label: Environment
options:
- Production
- Release
- Deploy preview
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
options:
- Cloud
- Self-hosted
- Local
validations:
required: true

View File

@@ -0,0 +1,28 @@
name: Feature request
description: Suggest a feature to improve Hoppscotch
title: "[feature]: "
labels: [feature]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to request a feature for Hoppscotch
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue related to this feature request already exists
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Summary
description: One paragraph description of the feature
validations:
required: true
- type: textarea
attributes:
label: Why should this be worked on?
description: A concise description of the problems or use cases for this feature request
validations:
required: true

View File

@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

7
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
contact_links:
- name: Help and support
url: https://github.com/hoppscotch/hoppscotch#support
about: Reach out to us on our Discord server or Telegram group or GitHub discussions.
- name: Dedicated support
url: mailto:support@hoppscotch.io
about: Write to us if you'd like dedicated support using Hoppscotch

View File

@@ -1,8 +0,0 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -46,7 +46,7 @@
#### **Support** #### **Support**
[![Chat on Discord](https://img.shields.io/badge/chat-Discord-7289DA?logo=discord)](https://hoppscotch.io/discord) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-2CA5E0?logo=Telegram)](https://hoppscotch.io/telegram) [![Chat on Discord](https://img.shields.io/badge/chat-Discord-7289DA?logo=discord)](https://hoppscotch.io/discord) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-2CA5E0?logo=telegram)](https://hoppscotch.io/telegram) [![Discuss on GitHub](https://img.shields.io/badge/discussions-GitHub-333333?logo=github)](https://github.com/hoppscotch/hoppscotch/discussions)
<details open> <details open>
<summary><b>Table of contents</b></summary> <summary><b>Table of contents</b></summary>

26
SECURITY.md Normal file
View File

@@ -0,0 +1,26 @@
# Security Policy
This document outlines security procedures and general policies for the Hoppscotch project.
1. [Reporting a security vulnerability](#reporting-a-security-vulnerability)
3. [Incident response process](#incident-response-process)
## Reporting a security vulnerability
Report security vulnerabilities by emailing the Hoppscotch Support team at support@hoppscotch.io.
The primary security point of contact from Hoppscotch Support team will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
**Do not create a GitHub issue ticket to report a security vulnerability.**
The Hoppscotch team and community take all security vulnerability reports in Hoppscotch seriously. Thank you for improving the security of Hoppscotch. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
Report security bugs in third-party modules to the person or team maintaining the module.
## Incident response process
In case an incident is discovered or reported, we will follow the following process to contain, respond, and remediate:
1. Confirm the problem and determine the affected versions.
2. Audit code to find any potential similar problems.
3. Prepare fixes for all releases still under maintenance. These fixes will be deployed as fast as possible to production.

View File

@@ -4,6 +4,7 @@
"description": "Open source API development ecosystem", "description": "Open source API development ecosystem",
"author": "Hoppscotch (support@hoppscotch.io)", "author": "Hoppscotch (support@hoppscotch.io)",
"private": true, "private": true,
"license": "MIT",
"scripts": { "scripts": {
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"prepare": "husky install", "prepare": "husky install",
@@ -20,10 +21,10 @@
], ],
"dependencies": { "dependencies": {
"husky": "^7.0.4", "husky": "^7.0.4",
"lint-staged": "^12.0.2" "lint-staged": "^12.0.3"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^14.1.0", "@commitlint/cli": "^15.0.0",
"@commitlint/config-conventional": "^14.1.0" "@commitlint/config-conventional": "^15.0.0"
} }
} }

View File

@@ -2,6 +2,7 @@
"name": "@hoppscotch/codemirror-lang-graphql", "name": "@hoppscotch/codemirror-lang-graphql",
"version": "0.1.0", "version": "0.1.0",
"description": "GraphQL language support for CodeMirror", "description": "GraphQL language support for CodeMirror",
"author": "Hoppscotch (support@hoppscotch.io)",
"scripts": { "scripts": {
"prepare": "rollup -c" "prepare": "rollup -c"
}, },
@@ -22,10 +23,10 @@
"devDependencies": { "devDependencies": {
"@lezer/generator": "^0.15.0", "@lezer/generator": "^0.15.0",
"mocha": "^9.0.1", "mocha": "^9.0.1",
"rollup": "^2.35.1", "rollup": "^2.60.0",
"rollup-plugin-dts": "^3.0.2", "rollup-plugin-dts": "^4.0.1",
"rollup-plugin-ts": "^1.4.0", "rollup-plugin-ts": "^2.0.4",
"typescript": "^4.3.4" "typescript": "^4.5.2"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@@ -35,13 +35,8 @@
@apply bg-divider; @apply bg-divider;
} }
.cm-focused {
@apply !outline-none;
}
input::placeholder, input::placeholder,
textarea::placeholder, textarea::placeholder {
.CodeMirror-empty {
@apply text-secondary; @apply text-secondary;
@apply opacity-25; @apply opacity-25;
} }
@@ -318,7 +313,7 @@ pre.ace_editor {
&.toasted-primary { &.toasted-primary {
@apply bg-tooltip; @apply bg-tooltip;
@apply text-primary; @apply text-primary;
@apply justify-start; @apply justify-between;
@apply shadow; @apply shadow;
@apply font-medium; @apply font-medium;
@apply transition; @apply transition;
@@ -391,7 +386,7 @@ pre.ace_editor {
.smart-splitter .splitpanes__splitter::before { .smart-splitter .splitpanes__splitter::before {
@apply absolute; @apply absolute;
@apply inset-0; @apply inset-0;
@apply bg-dividerLight; @apply bg-accentLight;
@apply opacity-0; @apply opacity-0;
@apply z-20; @apply z-20;
@apply transition; @apply transition;
@@ -435,29 +430,16 @@ pre.ace_editor {
@apply w-full; @apply w-full;
} }
.CodeMirror { .cm-focused {
@apply !h-auto; @apply select-auto;
@apply !outline-none;
font-size: var(--body-font-size); .cm-activeLine {
&:not(.CodeMirror-focused) .CodeMirror-activeline-background {
background: transparent !important;
}
.CodeMirror-dialog-top {
@apply bg-primaryLight; @apply bg-primaryLight;
@apply border-dividerLight;
@apply px-4;
@apply py-2;
@apply z-5;
} }
.CodeMirror-scroll { .cm-activeLineGutter {
@apply min-h-64; @apply bg-primaryDark;
}
* {
font-family: "Roboto Mono", monospace;
} }
} }

View File

@@ -53,17 +53,17 @@
} }
@mixin dark-editor-theme { @mixin dark-editor-theme {
--editor-type-color: theme("colors.purple.500"); --editor-type-color: theme("colors.purple.400");
--editor-name-color: theme("colors.blue.500"); --editor-name-color: theme("colors.blue.400");
--editor-operator-color: theme("colors.indigo.500"); --editor-operator-color: theme("colors.indigo.400");
--editor-invalid-color: theme("colors.red.500"); --editor-invalid-color: theme("colors.red.400");
--editor-separator-color: theme("colors.gray.500"); --editor-separator-color: theme("colors.gray.400");
--editor-meta-color: theme("colors.gray.500"); --editor-meta-color: theme("colors.gray.400");
--editor-variable-color: theme("colors.green.500"); --editor-variable-color: theme("colors.green.400");
--editor-link-color: theme("colors.cyan.500"); --editor-link-color: theme("colors.cyan.400");
--editor-process-color: theme("colors.gray.400"); --editor-process-color: theme("colors.fuchsia.400");
--editor-constant-color: theme("colors.fuchsia.500"); --editor-constant-color: theme("colors.violet.400");
--editor-keyword-color: theme("colors.pink.500"); --editor-keyword-color: theme("colors.pink.400");
} }
@mixin light-editor-theme { @mixin light-editor-theme {
@@ -82,15 +82,15 @@
@mixin black-editor-theme { @mixin black-editor-theme {
--editor-type-color: theme("colors.purple.400"); --editor-type-color: theme("colors.purple.400");
--editor-name-color: theme("colors.gray.400"); --editor-name-color: theme("colors.fuchsia.400");
--editor-operator-color: theme("colors.indigo.400"); --editor-operator-color: theme("colors.indigo.400");
--editor-invalid-color: theme("colors.red.400"); --editor-invalid-color: theme("colors.red.400");
--editor-separator-color: theme("colors.gray.400"); --editor-separator-color: theme("colors.gray.400");
--editor-meta-color: theme("colors.gray.400"); --editor-meta-color: theme("colors.gray.400");
--editor-variable-color: theme("colors.green.400"); --editor-variable-color: theme("colors.green.400");
--editor-link-color: theme("colors.cyan.400"); --editor-link-color: theme("colors.cyan.400");
--editor-process-color: theme("colors.blue.400"); --editor-process-color: theme("colors.violet.400");
--editor-constant-color: theme("colors.fuchsia.400"); --editor-constant-color: theme("colors.blue.400");
--editor-keyword-color: theme("colors.pink.400"); --editor-keyword-color: theme("colors.pink.400");
} }

View File

@@ -4,7 +4,7 @@
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="EXPAND_NAVIGATION ? $t('hide.sidebar') : $t('show.sidebar')" :title="EXPAND_NAVIGATION ? t('hide.sidebar') : t('show.sidebar')"
svg="sidebar" svg="sidebar"
class="transform" class="transform"
:class="{ '-rotate-180': !EXPAND_NAVIGATION }" :class="{ '-rotate-180': !EXPAND_NAVIGATION }"
@@ -12,9 +12,9 @@
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="`${ :title="`${ZEN_MODE ? t('action.turn_off') : t('action.turn_on')} ${t(
ZEN_MODE ? $t('action.turn_off') : $t('action.turn_on') 'layout.zen_mode'
} ${$t('layout.zen_mode')}`" )}`"
:svg="ZEN_MODE ? 'minimize' : 'maximize'" :svg="ZEN_MODE ? 'minimize' : 'maximize'"
:class="{ :class="{
'!text-accent !focus-visible:text-accentDark !hover:text-accentDark': '!text-accent !focus-visible:text-accentDark !hover:text-accentDark':
@@ -36,20 +36,20 @@
<ButtonSecondary <ButtonSecondary
svg="help-circle" svg="help-circle"
class="!rounded-none" class="!rounded-none"
:label="`${$t('app.help')}`" :label="`${t('app.help')}`"
/> />
</template> </template>
<div class="flex flex-col"> <div class="flex flex-col">
<SmartItem <SmartItem
svg="book" svg="book"
:label="`${$t('app.documentation')}`" :label="`${t('app.documentation')}`"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io"
blank blank
@click.native="$refs.options.tippy().hide()" @click.native="$refs.options.tippy().hide()"
/> />
<SmartItem <SmartItem
svg="zap" svg="zap"
:label="`${$t('app.keyboard_shortcuts')}`" :label="`${t('app.keyboard_shortcuts')}`"
@click.native=" @click.native="
() => { () => {
showShortcuts = true showShortcuts = true
@@ -59,14 +59,14 @@
/> />
<SmartItem <SmartItem
svg="gift" svg="gift"
:label="`${$t('app.whats_new')}`" :label="`${t('app.whats_new')}`"
to="https://docs.hoppscotch.io/changelog" to="https://docs.hoppscotch.io/changelog"
blank blank
@click.native="$refs.options.tippy().hide()" @click.native="$refs.options.tippy().hide()"
/> />
<SmartItem <SmartItem
svg="message-circle" svg="message-circle"
:label="`${$t('app.chat_with_us')}`" :label="`${t('app.chat_with_us')}`"
@click.native=" @click.native="
() => { () => {
chatWithUs() chatWithUs()
@@ -77,21 +77,21 @@
<hr /> <hr />
<SmartItem <SmartItem
svg="github" svg="github"
:label="`${$t('app.github')}`" :label="`${t('app.github')}`"
to="https://github.com/hoppscotch/hoppscotch" to="https://github.com/hoppscotch/hoppscotch"
blank blank
@click.native="$refs.options.tippy().hide()" @click.native="$refs.options.tippy().hide()"
/> />
<SmartItem <SmartItem
svg="twitter" svg="twitter"
:label="`${$t('app.twitter')}`" :label="`${t('app.twitter')}`"
to="https://hoppscotch.io/twitter" to="https://hoppscotch.io/twitter"
blank blank
@click.native="$refs.options.tippy().hide()" @click.native="$refs.options.tippy().hide()"
/> />
<SmartItem <SmartItem
svg="user-plus" svg="user-plus"
:label="`${$t('app.invite')}`" :label="`${t('app.invite')}`"
@click.native=" @click.native="
() => { () => {
showShare = true showShare = true
@@ -101,14 +101,14 @@
/> />
<SmartItem <SmartItem
svg="lock" svg="lock"
:label="`${$t('app.terms_and_privacy')}`" :label="`${t('app.terms_and_privacy')}`"
to="https://docs.hoppscotch.io/privacy" to="https://docs.hoppscotch.io/privacy"
blank blank
@click.native="$refs.options.tippy().hide()" @click.native="$refs.options.tippy().hide()"
/> />
<!-- <SmartItem :label="$t('app.status')" /> --> <!-- <SmartItem :label="t('app.status')" /> -->
<div class="flex opacity-50 py-2 px-4"> <div class="flex opacity-50 py-2 px-4">
{{ `${$t("app.name")} ${$t("app.version")}` }} {{ `${t("app.name")} ${t("app.version")}` }}
</div> </div>
</div> </div>
</tippy> </tippy>
@@ -116,19 +116,19 @@
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
svg="zap" svg="zap"
:title="$t('app.shortcuts')" :title="t('app.shortcuts')"
@click.native="showShortcuts = true" @click.native="showShortcuts = true"
/> />
<ButtonSecondary <ButtonSecondary
v-if="navigatorShare" v-if="navigatorShare"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
svg="share-2" svg="share-2"
:title="$t('request.share')" :title="t('request.share')"
@click.native="nativeShare()" @click.native="nativeShare()"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="COLUMN_LAYOUT ? $t('layout.row') : $t('layout.column')" :title="COLUMN_LAYOUT ? t('layout.row') : t('layout.column')"
svg="columns" svg="columns"
class="transform" class="transform"
:class="{ 'rotate-90': !COLUMN_LAYOUT }" :class="{ 'rotate-90': !COLUMN_LAYOUT }"
@@ -142,7 +142,7 @@
> >
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')" :title="SIDEBAR ? t('hide.sidebar') : t('show.sidebar')"
svg="sidebar-open" svg="sidebar-open"
class="transform" class="transform"
:class="{ 'rotate-180': !SIDEBAR }" :class="{ 'rotate-180': !SIDEBAR }"
@@ -156,45 +156,41 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api" import { ref, watch } from "@nuxtjs/composition-api"
import { defineActionHandler } from "~/helpers/actions" import { defineActionHandler } from "~/helpers/actions"
import { showChat } from "~/helpers/support" import { showChat } from "~/helpers/support"
import { useSetting } from "~/newstore/settings" import { useSetting } from "~/newstore/settings"
import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
setup() { const showShortcuts = ref(false)
const showShortcuts = ref(false) const showShare = ref(false)
const showShare = ref(false)
defineActionHandler("flyouts.keybinds.toggle", () => { defineActionHandler("flyouts.keybinds.toggle", () => {
showShortcuts.value = !showShortcuts.value showShortcuts.value = !showShortcuts.value
}) })
defineActionHandler("modals.share.toggle", () => { defineActionHandler("modals.share.toggle", () => {
showShare.value = !showShare.value showShare.value = !showShare.value
}) })
return { const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
EXPAND_NAVIGATION: useSetting("EXPAND_NAVIGATION"), const SIDEBAR = useSetting("SIDEBAR")
SIDEBAR: useSetting("SIDEBAR"), const ZEN_MODE = useSetting("ZEN_MODE")
ZEN_MODE: useSetting("ZEN_MODE"), const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"), const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
navigatorShare: !!navigator.share, const navigatorShare = !!navigator.share
showShortcuts, watch(
showShare, () => ZEN_MODE.value,
() => {
EXPAND_NAVIGATION.value = !ZEN_MODE.value
} }
}, )
watch: {
ZEN_MODE() { const nativeShare = () => {
this.EXPAND_NAVIGATION = !this.ZEN_MODE
},
},
methods: {
nativeShare() {
if (navigator.share) { if (navigator.share) {
navigator navigator
.share({ .share({
@@ -207,10 +203,9 @@ export default defineComponent({
} else { } else {
// fallback // fallback
} }
}, }
chatWithUs() {
const chatWithUs = () => {
showChat() showChat()
}, }
},
})
</script> </script>

View File

@@ -15,7 +15,7 @@
> >
<i class="opacity-75 pb-2 material-icons">manage_search</i> <i class="opacity-75 pb-2 material-icons">manage_search</i>
<span class="text-center"> <span class="text-center">
{{ $t("state.nothing_found") }} "{{ search }}" {{ t("state.nothing_found") }} "{{ search }}"
</span> </span>
</div> </div>
</div> </div>
@@ -26,6 +26,9 @@ import { computed, onUnmounted, onMounted } from "@nuxtjs/composition-api"
import Fuse from "fuse.js" import Fuse from "fuse.js"
import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation" import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation"
import { HoppAction } from "~/helpers/actions" import { HoppAction } from "~/helpers/actions"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
input: Record<string, any>[] input: Record<string, any>[]

View File

@@ -18,19 +18,13 @@
</transition> </transition>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import GithubButton from "vue-github-button" import GithubButton from "vue-github-button"
export default defineComponent({ defineProps({
components: {
GithubButton,
},
props: {
size: { size: {
type: String, type: String,
default: undefined, default: undefined,
}, },
},
}) })
</script> </script>

View File

@@ -15,21 +15,21 @@
<ButtonSecondary <ButtonSecondary
id="installPWA" id="installPWA"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('header.install_pwa')" :title="t('header.install_pwa')"
svg="download" svg="download"
class="rounded" class="rounded"
@click.native="showInstallPrompt()" @click.native="showInstallPrompt()"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="`${$t('app.search')} <kbd>/</kbd>`" :title="`${t('app.search')} <kbd>/</kbd>`"
svg="search" svg="search"
class="rounded" class="rounded"
@click.native="showSearch = true" @click.native="showSearch = true"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="`${$t('support.title')} <kbd>?</kbd>`" :title="`${t('support.title')} <kbd>?</kbd>`"
svg="life-buoy" svg="life-buoy"
class="rounded" class="rounded"
@click.native="showSupport = true" @click.native="showSupport = true"
@@ -37,21 +37,21 @@
<ButtonSecondary <ButtonSecondary
v-if="currentUser === null" v-if="currentUser === null"
svg="upload-cloud" svg="upload-cloud"
:label="$t('header.save_workspace')" :label="t('header.save_workspace')"
filled filled
class="hidden md:flex" class="hidden md:flex"
@click.native="showLogin = true" @click.native="showLogin = true"
/> />
<ButtonPrimary <ButtonPrimary
v-if="currentUser === null" v-if="currentUser === null"
:label="$t('header.login')" :label="t('header.login')"
@click.native="showLogin = true" @click.native="showLogin = true"
/> />
<div v-else class="space-x-2 inline-flex items-center"> <div v-else class="space-x-2 inline-flex items-center">
<ButtonPrimary <ButtonPrimary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('team.invite_tooltip')" :title="t('team.invite_tooltip')"
:label="$t('team.invite')" :label="t('team.invite')"
svg="user-plus" svg="user-plus"
class=" class="
!bg-green-500 !bg-green-500
@@ -78,7 +78,7 @@
<ButtonSecondary <ButtonSecondary
v-else v-else
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('header.account')" :title="t('header.account')"
class="rounded" class="rounded"
svg="user" svg="user"
/> />
@@ -86,13 +86,13 @@
<SmartItem <SmartItem
to="/profile" to="/profile"
svg="user" svg="user"
:label="$t('navigation.profile')" :label="t('navigation.profile')"
@click.native="$refs.user.tippy().hide()" @click.native="$refs.user.tippy().hide()"
/> />
<SmartItem <SmartItem
to="/settings" to="/settings"
svg="settings" svg="settings"
:label="$t('navigation.settings')" :label="t('navigation.settings')"
@click.native="$refs.user.tippy().hide()" @click.native="$refs.user.tippy().hide()"
/> />
<FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" /> <FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" />
@@ -110,18 +110,20 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, useContext } from "@nuxtjs/composition-api" import { onMounted, ref } from "@nuxtjs/composition-api"
import intializePwa from "~/helpers/pwa" import intializePwa from "~/helpers/pwa"
import { probableUser$ } from "~/helpers/fb/auth" import { probableUser$ } from "~/helpers/fb/auth"
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence" import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
import { useReadonlyStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useI18n,
useToast,
} from "~/helpers/utils/composables"
import { defineActionHandler } from "~/helpers/actions" import { defineActionHandler } from "~/helpers/actions"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
/** /**
* Once the PWA code is initialized, this holds a method * Once the PWA code is initialized, this holds a method
@@ -160,12 +162,11 @@ onMounted(() => {
const cookiesAllowed = getLocalConfig("cookiesAllowed") === "yes" const cookiesAllowed = getLocalConfig("cookiesAllowed") === "yes"
if (!cookiesAllowed) { if (!cookiesAllowed) {
$toast.show(t("app.we_use_cookies").toString(), { toast.show(`${t("app.we_use_cookies")}`, {
icon: "cookie",
duration: 0, duration: 0,
action: [ action: [
{ {
text: t("action.learn_more").toString(), text: `${t("action.learn_more")}`,
onClick: (_, toastObject) => { onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes") setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0) toastObject.goAway(0)
@@ -173,7 +174,7 @@ onMounted(() => {
}, },
}, },
{ {
text: t("action.dismiss").toString(), text: `${t("action.dismiss")}`,
onClick: (_, toastObject) => { onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes") setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0) toastObject.goAway(0)

View File

@@ -4,17 +4,17 @@
:on="PROXY_ENABLED" :on="PROXY_ENABLED"
@change="toggleSettingKey('PROXY_ENABLED')" @change="toggleSettingKey('PROXY_ENABLED')"
> >
{{ $t("settings.proxy") }} {{ t("settings.proxy") }}
</SmartToggle> </SmartToggle>
<SmartToggle <SmartToggle
:on="EXTENSIONS_ENABLED" :on="EXTENSIONS_ENABLED"
@change="toggleSettingKey('EXTENSIONS_ENABLED')" @change="toggleSettingKey('EXTENSIONS_ENABLED')"
> >
{{ $t("settings.extensions") }}: {{ t("settings.extensions") }}:
{{ {{
extensionVersion != null extensionVersion != null
? `v${extensionVersion.major}.${extensionVersion.minor}` ? `v${extensionVersion.major}.${extensionVersion.minor}`
: $t("settings.extension_ver_not_reported") : t("settings.extension_ver_not_reported")
}} }}
</SmartToggle> </SmartToggle>
</div> </div>
@@ -25,6 +25,9 @@ import { defineComponent } from "@nuxtjs/composition-api"
import { KeysMatching } from "~/types/ts-utils" import { KeysMatching } from "~/types/ts-utils"
import { SettingsType, toggleSetting, useSetting } from "~/newstore/settings" import { SettingsType, toggleSetting, useSetting } from "~/newstore/settings"
import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy" import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
const PROXY_ENABLED = useSetting("PROXY_ENABLED") const PROXY_ENABLED = useSetting("PROXY_ENABLED")
const EXTENSIONS_ENABLED = useSetting("EXTENSIONS_ENABLED") const EXTENSIONS_ENABLED = useSetting("EXTENSIONS_ENABLED")

View File

@@ -13,7 +13,7 @@
type="text" type="text"
autocomplete="off" autocomplete="off"
name="command" name="command"
:placeholder="`${$t('app.type_a_command_search')}`" :placeholder="`${t('app.type_a_command_search')}`"
class=" class="
bg-transparent bg-transparent
border-b border-dividerLight border-b border-dividerLight
@@ -45,7 +45,7 @@
class="flex flex-col" class="flex flex-col"
> >
<h5 class="my-2 text-secondaryLight py-2 px-6"> <h5 class="my-2 text-secondaryLight py-2 px-6">
{{ $t(map.section) }} {{ t(map.section) }}
</h5> </h5>
<AppPowerSearchEntry <AppPowerSearchEntry
v-for="(shortcut, shortcutIndex) in map.shortcuts" v-for="(shortcut, shortcutIndex) in map.shortcuts"
@@ -66,6 +66,9 @@ import { ref, computed, watch } from "@nuxtjs/composition-api"
import { HoppAction, invokeAction } from "~/helpers/actions" import { HoppAction, invokeAction } from "~/helpers/actions"
import { spotlight as mappings, fuse } from "~/helpers/shortcuts" import { spotlight as mappings, fuse } from "~/helpers/shortcuts"
import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation" import { useArrowKeysNavigation } from "~/helpers/powerSearchNavigation"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
show: boolean show: boolean

View File

@@ -24,7 +24,7 @@
class="flex flex-1 mr-4 font-medium transition" class="flex flex-1 mr-4 font-medium transition"
:class="{ 'text-secondaryDark': active }" :class="{ 'text-secondaryDark': active }"
> >
{{ $t(shortcut.label) }} {{ t(shortcut.label) }}
</span> </span>
<span <span
v-for="(key, keyIndex) in shortcut.keys" v-for="(key, keyIndex) in shortcut.keys"
@@ -37,6 +37,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
defineProps<{ defineProps<{
shortcut: Object shortcut: Object
active: Boolean active: Boolean

View File

@@ -4,15 +4,11 @@
</section> </section>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" defineProps({
export default defineComponent({
props: {
label: { label: {
type: String, type: String,
default: "Section", default: "Section",
}, },
},
}) })
</script> </script>

View File

@@ -1,12 +1,12 @@
<template> <template>
<SmartModal <SmartModal
v-if="show" v-if="show"
:title="$t('app.invite_your_friends')" :title="t('app.invite_your_friends')"
@close="$emit('hide-modal')" @close="hideModal"
> >
<template #body> <template #body>
<p class="text-secondaryLight mb-8 px-2"> <p class="text-secondaryLight mb-8 px-2">
{{ $t("app.invite_description") }} {{ t("app.invite_description") }}
</p> </p>
<div class="flex flex-col space-y-2 px-2"> <div class="flex flex-col space-y-2 px-2">
<div class="grid gap-4 grid-cols-3"> <div class="grid gap-4 grid-cols-3">
@@ -25,7 +25,7 @@
<button class="share-link" @click="copyAppLink"> <button class="share-link" @click="copyAppLink">
<SmartIcon class="h-6 text-xl w-6" :name="copyIcon" /> <SmartIcon class="h-6 text-xl w-6" :name="copyIcon" />
<span class="mt-3"> <span class="mt-3">
{{ $t("app.copy") }} {{ t("app.copy") }}
</span> </span>
</button> </button>
</div> </div>
@@ -34,28 +34,33 @@
</SmartModal> </SmartModal>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { ref } from "@nuxtjs/composition-api"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useI18n, useToast } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
props: {
show: Boolean, const toast = useToast()
},
data() { defineProps<{
const url = "https://hoppscotch.io" show: Boolean
const text = "Hoppscotch - Open source API development ecosystem." }>()
const description =
const emit = defineEmits<{
(e: "hide-modal"): void
}>()
const url = "https://hoppscotch.io"
const text = "Hoppscotch - Open source API development ecosystem."
const description =
"Helps you create requests faster, saving precious time on development." "Helps you create requests faster, saving precious time on development."
const subject = const subject = "Checkout Hoppscotch - an open source API development ecosystem"
"Checkout Hoppscotch - an open source API development ecosystem" const summary = `Hi there!%0D%0A%0D%0AI thought youll like this new platform that I joined called Hoppscotch - https://hoppscotch.io.%0D%0AIt is a simple and intuitive interface for creating and managing your APIs. You can build, test, document, and share your APIs.%0D%0A%0D%0AThe best part about Hoppscotch is that it is open source and free to get started.%0D%0A%0D%0A`
const summary = `Hi there!%0D%0A%0D%0AI thought youll like this new platform that I joined called Hoppscotch - https://hoppscotch.io.%0D%0AIt is a simple and intuitive interface for creating and managing your APIs. You can build, test, document, and share your APIs.%0D%0A%0D%0AThe best part about Hoppscotch is that it is open source and free to get started.%0D%0A%0D%0A` const twitter = "hoppscotch_io"
const twitter = "hoppscotch_io"
return { const copyIcon = ref("copy")
url: "https://hoppscotch.io", const platforms = [
copyIcon: "copy",
platforms: [
{ {
name: "Email", name: "Email",
icon: "mail", icon: "mail",
@@ -81,23 +86,18 @@ export default defineComponent({
icon: "brands/linkedin", icon: "brands/linkedin",
link: `https://www.linkedin.com/sharing/share-offsite/?url=${url}`, link: `https://www.linkedin.com/sharing/share-offsite/?url=${url}`,
}, },
], ]
}
}, const copyAppLink = () => {
methods: { copyToClipboard(url)
copyAppLink() { copyIcon.value = "check"
copyToClipboard(this.url) toast.success(`${t("state.copied_to_clipboard")}`)
this.copyIcon = "check" setTimeout(() => (copyIcon.value = "copy"), 1000)
this.$toast.success(this.$t("state.copied_to_clipboard"), { }
icon: "content_paste",
}) const hideModal = () => {
setTimeout(() => (this.copyIcon = "copy"), 1000) emit("hide-modal")
}, }
hideModal() {
this.$emit("hide-modal")
},
},
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -14,7 +14,7 @@
justify-between justify-between
" "
> >
<h3 class="ml-4 heading">{{ $t("app.shortcuts") }}</h3> <h3 class="ml-4 heading">{{ t("app.shortcuts") }}</h3>
<div class="flex"> <div class="flex">
<ButtonSecondary svg="x" class="rounded" @click.native="close()" /> <ButtonSecondary svg="x" class="rounded" @click.native="close()" />
</div> </div>
@@ -35,18 +35,26 @@
px-4 px-4
focus-visible:border-divider focus-visible:border-divider
" "
:placeholder="`${$t('action.search')}`" :placeholder="`${t('action.search')}`"
/> />
</div> </div>
</div> </div>
<div v-if="filterText"> <div
v-if="filterText"
class="
divide-y divide-dividerLight
flex flex-col flex-1
overflow-auto
hide-scrollbar
"
>
<div <div
v-for="(map, mapIndex) in searchResults" v-for="(map, mapIndex) in searchResults"
:key="`map-${mapIndex}`" :key="`map-${mapIndex}`"
class="space-y-4 py-4 px-6" class="space-y-4 py-4 px-6"
> >
<h1 class="font-semibold text-secondaryDark"> <h1 class="font-semibold text-secondaryDark">
{{ $t(map.item.section) }} {{ t(map.item.section) }}
</h1> </h1>
<AppShortcutsEntry <AppShortcutsEntry
v-for="(shortcut, index) in map.item.shortcuts" v-for="(shortcut, index) in map.item.shortcuts"
@@ -66,7 +74,7 @@
> >
<i class="opacity-75 pb-2 material-icons">manage_search</i> <i class="opacity-75 pb-2 material-icons">manage_search</i>
<span class="text-center"> <span class="text-center">
{{ $t("state.nothing_found") }} "{{ filterText }}" {{ t("state.nothing_found") }} "{{ filterText }}"
</span> </span>
</div> </div>
</div> </div>
@@ -85,7 +93,7 @@
class="space-y-4 py-4 px-6" class="space-y-4 py-4 px-6"
> >
<h1 class="font-semibold text-secondaryDark"> <h1 class="font-semibold text-secondaryDark">
{{ $t(map.section) }} {{ t(map.section) }}
</h1> </h1>
<AppShortcutsEntry <AppShortcutsEntry
v-for="(shortcut, shortcutIndex) in map.shortcuts" v-for="(shortcut, shortcutIndex) in map.shortcuts"
@@ -102,6 +110,9 @@
import { computed, ref } from "@nuxtjs/composition-api" import { computed, ref } from "@nuxtjs/composition-api"
import Fuse from "fuse.js" import Fuse from "fuse.js"
import mappings from "~/helpers/shortcuts" import mappings from "~/helpers/shortcuts"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
defineProps<{ defineProps<{
show: boolean show: boolean

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="flex items-center"> <div class="flex items-center">
<span class="flex flex-1 mr-4"> <span class="flex flex-1 mr-4">
{{ $t(shortcut.label) }} {{ t(shortcut.label) }}
</span> </span>
<span <span
v-for="(key, index) in shortcut.keys" v-for="(key, index) in shortcut.keys"
@@ -14,6 +14,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
defineProps<{ defineProps<{
shortcut: Object shortcut: Object
}>() }>()

View File

@@ -26,50 +26,43 @@
</aside> </aside>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import useWindowSize from "~/helpers/utils/useWindowSize" import useWindowSize from "~/helpers/utils/useWindowSize"
import { useSetting } from "~/newstore/settings" import { useSetting } from "~/newstore/settings"
import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
setup() {
return { const windowInnerWidth = useWindowSize()
windowInnerWidth: useWindowSize(), const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
EXPAND_NAVIGATION: useSetting("EXPAND_NAVIGATION"),
} const primaryNavigation = [
},
data() {
return {
primaryNavigation: [
{ {
target: "index", target: "index",
svg: "link-2", svg: "link-2",
title: this.$t("navigation.rest"), title: t("navigation.rest"),
}, },
{ {
target: "graphql", target: "graphql",
svg: "graphql", svg: "graphql",
title: this.$t("navigation.graphql"), title: t("navigation.graphql"),
}, },
{ {
target: "realtime", target: "realtime",
svg: "globe", svg: "globe",
title: this.$t("navigation.realtime"), title: t("navigation.realtime"),
}, },
{ {
target: "documentation", target: "documentation",
svg: "book-open", svg: "book-open",
title: this.$t("navigation.doc"), title: t("navigation.doc"),
}, },
{ {
target: "settings", target: "settings",
svg: "settings", svg: "settings",
title: this.$t("navigation.settings"), title: t("navigation.settings"),
}, },
], ]
}
},
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -33,37 +33,34 @@
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { onMounted, watch } from "@nuxtjs/composition-api"
export default defineComponent({ const props = defineProps<{
props: { show: Boolean
show: { }>()
type: Boolean,
required: true, const emit = defineEmits<{
default: false, (e: "close"): void
}, }>()
},
watch: { watch(
show: { () => props.show,
immediate: true, (show) => {
handler(show) {
if (process.client) { if (process.client) {
if (show) document.body.style.setProperty("overflow", "hidden") if (show) document.body.style.setProperty("overflow", "hidden")
else document.body.style.removeProperty("overflow") else document.body.style.removeProperty("overflow")
} }
}, }
}, )
},
mounted() { onMounted(() => {
document.addEventListener("keydown", (e) => { document.addEventListener("keydown", (e) => {
if (e.keyCode === 27 && this.show) this.close() if (e.keyCode === 27 && props.show) close()
}) })
},
methods: {
close() {
this.$emit("close")
},
},
}) })
const close = () => {
emit("close")
}
</script> </script>

View File

@@ -1,7 +1,7 @@
<template> <template>
<SmartModal <SmartModal
v-if="show" v-if="show"
:title="$t('support.title')" :title="t('support.title')"
max-width="sm:max-w-md" max-width="sm:max-w-md"
@close="$emit('hide-modal')" @close="$emit('hide-modal')"
> >
@@ -9,9 +9,9 @@
<div class="flex flex-col space-y-2"> <div class="flex flex-col space-y-2">
<SmartItem <SmartItem
svg="book" svg="book"
:label="$t('app.documentation')" :label="t('app.documentation')"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io"
:description="$t('support.documentation')" :description="t('support.documentation')"
info-icon="chevron_right" info-icon="chevron_right"
active active
blank blank
@@ -19,20 +19,17 @@
/> />
<SmartItem <SmartItem
svg="zap" svg="zap"
:label="$t('app.keyboard_shortcuts')" :label="t('app.keyboard_shortcuts')"
:description="$t('support.shortcuts')" :description="t('support.shortcuts')"
info-icon="chevron_right" info-icon="chevron_right"
active active
@click.native=" @click.native="showShortcuts()"
showShortcuts()
hideModal()
"
/> />
<SmartItem <SmartItem
svg="gift" svg="gift"
:label="$t('app.whats_new')" :label="t('app.whats_new')"
to="https://docs.hoppscotch.io/changelog" to="https://docs.hoppscotch.io/changelog"
:description="$t('support.changelog')" :description="t('support.changelog')"
info-icon="chevron_right" info-icon="chevron_right"
active active
blank blank
@@ -40,31 +37,28 @@
/> />
<SmartItem <SmartItem
svg="message-circle" svg="message-circle"
:label="$t('app.chat_with_us')" :label="t('app.chat_with_us')"
:description="$t('support.chat')" :description="t('support.chat')"
info-icon="chevron_right" info-icon="chevron_right"
active active
@click.native=" @click.native="chatWithUs()"
chatWithUs()
hideModal()
"
/> />
<SmartItem <SmartItem
svg="brands/discord" svg="brands/discord"
:label="$t('app.join_discord_community')" :label="t('app.join_discord_community')"
to="https://hoppscotch.io/discord" to="https://hoppscotch.io/discord"
blank blank
:description="$t('support.community')" :description="t('support.community')"
info-icon="chevron_right" info-icon="chevron_right"
active active
@click.native="hideModal()" @click.native="hideModal()"
/> />
<SmartItem <SmartItem
svg="brands/twitter" svg="brands/twitter"
:label="$t('app.twitter')" :label="t('app.twitter')"
to="https://hoppscotch.io/twitter" to="https://hoppscotch.io/twitter"
blank blank
:description="$t('support.twitter')" :description="t('support.twitter')"
info-icon="chevron_right" info-icon="chevron_right"
active active
@click.native="hideModal()" @click.native="hideModal()"
@@ -74,25 +68,32 @@
</SmartModal> </SmartModal>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { invokeAction } from "~/helpers/actions" import { invokeAction } from "~/helpers/actions"
import { showChat } from "~/helpers/support" import { showChat } from "~/helpers/support"
import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
props: {
show: Boolean, defineProps<{
}, show: Boolean
methods: { }>()
chatWithUs() {
const emit = defineEmits<{
(e: "hide-modal"): void
}>()
const chatWithUs = () => {
showChat() showChat()
}, hideModal()
showShortcuts() { }
const showShortcuts = () => {
invokeAction("flyouts.keybinds.toggle") invokeAction("flyouts.keybinds.toggle")
}, hideModal()
hideModal() { }
this.$emit("hide-modal")
}, const hideModal = () => {
}, emit("hide-modal")
}) }
</script> </script>

View File

@@ -47,9 +47,7 @@ export default defineComponent({
methods: { methods: {
addNewCollection() { addNewCollection() {
if (!this.name) { if (!this.name) {
this.$toast.error(this.$t("collection.invalid_name"), { this.$toast.error(this.$t("collection.invalid_name"))
icon: "error_outline",
})
return return
} }
this.$emit("submit", this.name) this.$emit("submit", this.name)

View File

@@ -51,9 +51,7 @@ export default defineComponent({
methods: { methods: {
addFolder() { addFolder() {
if (!this.name) { if (!this.name) {
this.$toast.error(this.$t("folder.invalid_name"), { this.$toast.error(this.$t("folder.invalid_name"))
icon: "error_outline",
})
return return
} }
this.$emit("add-folder", { this.$emit("add-folder", {

View File

@@ -48,9 +48,7 @@ export default defineComponent({
methods: { methods: {
saveCollection() { saveCollection() {
if (!this.name) { if (!this.name) {
this.$toast.error(this.$t("collection.invalid_name"), { this.$toast.error(this.$t("collection.invalid_name"))
icon: "error_outline",
})
return return
} }
this.$emit("submit", this.name) this.$emit("submit", this.name)

View File

@@ -48,9 +48,7 @@ export default defineComponent({
methods: { methods: {
editFolder() { editFolder() {
if (!this.name) { if (!this.name) {
this.$toast.error(this.$t("folder.invalid_name"), { this.$toast.error(this.$t("folder.invalid_name"))
icon: "error_outline",
})
return return
} }
this.$emit("submit", this.name) this.$emit("submit", this.name)

View File

@@ -47,9 +47,7 @@ export default defineComponent({
methods: { methods: {
saveRequest() { saveRequest() {
if (!this.requestUpdateData.name) { if (!this.requestUpdateData.name) {
this.$toast.error(this.$t("request.invalid_name"), { this.$toast.error(this.$t("request.invalid_name"))
icon: "error_outline",
})
return return
} }
this.$emit("submit", this.requestUpdateData) this.$emit("submit", this.requestUpdateData)

View File

@@ -229,15 +229,11 @@ export default defineComponent({
} }
) )
.then((res) => { .then((res) => {
this.$toast.success(this.$t("export.gist_created"), { this.$toast.success(this.$t("export.gist_created"))
icon: "done",
})
window.open(res.html_url) window.open(res.html_url)
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
}, },
@@ -415,23 +411,17 @@ export default defineComponent({
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json` a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json`
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
this.$toast.success(this.$t("state.download_started"), { this.$toast.success(this.$t("state.download_started"))
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
}, 1000) }, 1000)
}, },
fileImported() { fileImported() {
this.$toast.success(this.$t("state.file_imported"), { this.$toast.success(this.$t("state.file_imported"))
icon: "folder_shared",
})
}, },
failedImport() { failedImport() {
this.$toast.error(this.$t("import.failed"), { this.$toast.error(this.$t("import.failed"))
icon: "error_outline",
})
}, },
parsePostmanCollection({ info, name, item }) { parsePostmanCollection({ info, name, item }) {
const hoppscotchCollection = { const hoppscotchCollection = {

View File

@@ -1,7 +1,7 @@
<template> <template>
<SmartModal <SmartModal
v-if="show" v-if="show"
:title="`${$t('collection.save_as')}`" :title="`${t('collection.save_as')}`"
@close="hideModal" @close="hideModal"
> >
<template #body> <template #body>
@@ -18,11 +18,11 @@
@keyup.enter="saveRequestAs" @keyup.enter="saveRequestAs"
/> />
<label for="selectLabelSaveReq"> <label for="selectLabelSaveReq">
{{ $t("request.name") }} {{ t("request.name") }}
</label> </label>
</div> </div>
<label class="p-4"> <label class="p-4">
{{ $t("collection.select_location") }} {{ t("collection.select_location") }}
</label> </label>
<CollectionsGraphql <CollectionsGraphql
v-if="mode === 'graphql'" v-if="mode === 'graphql'"
@@ -45,11 +45,11 @@
<template #footer> <template #footer>
<span> <span>
<ButtonPrimary <ButtonPrimary
:label="`${$t('action.save')}`" :label="`${t('action.save')}`"
@click.native="saveRequestAs" @click.native="saveRequestAs"
/> />
<ButtonSecondary <ButtonSecondary
:label="`${$t('action.cancel')}`" :label="`${t('action.cancel')}`"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -58,7 +58,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, useContext, watch } from "@nuxtjs/composition-api" import { reactive, ref, watch } from "@nuxtjs/composition-api"
import { isHoppRESTRequest } from "~/helpers/types/HoppRESTRequest" import { isHoppRESTRequest } from "~/helpers/types/HoppRESTRequest"
import { import {
editGraphqlRequest, editGraphqlRequest,
@@ -75,6 +75,9 @@ import {
import * as teamUtils from "~/helpers/teams/utils" import * as teamUtils from "~/helpers/teams/utils"
import { apolloClient } from "~/helpers/apollo" import { apolloClient } from "~/helpers/apollo"
import { HoppGQLRequest } from "~/helpers/types/HoppGQLRequest" import { HoppGQLRequest } from "~/helpers/types/HoppGQLRequest"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
type CollectionType = type CollectionType =
| { | {
@@ -137,12 +140,7 @@ const emit = defineEmits<{
(e: "hide-modal"): void (e: "hide-modal"): void
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
// TODO: Use a better implementation with computed ? // TODO: Use a better implementation with computed ?
// This implementation can't work across updates to mode prop (which won't happen tho) // This implementation can't work across updates to mode prop (which won't happen tho)
@@ -194,15 +192,11 @@ const hideModal = () => {
const saveRequestAs = async () => { const saveRequestAs = async () => {
if (!requestName.value) { if (!requestName.value) {
$toast.error(`${t("error.empty_req_name")}`, { toast.error(`${t("error.empty_req_name")}`)
icon: "error_outline",
})
return return
} }
if (picked.value === null) { if (picked.value === null) {
$toast.error(`${t("collection.select")}`, { toast.error(`${t("collection.select")}`)
icon: "error_outline",
})
return return
} }
@@ -283,9 +277,7 @@ const saveRequestAs = async () => {
requestSaved() requestSaved()
}) })
.catch((error) => { .catch((error) => {
$toast.error(t("profile.no_permission").toString(), { toast.error(`${t("profile.no_permission")}`)
icon: "error_outline",
})
throw new Error(error) throw new Error(error)
}) })
@@ -320,9 +312,7 @@ const saveRequestAs = async () => {
requestSaved() requestSaved()
} catch (error) { } catch (error) {
$toast.error(t("profile.no_permission").toString(), { toast.error(`${t("profile.no_permission")}`)
icon: "error_outline",
})
console.error(error) console.error(error)
} }
} else if (picked.value.pickedType === "teams-collection") { } else if (picked.value.pickedType === "teams-collection") {
@@ -352,9 +342,7 @@ const saveRequestAs = async () => {
requestSaved() requestSaved()
} catch (error) { } catch (error) {
$toast.error(t("profile.no_permission").toString(), { toast.error(`${t("profile.no_permission")}`)
icon: "error_outline",
})
console.error(error) console.error(error)
} }
} else if (picked.value.pickedType === "gql-my-request") { } else if (picked.value.pickedType === "gql-my-request") {
@@ -386,9 +374,7 @@ const saveRequestAs = async () => {
} }
const requestSaved = () => { const requestSaved = () => {
$toast.success(`${t("request.added")}`, { toast.success(`${t("request.added")}`)
icon: "post_add",
})
hideModal() hideModal()
} }

View File

@@ -49,9 +49,7 @@ export default defineComponent({
methods: { methods: {
addNewCollection() { addNewCollection() {
if (!this.name) { if (!this.name) {
this.$toast.error(`${this.$t("collection.invalid_name")}`, { this.$toast.error(`${this.$t("collection.invalid_name")}`)
icon: "error_outline",
})
return return
} }

View File

@@ -251,9 +251,7 @@ export default defineComponent({
this.$emit("select", { picked: null }) this.$emit("select", { picked: null })
} }
removeGraphqlCollection(this.collectionIndex) removeGraphqlCollection(this.collectionIndex)
this.$toast.success(`${this.$t("state.deleted")}`, { this.$toast.success(`${this.$t("state.deleted")}`)
icon: "delete",
})
}, },
dropEvent({ dataTransfer }: any) { dropEvent({ dataTransfer }: any) {
this.dragging = !this.dragging this.dragging = !this.dragging

View File

@@ -54,9 +54,7 @@ export default defineComponent({
methods: { methods: {
saveCollection() { saveCollection() {
if (!this.name) { if (!this.name) {
this.$toast.error(`${this.$t("collection.invalid_name")}`, { this.$toast.error(`${this.$t("collection.invalid_name")}`)
icon: "error_outline",
})
return return
} }
const collectionUpdated = { const collectionUpdated = {

View File

@@ -54,9 +54,7 @@ export default defineComponent({
methods: { methods: {
editFolder() { editFolder() {
if (!this.name) { if (!this.name) {
this.$toast.error(`${this.$t("collection.invalid_name")}`, { this.$toast.error(`${this.$t("collection.invalid_name")}`)
icon: "error_outline",
})
return return
} }
editGraphqlFolder(this.folderPath, { editGraphqlFolder(this.folderPath, {

View File

@@ -58,9 +58,7 @@ export default defineComponent({
methods: { methods: {
saveRequest() { saveRequest() {
if (!this.requestUpdateData.name) { if (!this.requestUpdateData.name) {
this.$toast.error(`${this.$t("collection.invalid_name")}`, { this.$toast.error(`${this.$t("collection.invalid_name")}`)
icon: "error_outline",
})
return return
} }
const requestUpdated = { const requestUpdated = {

View File

@@ -250,9 +250,7 @@ export default defineComponent({
} }
removeGraphqlFolder(this.folderPath) removeGraphqlFolder(this.folderPath)
this.$toast.success(`${this.$t("state.deleted")}`, { this.$toast.success(`${this.$t("state.deleted")}`)
icon: "delete",
})
}, },
dropEvent({ dataTransfer }: any) { dropEvent({ dataTransfer }: any) {
this.dragging = !this.dragging this.dragging = !this.dragging

View File

@@ -140,15 +140,11 @@ export default defineComponent({
} }
) )
.then((res) => { .then((res) => {
this.$toast.success(this.$t("export.gist_created"), { this.$toast.success(this.$t("export.gist_created"))
icon: "done",
})
window.open(res.html_url) window.open(res.html_url)
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
}, },
@@ -252,23 +248,17 @@ export default defineComponent({
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json` a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json`
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
this.$toast.success(this.$t("state.download_started"), { this.$toast.success(this.$t("state.download_started"))
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
}, 1000) }, 1000)
}, },
fileImported() { fileImported() {
this.$toast.success(this.$t("state.file_imported"), { this.$toast.success(this.$t("state.file_imported"))
icon: "folder_shared",
})
}, },
failedImport() { failedImport() {
this.$toast.error(this.$t("import.failed"), { this.$toast.error(this.$t("import.failed"))
icon: "error_outline",
})
}, },
parsePostmanCollection({ info, name, item }) { parsePostmanCollection({ info, name, item }) {
const hoppscotchCollection = { const hoppscotchCollection = {

View File

@@ -194,9 +194,7 @@ export default defineComponent({
} }
removeGraphqlRequest(this.folderPath, this.requestIndex) removeGraphqlRequest(this.folderPath, this.requestIndex)
this.$toast.success(`${this.$t("state.deleted")}`, { this.$toast.success(`${this.$t("state.deleted")}`)
icon: "delete",
})
}, },
}, },
}) })

View File

@@ -361,14 +361,10 @@ export default defineComponent({
this.collectionsType.selectedTeam.id this.collectionsType.selectedTeam.id
) )
.then(() => { .then(() => {
this.$toast.success(this.$t("collection.created"), { this.$toast.success(this.$t("collection.created"))
icon: "done",
})
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -377,9 +373,7 @@ export default defineComponent({
// Intented to be called by CollectionEdit modal submit event // Intented to be called by CollectionEdit modal submit event
updateEditingCollection(newName) { updateEditingCollection(newName) {
if (!newName) { if (!newName) {
this.$toast.error(this.$t("collection.invalid_name"), { this.$toast.error(this.$t("collection.invalid_name"))
icon: "error_outline",
})
return return
} }
if (this.collectionsType.type === "my-collections") { if (this.collectionsType.type === "my-collections") {
@@ -396,14 +390,10 @@ export default defineComponent({
teamUtils teamUtils
.renameCollection(this.$apollo, newName, this.editingCollection.id) .renameCollection(this.$apollo, newName, this.editingCollection.id)
.then(() => { .then(() => {
this.$toast.success(this.$t("collection.renamed"), { this.$toast.success(this.$t("collection.renamed"))
icon: "done",
})
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -420,14 +410,10 @@ export default defineComponent({
teamUtils teamUtils
.renameCollection(this.$apollo, name, this.editingFolder.id) .renameCollection(this.$apollo, name, this.editingFolder.id)
.then(() => { .then(() => {
this.$toast.success(this.$t("folder.renamed"), { this.$toast.success(this.$t("folder.renamed"))
icon: "done",
})
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -460,15 +446,11 @@ export default defineComponent({
this.editingRequestIndex this.editingRequestIndex
) )
.then(() => { .then(() => {
this.$toast.success(this.$t("request.renamed"), { this.$toast.success(this.$t("request.renamed"))
icon: "done",
})
this.$emit("update-team-collections") this.$emit("update-team-collections")
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -533,15 +515,11 @@ export default defineComponent({
}, },
}) })
.then(() => { .then(() => {
this.$toast.success(this.$t("folder.created"), { this.$toast.success(this.$t("folder.created"))
icon: "done",
})
this.$emit("update-team-collections") this.$emit("update-team-collections")
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -605,9 +583,7 @@ export default defineComponent({
} }
removeRESTCollection(collectionIndex) removeRESTCollection(collectionIndex)
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
} else if (collectionsType.type === "team-collections") { } else if (collectionsType.type === "team-collections") {
// Cancel pick if picked collection is deleted // Cancel pick if picked collection is deleted
if ( if (
@@ -633,14 +609,10 @@ export default defineComponent({
}, },
}) })
.then(() => { .then(() => {
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }
@@ -658,9 +630,7 @@ export default defineComponent({
this.$emit("select", { picked: null }) this.$emit("select", { picked: null })
} }
removeRESTRequest(folderPath, requestIndex) removeRESTRequest(folderPath, requestIndex)
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
} else if (this.collectionsType.type === "team-collections") { } else if (this.collectionsType.type === "team-collections") {
// Cancel pick if the picked item is being deleted // Cancel pick if the picked item is being deleted
if ( if (
@@ -674,14 +644,10 @@ export default defineComponent({
teamUtils teamUtils
.deleteRequest(this.$apollo, requestIndex) .deleteRequest(this.$apollo, requestIndex)
.then(() => { .then(() => {
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
} }

View File

@@ -262,9 +262,7 @@ export default defineComponent({
this.$emit("select", { picked: null }) this.$emit("select", { picked: null })
} }
removeRESTFolder(this.folderPath) removeRESTFolder(this.folderPath)
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
}, },
dropEvent({ dataTransfer }) { dropEvent({ dataTransfer }) {
this.dragging = !this.dragging this.dragging = !this.dragging

View File

@@ -253,15 +253,11 @@ export default defineComponent({
teamUtils teamUtils
.deleteCollection(this.$apollo, this.folder.id) .deleteCollection(this.$apollo, this.folder.id)
.then(() => { .then(() => {
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"))
icon: "delete",
})
this.$emit("update-team-collections") this.$emit("update-team-collections")
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
this.$emit("update-team-collections") this.$emit("update-team-collections")

View File

@@ -52,9 +52,7 @@ export default defineComponent({
methods: { methods: {
addNewEnvironment() { addNewEnvironment() {
if (!this.name) { if (!this.name) {
this.$toast.error(`${this.$t("environment.invalid_name")}`, { this.$toast.error(`${this.$t("environment.invalid_name")}`)
icon: "error_outline",
})
return return
} }
createEnvironment(this.name) createEnvironment(this.name)

View File

@@ -177,9 +177,7 @@ export default defineComponent({
clearContent() { clearContent() {
this.vars = [] this.vars = []
this.clearIcon = "check" this.clearIcon = "check"
this.$toast.success(`${this.$t("state.cleared")}`, { this.$toast.success(`${this.$t("state.cleared")}`)
icon: "clear_all",
})
setTimeout(() => (this.clearIcon = "trash-2"), 1000) setTimeout(() => (this.clearIcon = "trash-2"), 1000)
}, },
addEnvironmentVariable() { addEnvironmentVariable() {
@@ -193,9 +191,7 @@ export default defineComponent({
}, },
saveEnvironment() { saveEnvironment() {
if (!this.name) { if (!this.name) {
this.$toast.error(`${this.$t("environment.invalid_name")}`, { this.$toast.error(`${this.$t("environment.invalid_name")}`)
icon: "error_outline",
})
return return
} }

View File

@@ -102,9 +102,7 @@ export default defineComponent({
removeEnvironment() { removeEnvironment() {
if (this.environmentIndex !== "Global") if (this.environmentIndex !== "Global")
deleteEnvironment(this.environmentIndex) deleteEnvironment(this.environmentIndex)
this.$toast.success(`${this.$t("state.deleted")}`, { this.$toast.success(`${this.$t("state.deleted")}`)
icon: "delete",
})
}, },
duplicateEnvironment() { duplicateEnvironment() {
if (this.environmentIndex === "Global") { if (this.environmentIndex === "Global") {

View File

@@ -140,15 +140,11 @@ export default defineComponent({
} }
) )
.then((res) => { .then((res) => {
this.$toast.success(this.$t("export.gist_created"), { this.$toast.success(this.$t("export.gist_created"))
icon: "done",
})
window.open(res.html_url) window.open(res.html_url)
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
}, },
@@ -230,18 +226,14 @@ export default defineComponent({
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json` a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}.json`
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
this.$toast.success(this.$t("state.download_started"), { this.$toast.success(this.$t("state.download_started"))
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
}, 1000) }, 1000)
}, },
fileImported() { fileImported() {
this.$toast.success(this.$t("state.file_imported"), { this.$toast.success(this.$t("state.file_imported"))
icon: "folder_shared",
})
}, },
}, },
}) })

View File

@@ -155,9 +155,7 @@ export default defineComponent({
}, },
methods: { methods: {
showLoginSuccess() { showLoginSuccess() {
this.$toast.success(`${this.$t("auth.login_success")}`, { this.$toast.success(`${this.$t("auth.login_success")}`)
icon: "vpn_key",
})
}, },
async signInWithGoogle() { async signInWithGoogle() {
this.signingInWithGoogle = true this.signingInWithGoogle = true
@@ -174,7 +172,6 @@ export default defineComponent({
// The pending Google credential. // The pending Google credential.
const pendingCred = e.credential const pendingCred = e.credential
this.$toast.info(`${this.$t("auth.account_exists")}`, { this.$toast.info(`${this.$t("auth.account_exists")}`, {
icon: "vpn_key",
duration: 0, duration: 0,
closeOnSwipe: false, closeOnSwipe: false,
action: { action: {
@@ -190,9 +187,7 @@ export default defineComponent({
}, },
}) })
} else { } else {
this.$toast.error(`${this.$t("error.something_went_wrong")}`, { this.$toast.error(`${this.$t("error.something_went_wrong")}`)
icon: "error_outline",
})
} }
} }
@@ -218,7 +213,6 @@ export default defineComponent({
// The pending Google credential. // The pending Google credential.
const pendingCred = e.credential const pendingCred = e.credential
this.$toast.info(`${this.$t("auth.account_exists")}`, { this.$toast.info(`${this.$t("auth.account_exists")}`, {
icon: "vpn_key",
duration: 0, duration: 0,
closeOnSwipe: false, closeOnSwipe: false,
action: { action: {
@@ -234,9 +228,7 @@ export default defineComponent({
}, },
}) })
} else { } else {
this.$toast.error(`${this.$t("error.something_went_wrong")}`, { this.$toast.error(`${this.$t("error.something_went_wrong")}`)
icon: "error_outline",
})
} }
} }
@@ -256,9 +248,7 @@ export default defineComponent({
}) })
.catch((e) => { .catch((e) => {
console.error(e) console.error(e)
this.$toast.error(e.message, { this.$toast.error(e.message)
icon: "error_outline",
})
this.signingInWithEmail = false this.signingInWithEmail = false
}) })
.finally(() => { .finally(() => {

View File

@@ -40,14 +40,10 @@ export default defineComponent({
async logout() { async logout() {
try { try {
await signOutUser() await signOutUser()
this.$toast.success(`${this.$t("auth.logged_out")}`, { this.$toast.success(`${this.$t("auth.logged_out")}`)
icon: "vpn_key",
})
} catch (e) { } catch (e) {
console.error(e) console.error(e)
this.$toast.error(`${this.$t("error.something_went_wrong")}`, { this.$toast.error(`${this.$t("error.something_went_wrong")}`)
icon: "error_outline",
})
} }
}, },
}, },

View File

@@ -18,14 +18,14 @@
hover:border-dividerDark hover:border-dividerDark
focus-visible:bg-transparent focus-visible:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark
" "
:placeholder="$t('request.url')" :placeholder="`${t('request.url')}`"
:disabled="connected" :disabled="connected"
@keyup.enter="onConnectClick" @keyup.enter="onConnectClick"
/> />
<ButtonPrimary <ButtonPrimary
id="get" id="get"
name="get" name="get"
:label="!connected ? $t('action.connect') : $t('action.disconnect')" :label="!connected ? t('action.connect') : t('action.disconnect')"
class="w-32" class="w-32"
@click.native="onConnectClick" @click.native="onConnectClick"
/> />
@@ -37,9 +37,15 @@
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics" import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import { GQLConnection } from "~/helpers/GQLConnection" import { GQLConnection } from "~/helpers/GQLConnection"
import { getCurrentStrategyID } from "~/helpers/network" import { getCurrentStrategyID } from "~/helpers/network"
import { useReadonlyStream, useStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useStream,
useI18n,
} from "~/helpers/utils/composables"
import { gqlHeaders$, gqlURL$, setGQLURL } from "~/newstore/GQLSession" import { gqlHeaders$, gqlURL$, setGQLURL } from "~/newstore/GQLSession"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
conn: GQLConnection conn: GQLConnection
}>() }>()

View File

@@ -3,20 +3,20 @@
<SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10"> <SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10">
<template #actions> <template #actions>
<ButtonSecondary <ButtonSecondary
:label="`${$t('request.run')}`" :label="`${t('request.run')}`"
svg="play" svg="play"
class="rounded-none !text-accent" class="rounded-none !text-accent"
@click.native="runQuery()" @click.native="runQuery()"
/> />
<ButtonSecondary <ButtonSecondary
ref="saveRequest" ref="saveRequest"
:label="`${$t('request.save')}`" :label="`${t('request.save')}`"
class="rounded-none" class="rounded-none"
@click.native="saveRequest" @click.native="saveRequest"
/> />
</template> </template>
<SmartTab :id="'query'" :label="`${$t('tab.query')}`" :selected="true"> <SmartTab :id="'query'" :label="`${t('tab.query')}`" :selected="true">
<AppSection label="query"> <AppSection label="query">
<div <div
class=" class="
@@ -33,25 +33,25 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.query") }} {{ t("request.query") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/graphql/#queries"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.prettify')" :title="t('action.prettify')"
:svg="`${prettifyQueryIcon}`" :svg="`${prettifyQueryIcon}`"
@click.native="prettifyQuery" @click.native="prettifyQuery"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="`${copyQueryIcon}`" :svg="`${copyQueryIcon}`"
@click.native="copyQuery" @click.native="copyQuery"
/> />
@@ -61,7 +61,7 @@
</AppSection> </AppSection>
</SmartTab> </SmartTab>
<SmartTab :id="'variables'" :label="`${$t('tab.variables')}`"> <SmartTab :id="'variables'" :label="`${t('tab.variables')}`">
<AppSection label="variables"> <AppSection label="variables">
<div <div
class=" class="
@@ -77,19 +77,19 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.variables") }} {{ t("request.variables") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/graphql/#queries"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="`${copyVariablesIcon}`" :svg="`${copyVariablesIcon}`"
@click.native="copyVariables" @click.native="copyVariables"
/> />
@@ -99,7 +99,7 @@
</AppSection> </AppSection>
</SmartTab> </SmartTab>
<SmartTab :id="'headers'" :label="`${$t('tab.headers')}`"> <SmartTab :id="'headers'" :label="`${t('tab.headers')}`">
<AppSection label="headers"> <AppSection label="headers">
<div <div
class=" class="
@@ -115,32 +115,32 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("tab.headers") }} {{ t("tab.headers") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/graphql/#headers"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')" :title="t('action.clear_all')"
svg="trash-2" svg="trash-2"
@click.native="bulkMode ? clearBulkEditor() : clearContent()" @click.native="clearContent()"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')" :title="t('state.bulk_mode')"
svg="edit" svg="edit"
:class="{ '!text-accent': bulkMode }" :class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode" @click.native="bulkMode = !bulkMode"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')" :title="t('add.new')"
svg="plus" svg="plus"
:disabled="bulkMode" :disabled="bulkMode"
@click.native="addRequestHeader" @click.native="addRequestHeader"
@@ -159,7 +159,7 @@
" "
> >
<SmartAutoComplete <SmartAutoComplete
:placeholder="`${$t('count.header', { count: index + 1 })}`" :placeholder="`${t('count.header', { count: index + 1 })}`"
:source="commonHeaders" :source="commonHeaders"
:spellcheck="false" :spellcheck="false"
:value="header.key" :value="header.key"
@@ -183,7 +183,7 @@
/> />
<input <input
class="bg-transparent flex flex-1 py-2 px-4" class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="`${$t('count.value', { count: index + 1 })}`" :placeholder="`${t('count.value', { count: index + 1 })}`"
:name="`value ${String(index)}`" :name="`value ${String(index)}`"
:value="header.value" :value="header.value"
autofocus autofocus
@@ -201,9 +201,9 @@
:title=" :title="
header.hasOwnProperty('active') header.hasOwnProperty('active')
? header.active ? header.active
? $t('action.turn_off') ? t('action.turn_off')
: $t('action.turn_on') : t('action.turn_on')
: $t('action.turn_off') : t('action.turn_off')
" "
:svg=" :svg="
header.hasOwnProperty('active') header.hasOwnProperty('active')
@@ -225,7 +225,7 @@
<span> <span>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="removeRequestHeader(index)" @click.native="removeRequestHeader(index)"
@@ -253,13 +253,13 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.headers')" :alt="`${t('empty.headers')}`"
/> />
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("empty.headers") }} {{ t("empty.headers") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
:label="`${$t('add.new')}`" :label="`${t('add.new')}`"
filled filled
svg="plus" svg="plus"
class="mb-4" class="mb-4"
@@ -280,7 +280,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, useContext, watch } from "@nuxtjs/composition-api" import { onMounted, ref, watch } from "@nuxtjs/composition-api"
import clone from "lodash/clone" import clone from "lodash/clone"
import * as gql from "graphql" import * as gql from "graphql"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
@@ -288,6 +288,8 @@ import {
useNuxt, useNuxt,
useReadonlyStream, useReadonlyStream,
useStream, useStream,
useI18n,
useToast,
} from "~/helpers/utils/composables" } from "~/helpers/utils/composables"
import { import {
addGQLHeader, addGQLHeader,
@@ -314,15 +316,14 @@ import jsonLinter from "~/helpers/editor/linting/json"
import { createGQLQueryLinter } from "~/helpers/editor/linting/gqlQuery" import { createGQLQueryLinter } from "~/helpers/editor/linting/gqlQuery"
import queryCompleter from "~/helpers/editor/completion/gqlQuery" import queryCompleter from "~/helpers/editor/completion/gqlQuery"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
conn: GQLConnection conn: GQLConnection
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const nuxt = useNuxt() const nuxt = useNuxt()
const bulkMode = ref(false) const bulkMode = ref(false)
@@ -335,11 +336,9 @@ watch(bulkHeaders, () => {
value: item.substring(item.indexOf(":") + 1).trim(), value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"), active: !item.trim().startsWith("//"),
})) }))
setGQLHeaders(transformation) setGQLHeaders(transformation as GQLHeader[])
} catch (e) { } catch (e) {
$toast.error(`${t("error.something_went_wrong")}`, { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(e) console.error(e)
} }
}) })
@@ -392,6 +391,7 @@ const showSaveRequestModal = ref(false)
watch( watch(
headers, headers,
() => { () => {
if (!bulkMode.value)
if ( if (
(headers.value[headers.value.length - 1]?.key !== "" || (headers.value[headers.value.length - 1]?.key !== "" ||
headers.value[headers.value.length - 1]?.value !== "") && headers.value[headers.value.length - 1]?.value !== "") &&
@@ -427,6 +427,7 @@ onMounted(() => {
const copyQuery = () => { const copyQuery = () => {
copyToClipboard(gqlQueryString.value) copyToClipboard(gqlQueryString.value)
copyQueryIcon.value = "check" copyQueryIcon.value = "check"
toast.success(`${t("state.copied_to_clipboard")}`)
setTimeout(() => (copyQueryIcon.value = "copy"), 1000) setTimeout(() => (copyQueryIcon.value = "copy"), 1000)
} }
@@ -470,18 +471,14 @@ const runQuery = async () => {
}) })
) )
$toast.success(`${t("state.finished_in", { duration })}`, { toast.success(`${t("state.finished_in", { duration })}`)
icon: "done",
})
} catch (e: any) { } catch (e: any) {
response.value = `${e}` response.value = `${e}`
nuxt.value.$loading.finish() nuxt.value.$loading.finish()
$toast.error( toast.error(
`${t("error.something_went_wrong")}. ${t("error.check_console_details")}`, `${t("error.something_went_wrong")}. ${t("error.check_console_details")}`,
{ {}
icon: "error_outline",
}
) )
console.error(e) console.error(e)
} }
@@ -499,12 +496,11 @@ const hideRequestModal = () => {
const prettifyQuery = () => { const prettifyQuery = () => {
try { try {
gqlQueryString.value = gql.print(gql.parse(gqlQueryString.value)) gqlQueryString.value = gql.print(gql.parse(gqlQueryString.value))
} catch (e) {
$toast.error(`${t("error.gql_prettify_invalid_query")}`, {
icon: "error_outline",
})
}
prettifyQueryIcon.value = "check" prettifyQueryIcon.value = "check"
} catch (e) {
toast.error(`${t("error.gql_prettify_invalid_query")}`)
prettifyQueryIcon.value = "info"
}
setTimeout(() => (prettifyQueryIcon.value = "wand"), 1000) setTimeout(() => (prettifyQueryIcon.value = "wand"), 1000)
} }
@@ -515,6 +511,7 @@ const saveRequest = () => {
const copyVariables = () => { const copyVariables = () => {
copyToClipboard(variableString.value) copyToClipboard(variableString.value)
copyVariablesIcon.value = "check" copyVariablesIcon.value = "check"
toast.success(`${t("state.copied_to_clipboard")}`)
setTimeout(() => (copyVariablesIcon.value = "copy"), 1000) setTimeout(() => (copyVariablesIcon.value = "copy"), 1000)
} }
@@ -542,11 +539,10 @@ const removeRequestHeader = (index: number) => {
const deletedItem = headersBeforeDeletion[index] const deletedItem = headersBeforeDeletion[index]
if (deletedItem.key || deletedItem.value) { if (deletedItem.key || deletedItem.value) {
$toast.success(t("state.deleted").toString(), { toast.success(`${t("state.deleted")}`, {
icon: "delete",
action: [ action: [
{ {
text: t("action.undo").toString(), text: `${t("action.undo")}`,
onClick: (_, toastObject) => { onClick: (_, toastObject) => {
setGQLHeaders(headersBeforeDeletion as GQLHeader[]) setGQLHeaders(headersBeforeDeletion as GQLHeader[])
editBulkHeadersLine(index, deletedItem) editBulkHeadersLine(index, deletedItem)

View File

@@ -5,7 +5,7 @@
class="flex flex-col p-4 items-center justify-center" class="flex flex-col p-4 items-center justify-center"
> >
<SmartSpinner class="my-4" /> <SmartSpinner class="my-4" />
<span class="text-secondaryLight">{{ $t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
<div v-else-if="responseString"> <div v-else-if="responseString">
<div <div
@@ -22,12 +22,12 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("response.title") }} {{ t("response.title") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -35,14 +35,14 @@
<ButtonSecondary <ButtonSecondary
ref="downloadResponse" ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadResponseIcon" :svg="downloadResponseIcon"
@click.native="downloadResponse" @click.native="downloadResponse"
/> />
<ButtonSecondary <ButtonSecondary
ref="copyResponseButton" ref="copyResponseButton"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyResponseIcon" :svg="copyResponseIcon"
@click.native="copyResponse" @click.native="copyResponse"
/> />
@@ -63,10 +63,10 @@
<div class="flex space-x-2 pb-4 my-4"> <div class="flex space-x-2 pb-4 my-4">
<div class="flex flex-col space-y-4 text-right items-end"> <div class="flex flex-col space-y-4 text-right items-end">
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.general.command_menu") }} {{ t("shortcut.general.command_menu") }}
</span> </span>
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.general.help_menu") }} {{ t("shortcut.general.help_menu") }}
</span> </span>
</div> </div>
<div class="flex flex-col space-y-4"> <div class="flex flex-col space-y-4">
@@ -79,8 +79,8 @@
</div> </div>
</div> </div>
<ButtonSecondary <ButtonSecondary
:label="`${$t('app.documentation')}`" :label="`${t('app.documentation')}`"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/features/response"
svg="external-link" svg="external-link"
blank blank
outline outline
@@ -91,17 +91,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, useContext } from "@nuxtjs/composition-api" import { reactive, ref } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useReadonlyStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useI18n,
useToast,
} from "~/helpers/utils/composables"
import { gqlResponse$ } from "~/newstore/GQLSession" import { gqlResponse$ } from "~/newstore/GQLSession"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
const responseString = useReadonlyStream(gqlResponse$, "") const responseString = useReadonlyStream(gqlResponse$, "")
@@ -128,6 +130,7 @@ const copyResponseIcon = ref("copy")
const copyResponse = () => { const copyResponse = () => {
copyToClipboard(responseString.value!) copyToClipboard(responseString.value!)
copyResponseIcon.value = "check" copyResponseIcon.value = "check"
toast.success(`${t("state.copied_to_clipboard")}`)
setTimeout(() => (copyResponseIcon.value = "copy"), 1000) setTimeout(() => (copyResponseIcon.value = "copy"), 1000)
} }
@@ -141,9 +144,7 @@ const downloadResponse = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadResponseIcon.value = "check" downloadResponseIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)

View File

@@ -3,7 +3,7 @@
<SmartTab <SmartTab
:id="'history'" :id="'history'"
icon="clock" icon="clock"
:label="`${$t('tab.history')}`" :label="`${t('tab.history')}`"
:selected="true" :selected="true"
> >
<History <History
@@ -16,7 +16,7 @@
<SmartTab <SmartTab
:id="'collections'" :id="'collections'"
icon="folder" icon="folder"
:label="`${$t('tab.collections')}`" :label="`${t('tab.collections')}`"
> >
<CollectionsGraphql /> <CollectionsGraphql />
</SmartTab> </SmartTab>
@@ -24,7 +24,7 @@
<SmartTab <SmartTab
:id="'docs'" :id="'docs'"
icon="book-open" icon="book-open"
:label="`${$t('tab.documentation')}`" :label="`${t('tab.documentation')}`"
> >
<AppSection label="docs"> <AppSection label="docs">
<div <div
@@ -53,10 +53,10 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.documentation')" :alt="`${t('empty.documentation')}`"
/> />
<span class="text-center mb-4"> <span class="text-center mb-4">
{{ $t("empty.documentation") }} {{ t("empty.documentation") }}
</span> </span>
</div> </div>
<div v-else> <div v-else>
@@ -65,7 +65,7 @@
v-model="graphqlFieldsFilterText" v-model="graphqlFieldsFilterText"
type="search" type="search"
autocomplete="off" autocomplete="off"
:placeholder="`${$t('action.search')}`" :placeholder="`${t('action.search')}`"
class="bg-transparent flex w-full p-4 py-2" class="bg-transparent flex w-full p-4 py-2"
/> />
<div class="flex"> <div class="flex">
@@ -73,7 +73,7 @@
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/quickstart/graphql" to="https://docs.hoppscotch.io/quickstart/graphql"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
</div> </div>
@@ -86,7 +86,7 @@
<SmartTab <SmartTab
v-if="queryFields.length > 0" v-if="queryFields.length > 0"
:id="'queries'" :id="'queries'"
:label="`${$t('tab.queries')}`" :label="`${t('tab.queries')}`"
:selected="true" :selected="true"
class="divide-y divide-dividerLight" class="divide-y divide-dividerLight"
> >
@@ -101,7 +101,7 @@
<SmartTab <SmartTab
v-if="mutationFields.length > 0" v-if="mutationFields.length > 0"
:id="'mutations'" :id="'mutations'"
:label="`${$t('graphql.mutations')}`" :label="`${t('graphql.mutations')}`"
class="divide-y divide-dividerLight" class="divide-y divide-dividerLight"
> >
<GraphqlField <GraphqlField
@@ -115,7 +115,7 @@
<SmartTab <SmartTab
v-if="subscriptionFields.length > 0" v-if="subscriptionFields.length > 0"
:id="'subscriptions'" :id="'subscriptions'"
:label="`${$t('graphql.subscriptions')}`" :label="`${t('graphql.subscriptions')}`"
class="divide-y divide-dividerLight" class="divide-y divide-dividerLight"
> >
<GraphqlField <GraphqlField
@@ -130,7 +130,7 @@
v-if="graphqlTypes.length > 0" v-if="graphqlTypes.length > 0"
:id="'types'" :id="'types'"
ref="typesTab" ref="typesTab"
:label="`${$t('tab.types')}`" :label="`${t('tab.types')}`"
class="divide-y divide-dividerLight" class="divide-y divide-dividerLight"
> >
<GraphqlType <GraphqlType
@@ -149,7 +149,7 @@
</AppSection> </AppSection>
</SmartTab> </SmartTab>
<SmartTab :id="'schema'" icon="box" :label="`${$t('tab.schema')}`"> <SmartTab :id="'schema'" icon="box" :label="`${t('tab.schema')}`">
<AppSection ref="schema" label="schema"> <AppSection ref="schema" label="schema">
<div <div
v-if="schemaString" v-if="schemaString"
@@ -166,19 +166,19 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("graphql.schema") }} {{ t("graphql.schema") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/quickstart/graphql" to="https://docs.hoppscotch.io/quickstart/graphql"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -186,14 +186,14 @@
<ButtonSecondary <ButtonSecondary
ref="downloadSchema" ref="downloadSchema"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadSchemaIcon" :svg="downloadSchemaIcon"
@click.native="downloadSchema" @click.native="downloadSchema"
/> />
<ButtonSecondary <ButtonSecondary
ref="copySchemaCode" ref="copySchemaCode"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copySchemaIcon" :svg="copySchemaIcon"
@click.native="copySchema" @click.native="copySchema"
/> />
@@ -221,10 +221,10 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.schema')" :alt="`${t('empty.schema')}`"
/> />
<span class="text-center mb-4"> <span class="text-center mb-4">
{{ $t("empty.schema") }} {{ t("empty.schema") }}
</span> </span>
</div> </div>
</AppSection> </AppSection>
@@ -233,20 +233,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import { computed, nextTick, reactive, ref } from "@nuxtjs/composition-api"
computed,
nextTick,
reactive,
ref,
useContext,
} from "@nuxtjs/composition-api"
import { GraphQLField, GraphQLType } from "graphql" import { GraphQLField, GraphQLType } from "graphql"
import { map } from "rxjs/operators" import { map } from "rxjs/operators"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { GQLConnection } from "~/helpers/GQLConnection" import { GQLConnection } from "~/helpers/GQLConnection"
import { GQLHeader } from "~/helpers/types/HoppGQLRequest" import { GQLHeader } from "~/helpers/types/HoppGQLRequest"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useReadonlyStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useI18n,
useToast,
} from "~/helpers/utils/composables"
import { import {
setGQLHeaders, setGQLHeaders,
setGQLQuery, setGQLQuery,
@@ -255,6 +253,8 @@ import {
setGQLVariables, setGQLVariables,
} from "~/newstore/GQLSession" } from "~/newstore/GQLSession"
const t = useI18n()
function isTextFoundInGraphqlFieldObject( function isTextFoundInGraphqlFieldObject(
text: string, text: string,
field: GraphQLField<any, any> field: GraphQLField<any, any>
@@ -321,11 +321,7 @@ const props = defineProps<{
conn: GQLConnection conn: GQLConnection
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const queryFields = useReadonlyStream( const queryFields = useReadonlyStream(
props.conn.queryFields$.pipe(map((x) => x ?? [])), props.conn.queryFields$.pipe(map((x) => x ?? [])),
@@ -449,9 +445,7 @@ const downloadSchema = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadSchemaIcon.value = "check" downloadSchemaIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)

View File

@@ -140,9 +140,7 @@ export default defineComponent({
clearHistory() { clearHistory() {
if (this.page === "rest") clearRESTHistory() if (this.page === "rest") clearRESTHistory()
else clearGraphqlHistory() else clearGraphqlHistory()
this.$toast.success(`${this.$t("state.history_deleted")}`, { this.$toast.success(`${this.$t("state.history_deleted")}`)
icon: "delete",
})
}, },
useHistory(entry: any) { useHistory(entry: any) {
if (this.page === "rest") setRESTRequest(entry.request) if (this.page === "rest") setRESTRequest(entry.request)
@@ -150,9 +148,7 @@ export default defineComponent({
deleteHistory(entry: any) { deleteHistory(entry: any) {
if (this.page === "rest") deleteRESTHistoryEntry(entry) if (this.page === "rest") deleteRESTHistoryEntry(entry)
else deleteGraphqlHistoryEntry(entry) else deleteGraphqlHistoryEntry(entry)
this.$toast.success(`${this.$t("state.deleted")}`, { this.$toast.success(`${this.$t("state.deleted")}`)
icon: "delete",
})
}, },
toggleStar(entry: any) { toggleStar(entry: any) {
if (this.page === "rest") toggleRESTHistoryEntryStar(entry) if (this.page === "rest") toggleRESTHistoryEntryStar(entry)

View File

@@ -49,13 +49,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { import { computed, defineComponent, PropType } from "@nuxtjs/composition-api"
computed,
defineComponent,
PropType,
useContext,
} from "@nuxtjs/composition-api"
import findStatusGroup from "~/helpers/findStatusGroup" import findStatusGroup from "~/helpers/findStatusGroup"
import { useI18n } from "~/helpers/utils/composables"
import { RESTHistoryEntry } from "~/newstore/history" import { RESTHistoryEntry } from "~/newstore/history"
export default defineComponent({ export default defineComponent({
@@ -64,10 +60,7 @@ export default defineComponent({
showMore: Boolean, showMore: Boolean,
}, },
setup(props) { setup(props) {
const { const t = useI18n()
app: { i18n },
} = useContext()
const $t = i18n.t.bind(i18n)
const duration = computed(() => { const duration = computed(() => {
if (props.entry.responseMeta.duration) { if (props.entry.responseMeta.duration) {
@@ -75,9 +68,9 @@ export default defineComponent({
if (!responseDuration) return "" if (!responseDuration) return ""
return responseDuration > 0 return responseDuration > 0
? `${$t("request.duration")}: ${responseDuration}ms` ? `${t("request.duration")}: ${responseDuration}ms`
: $t("error.no_duration") : t("error.no_duration")
} else return $t("error.no_duration") } else return t("error.no_duration")
}) })
const entryStatus = computed(() => { const entryStatus = computed(() => {

View File

@@ -107,7 +107,7 @@
<ButtonSecondary <ButtonSecondary
outline outline
:label="$t('app.documentation')" :label="$t('app.documentation')"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/features/authorization"
blank blank
svg="external-link" svg="external-link"
reverse reverse
@@ -151,7 +151,7 @@
<SmartAnchor <SmartAnchor
class="link" class="link"
:label="`${$t('authorization.learn')} \xA0 →`" :label="`${$t('authorization.learn')} \xA0 →`"
to="https://docs.hoppscotch.io/" to="https://docs.hoppscotch.io/features/authorization"
blank blank
/> />
</div> </div>
@@ -187,7 +187,7 @@
<SmartAnchor <SmartAnchor
class="link" class="link"
:label="`${$t('authorization.learn')} \xA0 →`" :label="`${$t('authorization.learn')} \xA0 →`"
to="https://docs.hoppscotch.io/" to="https://docs.hoppscotch.io/features/authorization"
blank blank
/> />
</div> </div>
@@ -227,7 +227,7 @@
<SmartAnchor <SmartAnchor
class="link" class="link"
:label="`${$t('authorization.learn')} \xA0 →`" :label="`${$t('authorization.learn')} \xA0 →`"
to="https://docs.hoppscotch.io/" to="https://docs.hoppscotch.io/features/authorization"
blank blank
/> />
</div> </div>

View File

@@ -77,7 +77,7 @@
<ButtonSecondary <ButtonSecondary
outline outline
:label="`${$t('app.documentation')}`" :label="`${$t('app.documentation')}`"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/features/body"
blank blank
svg="external-link" svg="external-link"
reverse reverse

View File

@@ -7,7 +7,7 @@
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col px-2">
<label for="requestType" class="px-4 pb-4"> <label for="requestType" class="px-4 pb-4">
{{ $t("request.choose_language") }} {{ t("request.choose_language") }}
</label> </label>
<tippy ref="options" interactive trigger="click" theme="popover" arrow> <tippy ref="options" interactive trigger="click" theme="popover" arrow>
<template #trigger> <template #trigger>
@@ -62,13 +62,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, useContext, watch } from "@nuxtjs/composition-api" import { computed, ref, watch } from "@nuxtjs/composition-api"
import { codegens, generateCodegenContext } from "~/helpers/codegen/codegen" import { codegens, generateCodegenContext } from "~/helpers/codegen/codegen"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { getEffectiveRESTRequest } from "~/helpers/utils/EffectiveURL" import { getEffectiveRESTRequest } from "~/helpers/utils/EffectiveURL"
import { getCurrentEnvironment } from "~/newstore/environments" import { getCurrentEnvironment } from "~/newstore/environments"
import { getRESTRequest } from "~/newstore/RESTSession" import { getRESTRequest } from "~/newstore/RESTSession"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
show: boolean show: boolean
@@ -78,11 +81,7 @@ const emit = defineEmits<{
(e: "hide-modal"): void (e: "hide-modal"): void
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const options = ref<any | null>(null) const options = ref<any | null>(null)
@@ -126,9 +125,7 @@ const hideModal = () => emit("hide-modal")
const copyRequestCode = () => { const copyRequestCode = () => {
copyToClipboard(requestCode.value) copyToClipboard(requestCode.value)
copyIcon.value = "check" copyIcon.value = "check"
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste",
})
setTimeout(() => (copyIcon.value = "copy"), 1000) setTimeout(() => (copyIcon.value = "copy"), 1000)
} }
</script> </script>

View File

@@ -14,32 +14,32 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.header_list") }} {{ t("request.header_list") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/headers" to="https://docs.hoppscotch.io/features/headers"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')" :title="t('action.clear_all')"
svg="trash-2" svg="trash-2"
@click.native="bulkMode ? clearBulkEditor() : clearContent()" @click.native="clearContent()"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')" :title="t('state.bulk_mode')"
svg="edit" svg="edit"
:class="{ '!text-accent': bulkMode }" :class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode" @click.native="bulkMode = !bulkMode"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')" :title="t('add.new')"
svg="plus" svg="plus"
:disabled="bulkMode" :disabled="bulkMode"
@click.native="addHeader" @click.native="addHeader"
@@ -54,7 +54,7 @@
class="divide-x divide-dividerLight border-b border-dividerLight flex" class="divide-x divide-dividerLight border-b border-dividerLight flex"
> >
<SmartAutoComplete <SmartAutoComplete
:placeholder="`${$t('count.header', { count: index + 1 })}`" :placeholder="`${t('count.header', { count: index + 1 })}`"
:source="commonHeaders" :source="commonHeaders"
:spellcheck="false" :spellcheck="false"
:value="header.key" :value="header.key"
@@ -78,7 +78,7 @@
/> />
<SmartEnvInput <SmartEnvInput
v-model="header.value" v-model="header.value"
:placeholder="`${$t('count.value', { count: index + 1 })}`" :placeholder="`${t('count.value', { count: index + 1 })}`"
styles=" styles="
bg-transparent bg-transparent
flex flex
@@ -100,9 +100,9 @@
:title=" :title="
header.hasOwnProperty('active') header.hasOwnProperty('active')
? header.active ? header.active
? $t('action.turn_off') ? t('action.turn_off')
: $t('action.turn_on') : t('action.turn_on')
: $t('action.turn_off') : t('action.turn_off')
" "
:svg=" :svg="
header.hasOwnProperty('active') header.hasOwnProperty('active')
@@ -126,7 +126,7 @@
<span> <span>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="deleteHeader(index)" @click.native="deleteHeader(index)"
@@ -154,14 +154,14 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.headers')" :alt="`${t('empty.headers')}`"
/> />
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("empty.headers") }} {{ t("empty.headers") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
filled filled
:label="`${$t('add.new')}`" :label="`${t('add.new')}`"
svg="plus" svg="plus"
class="mb-4" class="mb-4"
@click.native="addHeader" @click.native="addHeader"
@@ -172,7 +172,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUpdate, ref, useContext, watch } from "@nuxtjs/composition-api" import { onBeforeUpdate, ref, watch } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { import {
addRESTHeader, addRESTHeader,
@@ -183,14 +183,16 @@ import {
updateRESTHeader, updateRESTHeader,
} from "~/newstore/RESTSession" } from "~/newstore/RESTSession"
import { commonHeaders } from "~/helpers/headers" import { commonHeaders } from "~/helpers/headers"
import { useReadonlyStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useI18n,
useToast,
} from "~/helpers/utils/composables"
import { HoppRESTHeader } from "~/helpers/types/HoppRESTRequest" import { HoppRESTHeader } from "~/helpers/types/HoppRESTRequest"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
const bulkMode = ref(false) const bulkMode = ref(false)
const bulkHeaders = ref("") const bulkHeaders = ref("")
@@ -212,11 +214,9 @@ watch(bulkHeaders, () => {
value: item.substring(item.indexOf(":") + 1).trim(), value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"), active: !item.trim().startsWith("//"),
})) }))
setRESTHeaders(transformation) setRESTHeaders(transformation as HoppRESTHeader[])
} catch (e) { } catch (e) {
$toast.error(`${t("error.something_went_wrong")}`, { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(e) console.error(e)
} }
}) })
@@ -226,6 +226,7 @@ const headers$ = useReadonlyStream(restHeaders$, [])
watch( watch(
headers$, headers$,
(newValue) => { (newValue) => {
if (!bulkMode.value)
if ( if (
(newValue[newValue.length - 1]?.key !== "" || (newValue[newValue.length - 1]?.key !== "" ||
newValue[newValue.length - 1]?.value !== "") && newValue[newValue.length - 1]?.value !== "") &&
@@ -277,11 +278,10 @@ const deleteHeader = (index: number) => {
const deletedItem = headersBeforeDeletion[index] const deletedItem = headersBeforeDeletion[index]
if (deletedItem.key || deletedItem.value) { if (deletedItem.key || deletedItem.value) {
$toast.success(t("state.deleted").toString(), { toast.success(`${t("state.deleted")}`, {
icon: "delete",
action: [ action: [
{ {
text: t("action.undo").toString(), text: `${t("action.undo")}`,
onClick: (_, toastObject) => { onClick: (_, toastObject) => {
setRESTHeaders(headersBeforeDeletion as HoppRESTHeader[]) setRESTHeaders(headersBeforeDeletion as HoppRESTHeader[])
editBulkHeadersLine(index, deletedItem) editBulkHeadersLine(index, deletedItem)

View File

@@ -1,5 +1,5 @@
<template> <template>
<SmartModal v-if="show" :title="`${$t('import.curl')}`" @close="hideModal"> <SmartModal v-if="show" :title="`${t('import.curl')}`" @close="hideModal">
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col px-2">
<div ref="curlEditor" class="border border-dividerLight rounded"></div> <div ref="curlEditor" class="border border-dividerLight rounded"></div>
@@ -8,11 +8,11 @@
<template #footer> <template #footer>
<span class="flex"> <span class="flex">
<ButtonPrimary <ButtonPrimary
:label="`${$t('import.title')}`" :label="`${t('import.title')}`"
@click.native="handleImport" @click.native="handleImport"
/> />
<ButtonSecondary <ButtonSecondary
:label="`${$t('action.cancel')}`" :label="`${t('action.cancel')}`"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -21,7 +21,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, useContext } from "@nuxtjs/composition-api" import { ref } from "@nuxtjs/composition-api"
import parseCurlCommand from "~/helpers/curlparser" import parseCurlCommand from "~/helpers/curlparser"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { import {
@@ -30,12 +30,11 @@ import {
makeRESTRequest, makeRESTRequest,
} from "~/helpers/types/HoppRESTRequest" } from "~/helpers/types/HoppRESTRequest"
import { setRESTRequest } from "~/newstore/RESTSession" import { setRESTRequest } from "~/newstore/RESTSession"
import { useI18n, useToast } from "~/helpers/utils/composables"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
const curl = ref("") const curl = ref("")
@@ -123,9 +122,7 @@ const handleImport = () => {
) )
} catch (e) { } catch (e) {
console.error(e) console.error(e)
$toast.error(`${t("error.curl_invalid_format")}`, { toast.error(`${t("error.curl_invalid_format")}`)
icon: "error_outline",
})
} }
hideModal() hideModal()
} }

View File

@@ -48,7 +48,7 @@
<div class="p-2"> <div class="p-2">
<ButtonSecondary <ButtonSecondary
filled filled
:label="`${$t('authorization.generate_token')}`" :label="`${t('authorization.generate_token')}`"
@click.native="handleAccessTokenRequest()" @click.native="handleAccessTokenRequest()"
/> />
</div> </div>
@@ -56,19 +56,21 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Ref, useContext } from "@nuxtjs/composition-api" import { Ref } from "@nuxtjs/composition-api"
import { pluckRef, useStream } from "~/helpers/utils/composables" import {
pluckRef,
useI18n,
useStream,
useToast,
} from "~/helpers/utils/composables"
import { HoppRESTAuthOAuth2 } from "~/helpers/types/HoppRESTAuth" import { HoppRESTAuthOAuth2 } from "~/helpers/types/HoppRESTAuth"
import { restAuth$, setRESTAuth } from "~/newstore/RESTSession" import { restAuth$, setRESTAuth } from "~/newstore/RESTSession"
import { tokenRequest } from "~/helpers/oauth" import { tokenRequest } from "~/helpers/oauth"
export default { export default {
setup() { setup() {
const { const t = useI18n()
$toast, const toast = useToast()
app: { i18n },
} = useContext()
const $t = i18n.t.bind(i18n)
const auth = useStream( const auth = useStream(
restAuth$, restAuth$,
@@ -97,9 +99,7 @@ export default {
oidcDiscoveryURL.value === "" && oidcDiscoveryURL.value === "" &&
(authURL.value === "" || accessTokenURL.value === "") (authURL.value === "" || accessTokenURL.value === "")
) { ) {
$toast.error(`${$t("complete_config_urls")}`, { toast.error(`${t("complete_config_urls")}`)
icon: "error",
})
return return
} }
try { try {
@@ -113,9 +113,7 @@ export default {
} }
await tokenRequest(tokenReqParams) await tokenRequest(tokenReqParams)
} catch (e) { } catch (e) {
$toast.error(`${e}`, { toast.error(`${e}`)
icon: "code",
})
} }
} }

View File

@@ -14,32 +14,32 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.parameter_list") }} {{ t("request.parameter_list") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/parameters" to="https://docs.hoppscotch.io/features/parameters"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')" :title="t('action.clear_all')"
svg="trash-2" svg="trash-2"
@click.native="bulkMode ? clearBulkEditor() : clearContent()" @click.native="clearContent()"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')" :title="t('state.bulk_mode')"
svg="edit" svg="edit"
:class="{ '!text-accent': bulkMode }" :class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode" @click.native="bulkMode = !bulkMode"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')" :title="t('add.new')"
svg="plus" svg="plus"
:disabled="bulkMode" :disabled="bulkMode"
@click.native="addParam" @click.native="addParam"
@@ -55,7 +55,7 @@
> >
<SmartEnvInput <SmartEnvInput
v-model="param.key" v-model="param.key"
:placeholder="`${$t('count.parameter', { count: index + 1 })}`" :placeholder="`${t('count.parameter', { count: index + 1 })}`"
styles=" styles="
bg-transparent bg-transparent
flex flex
@@ -73,7 +73,7 @@
/> />
<SmartEnvInput <SmartEnvInput
v-model="param.value" v-model="param.value"
:placeholder="`${$t('count.value', { count: index + 1 })}`" :placeholder="`${t('count.value', { count: index + 1 })}`"
styles=" styles="
bg-transparent bg-transparent
flex flex
@@ -95,9 +95,9 @@
:title=" :title="
param.hasOwnProperty('active') param.hasOwnProperty('active')
? param.active ? param.active
? $t('action.turn_off') ? t('action.turn_off')
: $t('action.turn_on') : t('action.turn_on')
: $t('action.turn_off') : t('action.turn_off')
" "
:svg=" :svg="
param.hasOwnProperty('active') param.hasOwnProperty('active')
@@ -119,7 +119,7 @@
<span> <span>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="deleteParam(index)" @click.native="deleteParam(index)"
@@ -147,13 +147,13 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.parameters')" :alt="`${t('empty.parameters')}`"
/> />
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("empty.parameters") }} {{ t("empty.parameters") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
:label="`${$t('add.new')}`" :label="`${t('add.new')}`"
svg="plus" svg="plus"
filled filled
class="mb-4" class="mb-4"
@@ -165,10 +165,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, useContext, watch, onBeforeUpdate } from "@nuxtjs/composition-api" import { ref, watch, onBeforeUpdate } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { HoppRESTParam } from "~/helpers/types/HoppRESTRequest" import { HoppRESTParam } from "~/helpers/types/HoppRESTRequest"
import { useReadonlyStream } from "~/helpers/utils/composables" import {
useReadonlyStream,
useI18n,
useToast,
} from "~/helpers/utils/composables"
import { import {
restParams$, restParams$,
addRESTParam, addRESTParam,
@@ -178,11 +182,9 @@ import {
setRESTParams, setRESTParams,
} from "~/newstore/RESTSession" } from "~/newstore/RESTSession"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
const bulkMode = ref(false) const bulkMode = ref(false)
const bulkParams = ref("") const bulkParams = ref("")
@@ -194,11 +196,9 @@ watch(bulkParams, () => {
value: item.substring(item.indexOf(":") + 1).trim(), value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"), active: !item.trim().startsWith("//"),
})) }))
setRESTParams(transformation) setRESTParams(transformation as HoppRESTParam[])
} catch (e) { } catch (e) {
$toast.error(`${t("error.something_went_wrong")}`, { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(e) console.error(e)
} }
}) })
@@ -219,6 +219,7 @@ const params$ = useReadonlyStream(restParams$, [])
watch( watch(
params$, params$,
(newValue) => { (newValue) => {
if (!bulkMode.value)
if ( if (
(newValue[newValue.length - 1]?.key !== "" || (newValue[newValue.length - 1]?.key !== "" ||
newValue[newValue.length - 1]?.value !== "") && newValue[newValue.length - 1]?.value !== "") &&
@@ -270,11 +271,10 @@ const deleteParam = (index: number) => {
const deletedItem = parametersBeforeDeletion[index] const deletedItem = parametersBeforeDeletion[index]
if (deletedItem.key || deletedItem.value) { if (deletedItem.key || deletedItem.value) {
$toast.success(t("state.deleted").toString(), { toast.success(`${t("state.deleted")}`, {
icon: "delete",
action: [ action: [
{ {
text: t("action.undo").toString(), text: `${t("action.undo")}`,
onClick: (_, toastObject) => { onClick: (_, toastObject) => {
setRESTParams(parametersBeforeDeletion as HoppRESTParam[]) setRESTParams(parametersBeforeDeletion as HoppRESTParam[])
editBulkParamsLine(index, deletedItem) editBulkParamsLine(index, deletedItem)

View File

@@ -1,5 +1,5 @@
<template> <template>
<AppSection id="script" :label="`${$t('preRequest.script')}`"> <AppSection id="script" :label="`${t('preRequest.script')}`">
<div <div
class=" class="
bg-primary bg-primary
@@ -14,26 +14,26 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("preRequest.javascript_code") }} {{ t("preRequest.javascript_code") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/pre-request-script" to="https://docs.hoppscotch.io/features/pre-request-script"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear')" :title="t('action.clear')"
svg="trash-2" svg="trash-2"
@click.native="clearContent" @click.native="clearContent"
/> />
@@ -57,15 +57,15 @@
" "
> >
<div class="text-secondaryLight pb-2"> <div class="text-secondaryLight pb-2">
{{ $t("helpers.pre_request_script") }} {{ t("helpers.pre_request_script") }}
</div> </div>
<SmartAnchor <SmartAnchor
:label="`${$t('preRequest.learn')}`" :label="`${t('preRequest.learn')}`"
to="https://docs.hoppscotch.io/features/pre-request-script" to="https://docs.hoppscotch.io/features/pre-request-script"
blank blank
/> />
<h4 class="font-bold text-secondaryLight pt-6"> <h4 class="font-bold text-secondaryLight pt-6">
{{ $t("preRequest.snippets") }} {{ t("preRequest.snippets") }}
</h4> </h4>
<div class="flex flex-col pt-4"> <div class="flex flex-col pt-4">
<TabSecondary <TabSecondary
@@ -82,17 +82,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, useContext } from "@nuxtjs/composition-api" import { reactive, ref } from "@nuxtjs/composition-api"
import { usePreRequestScript } from "~/newstore/RESTSession" import { usePreRequestScript } from "~/newstore/RESTSession"
import snippets from "~/helpers/preRequestScriptSnippets" import snippets from "~/helpers/preRequestScriptSnippets"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import linter from "~/helpers/editor/linting/preRequest" import linter from "~/helpers/editor/linting/preRequest"
import completer from "~/helpers/editor/completion/preRequest" import completer from "~/helpers/editor/completion/preRequest"
import { useI18n } from "~/helpers/utils/composables"
const { const t = useI18n()
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const preRequestScript = usePreRequestScript() const preRequestScript = usePreRequestScript()

View File

@@ -14,26 +14,26 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.raw_body") }} {{ t("request.raw_body") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/body" to="https://docs.hoppscotch.io/features/body"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear')" :title="t('action.clear')"
svg="trash-2" svg="trash-2"
@click.native="clearContent" @click.native="clearContent"
/> />
@@ -41,14 +41,14 @@
v-if="contentType && contentType.endsWith('json')" v-if="contentType && contentType.endsWith('json')"
ref="prettifyRequest" ref="prettifyRequest"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.prettify')" :title="t('action.prettify')"
:svg="prettifyIcon" :svg="prettifyIcon"
@click.native="prettifyRequestBody" @click.native="prettifyRequestBody"
/> />
<label for="payload"> <label for="payload">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('import.json')" :title="t('import.json')"
svg="file-plus" svg="file-plus"
@click.native="$refs.payload.click()" @click.native="$refs.payload.click()"
/> />
@@ -67,21 +67,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive, ref, useContext } from "@nuxtjs/composition-api" import { computed, reactive, ref } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { getEditorLangForMimeType } from "~/helpers/editorutils" import { getEditorLangForMimeType } from "~/helpers/editorutils"
import { pluckRef } from "~/helpers/utils/composables" import { pluckRef, useI18n, useToast } from "~/helpers/utils/composables"
import { useRESTRequestBody } from "~/newstore/RESTSession" import { useRESTRequestBody } from "~/newstore/RESTSession"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
contentType: string contentType: string
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const rawParamsBody = pluckRef(useRESTRequestBody(), "body") const rawParamsBody = pluckRef(useRESTRequestBody(), "body")
const prettifyIcon = ref("wand") const prettifyIcon = ref("wand")
@@ -118,13 +116,9 @@ const uploadPayload = (e: InputEvent) => {
rawParamsBody.value = target?.result rawParamsBody.value = target?.result
} }
reader.readAsText(file) reader.readAsText(file)
$toast.success(`${t("state.file_imported")}`, { toast.success(`${t("state.file_imported")}`)
icon: "attach_file",
})
} else { } else {
$toast.error(`${t("action.choose_file")}`, { toast.error(`${t("action.choose_file")}`)
icon: "attach_file",
})
} }
} }
const prettifyRequestBody = () => { const prettifyRequestBody = () => {
@@ -135,9 +129,7 @@ const prettifyRequestBody = () => {
setTimeout(() => (prettifyIcon.value = "wand"), 1000) setTimeout(() => (prettifyIcon.value = "wand"), 1000)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
$toast.error(`${t("error.json_prettify_invalid_body")}`, { toast.error(`${t("error.json_prettify_invalid_body")}`)
icon: "error_outline",
})
} }
} }
</script> </script>

View File

@@ -43,7 +43,7 @@
" "
:value="newMethod" :value="newMethod"
:readonly="!isCustomMethod" :readonly="!isCustomMethod"
:placeholder="`${$t('request.method')}`" :placeholder="`${t('request.method')}`"
@input="onSelectMethod($event.target.value)" @input="onSelectMethod($event.target.value)"
/> />
</span> </span>
@@ -60,7 +60,7 @@
<div class="flex flex-1"> <div class="flex flex-1">
<SmartEnvInput <SmartEnvInput
v-model="newEndpoint" v-model="newEndpoint"
:placeholder="`${$t('request.url')}`" :placeholder="`${t('request.url')}`"
styles=" styles="
bg-primaryLight bg-primaryLight
border border-divider border border-divider
@@ -83,7 +83,7 @@
<ButtonPrimary <ButtonPrimary
id="send" id="send"
class="rounded-r-none flex-1 min-w-20" class="rounded-r-none flex-1 min-w-20"
:label="`${!loading ? $t('action.send') : $t('action.cancel')}`" :label="`${!loading ? t('action.send') : t('action.cancel')}`"
@click.native="!loading ? newSendRequest() : cancelRequest()" @click.native="!loading ? newSendRequest() : cancelRequest()"
/> />
<span class="flex"> <span class="flex">
@@ -98,7 +98,7 @@
<ButtonPrimary class="rounded-l-none" filled svg="chevron-down" /> <ButtonPrimary class="rounded-l-none" filled svg="chevron-down" />
</template> </template>
<SmartItem <SmartItem
:label="`${$t('import.curl')}`" :label="`${t('import.curl')}`"
svg="file-code" svg="file-code"
@click.native=" @click.native="
() => { () => {
@@ -108,7 +108,7 @@
" "
/> />
<SmartItem <SmartItem
:label="`${$t('show.code')}`" :label="`${t('show.code')}`"
svg="code-2" svg="code-2"
@click.native=" @click.native="
() => { () => {
@@ -119,7 +119,7 @@
/> />
<SmartItem <SmartItem
ref="clearAll" ref="clearAll"
:label="`${$t('action.clear_all')}`" :label="`${t('action.clear_all')}`"
svg="rotate-ccw" svg="rotate-ccw"
@click.native=" @click.native="
() => { () => {
@@ -134,7 +134,7 @@
class="rounded rounded-r-none ml-2" class="rounded rounded-r-none ml-2"
:label=" :label="
windowInnerWidth.x.value >= 768 && COLUMN_LAYOUT windowInnerWidth.x.value >= 768 && COLUMN_LAYOUT
? `${$t('request.save')}` ? `${t('request.save')}`
: '' : ''
" "
filled filled
@@ -159,7 +159,7 @@
<input <input
id="request-name" id="request-name"
v-model="requestName" v-model="requestName"
:placeholder="`${$t('request.name')}`" :placeholder="`${t('request.name')}`"
name="request-name" name="request-name"
type="text" type="text"
autocomplete="off" autocomplete="off"
@@ -179,7 +179,7 @@
/> />
<SmartItem <SmartItem
ref="saveRequest" ref="saveRequest"
:label="`${$t('request.save_as')}`" :label="`${t('request.save_as')}`"
svg="folder-plus" svg="folder-plus"
@click.native=" @click.native="
() => { () => {
@@ -208,7 +208,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, useContext, watch } from "@nuxtjs/composition-api" import { computed, ref, watch } from "@nuxtjs/composition-api"
import { isRight } from "fp-ts/lib/Either" import { isRight } from "fp-ts/lib/Either"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import { import {
@@ -228,6 +228,8 @@ import {
useStreamSubscriber, useStreamSubscriber,
useStream, useStream,
useNuxt, useNuxt,
useI18n,
useToast,
} from "~/helpers/utils/composables" } from "~/helpers/utils/composables"
import { defineActionHandler } from "~/helpers/actions" import { defineActionHandler } from "~/helpers/actions"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
@@ -237,6 +239,8 @@ import { apolloClient } from "~/helpers/apollo"
import useWindowSize from "~/helpers/utils/useWindowSize" import useWindowSize from "~/helpers/utils/useWindowSize"
import { createShortcode } from "~/helpers/backend/mutations/Shortcode" import { createShortcode } from "~/helpers/backend/mutations/Shortcode"
const t = useI18n()
const methods = [ const methods = [
"GET", "GET",
"POST", "POST",
@@ -250,12 +254,9 @@ const methods = [
"CUSTOM", "CUSTOM",
] ]
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const nuxt = useNuxt() const nuxt = useNuxt()
const t = i18n.t.bind(i18n)
const { subscribeToStream } = useStreamSubscriber() const { subscribeToStream } = useStreamSubscriber()
const newEndpoint = useStream(restEndpoint$, "", setRESTEndpoint) const newEndpoint = useStream(restEndpoint$, "", setRESTEndpoint)
@@ -373,7 +374,7 @@ const copyShareLink = (shareLink: string) => {
} else { } else {
copyLinkIcon.value = "check" copyLinkIcon.value = "check"
copyToClipboard(`https://hopp.sh/r${shareLink}`) copyToClipboard(`https://hopp.sh/r${shareLink}`)
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`, {
icon: "content_paste", icon: "content_paste",
}) })
setTimeout(() => (copyLinkIcon.value = "copy"), 2000) setTimeout(() => (copyLinkIcon.value = "copy"), 2000)
@@ -415,9 +416,7 @@ const saveRequest = () => {
if (saveCtx.originLocation === "user-collection") { if (saveCtx.originLocation === "user-collection") {
editRESTRequest(saveCtx.folderPath, saveCtx.requestIndex, getRESTRequest()) editRESTRequest(saveCtx.folderPath, saveCtx.requestIndex, getRESTRequest())
$toast.success(`${t("request.saved")}`, { toast.success(`${t("request.saved")}`)
icon: "playlist_add_check",
})
} else if (saveCtx.originLocation === "team-collection") { } else if (saveCtx.originLocation === "team-collection") {
const req = getRESTRequest() const req = getRESTRequest()
@@ -430,20 +429,14 @@ const saveRequest = () => {
saveCtx.requestID saveCtx.requestID
) )
.then(() => { .then(() => {
$toast.success(`${t("request.saved")}`, { toast.success(`${t("request.saved")}`)
icon: "playlist_add_check",
})
}) })
.catch(() => { .catch(() => {
$toast.error(t("profile.no_permission").toString(), { toast.error(`${t("profile.no_permission")}`)
icon: "error_outline",
})
}) })
} catch (error) { } catch (error) {
showSaveRequestModal.value = true showSaveRequestModal.value = true
$toast.error(t("error.something_went_wrong").toString(), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(error) console.error(error)
} }
} }

View File

@@ -1,5 +1,18 @@
<template> <template>
<div class="bg-primary flex p-4 top-0 z-10 sticky items-center"> <div
class="
bg-primary
flex
p-4
top-0
z-10
sticky
items-center
overflow-auto
hide-scrollbar
whitespace-nowrap
"
>
<div <div
v-if="response == null" v-if="response == null"
class=" class="
@@ -12,16 +25,16 @@
<div class="flex space-x-2 pb-4 my-4"> <div class="flex space-x-2 pb-4 my-4">
<div class="flex flex-col space-y-4 text-right items-end"> <div class="flex flex-col space-y-4 text-right items-end">
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.request.send_request") }} {{ t("shortcut.request.send_request") }}
</span> </span>
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.general.show_all") }} {{ t("shortcut.general.show_all") }}
</span> </span>
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.general.command_menu") }} {{ t("shortcut.general.command_menu") }}
</span> </span>
<span class="flex flex-1 items-center"> <span class="flex flex-1 items-center">
{{ $t("shortcut.general.help_menu") }} {{ t("shortcut.general.help_menu") }}
</span> </span>
</div> </div>
<div class="flex flex-col space-y-4"> <div class="flex flex-col space-y-4">
@@ -42,8 +55,8 @@
</div> </div>
</div> </div>
<ButtonSecondary <ButtonSecondary
:label="$t('app.documentation')" :label="t('app.documentation')"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/features/response"
svg="external-link" svg="external-link"
blank blank
outline outline
@@ -56,7 +69,7 @@
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
<SmartSpinner class="my-4" /> <SmartSpinner class="my-4" />
<span class="text-secondaryLight">{{ $t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
<div <div
v-if="response.type === 'network_fail'" v-if="response.type === 'network_fail'"
@@ -73,13 +86,13 @@
w-32 w-32
inline-flex inline-flex
" "
:alt="$t('empty.network_fail')" :alt="`${t('error.network_fail')}`"
/> />
<span class="text-center font-semibold mb-2"> <span class="text-center font-semibold mb-2">
{{ $t("error.network_fail") }} {{ t("error.network_fail") }}
</span> </span>
<span class="text-center text-secondaryLight mb-4 max-w-sm"> <span class="text-center text-secondaryLight mb-4 max-w-sm">
{{ $t("helpers.network_fail") }} {{ t("helpers.network_fail") }}
</span> </span>
<AppInterceptor /> <AppInterceptor />
</div> </div>
@@ -89,15 +102,15 @@
class="font-semibold space-x-4" class="font-semibold space-x-4"
> >
<span v-if="response.statusCode"> <span v-if="response.statusCode">
<span class="text-secondary"> {{ $t("response.status") }}: </span> <span class="text-secondary"> {{ t("response.status") }}: </span>
{{ response.statusCode || $t("state.waiting_send_request") }} {{ response.statusCode || t("state.waiting_send_request") }}
</span> </span>
<span v-if="response.meta && response.meta.responseDuration"> <span v-if="response.meta && response.meta.responseDuration">
<span class="text-secondary"> {{ $t("response.time") }}: </span> <span class="text-secondary"> {{ t("response.time") }}: </span>
{{ `${response.meta.responseDuration} ms` }} {{ `${response.meta.responseDuration} ms` }}
</span> </span>
<span v-if="response.meta && response.meta.responseSize"> <span v-if="response.meta && response.meta.responseSize">
<span class="text-secondary"> {{ $t("response.size") }}: </span> <span class="text-secondary"> {{ t("response.size") }}: </span>
{{ `${response.meta.responseSize} B` }} {{ `${response.meta.responseSize} B` }}
</span> </span>
</div> </div>
@@ -110,6 +123,9 @@ import { computed } from "@nuxtjs/composition-api"
import findStatusGroup from "~/helpers/findStatusGroup" import findStatusGroup from "~/helpers/findStatusGroup"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse" import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils" import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
response: HoppRESTResponse response: HoppRESTResponse

View File

@@ -1,5 +1,5 @@
<template> <template>
<AppSection :label="`${$t('test.results')}`"> <AppSection :label="`${t('test.results')}`">
<div <div
v-if=" v-if="
testResults && testResults &&
@@ -20,11 +20,11 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("test.report") }} {{ t("test.report") }}
</label> </label>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear')" :title="t('action.clear')"
svg="trash-2" svg="trash-2"
@click.native="clearContent()" @click.native="clearContent()"
/> />
@@ -64,9 +64,7 @@
<span class="text-secondaryLight"> <span class="text-secondaryLight">
{{ {{
` \xA0 — \xA0 ${ ` \xA0 — \xA0 ${
result.status === "pass" result.status === "pass" ? t("test.passed") : t("test.failed")
? $t("test.passed")
: $t("test.failed")
}` }`
}} }}
</span> </span>
@@ -82,18 +80,18 @@
:src="`/images/states/${$colorMode.value}/validation.svg`" :src="`/images/states/${$colorMode.value}/validation.svg`"
loading="lazy" loading="lazy"
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex" class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
:alt="$t('empty.tests')" :alt="`${t('empty.tests')}`"
/> />
<span class="text-center pb-2"> <span class="text-center pb-2">
{{ $t("empty.tests") }} {{ t("empty.tests") }}
</span> </span>
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("helpers.tests") }} {{ t("helpers.tests") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
outline outline
:label="`${$t('action.learn_more')}`" :label="`${t('action.learn_more')}`"
to="https://docs.hoppscotch.io" to="https://docs.hoppscotch.io/features/tests"
blank blank
svg="external-link" svg="external-link"
reverse reverse
@@ -104,9 +102,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useReadonlyStream } from "~/helpers/utils/composables" import { useReadonlyStream, useI18n } from "~/helpers/utils/composables"
import { restTestResults$, setRESTTestResults } from "~/newstore/RESTSession" import { restTestResults$, setRESTTestResults } from "~/newstore/RESTSession"
const t = useI18n()
const testResults = useReadonlyStream(restTestResults$, null) const testResults = useReadonlyStream(restTestResults$, null)
const clearContent = () => setRESTTestResults(null) const clearContent = () => setRESTTestResults(null)

View File

@@ -1,5 +1,5 @@
<template> <template>
<AppSection id="script" :label="`${$t('test.script')}`"> <AppSection id="script" :label="`${t('test.script')}`">
<div <div
class=" class="
bg-primary bg-primary
@@ -14,26 +14,26 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("test.javascript_code") }} {{ t("test.javascript_code") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/tests" to="https://docs.hoppscotch.io/features/tests"
blank blank
:title="$t('app.wiki')" :title="t('app.wiki')"
svg="help-circle" svg="help-circle"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
/> />
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear')" :title="t('action.clear')"
svg="trash-2" svg="trash-2"
@click.native="clearContent" @click.native="clearContent"
/> />
@@ -57,15 +57,15 @@
" "
> >
<div class="text-secondaryLight pb-2"> <div class="text-secondaryLight pb-2">
{{ $t("helpers.post_request_tests") }} {{ t("helpers.post_request_tests") }}
</div> </div>
<SmartAnchor <SmartAnchor
:label="`${$t('test.learn')}`" :label="`${t('test.learn')}`"
to="https://docs.hoppscotch.io/features/tests" to="https://docs.hoppscotch.io/features/tests"
blank blank
/> />
<h4 class="font-bold text-secondaryLight pt-6"> <h4 class="font-bold text-secondaryLight pt-6">
{{ $t("test.snippets") }} {{ t("test.snippets") }}
</h4> </h4>
<div class="flex flex-col pt-4"> <div class="flex flex-col pt-4">
<TabSecondary <TabSecondary
@@ -82,17 +82,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, useContext } from "@nuxtjs/composition-api" import { reactive, ref } from "@nuxtjs/composition-api"
import { useTestScript } from "~/newstore/RESTSession" import { useTestScript } from "~/newstore/RESTSession"
import testSnippets from "~/helpers/testSnippets" import testSnippets from "~/helpers/testSnippets"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import linter from "~/helpers/editor/linting/testScript" import linter from "~/helpers/editor/linting/testScript"
import completer from "~/helpers/editor/completion/testScript" import completer from "~/helpers/editor/completion/testScript"
import { useI18n } from "~/helpers/utils/composables"
const { const t = useI18n()
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const testScript = useTestScript() const testScript = useTestScript()

View File

@@ -14,14 +14,14 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("request.header_list") }} {{ t("request.header_list") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-if="headers" v-if="headers"
ref="copyHeaders" ref="copyHeaders"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyIcon" :svg="copyIcon"
@click.native="copyHeaders" @click.native="copyHeaders"
/> />
@@ -69,28 +69,26 @@
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { ref } from "@nuxtjs/composition-api"
import { HoppRESTHeader } from "~/helpers/types/HoppRESTRequest"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useI18n, useToast } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
props: {
headers: { type: Array, default: () => [] }, const toast = useToast()
},
data() { const props = defineProps<{
return { headers: Array<HoppRESTHeader>
copyIcon: "copy", }>()
}
}, const copyIcon = ref("copy")
methods: {
copyHeaders() { const copyHeaders = () => {
copyToClipboard(JSON.stringify(this.headers)) copyToClipboard(JSON.stringify(props.headers))
this.copyIcon = "check" copyIcon.value = "check"
this.$toast.success(this.$t("state.copied_to_clipboard"), { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste", setTimeout(() => (copyIcon.value = "copy"), 1000)
}) }
setTimeout(() => (this.copyIcon = "copy"), 1000)
},
},
})
</script> </script>

View File

@@ -14,13 +14,13 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("response.body") }} {{ t("response.body") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-if="response.body" v-if="response.body"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -29,7 +29,7 @@
v-if="response.body" v-if="response.body"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title=" :title="
previewEnabled ? $t('hide.preview') : $t('response.preview_html') previewEnabled ? t('hide.preview') : t('response.preview_html')
" "
:svg="!previewEnabled ? 'eye' : 'eye-off'" :svg="!previewEnabled ? 'eye' : 'eye-off'"
@click.native.prevent="togglePreview" @click.native.prevent="togglePreview"
@@ -38,7 +38,7 @@
v-if="response.body" v-if="response.body"
ref="downloadResponse" ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadIcon" :svg="downloadIcon"
@click.native="downloadResponse" @click.native="downloadResponse"
/> />
@@ -46,7 +46,7 @@
v-if="response.body" v-if="response.body"
ref="copyResponse" ref="copyResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyIcon" :svg="copyIcon"
@click.native="copyResponse" @click.native="copyResponse"
/> />
@@ -64,20 +64,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, useContext, reactive } from "@nuxtjs/composition-api" import { computed, ref, reactive } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse" import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
response: HoppRESTResponse response: HoppRESTResponse
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const responseBodyText = computed(() => { const responseBodyText = computed(() => {
if ( if (
@@ -127,9 +126,7 @@ const downloadResponse = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadIcon.value = "check" downloadIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
@@ -140,9 +137,7 @@ const downloadResponse = () => {
const copyResponse = () => { const copyResponse = () => {
copyToClipboard(responseBodyText.value) copyToClipboard(responseBodyText.value)
copyIcon.value = "check" copyIcon.value = "check"
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste",
})
setTimeout(() => (copyIcon.value = "copy"), 1000) setTimeout(() => (copyIcon.value = "copy"), 1000)
} }

View File

@@ -103,9 +103,7 @@ export default defineComponent({
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
this.downloadIcon = "check" this.downloadIcon = "check"
this.$toast.success(this.$t("state.download_started"), { this.$toast.success(this.$t("state.download_started"))
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)

View File

@@ -14,13 +14,13 @@
" "
> >
<label class="font-semibold text-secondaryLight">{{ <label class="font-semibold text-secondaryLight">{{
$t("response.body") t("response.body")
}}</label> }}</label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-if="response.body" v-if="response.body"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -29,7 +29,7 @@
v-if="response.body" v-if="response.body"
ref="downloadResponse" ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadIcon" :svg="downloadIcon"
@click.native="downloadResponse" @click.native="downloadResponse"
/> />
@@ -37,7 +37,7 @@
v-if="response.body" v-if="response.body"
ref="copyResponse" ref="copyResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyIcon" :svg="copyIcon"
@click.native="copyResponse" @click.native="copyResponse"
/> />
@@ -144,7 +144,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, useContext, reactive } from "@nuxtjs/composition-api" import { computed, ref, reactive } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse" import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
@@ -154,16 +154,15 @@ import {
convertIndexToLineCh, convertIndexToLineCh,
convertLineChToIndex, convertLineChToIndex,
} from "~/helpers/editor/utils" } from "~/helpers/editor/utils"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
response: HoppRESTResponse response: HoppRESTResponse
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const responseBodyText = computed(() => { const responseBodyText = computed(() => {
if ( if (
@@ -234,9 +233,7 @@ const downloadResponse = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadIcon.value = "check" downloadIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
@@ -256,9 +253,7 @@ const outlinePath = computed(() => {
const copyResponse = () => { const copyResponse = () => {
copyToClipboard(responseBodyText.value) copyToClipboard(responseBodyText.value)
copyIcon.value = "check" copyIcon.value = "check"
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste",
})
setTimeout(() => (copyIcon.value = "copy"), 1000) setTimeout(() => (copyIcon.value = "copy"), 1000)
} }
</script> </script>

View File

@@ -14,13 +14,13 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("response.body") }} {{ t("response.body") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-if="response.body" v-if="response.body"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -29,7 +29,7 @@
v-if="response.body" v-if="response.body"
ref="downloadResponse" ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadIcon" :svg="downloadIcon"
@click.native="downloadResponse" @click.native="downloadResponse"
/> />
@@ -37,7 +37,7 @@
v-if="response.body" v-if="response.body"
ref="copyResponse" ref="copyResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyIcon" :svg="copyIcon"
@click.native="copyResponse" @click.native="copyResponse"
/> />
@@ -48,20 +48,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, useContext, computed, reactive } from "@nuxtjs/composition-api" import { ref, computed, reactive } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse" import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
response: HoppRESTResponse response: HoppRESTResponse
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const responseBodyText = computed(() => { const responseBodyText = computed(() => {
if ( if (
@@ -117,9 +116,7 @@ const downloadResponse = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadIcon.value = "check" downloadIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
@@ -130,9 +127,7 @@ const downloadResponse = () => {
const copyResponse = () => { const copyResponse = () => {
copyToClipboard(responseBodyText.value) copyToClipboard(responseBodyText.value)
copyIcon.value = "check" copyIcon.value = "check"
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste",
})
setTimeout(() => (copyIcon.value = "copy"), 1000) setTimeout(() => (copyIcon.value = "copy"), 1000)
} }
</script> </script>

View File

@@ -14,13 +14,13 @@
" "
> >
<label class="font-semibold text-secondaryLight"> <label class="font-semibold text-secondaryLight">
{{ $t("response.body") }} {{ t("response.body") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-if="response.body" v-if="response.body"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('state.linewrap')" :title="t('state.linewrap')"
:class="{ '!text-accent': linewrapEnabled }" :class="{ '!text-accent': linewrapEnabled }"
svg="corner-down-left" svg="corner-down-left"
@click.native.prevent="linewrapEnabled = !linewrapEnabled" @click.native.prevent="linewrapEnabled = !linewrapEnabled"
@@ -29,7 +29,7 @@
v-if="response.body" v-if="response.body"
ref="downloadResponse" ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')" :title="t('action.download_file')"
:svg="downloadIcon" :svg="downloadIcon"
@click.native="downloadResponse" @click.native="downloadResponse"
/> />
@@ -37,7 +37,7 @@
v-if="response.body" v-if="response.body"
ref="copyResponse" ref="copyResponse"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')" :title="t('action.copy')"
:svg="copyIcon" :svg="copyIcon"
@click.native="copyResponse" @click.native="copyResponse"
/> />
@@ -48,20 +48,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, useContext, reactive } from "@nuxtjs/composition-api" import { computed, ref, reactive } from "@nuxtjs/composition-api"
import { useCodemirror } from "~/helpers/editor/codemirror" import { useCodemirror } from "~/helpers/editor/codemirror"
import { copyToClipboard } from "~/helpers/utils/clipboard" import { copyToClipboard } from "~/helpers/utils/clipboard"
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse" import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
response: HoppRESTResponse response: HoppRESTResponse
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const responseBodyText = computed(() => { const responseBodyText = computed(() => {
if ( if (
@@ -117,9 +116,7 @@ const downloadResponse = () => {
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
downloadIcon.value = "check" downloadIcon.value = "check"
$toast.success(`${t("state.download_started")}`, { toast.success(`${t("state.download_started")}`)
icon: "downloading",
})
setTimeout(() => { setTimeout(() => {
document.body.removeChild(a) document.body.removeChild(a)
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
@@ -130,9 +127,7 @@ const downloadResponse = () => {
const copyResponse = () => { const copyResponse = () => {
copyToClipboard(responseBodyText.value) copyToClipboard(responseBodyText.value)
copyIcon.value = "check" copyIcon.value = "check"
$toast.success(`${t("state.copied_to_clipboard")}`, { toast.success(`${t("state.copied_to_clipboard")}`)
icon: "content_paste",
})
setTimeout(() => (copyIcon.value = "copy"), 1000) setTimeout(() => (copyIcon.value = "copy"), 1000)
} }
</script> </script>

View File

@@ -26,7 +26,7 @@
>{{ entry.ts }}{{ source(entry.source) }}{{ entry.payload }}</span >{{ entry.ts }}{{ source(entry.source) }}{{ entry.payload }}</span
> >
</span> </span>
<span v-else>{{ $t("response.waiting_for_connection") }}</span> <span v-else>{{ t("response.waiting_for_connection") }}</span>
</div> </div>
</div> </div>
</template> </template>
@@ -34,6 +34,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, ref, watch } from "@nuxtjs/composition-api" import { nextTick, ref, watch } from "@nuxtjs/composition-api"
import { getSourcePrefix as source } from "~/helpers/utils/string" import { getSourcePrefix as source } from "~/helpers/utils/string"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps({ const props = defineProps({
log: { type: Array, default: () => [] }, log: { type: Array, default: () => [] },

View File

@@ -244,7 +244,9 @@ export default defineComponent({
] ]
const parseUrl = new URL(this.url) const parseUrl = new URL(this.url)
this.client = new Paho.Client( this.client = new Paho.Client(
parseUrl.hostname, `${parseUrl.hostname}${
parseUrl.pathname !== "/" ? parseUrl.pathname : ""
}`,
parseUrl.port !== "" ? Number(parseUrl.port) : 8081, parseUrl.port !== "" ? Number(parseUrl.port) : 8081,
"hoppscotch" "hoppscotch"
) )
@@ -286,9 +288,7 @@ export default defineComponent({
color: "var(--accent-color)", color: "var(--accent-color)",
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}) })
this.$toast.success(this.$t("state.connected"), { this.$toast.success(this.$t("state.connected"))
icon: "sync",
})
}, },
onMessageArrived({ payloadString, destinationName }) { onMessageArrived({ payloadString, destinationName }) {
this.log.push({ this.log.push({
@@ -319,13 +319,9 @@ export default defineComponent({
this.connectingState = false this.connectingState = false
this.connectionState = false this.connectionState = false
if (this.manualDisconnect) { if (this.manualDisconnect) {
this.$toast.error(this.$t("state.disconnected"), { this.$toast.error(this.$t("state.disconnected"))
icon: "sync_disabled",
})
} else { } else {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
} }
this.manualDisconnect = false this.manualDisconnect = false
this.subscriptionState = false this.subscriptionState = false

View File

@@ -325,9 +325,7 @@ export default defineComponent({
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}, },
] ]
this.$toast.success(this.$t("state.connected"), { this.$toast.success(this.$t("state.connected"))
icon: "sync",
})
}) })
this.io.on("*", ({ data }) => { this.io.on("*", ({ data }) => {
const [eventName, message] = data const [eventName, message] = data
@@ -355,15 +353,11 @@ export default defineComponent({
color: "#ff5555", color: "#ff5555",
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}) })
this.$toast.error(this.$t("state.disconnected"), { this.$toast.error(this.$t("state.disconnected"))
icon: "sync_disabled",
})
}) })
} catch (e) { } catch (e) {
this.handleError(e) this.handleError(e)
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
} }
logHoppRequestRunToAnalytics({ logHoppRequestRunToAnalytics({

View File

@@ -171,9 +171,7 @@ export default defineComponent({
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}, },
] ]
this.$toast.success(this.$t("state.connected"), { this.$toast.success(this.$t("state.connected"))
icon: "sync",
})
} }
this.sse.onerror = () => { this.sse.onerror = () => {
this.handleSSEError() this.handleSSEError()
@@ -188,9 +186,7 @@ export default defineComponent({
color: "#ff5555", color: "#ff5555",
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}) })
this.$toast.error(this.$t("state.disconnected"), { this.$toast.error(this.$t("state.disconnected"))
icon: "sync_disabled",
})
} }
this.sse.addEventListener(this.eventType, ({ data }) => { this.sse.addEventListener(this.eventType, ({ data }) => {
this.events.log.push({ this.events.log.push({
@@ -201,9 +197,7 @@ export default defineComponent({
}) })
} catch (e) { } catch (e) {
this.handleSSEError(e) this.handleSSEError(e)
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
} }
} else { } else {
this.events.log = [ this.events.log = [

View File

@@ -319,9 +319,7 @@ export default defineComponent({
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}, },
] ]
this.$toast.success(this.$t("state.connected"), { this.$toast.success(this.$t("state.connected"))
icon: "sync",
})
} }
this.socket.onerror = () => { this.socket.onerror = () => {
this.handleError() this.handleError()
@@ -334,9 +332,7 @@ export default defineComponent({
color: "#ff5555", color: "#ff5555",
ts: new Date().toLocaleTimeString(), ts: new Date().toLocaleTimeString(),
}) })
this.$toast.error(this.$t("state.disconnected"), { this.$toast.error(this.$t("state.disconnected"))
icon: "sync_disabled",
})
} }
this.socket.onmessage = ({ data }) => { this.socket.onmessage = ({ data }) => {
this.communication.log.push({ this.communication.log.push({
@@ -347,9 +343,7 @@ export default defineComponent({
} }
} catch (e) { } catch (e) {
this.handleError(e) this.handleError(e)
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
} }
logHoppRequestRunToAnalytics({ logHoppRequestRunToAnalytics({
@@ -433,7 +427,6 @@ export default defineComponent({
const oldProtocols = this.protocols.slice() const oldProtocols = this.protocols.slice()
this.$delete(this.protocols, index) this.$delete(this.protocols, index)
this.$toast.success(this.$t("state.deleted"), { this.$toast.success(this.$t("state.deleted"), {
icon: "delete",
action: { action: {
text: this.$t("action.undo"), text: this.$t("action.undo"),
duration: 4000, duration: 4000,

View File

@@ -23,8 +23,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { import {
HoppAccentColors, HoppAccentColors,
HoppAccentColor, HoppAccentColor,
@@ -32,18 +31,11 @@ import {
useSetting, useSetting,
} from "~/newstore/settings" } from "~/newstore/settings"
export default defineComponent({ const accentColors = HoppAccentColors
setup() { const active = useSetting("THEME_COLOR")
return {
accentColors: HoppAccentColors, const setActiveColor = (color: HoppAccentColor) => {
active: useSetting("THEME_COLOR"),
}
},
methods: {
setActiveColor(color: HoppAccentColor) {
document.documentElement.setAttribute("data-accent", color) document.documentElement.setAttribute("data-accent", color)
applySetting("THEME_COLOR", color) applySetting("THEME_COLOR", color)
}, }
},
})
</script> </script>

View File

@@ -4,7 +4,7 @@
v-for="(color, index) of colors" v-for="(color, index) of colors"
:key="`color-${index}`" :key="`color-${index}`"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t(getColorModeName(color))" :title="t(getColorModeName(color))"
:class="{ :class="{
'bg-primaryLight !text-accent hover:text-accent': color === active, 'bg-primaryLight !text-accent hover:text-accent': color === active,
}" }"
@@ -15,27 +15,25 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { import {
applySetting, applySetting,
HoppBgColor, HoppBgColor,
HoppBgColors, HoppBgColors,
useSetting, useSetting,
} from "~/newstore/settings" } from "~/newstore/settings"
import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
setup() {
return { const colors = HoppBgColors
colors: HoppBgColors, const active = useSetting("BG_COLOR")
active: useSetting("BG_COLOR"),
} const setBGMode = (color: HoppBgColor) => {
},
methods: {
setBGMode(color: HoppBgColor) {
applySetting("BG_COLOR", color) applySetting("BG_COLOR", color)
}, }
getIcon(color: HoppBgColor) {
const getIcon = (color: HoppBgColor) => {
switch (color) { switch (color) {
case "system": case "system":
return "monitor" return "monitor"
@@ -48,8 +46,9 @@ export default defineComponent({
default: default:
return "monitor" return "monitor"
} }
}, }
getColorModeName(colorMode: string) {
const getColorModeName = (colorMode: string) => {
switch (colorMode) { switch (colorMode) {
case "system": case "system":
return "settings.system_mode" return "settings.system_mode"
@@ -62,7 +61,5 @@ export default defineComponent({
default: default:
return "settings.system_mode" return "settings.system_mode"
} }
}, }
},
})
</script> </script>

View File

@@ -5,12 +5,12 @@
<span class="select-wrapper"> <span class="select-wrapper">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('settings.change_font_size')" :title="t('settings.change_font_size')"
class="pr-8" class="pr-8"
svg="type" svg="type"
outline outline
:label="`${getFontSizeName( :label="`${getFontSizeName(
fontSizes.find((size) => size == active) fontSizes.find((size) => size === active)
)}`" )}`"
/> />
</span> </span>
@@ -32,30 +32,26 @@
</span> </span>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { import {
HoppFontSizes, HoppFontSizes,
HoppFontSize, HoppFontSize,
applySetting, applySetting,
useSetting, useSetting,
} from "~/newstore/settings" } from "~/newstore/settings"
import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
setup() {
return { const fontSizes = HoppFontSizes
fontSizes: HoppFontSizes, const active = useSetting("FONT_SIZE")
active: useSetting("FONT_SIZE"),
} const getFontSizeName = (size: HoppFontSize) => {
}, return t(`settings.font_size_${size}`)
methods: { }
getFontSizeName(size: HoppFontSize) {
return this.$t(`settings.font_size_${size}`) const setActiveFont = (size: HoppFontSize) => {
},
setActiveFont(size: HoppFontSize) {
document.documentElement.setAttribute("data-font-size", size) document.documentElement.setAttribute("data-font-size", size)
applySetting("FONT_SIZE", size) applySetting("FONT_SIZE", size)
}, }
},
})
</script> </script>

View File

@@ -2,20 +2,14 @@
<component :is="src" /> <component :is="src" />
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { computed } from "@nuxtjs/composition-api"
export default defineComponent({ const props = defineProps<{
props: { name: String
name: { }>()
type: String,
required: true, const src = computed(() => {
}, return require(`~/assets/icons/${props.name}.svg?inline`)
},
computed: {
src() {
return require(`~/assets/icons/${this.name}.svg?inline`)
},
},
}) })
</script> </script>

View File

@@ -1,5 +1,5 @@
<template> <template>
<SmartModal v-if="show" :title="$t('team.new').toString()" @close="hideModal"> <SmartModal v-if="show" :title="t('team.new')" @close="hideModal">
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col px-2">
<input <input
@@ -13,18 +13,15 @@
@keyup.enter="addNewTeam" @keyup.enter="addNewTeam"
/> />
<label for="selectLabelTeamAdd"> <label for="selectLabelTeamAdd">
{{ $t("action.label") }} {{ t("action.label") }}
</label> </label>
</div> </div>
</template> </template>
<template #footer> <template #footer>
<span> <span>
<ButtonPrimary <ButtonPrimary :label="t('action.save')" @click.native="addNewTeam" />
:label="$t('action.save').toString()"
@click.native="addNewTeam"
/>
<ButtonSecondary <ButtonSecondary
:label="$t('action.cancel').toString()" :label="t('action.cancel')"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -33,18 +30,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, useContext } from "@nuxtjs/composition-api" import { ref } from "@nuxtjs/composition-api"
import { pipe } from "fp-ts/function" import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither" import * as TE from "fp-ts/TaskEither"
import { createTeam } from "~/helpers/backend/mutations/Team" import { createTeam } from "~/helpers/backend/mutations/Team"
import { TeamNameCodec } from "~/helpers/backend/types/TeamName" import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
import { useI18n, useToast } from "~/helpers/utils/composables"
const { const t = useI18n()
app: { i18n },
$toast,
} = useContext()
const t = i18n.t.bind(i18n) const toast = useToast()
defineProps<{ defineProps<{
show: boolean show: boolean
@@ -66,9 +61,7 @@ const addNewTeam = () =>
(err) => { (err) => {
// err is of type "invalid_name" | GQLError<Err> // err is of type "invalid_name" | GQLError<Err>
if (err === "invalid_name") { if (err === "invalid_name") {
$toast.error(t("team.name_length_insufficient").toString(), { toast.error(`${t("team.name_length_insufficient")}`)
icon: "error_outline",
})
} else { } else {
// Handle GQL errors (use err obj) // Handle GQL errors (use err obj)
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<SmartModal v-if="show" :title="$t('team.edit')" @close="hideModal"> <SmartModal v-if="show" :title="t('team.edit')" @close="hideModal">
<template #body> <template #body>
<div class="flex flex-col px-2"> <div class="flex flex-col px-2">
<div class="flex relative"> <div class="flex relative">
@@ -14,17 +14,17 @@
@keyup.enter="saveTeam" @keyup.enter="saveTeam"
/> />
<label for="selectLabelTeamEdit"> <label for="selectLabelTeamEdit">
{{ $t("action.label") }} {{ t("action.label") }}
</label> </label>
</div> </div>
<div class="flex pt-4 flex-1 justify-between items-center"> <div class="flex pt-4 flex-1 justify-between items-center">
<label for="memberList" class="p-4"> <label for="memberList" class="p-4">
{{ $t("team.members") }} {{ t("team.members") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
svg="user-plus" svg="user-plus"
:label="$t('team.invite')" :label="t('team.invite')"
filled filled
@click.native=" @click.native="
() => { () => {
@@ -39,7 +39,7 @@
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
<SmartSpinner class="mb-4" /> <SmartSpinner class="mb-4" />
<span class="text-secondaryLight">{{ $t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
<div <div
v-if=" v-if="
@@ -70,14 +70,14 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.members')" :alt="`${t('empty.members')}`"
/> />
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("empty.members") }} {{ t("empty.members") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
svg="user-plus" svg="user-plus"
:label="$t('team.invite')" :label="t('team.invite')"
@click.native=" @click.native="
() => { () => {
emit('invite-team') emit('invite-team')
@@ -93,7 +93,7 @@
> >
<input <input
class="bg-transparent flex flex-1 py-2 px-4" class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('team.email')" :placeholder="`${t('team.email')}`"
:name="'param' + index" :name="'param' + index"
:value="member.email" :value="member.email"
readonly readonly
@@ -116,7 +116,7 @@
py-2 py-2
px-4 px-4
" "
:placeholder="$t('team.permissions')" :placeholder="`${t('team.permissions')}`"
:name="'value' + index" :name="'value' + index"
:value=" :value="
typeof member.role === 'string' typeof member.role === 'string'
@@ -160,7 +160,7 @@
<ButtonSecondary <ButtonSecondary
id="member" id="member"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="removeExistingTeamMember(member.userID)" @click.native="removeExistingTeamMember(member.userID)"
@@ -174,15 +174,15 @@
class="flex flex-col items-center" class="flex flex-col items-center"
> >
<i class="mb-4 material-icons">help_outline</i> <i class="mb-4 material-icons">help_outline</i>
{{ $t("error.something_went_wrong") }} {{ t("error.something_went_wrong") }}
</div> </div>
</div> </div>
</template> </template>
<template #footer> <template #footer>
<span> <span>
<ButtonPrimary :label="$t('action.save')" @click.native="saveTeam" /> <ButtonPrimary :label="t('action.save')" @click.native="saveTeam" />
<ButtonSecondary <ButtonSecondary
:label="$t('action.cancel')" :label="t('action.cancel')"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -191,13 +191,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import { computed, ref, toRef, watch } from "@nuxtjs/composition-api"
computed,
ref,
toRef,
useContext,
watch,
} from "@nuxtjs/composition-api"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import { import {
GetTeamDocument, GetTeamDocument,
@@ -215,6 +209,9 @@ import {
} from "~/helpers/backend/mutations/Team" } from "~/helpers/backend/mutations/Team"
import { TeamNameCodec } from "~/helpers/backend/types/TeamName" import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
import { useGQLQuery } from "~/helpers/backend/GQLClient" import { useGQLQuery } from "~/helpers/backend/GQLClient"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const emit = defineEmits<{ const emit = defineEmits<{
(e: "hide-modal"): void (e: "hide-modal"): void
@@ -230,11 +227,7 @@ const props = defineProps<{
editingTeamID: string editingTeamID: string
}>() }>()
const { const toast = useToast()
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const name = toRef(props.editingTeam, "name") const name = toRef(props.editingTeam, "name")
@@ -361,13 +354,9 @@ const removeExistingTeamMember = async (userID: string) => {
props.editingTeamID props.editingTeamID
)() )()
if (E.isLeft(removeTeamMemberResult)) { if (E.isLeft(removeTeamMemberResult)) {
$toast.error(t("error.something_went_wrong"), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error",
})
} else { } else {
$toast.success(t("team.member_removed"), { toast.success(`${t("team.member_removed")}`)
icon: "done",
})
} }
} }
@@ -379,9 +368,7 @@ const saveTeam = async () => {
name.value name.value
)() )()
if (E.isLeft(updateTeamNameResult)) { if (E.isLeft(updateTeamNameResult)) {
$toast.error(t("error.something_went_wrong"), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error",
})
} else { } else {
roleUpdates.value.forEach(async (update) => { roleUpdates.value.forEach(async (update) => {
const updateMemberRoleResult = await updateTeamMemberRole( const updateMemberRoleResult = await updateTeamMemberRole(
@@ -390,26 +377,18 @@ const saveTeam = async () => {
update.role update.role
)() )()
if (E.isLeft(updateMemberRoleResult)) { if (E.isLeft(updateMemberRoleResult)) {
$toast.error(t("error.something_went_wrong"), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error",
})
console.error(updateMemberRoleResult.left.error) console.error(updateMemberRoleResult.left.error)
} }
}) })
} }
hideModal() hideModal()
$toast.success(t("team.saved"), { toast.success(`${t("team.saved")}`)
icon: "done",
})
} else { } else {
return $toast.error(t("team.name_length_insufficient"), { return toast.error(`${t("team.name_length_insufficient")}`)
icon: "error_outline",
})
} }
} else { } else {
return $toast.error(t("empty.team_name"), { return toast.error(`${t("empty.team_name")}`)
icon: "error_outline",
})
} }
} }

View File

@@ -1,14 +1,14 @@
<template> <template>
<SmartModal v-if="show" :title="$t('team.invite')" @close="hideModal"> <SmartModal v-if="show" :title="t('team.invite')" @close="hideModal">
<template #body> <template #body>
<div v-if="sendInvitesResult.length" class="flex flex-col px-4"> <div v-if="sendInvitesResult.length" class="flex flex-col px-4">
<div class="flex flex-col max-w-md justify-center items-center"> <div class="flex flex-col max-w-md justify-center items-center">
<SmartIcon class="h-6 text-accent w-6" name="users" /> <SmartIcon class="h-6 text-accent w-6" name="users" />
<h3 class="my-2 text-center text-lg"> <h3 class="my-2 text-center text-lg">
{{ $t("team.we_sent_invite_link") }} {{ t("team.we_sent_invite_link") }}
</h3> </h3>
<p class="text-center"> <p class="text-center">
{{ $t("team.we_sent_invite_link_description") }} {{ t("team.we_sent_invite_link_description") }}
</p> </p>
</div> </div>
<div <div
@@ -56,7 +56,7 @@
<div v-else class="flex flex-col px-2"> <div v-else class="flex flex-col px-2">
<div class="flex flex-1 justify-between items-center"> <div class="flex flex-1 justify-between items-center">
<label for="memberList" class="pb-4 px-4"> <label for="memberList" class="pb-4 px-4">
{{ $t("team.pending_invites") }} {{ t("team.pending_invites") }}
</label> </label>
</div> </div>
<div class="divide-y divide-dividerLight border-divider border rounded"> <div class="divide-y divide-dividerLight border-divider border rounded">
@@ -85,7 +85,7 @@
py-2 py-2
px-4 px-4
" "
:placeholder="`${$t('team.email')}`" :placeholder="`${t('team.email')}`"
:name="'param' + index" :name="'param' + index"
:value="invitee.inviteeEmail" :value="invitee.inviteeEmail"
readonly readonly
@@ -98,7 +98,7 @@
py-2 py-2
px-4 px-4
" "
:placeholder="`${$t('team.permissions')}`" :placeholder="`${t('team.permissions')}`"
:name="'value' + index" :name="'value' + index"
:value=" :value="
typeof invitee.inviteeRole === 'string' typeof invitee.inviteeRole === 'string'
@@ -110,7 +110,7 @@
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="removeInvitee(invitee.id)" @click.native="removeInvitee(invitee.id)"
@@ -132,7 +132,7 @@
" "
> >
<span class="text-center"> <span class="text-center">
{{ $t("empty.pending_invites") }} {{ t("empty.pending_invites") }}
</span> </span>
</div> </div>
<div <div
@@ -140,18 +140,18 @@
class="flex flex-col p-4 items-center" class="flex flex-col p-4 items-center"
> >
<i class="mb-4 material-icons">help_outline</i> <i class="mb-4 material-icons">help_outline</i>
{{ $t("error.something_went_wrong") }} {{ t("error.something_went_wrong") }}
</div> </div>
</div> </div>
</div> </div>
<div class="flex pt-4 flex-1 justify-between items-center"> <div class="flex pt-4 flex-1 justify-between items-center">
<label for="memberList" class="p-4"> <label for="memberList" class="p-4">
{{ $t("team.invite_tooltip") }} {{ t("team.invite_tooltip") }}
</label> </label>
<div class="flex"> <div class="flex">
<ButtonSecondary <ButtonSecondary
svg="plus" svg="plus"
:label="$t('add.new')" :label="t('add.new')"
filled filled
@click.native="addNewInvitee" @click.native="addNewInvitee"
/> />
@@ -166,7 +166,7 @@
<input <input
v-model="invitee.key" v-model="invitee.key"
class="bg-transparent flex flex-1 py-2 px-4" class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('team.email')" :placeholder="`${t('team.email')}`"
:name="'invitee' + index" :name="'invitee' + index"
autofocus autofocus
/> />
@@ -188,7 +188,7 @@
py-2 py-2
px-4 px-4
" "
:placeholder="$t('team.permissions')" :placeholder="`${t('team.permissions')}`"
:name="'value' + index" :name="'value' + index"
:value=" :value="
typeof invitee.value === 'string' typeof invitee.value === 'string'
@@ -232,7 +232,7 @@
<ButtonSecondary <ButtonSecondary
id="member" id="member"
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')" :title="t('action.remove')"
svg="trash" svg="trash"
color="red" color="red"
@click.native="removeNewInvitee(index)" @click.native="removeNewInvitee(index)"
@@ -260,13 +260,13 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.invites')" :alt="`${t('empty.invites')}`"
/> />
<span class="text-center pb-4"> <span class="text-center pb-4">
{{ $t("empty.invites") }} {{ t("empty.invites") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
:label="$t('add.new')" :label="t('add.new')"
filled filled
@click.native="addNewInvitee" @click.native="addNewInvitee"
/> />
@@ -299,11 +299,11 @@
" "
> >
<i class="text-secondaryLight mr-2 material-icons">help_outline</i> <i class="text-secondaryLight mr-2 material-icons">help_outline</i>
{{ $t("profile.roles") }} {{ t("profile.roles") }}
</span> </span>
<p> <p>
<span class="text-secondaryLight"> <span class="text-secondaryLight">
{{ $t("profile.roles_description") }} {{ t("profile.roles_description") }}
</span> </span>
</p> </p>
<ul class="mt-4 space-y-4"> <ul class="mt-4 space-y-4">
@@ -318,10 +318,10 @@
w-1/4 w-1/4
" "
> >
{{ $t("profile.owner") }} {{ t("profile.owner") }}
</span> </span>
<span class="flex flex-1"> <span class="flex flex-1">
{{ $t("profile.owner_description") }} {{ t("profile.owner_description") }}
</span> </span>
</li> </li>
<li class="flex"> <li class="flex">
@@ -335,10 +335,10 @@
w-1/4 w-1/4
" "
> >
{{ $t("profile.editor") }} {{ t("profile.editor") }}
</span> </span>
<span class="flex flex-1"> <span class="flex flex-1">
{{ $t("profile.editor_description") }} {{ t("profile.editor_description") }}
</span> </span>
</li> </li>
<li class="flex"> <li class="flex">
@@ -352,10 +352,10 @@
w-1/4 w-1/4
" "
> >
{{ $t("profile.viewer") }} {{ t("profile.viewer") }}
</span> </span>
<span class="flex flex-1"> <span class="flex flex-1">
{{ $t("profile.viewer_description") }} {{ t("profile.viewer_description") }}
</span> </span>
</li> </li>
</ul> </ul>
@@ -369,7 +369,7 @@
> >
<SmartAnchor <SmartAnchor
class="link" class="link"
:label="`← \xA0 ${$t('team.invite_more')}`" :label="`← \xA0 ${t('team.invite_more')}`"
@click.native=" @click.native="
() => { () => {
sendInvitesResult = [] sendInvitesResult = []
@@ -384,14 +384,14 @@
/> />
<SmartAnchor <SmartAnchor
class="link" class="link"
:label="`${$t('action.dismiss')}`" :label="`${t('action.dismiss')}`"
@click.native="hideModal" @click.native="hideModal"
/> />
</p> </p>
<span v-else> <span v-else>
<ButtonPrimary :label="$t('team.invite')" @click.native="sendInvites" /> <ButtonPrimary :label="t('team.invite')" @click.native="sendInvites" />
<ButtonSecondary <ButtonSecondary
:label="$t('action.cancel')" :label="t('action.cancel')"
@click.native="hideModal" @click.native="hideModal"
/> />
</span> </span>
@@ -400,13 +400,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import { watch, ref, reactive, computed } from "@nuxtjs/composition-api"
watch,
ref,
reactive,
useContext,
computed,
} from "@nuxtjs/composition-api"
import * as T from "fp-ts/Task" import * as T from "fp-ts/Task"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import * as A from "fp-ts/Array" import * as A from "fp-ts/Array"
@@ -427,12 +421,11 @@ import {
revokeTeamInvitation, revokeTeamInvitation,
} from "../../helpers/backend/mutations/TeamInvitation" } from "../../helpers/backend/mutations/TeamInvitation"
import { GQLError, useGQLQuery } from "~/helpers/backend/GQLClient" import { GQLError, useGQLQuery } from "~/helpers/backend/GQLClient"
import { useI18n, useToast } from "~/helpers/utils/composables"
const { const t = useI18n()
$toast,
app: { i18n }, const toast = useToast()
} = useContext()
const t = i18n.t.bind(i18n)
const newInviteeOptions = ref<any | null>(null) const newInviteeOptions = ref<any | null>(null)
@@ -491,13 +484,9 @@ watch(
const removeInvitee = async (id: string) => { const removeInvitee = async (id: string) => {
const result = await revokeTeamInvitation(id)() const result = await revokeTeamInvitation(id)()
if (E.isLeft(result)) { if (E.isLeft(result)) {
$toast.error(`${t("error.something_went_wrong")}`, { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
} else { } else {
$toast.success(`${t("team.member_removed")}`, { toast.success(`${t("team.member_removed")}`)
icon: "person",
})
} }
} }
@@ -557,9 +546,7 @@ const sendInvites = async () => {
if (O.isNone(validationResult)) { if (O.isNone(validationResult)) {
// Error handling for no validation // Error handling for no validation
$toast.error(`${t("error.incorrect_email")}`, { toast.error(`${t("error.incorrect_email")}`)
icon: "error_outline",
})
return return
} }

View File

@@ -1,26 +1,25 @@
<template> <template>
<SmartModal <SmartModal v-if="show" :title="t('team.select_a_team')" @close="hideModal">
v-if="show"
:title="$t('team.select_a_team')"
@close="$emit('hide-modal')"
>
<template #body> <template #body>
<Teams :modal="true" /> <Teams :modal="true" />
</template> </template>
</SmartModal> </SmartModal>
</template> </template>
<script> <script setup lang="ts">
import { defineComponent } from "@nuxtjs/composition-api" import { useI18n } from "~/helpers/utils/composables"
export default defineComponent({ const t = useI18n()
props: {
show: Boolean, defineProps<{
}, show: Boolean
methods: { }>()
hideModal() {
this.$emit("hide-modal") const emit = defineEmits<{
}, (e: "hide-modal"): void
}, }>()
})
const hideModal = () => {
emit("hide-modal")
}
</script> </script>

View File

@@ -22,7 +22,7 @@
class="font-semibold text-secondaryDark" class="font-semibold text-secondaryDark"
:class="{ 'cursor-pointer': compact && team.myRole === 'OWNER' }" :class="{ 'cursor-pointer': compact && team.myRole === 'OWNER' }"
> >
{{ team.name || $t("state.nothing_found") }} {{ team.name || t("state.nothing_found") }}
</label> </label>
<div class="flex -space-x-1 mt-2 overflow-hidden"> <div class="flex -space-x-1 mt-2 overflow-hidden">
<img <img
@@ -44,7 +44,7 @@
v-if="team.myRole === 'OWNER'" v-if="team.myRole === 'OWNER'"
svg="edit" svg="edit"
class="rounded-none" class="rounded-none"
:label="$t('action.edit').toString()" :label="t('action.edit')"
@click.native=" @click.native="
() => { () => {
$emit('edit-team') $emit('edit-team')
@@ -55,7 +55,7 @@
v-if="team.myRole === 'OWNER'" v-if="team.myRole === 'OWNER'"
svg="user-plus" svg="user-plus"
class="rounded-none" class="rounded-none"
:label="$t('team.invite')" :label="t('team.invite')"
@click.native=" @click.native="
() => { () => {
emit('invite-team') emit('invite-team')
@@ -68,14 +68,14 @@
<template #trigger> <template #trigger>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('action.more')" :title="t('action.more')"
svg="more-vertical" svg="more-vertical"
/> />
</template> </template>
<SmartItem <SmartItem
v-if="team.myRole === 'OWNER'" v-if="team.myRole === 'OWNER'"
svg="edit" svg="edit"
:label="$t('action.edit').toString()" :label="t('action.edit')"
@click.native=" @click.native="
() => { () => {
$emit('edit-team') $emit('edit-team')
@@ -87,7 +87,7 @@
v-if="team.myRole === 'OWNER'" v-if="team.myRole === 'OWNER'"
svg="trash-2" svg="trash-2"
color="red" color="red"
:label="$t('action.delete').toString()" :label="t('action.delete')"
@click.native=" @click.native="
() => { () => {
deleteTeam() deleteTeam()
@@ -98,7 +98,7 @@
<SmartItem <SmartItem
v-if="!(team.myRole === 'OWNER' && team.ownersCount == 1)" v-if="!(team.myRole === 'OWNER' && team.ownersCount == 1)"
svg="trash" svg="trash"
:label="$t('team.exit').toString()" :label="t('team.exit')"
@click.native=" @click.native="
() => { () => {
exitTeam() exitTeam()
@@ -113,7 +113,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useContext } from "@nuxtjs/composition-api"
import { pipe } from "fp-ts/function" import { pipe } from "fp-ts/function"
import * as TE from "fp-ts/TaskEither" import * as TE from "fp-ts/TaskEither"
import { TeamMemberRole } from "~/helpers/backend/graphql" import { TeamMemberRole } from "~/helpers/backend/graphql"
@@ -121,6 +120,9 @@ import {
deleteTeam as backendDeleteTeam, deleteTeam as backendDeleteTeam,
leaveTeam, leaveTeam,
} from "~/helpers/backend/mutations/Team" } from "~/helpers/backend/mutations/Team"
import { useI18n, useToast } from "~/helpers/utils/composables"
const t = useI18n()
const props = defineProps<{ const props = defineProps<{
team: { team: {
@@ -142,30 +144,21 @@ const emit = defineEmits<{
(e: "edit-team"): void (e: "edit-team"): void
}>() }>()
const { const toast = useToast()
app: { i18n },
$toast,
} = useContext()
const t = i18n.t.bind(i18n)
const deleteTeam = () => { const deleteTeam = () => {
if (!confirm(t("confirm.remove_team").toString())) return if (!confirm(`${t("confirm.remove_team")}`)) return
pipe( pipe(
backendDeleteTeam(props.teamID), backendDeleteTeam(props.teamID),
TE.match( TE.match(
(err) => { (err) => {
// TODO: Better errors ? We know the possible errors now // TODO: Better errors ? We know the possible errors now
$toast.error(t("error.something_went_wrong").toString(), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(err) console.error(err)
}, },
() => { () => {
$toast.success(t("team.deleted").toString(), { toast.success(`${t("team.deleted")}`)
icon: "done",
})
} }
) )
)() // Tasks (and TEs) are lazy, so call the function returned )() // Tasks (and TEs) are lazy, so call the function returned
@@ -179,23 +172,17 @@ const exitTeam = () => {
TE.match( TE.match(
(err) => { (err) => {
// TODO: Better errors ? // TODO: Better errors ?
$toast.error(t("error.something_went_wrong").toString(), { toast.error(`${t("error.something_went_wrong")}`)
icon: "error_outline",
})
console.error(err) console.error(err)
}, },
() => { () => {
$toast.success(t("team.left").toString(), { toast.success(`${t("team.left")}`)
icon: "done",
})
} }
) )
)() // Tasks (and TEs) are lazy, so call the function returned )() // Tasks (and TEs) are lazy, so call the function returned
} }
const noPermission = () => { const noPermission = () => {
$toast.error(t("profile.no_permission").toString(), { toast.error(`${t("profile.no_permission")}`)
icon: "error_outline",
})
} }
</script> </script>

View File

@@ -2,7 +2,7 @@
<AppSection label="teams"> <AppSection label="teams">
<div class="space-y-4 p-4"> <div class="space-y-4 p-4">
<ButtonSecondary <ButtonSecondary
:label="`${$t('team.create_new')}`" :label="`${t('team.create_new')}`"
outline outline
@click.native="displayModalAdd(true)" @click.native="displayModalAdd(true)"
/> />
@@ -11,7 +11,7 @@
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
<SmartSpinner class="mb-4" /> <SmartSpinner class="mb-4" />
<span class="text-secondaryLight">{{ $t("state.loading") }}</span> <span class="text-secondaryLight">{{ t("state.loading") }}</span>
</div> </div>
<div <div
v-if=" v-if="
@@ -38,13 +38,13 @@
w-16 w-16
inline-flex inline-flex
" "
:alt="$t('empty.teams')" :alt="`${t('empty.teams')}`"
/> />
<span class="text-center mb-4"> <span class="text-center mb-4">
{{ $t("empty.teams") }} {{ t("empty.teams") }}
</span> </span>
<ButtonSecondary <ButtonSecondary
:label="`${$t('team.create_new')}`" :label="`${t('team.create_new')}`"
filled filled
@click.native="displayModalAdd(true)" @click.native="displayModalAdd(true)"
/> />
@@ -71,7 +71,7 @@
class="flex flex-col items-center" class="flex flex-col items-center"
> >
<i class="mb-4 material-icons">help_outline</i> <i class="mb-4 material-icons">help_outline</i>
{{ $t("error.something_went_wrong") }} {{ t("error.something_went_wrong") }}
</div> </div>
</div> </div>
<TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" /> <TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
@@ -114,6 +114,9 @@ import {
MyTeamsQueryVariables, MyTeamsQueryVariables,
} from "~/helpers/backend/graphql" } from "~/helpers/backend/graphql"
import { MyTeamsQueryError } from "~/helpers/backend/QueryErrors" import { MyTeamsQueryError } from "~/helpers/backend/QueryErrors"
import { useI18n } from "~/helpers/utils/composables"
const t = useI18n()
defineProps<{ defineProps<{
modal: boolean modal: boolean

View File

@@ -91,12 +91,14 @@ export const baseTheme = EditorView.theme({
".cm-tooltip-autocomplete ul li[aria-selected] .cm-completionLabel": { ".cm-tooltip-autocomplete ul li[aria-selected] .cm-completionLabel": {
color: "var(--accent-contrast-color)", color: "var(--accent-contrast-color)",
}, },
".cm-activeLine": { backgroundColor: "var(--primary-light-color)" }, ".cm-activeLine": { backgroundColor: "transparent" },
".cm-searchMatch": { ".cm-searchMatch": {
outline: "1px solid var(--accent-dark-color)", outline: "1px solid var(--accent-dark-color)",
backgroundColor: "var(--divider-dark-color)",
}, },
".cm-selectionMatch": { ".cm-selectionMatch": {
outline: "1px solid var(--accent-dark-color)", outline: "1px solid var(--accent-dark-color)",
backgroundColor: "var(--divider-light-color)",
}, },
".cm-matchingBracket, .cm-nonmatchingBracket": { ".cm-matchingBracket, .cm-nonmatchingBracket": {
backgroundColor: "var(--divider-color)", backgroundColor: "var(--divider-color)",
@@ -121,14 +123,18 @@ export const baseTheme = EditorView.theme({
".cm-line": { ".cm-line": {
paddingLeft: "0.5em", paddingLeft: "0.5em",
paddingRight: "0.5em", paddingRight: "0.5em",
color: "var(--secondary-dark-color)",
}, },
".cm-activeLineGutter": { ".cm-activeLineGutter": {
backgroundColor: "var(--primary-dark-color)", backgroundColor: "transparent",
}, },
".cm-scroller::-webkit-scrollbar": { ".cm-scroller::-webkit-scrollbar": {
display: "none", display: "none",
}, },
".cm-foldPlaceholder": {
backgroundColor: "var(--divider-light-color)",
color: "var(--secondary-dark-color)",
borderColor: "var(--divider-dark-color)",
},
}) })
const editorTypeColor = "var(--editor-type-color)" const editorTypeColor = "var(--editor-type-color)"

View File

@@ -15,17 +15,18 @@ export function useArrowKeysNavigation(searchItems: any, options: any = {}) {
const itemsLength = searchItems.value.length const itemsLength = searchItems.value.length
const lastItemIndex = itemsLength - 1 const lastItemIndex = itemsLength - 1
const itemIndexValue = itemIndex.value const itemIndexValue = itemIndex.value
const action = searchItems.value[itemIndexValue].action const action = searchItems.value[itemIndexValue]?.action
if (action && event.key === "Enter" && options.onEnter) { if (action && event.key === "Enter" && options.onEnter) {
options.onEnter(action) options.onEnter(action)
return return
} }
if (event.key === "ArrowDown") { if (itemsLength && event.key === "ArrowDown") {
itemIndex.value = itemIndexValue < lastItemIndex ? itemIndexValue + 1 : 0 itemIndex.value = itemIndexValue < lastItemIndex ? itemIndexValue + 1 : 0
} else if (itemIndexValue === 0) itemIndex.value = lastItemIndex } else if (itemIndexValue === 0) itemIndex.value = lastItemIndex
else if (event.key === "ArrowUp") itemIndex.value = itemIndexValue - 1 else if (itemsLength && event.key === "ArrowUp")
itemIndex.value = itemIndexValue - 1
} }
const preventPropagation = options && options.stopPropagation const preventPropagation = options && options.stopPropagation

View File

@@ -5,6 +5,7 @@ import {
readonly, readonly,
Ref, Ref,
ref, ref,
useContext,
watch, watch,
wrapProperty, wrapProperty,
} from "@nuxtjs/composition-api" } from "@nuxtjs/composition-api"
@@ -132,3 +133,15 @@ export function useStreamSubscriber() {
subscribeToStream: runAndSubscribe, subscribeToStream: runAndSubscribe,
} }
} }
export function useI18n() {
const {
app: { i18n },
} = useContext()
return i18n.t.bind(i18n)
}
export function useToast() {
const { $toast } = useContext()
return $toast
}

View File

@@ -171,7 +171,6 @@ export default defineComponent({
workbox.addEventListener("installed", (event: any) => { workbox.addEventListener("installed", (event: any) => {
if (event.isUpdate) { if (event.isUpdate) {
this.$toast.show(`${this.$t("app.new_version_found")}`, { this.$toast.show(`${this.$t("app.new_version_found")}`, {
icon: "download_for_offline",
duration: 0, duration: 0,
action: [ action: [
{ {

View File

@@ -2,61 +2,61 @@
"action": { "action": {
"cancel": "Annulla", "cancel": "Annulla",
"choose_file": "Scegli un file", "choose_file": "Scegli un file",
"clear": "Chiaro", "clear": "Cancella",
"clear_all": "Cancella tutto", "clear_all": "Cancella tutto",
"connect": "Collegare", "connect": "Connetti",
"copy": "copia", "copy": "Copia",
"delete": "Elimina", "delete": "Elimina",
"disconnect": "Disconnetti", "disconnect": "Disconnetti",
"dismiss": "Congedare", "dismiss": "Abbandona",
"download_file": "Download file", "download_file": "Scarica file",
"duplicate": "Duplicate", "duplicate": "Duplica",
"edit": "Modificare", "edit": "Modifica",
"go_back": "Torna indietro", "go_back": "Torna indietro",
"label": "Etichetta", "label": "Etichetta",
"learn_more": "Per saperne di più", "learn_more": "Per saperne di più",
"more": "Di più", "more": "Di più",
"new": "Nuovo", "new": "Nuovo",
"no": "No", "no": "No",
"preserve_current": "Conserva la corrente", "preserve_current": "Conserva attuale",
"prettify": "Abbellire", "prettify": "Abbellisci",
"remove": "Rimuovere", "remove": "Rimuovi",
"replace_current": "Sostituisci corrente", "replace_current": "Sostituisci attuale",
"replace_json": "Sostituisci con JSON", "replace_json": "Sostituisci con JSON",
"restore": "Ristabilire", "restore": "Ripristina",
"save": "Salva", "save": "Salva",
"search": "Ricerca", "search": "Cerca",
"send": "Spedire", "send": "Invia",
"start": "Cominciare", "start": "Avvia",
"stop": "Fermare", "stop": "Interrompi",
"turn_off": "Spegni", "turn_off": "Spegni",
"turn_on": "Accendere", "turn_on": "Accendi",
"undo": "Annullare", "undo": "Annulla",
"yes": "sì" "yes": "Sì"
}, },
"add": { "add": {
"new": "Aggiungere nuova", "new": "Aggiungi nuova",
"star": "Aggiungi stella" "star": "Aggiungi stella"
}, },
"app": { "app": {
"chat_with_us": "chatta con noi", "chat_with_us": "Chatta con noi",
"contact_us": "Contattaci", "contact_us": "Contattaci",
"copy": "copia", "copy": "Copia",
"documentation": "Documentazione", "documentation": "Documentazione",
"github": "GitHub", "github": "GitHub",
"help": "Aiuto, feedback e documentazione", "help": "Aiuto, feedback e documentazione",
"home": "Casa", "home": "Home",
"invite": "Invitare", "invite": "Invita",
"invite_description": "In Hoppscotch, abbiamo progettato un'interfaccia semplice e intuitiva per creare e gestire le tue API. Hoppscotch è uno strumento che ti aiuta a creare, testare, documentare e condividere le tue API.", "invite_description": "In Hoppscotch, abbiamo progettato un'interfaccia semplice e intuitiva per creare e gestire le tue API. Hoppscotch è uno strumento che ti aiuta a creare, testare, documentare e condividere le tue API.",
"invite_your_friends": "Invita i tuoi amici", "invite_your_friends": "Invita i tuoi amici",
"join_discord_community": "Unisciti alla nostra comunità Discord", "join_discord_community": "Unisciti alla nostra comunità Discord",
"keyboard_shortcuts": "Tasti rapidi", "keyboard_shortcuts": "Tasti rapidi",
"name": "Hoppscotch", "name": "Hoppscotch",
"new_version_found": "Nuova versione trovata. Aggiorna per aggiornare.", "new_version_found": "Nuova versione trovata. Aggiorna la pagina per aggiornare.",
"proxy_privacy_policy": "Informativa sulla privacy del proxy", "proxy_privacy_policy": "Informativa sulla privacy del proxy",
"reload": "Ricaricare", "reload": "Ricarica",
"search": "Ricerca", "search": "Cerca",
"share": "Condividere", "share": "Condividi",
"shortcuts": "Scorciatoie", "shortcuts": "Scorciatoie",
"spotlight": "Riflettore", "spotlight": "Riflettore",
"status": "Stato", "status": "Stato",
@@ -76,13 +76,13 @@
"continue_with_google": "Continua con Google", "continue_with_google": "Continua con Google",
"email": "E-mail", "email": "E-mail",
"logged_out": "Disconnesso", "logged_out": "Disconnesso",
"login": "Login", "login": "Accedi",
"login_success": "Accesso effettuato con successo", "login_success": "Accesso effettuato con successo",
"login_to_hoppscotch": "Accedi a Hoppscotch", "login_to_hoppscotch": "Accedi a Hoppscotch",
"logout": "Disconnettersi", "logout": "Disconnettersi",
"re_enter_email": "Reinserisci l'email", "re_enter_email": "Reinserisci l'email",
"send_magic_link": "Invia un link magico", "send_magic_link": "Invia un link magico",
"sync": "Sincronizzazione", "sync": "Sincronizza",
"we_sent_magic_link": "Ti abbiamo inviato un link magico!", "we_sent_magic_link": "Ti abbiamo inviato un link magico!",
"we_sent_magic_link_description": "Controlla la tua casella di posta: abbiamo inviato un'email a {email}. Contiene un collegamento magico che ti consentirà di accedere." "we_sent_magic_link_description": "Controlla la tua casella di posta: abbiamo inviato un'email a {email}. Contiene un collegamento magico che ti consentirà di accedere."
}, },
@@ -90,24 +90,24 @@
"generate_token": "Genera token", "generate_token": "Genera token",
"include_in_url": "Includi nell'URL", "include_in_url": "Includi nell'URL",
"learn": "Impara come", "learn": "Impara come",
"password": "Parola d'ordine", "password": "Password",
"token": "Gettone", "token": "Token",
"type": "Tipo di autorizzazione", "type": "Tipo di autorizzazione",
"username": "Nome utente" "username": "Nome utente"
}, },
"collection": { "collection": {
"created": "Collezione creata", "created": "Raccolta creata",
"edit": "Modifica raccolta", "edit": "Modifica raccolta",
"invalid_name": "Si prega di fornire un nome valido per la raccolta", "invalid_name": "Si prega di fornire un nome valido per la raccolta",
"my_collections": "Le mie collezioni", "my_collections": "Le Mie Raccolte",
"name": "La mia nuova collezione", "name": "La mia nuova raccolta",
"new": "Nuova collezione", "new": "Nuova raccolta",
"renamed": "Collezione rinominata", "renamed": "Raccolta rinominata",
"save_as": "Salva come", "save_as": "Salva come",
"select": "Seleziona una collezione", "select": "Seleziona una raccolta",
"select_location": "Seleziona la posizione", "select_location": "Seleziona la posizione",
"select_team": "Seleziona una squadra", "select_team": "Seleziona un team",
"team_collections": "Collezioni squadra" "team_collections": "Raccolte di team"
}, },
"confirm": { "confirm": {
"logout": "Sei sicuro di voler uscire?", "logout": "Sei sicuro di voler uscire?",
@@ -116,9 +116,9 @@
"remove_folder": "Sei sicuro di voler eliminare definitivamente questa cartella?", "remove_folder": "Sei sicuro di voler eliminare definitivamente questa cartella?",
"remove_history": "Sei sicuro di voler eliminare definitivamente tutta la cronologia?", "remove_history": "Sei sicuro di voler eliminare definitivamente tutta la cronologia?",
"remove_request": "Sei sicuro di voler eliminare definitivamente questa richiesta?", "remove_request": "Sei sicuro di voler eliminare definitivamente questa richiesta?",
"remove_team": "Sei sicuro di voler eliminare questa squadra?", "remove_team": "Sei sicuro di voler eliminare questo team?",
"remove_telemetry": "Sei sicuro di voler disattivare la telemetria?", "remove_telemetry": "Sei sicuro di voler disattivare la telemetria?",
"sync": "Sei sicuro di voler sincronizzare questo spazio di lavoro?" "sync": "Vuoi ripristinare il tuo spazio di lavoro con quello del cloud? Questo annullerà le tue modifiche fatte in locale."
}, },
"count": { "count": {
"header": "Intestazione {count}", "header": "Intestazione {count}",
@@ -130,27 +130,27 @@
}, },
"documentation": { "documentation": {
"generate": "Genera documentazione", "generate": "Genera documentazione",
"generate_message": "Importa qualsiasi collezione Hoppscotch per generare documentazione API in movimento." "generate_message": "Importa qualsiasi raccolta Hoppscotch per generare documentazione API al volo."
}, },
"empty": { "empty": {
"authorization": "Questa richiesta non utilizza alcuna autorizzazione", "authorization": "Questa richiesta non utilizza alcuna autorizzazione",
"body": "Questa richiesta non ha un corpo", "body": "Questa richiesta non ha un corpo",
"collection": "La raccolta è vuota", "collection": "La raccolta è vuota",
"collections": "Le raccolte sono vuote", "collections": "Le raccolte sono vuote",
"documentation": "Connect to a GraphQL endpoint to view documentation", "documentation": "Connetti ad un endpoint GraphQL per mostrare la documentazione",
"environments": "Gli ambienti sono vuoti", "environments": "Gli ambienti sono vuoti",
"folder": "La cartella è vuota", "folder": "La cartella è vuota",
"headers": "Questa richiesta non ha intestazioni", "headers": "Questa richiesta non ha intestazioni",
"history": "La storia è vuota", "history": "La cronologia è vuota",
"invites": "Invite list is empty", "invites": "La lista degli inviti è vuota",
"members": "La squadra è vuota", "members": "Il team non ha membri",
"parameters": "Questa richiesta non ha parametri", "parameters": "Questa richiesta non ha parametri",
"pending_invites": "There are no pending invites for this team", "pending_invites": "Non ci sono inviti pendenti per questo team",
"profile": "Login in to view your profile", "profile": "Accedi per mostrare il tuo profilo",
"protocols": "I protocolli sono vuoti", "protocols": "I protocolli sono vuoti",
"schema": "Connettiti a un endpoint GraphQL", "schema": "Connettiti a un endpoint GraphQL per mostrare lo schema",
"team_name": "Nome della squadra vuoto", "team_name": "Il nome del team è vuoto",
"teams": "Le squadre sono vuote", "teams": "I team sono vuoti",
"tests": "Non ci sono test per questa richiesta" "tests": "Non ci sono test per questa richiesta"
}, },
"environment": { "environment": {
@@ -164,26 +164,26 @@
"variable_list": "Elenco variabili" "variable_list": "Elenco variabili"
}, },
"error": { "error": {
"browser_support_sse": "Questo browser non sembra supportare gli eventi inviati dal server.", "browser_support_sse": "Questo browser non sembra supportare gli eventi inviati dal server (Server Sent Events).",
"check_console_details": "Controlla il registro della console per i dettagli.", "check_console_details": "Controlla il log della console per i dettagli.",
"curl_invalid_format": "cURL non è formattato correttamente", "curl_invalid_format": "cURL non è formattato correttamente",
"empty_req_name": "Nome richiesta vuoto", "empty_req_name": "Nome richiesta vuoto",
"f12_details": "(F12 per i dettagli)", "f12_details": "(F12 per i dettagli)",
"gql_prettify_invalid_query": "Impossibile abbellire una query non valida, risolvere gli errori di sintassi della query e riprovare", "gql_prettify_invalid_query": "Impossibile abbellire una query non valida, risolvere gli errori di sintassi della query e riprovare",
"incorrect_email": "Incorrect email", "incorrect_email": "Indirizzo email errato",
"invalid_link": "Invalid link", "invalid_link": "Invalid link",
"invalid_link_description": "The link you clicked is invalid or expired.", "invalid_link_description": "The link you clicked is invalid or expired.",
"json_prettify_invalid_body": "Impossibile abbellire un corpo non valido, risolvere gli errori di sintassi json e riprovare", "json_prettify_invalid_body": "Impossibile abbellire un corpo non valido, risolvere gli errori di sintassi JSON e riprovare",
"network_error": "There seems to be a network error. Please try again.", "network_error": "Sembra ci sia un problema di rete. Per favore prova di nuovo.",
"network_fail": "Impossibile inviare la richiesta", "network_fail": "Impossibile inviare la richiesta",
"no_duration": "Nessuna durata", "no_duration": "Nessuna durata",
"something_went_wrong": "Qualcosa è andato storto" "something_went_wrong": "Qualcosa è andato storto"
}, },
"export": { "export": {
"as_json": "Esporta come JSON", "as_json": "Esporta come JSON",
"create_secret_gist": "Crea un segreto Gist", "create_secret_gist": "Crea un Gist segreto",
"gist_created": "Gist creato", "gist_created": "Gist creato",
"require_github": "Accedi con GitHub per creare un segreto" "require_github": "Accedi con GitHub per creare un Gist segreto"
}, },
"folder": { "folder": {
"created": "Cartella creata", "created": "Cartella creata",
@@ -193,20 +193,20 @@
"renamed": "Cartella rinominata" "renamed": "Cartella rinominata"
}, },
"graphql": { "graphql": {
"mutations": "mutazioni", "mutations": "Mutazioni",
"schema": "Schema", "schema": "Schema",
"subscriptions": "Abbonamenti" "subscriptions": "Sottoscrizioni"
}, },
"header": { "header": {
"account": "Account", "account": "Account",
"install_pwa": "Installa l'applicazione", "install_pwa": "Installa l'applicazione",
"login": "Login", "login": "Accedi",
"save_workspace": "Salva il mio spazio di lavoro" "save_workspace": "Salva il mio spazio di lavoro"
}, },
"helpers": { "helpers": {
"authorization": "L'intestazione dell'autorizzazione verrà generata automaticamente quando invii la richiesta.", "authorization": "L'intestazione di autorizzazione verrà generata automaticamente quando invii la richiesta.",
"generate_documentation_first": "Generare prima la documentazione", "generate_documentation_first": "Generare prima la documentazione",
"network_fail": "Impossibile raggiungere l'endpoint API. Controlla la tua connessione di rete e riprova.", "network_fail": "Impossibile raggiungere l'endpoint API. Controlla la tua connessione di rete o accendi il Proxy Interceptor e riprova.",
"offline": "Sembra che tu sia offline. I dati in questo spazio di lavoro potrebbero non essere aggiornati.", "offline": "Sembra che tu sia offline. I dati in questo spazio di lavoro potrebbero non essere aggiornati.",
"offline_short": "Sembra che tu sia offline.", "offline_short": "Sembra che tu sia offline.",
"post_request_tests": "Gli script di test sono scritti in JavaScript e vengono eseguiti dopo aver ricevuto la risposta.", "post_request_tests": "Gli script di test sono scritti in JavaScript e vengono eseguiti dopo aver ricevuto la risposta.",
@@ -219,42 +219,42 @@
"sidebar": "Nascondi barra laterale" "sidebar": "Nascondi barra laterale"
}, },
"import": { "import": {
"collections": "Importa collezioni", "collections": "Importa raccolte",
"curl": "Importa cURL", "curl": "Importa cURL",
"failed": "Importazione non riuscita", "failed": "Importazione non riuscita",
"from_gist": "Importa da Gist", "from_gist": "Importa da Gist",
"from_my_collections": "Importa da Le mie raccolte", "from_my_collections": "Importa da Le Mie Raccolte",
"gist_url": "Inserisci l'URL principale", "gist_url": "Inserisci l'URL del Gist",
"json": "Importa da JSON", "json": "Importa da JSON",
"title": "Importare" "title": "Importa"
}, },
"layout": { "layout": {
"column": "Vertical layout", "column": "Disposizione verticale",
"row": "Horizontal layout", "row": "Disposizione orizzontale",
"zen_mode": "Modalità Zen" "zen_mode": "Modalità zen"
}, },
"modal": { "modal": {
"collections": "Collezioni", "collections": "Raccolte",
"confirm": "Confermare", "confirm": "Conferma",
"edit_request": "Modifica richiesta", "edit_request": "Modifica richiesta",
"import_export": "Importa/Esporta" "import_export": "Importa/Esporta"
}, },
"mqtt": { "mqtt": {
"communication": "Comunicazione", "communication": "Comunicazione",
"log": "Tronco d'albero", "log": "Log",
"message": "Messaggio", "message": "Messaggio",
"publish": "Pubblicare", "publish": "Pubblica",
"subscribe": "sottoscrivi", "subscribe": "Sottoscrivi",
"topic": "Argomento", "topic": "Argomento",
"topic_name": "Nome argomento", "topic_name": "Nome argomento",
"topic_title": "Pubblica / Sottoscrivi argomento", "topic_title": "Pubblica / Sottoscrivi argomento",
"unsubscribe": "Annulla l'iscrizione", "unsubscribe": "Annulla la sottoscrizione",
"url": "URL" "url": "URL"
}, },
"navigation": { "navigation": {
"doc": "Documenti", "doc": "Documenti",
"graphql": "GraphQL", "graphql": "GraphQL",
"profile": "Profile", "profile": "Profilo",
"realtime": "Tempo reale", "realtime": "Tempo reale",
"rest": "REST", "rest": "REST",
"settings": "Impostazioni" "settings": "Impostazioni"
@@ -263,19 +263,19 @@
"javascript_code": "Codice JavaScript", "javascript_code": "Codice JavaScript",
"learn": "Leggi la documentazione", "learn": "Leggi la documentazione",
"script": "Script di pre-richiesta", "script": "Script di pre-richiesta",
"snippets": "frammenti" "snippets": "Frammenti"
}, },
"profile": { "profile": {
"app_settings": "App Settings", "app_settings": "Impostazioni della app",
"editor": "Editor", "editor": "Autore",
"editor_description": "Editors can add, edit, and delete requests.", "editor_description": "Gli Autori possono aggiungere, modificare e cancellare richieste.",
"no_permission": "You do not have permission to perform this action.", "no_permission": "Non hai i permessi per compiere questa azione.",
"owner": "Owner", "owner": "Proprietario",
"owner_description": "Owners can add, edit, and delete requests, collections and team members.", "owner_description": "I Proprietari possono aggiungere, modificare e cancellare richieste, raccolte e membri del team.",
"roles": "Roles", "roles": "Ruoli",
"roles_description": "Roles are used to control access to the shared collections.", "roles_description": "I ruoli sono usati per controllare l'accesso alle raccolte condivise.",
"viewer": "Viewer", "viewer": "Visualizzatore",
"viewer_description": "Viewers can only view and use requests." "viewer_description": "I Visualizzatori possono soltanto vedere e invocare richieste."
}, },
"remove": { "remove": {
"star": "Rimuovi stella" "star": "Rimuovi stella"
@@ -283,10 +283,10 @@
"request": { "request": {
"added": "Richiesta aggiunta", "added": "Richiesta aggiunta",
"authorization": "Autorizzazione", "authorization": "Autorizzazione",
"body": "Richiedi corpo", "body": "Corpo della richiesta",
"choose_language": "Scegli la lingua", "choose_language": "Scegli la lingua",
"content_type": "Tipo di contenuto", "content_type": "Tipo di contenuto (Content Type)",
"copy_link": "Copia link", "copy_link": "Copia collegamento",
"duration": "Durata", "duration": "Durata",
"enter_curl": "Inserisci cURL", "enter_curl": "Inserisci cURL",
"generate_code": "Genera codice", "generate_code": "Genera codice",
@@ -295,78 +295,78 @@
"invalid_name": "Si prega di fornire un nome per la richiesta", "invalid_name": "Si prega di fornire un nome per la richiesta",
"method": "Metodo", "method": "Metodo",
"name": "Nome richiesta", "name": "Nome richiesta",
"parameter_list": "Parametri di query", "parameter_list": "Parametri della query",
"parameters": "Parametri", "parameters": "Parametri",
"payload": "Carico utile", "payload": "Contenuto (Payload)",
"query": "domanda", "query": "Query",
"raw_body": "Corpo della richiesta grezza", "raw_body": "Corpo della richiesta non formattato",
"renamed": "Richiesta rinominata", "renamed": "Richiesta rinominata",
"run": "Correre", "run": "Esegui",
"save": "Salva", "save": "Salva",
"save_as": "Salva come", "save_as": "Salva come",
"saved": "Richiesta salvata", "saved": "Richiesta salvata",
"share": "Condividere", "share": "Condividi",
"title": "Richiesta", "title": "Richiesta",
"type": "Tipo di richiesta", "type": "Tipo di richiesta",
"url": "URL", "url": "URL",
"variables": "Variabili" "variables": "Variabili"
}, },
"response": { "response": {
"body": "Corpo di risposta", "body": "Corpo della risposta",
"headers": "intestazioni", "headers": "Intestazioni",
"html": "HTML", "html": "HTML",
"image": "Immagine", "image": "Immagine",
"json": "JSON", "json": "JSON",
"preview_html": "Anteprima HTML", "preview_html": "Anteprima HTML",
"raw": "Crudo", "raw": "Non formattato",
"size": "Taglia", "size": "Dimensione",
"status": "Stato", "status": "Stato",
"time": "Volta", "time": "Tempo impiegato",
"title": "Risposta", "title": "Risposta",
"waiting_for_connection": "in attesa di connessione", "waiting_for_connection": "In attesa di connessione",
"xml": "XML" "xml": "XML"
}, },
"settings": { "settings": {
"accent_color": "Colore accento", "accent_color": "Colore in risalto",
"account": "Account", "account": "Account",
"account_description": "Personalizza le impostazioni del tuo account.", "account_description": "Personalizza le impostazioni del tuo account.",
"account_email_description": "Il tuo indirizzo email principale.", "account_email_description": "Il tuo indirizzo email principale.",
"account_name_description": "Questo è il tuo nome visualizzato.", "account_name_description": "Questo è il tuo nome mostrato.",
"background": "Sfondo", "background": "Sfondo",
"black_mode": "Nero", "black_mode": "Nero",
"change_font_size": "Cambiare la dimensione del font", "change_font_size": "Cambia la dimensione dei caratteri",
"choose_language": "Scegli la lingua", "choose_language": "Scegli la lingua",
"dark_mode": "Buio", "dark_mode": "Scuro",
"expand_navigation": "Expand navigation", "expand_navigation": "Espandi navigazione",
"experiments": "esperimenti", "experiments": "Sperimentale",
"experiments_notice": "Questa è una raccolta di esperimenti su cui stiamo lavorando che potrebbero rivelarsi utili, divertenti, entrambi o nessuno dei due. Non sono definitivi e potrebbero non essere stabili, quindi se succede qualcosa di eccessivamente strano, niente panico. Spegni solo quella dannata cosa. Scherzi a parte,", "experiments_notice": "Questa è una raccolta di esperimenti su cui stiamo lavorando che potrebbero rivelarsi utili, divertenti, entrambi o nessuno dei due. Non sono definitivi e potrebbero non essere stabili, quindi se succede qualcosa di eccessivamente strano, niente panico. Basta solo disabilitare quella dannata cosa. Scherzi a parte, ",
"extension_ver_not_reported": "Non riportato", "extension_ver_not_reported": "Non riportato",
"extension_version": "Versione di estensione", "extension_version": "Versione dell'estensione",
"extensions": "Estensioni", "extensions": "Estensioni",
"extensions_use_toggle": "Utilizza l'estensione del browser per inviare richieste (se presente)", "extensions_use_toggle": "Utilizza l'estensione del browser per inviare richieste (se presente)",
"font_size": "Dimensione del font", "font_size": "Dimensione dei caratteri",
"font_size_large": "Grande", "font_size_large": "Grande",
"font_size_medium": "medio", "font_size_medium": "Medio",
"font_size_small": "Piccolo", "font_size_small": "Piccolo",
"interceptor": "Intercettore", "interceptor": "Interceptor",
"interceptor_description": "Middleware tra applicazione e API.", "interceptor_description": "Middleware tra applicazione e API.",
"language": "Lingua", "language": "Lingua",
"light_mode": "Leggero", "light_mode": "Chiaro",
"official_proxy_hosting": "Il proxy ufficiale è ospitato da Hoppscotch.", "official_proxy_hosting": "Il proxy ufficiale è ospitato da Hoppscotch.",
"profile": "Profile", "profile": "Profilo",
"profile_description": "Update your profile details", "profile_description": "Aggiorna i dettagli del tuo profilo",
"profile_name": "Profile name", "profile_name": "Nome del profilo",
"proxy": "proxy", "proxy": "Proxy",
"proxy_url": "URL proxy", "proxy_url": "URL del proxy",
"proxy_use_toggle": "Usa il middleware proxy per inviare richieste", "proxy_use_toggle": "Usa il middleware proxy per inviare richieste",
"read_the": "Leggi il", "read_the": "Leggi il",
"reset_default": "Riportare alle condizioni originali", "reset_default": "Riporta alle impostazioni originali",
"sidebar_on_left": "Sidebar on left", "sidebar_on_left": "Barra laterale a sinistra",
"sync": "Sincronizzare", "sync": "Sincronizza",
"sync_collections": "Collezioni", "sync_collections": "Raccolte",
"sync_description": "Queste impostazioni sono sincronizzate con il cloud.", "sync_description": "Queste impostazioni sono sincronizzate con il cloud.",
"sync_environments": "Ambienti", "sync_environments": "Ambienti",
"sync_history": "Storia", "sync_history": "Cronologia",
"system_mode": "Sistema", "system_mode": "Sistema",
"telemetry": "Telemetria", "telemetry": "Telemetria",
"telemetry_helps_us": "La telemetria ci aiuta a personalizzare le nostre operazioni e a offrirti la migliore esperienza.", "telemetry_helps_us": "La telemetria ci aiuta a personalizzare le nostre operazioni e a offrirti la migliore esperienza.",
@@ -392,57 +392,57 @@
"documentation": "Vai alla pagina della documentazione", "documentation": "Vai alla pagina della documentazione",
"forward": "Vai alla pagina successiva", "forward": "Vai alla pagina successiva",
"graphql": "Vai alla pagina GraphQL", "graphql": "Vai alla pagina GraphQL",
"realtime": "Vai alla pagina in tempo reale", "realtime": "Vai alla pagina Real Time",
"rest": "Vai alla pagina REST", "rest": "Vai alla pagina REST",
"settings": "Vai alla pagina Impostazioni", "settings": "Vai alla pagina Impostazioni",
"title": "Navigazione" "title": "Navigazione"
}, },
"request": { "request": {
"copy_request_link": "Copia link richiesta", "copy_request_link": "Copia il link alla richiesta",
"delete_method": "Seleziona il metodo ELIMINA", "delete_method": "Seleziona il metodo DELETE",
"get_method": "Seleziona il metodo OTTIENI", "get_method": "Seleziona il metodo GET",
"head_method": "Seleziona il metodo HEAD", "head_method": "Seleziona il metodo HEAD",
"method": "Metodo", "method": "Metodo",
"next_method": "Seleziona il metodo successivo", "next_method": "Seleziona il metodo successivo",
"path": "Il percorso", "path": "Percorso",
"post_method": "Seleziona il metodo POST", "post_method": "Seleziona il metodo POST",
"previous_method": "Seleziona il metodo precedente", "previous_method": "Seleziona il metodo precedente",
"put_method": "Seleziona il metodo PUT", "put_method": "Seleziona il metodo PUT",
"reset_request": "Richiesta di ripristino", "reset_request": "Resetta la richiesta",
"save_to_collections": "Salva nelle raccolte", "save_to_collections": "Salva nelle raccolte",
"send_request": "Invia richiesta", "send_request": "Invia richiesta",
"title": "Richiesta" "title": "Richiesta"
} }
}, },
"show": { "show": {
"code": "Mostra codice", "code": "Mostra il codice",
"more": "Mostra di più", "more": "Mostra di più",
"sidebar": "Mostra barra laterale" "sidebar": "Mostra la barra laterale"
}, },
"socketio": { "socketio": {
"communication": "Comunicazione", "communication": "Comunicazione",
"event_name": "Nome dell'evento", "event_name": "Nome dell'evento",
"events": "Eventi", "events": "Eventi",
"log": "Tronco d'albero", "log": "Log",
"url": "URL" "url": "URL"
}, },
"sse": { "sse": {
"event_type": "Tipo di evento", "event_type": "Tipo di evento",
"log": "Tronco d'albero", "log": "Log",
"url": "URL" "url": "URL"
}, },
"state": { "state": {
"bulk_mode": "Modifica in blocco", "bulk_mode": "Modifica in blocco",
"bulk_mode_placeholder": "Le voci sono separate da newline\nChiavi e valori sono separati da:\nAnteponi // a qualsiasi riga che desideri aggiungere ma mantieni disabilitato", "bulk_mode_placeholder": "Le voci sono separate tramite Invio\nChiavi e valori sono separati da:\nAnteponi // a qualsiasi riga che desideri aggiungere ma lasciare disabilitata",
"cleared": "Cancellato", "cleared": "Cancellato",
"connected": "Collegato", "connected": "Connesso",
"connected_to": "Collegato a {nome}", "connected_to": "Connesso a {nome}",
"connecting_to": "Connessione a {nome}...", "connecting_to": "Connessione a {nome}...",
"copied_to_clipboard": "Copiato negli appunti", "copied_to_clipboard": "Copiato negli appunti",
"deleted": "Eliminato", "deleted": "Eliminato",
"deprecated": "DEPRECATO", "deprecated": "DEPRECATO",
"disabled": "Disabilitato", "disabled": "Disabilitato",
"disconnected": "disconnesso", "disconnected": "Disconnesso",
"disconnected_from": "Disconnesso da {name}", "disconnected_from": "Disconnesso da {name}",
"docs_generated": "Documentazione generata", "docs_generated": "Documentazione generata",
"download_started": "Download avviato", "download_started": "Download avviato",
@@ -450,19 +450,19 @@
"file_imported": "File importato", "file_imported": "File importato",
"finished_in": "Finito in {duration}ms", "finished_in": "Finito in {duration}ms",
"history_deleted": "Cronologia cancellata", "history_deleted": "Cronologia cancellata",
"linewrap": "Avvolgere le linee", "linewrap": "Testo a capo",
"loading": "Caricamento in corso...", "loading": "Caricamento in corso...",
"none": "Nessuno", "none": "Nessuno",
"nothing_found": "Niente trovato per", "nothing_found": "Non è stato trovato nulla per",
"waiting_send_request": "In attesa di inviare richiesta" "waiting_send_request": "In attesa di inviare la richiesta"
}, },
"support": { "support": {
"changelog": "Maggiori informazioni sulle ultime versioni", "changelog": "Maggiori informazioni sulle ultime versioni",
"chat": "Domande? Chatta con noi!", "chat": "Domande? Chatta con noi!",
"community": "Fai domande e aiuta gli altri", "community": "Fai domande e aiuta gli altri",
"documentation": "Leggi di più su Hoppscotch", "documentation": "Maggiori informazioni su Hoppscotch",
"forum": "Fai domande e ottieni risposte", "forum": "Fai domande e ottieni risposte",
"shortcuts": "Sfoglia l'app più velocemente", "shortcuts": "Naviga nella app più velocemente",
"team": "Mettiti in contatto con il team", "team": "Mettiti in contatto con il team",
"title": "Supporto", "title": "Supporto",
"twitter": "Seguici su Twitter" "twitter": "Seguici su Twitter"
@@ -470,84 +470,84 @@
"tab": { "tab": {
"authorization": "Autorizzazione", "authorization": "Autorizzazione",
"body": "Corpo", "body": "Corpo",
"collections": "Collezioni", "collections": "Raccolte",
"documentation": "Documentazione", "documentation": "Documentazione",
"headers": "intestazioni", "headers": "Intestazioni",
"history": "Storia", "history": "Cronologia",
"mqtt": "MQTT", "mqtt": "MQTT",
"parameters": "Parametri", "parameters": "Parametri",
"pre_request_script": "Script di pre-richiesta", "pre_request_script": "Script di pre-richiesta",
"queries": "Interrogazioni", "queries": "Query",
"query": "domanda", "query": "Query",
"schema": "Schema", "schema": "Schema",
"socketio": "Presa.IO", "socketio": "Socket.IO",
"sse": "SSE", "sse": "SSE",
"tests": "test", "tests": "Test",
"types": "tipi", "types": "Tipi",
"variables": "Variabili", "variables": "Variabili",
"websocket": "WebSocket" "websocket": "WebSocket"
}, },
"team": { "team": {
"already_member": "You are already a member of this team. Contact your team owner.", "already_member": "Sei già membro di questo team. Contatta il proprietario del team.",
"create_new": "Crea una nuova squadra", "create_new": "Crea una nuovo team",
"deleted": "Squadra eliminata", "deleted": "Team eliminato",
"edit": "Modifica squadra", "edit": "Modifica team",
"email": "E-mail", "email": "E-mail",
"email_do_not_match": "Email doesn't match with your account details. Contact your team owner.", "email_do_not_match": "L'indirizzo email non corrisponde a quella del tuo account. Contatta il proprietario del team.",
"exit": "Esci dalla squadra", "exit": "Lascia il team",
"exit_disabled": "Solo il proprietario non può uscire dalla squadra", "exit_disabled": "Solo il proprietario non può lasciare il team",
"invalid_email_format": "Il formato dell'email non è valido", "invalid_email_format": "Il formato dell'email non è valido",
"invalid_id": "Invalid team ID. Contact your team owner.", "invalid_id": "L'ID del team non è valido. Contatta il proprietario del team.",
"invalid_invite_link": "Invalid invite link", "invalid_invite_link": "Il link di invito non è valido",
"invalid_invite_link_description": "The link you followed is invalid. Contact your team owner.", "invalid_invite_link_description": "Il link che hai seguito non è valido. Contatta il proprietario del team.",
"invalid_member_permission": "Si prega di fornire un permesso valido al membro del team", "invalid_member_permission": "Si prega di fornire un permesso valido al membro del team",
"invite": "Invite", "invite": "Invita",
"invite_more": "Invite more", "invite_more": "Invita altri",
"invite_tooltip": "Invite people to this workspace", "invite_tooltip": "Invita persone in questo spazio di lavoro",
"invited_to_team": "{owner} invited you to join {team}", "invited_to_team": "{owner} ti ha invitato ad unirti al team {team}",
"join": "Invitation accepted", "join": "Invito accettato",
"join_beta": "Partecipa al programma beta per accedere ai team.", "join_beta": "Partecipa al programma beta per accedere ai team.",
"join_team": "Join {team}", "join_team": "Unisciti al team {team}",
"joined_team": "You have joined {team}", "joined_team": "Sei parte del team {team}",
"joined_team_description": "You are now a member of this team", "joined_team_description": "Ora sei un membro di questo team",
"left": "Hai lasciato la squadra", "left": "Hai lasciato il team",
"login_to_continue": "Login to continue", "login_to_continue": "Accedi per continuare",
"login_to_continue_description": "You need to be logged in to join a team.", "login_to_continue_description": "Devi aver effettuato l'accesso per unirti a un team.",
"logout_and_try_again": "Logout and sign in with another account", "logout_and_try_again": "Disconnettiti ed accedi con un altro account",
"member_has_invite": "This email ID already has an invite. Contact your team owner.", "member_has_invite": "Questo ID email ha già un invito. Contatta il proprietario del team.",
"member_not_found": "Member not found. Contact your team owner.", "member_not_found": "Membro non trovato. Contatta il proprietario del team.",
"member_removed": "Utente rimosso", "member_removed": "Utente rimosso",
"member_role_updated": "Ruoli utente aggiornati", "member_role_updated": "Ruoli dell'utente aggiornati",
"members": "Membri", "members": "Membri",
"name_length_insufficient": "Il nome della squadra deve essere lungo almeno 6 caratteri", "name_length_insufficient": "Il nome del team deve essere lungo almeno 6 caratteri",
"name_updated": "Team name updated", "name_updated": "Nome del team aggiornato",
"new": "Nuova squadra", "new": "Nuovo team",
"new_created": "Nuova squadra creata", "new_created": "Nuovo team creato",
"new_name": "La mia nuova squadra", "new_name": "Il mio nuovo team",
"no_access": "Non hai accesso in modifica a queste raccolte", "no_access": "Non sei autorizzato a modificare queste raccolte",
"no_invite_found": "Invitation not found. Contact your team owner.", "no_invite_found": "Invito non trovato. Contatta il proprietario del team.",
"not_valid_viewer": "You are not a valid viewer. Contact your team owner.", "not_valid_viewer": "Non sei autorizzato a visualizzare. Contatta il proprietario del team.",
"pending_invites": "Pending invites", "pending_invites": "Inviti pendenti",
"permissions": "Permessi", "permissions": "Permessi",
"saved": "Squadra salvata", "saved": "Team salvato",
"select_a_team": "Select a team", "select_a_team": "Seleziona un team",
"title": "Squadre", "title": "Team",
"we_sent_invite_link": "We sent an invite link to all invitees!", "we_sent_invite_link": "Abbiamo inviato un link di invito a tutti gli invitati!",
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the team." "we_sent_invite_link_description": "Chiedi a tutti gli invitati di controllare la loro casella email. Cliccando sul link possono entrare nel team."
}, },
"test": { "test": {
"failed": "test failed", "failed": "Test fallito",
"javascript_code": "Codice JavaScript", "javascript_code": "Codice JavaScript",
"learn": "Leggi la documentazione", "learn": "Leggi la documentazione",
"passed": "test passed", "passed": "Test superato",
"report": "Rapporto di prova", "report": "Report del test",
"results": "Risultati del test", "results": "Risultati del test",
"script": "sceneggiatura", "script": "Script",
"snippets": "frammenti" "snippets": "Frammenti"
}, },
"websocket": { "websocket": {
"communication": "Comunicazione", "communication": "Comunicazione",
"log": "Tronco d'albero", "log": "Log",
"message": "Messaggio", "message": "Messaggio",
"protocols": "Protocolli", "protocols": "Protocolli",
"url": "URL" "url": "URL"

View File

@@ -8,29 +8,29 @@
"copy": "Копировать", "copy": "Копировать",
"delete": "Удалить", "delete": "Удалить",
"disconnect": "Отключить", "disconnect": "Отключить",
"dismiss": "Увольнять", "dismiss": "Отклонить",
"download_file": "Скачать файл", "download_file": "Скачать файл",
"duplicate": "Duplicate", "duplicate": "Дублировать",
"edit": "Редактировать", "edit": "Редактировать",
"go_back": "Вернись", "go_back": "Вернуться",
"label": "Этикетка", "label": "Этикетка",
"learn_more": "Выучить больше", "learn_more": "Узнать больше",
"more": "Более", "more": "Больше",
"new": "Новый", "new": "Новый",
"no": "Нет", "no": "Нет",
"preserve_current": "Сохранить текущий", "preserve_current": "Сохранить текущий",
"prettify": "Украсить", "prettify": "Форматировать",
"remove": "Удалять", "remove": "Удалить",
"replace_current": "Заменить текущий", "replace_current": "Заменить текущий",
"replace_json": "Заменить на JSON", "replace_json": "Заменить на JSON",
"restore": "Восстановить", "restore": "Восстановить",
"save": "Сохранить", "save": "Сохранить",
"search": "Поиск", "search": "Поиск",
"send": "послать", "send": "Отправить",
"start": "Начинать", "start": "Начать",
"stop": "Стоп", "stop": "Стоп",
"turn_off": "Выключить", "turn_off": "Выключить",
"turn_on": "Включи", "turn_on": "Включить",
"undo": "Отменить", "undo": "Отменить",
"yes": "да" "yes": "да"
}, },
@@ -52,7 +52,7 @@
"join_discord_community": "Присоединяйтесь к нашему сообществу Discord", "join_discord_community": "Присоединяйтесь к нашему сообществу Discord",
"keyboard_shortcuts": "Горячие клавиши", "keyboard_shortcuts": "Горячие клавиши",
"name": "Hoppscotch", "name": "Hoppscotch",
"new_version_found": "Найдена новая версия. Обновите, чтобы обновить.", "new_version_found": "Найдена новая версия. Перезагрузите для обновления.",
"proxy_privacy_policy": "Политика конфиденциальности прокси", "proxy_privacy_policy": "Политика конфиденциальности прокси",
"reload": "Перезагрузить", "reload": "Перезагрузить",
"search": "Поиск", "search": "Поиск",
@@ -65,7 +65,7 @@
"type_a_command_search": "Введите команду или выполните поиск…", "type_a_command_search": "Введите команду или выполните поиск…",
"version": "v2.0", "version": "v2.0",
"we_use_cookies": "Мы используем куки", "we_use_cookies": "Мы используем куки",
"whats_new": "Какие новости?", "whats_new": "Что нового?",
"wiki": "Вики" "wiki": "Вики"
}, },
"auth": { "auth": {
@@ -241,7 +241,7 @@
}, },
"mqtt": { "mqtt": {
"communication": "Коммуникация", "communication": "Коммуникация",
"log": "Бревно", "log": "Лог",
"message": "Сообщение", "message": "Сообщение",
"publish": "Публиковать", "publish": "Публиковать",
"subscribe": "Подписаться", "subscribe": "Подписаться",
@@ -332,7 +332,7 @@
"account_description": "Настройте параметры своей учетной записи.", "account_description": "Настройте параметры своей учетной записи.",
"account_email_description": "Ваш основной адрес электронной почты.", "account_email_description": "Ваш основной адрес электронной почты.",
"account_name_description": "Это ваше отображаемое имя.", "account_name_description": "Это ваше отображаемое имя.",
"background": "Задний план", "background": "Задний фон",
"black_mode": "Чернить", "black_mode": "Чернить",
"change_font_size": "Изменить размер шрифта", "change_font_size": "Изменить размер шрифта",
"choose_language": "Выберите язык", "choose_language": "Выберите язык",
@@ -353,7 +353,7 @@
"language": "Язык", "language": "Язык",
"light_mode": "Свет", "light_mode": "Свет",
"official_proxy_hosting": "Официальный прокси-сервер размещен на Hoppscotch.", "official_proxy_hosting": "Официальный прокси-сервер размещен на Hoppscotch.",
"profile": "Profile", "profile": "Профиль",
"profile_description": "Update your profile details", "profile_description": "Update your profile details",
"profile_name": "Profile name", "profile_name": "Profile name",
"proxy": "Прокси", "proxy": "Прокси",
@@ -404,7 +404,7 @@
"head_method": "Выберите метод HEAD", "head_method": "Выберите метод HEAD",
"method": "Методика", "method": "Методика",
"next_method": "Выберите следующий метод", "next_method": "Выберите следующий метод",
"path": "Дорожка", "path": "Путь",
"post_method": "Выберите метод POST", "post_method": "Выберите метод POST",
"previous_method": "Выбрать предыдущий метод", "previous_method": "Выбрать предыдущий метод",
"put_method": "Выберите метод PUT", "put_method": "Выберите метод PUT",
@@ -423,12 +423,12 @@
"communication": "Коммуникация", "communication": "Коммуникация",
"event_name": "Название события", "event_name": "Название события",
"events": "События", "events": "События",
"log": "Бревно", "log": "Лог",
"url": "URL" "url": "URL"
}, },
"sse": { "sse": {
"event_type": "Тип события", "event_type": "Тип события",
"log": "Бревно", "log": "Лог",
"url": "URL" "url": "URL"
}, },
"state": { "state": {
@@ -511,7 +511,7 @@
"joined_team": "You have joined {team}", "joined_team": "You have joined {team}",
"joined_team_description": "You are now a member of this team", "joined_team_description": "You are now a member of this team",
"left": "Ты покинул команду", "left": "Ты покинул команду",
"login_to_continue": "Login to continue", "login_to_continue": "Войдите для продолжения",
"login_to_continue_description": "You need to be logged in to join a team.", "login_to_continue_description": "You need to be logged in to join a team.",
"logout_and_try_again": "Logout and sign in with another account", "logout_and_try_again": "Logout and sign in with another account",
"member_has_invite": "This email ID already has an invite. Contact your team owner.", "member_has_invite": "This email ID already has an invite. Contact your team owner.",
@@ -536,18 +536,18 @@
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the team." "we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the team."
}, },
"test": { "test": {
"failed": "test failed", "failed": "Тест не пройден",
"javascript_code": "Код JavaScript", "javascript_code": "Код JavaScript",
"learn": "Читать документацию", "learn": "Читать документацию",
"passed": "test passed", "passed": "Тест пройден",
"report": "Отчет об испытаниях", "report": "Отчет об испытаниях",
"results": "Результаты теста", "results": "Результаты теста",
"script": "Сценарий", "script": "Скрипт",
"snippets": "Фрагменты" "snippets": "Фрагменты"
}, },
"websocket": { "websocket": {
"communication": "Коммуникация", "communication": "Коммуникация",
"log": "Бревно", "log": "Лог",
"message": "Сообщение", "message": "Сообщение",
"protocols": "Протоколы", "protocols": "Протоколы",
"url": "URL" "url": "URL"

View File

@@ -64,12 +64,12 @@
"@urql/core": "^2.3.5", "@urql/core": "^2.3.5",
"@urql/exchange-auth": "^0.1.6", "@urql/exchange-auth": "^0.1.6",
"@urql/exchange-graphcache": "^4.3.5", "@urql/exchange-graphcache": "^4.3.5",
"acorn": "^8.5.0", "acorn": "^8.6.0",
"acorn-walk": "^8.2.0", "acorn-walk": "^8.2.0",
"axios": "^0.24.0", "axios": "^0.24.0",
"core-js": "^3.19.1", "core-js": "^3.19.1",
"esprima": "^4.0.1", "esprima": "^4.0.1",
"firebase": "^9.4.1", "firebase": "^9.5.0",
"fp-ts": "^2.11.5", "fp-ts": "^2.11.5",
"fuse.js": "^6.4.6", "fuse.js": "^6.4.6",
"graphql": "^15.7.2", "graphql": "^15.7.2",
@@ -92,7 +92,7 @@
"subscriptions-transport-ws": "^0.11.0", "subscriptions-transport-ws": "^0.11.0",
"tern": "^0.24.3", "tern": "^0.24.3",
"uuid": "8.3.2", "uuid": "8.3.2",
"vue-apollo": "^3.0.8", "vue-apollo": "^3.1.0",
"vue-cli-plugin-apollo": "^0.22.2", "vue-cli-plugin-apollo": "^0.22.2",
"vue-functional-data-merge": "^3.1.0", "vue-functional-data-merge": "^3.1.0",
"vue-github-button": "^1.3.0", "vue-github-button": "^1.3.0",
@@ -104,7 +104,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.16.0", "@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.0", "@babel/preset-env": "^7.16.4",
"@graphql-codegen/add": "^3.1.0", "@graphql-codegen/add": "^3.1.0",
"@graphql-codegen/cli": "2.2.2", "@graphql-codegen/cli": "2.2.2",
"@graphql-codegen/typed-document-node": "^2.2.0", "@graphql-codegen/typed-document-node": "^2.2.0",
@@ -132,14 +132,14 @@
"@types/splitpanes": "^2.2.1", "@types/splitpanes": "^2.2.1",
"@urql/devtools": "^2.0.3", "@urql/devtools": "^2.0.3",
"@vue/runtime-dom": "^3.2.22", "@vue/runtime-dom": "^3.2.22",
"@vue/test-utils": "^1.2.2", "@vue/test-utils": "^1.3.0",
"babel-core": "^7.0.0-bridge.0", "babel-core": "^7.0.0-bridge.0",
"babel-jest": "^27.3.1", "babel-jest": "^27.3.1",
"eslint": "^8.2.0", "eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^3.0.0", "eslint-plugin-nuxt": "^3.0.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.1.1",
"jest": "^27.3.1", "jest": "^27.3.1",
"jest-serializer-vue": "^2.0.2", "jest-serializer-vue": "^2.0.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
@@ -151,7 +151,7 @@
"stylelint": "^14.1.0", "stylelint": "^14.1.0",
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^24.0.0", "stylelint-config-standard": "^24.0.0",
"stylelint-config-standard-scss": "^2.0.1", "stylelint-config-standard-scss": "^3.0.0",
"ts-jest": "^27.0.7", "ts-jest": "^27.0.7",
"typescript": "^4.4.4", "typescript": "^4.4.4",
"vue-jest": "^3.0.7", "vue-jest": "^3.0.7",

View File

@@ -230,15 +230,11 @@ export default defineComponent({
} }
) )
.then((res) => { .then((res) => {
this.$toast.success(this.$t("export.gist_created"), { this.$toast.success(this.$t("export.gist_created"))
icon: "done",
})
window.open(res.html_url) window.open(res.html_url)
}) })
.catch((e) => { .catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
console.error(e) console.error(e)
}) })
}, },
@@ -251,13 +247,9 @@ export default defineComponent({
this.collectionJSON = target.result this.collectionJSON = target.result
} }
reader.readAsText(file) reader.readAsText(file)
this.$toast.success(this.$t("state.file_imported"), { this.$toast.success(this.$t("state.file_imported"))
icon: "attach_file",
})
} else { } else {
this.$toast.error(this.$t("action.choose_file"), { this.$toast.error(this.$t("action.choose_file"))
icon: "attach_file",
})
} }
this.$refs.collectionUpload.value = "" this.$refs.collectionUpload.value = ""
}, },
@@ -288,9 +280,7 @@ export default defineComponent({
this.items = JSON.parse(this.collectionJSON) this.items = JSON.parse(this.collectionJSON)
this.assignIDs(this.items, "", "#") this.assignIDs(this.items, "", "#")
this.$toast.clear() this.$toast.clear()
this.$toast.success(this.$t("state.docs_generated"), { this.$toast.success(this.$t("state.docs_generated"))
icon: "book",
})
const docsMarkdown = Mustache.render( const docsMarkdown = Mustache.render(
DocsTemplate, DocsTemplate,
{ {
@@ -325,9 +315,7 @@ export default defineComponent({
this.docsMarkdown = docsMarkdown.replace(/^\s*[\r\n]/gm, "\n\n") this.docsMarkdown = docsMarkdown.replace(/^\s*[\r\n]/gm, "\n\n")
} catch (e) { } catch (e) {
console.error(e) console.error(e)
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(this.$t("error.something_went_wrong"))
icon: "error_outline",
})
} }
}, },

View File

@@ -238,9 +238,7 @@ export default defineComponent({
TE.matchW( TE.matchW(
() => { () => {
this.loading = false this.loading = false
this.$toast.error(this.$t("error.something_went_wrong"), { this.$toast.error(`${this.$t("error.something_went_wrong")}`)
icon: "error_outline",
})
}, },
() => { () => {
this.joinTeamSuccess = true this.joinTeamSuccess = true

View File

@@ -17,13 +17,13 @@
w-24 w-24
inline-flex inline-flex
" "
:alt="$t('empty.parameters')" :alt="`${t('empty.parameters')}`"
/> />
<p class="text-center pb-4 text-secondaryLight"> <p class="text-center pb-4 text-secondaryLight">
{{ $t("empty.profile") }} {{ t("empty.profile") }}
</p> </p>
<ButtonPrimary <ButtonPrimary
:label="$t('auth.login')" :label="t('auth.login')"
class="mb-4" class="mb-4"
@click.native="showLogin = true" @click.native="showLogin = true"
/> />
@@ -44,7 +44,7 @@
<SmartIcon v-else name="user" class="svg-icons" /> <SmartIcon v-else name="user" class="svg-icons" />
<div class="ml-4"> <div class="ml-4">
<label class="heading"> <label class="heading">
{{ currentUser.displayName || $t("state.nothing_found") }} {{ currentUser.displayName || t("state.nothing_found") }}
</label> </label>
<p class="flex text-secondaryLight items-center"> <p class="flex text-secondaryLight items-center">
{{ currentUser.email }} {{ currentUser.email }}
@@ -61,7 +61,7 @@
<SmartItem <SmartItem
to="/settings" to="/settings"
svg="settings" svg="settings"
:label="$t('profile.app_settings')" :label="t('profile.app_settings')"
outline outline
/> />
</div> </div>
@@ -71,19 +71,19 @@
<SmartTabs> <SmartTabs>
<SmartTab <SmartTab
:id="'sync'" :id="'sync'"
:label="$t('settings.account')" :label="t('settings.account')"
:selected="true" :selected="true"
> >
<section class="p-4"> <section class="p-4">
<h4 class="font-semibold text-secondaryDark"> <h4 class="font-semibold text-secondaryDark">
{{ $t("settings.profile") }} {{ t("settings.profile") }}
</h4> </h4>
<div class="mt-1 text-secondaryLight"> <div class="mt-1 text-secondaryLight">
{{ $t("settings.profile_description") }} {{ t("settings.profile_description") }}
</div> </div>
<div class="py-4"> <div class="py-4">
<label for="displayName"> <label for="displayName">
{{ $t("settings.profile_name") }} {{ t("settings.profile_name") }}
</label> </label>
<form <form
class="flex md:max-w-sm mt-2" class="flex md:max-w-sm mt-2"
@@ -93,13 +93,13 @@
id="displayName" id="displayName"
v-model="displayName" v-model="displayName"
class="input" class="input"
:placeholder="$t('settings.profile_name')" :placeholder="`${t('settings.profile_name')}`"
type="text" type="text"
autocomplete="off" autocomplete="off"
required required
/> />
<ButtonPrimary <ButtonPrimary
:label="$t('action.save').toString()" :label="t('action.save')"
class="ml-2 min-w-16" class="ml-2 min-w-16"
type="submit" type="submit"
:loading="updatingDisplayName" :loading="updatingDisplayName"
@@ -109,10 +109,10 @@
</section> </section>
<section class="p-4"> <section class="p-4">
<h4 class="font-semibold text-secondaryDark"> <h4 class="font-semibold text-secondaryDark">
{{ $t("settings.sync") }} {{ t("settings.sync") }}
</h4> </h4>
<div class="mt-1 text-secondaryLight"> <div class="mt-1 text-secondaryLight">
{{ $t("settings.sync_description") }} {{ t("settings.sync_description") }}
</div> </div>
<div class="space-y-4 py-4"> <div class="space-y-4 py-4">
<div class="flex items-center"> <div class="flex items-center">
@@ -120,7 +120,7 @@
:on="SYNC_COLLECTIONS" :on="SYNC_COLLECTIONS"
@change="toggleSetting('syncCollections')" @change="toggleSetting('syncCollections')"
> >
{{ $t("settings.sync_collections") }} {{ t("settings.sync_collections") }}
</SmartToggle> </SmartToggle>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
@@ -128,7 +128,7 @@
:on="SYNC_ENVIRONMENTS" :on="SYNC_ENVIRONMENTS"
@change="toggleSetting('syncEnvironments')" @change="toggleSetting('syncEnvironments')"
> >
{{ $t("settings.sync_environments") }} {{ t("settings.sync_environments") }}
</SmartToggle> </SmartToggle>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
@@ -136,13 +136,13 @@
:on="SYNC_HISTORY" :on="SYNC_HISTORY"
@change="toggleSetting('syncHistory')" @change="toggleSetting('syncHistory')"
> >
{{ $t("settings.sync_history") }} {{ t("settings.sync_history") }}
</SmartToggle> </SmartToggle>
</div> </div>
</div> </div>
</section> </section>
</SmartTab> </SmartTab>
<SmartTab :id="'teams'" :label="$t('team.title')"> <SmartTab :id="'teams'" :label="t('team.title')">
<AppSection label="teams"> <AppSection label="teams">
<Teams :modal="false" /> <Teams :modal="false" />
</AppSection> </AppSection>
@@ -156,21 +156,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { import { ref, useMeta, defineComponent } from "@nuxtjs/composition-api"
ref,
useContext,
useMeta,
defineComponent,
} from "@nuxtjs/composition-api"
import { currentUser$, setDisplayName } from "~/helpers/fb/auth" import { currentUser$, setDisplayName } from "~/helpers/fb/auth"
import { useReadonlyStream } from "~/helpers/utils/composables" import { useReadonlyStream, useI18n } from "~/helpers/utils/composables"
import { toggleSetting, useSetting } from "~/newstore/settings" import { toggleSetting, useSetting } from "~/newstore/settings"
const { const t = useI18n()
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const showLogin = ref(false) const showLogin = ref(false)

Some files were not shown because too many files have changed in this diff Show More