Compare commits
63 Commits
bug/withDe
...
refactor/s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ffc9e3a4d | ||
|
|
75e34feabf | ||
|
|
fe13de2ea0 | ||
|
|
dec26ce2aa | ||
|
|
b0f02fee57 | ||
|
|
02be413eff | ||
|
|
42849e6853 | ||
|
|
e7535d505e | ||
|
|
fb6015ce26 | ||
|
|
f3a38bab3c | ||
|
|
1a1f45401c | ||
|
|
4a43807f34 | ||
|
|
88cc21e3d4 | ||
|
|
ecce830787 | ||
|
|
084039f59f | ||
|
|
0de9f3d8c3 | ||
|
|
4d6d30c92b | ||
|
|
38755bf3e3 | ||
|
|
2884854aab | ||
|
|
d24d07e420 | ||
|
|
cc81242294 | ||
|
|
a508909471 | ||
|
|
475a28b159 | ||
|
|
520ac8ede5 | ||
|
|
2a59557851 | ||
|
|
4089bc288c | ||
|
|
1999819846 | ||
|
|
0bf856291c | ||
|
|
da8c446ad7 | ||
|
|
3614877964 | ||
|
|
85c8171aa8 | ||
|
|
b58278d55e | ||
|
|
b398ed1e90 | ||
|
|
afa750e409 | ||
|
|
fdf12a24ed | ||
|
|
4c5ca1b31d | ||
|
|
bcb9b97b6b | ||
|
|
757294ae38 | ||
|
|
8d4dd8c428 | ||
|
|
508809eba1 | ||
|
|
d0386ef86f | ||
|
|
56cdb79773 | ||
|
|
6ed4211004 | ||
|
|
222f0800d2 | ||
|
|
12a9dd1058 | ||
|
|
4a32fc6180 | ||
|
|
1e08e7f73d | ||
|
|
8b05b063ff | ||
|
|
0bcfeb86ae | ||
|
|
03a056b6c1 | ||
|
|
d57e465806 | ||
|
|
5ab24d1439 | ||
|
|
47661de974 | ||
|
|
26429466e9 | ||
|
|
cad8f3e856 | ||
|
|
1a4eb1fabe | ||
|
|
680f61b7dc | ||
|
|
f602a1e2d3 | ||
|
|
1572ff9e67 | ||
|
|
fe7b236ad9 | ||
|
|
3080af1ea5 | ||
|
|
0f83c8b490 | ||
|
|
7d590ab966 |
57
.github/ISSUE_TEMPLATE/--bug-report.yaml
vendored
Normal 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
|
||||||
28
.github/ISSUE_TEMPLATE/--feature-request.yaml
vendored
Normal 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
|
||||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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
@@ -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
|
||||||
8
.github/ISSUE_TEMPLATE/custom.md
vendored
@@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: Custom issue template
|
|
||||||
about: Describe this issue template's purpose here.
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -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.
|
|
||||||
@@ -3,8 +3,10 @@ FROM node:lts-alpine
|
|||||||
LABEL maintainer="Hoppscotch (support@hoppscotch.io)"
|
LABEL maintainer="Hoppscotch (support@hoppscotch.io)"
|
||||||
|
|
||||||
# Add git as the prebuild target requires it to parse version information
|
# Add git as the prebuild target requires it to parse version information
|
||||||
RUN apk add --update --no-cache \
|
RUN apk add --no-cache --virtual .gyp \
|
||||||
git
|
python3 \
|
||||||
|
make \
|
||||||
|
g++
|
||||||
|
|
||||||
# Create app directory
|
# Create app directory
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#### **Support**
|
#### **Support**
|
||||||
|
|
||||||
[](https://hoppscotch.io/discord) [](https://hoppscotch.io/telegram)
|
[](https://hoppscotch.io/discord) [](https://hoppscotch.io/telegram) [](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
@@ -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.
|
||||||
@@ -9,16 +9,19 @@ Before you start working on a new language, please look through the [open pull r
|
|||||||
if there is no existing translation, you can create a new one by following these steps:
|
if there is no existing translation, you can create a new one by following these steps:
|
||||||
|
|
||||||
1. **[Fork the repository](https://github.com/hoppscotch/hoppscotch/fork).**
|
1. **[Fork the repository](https://github.com/hoppscotch/hoppscotch/fork).**
|
||||||
2. **Create a new branch for your translation.**
|
2. **Checkout the `i18n` branch for latest translations.**
|
||||||
3. **Create target language file in the [`locales`](https://github.com/hoppscotch/hoppscotch/tree/main/packages/hoppscotch-app/locales) directory.**
|
3. **Create a new branch for your translation with base branch `i18n`.**
|
||||||
4. **Copy the contents of the source file [`locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/locales/en.json) to the target language file.**
|
4. **Create target language file in the [`locales`](https://github.com/hoppscotch/hoppscotch/tree/main/packages/hoppscotch-app/locales) directory.**
|
||||||
5. **Translate the strings in the target language file.**
|
5. **Copy the contents of the source file [`locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/locales/en.json) to the target language file.**
|
||||||
6. **Add your language entry to [`languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/languages.json).**
|
6. **Translate the strings in the target language file.**
|
||||||
7. **Save & commit changes.**
|
7. **Add your language entry to [`languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/languages.json).**
|
||||||
8. **Send a pull request.**
|
8. **Save & commit changes.**
|
||||||
|
9. **Send a pull request.**
|
||||||
|
|
||||||
_You may send a pull request before all steps above are complete: e.g., you may want to ask for help with translations, or getting tests to pass. However, your pull request will not be merged until all steps above are complete._
|
_You may send a pull request before all steps above are complete: e.g., you may want to ask for help with translations, or getting tests to pass. However, your pull request will not be merged until all steps above are complete._
|
||||||
|
|
||||||
|
`i18n` branch will be merged into `main` branch once every week.
|
||||||
|
|
||||||
Completing an initial translation of the whole site is a fairly large task. One way to break that task up is to work with other translators through pull requests on your fork. You can also [add collaborators to your fork](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) if you'd like to invite other translators to commit directly to your fork and share responsibility for merging pull requests.
|
Completing an initial translation of the whole site is a fairly large task. One way to break that task up is to work with other translators through pull requests on your fork. You can also [add collaborators to your fork](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) if you'd like to invite other translators to commit directly to your fork and share responsibility for merging pull requests.
|
||||||
|
|
||||||
## Updating a translation
|
## Updating a translation
|
||||||
|
|||||||
@@ -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.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^14.1.0",
|
"@commitlint/cli": "^15.0.0",
|
||||||
"@commitlint/config-conventional": "^14.1.0"
|
"@commitlint/config-conventional": "^15.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
},
|
},
|
||||||
@@ -15,17 +16,17 @@
|
|||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/highlight": "^0.19.0",
|
"@codemirror/highlight": "^0.19.6",
|
||||||
"@codemirror/language": "^0.19.0",
|
"@codemirror/language": "^0.19.7",
|
||||||
"@lezer/lr": "^0.15.0"
|
"@lezer/lr": "^0.15.5"
|
||||||
},
|
},
|
||||||
"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.2",
|
||||||
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path d="M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z"></path>
|
|
||||||
<line x1="9" y1="14" x2="15" y2="14"></line>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 325 B |
@@ -1,4 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<polyline points="9 10 4 15 9 20"></polyline>
|
<path d="M6 17l2-5h14l-3 8a2 2 0 01-2 1H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h7a2 2 0 012 2v4"></path>
|
||||||
<path d="M20 4v7a4 4 0 01-4 4H4"></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 291 B |
@@ -1,10 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<line x1="12" y1="2" x2="12" y2="6"></line>
|
<path d="M21 12a9 9 0 11-6.219-8.56"></path>
|
||||||
<line x1="12" y1="18" x2="12" y2="22"></line>
|
|
||||||
<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>
|
|
||||||
<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>
|
|
||||||
<line x1="2" y1="12" x2="6" y2="12"></line>
|
|
||||||
<line x1="18" y1="12" x2="22" y2="12"></line>
|
|
||||||
<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>
|
|
||||||
<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 608 B After Width: | Height: | Size: 235 B |
25
packages/hoppscotch-app/assets/icons/logo.svg
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 16C0 7.16344 7.16344 0 16 0H112C120.837 0 128 7.16344 128 16V112C128 120.837 120.837 128 112 128H16C7.16344 128 0 120.837 0 112V16Z" fill="#10B981"/>
|
||||||
|
<ellipse cx="49.94" cy="39.46" rx="2.5" ry="2.5" fill="white" fill-opacity="0.75"/>
|
||||||
|
<ellipse cx="65.44" cy="40.46" rx="3" ry="3" fill="white" fill-opacity="0.75"/>
|
||||||
|
<ellipse cx="80.44" cy="44.46" rx="2.50001" ry="2.5" fill="white" fill-opacity="0.75"/>
|
||||||
|
<path d="M86.7407 58.919C87.2596 55.7445 77.0229 51.468 63.9989 49.3955C50.9765 47.3216 39.8979 48.2292 39.379 51.4037C39.3147 51.6624 39.379 51.8568 39.4448 52.1169C39.1203 51.9868 20.2663 104.92 20.2663 104.92H91.5347C91.5347 104.92 87.1295 59.5665 86.482 59.5665C86.6107 59.3735 86.7407 59.1792 86.7407 58.919Z" fill="url(#paint0_linear_202_73)"/>
|
||||||
|
<path d="M79.2254 56.8465C78.9009 58.8547 71.5157 59.3078 62.6397 57.9471C53.828 56.5221 46.8943 53.7363 47.2188 51.7925C47.3489 51.145 48.1907 50.6261 49.5514 50.3675C45.0162 50.5618 42.0361 51.4037 41.7774 52.8287C41.3887 55.4858 50.4591 59.1134 62.1208 60.993C73.7826 62.8711 83.5662 62.1593 84.0193 59.5679C84.2795 58.0114 81.6867 56.3277 77.4116 54.7083C78.6422 55.4201 79.2897 56.1976 79.2254 56.8465Z" fill="#A7F3D0" fill-opacity="0.5"/>
|
||||||
|
<path d="M83.8892 39.3532C83.1131 31.319 76.9571 24.5155 68.6642 23.2205C60.3713 21.9241 52.5315 26.4593 49.227 33.7803C54.5397 34.1047 60.2412 34.6879 66.2029 35.6598C72.5519 36.6318 78.5122 37.9282 83.8892 39.3532Z" fill="url(#paint1_radial_202_73)"/>
|
||||||
|
<path d="M19.0356 39.5005C18.3882 43.4526 26.6153 48.3123 39.5091 52.2643C39.4448 52.0042 39.4448 51.8098 39.4448 51.5511C39.9622 48.3766 50.9765 47.469 64.0647 49.5429C77.1515 51.6154 87.3239 55.8919 86.805 59.0664C86.7407 59.3266 86.6764 59.5209 86.5463 59.7139C99.9576 59.9083 109.288 57.8358 109.936 53.8837C110.842 47.8577 91.2759 39.7592 66.203 35.8072C41.0642 31.8552 19.9418 33.4746 19.0356 39.5005ZM47.9321 39.1761C48.1264 38.1398 49.0984 37.3623 50.1346 37.5567C51.1709 37.7511 51.9484 38.723 51.754 39.7592C51.6239 40.7955 50.5877 41.5087 49.5515 41.3786C48.5152 41.1843 47.7377 40.2123 47.9321 39.1761ZM62.8984 40.2123C63.0928 38.7873 64.4535 37.8154 65.8785 38.0755C67.3035 38.2699 68.2754 39.6292 68.0168 41.0556C67.7566 42.4164 66.3973 43.3883 65.0366 43.1939C63.6102 42.9995 62.6382 41.6388 62.8984 40.2123ZM78.6423 44.0358C78.8366 42.9995 79.8086 42.222 80.8448 42.4164C81.8811 42.6107 82.6586 43.5827 82.4642 44.6189C82.3356 45.6552 81.2979 46.4327 80.2617 46.2383C79.2254 46.0439 78.4479 45.072 78.6423 44.0358Z" fill="url(#paint2_radial_202_73)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_202_73" x1="56.7496" y1="39.4014" x2="56.7496" y2="100.924" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#86EFAC" stop-opacity="0.75"/>
|
||||||
|
<stop offset="0.635417" stop-color="white" stop-opacity="0.2"/>
|
||||||
|
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="paint1_radial_202_73" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(66.5581 31.1766) rotate(90) scale(8.17659 17.3311)">
|
||||||
|
<stop stop-color="#047857"/>
|
||||||
|
<stop offset="1" stop-color="#064E3B"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="paint2_radial_202_73" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(64.4593 46.6885) scale(347.403)">
|
||||||
|
<stop stop-color="#047857"/>
|
||||||
|
<stop offset="0.114583" stop-color="#064E3B"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
6
packages/hoppscotch-app/assets/icons/wrap-text.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<path d="M3 12h15a3 3 0 110 6h-4"></path>
|
||||||
|
<polyline points="16 16 14 18 16 20"></polyline>
|
||||||
|
<line x1="3" y1="18" x2="10" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 375 B |
@@ -19,7 +19,8 @@
|
|||||||
@apply bg-divider bg-clip-content;
|
@apply bg-divider bg-clip-content;
|
||||||
@apply rounded-full;
|
@apply rounded-full;
|
||||||
@apply border-solid border-transparent border-4;
|
@apply border-solid border-transparent border-4;
|
||||||
@apply hover:(bg-dividerDark bg-clip-content);
|
@apply hover:bg-dividerDark;
|
||||||
|
@apply hover:bg-clip-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
@@ -27,23 +28,24 @@
|
|||||||
@apply h-4;
|
@apply h-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hide-scrollbar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
.hide-scrollbar::-webkit-scrollbar {
|
.hide-scrollbar::-webkit-scrollbar {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
@apply bg-divider;
|
@apply bg-accentDark;
|
||||||
}
|
@apply text-accentContrast;
|
||||||
|
|
||||||
.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-35;
|
||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
@@ -66,7 +68,6 @@ body {
|
|||||||
animation: fade 300ms forwards;
|
animation: fade 300ms forwards;
|
||||||
font-size: var(--body-font-size);
|
font-size: var(--body-font-size);
|
||||||
line-height: var(--body-line-height);
|
line-height: var(--body-line-height);
|
||||||
overflow: overlay;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,8 @@ a {
|
|||||||
@apply text-accent;
|
@apply text-accent;
|
||||||
@apply rounded;
|
@apply rounded;
|
||||||
@apply hover:text-accentDark;
|
@apply hover:text-accentDark;
|
||||||
@apply focus-visible:(ring ring-accent);
|
@apply focus-visible:ring;
|
||||||
|
@apply focus-visible:ring-accent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +320,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;
|
||||||
@@ -336,7 +338,8 @@ pre.ace_editor {
|
|||||||
@apply rounded;
|
@apply rounded;
|
||||||
@apply text-current;
|
@apply text-current;
|
||||||
@apply normal-case;
|
@apply normal-case;
|
||||||
@apply hover:(bg-opacity-20 no-underline);
|
@apply hover:bg-opacity-20;
|
||||||
|
@apply hover:no-underline;
|
||||||
@apply font-medium;
|
@apply font-medium;
|
||||||
|
|
||||||
font-size: var(--body-font-size);
|
font-size: var(--body-font-size);
|
||||||
@@ -391,7 +394,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 +438,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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bg-error flex justify-between">
|
<div class="bg-error flex justify-between">
|
||||||
<span
|
<span
|
||||||
class="
|
class="flex py-2 px-4 transition justify-center group relative items-center"
|
||||||
flex
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
transition
|
|
||||||
relative
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
group
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<i class="mr-2 material-icons">info_outline</i>
|
<i class="mr-2 material-icons">info_outline</i>
|
||||||
<span class="text-secondaryDark">
|
<span class="text-secondaryDark">
|
||||||
<span class="md:hidden">
|
<span class="md:hidden">
|
||||||
{{ $t("helpers.offline_short") }}
|
{{ t("helpers.offline_short") }}
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden md:inline">
|
<span class="hidden md:inline">
|
||||||
{{ $t("helpers.offline") }}
|
{{ t("helpers.offline") }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -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 }"
|
||||||
@@ -161,7 +161,9 @@ 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"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
const showShortcuts = ref(false)
|
const showShortcuts = ref(false)
|
||||||
const showShare = ref(false)
|
const showShare = ref(false)
|
||||||
|
|
||||||
|
|||||||
@@ -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>[]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
>
|
>
|
||||||
<div class="space-x-2 inline-flex items-center">
|
<div class="space-x-2 inline-flex items-center">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
class="tracking-wide !font-bold !text-secondaryDark"
|
class="tracking-wide !font-bold !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
label="HOPPSCOTCH"
|
label="HOPPSCOTCH"
|
||||||
to="/"
|
to="/"
|
||||||
/>
|
/>
|
||||||
@@ -15,50 +15,45 @@
|
|||||||
<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 hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
@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 hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
@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 hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
@click.native="showSupport = true"
|
@click.native="showSupport = true"
|
||||||
/>
|
/>
|
||||||
<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-opacity-15 !text-green-500 !hover:bg-opacity-10 !hover:bg-green-400 !hover:text-green-600"
|
||||||
!bg-green-500
|
|
||||||
!text-green-500
|
|
||||||
!bg-opacity-15
|
|
||||||
!hover:bg-opacity-10 !hover:text-green-600 !hover:bg-green-400
|
|
||||||
"
|
|
||||||
@click.native="showTeamsModal = true"
|
@click.native="showTeamsModal = true"
|
||||||
/>
|
/>
|
||||||
<span class="px-2">
|
<span class="px-2">
|
||||||
@@ -78,21 +73,21 @@
|
|||||||
<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 hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||||
svg="user"
|
svg="user"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<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 +105,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 +157,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 +169,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)
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex p-4 space-y-4 items-start flex-col">
|
<div class="flex flex-col space-y-4 p-4 items-start">
|
||||||
<SmartToggle
|
<SmartToggle
|
||||||
: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")
|
||||||
|
|||||||
@@ -13,14 +13,8 @@
|
|||||||
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 border-b border-dividerLight flex flex-shrink-0 text-base text-secondaryDark p-6"
|
||||||
bg-transparent
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-shrink-0
|
|
||||||
text-secondaryDark text-base
|
|
||||||
p-6
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<AppFuse
|
<AppFuse
|
||||||
v-if="search && show"
|
v-if="search && show"
|
||||||
@@ -30,14 +24,7 @@
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="divide-dividerLight divide-y flex flex-col space-y-4 flex-1 overflow-auto hide-scrollbar"
|
||||||
divide-y divide-dividerLight
|
|
||||||
flex flex-col
|
|
||||||
space-y-4
|
|
||||||
flex-1
|
|
||||||
overflow-auto
|
|
||||||
hide-scrollbar
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(map, mapIndex) in mappings"
|
v-for="(map, mapIndex) in mappings"
|
||||||
@@ -45,7 +32,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 +53,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
|
||||||
|
|||||||
@@ -1,15 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="
|
class="cursor-pointer flex flex-1 py-2 px-6 transition items-center search-entry focus:outline-none"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
py-2
|
|
||||||
px-6
|
|
||||||
transition
|
|
||||||
items-center
|
|
||||||
search-entry
|
|
||||||
focus:outline-none
|
|
||||||
"
|
|
||||||
:class="{ active: active }"
|
:class="{ active: active }"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
@click="$emit('action', shortcut.action)"
|
@click="$emit('action', shortcut.action)"
|
||||||
@@ -21,10 +12,10 @@
|
|||||||
:name="shortcut.icon"
|
:name="shortcut.icon"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
class="flex flex-1 mr-4 font-medium transition"
|
class="flex font-medium flex-1 mr-4 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 +28,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
|
||||||
|
|||||||
@@ -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="hideModal"
|
@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>
|
||||||
@@ -35,14 +35,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, useContext } 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"
|
||||||
|
|
||||||
const {
|
const t = useI18n()
|
||||||
$toast,
|
|
||||||
app: { i18n },
|
const toast = useToast()
|
||||||
} = useContext()
|
|
||||||
const t = i18n.t.bind(i18n)
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
show: Boolean
|
show: Boolean
|
||||||
@@ -92,9 +91,7 @@ const platforms = [
|
|||||||
const copyAppLink = () => {
|
const copyAppLink = () => {
|
||||||
copyToClipboard(url)
|
copyToClipboard(url)
|
||||||
copyIcon.value = "check"
|
copyIcon.value = "check"
|
||||||
$toast.success(t("state.copied_to_clipboard").toString(), {
|
toast.success(`${t("state.copied_to_clipboard")}`)
|
||||||
icon: "content_paste",
|
|
||||||
})
|
|
||||||
setTimeout(() => (copyIcon.value = "copy"), 1000)
|
setTimeout(() => (copyIcon.value = "copy"), 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,11 @@
|
|||||||
<AppSlideOver :show="show" @close="close()">
|
<AppSlideOver :show="show" @close="close()">
|
||||||
<template #content>
|
<template #content>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex p-2 top-0 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex
|
|
||||||
p-2
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
items-center
|
|
||||||
sticky
|
|
||||||
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" @click.native="close()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-primary border-b border-dividerLight">
|
<div class="bg-primary border-b border-dividerLight">
|
||||||
@@ -25,28 +15,22 @@
|
|||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
type="search"
|
type="search"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class="
|
class="bg-primaryLight border border-dividerLight rounded flex w-full py-2 px-4 focus-visible:border-divider"
|
||||||
bg-primaryLight
|
:placeholder="`${t('action.search')}`"
|
||||||
border border-dividerLight
|
|
||||||
rounded
|
|
||||||
flex
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
focus-visible:border-divider
|
|
||||||
"
|
|
||||||
:placeholder="`${$t('action.search')}`"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="filterText">
|
<div
|
||||||
|
v-if="filterText"
|
||||||
|
class="divide-dividerLight divide-y 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"
|
||||||
@@ -56,28 +40,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="searchResults.length === 0"
|
v-if="searchResults.length === 0"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="divide-dividerLight divide-y flex flex-col flex-1 overflow-auto hide-scrollbar"
|
||||||
divide-y divide-dividerLight
|
|
||||||
flex flex-col flex-1
|
|
||||||
overflow-auto
|
|
||||||
hide-scrollbar
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(map, mapIndex) in mappings"
|
v-for="(map, mapIndex) in mappings"
|
||||||
@@ -85,7 +58,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 +75,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
|
||||||
|
|||||||
@@ -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
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<aside class="flex h-full justify-between md:flex-col">
|
<aside class="flex h-full justify-between md:flex-col">
|
||||||
<nav class="flex flex-nowrap md:flex-col flex-1 md:flex-none">
|
<nav class="flex flex-nowrap flex-1 md:flex-col md:flex-none">
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-for="(navigation, index) in primaryNavigation"
|
v-for="(navigation, index) in primaryNavigation"
|
||||||
:key="`navigation-${index}`"
|
:key="`navigation-${index}`"
|
||||||
@@ -27,14 +27,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useContext } 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"
|
||||||
|
|
||||||
const {
|
const t = useI18n()
|
||||||
app: { i18n },
|
|
||||||
} = useContext()
|
|
||||||
const t = i18n.t.bind(i18n)
|
|
||||||
|
|
||||||
const windowInnerWidth = useWindowSize()
|
const windowInnerWidth = useWindowSize()
|
||||||
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
|
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
|
||||||
|
|||||||
@@ -10,22 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<aside
|
<aside
|
||||||
class="
|
class="bg-primary flex flex-col h-full max-w-full transform transition top-0 ease-in-out right-0 w-96 z-30 duration-300 fixed overflow-auto"
|
||||||
bg-primary
|
|
||||||
flex flex-col
|
|
||||||
h-full
|
|
||||||
max-w-full
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
top-0
|
|
||||||
ease-in-out
|
|
||||||
right-0
|
|
||||||
w-96
|
|
||||||
z-30
|
|
||||||
duration-300
|
|
||||||
fixed
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
:class="show ? 'shadow-xl translate-x-0' : 'translate-x-full'"
|
:class="show ? 'shadow-xl translate-x-0' : 'translate-x-full'"
|
||||||
>
|
>
|
||||||
<slot name="content"></slot>
|
<slot name="content"></slot>
|
||||||
|
|||||||
@@ -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,17 +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="showShortcuts()"
|
@click.native="showShortcuts()"
|
||||||
/>
|
/>
|
||||||
<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
|
||||||
@@ -37,28 +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="chatWithUs()"
|
@click.native="chatWithUs()"
|
||||||
/>
|
/>
|
||||||
<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()"
|
||||||
@@ -71,6 +71,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
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"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
show: Boolean
|
show: Boolean
|
||||||
@@ -87,6 +90,7 @@ const chatWithUs = () => {
|
|||||||
|
|
||||||
const showShortcuts = () => {
|
const showShortcuts = () => {
|
||||||
invokeAction("flyouts.keybinds.toggle")
|
invokeAction("flyouts.keybinds.toggle")
|
||||||
|
hideModal()
|
||||||
}
|
}
|
||||||
|
|
||||||
const hideModal = () => {
|
const hideModal = () => {
|
||||||
|
|||||||
@@ -3,16 +3,7 @@
|
|||||||
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
|
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
|
||||||
:exact="exact"
|
:exact="exact"
|
||||||
:blank="blank"
|
:blank="blank"
|
||||||
class="
|
class="font-bold py-2 transition inline-flex items-center justify-center focus:outline-none focus-visible:bg-accentDark"
|
||||||
font-bold
|
|
||||||
py-2
|
|
||||||
transition
|
|
||||||
inline-flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
focus:outline-none
|
|
||||||
focus-visible:bg-accentDark
|
|
||||||
"
|
|
||||||
:class="[
|
:class="[
|
||||||
color
|
color
|
||||||
? `text-${color}-800 bg-${color}-200 hover:(text-${color}-900 bg-${color}-300) focus-visible:(text-${color}-900 bg-${color}-300)`
|
? `text-${color}-800 bg-${color}-200 hover:(text-${color}-900 bg-${color}-300) focus-visible:(text-${color}-900 bg-${color}-300)`
|
||||||
|
|||||||
@@ -3,22 +3,12 @@
|
|||||||
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
|
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
|
||||||
:exact="exact"
|
:exact="exact"
|
||||||
:blank="blank"
|
:blank="blank"
|
||||||
class="
|
class="font-semibold py-2 transition inline-flex items-center justify-center whitespace-nowrap focus:outline-none"
|
||||||
font-semibold
|
|
||||||
py-2
|
|
||||||
transition
|
|
||||||
inline-flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
whitespace-nowrap
|
|
||||||
hover:bg-primaryDark
|
|
||||||
focus:outline-none
|
|
||||||
focus-visible:bg-primaryDark
|
|
||||||
"
|
|
||||||
:class="[
|
:class="[
|
||||||
color
|
color
|
||||||
? `text-${color}-500 hover:(text-${color}-600 text-${color}-600)`
|
? `text-${color}-500 hover:text-${color}-600 focus-visible:text-${color}-600`
|
||||||
: 'text-secondary hover:text-secondaryDark focus-visible:text-secondaryDark',
|
: 'text-secondary hover:text-secondaryDark focus-visible:text-secondaryDark',
|
||||||
|
{ 'pointer-events-none': loading },
|
||||||
label ? 'rounded px-4' : 'px-2',
|
label ? 'rounded px-4' : 'px-2',
|
||||||
{ 'rounded-full': rounded },
|
{ 'rounded-full': rounded },
|
||||||
{ 'opacity-75 cursor-not-allowed': disabled },
|
{ 'opacity-75 cursor-not-allowed': disabled },
|
||||||
@@ -28,9 +18,18 @@
|
|||||||
'border border-divider hover:border-dividerDark focus-visible:border-dividerDark':
|
'border border-divider hover:border-dividerDark focus-visible:border-dividerDark':
|
||||||
outline,
|
outline,
|
||||||
},
|
},
|
||||||
{ '!bg-primaryDark': filled },
|
{
|
||||||
|
'bg-primaryLight hover:bg-primaryDark focus-visible:bg-primaryDark':
|
||||||
|
filled,
|
||||||
|
},
|
||||||
]"
|
]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
|
:tabindex="loading ? '-1' : '0'"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="!loading"
|
||||||
|
class="inline-flex items-center justify-center whitespace-nowrap"
|
||||||
|
:class="{ 'flex-row-reverse': reverse }"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
v-if="icon"
|
v-if="icon"
|
||||||
@@ -56,18 +55,13 @@
|
|||||||
<kbd
|
<kbd
|
||||||
v-for="(key, index) in shortcut"
|
v-for="(key, index) in shortcut"
|
||||||
:key="`key-${index}`"
|
:key="`key-${index}`"
|
||||||
class="
|
class="bg-dividerLight rounded text-secondaryLight ml-1 px-1 inline-flex"
|
||||||
bg-dividerLight
|
|
||||||
rounded
|
|
||||||
text-secondaryLight
|
|
||||||
ml-1
|
|
||||||
px-1
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ key }}
|
{{ key }}
|
||||||
</kbd>
|
</kbd>
|
||||||
</div>
|
</div>
|
||||||
|
</span>
|
||||||
|
<SmartSpinner v-else />
|
||||||
</SmartLink>
|
</SmartLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -108,6 +102,10 @@ export default defineComponent({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
reverse: {
|
reverse: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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", {
|
||||||
|
|||||||
@@ -18,18 +18,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autofocus
|
autofocus
|
||||||
class="
|
class="bg-transparent border-t border-dividerLight cursor-pointer flex font-semibold w-full py-2 px-4 appearance-none hover:bg-primaryDark"
|
||||||
bg-transparent
|
|
||||||
border-t border-dividerLight
|
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
font-semibold
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
appearance-none
|
|
||||||
hover:bg-primaryDark
|
|
||||||
"
|
|
||||||
@change="updateSelectedTeam(myTeams[$event.target.value])"
|
@change="updateSelectedTeam(myTeams[$event.target.value])"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
|
|||||||
@@ -38,19 +38,22 @@ import { defineComponent } from "@nuxtjs/composition-api"
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
placeholderCollName: { type: String, default: null },
|
editingCollectionName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: null,
|
name: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingCollectionName(val) {
|
||||||
|
this.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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)
|
||||||
|
|||||||
@@ -39,18 +39,22 @@ import { defineComponent } from "@nuxtjs/composition-api"
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
|
editingFolderName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: null,
|
name: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingFolderName(val) {
|
||||||
|
this.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import { defineComponent } from "@nuxtjs/composition-api"
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
placeholderReqName: { type: String, default: null },
|
editingRequestName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -44,12 +44,15 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingRequestName(val) {
|
||||||
|
this.requestUpdateData.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
v-if="mode == 'import_from_my_collections'"
|
v-if="mode == 'import_from_my_collections'"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.go_back')"
|
:title="$t('action.go_back')"
|
||||||
class="rounded"
|
|
||||||
svg="arrow-left"
|
svg="arrow-left"
|
||||||
@click.native="
|
@click.native="
|
||||||
() => {
|
() => {
|
||||||
@@ -34,7 +33,6 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.more')"
|
:title="$t('action.more')"
|
||||||
class="rounded"
|
|
||||||
svg="more-vertical"
|
svg="more-vertical"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -229,15 +227,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 +409,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 = {
|
||||||
|
|||||||
@@ -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,8 +58,9 @@
|
|||||||
</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 { HoppGQLRequest, isHoppRESTRequest } from "@hoppscotch/data"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
import {
|
import {
|
||||||
editGraphqlRequest,
|
editGraphqlRequest,
|
||||||
editRESTRequest,
|
editRESTRequest,
|
||||||
@@ -74,7 +75,9 @@ import {
|
|||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
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 { 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,20 +192,20 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone Deep because objects are shared by reference so updating
|
||||||
|
// just one bit will update other referenced shared instances
|
||||||
const requestUpdated =
|
const requestUpdated =
|
||||||
props.mode === "rest" ? getRESTRequest() : getGQLSession().request
|
props.mode === "rest"
|
||||||
|
? cloneDeep(getRESTRequest())
|
||||||
|
: cloneDeep(getGQLSession().request)
|
||||||
|
|
||||||
// // Filter out all REST file inputs
|
// // Filter out all REST file inputs
|
||||||
// if (this.mode === "rest" && requestUpdated.bodyParams) {
|
// if (this.mode === "rest" && requestUpdated.bodyParams) {
|
||||||
@@ -283,9 +281,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 +316,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 +346,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 +378,7 @@ const saveRequestAs = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const requestSaved = () => {
|
const requestSaved = () => {
|
||||||
$toast.success(`${t("request.added")}`, {
|
toast.success(`${t("request.added")}`)
|
||||||
icon: "post_add",
|
|
||||||
})
|
|
||||||
hideModal()
|
hideModal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "@nuxtjs/composition-api"
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { HoppGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
import { HoppGQLRequest } from "@hoppscotch/data"
|
||||||
import { addGraphqlCollection, makeCollection } from "~/newstore/collections"
|
import { addGraphqlCollection, makeCollection } from "~/newstore/collections"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@drop.prevent="dropEvent"
|
@drop.prevent="dropEvent"
|
||||||
@dragover="dragging = true"
|
@dragover="dragging = true"
|
||||||
@drop="dragging = false"
|
@drop="dragging = false"
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -20,15 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ collection.name }} </span>
|
<span class="truncate"> {{ collection.name }} </span>
|
||||||
@@ -99,16 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -149,25 +133,12 @@
|
|||||||
v-if="
|
v-if="
|
||||||
collection.folders.length === 0 && collection.requests.length === 0
|
collection.folders.length === 0 && collection.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.collection')"
|
:alt="$t('empty.collection')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -221,7 +192,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -251,9 +222,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
|
||||||
|
|||||||
@@ -45,18 +45,22 @@ export default defineComponent({
|
|||||||
show: Boolean,
|
show: Boolean,
|
||||||
editingCollection: { type: Object, default: () => {} },
|
editingCollection: { type: Object, default: () => {} },
|
||||||
editingCollectionIndex: { type: Number, default: null },
|
editingCollectionIndex: { type: Number, default: null },
|
||||||
|
editingCollectionName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: null as string | null,
|
name: null as string | null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingCollectionName(val) {
|
||||||
|
this.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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 = {
|
||||||
|
|||||||
@@ -45,18 +45,22 @@ export default defineComponent({
|
|||||||
show: Boolean,
|
show: Boolean,
|
||||||
folder: { type: Object, default: () => {} },
|
folder: { type: Object, default: () => {} },
|
||||||
folderPath: { type: String, default: null },
|
folderPath: { type: String, default: null },
|
||||||
|
editingFolderName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: "",
|
name: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingFolderName(val) {
|
||||||
|
this.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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, {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType } from "@nuxtjs/composition-api"
|
import { defineComponent, PropType } from "@nuxtjs/composition-api"
|
||||||
import { HoppGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
import { HoppGQLRequest } from "@hoppscotch/data"
|
||||||
import { editGraphqlRequest } from "~/newstore/collections"
|
import { editGraphqlRequest } from "~/newstore/collections"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -47,6 +47,7 @@ export default defineComponent({
|
|||||||
folderPath: { type: String, default: null },
|
folderPath: { type: String, default: null },
|
||||||
request: { type: Object as PropType<HoppGQLRequest>, default: () => {} },
|
request: { type: Object as PropType<HoppGQLRequest>, default: () => {} },
|
||||||
requestIndex: { type: Number, default: null },
|
requestIndex: { type: Number, default: null },
|
||||||
|
editingRequestName: { type: String, default: null },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -55,12 +56,15 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
editingRequestName(val) {
|
||||||
|
this.requestUpdateData.name = val
|
||||||
|
},
|
||||||
|
},
|
||||||
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 = {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@drop.prevent="dropEvent"
|
@drop.prevent="dropEvent"
|
||||||
@dragover="dragging = true"
|
@dragover="dragging = true"
|
||||||
@drop="dragging = false"
|
@drop="dragging = false"
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -20,15 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="truncate">
|
||||||
@@ -95,16 +88,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -148,25 +132,12 @@
|
|||||||
folder.requests &&
|
folder.requests &&
|
||||||
folder.requests.length === 0
|
folder.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.folder')"
|
:alt="$t('empty.folder')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -219,7 +190,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -250,9 +221,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
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.more')"
|
:title="$t('action.more')"
|
||||||
class="rounded"
|
|
||||||
svg="more-vertical"
|
svg="more-vertical"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -140,15 +139,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 +247,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 = {
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
@dragstart="dragStart"
|
@dragstart="dragStart"
|
||||||
@dragover.stop
|
@dragover.stop
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex px-2 w-16 items-center justify-center truncate"
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
px-2
|
|
||||||
w-16
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
truncate
|
|
||||||
"
|
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -27,15 +20,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ request.name }} </span>
|
<span class="truncate"> {{ request.name }} </span>
|
||||||
@@ -118,7 +103,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType } from "@nuxtjs/composition-api"
|
import { defineComponent, PropType } from "@nuxtjs/composition-api"
|
||||||
import { HoppGQLRequest, makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
import { HoppGQLRequest, makeGQLRequest } from "@hoppscotch/data"
|
||||||
import { removeGraphqlRequest } from "~/newstore/collections"
|
import { removeGraphqlRequest } from "~/newstore/collections"
|
||||||
import { setGQLSession } from "~/newstore/GQLSession"
|
import { setGQLSession } from "~/newstore/GQLSession"
|
||||||
|
|
||||||
@@ -194,9 +179,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",
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,14 +4,7 @@
|
|||||||
:class="{ 'rounded border border-divider': savingMode }"
|
:class="{ 'rounded border border-divider': savingMode }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="
|
class="divide-dividerLight divide-y border-b border-dividerLight flex flex-col top-0 z-10 sticky"
|
||||||
divide-y divide-dividerLight
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-col
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
"
|
|
||||||
:class="{ 'bg-primary': !savingMode }"
|
:class="{ 'bg-primary': !savingMode }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -74,7 +67,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.collections')"
|
:alt="$t('empty.collections')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -103,6 +96,7 @@
|
|||||||
:show="showModalEdit"
|
:show="showModalEdit"
|
||||||
:editing-collection="editingCollection"
|
:editing-collection="editingCollection"
|
||||||
:editing-collection-index="editingCollectionIndex"
|
:editing-collection-index="editingCollectionIndex"
|
||||||
|
:editing-collection-name="editingCollection ? editingCollection.name : ''"
|
||||||
@hide-modal="displayModalEdit(false)"
|
@hide-modal="displayModalEdit(false)"
|
||||||
/>
|
/>
|
||||||
<CollectionsGraphqlAddFolder
|
<CollectionsGraphqlAddFolder
|
||||||
@@ -117,6 +111,7 @@
|
|||||||
:folder="editingFolder"
|
:folder="editingFolder"
|
||||||
:folder-index="editingFolderIndex"
|
:folder-index="editingFolderIndex"
|
||||||
:folder-path="editingFolderPath"
|
:folder-path="editingFolderPath"
|
||||||
|
:editing-folder-name="editingFolder ? editingFolder.name : ''"
|
||||||
@hide-modal="displayModalEditFolder(false)"
|
@hide-modal="displayModalEditFolder(false)"
|
||||||
/>
|
/>
|
||||||
<CollectionsGraphqlEditRequest
|
<CollectionsGraphqlEditRequest
|
||||||
@@ -124,6 +119,7 @@
|
|||||||
:folder-path="editingFolderPath"
|
:folder-path="editingFolderPath"
|
||||||
:request="editingRequest"
|
:request="editingRequest"
|
||||||
:request-index="editingRequestIndex"
|
:request-index="editingRequestIndex"
|
||||||
|
:editing-request-name="editingRequest ? editingRequest.name : ''"
|
||||||
@hide-modal="displayModalEditRequest(false)"
|
@hide-modal="displayModalEditRequest(false)"
|
||||||
/>
|
/>
|
||||||
<CollectionsGraphqlImportExport
|
<CollectionsGraphqlImportExport
|
||||||
|
|||||||
@@ -4,16 +4,8 @@
|
|||||||
:class="{ 'rounded border border-divider': saveRequest }"
|
:class="{ 'rounded border border-divider': saveRequest }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="
|
class="divide-dividerLight divide-y bg-primary border-b border-dividerLight rounded-t flex flex-col z-10 sticky"
|
||||||
divide-y divide-dividerLight
|
:style="saveRequest ? 'top: calc(-1 * var(--body-font-size))' : 'top: 0'"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
rounded-t
|
|
||||||
flex flex-col
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div v-if="!saveRequest" class="search-wrappe">
|
<div v-if="!saveRequest" class="search-wrappe">
|
||||||
<input
|
<input
|
||||||
@@ -112,7 +104,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.collections')"
|
:alt="$t('empty.collections')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -154,8 +146,11 @@
|
|||||||
/>
|
/>
|
||||||
<CollectionsEdit
|
<CollectionsEdit
|
||||||
:show="showModalEdit"
|
:show="showModalEdit"
|
||||||
:editing-coll-name="editingCollection ? editingCollection.name : ''"
|
:editing-collection-name="
|
||||||
:placeholder-coll-name="editingCollection ? editingCollection.name : ''"
|
editingCollection
|
||||||
|
? editingCollection.name || editingCollection.title
|
||||||
|
: ''
|
||||||
|
"
|
||||||
@hide-modal="displayModalEdit(false)"
|
@hide-modal="displayModalEdit(false)"
|
||||||
@submit="updateEditingCollection"
|
@submit="updateEditingCollection"
|
||||||
/>
|
/>
|
||||||
@@ -168,12 +163,15 @@
|
|||||||
/>
|
/>
|
||||||
<CollectionsEditFolder
|
<CollectionsEditFolder
|
||||||
:show="showModalEditFolder"
|
:show="showModalEditFolder"
|
||||||
|
:editing-folder-name="
|
||||||
|
editingFolder ? editingFolder.name || editingFolder.title : ''
|
||||||
|
"
|
||||||
@submit="updateEditingFolder"
|
@submit="updateEditingFolder"
|
||||||
@hide-modal="displayModalEditFolder(false)"
|
@hide-modal="displayModalEditFolder(false)"
|
||||||
/>
|
/>
|
||||||
<CollectionsEditRequest
|
<CollectionsEditRequest
|
||||||
:show="showModalEditRequest"
|
:show="showModalEditRequest"
|
||||||
:placeholder-req-name="editingRequest ? editingRequest.name : ''"
|
:editing-request-name="editingRequest ? editingRequest.name : ''"
|
||||||
@submit="updateEditingRequest"
|
@submit="updateEditingRequest"
|
||||||
@hide-modal="displayModalEditRequest(false)"
|
@hide-modal="displayModalEditRequest(false)"
|
||||||
/>
|
/>
|
||||||
@@ -361,14 +359,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 +371,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 +388,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 +408,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 +444,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 +513,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 +581,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 +607,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 +628,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 +642,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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@drop.prevent="dropEvent"
|
@drop.prevent="dropEvent"
|
||||||
@dragover="dragging = true"
|
@dragover="dragging = true"
|
||||||
@drop="dragging = false"
|
@drop="dragging = false"
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -20,15 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ collection.name }} </span>
|
<span class="truncate"> {{ collection.name }} </span>
|
||||||
@@ -118,16 +111,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -175,25 +159,12 @@
|
|||||||
(collection.requests == undefined ||
|
(collection.requests == undefined ||
|
||||||
collection.requests.length === 0)
|
collection.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.collection')"
|
:alt="$t('empty.collection')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -248,7 +219,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
@dragover.prevent
|
@dragover.prevent
|
||||||
@drop.prevent="dropEvent"
|
@drop.prevent="dropEvent"
|
||||||
@dragover="dragging = true"
|
@dragover="dragging = true"
|
||||||
@drop="dragging = false"
|
@drop="dragging = false"
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -20,15 +21,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="truncate">
|
||||||
@@ -100,16 +93,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -157,25 +141,12 @@
|
|||||||
folder.requests &&
|
folder.requests &&
|
||||||
folder.requests.length === 0
|
folder.requests.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.folder')"
|
:alt="$t('empty.folder')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -234,7 +205,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -262,9 +233,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
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
<div class="flex flex-col" :class="[{ 'bg-primaryLight': dragging }]">
|
||||||
<div
|
<div
|
||||||
class="flex items-center group"
|
class="flex items-stretch group"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
@dragstart="dragStart"
|
@dragstart="dragStart"
|
||||||
@dragover.stop
|
@dragover.stop
|
||||||
@dragleave="dragging = false"
|
@dragleave="dragging = false"
|
||||||
@dragend="dragging = false"
|
@dragend="dragging = false"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex px-2 w-16 items-center justify-center truncate"
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
px-2
|
|
||||||
w-16
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
truncate
|
|
||||||
"
|
|
||||||
:class="getRequestLabelColor(request.method)"
|
:class="getRequestLabelColor(request.method)"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
@@ -32,16 +25,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition items-center group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
items-center
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ request.name }} </span>
|
<span class="truncate"> {{ request.name }} </span>
|
||||||
@@ -133,7 +117,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from "@nuxtjs/composition-api"
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { translateToNewRequest } from "~/helpers/types/HoppRESTRequest"
|
import { translateToNewRequest } from "@hoppscotch/data"
|
||||||
import { useReadonlyStream } from "~/helpers/utils/composables"
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
import {
|
import {
|
||||||
restSaveContext$,
|
restSaveContext$,
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex items-center group">
|
<div
|
||||||
|
class="flex items-stretch group"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -12,15 +15,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ collection.title }} </span>
|
<span class="truncate"> {{ collection.title }} </span>
|
||||||
@@ -114,16 +109,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -169,25 +155,12 @@
|
|||||||
(collection.requests == undefined ||
|
(collection.requests == undefined ||
|
||||||
collection.requests.length === 0)
|
collection.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.collection')"
|
:alt="$t('empty.collection')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -240,7 +213,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex items-center group">
|
<div
|
||||||
|
class="flex items-stretch group"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<SmartIcon
|
<SmartIcon
|
||||||
@@ -12,15 +15,7 @@
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="truncate">
|
||||||
@@ -97,16 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="showChildren || isFiltered" class="flex">
|
<div v-if="showChildren || isFiltered" class="flex">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-dividerLight cursor-nsResize flex ml-5.5 transform transition w-1 hover:bg-dividerDark hover:scale-x-125"
|
||||||
flex
|
|
||||||
w-1
|
|
||||||
transform
|
|
||||||
transition
|
|
||||||
cursor-nsResize
|
|
||||||
ml-5.5
|
|
||||||
bg-dividerLight
|
|
||||||
hover:scale-x-125 hover:bg-dividerDark
|
|
||||||
"
|
|
||||||
@click="toggleShowChildren()"
|
@click="toggleShowChildren()"
|
||||||
></div>
|
></div>
|
||||||
<div class="flex flex-col flex-1 truncate">
|
<div class="flex flex-col flex-1 truncate">
|
||||||
@@ -150,25 +136,12 @@
|
|||||||
(folder.children == undefined || folder.children.length === 0) &&
|
(folder.children == undefined || folder.children.length === 0) &&
|
||||||
(folder.requests == undefined || folder.requests.length === 0)
|
(folder.requests == undefined || folder.requests.length === 0)
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
:src="`/images/states/${$colorMode.value}/pack.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 mb-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
mb-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.folder')"
|
:alt="$t('empty.folder')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center">
|
<span class="text-center">
|
||||||
@@ -222,7 +195,7 @@ export default defineComponent({
|
|||||||
getCollectionIcon() {
|
getCollectionIcon() {
|
||||||
if (this.isSelected) return "check-circle"
|
if (this.isSelected) return "check-circle"
|
||||||
else if (!this.showChildren && !this.isFiltered) return "folder"
|
else if (!this.showChildren && !this.isFiltered) return "folder"
|
||||||
else if (this.showChildren || this.isFiltered) return "folder-minus"
|
else if (this.showChildren || this.isFiltered) return "folder-open"
|
||||||
else return "folder"
|
else return "folder"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -253,15 +226,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")
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex items-center group">
|
<div
|
||||||
|
class="flex items-stretch group"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex px-2 w-16 items-center justify-center truncate"
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
px-2
|
|
||||||
w-16
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
truncate
|
|
||||||
"
|
|
||||||
:class="getRequestLabelColor(request.method)"
|
:class="getRequestLabelColor(request.method)"
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
@@ -25,16 +20,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition items-center group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
items-center
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="!doc ? selectRequest() : {}"
|
@click="!doc ? selectRequest() : {}"
|
||||||
>
|
>
|
||||||
<span class="truncate"> {{ request.name }} </span>
|
<span class="truncate"> {{ request.name }} </span>
|
||||||
@@ -110,7 +96,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "@nuxtjs/composition-api"
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { translateToNewRequest } from "~/helpers/types/HoppRESTRequest"
|
import { translateToNewRequest } from "@hoppscotch/data"
|
||||||
import { useReadonlyStream } from "~/helpers/utils/composables"
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
import {
|
import {
|
||||||
restSaveContext$,
|
restSaveContext$,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="folder">
|
<div class="folder">
|
||||||
<h3 class="heading">
|
<h3 class="heading">
|
||||||
<SmartIcon name="folder-minus" class="svg-icons" />
|
<SmartIcon name="folder-open" class="svg-icons" />
|
||||||
{{ folder.name || $t("state.none") }}
|
{{ folder.name || $t("state.none") }}
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
{{ $t("action.label") }}
|
{{ $t("action.label") }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 justify-between items-center">
|
<div class="flex flex-1 items-center justify-between">
|
||||||
<label for="variableList" class="p-4">
|
<label for="variableList" class="p-4">
|
||||||
{{ $t("environment.variable_list") }}
|
{{ $t("environment.variable_list") }}
|
||||||
</label>
|
</label>
|
||||||
@@ -31,23 +31,21 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.clear_all')"
|
:title="$t('action.clear_all')"
|
||||||
:svg="clearIcon"
|
:svg="clearIcon"
|
||||||
class="rounded"
|
|
||||||
@click.native="clearContent()"
|
@click.native="clearContent()"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
svg="plus"
|
svg="plus"
|
||||||
:title="$t('add.new')"
|
:title="$t('add.new')"
|
||||||
class="rounded"
|
|
||||||
@click.native="addEnvironmentVariable"
|
@click.native="addEnvironmentVariable"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divide-y divide-dividerLight border-divider border rounded">
|
<div class="divide-dividerLight divide-y border border-divider rounded">
|
||||||
<div
|
<div
|
||||||
v-for="(variable, index) in vars"
|
v-for="(variable, index) in vars"
|
||||||
:key="`variable-${index}`"
|
:key="`variable-${index}`"
|
||||||
class="divide-x divide-dividerLight flex"
|
class="divide-dividerLight divide-x flex"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="variable.key"
|
v-model="variable.key"
|
||||||
@@ -74,25 +72,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="vars.length === 0"
|
v-if="vars.length === 0"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.environments')"
|
:alt="$t('empty.environments')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -177,9 +162,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 +176,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center group">
|
<div
|
||||||
|
class="flex items-stretch group"
|
||||||
|
@contextmenu.prevent="$refs.options.tippy().show()"
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-4 justify-center items-center"
|
class="cursor-pointer flex px-4 items-center justify-center"
|
||||||
@click="$emit('edit-environment')"
|
@click="$emit('edit-environment')"
|
||||||
>
|
>
|
||||||
<SmartIcon class="svg-icons" name="layers" />
|
<SmartIcon class="svg-icons" name="layers" />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
@click="$emit('edit-environment')"
|
@click="$emit('edit-environment')"
|
||||||
>
|
>
|
||||||
<span class="truncate">
|
<span class="truncate">
|
||||||
@@ -102,9 +97,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") {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.more')"
|
:title="$t('action.more')"
|
||||||
class="rounded"
|
|
||||||
svg="more-vertical"
|
svg="more-vertical"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -140,15 +139,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 +225,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",
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,12 +6,7 @@
|
|||||||
<span
|
<span
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="`${$t('environment.select')}`"
|
:title="`${$t('environment.select')}`"
|
||||||
class="
|
class="bg-transparent border-b border-dividerLight flex-1 select-wrapper"
|
||||||
bg-transparent
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex-1
|
|
||||||
select-wrapper
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-if="selectedEnvironmentIndex !== -1"
|
v-if="selectedEnvironmentIndex !== -1"
|
||||||
@@ -109,7 +104,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.environments')"
|
:alt="$t('empty.environments')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
|
|||||||
@@ -56,9 +56,9 @@
|
|||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
<div v-if="mode === 'email-sent'" class="flex flex-col px-4">
|
<div v-if="mode === 'email-sent'" 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 items-center justify-center">
|
||||||
<SmartIcon class="h-6 text-accent w-6" name="inbox" />
|
<SmartIcon class="h-6 text-accent w-6" name="inbox" />
|
||||||
<h3 class="my-2 text-center text-lg">
|
<h3 class="my-2 text-lg text-center">
|
||||||
{{ $t("auth.we_sent_magic_link") }}
|
{{ $t("auth.we_sent_magic_link") }}
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,16 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="gqlField.isDeprecated"
|
v-if="gqlField.isDeprecated"
|
||||||
class="
|
class="rounded bg-yellow-200 my-1 text-black py-1 px-2 inline-block field-deprecated"
|
||||||
rounded
|
|
||||||
bg-yellow-200
|
|
||||||
my-1
|
|
||||||
text-black
|
|
||||||
py-1
|
|
||||||
px-2
|
|
||||||
inline-block
|
|
||||||
field-deprecated
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ $t("state.deprecated") }}
|
{{ $t("state.deprecated") }}
|
||||||
</div>
|
</div>
|
||||||
@@ -86,7 +77,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.field-highlighted {
|
.field-highlighted {
|
||||||
@apply border-b-2 border-accent;
|
@apply border-accent border-b-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-title {
|
.field-title {
|
||||||
|
|||||||
@@ -7,25 +7,15 @@
|
|||||||
type="url"
|
type="url"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
:placeholder="`${t('request.url')}`"
|
||||||
border border-divider
|
|
||||||
rounded
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
: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 +27,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
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@@ -1,57 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10">
|
<SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10">
|
||||||
<template #actions>
|
<SmartTab :id="'query'" :label="`${t('tab.query')}`" :selected="true">
|
||||||
|
<AppSection label="query">
|
||||||
|
<div
|
||||||
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between gqlRunQuery"
|
||||||
|
>
|
||||||
|
<label class="font-semibold text-secondaryLight">
|
||||||
|
{{ t("request.query") }}
|
||||||
|
</label>
|
||||||
|
<div class="flex">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
:label="`${$t('request.run')}`"
|
:label="`${t('request.run')}`"
|
||||||
svg="play"
|
svg="play"
|
||||||
class="rounded-none !text-accent"
|
class="rounded-none !text-accent !hover:text-accentDark"
|
||||||
@click.native="runQuery()"
|
@click.native="runQuery()"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
ref="saveRequest"
|
ref="saveRequest"
|
||||||
:label="`${$t('request.save')}`"
|
:label="`${t('request.save')}`"
|
||||||
|
svg="save"
|
||||||
class="rounded-none"
|
class="rounded-none"
|
||||||
@click.native="saveRequest"
|
@click.native="saveRequest"
|
||||||
/>
|
/>
|
||||||
</template>
|
|
||||||
|
|
||||||
<SmartTab :id="'query'" :label="`${$t('tab.query')}`" :selected="true">
|
|
||||||
<AppSection label="query">
|
|
||||||
<div
|
|
||||||
class="
|
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
gqlRunQuery
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<label class="font-semibold text-secondaryLight">
|
|
||||||
{{ $t("request.query") }}
|
|
||||||
</label>
|
|
||||||
<div class="flex">
|
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
to="https://docs.hoppscotch.io"
|
to="https://docs.hoppscotch.io/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('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,35 +48,25 @@
|
|||||||
</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="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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"
|
||||||
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,48 +76,38 @@
|
|||||||
</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="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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"
|
||||||
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"
|
||||||
@@ -152,14 +119,10 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(header, index) in headers"
|
v-for="(header, index) in headers"
|
||||||
:key="`header-${String(index)}`"
|
:key="`header-${String(index)}`"
|
||||||
class="
|
class="divide-dividerLight divide-x border-b border-dividerLight flex"
|
||||||
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"
|
||||||
@@ -172,7 +135,7 @@
|
|||||||
px-4
|
px-4
|
||||||
truncate
|
truncate
|
||||||
"
|
"
|
||||||
class="!flex flex-1"
|
class="flex-1 !flex"
|
||||||
@input="
|
@input="
|
||||||
updateRequestHeader(index, {
|
updateRequestHeader(index, {
|
||||||
key: $event,
|
key: $event,
|
||||||
@@ -183,7 +146,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 +164,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 +188,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)"
|
||||||
@@ -234,32 +197,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="headers.length === 0"
|
v-if="headers.length === 0"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/add_category.svg`"
|
:src="`/images/states/${$colorMode.value}/add_category.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
:alt="`${t('empty.headers')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
: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,14 +230,17 @@
|
|||||||
</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 { GQLHeader, makeGQLRequest } from "@hoppscotch/data"
|
||||||
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
import { copyToClipboard } from "~/helpers/utils/clipboard"
|
||||||
import {
|
import {
|
||||||
useNuxt,
|
useNuxt,
|
||||||
useReadonlyStream,
|
useReadonlyStream,
|
||||||
useStream,
|
useStream,
|
||||||
|
useI18n,
|
||||||
|
useToast,
|
||||||
} from "~/helpers/utils/composables"
|
} from "~/helpers/utils/composables"
|
||||||
import {
|
import {
|
||||||
addGQLHeader,
|
addGQLHeader,
|
||||||
@@ -308,21 +261,19 @@ import { GQLConnection } from "~/helpers/GQLConnection"
|
|||||||
import { makeGQLHistoryEntry, addGraphqlHistoryEntry } from "~/newstore/history"
|
import { makeGQLHistoryEntry, addGraphqlHistoryEntry } from "~/newstore/history"
|
||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
import { getCurrentStrategyID } from "~/helpers/network"
|
import { getCurrentStrategyID } from "~/helpers/network"
|
||||||
import { GQLHeader, makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
|
||||||
import { useCodemirror } from "~/helpers/editor/codemirror"
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
import jsonLinter from "~/helpers/editor/linting/json"
|
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 +286,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 +341,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 +377,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 +421,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 +446,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 +461,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 +489,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)
|
||||||
|
|||||||
@@ -5,44 +5,34 @@
|
|||||||
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
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 pl-4 top-0 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
pl-4
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<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"
|
||||||
/>
|
/>
|
||||||
@@ -52,21 +42,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="flex flex-col flex-1 text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col flex-1
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="flex space-x-2 pb-4 my-4">
|
<div class="flex space-x-2 my-4 pb-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 +63,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 +75,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 +114,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 +128,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)
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -34,29 +34,16 @@
|
|||||||
subscriptionFields.length === 0 &&
|
subscriptionFields.length === 0 &&
|
||||||
graphqlTypes.length === 0
|
graphqlTypes.length === 0
|
||||||
"
|
"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/add_comment.svg`"
|
:src="`/images/states/${$colorMode.value}/add_comment.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
:alt="`${t('empty.documentation')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
: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 +52,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 +60,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,9 +73,9 @@
|
|||||||
<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-dividerLight divide-y"
|
||||||
>
|
>
|
||||||
<GraphqlField
|
<GraphqlField
|
||||||
v-for="(field, index) in filteredQueryFields"
|
v-for="(field, index) in filteredQueryFields"
|
||||||
@@ -101,8 +88,8 @@
|
|||||||
<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-dividerLight divide-y"
|
||||||
>
|
>
|
||||||
<GraphqlField
|
<GraphqlField
|
||||||
v-for="(field, index) in filteredMutationFields"
|
v-for="(field, index) in filteredMutationFields"
|
||||||
@@ -115,8 +102,8 @@
|
|||||||
<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-dividerLight divide-y"
|
||||||
>
|
>
|
||||||
<GraphqlField
|
<GraphqlField
|
||||||
v-for="(field, index) in filteredSubscriptionFields"
|
v-for="(field, index) in filteredSubscriptionFields"
|
||||||
@@ -130,8 +117,8 @@
|
|||||||
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-dividerLight divide-y"
|
||||||
>
|
>
|
||||||
<GraphqlType
|
<GraphqlType
|
||||||
v-for="(type, index) in filteredGraphqlTypes"
|
v-for="(type, index) in filteredGraphqlTypes"
|
||||||
@@ -149,51 +136,41 @@
|
|||||||
</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"
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 pl-4 top-0 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
flex flex-1
|
|
||||||
top-0
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
border-b border-dividerLight
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<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"
|
||||||
/>
|
/>
|
||||||
@@ -202,29 +179,16 @@
|
|||||||
<div v-if="schemaString" ref="schemaEditor"></div>
|
<div v-if="schemaString" ref="schemaEditor"></div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
:src="`/images/states/${$colorMode.value}/blockchain.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
:alt="`${t('empty.schema')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
: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 +197,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 { GQLHeader } from "@hoppscotch/data"
|
||||||
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 { 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 +217,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 +285,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 ?? [])),
|
||||||
@@ -408,12 +368,25 @@ const handleJumpToType = async (type: GraphQLType) => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
const rootTypeName = resolveRootType(type).name
|
const rootTypeName = resolveRootType(type).name
|
||||||
|
|
||||||
const target = document.getElementById(`type_${rootTypeName}`)
|
const target = document.getElementById(`type_${rootTypeName}`)
|
||||||
if (target) {
|
if (target) {
|
||||||
gqlTabs.value.$el
|
target.scrollIntoView({ block: "center", behavior: "smooth" })
|
||||||
.querySelector(".gqlTabs")
|
target.classList.add(
|
||||||
.scrollTo({ top: target.offsetTop, behavior: "smooth" })
|
"transition-all",
|
||||||
|
"ring-inset",
|
||||||
|
"ring-accentLight",
|
||||||
|
"ring-4"
|
||||||
|
)
|
||||||
|
setTimeout(
|
||||||
|
() =>
|
||||||
|
target.classList.remove(
|
||||||
|
"ring-inset",
|
||||||
|
"ring-accentLight",
|
||||||
|
"ring-4",
|
||||||
|
"transition-all"
|
||||||
|
),
|
||||||
|
2000
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,9 +422,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)
|
||||||
|
|||||||
@@ -2,16 +2,7 @@
|
|||||||
<div class="flex flex-col group">
|
<div class="flex flex-col group">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 pl-4 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
pl-4
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
@click="useEntry"
|
@click="useEntry"
|
||||||
>
|
>
|
||||||
@@ -49,7 +40,7 @@
|
|||||||
<span
|
<span
|
||||||
v-for="(line, index) in query"
|
v-for="(line, index) in query"
|
||||||
:key="`line-${index}`"
|
:key="`line-${index}`"
|
||||||
class="cursor-pointer text-secondaryLight px-4 whitespace-pre truncate"
|
class="cursor-pointer font-mono text-secondaryLight px-4 truncate whitespace-pre"
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
@click="useEntry"
|
@click="useEntry"
|
||||||
>{{ line }}</span
|
>{{ line }}</span
|
||||||
@@ -65,7 +56,7 @@ import {
|
|||||||
PropType,
|
PropType,
|
||||||
ref,
|
ref,
|
||||||
} from "@nuxtjs/composition-api"
|
} from "@nuxtjs/composition-api"
|
||||||
import { makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
import { makeGQLRequest } from "@hoppscotch/data"
|
||||||
import { setGQLSession } from "~/newstore/GQLSession"
|
import { setGQLSession } from "~/newstore/GQLSession"
|
||||||
import { GQLHistoryEntry } from "~/newstore/history"
|
import { GQLHistoryEntry } from "~/newstore/history"
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/history.svg`"
|
:src="`/images/states/${$colorMode.value}/history.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.history')"
|
:alt="$t('empty.history')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center mb-4">
|
<span class="text-center mb-4">
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center group">
|
<div class="flex items-stretch group">
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer flex px-2 w-16 justify-center items-center truncate"
|
class="cursor-pointer flex px-2 w-16 items-center justify-center truncate"
|
||||||
:class="entryStatus.className"
|
:class="entryStatus.className"
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
:title="`${duration}`"
|
:title="`${duration}`"
|
||||||
@@ -10,15 +10,7 @@
|
|||||||
{{ entry.request.method }}
|
{{ entry.request.method }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="cursor-pointer flex flex-1 min-w-0 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||||
cursor-pointer
|
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
pr-2
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
data-testid="restore_history_entry"
|
data-testid="restore_history_entry"
|
||||||
:title="`${duration}`"
|
:title="`${duration}`"
|
||||||
@click="$emit('use-entry')"
|
@click="$emit('use-entry')"
|
||||||
@@ -49,13 +41,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 +52,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 +60,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(() => {
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
<label class="font-semibold text-secondaryLight">
|
<label class="font-semibold text-secondaryLight">
|
||||||
@@ -34,6 +24,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
label="None"
|
label="None"
|
||||||
|
:icon="
|
||||||
|
authName === 'None'
|
||||||
|
? 'radio_button_checked'
|
||||||
|
: 'radio_button_unchecked'
|
||||||
|
"
|
||||||
@click.native="
|
@click.native="
|
||||||
authType = 'none'
|
authType = 'none'
|
||||||
$refs.authTypeOptions.tippy().hide()
|
$refs.authTypeOptions.tippy().hide()
|
||||||
@@ -41,6 +36,11 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
label="Basic Auth"
|
label="Basic Auth"
|
||||||
|
:icon="
|
||||||
|
authName === 'Basic Auth'
|
||||||
|
? 'radio_button_checked'
|
||||||
|
: 'radio_button_unchecked'
|
||||||
|
"
|
||||||
@click.native="
|
@click.native="
|
||||||
authType = 'basic'
|
authType = 'basic'
|
||||||
$refs.authTypeOptions.tippy().hide()
|
$refs.authTypeOptions.tippy().hide()
|
||||||
@@ -48,6 +48,11 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
label="Bearer Token"
|
label="Bearer Token"
|
||||||
|
:icon="
|
||||||
|
authName === 'Bearer'
|
||||||
|
? 'radio_button_checked'
|
||||||
|
: 'radio_button_unchecked'
|
||||||
|
"
|
||||||
@click.native="
|
@click.native="
|
||||||
authType = 'bearer'
|
authType = 'bearer'
|
||||||
$refs.authTypeOptions.tippy().hide()
|
$refs.authTypeOptions.tippy().hide()
|
||||||
@@ -55,6 +60,11 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
label="OAuth 2.0"
|
label="OAuth 2.0"
|
||||||
|
:icon="
|
||||||
|
authName === 'OAuth 2.0'
|
||||||
|
? 'radio_button_checked'
|
||||||
|
: 'radio_button_unchecked'
|
||||||
|
"
|
||||||
@click.native="
|
@click.native="
|
||||||
authType = 'oauth-2'
|
authType = 'oauth-2'
|
||||||
$refs.authTypeOptions.tippy().hide()
|
$refs.authTypeOptions.tippy().hide()
|
||||||
@@ -98,7 +108,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/login.svg`"
|
:src="`/images/states/${$colorMode.value}/login.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.authorization')"
|
:alt="$t('empty.authorization')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -107,7 +117,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
|
||||||
@@ -132,17 +142,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary h-full top-upperTertiaryStickyFold min-w-46 max-w-1/3 p-4 z-9 sticky overflow-auto"
|
||||||
bg-primary
|
|
||||||
h-full
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
min-w-46
|
|
||||||
max-w-1/3
|
|
||||||
p-4
|
|
||||||
z-9
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<div class="text-secondaryLight pb-2">
|
<div class="text-secondaryLight pb-2">
|
||||||
@@ -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>
|
||||||
@@ -168,17 +168,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary h-full top-upperTertiaryStickyFold min-w-46 max-w-1/3 p-4 z-9 sticky overflow-auto"
|
||||||
bg-primary
|
|
||||||
h-full
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
min-w-46
|
|
||||||
max-w-1/3
|
|
||||||
p-4
|
|
||||||
z-9
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<div class="text-secondaryLight pb-2">
|
<div class="text-secondaryLight pb-2">
|
||||||
@@ -187,7 +177,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>
|
||||||
@@ -208,17 +198,7 @@
|
|||||||
<HttpOAuth2Authorization />
|
<HttpOAuth2Authorization />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary h-full top-upperTertiaryStickyFold min-w-46 max-w-1/3 p-4 z-9 sticky overflow-auto"
|
||||||
bg-primary
|
|
||||||
h-full
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
min-w-46
|
|
||||||
max-w-1/3
|
|
||||||
p-4
|
|
||||||
z-9
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<div class="text-secondaryLight pb-2">
|
<div class="text-secondaryLight pb-2">
|
||||||
@@ -227,7 +207,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>
|
||||||
@@ -242,7 +222,7 @@ import {
|
|||||||
HoppRESTAuthBasic,
|
HoppRESTAuthBasic,
|
||||||
HoppRESTAuthBearer,
|
HoppRESTAuthBearer,
|
||||||
HoppRESTAuthOAuth2,
|
HoppRESTAuthOAuth2,
|
||||||
} from "~/helpers/types/HoppRESTAuth"
|
} from "@hoppscotch/data"
|
||||||
import { pluckRef, useStream } from "~/helpers/utils/composables"
|
import { pluckRef, useStream } from "~/helpers/utils/composables"
|
||||||
import { restAuth$, setRESTAuth } from "~/newstore/RESTSession"
|
import { restAuth$, setRESTAuth } from "~/newstore/RESTSession"
|
||||||
import { useSetting } from "~/newstore/settings"
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span class="flex items-center">
|
<span class="flex items-center">
|
||||||
<label class="font-semibold text-secondaryLight">
|
<label class="font-semibold text-secondaryLight">
|
||||||
@@ -68,7 +58,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/upload_single_file.svg`"
|
:src="`/images/states/${$colorMode.value}/upload_single_file.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.body')"
|
:alt="$t('empty.body')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -77,7 +67,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
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection label="bodyParameters">
|
<AppSection label="bodyParameters">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperTertiaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<label class="font-semibold text-secondaryLight">
|
<label class="font-semibold text-secondaryLight">
|
||||||
{{ $t("request.body") }}
|
{{ $t("request.body") }}
|
||||||
@@ -41,7 +31,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(param, index) in bodyParams"
|
v-for="(param, index) in bodyParams"
|
||||||
:key="`param-${index}`"
|
:key="`param-${index}`"
|
||||||
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
class="divide-dividerLight divide-x border-b border-dividerLight flex"
|
||||||
>
|
>
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="param.key"
|
v-model="param.key"
|
||||||
@@ -156,7 +146,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/upload_single_file.svg`"
|
:src="`/images/states/${$colorMode.value}/upload_single_file.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="flex-col my-4 object-contain object-center h-16 w-16 inline-flex"
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
:alt="$t('empty.body')"
|
:alt="$t('empty.body')"
|
||||||
/>
|
/>
|
||||||
<span class="text-center pb-4">
|
<span class="text-center pb-4">
|
||||||
@@ -175,7 +165,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, onMounted, Ref, watch } from "@nuxtjs/composition-api"
|
import { defineComponent, onMounted, Ref, watch } from "@nuxtjs/composition-api"
|
||||||
import { FormDataKeyValue } from "~/helpers/types/HoppRESTRequest"
|
import { FormDataKeyValue } from "@hoppscotch/data"
|
||||||
import { pluckRef } from "~/helpers/utils/composables"
|
import { pluckRef } from "~/helpers/utils/composables"
|
||||||
import {
|
import {
|
||||||
addFormDataEntry,
|
addFormDataEntry,
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,45 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection label="headers">
|
<AppSection label="headers">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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"
|
||||||
@@ -51,10 +41,10 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(header, index) in headers$"
|
v-for="(header, index) in headers$"
|
||||||
:key="`header-${index}`"
|
:key="`header-${index}`"
|
||||||
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
class="divide-dividerLight divide-x 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"
|
||||||
@@ -67,7 +57,7 @@
|
|||||||
px-4
|
px-4
|
||||||
truncate
|
truncate
|
||||||
"
|
"
|
||||||
class="!flex flex-1"
|
class="flex-1 !flex"
|
||||||
@input="
|
@input="
|
||||||
updateHeader(index, {
|
updateHeader(index, {
|
||||||
key: $event,
|
key: $event,
|
||||||
@@ -78,7 +68,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 +90,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 +116,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)"
|
||||||
@@ -135,33 +125,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="headers$.length === 0"
|
v-if="headers$.length === 0"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/add_category.svg`"
|
:src="`/images/states/${$colorMode.value}/add_category.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
:alt="`${t('empty.headers')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
: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 +149,8 @@
|
|||||||
</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 { HoppRESTHeader } from "@hoppscotch/data"
|
||||||
import { useCodemirror } from "~/helpers/editor/codemirror"
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
import {
|
import {
|
||||||
addRESTHeader,
|
addRESTHeader,
|
||||||
@@ -183,14 +161,15 @@ 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 {
|
||||||
import { HoppRESTHeader } from "~/helpers/types/HoppRESTRequest"
|
useReadonlyStream,
|
||||||
|
useI18n,
|
||||||
|
useToast,
|
||||||
|
} from "~/helpers/utils/composables"
|
||||||
|
|
||||||
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 +191,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 +203,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 +255,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)
|
||||||
|
|||||||
@@ -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,21 +21,20 @@
|
|||||||
</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 { useCodemirror } from "~/helpers/editor/codemirror"
|
|
||||||
import {
|
import {
|
||||||
HoppRESTHeader,
|
HoppRESTHeader,
|
||||||
HoppRESTParam,
|
HoppRESTParam,
|
||||||
makeRESTRequest,
|
makeRESTRequest,
|
||||||
} from "~/helpers/types/HoppRESTRequest"
|
} from "@hoppscotch/data"
|
||||||
|
import parseCurlCommand from "~/helpers/curlparser"
|
||||||
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 { HoppRESTAuthOAuth2 } from "@hoppscotch/data"
|
||||||
import { HoppRESTAuthOAuth2 } from "~/helpers/types/HoppRESTAuth"
|
import {
|
||||||
|
pluckRef,
|
||||||
|
useI18n,
|
||||||
|
useStream,
|
||||||
|
useToast,
|
||||||
|
} from "~/helpers/utils/composables"
|
||||||
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",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +124,7 @@ export default {
|
|||||||
clientID,
|
clientID,
|
||||||
scope,
|
scope,
|
||||||
handleAccessTokenRequest,
|
handleAccessTokenRequest,
|
||||||
|
t,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection label="parameters">
|
<AppSection label="parameters">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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"
|
||||||
@@ -51,11 +41,11 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(param, index) in params$"
|
v-for="(param, index) in params$"
|
||||||
:key="`param-${index}`"
|
:key="`param-${index}`"
|
||||||
class="divide-x divide-dividerLight border-b border-dividerLight flex"
|
class="divide-dividerLight divide-x border-b border-dividerLight flex"
|
||||||
>
|
>
|
||||||
<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 +63,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 +85,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 +109,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)"
|
||||||
@@ -128,32 +118,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="params$.length === 0"
|
v-if="params$.length === 0"
|
||||||
class="
|
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
|
||||||
flex flex-col
|
|
||||||
text-secondaryLight
|
|
||||||
p-4
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/add_files.svg`"
|
:src="`/images/states/${$colorMode.value}/add_files.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
|
||||||
flex-col
|
:alt="`${t('empty.parameters')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-16
|
|
||||||
w-16
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
: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 +142,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 { HoppRESTParam } from "@hoppscotch/data"
|
||||||
import { useCodemirror } from "~/helpers/editor/codemirror"
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
import { HoppRESTParam } from "~/helpers/types/HoppRESTRequest"
|
import {
|
||||||
import { useReadonlyStream } from "~/helpers/utils/composables"
|
useReadonlyStream,
|
||||||
|
useI18n,
|
||||||
|
useToast,
|
||||||
|
} from "~/helpers/utils/composables"
|
||||||
import {
|
import {
|
||||||
restParams$,
|
restParams$,
|
||||||
addRESTParam,
|
addRESTParam,
|
||||||
@@ -178,11 +159,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 +173,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 +196,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 +248,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)
|
||||||
|
|||||||
@@ -1,39 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection id="script" :label="`${$t('preRequest.script')}`">
|
<AppSection id="script" :label="`${t('preRequest.script')}`">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@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"
|
||||||
/>
|
/>
|
||||||
@@ -44,28 +34,18 @@
|
|||||||
<div ref="preRrequestEditor"></div>
|
<div ref="preRrequestEditor"></div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary h-full top-upperTertiaryStickyFold min-w-46 max-w-1/3 p-4 z-9 sticky overflow-auto"
|
||||||
bg-primary
|
|
||||||
h-full
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
min-w-46
|
|
||||||
max-w-1/3
|
|
||||||
p-4
|
|
||||||
z-9
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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 +62,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()
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperTertiaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@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 +31,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 +57,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 +106,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 +119,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>
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary flex space-x-2 p-4 top-0 z-10 sticky overflow-x-auto hide-scrollbar"
|
||||||
bg-primary
|
|
||||||
flex
|
|
||||||
space-x-2
|
|
||||||
p-4
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
overflow-x-auto
|
|
||||||
hide-scrollbar
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
<div class="flex relative">
|
<div class="flex relative">
|
||||||
@@ -26,24 +16,10 @@
|
|||||||
<span class="select-wrapper">
|
<span class="select-wrapper">
|
||||||
<input
|
<input
|
||||||
id="method"
|
id="method"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded-l cursor-pointer flex font-semibold text-secondaryDark py-2 px-4 w-26 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded-l
|
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
font-semibold
|
|
||||||
text-secondaryDark
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
w-26
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent
|
|
||||||
focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
: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 +36,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 +59,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 +74,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 +84,7 @@
|
|||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
:label="`${$t('show.code')}`"
|
:label="`${t('show.code')}`"
|
||||||
svg="code-2"
|
svg="code-2"
|
||||||
@click.native="
|
@click.native="
|
||||||
() => {
|
() => {
|
||||||
@@ -119,7 +95,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 +110,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 +135,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"
|
||||||
@@ -168,18 +144,18 @@
|
|||||||
/>
|
/>
|
||||||
<SmartItem
|
<SmartItem
|
||||||
ref="copyRequest"
|
ref="copyRequest"
|
||||||
:label="`${$t('request.copy_link')}`"
|
:label="shareButtonText"
|
||||||
:svg="hasNavigatorShare ? 'share-2' : 'copy'"
|
:svg="copyLinkIcon"
|
||||||
|
:loading="fetchingShareLink"
|
||||||
@click.native="
|
@click.native="
|
||||||
() => {
|
() => {
|
||||||
copyRequest()
|
copyRequest()
|
||||||
saveOptions.tippy().hide()
|
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<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,8 +184,9 @@
|
|||||||
</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 { isLeft, isRight } from "fp-ts/lib/Either"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
import {
|
import {
|
||||||
updateRESTResponse,
|
updateRESTResponse,
|
||||||
restEndpoint$,
|
restEndpoint$,
|
||||||
@@ -220,6 +197,8 @@ import {
|
|||||||
useRESTRequestName,
|
useRESTRequestName,
|
||||||
getRESTSaveContext,
|
getRESTSaveContext,
|
||||||
getRESTRequest,
|
getRESTRequest,
|
||||||
|
restRequest$,
|
||||||
|
setRESTSaveContext,
|
||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
import { editRESTRequest } from "~/newstore/collections"
|
import { editRESTRequest } from "~/newstore/collections"
|
||||||
import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
||||||
@@ -227,6 +206,9 @@ import {
|
|||||||
useStreamSubscriber,
|
useStreamSubscriber,
|
||||||
useStream,
|
useStream,
|
||||||
useNuxt,
|
useNuxt,
|
||||||
|
useI18n,
|
||||||
|
useToast,
|
||||||
|
useReadonlyStream,
|
||||||
} 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"
|
||||||
@@ -234,6 +216,9 @@ import { useSetting } from "~/newstore/settings"
|
|||||||
import { overwriteRequestTeams } from "~/helpers/teams/utils"
|
import { overwriteRequestTeams } from "~/helpers/teams/utils"
|
||||||
import { apolloClient } from "~/helpers/apollo"
|
import { apolloClient } from "~/helpers/apollo"
|
||||||
import useWindowSize from "~/helpers/utils/useWindowSize"
|
import useWindowSize from "~/helpers/utils/useWindowSize"
|
||||||
|
import { createShortcode } from "~/helpers/backend/mutations/Shortcode"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
|
||||||
const methods = [
|
const methods = [
|
||||||
"GET",
|
"GET",
|
||||||
@@ -248,12 +233,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)
|
||||||
@@ -282,12 +264,16 @@ watch(loading, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const newSendRequest = async () => {
|
const newSendRequest = async () => {
|
||||||
|
if (newEndpoint.value === "" || /^\s+$/.test(newEndpoint.value)) {
|
||||||
|
toast.error(`${t("empty.endpoint")}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
// Double calling is because the function returns a TaskEither than should be executed
|
// Double calling is because the function returns a TaskEither than should be executed
|
||||||
const streamResult = await runRESTRequest$()()
|
const streamResult = await runRESTRequest$()()
|
||||||
|
|
||||||
// TODO: What if stream fetching failed (script execution errors ?) (isLeft)
|
|
||||||
if (isRight(streamResult)) {
|
if (isRight(streamResult)) {
|
||||||
subscribeToStream(
|
subscribeToStream(
|
||||||
streamResult.right,
|
streamResult.right,
|
||||||
@@ -305,6 +291,19 @@ const newSendRequest = async () => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else if (isLeft(streamResult)) {
|
||||||
|
loading.value = false
|
||||||
|
toast.error(`${t("error.script_fail")}`)
|
||||||
|
let error: Error
|
||||||
|
if (typeof streamResult.left === "string") {
|
||||||
|
error = { name: "RequestFailure", message: streamResult.left }
|
||||||
|
} else {
|
||||||
|
error = streamResult.left
|
||||||
|
}
|
||||||
|
updateRESTResponse({
|
||||||
|
type: "script_fail",
|
||||||
|
error,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +326,46 @@ const clearContent = () => {
|
|||||||
resetRESTRequest()
|
resetRESTRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyRequest = () => {
|
const copyLinkIcon = hasNavigatorShare ? ref("share-2") : ref("copy")
|
||||||
|
const shareLink = ref<string | null>("")
|
||||||
|
const fetchingShareLink = ref(false)
|
||||||
|
|
||||||
|
const shareButtonText = computed(() => {
|
||||||
|
if (shareLink.value) {
|
||||||
|
return shareLink.value
|
||||||
|
} else if (fetchingShareLink.value) {
|
||||||
|
return t("state.loading")
|
||||||
|
} else {
|
||||||
|
return t("request.copy_link")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const request = useReadonlyStream(restRequest$, getRESTRequest())
|
||||||
|
|
||||||
|
watch(request, () => {
|
||||||
|
shareLink.value = null
|
||||||
|
})
|
||||||
|
|
||||||
|
const copyRequest = async () => {
|
||||||
|
if (shareLink.value) {
|
||||||
|
copyShareLink(shareLink.value)
|
||||||
|
} else {
|
||||||
|
shareLink.value = ""
|
||||||
|
fetchingShareLink.value = true
|
||||||
|
const request = getRESTRequest()
|
||||||
|
const shortcodeResult = await createShortcode(request)()
|
||||||
|
if (E.isLeft(shortcodeResult)) {
|
||||||
|
toast.error(`${shortcodeResult.left.error}`)
|
||||||
|
shareLink.value = `${t("error.something_went_wrong")}`
|
||||||
|
} else if (E.isRight(shortcodeResult)) {
|
||||||
|
shareLink.value = `/${shortcodeResult.right.createShortcode.id}`
|
||||||
|
copyShareLink(shareLink.value)
|
||||||
|
}
|
||||||
|
fetchingShareLink.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyShareLink = (shareLink: string) => {
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
const time = new Date().toLocaleTimeString()
|
const time = new Date().toLocaleTimeString()
|
||||||
const date = new Date().toLocaleDateString()
|
const date = new Date().toLocaleDateString()
|
||||||
@@ -335,15 +373,15 @@ const copyRequest = () => {
|
|||||||
.share({
|
.share({
|
||||||
title: "Hoppscotch",
|
title: "Hoppscotch",
|
||||||
text: `Hoppscotch • Open source API development ecosystem at ${time} on ${date}`,
|
text: `Hoppscotch • Open source API development ecosystem at ${time} on ${date}`,
|
||||||
url: window.location.href,
|
url: `https://hopp.sh/r${shareLink}`,
|
||||||
})
|
})
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
} else {
|
} else {
|
||||||
copyToClipboard(window.location.href)
|
copyLinkIcon.value = "check"
|
||||||
$toast.success(`${t("state.copied_to_clipboard")}`, {
|
copyToClipboard(`https://hopp.sh/r${shareLink}`)
|
||||||
icon: "content_paste",
|
toast.success(`${t("state.copied_to_clipboard")}`)
|
||||||
})
|
setTimeout(() => (copyLinkIcon.value = "copy"), 2000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,10 +419,17 @@ const saveRequest = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (saveCtx.originLocation === "user-collection") {
|
if (saveCtx.originLocation === "user-collection") {
|
||||||
editRESTRequest(saveCtx.folderPath, saveCtx.requestIndex, getRESTRequest())
|
try {
|
||||||
$toast.success(`${t("request.saved")}`, {
|
editRESTRequest(
|
||||||
icon: "playlist_add_check",
|
saveCtx.folderPath,
|
||||||
})
|
saveCtx.requestIndex,
|
||||||
|
getRESTRequest()
|
||||||
|
)
|
||||||
|
toast.success(`${t("request.saved")}`)
|
||||||
|
} catch (e) {
|
||||||
|
setRESTSaveContext(null)
|
||||||
|
saveRequest()
|
||||||
|
}
|
||||||
} else if (saveCtx.originLocation === "team-collection") {
|
} else if (saveCtx.originLocation === "team-collection") {
|
||||||
const req = getRESTRequest()
|
const req = getRESTRequest()
|
||||||
|
|
||||||
@@ -397,20 +442,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,24 @@
|
|||||||
<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="flex flex-col flex-1 text-secondaryLight items-center justify-center"
|
||||||
flex flex-col flex-1
|
|
||||||
text-secondaryLight
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div class="flex space-x-2 pb-4 my-4">
|
<div class="flex space-x-2 my-4 pb-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 +39,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 +53,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'"
|
||||||
@@ -65,39 +62,59 @@
|
|||||||
<img
|
<img
|
||||||
:src="`/images/states/${$colorMode.value}/youre_lost.svg`"
|
:src="`/images/states/${$colorMode.value}/youre_lost.svg`"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="
|
class="flex-col object-contain object-center h-32 my-4 w-32 inline-flex"
|
||||||
flex-col
|
:alt="`${t('error.network_fail')}`"
|
||||||
my-4
|
|
||||||
object-contain object-center
|
|
||||||
h-32
|
|
||||||
w-32
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
:alt="$t('empty.network_fail')"
|
|
||||||
/>
|
/>
|
||||||
<span class="text-center font-semibold mb-2">
|
<span class="font-semibold text-center mb-2">
|
||||||
{{ $t("error.network_fail") }}
|
{{ t("error.network_fail") }}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-center text-secondaryLight mb-4 max-w-sm">
|
<span
|
||||||
{{ $t("helpers.network_fail") }}
|
class="max-w-sm text-secondaryLight text-center mb-4 whitespace-normal"
|
||||||
|
>
|
||||||
|
{{ t("helpers.network_fail") }}
|
||||||
</span>
|
</span>
|
||||||
<AppInterceptor />
|
<AppInterceptor />
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="response.type === 'script_fail'"
|
||||||
|
class="flex flex-col flex-1 p-4 items-center justify-center"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`/images/states/${$colorMode.value}/youre_lost.svg`"
|
||||||
|
loading="lazy"
|
||||||
|
class="flex-col object-contain object-center h-32 my-4 w-32 inline-flex"
|
||||||
|
:alt="`${t('error.script_fail')}`"
|
||||||
|
/>
|
||||||
|
<span class="font-semibold text-center mb-2">
|
||||||
|
{{ t("error.script_fail") }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="max-w-sm text-secondaryLight text-center mb-4 whitespace-normal"
|
||||||
|
>
|
||||||
|
{{ t("helpers.script_fail") }}
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="bg-primaryLight rounded font-mono w-full py-2 px-4 text-red-400 overflow-auto whitespace-normal"
|
||||||
|
>
|
||||||
|
{{ response.error.name }}: {{ response.error.message }}<br />
|
||||||
|
{{ response.error.stack }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="response.type === 'success' || 'fail'"
|
v-if="response.type === 'success' || 'fail'"
|
||||||
:class="statusCategory.className"
|
:class="statusCategory.className"
|
||||||
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 +127,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
|
||||||
@@ -118,7 +138,8 @@ const props = defineProps<{
|
|||||||
const statusCategory = computed(() => {
|
const statusCategory = computed(() => {
|
||||||
if (
|
if (
|
||||||
props.response.type === "loading" ||
|
props.response.type === "loading" ||
|
||||||
props.response.type === "network_fail"
|
props.response.type === "network_fail" ||
|
||||||
|
props.response.type === "script_fail"
|
||||||
)
|
)
|
||||||
return ""
|
return ""
|
||||||
return findStatusGroup(props.response.statusCode)
|
return findStatusGroup(props.response.statusCode)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection :label="`${$t('test.results')}`">
|
<AppSection :label="`${t('test.results')}`">
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
testResults &&
|
testResults &&
|
||||||
@@ -7,29 +7,19 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-dividerLight border-b
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="divide-dividerLight border-dividerLight border-b divide-y-4">
|
<div class="divide-dividerLight border-b border-dividerLight divide-y-4">
|
||||||
<div v-if="testResults.tests" class="divide-dividerLight divide-y-4">
|
<div v-if="testResults.tests" class="divide-dividerLight divide-y-4">
|
||||||
<HttpTestResultEntry
|
<HttpTestResultEntry
|
||||||
v-for="(result, index) in testResults.tests"
|
v-for="(result, index) in testResults.tests"
|
||||||
@@ -64,9 +54,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>
|
||||||
@@ -81,19 +69,19 @@
|
|||||||
<img
|
<img
|
||||||
: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 object-contain object-center h-16 my-4 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 +92,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)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
>
|
>
|
||||||
{{ testResults.description }}
|
{{ testResults.description }}
|
||||||
</span>
|
</span>
|
||||||
<div v-if="testResults.expectResults" class="divide-y divide-dividerLight">
|
<div v-if="testResults.expectResults" class="divide-dividerLight divide-y">
|
||||||
<HttpTestResultReport
|
<HttpTestResultReport
|
||||||
v-if="testResults.expectResults.length"
|
v-if="testResults.expectResults.length"
|
||||||
:test-results="testResults"
|
:test-results="testResults"
|
||||||
|
|||||||
@@ -1,39 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppSection id="script" :label="`${$t('test.script')}`">
|
<AppSection id="script" :label="`${t('test.script')}`">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-upperSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-upperSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@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"
|
||||||
/>
|
/>
|
||||||
@@ -44,28 +34,18 @@
|
|||||||
<div ref="testScriptEditor"></div>
|
<div ref="testScriptEditor"></div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary h-full top-upperTertiaryStickyFold min-w-46 max-w-1/3 p-4 z-9 sticky overflow-auto"
|
||||||
bg-primary
|
|
||||||
h-full
|
|
||||||
top-upperTertiaryStickyFold
|
|
||||||
min-w-46
|
|
||||||
max-w-1/3
|
|
||||||
p-4
|
|
||||||
z-9
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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 +62,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()
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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"
|
||||||
/>
|
/>
|
||||||
@@ -30,38 +20,19 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(header, index) in headers"
|
v-for="(header, index) in headers"
|
||||||
:key="`header-${index}`"
|
:key="`header-${index}`"
|
||||||
class="
|
class="divide-dividerLight divide-x border-b border-dividerLight flex group"
|
||||||
divide-x divide-dividerLight
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex
|
|
||||||
group
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="
|
class="flex flex-1 min-w-0 py-2 px-4 transition group-hover:text-secondaryDark"
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span class="rounded-sm select-all truncate">
|
<span class="rounded-sm truncate select-all">
|
||||||
{{ header.key }}
|
{{ header.key }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="
|
class="flex flex-1 min-w-0 py-2 px-4 transition group-hover:text-secondaryDark"
|
||||||
flex flex-1
|
|
||||||
min-w-0
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
transition
|
|
||||||
group-hover:text-secondaryDark
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span class="rounded-sm select-all truncate">
|
<span class="rounded-sm truncate select-all">
|
||||||
{{ header.value }}
|
{{ header.value }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@@ -69,28 +40,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 "@hoppscotch/data"
|
||||||
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>
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col flex-1">
|
<div class="flex flex-col flex-1">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
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 +28,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 +36,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 +54,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 +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)
|
||||||
@@ -140,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<label class="font-semibold text-secondaryLight">
|
<label class="font-semibold text-secondaryLight">
|
||||||
{{ $t("response.body") }}
|
{{ $t("response.body") }}
|
||||||
@@ -103,9 +93,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)
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
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 +27,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"
|
||||||
/>
|
/>
|
||||||
@@ -46,17 +36,7 @@
|
|||||||
<div ref="jsonResponse"></div>
|
<div ref="jsonResponse"></div>
|
||||||
<div
|
<div
|
||||||
v-if="outlinePath"
|
v-if="outlinePath"
|
||||||
class="
|
class="bg-primaryLight border-t border-dividerLight flex flex-nowrap flex-1 px-2 bottom-0 z-10 sticky overflow-auto hide-scrollbar"
|
||||||
bg-primaryLight
|
|
||||||
border-t border-dividerLight
|
|
||||||
flex flex-nowrap flex-1
|
|
||||||
px-2
|
|
||||||
bottom-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
overflow-auto
|
|
||||||
hide-scrollbar
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in outlinePath"
|
v-for="(item, index) in outlinePath"
|
||||||
@@ -144,7 +124,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 +134,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 +213,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 +233,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>
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
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 +27,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 +38,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 +106,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 +117,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>
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 top-lowerSecondaryStickyFold pl-4 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
top-lowerSecondaryStickyFold
|
|
||||||
pl-4
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<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="wrap-text"
|
||||||
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
@click.native.prevent="linewrapEnabled = !linewrapEnabled"
|
||||||
/>
|
/>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
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 +27,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 +38,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 +106,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 +117,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>
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="cursor-pointer flex h-5 w-5 relative items-center justify-center">
|
<div class="cursor-pointer flex h-5 w-5 relative items-center justify-center">
|
||||||
<img
|
<img
|
||||||
class="
|
class="bg-primaryDark rounded-full object-cover object-center h-5 transition w-5 absolute"
|
||||||
bg-primaryDark bg-primaryLight
|
|
||||||
rounded-full
|
|
||||||
object-cover object-center
|
|
||||||
h-5
|
|
||||||
transition
|
|
||||||
w-5
|
|
||||||
absolute
|
|
||||||
"
|
|
||||||
:src="url"
|
:src="url"
|
||||||
:alt="alt"
|
:alt="alt"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
@@ -17,16 +9,7 @@
|
|||||||
<div class="rounded-full shadow-inner inset-0 absolute"></div>
|
<div class="rounded-full shadow-inner inset-0 absolute"></div>
|
||||||
<span
|
<span
|
||||||
v-if="indicator"
|
v-if="indicator"
|
||||||
class="
|
class="border-primary rounded-full border-2 h-2.5 -top-0.5 -right-0.5 w-2.5 absolute"
|
||||||
border-primary
|
|
||||||
rounded-full
|
|
||||||
border-2
|
|
||||||
h-2.5
|
|
||||||
-top-0.5
|
|
||||||
-right-0.5
|
|
||||||
w-2.5
|
|
||||||
absolute
|
|
||||||
"
|
|
||||||
:class="indicatorStyles"
|
:class="indicatorStyles"
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div
|
<div
|
||||||
class="
|
class="bg-primary border-b border-dividerLight flex flex-1 pl-4 top-0 z-10 sticky items-center justify-between"
|
||||||
bg-primary
|
|
||||||
border-b border-dividerLight
|
|
||||||
flex flex-1
|
|
||||||
pl-4
|
|
||||||
top-0
|
|
||||||
z-10
|
|
||||||
sticky
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<label for="log" class="font-semibold text-secondaryLight py-2">
|
<label for="log" class="font-semibold text-secondaryLight py-2">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
@@ -26,7 +16,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 +24,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: () => [] },
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
>
|
>
|
||||||
<Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
|
<Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
|
||||||
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane
|
||||||
|
:size="COLUMN_LAYOUT ? 45 : 50"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<div
|
<div
|
||||||
class="bg-primary flex flex-col space-y-4 p-4 top-0 z-10 sticky"
|
class="bg-primary flex flex-col space-y-4 p-4 top-0 z-10 sticky"
|
||||||
@@ -21,18 +24,7 @@
|
|||||||
type="url"
|
type="url"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent
|
|
||||||
focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
:placeholder="$t('mqtt.url')"
|
:placeholder="$t('mqtt.url')"
|
||||||
:disabled="connectionState"
|
:disabled="connectionState"
|
||||||
@keyup.enter="validUrl ? toggleConnection() : null"
|
@keyup.enter="validUrl ? toggleConnection() : null"
|
||||||
@@ -71,7 +63,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane
|
||||||
|
:size="COLUMN_LAYOUT ? 65 : 50"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<RealtimeLog :title="$t('mqtt.log')" :log="log" />
|
<RealtimeLog :title="$t('mqtt.log')" :log="log" />
|
||||||
</AppSection>
|
</AppSection>
|
||||||
@@ -125,13 +120,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="
|
class="border-t border-dividerLight flex flex-col flex-1 mt-4 p-4 inline-flex"
|
||||||
border-t border-dividerLight
|
|
||||||
flex flex-col flex-1
|
|
||||||
mt-4
|
|
||||||
p-4
|
|
||||||
inline-flex
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<label for="sub_topic" class="font-semibold text-secondaryLight">
|
<label for="sub_topic" class="font-semibold text-secondaryLight">
|
||||||
{{ $t("mqtt.topic") }}
|
{{ $t("mqtt.topic") }}
|
||||||
@@ -172,6 +161,22 @@ import debounce from "lodash/debounce"
|
|||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
import { useSetting } from "~/newstore/settings"
|
import { useSetting } from "~/newstore/settings"
|
||||||
import useWindowSize from "~/helpers/utils/useWindowSize"
|
import useWindowSize from "~/helpers/utils/useWindowSize"
|
||||||
|
import {
|
||||||
|
MQTTEndpoint$,
|
||||||
|
setMQTTEndpoint,
|
||||||
|
MQTTConnectingState$,
|
||||||
|
MQTTConnectionState$,
|
||||||
|
setMQTTConnectingState,
|
||||||
|
setMQTTConnectionState,
|
||||||
|
MQTTSubscriptionState$,
|
||||||
|
setMQTTSubscriptionState,
|
||||||
|
MQTTSocket$,
|
||||||
|
setMQTTSocket,
|
||||||
|
MQTTLog$,
|
||||||
|
setMQTTLog,
|
||||||
|
addMQTTLogLine,
|
||||||
|
} from "~/newstore/MQTTSession"
|
||||||
|
import { useStream } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { Splitpanes, Pane },
|
components: { Splitpanes, Pane },
|
||||||
@@ -181,21 +186,33 @@ export default defineComponent({
|
|||||||
SIDEBAR: useSetting("SIDEBAR"),
|
SIDEBAR: useSetting("SIDEBAR"),
|
||||||
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
||||||
SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
|
SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
|
||||||
|
url: useStream(MQTTEndpoint$, "", setMQTTEndpoint),
|
||||||
|
connectionState: useStream(
|
||||||
|
MQTTConnectionState$,
|
||||||
|
false,
|
||||||
|
setMQTTConnectionState
|
||||||
|
),
|
||||||
|
connectingState: useStream(
|
||||||
|
MQTTConnectingState$,
|
||||||
|
false,
|
||||||
|
setMQTTConnectingState
|
||||||
|
),
|
||||||
|
subscriptionState: useStream(
|
||||||
|
MQTTSubscriptionState$,
|
||||||
|
false,
|
||||||
|
setMQTTSubscriptionState
|
||||||
|
),
|
||||||
|
log: useStream(MQTTLog$, null, setMQTTLog),
|
||||||
|
client: useStream(MQTTSocket$, null, setMQTTSocket),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
url: "wss://test.mosquitto.org:8081",
|
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
client: null,
|
|
||||||
pub_topic: "",
|
pub_topic: "",
|
||||||
sub_topic: "",
|
sub_topic: "",
|
||||||
msg: "",
|
msg: "",
|
||||||
connectionState: false,
|
|
||||||
connectingState: false,
|
|
||||||
log: null,
|
|
||||||
manualDisconnect: false,
|
manualDisconnect: false,
|
||||||
subscriptionState: false,
|
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
}
|
}
|
||||||
@@ -272,7 +289,7 @@ export default defineComponent({
|
|||||||
onConnectionFailure() {
|
onConnectionFailure() {
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload: this.$t("error.something_went_wrong"),
|
payload: this.$t("error.something_went_wrong"),
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
@@ -282,18 +299,16 @@ export default defineComponent({
|
|||||||
onConnectionSuccess() {
|
onConnectionSuccess() {
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionState = true
|
this.connectionState = true
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload: this.$t("state.connected_to", { name: this.url }),
|
payload: this.$t("state.connected_to", { name: this.url }),
|
||||||
source: "info",
|
source: "info",
|
||||||
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({
|
addMQTTLogLine({
|
||||||
payload: `Message: ${payloadString} arrived on topic: ${destinationName}`,
|
payload: `Message: ${payloadString} arrived on topic: ${destinationName}`,
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "var(--accent-color)",
|
color: "var(--accent-color)",
|
||||||
@@ -310,7 +325,7 @@ export default defineComponent({
|
|||||||
disconnect() {
|
disconnect() {
|
||||||
this.manualDisconnect = true
|
this.manualDisconnect = true
|
||||||
this.client.disconnect()
|
this.client.disconnect()
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload: this.$t("state.disconnected_from", { name: this.url }),
|
payload: this.$t("state.disconnected_from", { name: this.url }),
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
@@ -321,13 +336,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
|
||||||
@@ -335,14 +346,14 @@ export default defineComponent({
|
|||||||
publish() {
|
publish() {
|
||||||
try {
|
try {
|
||||||
this.client.publish(this.pub_topic, this.msg, 0, false)
|
this.client.publish(this.pub_topic, this.msg, 0, false)
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload: `Published message: ${this.msg} to topic: ${this.pub_topic}`,
|
payload: `Published message: ${this.msg} to topic: ${this.pub_topic}`,
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "var(--accent-color)",
|
color: "var(--accent-color)",
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload:
|
payload:
|
||||||
this.$t("error.something_went_wrong") +
|
this.$t("error.something_went_wrong") +
|
||||||
`while publishing msg: ${this.msg} to topic: ${this.pub_topic}`,
|
`while publishing msg: ${this.msg} to topic: ${this.pub_topic}`,
|
||||||
@@ -366,7 +377,7 @@ export default defineComponent({
|
|||||||
onFailure: this.usubFailure,
|
onFailure: this.usubFailure,
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload:
|
payload:
|
||||||
this.$t("error.something_went_wrong") +
|
this.$t("error.something_went_wrong") +
|
||||||
`while subscribing to topic: ${this.sub_topic}`,
|
`while subscribing to topic: ${this.sub_topic}`,
|
||||||
@@ -378,7 +389,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
usubSuccess() {
|
usubSuccess() {
|
||||||
this.subscriptionState = !this.subscriptionState
|
this.subscriptionState = !this.subscriptionState
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload:
|
payload:
|
||||||
`Successfully ` +
|
`Successfully ` +
|
||||||
(this.subscriptionState ? "subscribed" : "unsubscribed") +
|
(this.subscriptionState ? "subscribed" : "unsubscribed") +
|
||||||
@@ -389,7 +400,7 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
usubFailure() {
|
usubFailure() {
|
||||||
this.log.push({
|
addMQTTLogLine({
|
||||||
payload:
|
payload:
|
||||||
`Failed to ` +
|
`Failed to ` +
|
||||||
(this.subscriptionState ? "unsubscribe" : "subscribe") +
|
(this.subscriptionState ? "unsubscribe" : "subscribe") +
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
>
|
>
|
||||||
<Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
|
<Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
|
||||||
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane
|
||||||
|
:size="COLUMN_LAYOUT ? 45 : 50"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="request">
|
<AppSection label="request">
|
||||||
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<div class="space-x-2 flex-1 inline-flex">
|
<div class="space-x-2 flex-1 inline-flex">
|
||||||
@@ -28,21 +31,7 @@
|
|||||||
id="client-version"
|
id="client-version"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
title="socket.io-client version"
|
title="socket.io-client version"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded-l cursor-pointer flex font-semibold text-secondaryDark py-2 px-4 w-26 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded-l
|
|
||||||
cursor-pointer
|
|
||||||
flex
|
|
||||||
font-semibold
|
|
||||||
text-secondaryDark
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
w-26
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent
|
|
||||||
focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
:value="`Client ${clientVersion}`"
|
:value="`Client ${clientVersion}`"
|
||||||
readonly
|
readonly
|
||||||
:disabled="connectionState"
|
:disabled="connectionState"
|
||||||
@@ -64,18 +53,7 @@
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:class="{ error: !urlValid }"
|
:class="{ error: !urlValid }"
|
||||||
class="
|
class="bg-primaryLight border border-divider flex flex-1 text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
flex flex-1
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent
|
|
||||||
focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
:placeholder="$t('socketio.url')"
|
:placeholder="$t('socketio.url')"
|
||||||
:disabled="connectionState"
|
:disabled="connectionState"
|
||||||
@keyup.enter="urlValid ? toggleConnection() : null"
|
@keyup.enter="urlValid ? toggleConnection() : null"
|
||||||
@@ -83,19 +61,7 @@
|
|||||||
<input
|
<input
|
||||||
id="socketio-path"
|
id="socketio-path"
|
||||||
v-model="path"
|
v-model="path"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded-r flex flex-1 text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded-r
|
|
||||||
flex flex-1
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent
|
|
||||||
focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:disabled="connectionState"
|
:disabled="connectionState"
|
||||||
@keyup.enter="urlValid ? toggleConnection() : null"
|
@keyup.enter="urlValid ? toggleConnection() : null"
|
||||||
@@ -118,9 +84,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane
|
||||||
|
:size="COLUMN_LAYOUT ? 65 : 50"
|
||||||
|
class="hide-scrollbar !overflow-auto"
|
||||||
|
>
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<RealtimeLog :title="$t('socketio.log')" :log="communication.log" />
|
<RealtimeLog :title="$t('socketio.log')" :log="log" />
|
||||||
</AppSection>
|
</AppSection>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
@@ -158,7 +127,6 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('add.new')"
|
:title="$t('add.new')"
|
||||||
svg="plus"
|
svg="plus"
|
||||||
class="rounded"
|
|
||||||
@click.native="addCommunicationInput"
|
@click.native="addCommunicationInput"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -184,7 +152,6 @@
|
|||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="$t('action.remove')"
|
:title="$t('action.remove')"
|
||||||
svg="trash"
|
svg="trash"
|
||||||
class="rounded"
|
|
||||||
color="red"
|
color="red"
|
||||||
outline
|
outline
|
||||||
@click.native="removeCommunicationInput({ index })"
|
@click.native="removeCommunicationInput({ index })"
|
||||||
@@ -219,6 +186,24 @@ import debounce from "lodash/debounce"
|
|||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
import { useSetting } from "~/newstore/settings"
|
import { useSetting } from "~/newstore/settings"
|
||||||
import useWindowSize from "~/helpers/utils/useWindowSize"
|
import useWindowSize from "~/helpers/utils/useWindowSize"
|
||||||
|
import {
|
||||||
|
SIOEndpoint$,
|
||||||
|
setSIOEndpoint,
|
||||||
|
SIOVersion$,
|
||||||
|
setSIOVersion,
|
||||||
|
SIOPath$,
|
||||||
|
setSIOPath,
|
||||||
|
SIOConnectionState$,
|
||||||
|
SIOConnectingState$,
|
||||||
|
setSIOConnectionState,
|
||||||
|
setSIOConnectingState,
|
||||||
|
SIOSocket$,
|
||||||
|
setSIOSocket,
|
||||||
|
SIOLog$,
|
||||||
|
setSIOLog,
|
||||||
|
addSIOLogLine,
|
||||||
|
} from "~/newstore/SocketIOSession"
|
||||||
|
import { useStream } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
const socketIoClients = {
|
const socketIoClients = {
|
||||||
v4: ClientV4,
|
v4: ClientV4,
|
||||||
@@ -235,20 +220,27 @@ export default defineComponent({
|
|||||||
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
||||||
SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
|
SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
|
||||||
socketIoClients,
|
socketIoClients,
|
||||||
|
url: useStream(SIOEndpoint$, "", setSIOEndpoint),
|
||||||
|
clientVersion: useStream(SIOVersion$, "", setSIOVersion),
|
||||||
|
path: useStream(SIOPath$, "", setSIOPath),
|
||||||
|
connectingState: useStream(
|
||||||
|
SIOConnectingState$,
|
||||||
|
false,
|
||||||
|
setSIOConnectingState
|
||||||
|
),
|
||||||
|
connectionState: useStream(
|
||||||
|
SIOConnectionState$,
|
||||||
|
false,
|
||||||
|
setSIOConnectionState
|
||||||
|
),
|
||||||
|
io: useStream(SIOSocket$, null, setSIOSocket),
|
||||||
|
log: useStream(SIOLog$, [], setSIOLog),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// default version is set to v4
|
|
||||||
clientVersion: "v4",
|
|
||||||
url: "wss://hoppscotch-socketio.herokuapp.com",
|
|
||||||
path: "/socket.io",
|
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
connectingState: false,
|
|
||||||
connectionState: false,
|
|
||||||
io: null,
|
|
||||||
communication: {
|
communication: {
|
||||||
log: null,
|
|
||||||
eventName: "",
|
eventName: "",
|
||||||
inputs: [""],
|
inputs: [""],
|
||||||
},
|
},
|
||||||
@@ -298,7 +290,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
connect() {
|
connect() {
|
||||||
this.connectingState = true
|
this.connectingState = true
|
||||||
this.communication.log = [
|
this.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("state.connecting_to", { name: this.url }),
|
payload: this.$t("state.connecting_to", { name: this.url }),
|
||||||
source: "info",
|
source: "info",
|
||||||
@@ -317,7 +309,7 @@ export default defineComponent({
|
|||||||
this.io.on("connect", () => {
|
this.io.on("connect", () => {
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionState = true
|
this.connectionState = true
|
||||||
this.communication.log = [
|
this.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("state.connected_to", { name: this.url }),
|
payload: this.$t("state.connected_to", { name: this.url }),
|
||||||
source: "info",
|
source: "info",
|
||||||
@@ -325,13 +317,11 @@ 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
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: `[${eventName}] ${message ? JSON.stringify(message) : ""}`,
|
payload: `[${eventName}] ${message ? JSON.stringify(message) : ""}`,
|
||||||
source: "server",
|
source: "server",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
@@ -349,21 +339,17 @@ export default defineComponent({
|
|||||||
this.io.on("disconnect", () => {
|
this.io.on("disconnect", () => {
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: this.$t("state.disconnected_from", { name: this.url }),
|
payload: this.$t("state.disconnected_from", { name: this.url }),
|
||||||
source: "info",
|
source: "info",
|
||||||
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({
|
||||||
@@ -377,14 +363,14 @@ export default defineComponent({
|
|||||||
this.disconnect()
|
this.disconnect()
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionState = false
|
this.connectionState = false
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: this.$t("error.something_went_wrong"),
|
payload: this.$t("error.something_went_wrong"),
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
})
|
})
|
||||||
if (error !== null)
|
if (error !== null)
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: error,
|
payload: error,
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
@@ -406,14 +392,14 @@ export default defineComponent({
|
|||||||
if (this.io) {
|
if (this.io) {
|
||||||
this.io.emit(eventName, ...messages, (data) => {
|
this.io.emit(eventName, ...messages, (data) => {
|
||||||
// receive response from server
|
// receive response from server
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: `[${eventName}] ${JSON.stringify(data)}`,
|
payload: `[${eventName}] ${JSON.stringify(data)}`,
|
||||||
source: "server",
|
source: "server",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.communication.log.push({
|
addSIOLogLine({
|
||||||
payload: `[${eventName}] ${JSON.stringify(messages)}`,
|
payload: `[${eventName}] ${JSON.stringify(messages)}`,
|
||||||
source: "client",
|
source: "client",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane :size="COLUMN_LAYOUT ? 45 : 50" class="hide-scrollbar !overflow-auto">
|
||||||
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
<div class="bg-primary flex p-4 top-0 z-10 sticky">
|
||||||
<div class="space-x-2 flex-1 inline-flex">
|
<div class="space-x-2 flex-1 inline-flex">
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
@@ -10,51 +10,21 @@
|
|||||||
type="url"
|
type="url"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:class="{ error: !serverValid }"
|
:class="{ error: !serverValid }"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded-l flex flex-1 text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded-l
|
|
||||||
flex flex-1
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
:placeholder="$t('sse.url')"
|
:placeholder="$t('sse.url')"
|
||||||
:disabled="connectionSSEState"
|
:disabled="connectionSSEState"
|
||||||
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
for="event-type"
|
for="event-type"
|
||||||
class="
|
class="bg-primaryLight border-t border-b border-divider font-semibold text-secondaryLight py-2 px-4 truncate"
|
||||||
bg-primaryLight
|
|
||||||
border-t border-b border-divider
|
|
||||||
font-semibold
|
|
||||||
text-secondaryLight
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
truncate
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ $t("sse.event_type") }}
|
{{ $t("sse.event_type") }}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="event-type"
|
id="event-type"
|
||||||
v-model="eventType"
|
v-model="eventType"
|
||||||
class="
|
class="bg-primaryLight border border-divider rounded-r flex flex-1 text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
|
||||||
bg-primaryLight
|
|
||||||
border border-divider
|
|
||||||
rounded-r
|
|
||||||
flex flex-1
|
|
||||||
text-secondaryDark
|
|
||||||
w-full
|
|
||||||
py-2
|
|
||||||
px-4
|
|
||||||
hover:border-dividerDark
|
|
||||||
focus-visible:bg-transparent focus-visible:border-dividerDark
|
|
||||||
"
|
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
:disabled="connectionSSEState"
|
:disabled="connectionSSEState"
|
||||||
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
@keyup.enter="serverValid ? toggleSSEConnection() : null"
|
||||||
@@ -74,11 +44,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane class="hide-scrollbar !overflow-auto">
|
<Pane :size="COLUMN_LAYOUT ? 65 : 50" class="hide-scrollbar !overflow-auto">
|
||||||
<AppSection label="response">
|
<AppSection label="response">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<RealtimeLog :title="$t('sse.log')" :log="events.log" />
|
<RealtimeLog :title="$t('sse.log')" :log="log" />
|
||||||
<div id="result"></div>
|
<div id="result"></div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -94,26 +64,47 @@ import "splitpanes/dist/splitpanes.css"
|
|||||||
import debounce from "lodash/debounce"
|
import debounce from "lodash/debounce"
|
||||||
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
|
||||||
import { useSetting } from "~/newstore/settings"
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
import {
|
||||||
|
SSEEndpoint$,
|
||||||
|
setSSEEndpoint,
|
||||||
|
SSEEventType$,
|
||||||
|
setSSEEventType,
|
||||||
|
SSESocket$,
|
||||||
|
setSSESocket,
|
||||||
|
SSEConnectingState$,
|
||||||
|
SSEConnectionState$,
|
||||||
|
setSSEConnectionState,
|
||||||
|
setSSEConnectingState,
|
||||||
|
SSELog$,
|
||||||
|
setSSELog,
|
||||||
|
addSSELogLine,
|
||||||
|
} from "~/newstore/SSESession"
|
||||||
|
import { useStream } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { Splitpanes, Pane },
|
components: { Splitpanes, Pane },
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
|
||||||
|
connectionSSEState: useStream(
|
||||||
|
SSEConnectionState$,
|
||||||
|
false,
|
||||||
|
setSSEConnectionState
|
||||||
|
),
|
||||||
|
connectingState: useStream(
|
||||||
|
SSEConnectingState$,
|
||||||
|
false,
|
||||||
|
setSSEConnectingState
|
||||||
|
),
|
||||||
|
server: useStream(SSEEndpoint$, "", setSSEEndpoint),
|
||||||
|
eventType: useStream(SSEEventType$, "", setSSEEventType),
|
||||||
|
sse: useStream(SSESocket$, null, setSSESocket),
|
||||||
|
log: useStream(SSELog$, [], setSSELog),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
connectionSSEState: false,
|
|
||||||
connectingState: false,
|
|
||||||
server: "https://express-eventsource.herokuapp.com/events",
|
|
||||||
isUrlValid: true,
|
isUrlValid: true,
|
||||||
sse: null,
|
|
||||||
events: {
|
|
||||||
log: null,
|
|
||||||
input: "",
|
|
||||||
},
|
|
||||||
eventType: "data",
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -150,7 +141,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
start() {
|
start() {
|
||||||
this.connectingState = true
|
this.connectingState = true
|
||||||
this.events.log = [
|
this.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("state.connecting_to", { name: this.server }),
|
payload: this.$t("state.connecting_to", { name: this.server }),
|
||||||
source: "info",
|
source: "info",
|
||||||
@@ -163,7 +154,7 @@ export default defineComponent({
|
|||||||
this.sse.onopen = () => {
|
this.sse.onopen = () => {
|
||||||
this.connectingState = false
|
this.connectingState = false
|
||||||
this.connectionSSEState = true
|
this.connectionSSEState = true
|
||||||
this.events.log = [
|
this.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("state.connected_to", { name: this.server }),
|
payload: this.$t("state.connected_to", { name: this.server }),
|
||||||
source: "info",
|
source: "info",
|
||||||
@@ -171,16 +162,14 @@ 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()
|
||||||
}
|
}
|
||||||
this.sse.onclose = () => {
|
this.sse.onclose = () => {
|
||||||
this.connectionSSEState = false
|
this.connectionSSEState = false
|
||||||
this.events.log.push({
|
addSSELogLine({
|
||||||
payload: this.$t("state.disconnected_from", {
|
payload: this.$t("state.disconnected_from", {
|
||||||
name: this.server,
|
name: this.server,
|
||||||
}),
|
}),
|
||||||
@@ -188,12 +177,10 @@ 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({
|
addSSELogLine({
|
||||||
payload: data,
|
payload: data,
|
||||||
source: "server",
|
source: "server",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
@@ -201,12 +188,10 @@ 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.log = [
|
||||||
{
|
{
|
||||||
payload: this.$t("error.browser_support_sse"),
|
payload: this.$t("error.browser_support_sse"),
|
||||||
source: "info",
|
source: "info",
|
||||||
@@ -223,14 +208,14 @@ export default defineComponent({
|
|||||||
handleSSEError(error) {
|
handleSSEError(error) {
|
||||||
this.stop()
|
this.stop()
|
||||||
this.connectionSSEState = false
|
this.connectionSSEState = false
|
||||||
this.events.log.push({
|
addSSELogLine({
|
||||||
payload: this.$t("error.something_went_wrong"),
|
payload: this.$t("error.something_went_wrong"),
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
ts: new Date().toLocaleTimeString(),
|
ts: new Date().toLocaleTimeString(),
|
||||||
})
|
})
|
||||||
if (error !== null)
|
if (error !== null)
|
||||||
this.events.log.push({
|
addSSELogLine({
|
||||||
payload: error,
|
payload: error,
|
||||||
source: "info",
|
source: "info",
|
||||||
color: "#ff5555",
|
color: "#ff5555",
|
||||||
|
|||||||