Compare commits
120 Commits
2024.3.0
...
refactor/w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c74d0f865 | ||
|
|
8b930a6d3d | ||
|
|
f4a37f19c9 | ||
|
|
86b17e2bd3 | ||
|
|
e0083aa70d | ||
|
|
25b0818016 | ||
|
|
648cc8f5bd | ||
|
|
6032cbb17b | ||
|
|
52bff8ee68 | ||
|
|
e342e53db1 | ||
|
|
141652ffb6 | ||
|
|
bb57b2248c | ||
|
|
5d8da5fe49 | ||
|
|
c8f0142b16 | ||
|
|
2f2273ee2c | ||
|
|
b239b6b4a6 | ||
|
|
bbac317b71 | ||
|
|
412daa4d17 | ||
|
|
0abdc63f0e | ||
|
|
9e8112a4e5 | ||
|
|
5aa57fce3f | ||
|
|
8b65090dfb | ||
|
|
7ca94a99b7 | ||
|
|
fe3adeeb17 | ||
|
|
3a195711a4 | ||
|
|
6cde6200ae | ||
|
|
e5e1260632 | ||
|
|
90c9f2a9b1 | ||
|
|
db9ba17529 | ||
|
|
197d253e8b | ||
|
|
cd92dfec47 | ||
|
|
8467417e7a | ||
|
|
f6067f14aa | ||
|
|
3fd85df84b | ||
|
|
01573cc51c | ||
|
|
b19486ea03 | ||
|
|
a729dfcacb | ||
|
|
62612e6c51 | ||
|
|
f87a4c81d8 | ||
|
|
116f2fd279 | ||
|
|
7e2deaac5b | ||
|
|
240b131e06 | ||
|
|
5b3986a53f | ||
|
|
84fc31e8a9 | ||
|
|
c0978c3b20 | ||
|
|
d70d5bdb16 | ||
|
|
c30ee5becc | ||
|
|
5a64cdb7bc | ||
|
|
89f2479845 | ||
|
|
46654853f0 | ||
|
|
af7e6b70cd | ||
|
|
7c52c6b79d | ||
|
|
fe01322bf7 | ||
|
|
0a0f441da1 | ||
|
|
d0c7c4a245 | ||
|
|
076006c4a6 | ||
|
|
6ed9c09f06 | ||
|
|
8483339005 | ||
|
|
cd23bb63c1 | ||
|
|
f4ea999d2d | ||
|
|
c43e4fcefd | ||
|
|
316dc8f759 | ||
|
|
89f7c2ce5e | ||
|
|
0d00826019 | ||
|
|
00285df348 | ||
|
|
b821f452cf | ||
|
|
faa0bf7714 | ||
|
|
3a176f6620 | ||
|
|
7549e456c8 | ||
|
|
68795a5017 | ||
|
|
b0c72fd295 | ||
|
|
63eca80ff6 | ||
|
|
30b6a67505 | ||
|
|
97899ec023 | ||
|
|
2c47a63ca0 | ||
|
|
a0e373a4f3 | ||
|
|
392b2fc48d | ||
|
|
c1a8a871d2 | ||
|
|
1abbdb0fe0 | ||
|
|
f0f504d10e | ||
|
|
f0dab55c99 | ||
|
|
d6a8e60239 | ||
|
|
89bcc58de6 | ||
|
|
ab7df212c2 | ||
|
|
29e25b0ead | ||
|
|
f8ac6dfeb1 | ||
|
|
7d2d335b37 | ||
|
|
76875db865 | ||
|
|
96e2d87b57 | ||
|
|
be353d9f72 | ||
|
|
38bc2c12c3 | ||
|
|
97644fa508 | ||
|
|
eb3446ae23 | ||
|
|
6c29961d09 | ||
|
|
ef1117d8cc | ||
|
|
5c4b651aee | ||
|
|
391e5a20f5 | ||
|
|
4b8f3bd8da | ||
|
|
94248076e6 | ||
|
|
eecc3db4e9 | ||
|
|
426e7594f4 | ||
|
|
934dc473f0 | ||
|
|
be57255bf7 | ||
|
|
f89561da54 | ||
|
|
c2c4e620c2 | ||
|
|
844eee0fa4 | ||
|
|
d21bb65511 | ||
|
|
4f614f7257 | ||
|
|
0e2887b4e9 | ||
|
|
18652ce400 | ||
|
|
08c655235d | ||
|
|
51412549e8 | ||
|
|
22c6eabd13 | ||
|
|
a079e0f04b | ||
|
|
375d53263a | ||
|
|
57ef3e085f | ||
|
|
9fb6e59e36 | ||
|
|
1b0802b0e6 | ||
|
|
fb45fe4627 | ||
|
|
0f592d1789 |
15
.github/workflows/tests.yml
vendored
15
.github/workflows/tests.yml
vendored
@@ -17,22 +17,21 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup environment
|
||||
run: mv .env.example .env
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 8
|
||||
run_install: true
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Run tests
|
||||
run: pnpm test
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"vue": "3.3.9"
|
||||
"vue": "3.4.27"
|
||||
},
|
||||
"packageExtensions": {
|
||||
"httpsnippet@3.0.1": {
|
||||
"peerDependencies": {
|
||||
"dependencies": {
|
||||
"ajv": "6.12.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:18.8.0 AS builder
|
||||
FROM node:20.12.2 AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"assets": [
|
||||
"**/*.hbs"
|
||||
],
|
||||
"assets": [{ "include": "mailer/templates/**/*", "outDir": "dist" }],
|
||||
"watchAssets": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hoppscotch-backend",
|
||||
"version": "2024.3.0",
|
||||
"version": "2024.3.3",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
@@ -35,6 +35,7 @@
|
||||
"@nestjs/passport": "10.0.2",
|
||||
"@nestjs/platform-express": "10.2.7",
|
||||
"@nestjs/schedule": "4.0.1",
|
||||
"@nestjs/terminus": "10.2.3",
|
||||
"@nestjs/throttler": "5.0.1",
|
||||
"@prisma/client": "5.8.1",
|
||||
"argon2": "0.30.3",
|
||||
@@ -121,4 +122,4 @@
|
||||
"^src/(.*)$": "<rootDir>/$1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { loadInfraConfiguration } from './infra-config/helper';
|
||||
import { MailerModule } from './mailer/mailer.module';
|
||||
import { PosthogModule } from './posthog/posthog.module';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { HealthModule } from './health/health.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -100,6 +101,7 @@ import { ScheduleModule } from '@nestjs/schedule';
|
||||
InfraConfigModule,
|
||||
PosthogModule,
|
||||
ScheduleModule.forRoot(),
|
||||
HealthModule,
|
||||
],
|
||||
providers: [GQLComplexityPlugin],
|
||||
controllers: [AppController],
|
||||
|
||||
24
packages/hoppscotch-backend/src/health/health.controller.ts
Normal file
24
packages/hoppscotch-backend/src/health/health.controller.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import {
|
||||
HealthCheck,
|
||||
HealthCheckService,
|
||||
PrismaHealthIndicator,
|
||||
} from '@nestjs/terminus';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
constructor(
|
||||
private health: HealthCheckService,
|
||||
private prismaHealth: PrismaHealthIndicator,
|
||||
private prisma: PrismaService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@HealthCheck()
|
||||
check() {
|
||||
return this.health.check([
|
||||
async () => this.prismaHealth.pingCheck('database', this.prisma),
|
||||
]);
|
||||
}
|
||||
}
|
||||
10
packages/hoppscotch-backend/src/health/health.module.ts
Normal file
10
packages/hoppscotch-backend/src/health/health.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HealthController } from './health.controller';
|
||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, TerminusModule],
|
||||
controllers: [HealthController],
|
||||
})
|
||||
export class HealthModule {}
|
||||
@@ -156,6 +156,25 @@ export async function getDefaultInfraConfigs(): Promise<
|
||||
return infraConfigDefaultObjs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the missing entries in the 'infra_config' table
|
||||
* @returns Array of InfraConfig
|
||||
*/
|
||||
export async function getMissingInfraConfigEntries() {
|
||||
const prisma = new PrismaService();
|
||||
const [dbInfraConfigs, infraConfigDefaultObjs] = await Promise.all([
|
||||
prisma.infraConfig.findMany(),
|
||||
getDefaultInfraConfigs(),
|
||||
]);
|
||||
|
||||
const missingEntries = infraConfigDefaultObjs.filter(
|
||||
(config) =>
|
||||
!dbInfraConfigs.some((dbConfig) => dbConfig.name === config.name),
|
||||
);
|
||||
|
||||
return missingEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if 'infra_config' table is loaded with all entries
|
||||
* @returns boolean
|
||||
@@ -163,12 +182,7 @@ export async function getDefaultInfraConfigs(): Promise<
|
||||
export async function isInfraConfigTablePopulated(): Promise<boolean> {
|
||||
const prisma = new PrismaService();
|
||||
try {
|
||||
const dbInfraConfigs = await prisma.infraConfig.findMany();
|
||||
const infraConfigDefaultObjs = await getDefaultInfraConfigs();
|
||||
|
||||
const propsRemainingToInsert = infraConfigDefaultObjs.filter(
|
||||
(p) => !dbInfraConfigs.find((e) => e.name === p.name),
|
||||
);
|
||||
const propsRemainingToInsert = await getMissingInfraConfigEntries();
|
||||
|
||||
if (propsRemainingToInsert.length > 0) {
|
||||
console.log(
|
||||
|
||||
@@ -21,7 +21,12 @@ import {
|
||||
validateUrl,
|
||||
} from 'src/utils';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { ServiceStatus, getDefaultInfraConfigs, stopApp } from './helper';
|
||||
import {
|
||||
ServiceStatus,
|
||||
getDefaultInfraConfigs,
|
||||
getMissingInfraConfigEntries,
|
||||
stopApp,
|
||||
} from './helper';
|
||||
import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args';
|
||||
import { AuthProvider } from 'src/auth/helper';
|
||||
|
||||
@@ -56,14 +61,7 @@ export class InfraConfigService implements OnModuleInit {
|
||||
*/
|
||||
async initializeInfraConfigTable() {
|
||||
try {
|
||||
// Fetch the default values (value in .env) for configs to be saved in 'infra_config' table
|
||||
const infraConfigDefaultObjs = await getDefaultInfraConfigs();
|
||||
|
||||
// Eliminate the rows (from 'infraConfigDefaultObjs') that are already present in the database table
|
||||
const dbInfraConfigs = await this.prisma.infraConfig.findMany();
|
||||
const propsToInsert = infraConfigDefaultObjs.filter(
|
||||
(p) => !dbInfraConfigs.find((e) => e.name === p.name),
|
||||
);
|
||||
const propsToInsert = await getMissingInfraConfigEntries();
|
||||
|
||||
if (propsToInsert.length > 0) {
|
||||
await this.prisma.infraConfig.createMany({ data: propsToInsert });
|
||||
@@ -285,6 +283,7 @@ export class InfraConfigService implements OnModuleInit {
|
||||
/**
|
||||
* Get InfraConfigs by names
|
||||
* @param names Names of the InfraConfigs
|
||||
* @param checkDisallowedKeys If true, check if the names are allowed to fetch by client
|
||||
* @returns InfraConfig model
|
||||
*/
|
||||
async getMany(names: InfraConfigEnum[], checkDisallowedKeys: boolean = true) {
|
||||
|
||||
@@ -52,11 +52,34 @@ hopp [options or commands] arguments
|
||||
Taking the above example, `pw.env.get("ENV1")` will return `"value1"`
|
||||
|
||||
## Install
|
||||
- Before you install Hoppscotch CLI you need to make sure you have the dependencies it requires to run.
|
||||
- **Windows & macOS**: You will need `node-gyp` installed. Find instructions here: https://github.com/nodejs/node-gyp
|
||||
- **Debian/Ubuntu derivatives**:
|
||||
```sh
|
||||
sudo apt-get install python g++ build-essential
|
||||
```
|
||||
- **Alpine Linux**:
|
||||
```sh
|
||||
sudo apk add python3 make g++
|
||||
```
|
||||
- **Amazon Linux (AMI)**
|
||||
```sh
|
||||
sudo yum install gcc72 gcc72-c++
|
||||
```
|
||||
- **Arch Linux**
|
||||
```sh
|
||||
sudo pacman -S make gcc python
|
||||
```
|
||||
- **RHEL/Fedora derivatives**:
|
||||
```sh
|
||||
sudo dnf install python3 make gcc gcc-c++ zlib-devel brotli-devel openssl-devel libuv-devel
|
||||
```
|
||||
|
||||
Install [@hoppscotch/cli](https://www.npmjs.com/package/@hoppscotch/cli) from npm by running:
|
||||
```
|
||||
npm i -g @hoppscotch/cli
|
||||
```
|
||||
|
||||
- Once the dependencies are installed, install [@hoppscotch/cli](https://www.npmjs.com/package/@hoppscotch/cli) from npm by running:
|
||||
```
|
||||
npm i -g @hoppscotch/cli
|
||||
```
|
||||
|
||||
## **Developing:**
|
||||
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
// * The entry point of the CLI
|
||||
// @ts-check
|
||||
|
||||
import { cli } from "../dist/index.js";
|
||||
|
||||
cli(process.argv);
|
||||
import { spawnSync } from "child_process";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
|
||||
const nodeVersion = parseInt(process.versions.node.split(".")[0]);
|
||||
|
||||
// As per isolated-vm documentation, we need to supply `--no-node-snapshot` for node >= 20
|
||||
// src: https://github.com/laverdet/isolated-vm?tab=readme-ov-file#requirements
|
||||
if (nodeVersion >= 20 && !process.execArgv.includes("--no-node-snapshot")) {
|
||||
const argCopy = cloneDeep(process.argv);
|
||||
|
||||
// Replace first argument with --no-node-snapshot
|
||||
// We can get argv[0] from process.argv0
|
||||
argCopy[0] = "--no-node-snapshot";
|
||||
|
||||
const result = spawnSync(
|
||||
process.argv0,
|
||||
argCopy,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
|
||||
// Exit with the same status code as the spawned process
|
||||
process.exit(result.status ?? 0);
|
||||
} else {
|
||||
cli(process.argv);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hoppscotch/cli",
|
||||
"version": "0.7.0",
|
||||
"version": "0.8.0",
|
||||
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
||||
"homepage": "https://hoppscotch.io",
|
||||
"type": "module",
|
||||
@@ -44,6 +44,7 @@
|
||||
"axios": "1.6.7",
|
||||
"chalk": "5.3.0",
|
||||
"commander": "11.1.0",
|
||||
"isolated-vm": "4.7.2",
|
||||
"lodash-es": "4.17.21",
|
||||
"qs": "6.11.2",
|
||||
"verzod": "0.2.2",
|
||||
@@ -65,4 +66,4 @@
|
||||
"tsup": "8.0.2",
|
||||
"typescript": "5.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ describe("Test `hopp test <file> --env <file>` command:", () => {
|
||||
});
|
||||
|
||||
describe("Secret environment variables", () => {
|
||||
jest.setTimeout(10000);
|
||||
jest.setTimeout(100000);
|
||||
|
||||
// Reads secret environment values from system environment
|
||||
test("Successfully picks the values for secret environment variables from `process.env` and persists the variables set from the pre-request script", async () => {
|
||||
|
||||
@@ -1,27 +1,55 @@
|
||||
{
|
||||
"v": 1,
|
||||
"name": "coll-v1",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
"v": 1,
|
||||
"name": "coll-v1",
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "coll-v1-child",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"url": "https://httpbin.org",
|
||||
"path": "/get",
|
||||
"headers": [
|
||||
{ "key": "Inactive-Header", "value": "Inactive Header", "active": false },
|
||||
{ "key": "Authorization", "value": "Bearer token123", "active": true }
|
||||
],
|
||||
"params": [
|
||||
{ "key": "key", "value": "value", "active": true },
|
||||
{ "key": "inactive-key", "value": "inactive-param", "active": false }
|
||||
],
|
||||
"name": "req-v0",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
|
||||
"contentType": "application/json",
|
||||
"body": "",
|
||||
"auth": "Bearer Token",
|
||||
"bearerToken": "token123"
|
||||
}
|
||||
]
|
||||
}
|
||||
"url": "https://echo.hoppscotch.io",
|
||||
"path": "/get",
|
||||
"headers": [
|
||||
{ "key": "Inactive-Header", "value": "Inactive Header", "active": false },
|
||||
{ "key": "Authorization", "value": "Bearer token123", "active": true }
|
||||
],
|
||||
"params": [
|
||||
{ "key": "key", "value": "value", "active": true },
|
||||
{ "key": "inactive-key", "value": "inactive-param", "active": false }
|
||||
],
|
||||
"name": "req-v0-II",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"contentType": "application/json",
|
||||
"body": "",
|
||||
"auth": "Bearer Token",
|
||||
"bearerToken": "token123"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"url": "https://echo.hoppscotch.io",
|
||||
"path": "/get",
|
||||
"headers": [
|
||||
{ "key": "Inactive-Header", "value": "Inactive Header", "active": false },
|
||||
{ "key": "Authorization", "value": "Bearer token123", "active": true }
|
||||
],
|
||||
"params": [
|
||||
{ "key": "key", "value": "value", "active": true },
|
||||
{ "key": "inactive-key", "value": "inactive-param", "active": false }
|
||||
],
|
||||
"name": "req-v0",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"contentType": "application/json",
|
||||
"body": "",
|
||||
"auth": "Bearer Token",
|
||||
"bearerToken": "token123"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,11 +1,60 @@
|
||||
{
|
||||
"v": 1,
|
||||
"name": "coll-v1",
|
||||
"folders": [],
|
||||
"folders": [
|
||||
{
|
||||
"v": 1,
|
||||
"name": "coll-v1-child",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
"value": "Inactive Header",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Bearer token123",
|
||||
"active": true
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"key": "key",
|
||||
"value": "value",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"key": "inactive-key",
|
||||
"value": "inactive-param",
|
||||
"active": false
|
||||
}
|
||||
],
|
||||
"name": "req-v1-II",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"auth": {
|
||||
"authType": "bearer",
|
||||
"authActive": true,
|
||||
"token": "token123"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "1",
|
||||
"endpoint": "https://httpbin.org/get",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
@@ -33,7 +82,7 @@
|
||||
"name": "req-v1",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
|
||||
@@ -1,11 +1,66 @@
|
||||
{
|
||||
"v": 2,
|
||||
"name": "coll-v2",
|
||||
"folders": [],
|
||||
"folders": [
|
||||
{
|
||||
"v": 2,
|
||||
"name": "coll-v2-child",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"v": "2",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
"value": "Inactive Header",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Bearer token123",
|
||||
"active": true
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"key": "key",
|
||||
"value": "value",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"key": "inactive-key",
|
||||
"value": "inactive-param",
|
||||
"active": false
|
||||
}
|
||||
],
|
||||
"name": "req-v2-II",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"auth": {
|
||||
"authType": "bearer",
|
||||
"authActive": true,
|
||||
"token": "token123"
|
||||
},
|
||||
"requestVariables": []
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "2",
|
||||
"endpoint": "https://httpbin.org/get",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
@@ -33,7 +88,7 @@
|
||||
"name": "req-v2",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
|
||||
@@ -1,11 +1,66 @@
|
||||
{
|
||||
"v": 2,
|
||||
"name": "coll-v2",
|
||||
"folders": [],
|
||||
"folders": [
|
||||
{
|
||||
"v": 2,
|
||||
"name": "coll-v2-child",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
"v": "3",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
"value": "Inactive Header",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"key": "Authorization",
|
||||
"value": "Bearer token123",
|
||||
"active": true
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"key": "key",
|
||||
"value": "value",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"key": "inactive-key",
|
||||
"value": "inactive-param",
|
||||
"active": false
|
||||
}
|
||||
],
|
||||
"name": "req-v3-II",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
},
|
||||
"auth": {
|
||||
"authType": "bearer",
|
||||
"authActive": true,
|
||||
"token": "token123"
|
||||
},
|
||||
"requestVariables": []
|
||||
}
|
||||
],
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": true
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
],
|
||||
"requests": [
|
||||
{
|
||||
"v": "3",
|
||||
"endpoint": "https://httpbin.org/get",
|
||||
"endpoint": "https://echo.hoppscotch.io",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Inactive-Header",
|
||||
@@ -33,7 +88,7 @@
|
||||
"name": "req-v3",
|
||||
"method": "GET",
|
||||
"preRequestScript": "",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"Authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"Inactive-Header\"]).toBe(undefined)\n})",
|
||||
"testScript": "pw.test(\"Asserts request params\", () => {\n pw.expect(pw.response.body.args.key).toBe(\"value\")\n pw.expect(pw.response.body.args[\"inactive-key\"]).toBe(undefined)\n})\n\npw.test(\"Asserts request headers\", () => {\n pw.expect(pw.response.body.headers[\"authorization\"]).toBe(\"Bearer token123\")\n pw.expect(pw.response.body.headers[\"inactive-header\"]).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": null,
|
||||
"body": null
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
"auth": {
|
||||
"authType": "api-key",
|
||||
"authActive": true,
|
||||
"addTo": "Headers",
|
||||
"addTo": "HEADERS",
|
||||
"key": "key",
|
||||
"value": "test-key"
|
||||
},
|
||||
|
||||
@@ -5,8 +5,14 @@
|
||||
"requests": [
|
||||
{
|
||||
"v": "3",
|
||||
"auth": { "authType": "none", "authActive": true },
|
||||
"body": { "body": null, "contentType": null },
|
||||
"auth": {
|
||||
"authType": "none",
|
||||
"authActive": true
|
||||
},
|
||||
"body": {
|
||||
"body": null,
|
||||
"contentType": null
|
||||
},
|
||||
"name": "test-secret-headers",
|
||||
"method": "GET",
|
||||
"params": [],
|
||||
@@ -18,13 +24,16 @@
|
||||
}
|
||||
],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>/headers",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.get(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.get(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
||||
"endpoint": "<<echoHoppBaseURL>>/headers",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.get(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"secret-header-key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.get(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
||||
"preRequestScript": "const secretHeaderValueFromPreReqScript = pw.env.get(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||
},
|
||||
{
|
||||
"v": "3",
|
||||
"auth": { "authType": "none", "authActive": true },
|
||||
"auth": {
|
||||
"authType": "none",
|
||||
"authActive": true
|
||||
},
|
||||
"body": {
|
||||
"body": "{\n \"secretBodyKey\": \"<<secretBodyValue>>\"\n}",
|
||||
"contentType": "application/json"
|
||||
@@ -34,14 +43,20 @@
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>/post",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||
"endpoint": "<<echoHoppBaseURL>>/post",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(JSON.parse(pw.response.body.data).secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||
"preRequestScript": "const secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
||||
},
|
||||
{
|
||||
"v": "3",
|
||||
"auth": { "authType": "none", "authActive": true },
|
||||
"body": { "body": null, "contentType": null },
|
||||
"auth": {
|
||||
"authType": "none",
|
||||
"authActive": true
|
||||
},
|
||||
"body": {
|
||||
"body": null,
|
||||
"contentType": null
|
||||
},
|
||||
"name": "test-secret-query-params",
|
||||
"method": "GET",
|
||||
"params": [
|
||||
@@ -53,7 +68,7 @@
|
||||
],
|
||||
"headers": [],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>/get",
|
||||
"endpoint": "<<echoHoppBaseURL>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
||||
"preRequestScript": "const secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
||||
},
|
||||
@@ -65,14 +80,17 @@
|
||||
"username": "<<secretBasicAuthUsername>>",
|
||||
"authActive": true
|
||||
},
|
||||
"body": { "body": null, "contentType": null },
|
||||
"body": {
|
||||
"body": null,
|
||||
"contentType": null
|
||||
},
|
||||
"name": "test-secret-basic-auth",
|
||||
"method": "GET",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||
"endpoint": "<<httpbinBaseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n // The endpoint at times results in a `502` bad gateway\n if (pw.response.status !== 200) {\n return\n }\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||
"preRequestScript": ""
|
||||
},
|
||||
{
|
||||
@@ -84,30 +102,42 @@
|
||||
"username": "testuser",
|
||||
"authActive": true
|
||||
},
|
||||
"body": { "body": null, "contentType": null },
|
||||
"body": {
|
||||
"body": null,
|
||||
"contentType": null
|
||||
},
|
||||
"name": "test-secret-bearer-auth",
|
||||
"method": "GET",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>/bearer",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.get(\"secretBearerToken\")\n const preReqSecretBearerToken = pw.env.get(\"preReqSecretBearerToken\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||
"endpoint": "<<httpbinBaseURL>>/bearer",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.get(\"secretBearerToken\")\n const preReqSecretBearerToken = pw.env.get(\"preReqSecretBearerToken\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n // Safeguard to prevent test failures due to the endpoint\n if (pw.response.status !== 200) {\n return\n }\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||
"preRequestScript": "const secretBearerToken = pw.env.get(\"secretBearerToken\")\npw.env.set(\"preReqSecretBearerToken\", secretBearerToken)"
|
||||
},
|
||||
{
|
||||
"v": "3",
|
||||
"auth": { "authType": "none", "authActive": true },
|
||||
"body": { "body": null, "contentType": null },
|
||||
"auth": {
|
||||
"authType": "none",
|
||||
"authActive": true
|
||||
},
|
||||
"body": {
|
||||
"body": null,
|
||||
"contentType": null
|
||||
},
|
||||
"name": "test-secret-fallback",
|
||||
"method": "GET",
|
||||
"params": [],
|
||||
"headers": [],
|
||||
"requestVariables": [],
|
||||
"endpoint": "<<baseURL>>",
|
||||
"endpoint": "<<echoHoppBaseURL>>",
|
||||
"testScript": "pw.test(\"Returns an empty string if the value for a secret environment variable is not found in the system environment\", () => {\n pw.expect(pw.env.get(\"nonExistentValueInSystemEnv\")).toBe(\"\")\n})",
|
||||
"preRequestScript": ""
|
||||
}
|
||||
],
|
||||
"auth": { "authType": "inherit", "authActive": false },
|
||||
"auth": {
|
||||
"authType": "inherit",
|
||||
"authActive": false
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"v": 2,
|
||||
"name": "secret-envs-setters-coll",
|
||||
"name": "secret-envs-persistence-coll",
|
||||
"folders": [],
|
||||
"requests": [
|
||||
{
|
||||
@@ -24,8 +24,8 @@
|
||||
"active": true
|
||||
}
|
||||
],
|
||||
"endpoint": "<<baseURL>>/headers",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
||||
"endpoint": "<<echoHoppBaseURL>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the header value\", () => {\n const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"secret-header-key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value\")\n})",
|
||||
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||
},
|
||||
{
|
||||
@@ -49,8 +49,8 @@
|
||||
"active": true
|
||||
}
|
||||
],
|
||||
"endpoint": "<<baseURL>>/headers",
|
||||
"testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"Secret-Header-Key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
|
||||
"endpoint": "<<echoHoppBaseURL>>",
|
||||
"testScript": "pw.test(\"Value set at the pre-request script takes precedence\", () => {\n const secretHeaderValue = pw.env.getResolve(\"secretHeaderValue\")\n pw.expect(secretHeaderValue).toBe(\"secret-header-value-overriden\")\n \n if (secretHeaderValue) {\n pw.expect(pw.response.body.headers[\"secret-header-key\"]).toBe(secretHeaderValue)\n }\n\n pw.expect(pw.env.getResolve(\"secretHeaderValueFromPreReqScript\")).toBe(\"secret-header-value-overriden\")\n})",
|
||||
"preRequestScript": "pw.env.set(\"secretHeaderValue\", \"secret-header-value-overriden\")\n\nconst secretHeaderValueFromPreReqScript = pw.env.getResolve(\"secretHeaderValue\")\npw.env.set(\"secretHeaderValueFromPreReqScript\", secretHeaderValueFromPreReqScript)"
|
||||
},
|
||||
{
|
||||
@@ -68,8 +68,8 @@
|
||||
"params": [],
|
||||
"requestVariables": [],
|
||||
"headers": [],
|
||||
"endpoint": "<<baseURL>>/post",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(pw.response.body.json.secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||
"endpoint": "<<echoHoppBaseURL>>/post",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the request body value\", () => {\n const secretBodyValue = pw.env.get(\"secretBodyValue\")\n pw.expect(secretBodyValue).toBe(\"secret-body-value\")\n \n if (secretBodyValue) {\n pw.expect(JSON.parse(pw.response.body.data).secretBodyKey).toBe(secretBodyValue)\n }\n\n pw.expect(pw.env.get(\"secretBodyValueFromPreReqScript\")).toBe(\"secret-body-value\")\n})",
|
||||
"preRequestScript": "const secretBodyValue = pw.env.get(\"secretBodyValue\")\n\nif (!secretBodyValue) { \n pw.env.set(\"secretBodyValue\", \"secret-body-value\")\n}\n\nconst secretBodyValueFromPreReqScript = pw.env.get(\"secretBodyValue\")\npw.env.set(\"secretBodyValueFromPreReqScript\", secretBodyValueFromPreReqScript)"
|
||||
},
|
||||
{
|
||||
@@ -93,7 +93,7 @@
|
||||
],
|
||||
"requestVariables": [],
|
||||
"headers": [],
|
||||
"endpoint": "<<baseURL>>/get",
|
||||
"endpoint": "<<echoHoppBaseURL>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the query param value\", () => {\n const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n pw.expect(secretQueryParamValue).toBe(\"secret-query-param-value\")\n \n if (secretQueryParamValue) {\n pw.expect(pw.response.body.args.secretQueryParamKey).toBe(secretQueryParamValue)\n }\n\n pw.expect(pw.env.get(\"secretQueryParamValueFromPreReqScript\")).toBe(\"secret-query-param-value\")\n})",
|
||||
"preRequestScript": "const secretQueryParamValue = pw.env.get(\"secretQueryParamValue\")\n\nif (!secretQueryParamValue) {\n pw.env.set(\"secretQueryParamValue\", \"secret-query-param-value\")\n}\n\nconst secretQueryParamValueFromPreReqScript = pw.env.get(\"secretQueryParamValue\")\npw.env.set(\"secretQueryParamValueFromPreReqScript\", secretQueryParamValueFromPreReqScript)"
|
||||
},
|
||||
@@ -114,8 +114,8 @@
|
||||
"params": [],
|
||||
"requestVariables": [],
|
||||
"headers": [],
|
||||
"endpoint": "<<baseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||
"endpoint": "<<httpbinBaseURL>>/basic-auth/<<secretBasicAuthUsername>>/<<secretBasicAuthPassword>>",
|
||||
"testScript": "pw.test(\"Successfully parses secret variables holding basic auth credentials\", () => {\n\tconst secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n \tconst secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\n pw.expect(secretBasicAuthUsername).toBe(\"test-user\")\n pw.expect(secretBasicAuthPassword).toBe(\"test-pass\")\n\n // The endpoint at times results in a `502` bad gateway\n if (pw.response.status !== 200) {\n return\n }\n\n if (secretBasicAuthUsername && secretBasicAuthPassword) {\n const { authenticated, user } = pw.response.body\n pw.expect(authenticated).toBe(true)\n pw.expect(user).toBe(secretBasicAuthUsername)\n }\n});",
|
||||
"preRequestScript": "let secretBasicAuthUsername = pw.env.get(\"secretBasicAuthUsername\")\n\nlet secretBasicAuthPassword = pw.env.get(\"secretBasicAuthPassword\")\n\nif (!secretBasicAuthUsername) {\n pw.env.set(\"secretBasicAuthUsername\", \"test-user\")\n}\n\nif (!secretBasicAuthPassword) {\n pw.env.set(\"secretBasicAuthPassword\", \"test-pass\")\n}"
|
||||
},
|
||||
{
|
||||
@@ -136,8 +136,8 @@
|
||||
"params": [],
|
||||
"requestVariables": [],
|
||||
"headers": [],
|
||||
"endpoint": "<<baseURL>>/bearer",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n const preReqSecretBearerToken = pw.env.resolve(\"<<preReqSecretBearerToken>>\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||
"endpoint": "<<httpbinBaseURL>>/bearer",
|
||||
"testScript": "pw.test(\"Successfully parses secret variable holding the bearer token\", () => {\n const secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n const preReqSecretBearerToken = pw.env.resolve(\"<<preReqSecretBearerToken>>\")\n\n pw.expect(secretBearerToken).toBe(\"test-token\")\n\n // Safeguard to prevent test failures due to the endpoint\n if (pw.response.status !== 200) {\n return\n }\n\n if (secretBearerToken) { \n pw.expect(pw.response.body.token).toBe(secretBearerToken)\n pw.expect(preReqSecretBearerToken).toBe(\"test-token\")\n }\n});",
|
||||
"preRequestScript": "let secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n\nif (!secretBearerToken) {\n pw.env.set(\"secretBearerToken\", \"test-token\")\n secretBearerToken = pw.env.resolve(\"<<secretBearerToken>>\")\n}\n\npw.env.set(\"preReqSecretBearerToken\", secretBearerToken)"
|
||||
}
|
||||
],
|
||||
@@ -146,4 +146,4 @@
|
||||
"authActive": false
|
||||
},
|
||||
"headers": []
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"requests": [
|
||||
{
|
||||
"v": "3",
|
||||
"endpoint": "https://httpbin.org/post",
|
||||
"endpoint": "https://echo.hoppscotch.io/post",
|
||||
"name": "req",
|
||||
"params": [],
|
||||
"headers": [
|
||||
@@ -18,7 +18,7 @@
|
||||
"method": "POST",
|
||||
"auth": { "authType": "none", "authActive": true },
|
||||
"preRequestScript": "pw.env.set(\"preReqVarOne\", \"pre-req-value-one\")\n\npw.env.set(\"preReqVarTwo\", \"pre-req-value-two\")\n\npw.env.set(\"customHeaderValueFromSecretVar\", \"custom-header-secret-value\")\n\npw.env.set(\"customBodyValue\", \"custom-body-value\")",
|
||||
"testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request sccript\", () => {\n pw.expect(pw.response.body.headers[\"Custom-Header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request sccript\", () => {\n pw.expect(pw.response.body.json.key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n pw.env.unset(\"preReqVarOne\")\n pw.env.unset(\"postReqVarTwo\")\n\n pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
|
||||
"testScript": "pw.test(\"Secret environment value set from the pre-request script takes precedence\", () => {\n pw.expect(pw.env.get(\"preReqVarOne\")).toBe(\"pre-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the pre-request script\", () => {\n pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request headers that are set in pre-request script\", () => {\n pw.expect(pw.response.body.headers[\"custom-header\"]).toBe(\"custom-header-secret-value\")\n})\n\npw.test(\"Successfully resolves secret variable values referred in request body that are set in pre-request script\", () => {\n pw.expect(JSON.parse(pw.response.body.data).key).toBe(\"custom-body-value\")\n})\n\npw.test(\"Secret environment variable set from the post-request script takes precedence\", () => {\n pw.env.set(\"postReqVarOne\", \"post-req-value-one\")\n pw.expect(pw.env.get(\"postReqVarOne\")).toBe(\"post-req-value-one\")\n})\n\npw.test(\"Successfully sets initial value for the secret variable from the post-request script\", () => {\n pw.env.set(\"postReqVarTwo\", \"post-req-value-two\")\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(\"post-req-value-two\")\n})\n\npw.test(\"Successfully removes environment variables via the pw.env.unset method\", () => {\n pw.env.unset(\"preReqVarOne\")\n pw.env.unset(\"postReqVarTwo\")\n\n pw.expect(pw.env.get(\"preReqVarOne\")).toBe(undefined)\n pw.expect(pw.env.get(\"postReqVarTwo\")).toBe(undefined)\n})",
|
||||
"body": {
|
||||
"contentType": "application/json",
|
||||
"body": "{\n \"key\": \"<<customBodyValue>>\"\n}"
|
||||
|
||||
@@ -32,7 +32,12 @@
|
||||
"secret": true
|
||||
},
|
||||
{
|
||||
"key": "baseURL",
|
||||
"key": "echoHoppBaseURL",
|
||||
"value": "https://echo.hoppscotch.io",
|
||||
"secret": false
|
||||
},
|
||||
{
|
||||
"key": "httpbinBaseURL",
|
||||
"value": "https://httpbin.org",
|
||||
"secret": false
|
||||
}
|
||||
|
||||
@@ -38,7 +38,12 @@
|
||||
"secret": true
|
||||
},
|
||||
{
|
||||
"key": "baseURL",
|
||||
"key": "echoHoppBaseURL",
|
||||
"value": "https://echo.hoppscotch.io",
|
||||
"secret": false
|
||||
},
|
||||
{
|
||||
"key": "httpbinBaseURL",
|
||||
"value": "https://httpbin.org",
|
||||
"secret": false
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@ import { resolve } from "path";
|
||||
|
||||
import { ExecResponse } from "./types";
|
||||
|
||||
export const runCLI = (args: string, options = {}): Promise<ExecResponse> =>
|
||||
{
|
||||
const CLI_PATH = resolve(__dirname, "../../bin/hopp");
|
||||
const command = `node ${CLI_PATH} ${args}`
|
||||
export const runCLI = (args: string, options = {}): Promise<ExecResponse> => {
|
||||
const CLI_PATH = resolve(__dirname, "../../bin/hopp.js");
|
||||
const command = `node ${CLI_PATH} ${args}`;
|
||||
|
||||
return new Promise((resolve) =>
|
||||
exec(command, options, (error, stdout, stderr) => resolve({ error, stdout, stderr }))
|
||||
);
|
||||
}
|
||||
return new Promise((resolve) =>
|
||||
exec(command, options, (error, stdout, stderr) =>
|
||||
resolve({ error, stdout, stderr })
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const trimAnsi = (target: string) => {
|
||||
const ansiRegex =
|
||||
@@ -25,12 +26,18 @@ export const getErrorCode = (out: string) => {
|
||||
return ansiTrimmedStr.split(" ")[0];
|
||||
};
|
||||
|
||||
export const getTestJsonFilePath = (file: string, kind: "collection" | "environment") => {
|
||||
export const getTestJsonFilePath = (
|
||||
file: string,
|
||||
kind: "collection" | "environment"
|
||||
) => {
|
||||
const kindDir = {
|
||||
collection: "collections",
|
||||
environment: "environments",
|
||||
}[kind];
|
||||
|
||||
const filePath = resolve(__dirname, `../../src/__tests__/samples/${kindDir}/${file}`);
|
||||
const filePath = resolve(
|
||||
__dirname,
|
||||
`../../src/__tests__/samples/${kindDir}/${file}`
|
||||
);
|
||||
return filePath;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import chalk from "chalk";
|
||||
import { Command } from "commander";
|
||||
import * as E from "fp-ts/Either";
|
||||
|
||||
import { version } from "../package.json";
|
||||
import { test } from "./commands/test";
|
||||
import { handleError } from "./handlers/error";
|
||||
@@ -20,7 +21,7 @@ const CLI_AFTER_ALL_TXT = `\nFor more help, head on to ${accent(
|
||||
"https://docs.hoppscotch.io/documentation/clients/cli"
|
||||
)}`;
|
||||
|
||||
const program = new Command()
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name("hopp")
|
||||
|
||||
@@ -7,6 +7,41 @@ import { error } from "../types/errors";
|
||||
import { FormDataEntry } from "../types/request";
|
||||
import { isHoppErrnoException } from "./checks";
|
||||
|
||||
const getValidRequests = (
|
||||
collections: HoppCollection[],
|
||||
collectionFilePath: string
|
||||
) => {
|
||||
return collections.map((collection) => {
|
||||
// Validate requests using zod schema
|
||||
const requestSchemaParsedResult = z
|
||||
.array(entityReference(HoppRESTRequest))
|
||||
.safeParse(collection.requests);
|
||||
|
||||
// Handle validation errors
|
||||
if (!requestSchemaParsedResult.success) {
|
||||
throw error({
|
||||
code: "MALFORMED_COLLECTION",
|
||||
path: collectionFilePath,
|
||||
data: "Please check the collection data.",
|
||||
});
|
||||
}
|
||||
|
||||
// Recursively validate requests in nested folders
|
||||
if (collection.folders.length > 0) {
|
||||
collection.folders = getValidRequests(
|
||||
collection.folders,
|
||||
collectionFilePath
|
||||
);
|
||||
}
|
||||
|
||||
// Return validated collection
|
||||
return {
|
||||
...collection,
|
||||
requests: requestSchemaParsedResult.data,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses array of FormDataEntry to FormData.
|
||||
* @param values Array of FormDataEntry.
|
||||
@@ -82,22 +117,5 @@ export async function parseCollectionData(
|
||||
});
|
||||
}
|
||||
|
||||
return collectionSchemaParsedResult.data.map((collection) => {
|
||||
const requestSchemaParsedResult = z
|
||||
.array(entityReference(HoppRESTRequest))
|
||||
.safeParse(collection.requests);
|
||||
|
||||
if (!requestSchemaParsedResult.success) {
|
||||
throw error({
|
||||
code: "MALFORMED_COLLECTION",
|
||||
path,
|
||||
data: "Please check the collection data.",
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...collection,
|
||||
requests: requestSchemaParsedResult.data,
|
||||
};
|
||||
});
|
||||
return getValidRequests(collectionSchemaParsedResult.data, path);
|
||||
}
|
||||
|
||||
@@ -136,13 +136,13 @@ export function getEffectiveRESTRequest(
|
||||
}
|
||||
} else if (request.auth.authType === "api-key") {
|
||||
const { key, value, addTo } = request.auth;
|
||||
if (addTo === "Headers") {
|
||||
if (addTo === "HEADERS") {
|
||||
effectiveFinalHeaders.push({
|
||||
active: true,
|
||||
key: parseTemplateString(key, envVariables),
|
||||
value: parseTemplateString(value, envVariables),
|
||||
});
|
||||
} else if (addTo === "Query params") {
|
||||
} else if (addTo === "QUERY_PARAMS") {
|
||||
effectiveFinalParams.push({
|
||||
active: true,
|
||||
key: parseTemplateString(key, envVariables),
|
||||
|
||||
@@ -162,6 +162,8 @@
|
||||
"label_client_credentials": "Client Credentials"
|
||||
},
|
||||
"pass_key_by": "Pass by",
|
||||
"pass_by_query_params_label": "Query Parameters",
|
||||
"pass_by_headers_label": "Headers",
|
||||
"password": "Password",
|
||||
"save_to_inherit": "Please save this request in any collection to inherit the authorization",
|
||||
"token": "Token",
|
||||
@@ -173,6 +175,7 @@
|
||||
"different_parent": "Cannot reorder collection with different parent",
|
||||
"edit": "Edit Collection",
|
||||
"import_or_create": "Import or create a collection",
|
||||
"import_collection":"Import Collection",
|
||||
"invalid_name": "Please provide a name for the collection",
|
||||
"invalid_root_move": "Collection already in the root",
|
||||
"moved": "Moved Successfully",
|
||||
@@ -371,7 +374,8 @@
|
||||
"mutations": "Mutations",
|
||||
"schema": "Schema",
|
||||
"subscriptions": "Subscriptions",
|
||||
"switch_connection": "Switch connection"
|
||||
"switch_connection": "Switch connection",
|
||||
"url_placeholder": "Enter a GraphQL endpoint URL"
|
||||
},
|
||||
"graphql_collections": {
|
||||
"title": "GraphQL Collections"
|
||||
@@ -595,6 +599,7 @@
|
||||
"title": "Request",
|
||||
"type": "Request type",
|
||||
"url": "URL",
|
||||
"url_placeholder": "Enter a URL or paste a cURL command",
|
||||
"variables": "Variables",
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
@@ -847,6 +852,13 @@
|
||||
"new": "Create new workspace",
|
||||
"switch_to_personal": "Switch to your personal workspace",
|
||||
"title": "Workspaces"
|
||||
},
|
||||
"phrases":{
|
||||
"try": "Try",
|
||||
"import_collections": "Import collections",
|
||||
"create_environment": "Create environment",
|
||||
"create_workspace": "Create workspace",
|
||||
"share_request": "Share request"
|
||||
}
|
||||
},
|
||||
"sse": {
|
||||
@@ -1015,7 +1027,8 @@
|
||||
"personal": "Personal Workspace",
|
||||
"other_workspaces": "My Workspaces",
|
||||
"team": "Workspace",
|
||||
"title": "Workspaces"
|
||||
"title": "Workspaces",
|
||||
"no_workspace": "No Workspace"
|
||||
},
|
||||
"site_protection": {
|
||||
"login_to_continue": "Login to continue",
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
"no": "No",
|
||||
"open_workspace": "Abrir espacio de trabajo",
|
||||
"paste": "Pegar",
|
||||
"prettify": "Embellecer",
|
||||
"properties": "Properties",
|
||||
"prettify": "Formatear",
|
||||
"properties": "Propiedades",
|
||||
"remove": "Eliminar",
|
||||
"rename": "Rename",
|
||||
"restore": "Restaurar",
|
||||
@@ -63,7 +63,7 @@
|
||||
"contact_us": "Contáctanos",
|
||||
"cookies": "Cookies",
|
||||
"copy": "Copiar",
|
||||
"copy_interface_type": "Copy interface type",
|
||||
"copy_interface_type": "Copiar tipo de interfaz",
|
||||
"copy_user_id": "Copiar token de autenticación de usuario",
|
||||
"developer_option": "Opciones para desarrolladores",
|
||||
"developer_option_description": "Herramientas para desarrolladores que ayudan en el desarrollo y mantenimiento de Hoppscotch.",
|
||||
@@ -80,14 +80,14 @@
|
||||
"name": "Hoppscotch",
|
||||
"new_version_found": "Se ha encontrado una nueva versión. Recarga la página para usarla.",
|
||||
"open_in_hoppscotch": "Open in Hoppscotch",
|
||||
"options": "Options",
|
||||
"options": "Opciones",
|
||||
"proxy_privacy_policy": "Política de privacidad de proxy",
|
||||
"reload": "Recargar",
|
||||
"search": "Buscar",
|
||||
"share": "Compartir",
|
||||
"shortcuts": "Atajos",
|
||||
"social_description": "Follow us on social media to stay updated with the latest news, updates and releases.",
|
||||
"social_links": "Social links",
|
||||
"social_description": "Síguenos en redes sociales para estar al día de las últimas noticias, actualizaciones y lanzamientos.",
|
||||
"social_links": "Redes sociales",
|
||||
"spotlight": "Destacar",
|
||||
"status": "Estado",
|
||||
"status_description": "Comprobar el estado del sitio web",
|
||||
@@ -119,27 +119,27 @@
|
||||
},
|
||||
"authorization": {
|
||||
"generate_token": "Generar token",
|
||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||
"graphql_headers": "Las cabeceras de autorización se envían como parte de la carga útil de connection_init",
|
||||
"include_in_url": "Incluir en la URL",
|
||||
"inherited_from": "Inherited from {auth} from Parent Collection {collection} ",
|
||||
"inherited_from": "Heredado {auth} de colección padre {collection} ",
|
||||
"learn": "Aprender",
|
||||
"oauth": {
|
||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||
"redirect_auth_token_request_failed": "Request to get the auth token failed",
|
||||
"redirect_auth_token_request_invalid_response": "Invalid Response from the Token Endpoint when requesting for an auth token",
|
||||
"redirect_invalid_state": "Invalid State value present in the redirect",
|
||||
"redirect_no_auth_code": "No Authorization Code present in the redirect",
|
||||
"redirect_no_client_id": "No Client ID defined",
|
||||
"redirect_no_client_secret": "No Client Secret Defined",
|
||||
"redirect_no_code_verifier": "No Code Verifier Defined",
|
||||
"redirect_no_token_endpoint": "No Token Endpoint Defined",
|
||||
"something_went_wrong_on_oauth_redirect": "Something went wrong during OAuth Redirect",
|
||||
"something_went_wrong_on_token_generation": "Something went wrong on token generation",
|
||||
"token_generation_oidc_discovery_failed": "Failure on token generation: OpenID Connect Discovery Failed"
|
||||
"redirect_auth_server_returned_error": "El servidor de autenticación ha devuelto un estado de error",
|
||||
"redirect_auth_token_request_failed": "Fallo en la solicitud de token de autentificación",
|
||||
"redirect_auth_token_request_invalid_response": "Respuesta no válida del punto final de Token al solicitar un token de autentificación",
|
||||
"redirect_invalid_state": "Valor de estado no válido presente en la redirección",
|
||||
"redirect_no_auth_code": "No hay código de autorización en la redirección",
|
||||
"redirect_no_client_id": "No se ha definido el ID de cliente",
|
||||
"redirect_no_client_secret": "No se ha definido ningún ID secreto de cliente",
|
||||
"redirect_no_code_verifier": "No se ha definido ningún verificador de códigos",
|
||||
"redirect_no_token_endpoint": "No se ha definido ningún punto final de token",
|
||||
"something_went_wrong_on_oauth_redirect": "Algo ha ido mal durante la redirección OAuth",
|
||||
"something_went_wrong_on_token_generation": "Algo salió mal en la generación del token",
|
||||
"token_generation_oidc_discovery_failed": "Fallo en la generación del token: OpenID Connect Discovery Failed"
|
||||
},
|
||||
"pass_key_by": "Pasar por",
|
||||
"password": "Contraseña",
|
||||
"save_to_inherit": "Please save this request in any collection to inherit the authorization",
|
||||
"save_to_inherit": "Por favor, guarda esta solicitud en cualquier colección para heredar la autorización",
|
||||
"token": "Token",
|
||||
"type": "Tipo de autorización",
|
||||
"username": "Nombre de usuario"
|
||||
@@ -148,7 +148,7 @@
|
||||
"created": "Colección creada",
|
||||
"different_parent": "No se puede reordenar la colección con un padre diferente",
|
||||
"edit": "Editar colección",
|
||||
"import_or_create": "Import or create a collection",
|
||||
"import_or_create": "Importar o crear una colección",
|
||||
"invalid_name": "Proporciona un nombre válido para la colección.",
|
||||
"invalid_root_move": "La colección ya está en la raíz",
|
||||
"moved": "Movido con éxito",
|
||||
@@ -157,20 +157,20 @@
|
||||
"name_length_insufficient": "El nombre de la colección debe tener al menos 3 caracteres",
|
||||
"new": "Nueva colección",
|
||||
"order_changed": "Orden de colección actualizada",
|
||||
"properties": "Collection Properties",
|
||||
"properties_updated": "Collection Properties Updated",
|
||||
"properties": "Propiedades de la colección",
|
||||
"properties_updated": "Propiedades de la colección actualizadas",
|
||||
"renamed": "Colección renombrada",
|
||||
"request_in_use": "Solicitud en uso",
|
||||
"save_as": "Guardar como",
|
||||
"save_to_collection": "Save to Collection",
|
||||
"save_to_collection": "Guardar en la colección",
|
||||
"select": "Seleccionar colección",
|
||||
"select_location": "Seleccionar ubicación",
|
||||
"select_team": "Seleccionar equipo",
|
||||
"team_collections": "Colecciones de equipos"
|
||||
},
|
||||
"confirm": {
|
||||
"close_unsaved_tab": "Are you sure you want to close this tab?",
|
||||
"close_unsaved_tabs": "Are you sure you want to close all tabs? {count} unsaved tabs will be lost.",
|
||||
"close_unsaved_tab": "¿Seguro que quieres cerrar esta pestaña?",
|
||||
"close_unsaved_tabs": "¿Estás seguro de que quieres cerrar todas las pestañas? {count} pestañas no guardadas se perderán.",
|
||||
"exit_team": "¿Estás seguro de que quieres dejar este equipo?",
|
||||
"logout": "¿Estás seguro de que deseas cerrar la sesión?",
|
||||
"remove_collection": "¿Estás seguro de que deseas eliminar esta colección de forma permanente?",
|
||||
@@ -178,7 +178,7 @@
|
||||
"remove_folder": "¿Estás seguro de que deseas eliminar esta carpeta de forma permanente?",
|
||||
"remove_history": "¿Estás seguro de que deseas eliminar todo el historial de forma permanente?",
|
||||
"remove_request": "¿Estás seguro de que deseas eliminar esta solicitud de forma permanente?",
|
||||
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
||||
"remove_shared_request": "¿Estás seguro de que quieres eliminar definitivamente esta solicitud compartida?",
|
||||
"remove_team": "¿Estás seguro de que deseas eliminar este equipo?",
|
||||
"remove_telemetry": "¿Estás seguro de que deseas darse de baja de la telemetría?",
|
||||
"request_change": "¿Estás seguro de que deseas descartar la solicitud actual, los cambios no guardados se perderán.",
|
||||
@@ -186,35 +186,35 @@
|
||||
"sync": "¿Estás seguro de que deseas sincronizar este espacio de trabajo?"
|
||||
},
|
||||
"context_menu": {
|
||||
"add_parameters": "Add to parameters",
|
||||
"open_request_in_new_tab": "Open request in new tab",
|
||||
"set_environment_variable": "Set as variable"
|
||||
"add_parameters": "Añadir a parámetros",
|
||||
"open_request_in_new_tab": "Abrir solicitud en una nueva pestaña",
|
||||
"set_environment_variable": "Establecer como variable"
|
||||
},
|
||||
"cookies": {
|
||||
"modal": {
|
||||
"cookie_expires": "Expires",
|
||||
"cookie_name": "Name",
|
||||
"cookie_path": "Path",
|
||||
"cookie_string": "Cookie string",
|
||||
"cookie_value": "Value",
|
||||
"empty_domain": "Domain is empty",
|
||||
"empty_domains": "Domain list is empty",
|
||||
"enter_cookie_string": "Enter cookie string",
|
||||
"interceptor_no_support": "Your currently selected interceptor does not support cookies. Select a different Interceptor and try again.",
|
||||
"managed_tab": "Managed",
|
||||
"new_domain_name": "New domain name",
|
||||
"no_cookies_in_domain": "No cookies set for this domain",
|
||||
"raw_tab": "Raw",
|
||||
"set": "Set a cookie"
|
||||
"cookie_expires": "Expira en",
|
||||
"cookie_name": "Nombre",
|
||||
"cookie_path": "Ruta",
|
||||
"cookie_string": "Cookies",
|
||||
"cookie_value": "Valor",
|
||||
"empty_domain": "Dominio vacio",
|
||||
"empty_domains": "No hay dominios",
|
||||
"enter_cookie_string": "Introducir cookies",
|
||||
"interceptor_no_support": "El interceptor seleccionado actualmente no admite cookies. Seleccione otro interceptor e inténtelo de nuevo.",
|
||||
"managed_tab": "Gestionado",
|
||||
"new_domain_name": "Nuevo nombre de dominio",
|
||||
"no_cookies_in_domain": "No hay cookies para este dominio",
|
||||
"raw_tab": "Sin procesar",
|
||||
"set": "Establecer una cookie"
|
||||
}
|
||||
},
|
||||
"count": {
|
||||
"header": "Encabezado {count}",
|
||||
"message": "Mensaje {count}",
|
||||
"parameter": "Parámetro {count}",
|
||||
"protocol": "Protocolo {count}",
|
||||
"value": "Valor {cuenta}",
|
||||
"variable": "Variable {count}"
|
||||
"header": "{count} encabezado(s)",
|
||||
"message": "{count} mensaje(s)",
|
||||
"parameter": "{count} parámetro(s)",
|
||||
"protocol": "{count} protocolo(s)",
|
||||
"value": "{cuenta} valor(es)",
|
||||
"variable": "{count} variable(es)"
|
||||
},
|
||||
"documentation": {
|
||||
"generate": "Generar documentación",
|
||||
@@ -223,26 +223,26 @@
|
||||
"empty": {
|
||||
"authorization": "Esta solicitud no utiliza ninguna autorización.",
|
||||
"body": "Esta solicitud no tiene cuerpo",
|
||||
"collection": "La colección está vacía",
|
||||
"collections": "Las colecciones están vacías",
|
||||
"collection": "Colección vacía",
|
||||
"collections": "No hay colecciones",
|
||||
"documentation": "Conectarse a un punto final de GraphQL para ver la documentación",
|
||||
"endpoint": "El punto final no puede estar vacío",
|
||||
"environments": "Los entornos están vacíos",
|
||||
"folder": "La carpeta está vacía",
|
||||
"environments": "No hay entornos",
|
||||
"folder": "Carpeta vacía",
|
||||
"headers": "Esta solicitud no tiene encabezados",
|
||||
"history": "El historial está vacío",
|
||||
"invites": "La lista de invitados está vacía",
|
||||
"members": "El equipo está vacío",
|
||||
"history": "No hay historial",
|
||||
"invites": "Lista de invitados vacía",
|
||||
"members": "No hay miembros en el equipo",
|
||||
"parameters": "Esta solicitud no tiene ningún parámetro",
|
||||
"pending_invites": "No hay invitaciones pendientes para este equipo",
|
||||
"profile": "Iniciar sesión para ver tu perfil",
|
||||
"protocols": "Los protocolos están vacíos",
|
||||
"protocols": "No hay protocolos",
|
||||
"schema": "Conectarse a un punto final de GraphQL",
|
||||
"shared_requests": "Shared requests are empty",
|
||||
"shared_requests_logout": "Login to view your shared requests or create a new one",
|
||||
"subscription": "Subscriptions are empty",
|
||||
"shared_requests": "No hay solicitudes compartidas",
|
||||
"shared_requests_logout": "Iniciar sesión para ver sus solicitudes compartidas o crear una nueva",
|
||||
"subscription": "No hay suscripciones",
|
||||
"team_name": "Nombre del equipo vacío",
|
||||
"teams": "Los equipos están vacíos",
|
||||
"teams": "No hay equipos",
|
||||
"tests": "No hay pruebas para esta solicitud",
|
||||
"shortcodes": "Aún no se han creado Shortcodes"
|
||||
},
|
||||
@@ -250,41 +250,41 @@
|
||||
"add_to_global": "Añadir a Global",
|
||||
"added": "Adición al entorno",
|
||||
"create_new": "Crear un nuevo entorno",
|
||||
"created": "Environment created",
|
||||
"created": "Entorno creado",
|
||||
"deleted": "Eliminar el entorno",
|
||||
"duplicated": "Environment duplicated",
|
||||
"duplicated": "Entorno duplicado",
|
||||
"edit": "Editar entorno",
|
||||
"empty_variables": "No variables",
|
||||
"empty_variables": "No hay variables",
|
||||
"global": "Global",
|
||||
"global_variables": "Global variables",
|
||||
"import_or_create": "Import or create a environment",
|
||||
"global_variables": "Variables globales",
|
||||
"import_or_create": "Importar o crear un entorno",
|
||||
"invalid_name": "Proporciona un nombre válido para el entorno.",
|
||||
"list": "Environment variables",
|
||||
"list": "Variables de entorno",
|
||||
"my_environments": "Mis entornos",
|
||||
"name": "Name",
|
||||
"name": "Nombre",
|
||||
"nested_overflow": "las variables de entorno anidadas están limitadas a 10 niveles",
|
||||
"new": "Nuevo entorno",
|
||||
"no_active_environment": "No active environment",
|
||||
"no_active_environment": "Ningún entorno activo",
|
||||
"no_environment": "Sin entorno",
|
||||
"no_environment_description": "No se ha seleccionado ningún entorno. Elije qué hacer con las siguientes variables.",
|
||||
"quick_peek": "Environment Quick Peek",
|
||||
"replace_with_variable": "Replace with variable",
|
||||
"scope": "Scope",
|
||||
"quick_peek": "Vistazo rápido al entorno",
|
||||
"replace_with_variable": "Sustituir por variable",
|
||||
"scope": "Ámbito",
|
||||
"select": "Seleccionar entorno",
|
||||
"set": "Set environment",
|
||||
"set_as_environment": "Set as environment",
|
||||
"set": "Establecer entorno",
|
||||
"set_as_environment": "Establecer como entorno",
|
||||
"team_environments": "Entornos de trabajo en equipo",
|
||||
"title": "Entornos",
|
||||
"updated": "Entorno actualizado",
|
||||
"value": "Value",
|
||||
"value": "Valor",
|
||||
"variable": "Variable",
|
||||
"variable_list": "Lista de variables"
|
||||
},
|
||||
"error": {
|
||||
"authproviders_load_error": "Unable to load auth providers",
|
||||
"authproviders_load_error": "No se han podido cargar los proveedores de autenticación",
|
||||
"browser_support_sse": "Este navegador no parece ser compatible con los eventos enviados por el servidor.",
|
||||
"check_console_details": "Consulta el registro de la consola para obtener más detalles.",
|
||||
"check_how_to_add_origin": "Check how you can add an origin",
|
||||
"check_how_to_add_origin": "Comprueba cómo puede añadir un origen",
|
||||
"curl_invalid_format": "cURL no está formateado correctamente",
|
||||
"danger_zone": "Zona de peligro",
|
||||
"delete_account": "Tu cuenta es actualmente propietaria en estos equipos:",
|
||||
@@ -300,13 +300,13 @@
|
||||
"json_prettify_invalid_body": "No se puede aplicar embellecedor a un cuerpo inválido, resuelve errores de sintaxis json y vuelve a intentarlo",
|
||||
"network_error": "Parece que hay un error de red. Por favor, inténtalo de nuevo.",
|
||||
"network_fail": "No se pudo enviar la solicitud",
|
||||
"no_collections_to_export": "No collections to export. Please create a collection to get started.",
|
||||
"no_collections_to_export": "No hay colecciones para exportar. Crea una colección para empezar.",
|
||||
"no_duration": "Sin duración",
|
||||
"no_environments_to_export": "No environments to export. Please create an environment to get started.",
|
||||
"no_environments_to_export": "No hay entornos para exportar. Por favor, crea un entorno para empezar.",
|
||||
"no_results_found": "No se han encontrado coincidencias",
|
||||
"page_not_found": "No se ha podido encontrar esta página",
|
||||
"please_install_extension": "Please install the extension and add origin to the extension.",
|
||||
"proxy_error": "Proxy error",
|
||||
"proxy_error": "Error de proxy",
|
||||
"script_fail": "No se pudo ejecutar el script de solicitud previa",
|
||||
"something_went_wrong": "Algo salió mal",
|
||||
"test_script_fail": "No se ha podido ejecutar la secuencia de comandos posterior a la solicitud"
|
||||
@@ -314,15 +314,15 @@
|
||||
"export": {
|
||||
"as_json": "Exportar como JSON",
|
||||
"create_secret_gist": "Crear un Gist secreto",
|
||||
"failed": "Something went wrong while exporting",
|
||||
"failed": "Algo ha ido mal al exportar",
|
||||
"gist_created": "Gist creado",
|
||||
"require_github": "Iniciar sesión con GitHub para crear un Gist secreto",
|
||||
"title": "Exportar"
|
||||
},
|
||||
"filter": {
|
||||
"all": "All",
|
||||
"none": "None",
|
||||
"starred": "Starred"
|
||||
"all": "Todos",
|
||||
"none": "Ninguno",
|
||||
"starred": "Destacado"
|
||||
},
|
||||
"folder": {
|
||||
"created": "Carpeta creada",
|
||||
@@ -333,16 +333,16 @@
|
||||
"renamed": "Carpeta renombrada"
|
||||
},
|
||||
"graphql": {
|
||||
"connection_switch_confirm": "Do you want to connect with the latest GraphQL endpoint?",
|
||||
"connection_switch_new_url": "Switching to a tab will disconnected you from the active GraphQL connection. New connection URL is",
|
||||
"connection_switch_url": "You're connected to a GraphQL endpoint the connection URL is",
|
||||
"connection_switch_confirm": "¿Deseas conectarte con el endpoint GraphQL más reciente?",
|
||||
"connection_switch_new_url": "Al cambiar a una pestaña se desconectará de la conexión GraphQL activa. La nueva URL de conexión es",
|
||||
"connection_switch_url": "Estás conectado a un endpoint GraphQL cuya URL de conexión es",
|
||||
"mutations": "Mutaciones",
|
||||
"schema": "Esquema",
|
||||
"subscriptions": "Suscripciones",
|
||||
"switch_connection": "Switch connection"
|
||||
"switch_connection": "Cambiar conexión"
|
||||
},
|
||||
"graphql_collections": {
|
||||
"title": "GraphQL Collections"
|
||||
"title": "Colecciones de GraphQL"
|
||||
},
|
||||
"group": {
|
||||
"time": "Tiempo",
|
||||
@@ -355,8 +355,8 @@
|
||||
},
|
||||
"helpers": {
|
||||
"authorization": "El encabezado de autorización se generará automáticamente cuando se envía la solicitud.",
|
||||
"collection_properties_authorization": " This authorization will be set for every request in this collection.",
|
||||
"collection_properties_header": "This header will be set for every request in this collection.",
|
||||
"collection_properties_authorization": " Esta autorización se establecerá para cada solicitud de esta colección.",
|
||||
"collection_properties_header": "Este encabezado se establecerá para cada solicitud de esta colección.",
|
||||
"generate_documentation_first": "Generar la documentación primero",
|
||||
"network_fail": "No se puede acceder a la API. Comprueba tu conexión de red y vuelve a intentarlo.",
|
||||
"offline": "Parece estar desconectado. Es posible que los datos de este espacio de trabajo no estén actualizados.",
|
||||
@@ -376,10 +376,10 @@
|
||||
"import": {
|
||||
"collections": "Importar colecciones",
|
||||
"curl": "Importar cURL",
|
||||
"environments_from_gist": "Import From Gist",
|
||||
"environments_from_gist_description": "Import Hoppscotch Environments From Gist",
|
||||
"environments_from_gist": "Importar desde Gist",
|
||||
"environments_from_gist_description": "Importar entornos Hoppscotch desde Gist",
|
||||
"failed": "Importación fallida",
|
||||
"from_file": "Import from File",
|
||||
"from_file": "Importar desde archivo",
|
||||
"from_gist": "Importar desde Gist",
|
||||
"from_gist_description": "Importar desde URL de Gist",
|
||||
"from_insomnia": "Importar desde Insomnia",
|
||||
@@ -394,41 +394,41 @@
|
||||
"from_postman_description": "Importar desde una colección de Postman",
|
||||
"from_url": "Importar desde una URL",
|
||||
"gist_url": "Introduce la URL de Gist",
|
||||
"gql_collections_from_gist_description": "Import GraphQL Collections From Gist",
|
||||
"hoppscotch_environment": "Hoppscotch Environment",
|
||||
"hoppscotch_environment_description": "Import Hoppscotch Environment JSON file",
|
||||
"import_from_url_invalid_fetch": "Couldn't get data from the url",
|
||||
"import_from_url_invalid_file_format": "Error while importing collections",
|
||||
"import_from_url_invalid_type": "Unsupported type. accepted values are 'hoppscotch', 'openapi', 'postman', 'insomnia'",
|
||||
"import_from_url_success": "Collections Imported",
|
||||
"insomnia_environment_description": "Import Insomnia Environment from a JSON/YAML file",
|
||||
"gql_collections_from_gist_description": "Importar colecciones GraphQL desde Gist",
|
||||
"hoppscotch_environment": "Entorno de Hoppscotch",
|
||||
"hoppscotch_environment_description": "Importar archivo JSON del entorno de Hoppscotch",
|
||||
"import_from_url_invalid_fetch": "No se han podido obtener datos de la url",
|
||||
"import_from_url_invalid_file_format": "Error al importar colecciones",
|
||||
"import_from_url_invalid_type": "Tipo no admitido. Los valores aceptados son \"hoppscotch\", \"openapi\", \"postman\", \"insomnia\".",
|
||||
"import_from_url_success": "Colecciones Importadas",
|
||||
"insomnia_environment_description": "Importar el entorno de Insomnia desde un archivo JSON/YAML",
|
||||
"json_description": "Importar colecciones desde un archivo JSON de colecciones de Hoppscotch",
|
||||
"postman_environment": "Postman Environment",
|
||||
"postman_environment_description": "Import Postman Environment from a JSON file",
|
||||
"postman_environment": "Entorno de Postman",
|
||||
"postman_environment_description": "Importar entorno de Postman desde un archivo JSON",
|
||||
"title": "Importar"
|
||||
},
|
||||
"inspections": {
|
||||
"description": "Inspect possible errors",
|
||||
"description": "Inspeccionar posibles errores",
|
||||
"environment": {
|
||||
"add_environment": "Add to Environment",
|
||||
"not_found": "Environment variable “{environment}” not found."
|
||||
"add_environment": "Añadir al Entorno",
|
||||
"not_found": "No se ha encontrado la variable de entorno \"{environment}\"."
|
||||
},
|
||||
"header": {
|
||||
"cookie": "The browser doesn't allow Hoppscotch to set the Cookie Header. While we're working on the Hoppscotch Desktop App (coming soon), please use the Authorization Header instead."
|
||||
"cookie": "El navegador no permite que Hoppscotch establezca el encabezado Cookie. Mientras trabajamos en la aplicación de escritorio de Hoppscotch (próximamente), por favor utilice el encabezado de autorización en su lugar."
|
||||
},
|
||||
"response": {
|
||||
"401_error": "Please check your authentication credentials.",
|
||||
"404_error": "Please check your request URL and method type.",
|
||||
"cors_error": "Please check your Cross-Origin Resource Sharing configuration.",
|
||||
"default_error": "Please check your request.",
|
||||
"network_error": "Please check your network connection."
|
||||
"401_error": "Compruebe tus credenciales de autenticación.",
|
||||
"404_error": "Compruebe la URL de su solicitud y el tipo de método.",
|
||||
"cors_error": "Por favor, comprueba tu configuración de Compartición de Recursos \"Cross-Origin\".",
|
||||
"default_error": "Por favor, comprueba tu solicitud.",
|
||||
"network_error": "Comprueba tu conexión de red."
|
||||
},
|
||||
"title": "Inspector",
|
||||
"title": "Inspeccionador",
|
||||
"url": {
|
||||
"extension_not_installed": "Extension not installed.",
|
||||
"extension_unknown_origin": "Make sure you've added the API endpoint's origin to the Hoppscotch Browser Extension list.",
|
||||
"extention_enable_action": "Enable Browser Extension",
|
||||
"extention_not_enabled": "Extension not enabled."
|
||||
"extension_not_installed": "Extensión no instalada.",
|
||||
"extension_unknown_origin": "Asegúrate de haber agregado el origen del punto final de la API a la lista de Extensiones del Navegador Hoppscotch.",
|
||||
"extention_enable_action": "Activar la extensión del navegador",
|
||||
"extention_not_enabled": "Extensión no habilitada."
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
@@ -442,10 +442,10 @@
|
||||
"close_unsaved_tab": "Tienes cambios sin guardar",
|
||||
"collections": "Colecciones",
|
||||
"confirm": "Confirmar",
|
||||
"customize_request": "Customize Request",
|
||||
"customize_request": "Personalizar solicitud",
|
||||
"edit_request": "Editar solicitud",
|
||||
"import_export": "Importación y exportación",
|
||||
"share_request": "Share Request"
|
||||
"share_request": "Compartir solicitud"
|
||||
},
|
||||
"mqtt": {
|
||||
"already_subscribed": "Ya estás suscrito a este tema.",
|
||||
@@ -493,7 +493,7 @@
|
||||
},
|
||||
"profile": {
|
||||
"app_settings": "Ajustes de la aplicación",
|
||||
"default_hopp_displayname": "Unnamed User",
|
||||
"default_hopp_displayname": "Usuario anónimo",
|
||||
"editor": "Editor",
|
||||
"editor_description": "Los editores pueden añadir, editar y eliminar solicitudes.",
|
||||
"email_verification_mail": "Se ha enviado un correo electrónico de verificación a tu dirección de correo electrónico. Haz clic en el enlace para verificar tu dirección de correo electrónico.",
|
||||
@@ -526,12 +526,12 @@
|
||||
"enter_curl": "Ingrese cURL",
|
||||
"generate_code": "Generar código",
|
||||
"generated_code": "Código generado",
|
||||
"go_to_authorization_tab": "Go to Authorization tab",
|
||||
"go_to_body_tab": "Go to Body tab",
|
||||
"go_to_authorization_tab": "Ir a la pestaña Autorización",
|
||||
"go_to_body_tab": "Ir a la pestaña de cuerpo",
|
||||
"header_list": "Lista de encabezados",
|
||||
"invalid_name": "Proporciona un nombre para la solicitud.",
|
||||
"method": "Método",
|
||||
"moved": "Request moved",
|
||||
"moved": "Solicitud movida",
|
||||
"name": "Nombre de solicitud",
|
||||
"new": "Nueva solicitud",
|
||||
"order_changed": "Orden de solicitudes actualizadas",
|
||||
@@ -543,8 +543,8 @@
|
||||
"path": "Ruta",
|
||||
"payload": "Carga útil",
|
||||
"query": "Consulta",
|
||||
"raw_body": "Cuerpo de solicitud sin procesar",
|
||||
"rename": "Rename Request",
|
||||
"raw_body": "cuerpo sin procesar",
|
||||
"rename": "Renombrar solicitud",
|
||||
"renamed": "Solicitud renombrada",
|
||||
"run": "Ejecutar",
|
||||
"save": "Guardar",
|
||||
@@ -552,8 +552,8 @@
|
||||
"saved": "Solicitud guardada",
|
||||
"share": "Compartir",
|
||||
"share_description": "Comparte Hoppscotch con tus amigos",
|
||||
"share_request": "Share Request",
|
||||
"stop": "Stop",
|
||||
"share_request": "Compartir solicitud",
|
||||
"stop": "Detener",
|
||||
"title": "Solicitud",
|
||||
"type": "Tipo de solicitud",
|
||||
"url": "URL",
|
||||
@@ -571,7 +571,7 @@
|
||||
"json": "JSON",
|
||||
"pdf": "PDF",
|
||||
"preview_html": "Vista previa de HTML",
|
||||
"raw": "Crudo",
|
||||
"raw": "Sin procesar",
|
||||
"size": "Tamaño",
|
||||
"status": "Estado",
|
||||
"time": "Tiempo",
|
||||
@@ -635,29 +635,29 @@
|
||||
"verify_email": "Verificar correo electrónico"
|
||||
},
|
||||
"shared_requests": {
|
||||
"button": "Button",
|
||||
"button_info": "Create a 'Run in Hoppscotch' button for your website, blog or a README.",
|
||||
"copy_html": "Copy HTML",
|
||||
"copy_link": "Copy Link",
|
||||
"copy_markdown": "Copy Markdown",
|
||||
"creating_widget": "Creating widget",
|
||||
"customize": "Customize",
|
||||
"deleted": "Shared request deleted",
|
||||
"description": "Select a widget, you can change and customize this later",
|
||||
"embed": "Embed",
|
||||
"embed_info": "Add a mini 'Hoppscotch API Playground' to your website, blog or documentation.",
|
||||
"link": "Link",
|
||||
"link_info": "Create a shareable link to share with anyone on the internet with view access.",
|
||||
"modified": "Shared request modified",
|
||||
"not_found": "Shared request not found",
|
||||
"open_new_tab": "Open in new tab",
|
||||
"preview": "Preview",
|
||||
"run_in_hoppscotch": "Run in Hoppscotch",
|
||||
"button": "Botón",
|
||||
"button_info": "Crea un botón \"Ejecutar en Hoppscotch\" para tu página web, blog o un README.",
|
||||
"copy_html": "Copiar HTML",
|
||||
"copy_link": "Copiar enlace",
|
||||
"copy_markdown": "Copiar Markdown",
|
||||
"creating_widget": "Crear widget",
|
||||
"customize": "Personalizar",
|
||||
"deleted": "Solicitud compartida eliminada",
|
||||
"description": "Selecciona un widget, puedes cambiarlo y personalizarlo más tarde",
|
||||
"embed": "Incrustar",
|
||||
"embed_info": "Añada un mini \"Hoppscotch API Playground\" a tu sitio web, blog o documentación.",
|
||||
"link": "Enlace",
|
||||
"link_info": "Crea un enlace compartible para compartirlo con cualquier persona en Internet con acceso de visualización.",
|
||||
"modified": "Solicitud compartida modificada",
|
||||
"not_found": "Solicitud compartida no encontrada",
|
||||
"open_new_tab": "Abrir en una nueva pestaña",
|
||||
"preview": "Vista previa",
|
||||
"run_in_hoppscotch": "Correr en Hoppscotch",
|
||||
"theme": {
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System",
|
||||
"title": "Theme"
|
||||
"dark": "Oscuro",
|
||||
"light": "Claro",
|
||||
"system": "Sistema",
|
||||
"title": "Tema"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
@@ -684,8 +684,8 @@
|
||||
"title": "Navegación"
|
||||
},
|
||||
"others": {
|
||||
"prettify": "Prettify Editor's Content",
|
||||
"title": "Others"
|
||||
"prettify": "Formatear el contenido del editor",
|
||||
"title": "Otros"
|
||||
},
|
||||
"request": {
|
||||
"delete_method": "Seleccionar método DELETE",
|
||||
@@ -697,13 +697,13 @@
|
||||
"post_method": "Seleccionar método POST",
|
||||
"previous_method": "Seleccionar método anterior",
|
||||
"put_method": "Seleccionar método PUT",
|
||||
"rename": "Rename Request",
|
||||
"rename": "Renombrar solicitud",
|
||||
"reset_request": "Solicitud de reinicio",
|
||||
"save_request": "Save Request",
|
||||
"save_request": "Guardar solicitud",
|
||||
"save_to_collections": "Guardar en colecciones",
|
||||
"send_request": "Enviar solicitud",
|
||||
"share_request": "Share Request",
|
||||
"show_code": "Generate code snippet",
|
||||
"share_request": "Compartir solicitud",
|
||||
"show_code": "Generar fragmento de código",
|
||||
"title": "Solicitud",
|
||||
"copy_request_link": "Copiar enlace de solicitud"
|
||||
},
|
||||
@@ -722,95 +722,95 @@
|
||||
},
|
||||
"show": {
|
||||
"code": "Mostrar código",
|
||||
"collection": "Expand Collection Panel",
|
||||
"collection": "Ampliar el panel de colecciones",
|
||||
"more": "Mostrar más",
|
||||
"sidebar": "Mostrar barra lateral"
|
||||
},
|
||||
"socketio": {
|
||||
"communication": "Comunicación",
|
||||
"connection_not_authorized": "This SocketIO connection does not use any authentication.",
|
||||
"connection_not_authorized": "Esta conexión SocketIO no utiliza ningún tipo de autenticación.",
|
||||
"event_name": "Nombre del evento",
|
||||
"events": "Eventos",
|
||||
"log": "Registro",
|
||||
"url": "URL"
|
||||
},
|
||||
"spotlight": {
|
||||
"change_language": "Change Language",
|
||||
"change_language": "Cambiar idioma",
|
||||
"environments": {
|
||||
"delete": "Delete current environment",
|
||||
"duplicate": "Duplicate current environment",
|
||||
"duplicate_global": "Duplicate global environment",
|
||||
"edit": "Edit current environment",
|
||||
"edit_global": "Edit global environment",
|
||||
"new": "Create new environment",
|
||||
"new_variable": "Create a new environment variable",
|
||||
"title": "Environments"
|
||||
"delete": "Borrar el entorno actual",
|
||||
"duplicate": "Duplicar el entorno actual",
|
||||
"duplicate_global": "Entorno global duplicado",
|
||||
"edit": "Editar el entorno actual",
|
||||
"edit_global": "Editar el entorno global",
|
||||
"new": "Crear un nuevo entorno",
|
||||
"new_variable": "Crear una nueva variable de entorno",
|
||||
"title": "Entornos"
|
||||
},
|
||||
"general": {
|
||||
"chat": "Chat with support",
|
||||
"help_menu": "Help and support",
|
||||
"open_docs": "Read Documentation",
|
||||
"open_github": "Open GitHub repository",
|
||||
"open_keybindings": "Keyboard shortcuts",
|
||||
"chat": "Chatear con el servicio de asistencia",
|
||||
"help_menu": "Ayuda y asistencia",
|
||||
"open_docs": "Leer la documentación",
|
||||
"open_github": "Abrir repositorio de GitHub",
|
||||
"open_keybindings": "Atajos de teclado",
|
||||
"social": "Social",
|
||||
"title": "General"
|
||||
},
|
||||
"graphql": {
|
||||
"connect": "Connect to server",
|
||||
"disconnect": "Disconnect from server"
|
||||
"connect": "Conectarse al servidor",
|
||||
"disconnect": "Desconectarse del servidor"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"invite": "Invite your friends to Hoppscotch",
|
||||
"title": "Miscellaneous"
|
||||
"invite": "Invita a tus amigos a Hoppscotch",
|
||||
"title": "Varios"
|
||||
},
|
||||
"request": {
|
||||
"save_as_new": "Save as new request",
|
||||
"select_method": "Select method",
|
||||
"switch_to": "Switch to",
|
||||
"tab_authorization": "Authorization tab",
|
||||
"tab_body": "Body tab",
|
||||
"tab_headers": "Headers tab",
|
||||
"tab_parameters": "Parameters tab",
|
||||
"tab_pre_request_script": "Pre-request script tab",
|
||||
"tab_query": "Query tab",
|
||||
"tab_tests": "Tests tab",
|
||||
"tab_variables": "Variables tab"
|
||||
"save_as_new": "Guardar como nueva solicitud",
|
||||
"select_method": "Seleccionar método",
|
||||
"switch_to": "Cambiar a",
|
||||
"tab_authorization": "Pestaña de autorización",
|
||||
"tab_body": "Pestaña de cuerpo",
|
||||
"tab_headers": "Pestaña de encabezados",
|
||||
"tab_parameters": "Pestaña de parámetros",
|
||||
"tab_pre_request_script": "Pestaña del script de pre-solicitud",
|
||||
"tab_query": "Pestaña de consulta",
|
||||
"tab_tests": "Pestaña de pruebas",
|
||||
"tab_variables": "Pestaña de variables"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Copy response",
|
||||
"download": "Download response as file",
|
||||
"title": "Response"
|
||||
"copy": "Copiar respuesta",
|
||||
"download": "Descargar la respuesta como archivo",
|
||||
"title": "Respuesta"
|
||||
},
|
||||
"section": {
|
||||
"interceptor": "Interceptor",
|
||||
"interface": "Interface",
|
||||
"theme": "Theme",
|
||||
"user": "User"
|
||||
"interface": "Interfaz",
|
||||
"theme": "Tema",
|
||||
"user": "Usuario"
|
||||
},
|
||||
"settings": {
|
||||
"change_interceptor": "Change Interceptor",
|
||||
"change_language": "Change Language",
|
||||
"change_interceptor": "Cambiar Interceptor",
|
||||
"change_language": "Cambiar idioma",
|
||||
"theme": {
|
||||
"black": "Black",
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System preference"
|
||||
"black": "Negro",
|
||||
"dark": "Oscuro",
|
||||
"light": "Claro",
|
||||
"system": "Preferencia del sistema"
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"close_current": "Close current tab",
|
||||
"close_others": "Close all other tabs",
|
||||
"duplicate": "Duplicate current tab",
|
||||
"new_tab": "Open a new tab",
|
||||
"title": "Tabs"
|
||||
"close_current": "Cerrar la pestaña actual",
|
||||
"close_others": "Cerrar todas las demás pestañas",
|
||||
"duplicate": "Duplicar pestaña actual",
|
||||
"new_tab": "Abrir una nueva pestaña",
|
||||
"title": "Pestañas"
|
||||
},
|
||||
"workspace": {
|
||||
"delete": "Delete current team",
|
||||
"edit": "Edit current team",
|
||||
"invite": "Invite people to team",
|
||||
"new": "Create new team",
|
||||
"switch_to_personal": "Switch to your personal workspace",
|
||||
"title": "Teams"
|
||||
"delete": "Borrar el equipo actual",
|
||||
"edit": "Editar el equipo actual",
|
||||
"invite": "Invitar al equipo",
|
||||
"new": "Crear un nuevo equipo",
|
||||
"switch_to_personal": "Cambia a tu espacio de trabajo personal",
|
||||
"title": "Equipos"
|
||||
}
|
||||
},
|
||||
"sse": {
|
||||
@@ -825,10 +825,10 @@
|
||||
"connected": "Conectado",
|
||||
"connected_to": "Conectado a {name}",
|
||||
"connecting_to": "Conectando con {name}...",
|
||||
"connection_error": "Failed to connect",
|
||||
"connection_failed": "Error de conexión",
|
||||
"connection_error": "Error de conexión",
|
||||
"connection_failed": "Conexión fallida",
|
||||
"connection_lost": "Conexión perdida",
|
||||
"copied_interface_to_clipboard": "Copied {language} interface type to clipboard",
|
||||
"copied_interface_to_clipboard": "Copiado tipo de interfaz {language} al portapapeles",
|
||||
"copied_to_clipboard": "Copiado al portapapeles",
|
||||
"deleted": "Eliminado",
|
||||
"deprecated": "OBSOLETO",
|
||||
@@ -836,21 +836,21 @@
|
||||
"disconnected": "Desconectado",
|
||||
"disconnected_from": "Desconectado de {name}",
|
||||
"docs_generated": "Documentación generada",
|
||||
"download_failed": "Download failed",
|
||||
"download_failed": "Descarga fallida",
|
||||
"download_started": "Descarga iniciada",
|
||||
"enabled": "Activado",
|
||||
"file_imported": "Archivo importado",
|
||||
"finished_in": "Terminado en {duration} ms",
|
||||
"hide": "Hide",
|
||||
"finished_in": "Terminado en {duration}ms",
|
||||
"hide": "Ocultar",
|
||||
"history_deleted": "Historial eliminado",
|
||||
"linewrap": "Envolver líneas",
|
||||
"loading": "Cargando...",
|
||||
"message_received": "Mensaje: {mensaje} llegó sobre el tema: {topic}",
|
||||
"message_received": "Mensaje: llegó {message} al: {topic}",
|
||||
"mqtt_subscription_failed": "Algo ha ido mal al suscribirse al tema: {topic}",
|
||||
"none": "Ninguno",
|
||||
"nothing_found": "Nada encontrado para",
|
||||
"published_error": "Algo ha ido mal al publicar el mensaje: {topic} al tema: {message}",
|
||||
"published_message": "Mensaje publicado: {mensaje} al tema: {topic}",
|
||||
"published_error": "Algo ha ido mal al publicar el mensaje: {message} al tema: {topic}",
|
||||
"published_message": "Mensaje publicado: {message} al tema: {topic}",
|
||||
"reconnection_error": "Fallo en la reconexión",
|
||||
"show": "Show",
|
||||
"subscribed_failed": "Error al suscribirse al tema: {topic}",
|
||||
@@ -874,12 +874,12 @@
|
||||
"tab": {
|
||||
"authorization": "Autorización",
|
||||
"body": "Cuerpo",
|
||||
"close": "Close Tab",
|
||||
"close_others": "Close other Tabs",
|
||||
"close": "Cerrar pestaña",
|
||||
"close_others": "Cerrar otras pestañas",
|
||||
"collections": "Colecciones",
|
||||
"documentation": "Documentación",
|
||||
"duplicate": "Duplicate Tab",
|
||||
"environments": "Environments",
|
||||
"duplicate": "Duplicar pestaña",
|
||||
"environments": "Entornos",
|
||||
"headers": "Encabezados",
|
||||
"history": "Historial",
|
||||
"mqtt": "MQTT",
|
||||
@@ -888,7 +888,7 @@
|
||||
"queries": "Consultas",
|
||||
"query": "Consulta",
|
||||
"schema": "Esquema",
|
||||
"shared_requests": "Shared Requests",
|
||||
"shared_requests": "Solicitudes compartidas",
|
||||
"socketio": "Socket.IO",
|
||||
"sse": "SSE",
|
||||
"tests": "Pruebas",
|
||||
@@ -905,7 +905,7 @@
|
||||
"email_do_not_match": "El correo electrónico no coincide con los datos de tu cuenta. Ponte en contacto con el propietario de tu equipo.",
|
||||
"exit": "Salir del equipo",
|
||||
"exit_disabled": "Solo el propietario puede salir del equipo",
|
||||
"failed_invites": "Failed invites",
|
||||
"failed_invites": "Invitaciones fallidas",
|
||||
"invalid_coll_id": "Identificador de colección no válido",
|
||||
"invalid_email_format": "El formato de correo electrónico no es válido",
|
||||
"invalid_id": "Identificador de equipo inválido. Ponte en contacto con el propietario de tu equipo.",
|
||||
@@ -915,7 +915,7 @@
|
||||
"invite": "Invitar",
|
||||
"invite_more": "Invitar a más",
|
||||
"invite_tooltip": "Invite a personas a este espacio de trabajo",
|
||||
"invited_to_team": "{owner} te ha invitado a unirte al {tema}",
|
||||
"invited_to_team": "{owner} te ha invitado al equipo {team}",
|
||||
"join": "Invitación aceptada",
|
||||
"join_beta": "Únete al programa beta para acceder a los equipos.",
|
||||
"join_team": "Entrar a {team}",
|
||||
@@ -930,7 +930,7 @@
|
||||
"member_removed": "Usuario eliminado",
|
||||
"member_role_updated": "Funciones de usuario actualizadas",
|
||||
"members": "Miembros",
|
||||
"more_members": "+{count} more",
|
||||
"more_members": "+{count} más",
|
||||
"name_length_insufficient": "El nombre del equipo debe tener al menos 6 caracteres",
|
||||
"name_updated": "Nombre de equipo actualizado",
|
||||
"new": "Nuevo equipo",
|
||||
@@ -944,13 +944,13 @@
|
||||
"parent_coll_move": "No se puede mover la colección a una colección hija",
|
||||
"pending_invites": "Invitaciones pendientes",
|
||||
"permissions": "Permisos",
|
||||
"same_target_destination": "Same target and destination",
|
||||
"same_target_destination": "Mismo objetivo y destino",
|
||||
"saved": "Equipo guardado",
|
||||
"select_a_team": "Seleccionar un equipo",
|
||||
"success_invites": "Success invites",
|
||||
"success_invites": "Invitaciones con éxito",
|
||||
"title": "Equipos",
|
||||
"we_sent_invite_link": "¡Hemos enviado un enlace de invitación a todos los invitados!",
|
||||
"we_sent_invite_link_description": "Pide a todos los invitados que revisen tu bandeja de entrada. Haz clic en el enlace para unirse al equipo."
|
||||
"we_sent_invite_link_description": "Pide a todos los invitados que revisen su bandeja de entrada. Tienen que hacer clic en el enlace para unirse al equipo."
|
||||
},
|
||||
"team_environment": {
|
||||
"deleted": "Entorno eliminado",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"action": {
|
||||
"add": "Add",
|
||||
"autoscroll": "Autoscroll",
|
||||
"add": "Ajouter",
|
||||
"autoscroll": "Auto-scroll",
|
||||
"cancel": "Annuler",
|
||||
"choose_file": "Choisir un fichier",
|
||||
"clear": "Effacer",
|
||||
"clear_all": "Tout effacer",
|
||||
"clear_history": "Clear all History",
|
||||
"close": "Close",
|
||||
"clear_history": "Effacer tout l'historique",
|
||||
"close": "Fermer",
|
||||
"connect": "Connecter",
|
||||
"connecting": "Connecting",
|
||||
"connecting": "Connexion",
|
||||
"copy": "Copier",
|
||||
"create": "Create",
|
||||
"delete": "Supprimer",
|
||||
@@ -22,8 +22,8 @@
|
||||
"edit": "Éditer",
|
||||
"filter": "Filter",
|
||||
"go_back": "Retour",
|
||||
"go_forward": "Go forward",
|
||||
"group_by": "Group by",
|
||||
"go_forward": "Avancer",
|
||||
"group_by": "Grouper par",
|
||||
"label": "Étiqueter",
|
||||
"learn_more": "En savoir plus",
|
||||
"less": "Moins",
|
||||
@@ -35,16 +35,16 @@
|
||||
"prettify": "Formater",
|
||||
"properties": "Properties",
|
||||
"remove": "Supprimer",
|
||||
"rename": "Rename",
|
||||
"rename": "Renommer",
|
||||
"restore": "Restaurer",
|
||||
"save": "Sauvegarder",
|
||||
"scroll_to_bottom": "Scroll to bottom",
|
||||
"scroll_to_top": "Scroll to top",
|
||||
"scroll_to_bottom": "Défiler vers le bas",
|
||||
"scroll_to_top": "Défiler vers le haut",
|
||||
"search": "Chercher",
|
||||
"send": "Envoyer",
|
||||
"share": "Share",
|
||||
"start": "Démarrer",
|
||||
"starting": "Starting",
|
||||
"starting": "Démarrage",
|
||||
"stop": "Arrêter",
|
||||
"to_close": "pour fermer",
|
||||
"to_navigate": "pour naviguer",
|
||||
@@ -86,8 +86,8 @@
|
||||
"search": "Chercher",
|
||||
"share": "Partager",
|
||||
"shortcuts": "Raccourcis",
|
||||
"social_description": "Follow us on social media to stay updated with the latest news, updates and releases.",
|
||||
"social_links": "Social links",
|
||||
"social_description": "Suivez-nous sur les médias sociaux pour rester informé des dernières nouvelles, mises à jour et communiqués.",
|
||||
"social_links": "Liens sociaux",
|
||||
"spotlight": "Projecteur",
|
||||
"status": "Statut",
|
||||
"status_description": "Vérifier l'état du site web",
|
||||
@@ -95,7 +95,7 @@
|
||||
"twitter": "Twitter",
|
||||
"type_a_command_search": "Tapez une commande ou recherchez…",
|
||||
"we_use_cookies": "Nous utilisons des cookies",
|
||||
"whats_new": "Quoi de neuf?",
|
||||
"whats_new": "Quoi de neuf ?",
|
||||
"wiki": "Wiki"
|
||||
},
|
||||
"auth": {
|
||||
@@ -119,39 +119,38 @@
|
||||
},
|
||||
"authorization": {
|
||||
"generate_token": "Générer un jeton",
|
||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||
"graphql_headers": "Les en-têtes d'autorisation sont envoyés en tant que partie de la charge utile de connection_init.",
|
||||
"include_in_url": "Inclure dans l'URL",
|
||||
"inherited_from": "Inherited from {auth} from Parent Collection {collection} ",
|
||||
"learn": "Apprendre comment",
|
||||
"oauth": {
|
||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||
"redirect_auth_token_request_failed": "Request to get the auth token failed",
|
||||
"redirect_auth_token_request_invalid_response": "Invalid Response from the Token Endpoint when requesting for an auth token",
|
||||
"redirect_invalid_state": "Invalid State value present in the redirect",
|
||||
"redirect_no_auth_code": "No Authorization Code present in the redirect",
|
||||
"redirect_no_client_id": "No Client ID defined",
|
||||
"redirect_no_client_secret": "No Client Secret Defined",
|
||||
"redirect_no_code_verifier": "No Code Verifier Defined",
|
||||
"redirect_no_token_endpoint": "No Token Endpoint Defined",
|
||||
"something_went_wrong_on_oauth_redirect": "Something went wrong during OAuth Redirect",
|
||||
"something_went_wrong_on_token_generation": "Something went wrong on token generation",
|
||||
"token_generation_oidc_discovery_failed": "Failure on token generation: OpenID Connect Discovery Failed"
|
||||
},
|
||||
"pass_key_by": "Pass by",
|
||||
"password": "Mot de passe",
|
||||
"save_to_inherit": "Please save this request in any collection to inherit the authorization",
|
||||
"token": "Jeton",
|
||||
"type": "Type d'autorisation",
|
||||
"username": "Nom d'utilisateur"
|
||||
"username": "Nom d'utilisateur",
|
||||
"oauth": {
|
||||
"something_went_wrong_on_token_generation": "Un problème s'est produit lors de la génération des jetons",
|
||||
"redirect_auth_server_returned_error": "Le serveur d'authentification a renvoyé un état d'erreur",
|
||||
"redirect_no_auth_code": "Pas de code d'autorisation dans la redirection",
|
||||
"redirect_invalid_state": "Valeur d'état non valide présente dans la redirection",
|
||||
"redirect_no_token_endpoint": "Aucun point de terminaison de jeton n'est défini",
|
||||
"redirect_no_client_id": "Pas d'ID client défini",
|
||||
"redirect_no_client_secret": "Pas de secret client défini",
|
||||
"redirect_no_code_verifier": "Pas de vérificateur de code défini",
|
||||
"redirect_auth_token_request_failed": "La demande d'obtention du jeton d'authentification a échoué",
|
||||
"redirect_auth_token_request_invalid_response": "Réponse invalide du point de terminaison Token lors de la demande d'un jeton d'authentification",
|
||||
"something_went_wrong_on_oauth_redirect": "Quelque chose s'est mal passé lors de la redirection OAuth"
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
"created": "Collection créée",
|
||||
"different_parent": "Cannot reorder collection with different parent",
|
||||
"different_parent": "Impossible de réorganiser une collection dont le parent est différent",
|
||||
"edit": "Modifier la collection",
|
||||
"import_or_create": "Import or create a collection",
|
||||
"import_or_create": "Importer ou créer une collection",
|
||||
"invalid_name": "Veuillez fournir un nom valide pour la collection",
|
||||
"invalid_root_move": "Collection already in the root",
|
||||
"moved": "Moved Successfully",
|
||||
"invalid_root_move": "Collection déjà présente dans la racine",
|
||||
"moved": "Déplacement réussi",
|
||||
"my_collections": "Mes collections",
|
||||
"name": "Ma nouvelle collection",
|
||||
"name_length_insufficient": "Le nom de la collection doit comporter au moins 3 caractères",
|
||||
@@ -162,16 +161,16 @@
|
||||
"renamed": "Collection renommée",
|
||||
"request_in_use": "Demande en cours d'utilisation",
|
||||
"save_as": "Enregistrer sous",
|
||||
"save_to_collection": "Save to Collection",
|
||||
"save_to_collection": "Enregistrer dans la collection",
|
||||
"select": "Sélectionnez une collection",
|
||||
"select_location": "Sélectionnez l'emplacement",
|
||||
"select_team": "Sélectionnez une équipe",
|
||||
"team_collections": "Collections de l'équipe"
|
||||
},
|
||||
"confirm": {
|
||||
"close_unsaved_tab": "Are you sure you want to close this tab?",
|
||||
"close_unsaved_tabs": "Are you sure you want to close all tabs? {count} unsaved tabs will be lost.",
|
||||
"exit_team": "Are you sure you want to leave this team?",
|
||||
"close_unsaved_tab": "Êtes-vous sûr de vouloir fermer cet onglet ?",
|
||||
"close_unsaved_tabs": "Êtes-vous sûr de vouloir fermer tous les onglets ? {count} onglets non enregistrés seront perdus",
|
||||
"exit_team": "Êtes-vous sûr de vouloir quitter cette équipe ?",
|
||||
"logout": "Êtes-vous sûr de vouloir vous déconnecter?",
|
||||
"remove_collection": "Voulez-vous vraiment supprimer définitivement cette collection ?",
|
||||
"remove_environment": "Voulez-vous vraiment supprimer définitivement cet environnement ?",
|
||||
@@ -181,31 +180,31 @@
|
||||
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
||||
"remove_team": "Voulez-vous vraiment supprimer cette équipe ?",
|
||||
"remove_telemetry": "Êtes-vous sûr de vouloir désactiver la télémétrie ?",
|
||||
"request_change": "Are you sure you want to discard current request, unsaved changes will be lost.",
|
||||
"save_unsaved_tab": "Do you want to save changes made in this tab?",
|
||||
"request_change": "Êtes-vous sûr de vouloir rejeter la demande en cours ? Les modifications non enregistrées seront perdues.",
|
||||
"save_unsaved_tab": "Souhaitez-vous enregistrer les modifications apportées dans cet onglet ?",
|
||||
"sync": "Voulez-vous vraiment synchroniser cet espace de travail ?"
|
||||
},
|
||||
"context_menu": {
|
||||
"add_parameters": "Add to parameters",
|
||||
"open_request_in_new_tab": "Open request in new tab",
|
||||
"set_environment_variable": "Set as variable"
|
||||
"add_parameters": "Ajouter aux paramètres",
|
||||
"open_request_in_new_tab": "Ouvrir la demande dans un nouvel onglet",
|
||||
"set_environment_variable": "Définir comme variable"
|
||||
},
|
||||
"cookies": {
|
||||
"modal": {
|
||||
"cookie_expires": "Expires",
|
||||
"cookie_name": "Name",
|
||||
"cookie_path": "Path",
|
||||
"cookie_string": "Cookie string",
|
||||
"cookie_value": "Value",
|
||||
"empty_domain": "Domain is empty",
|
||||
"empty_domains": "Domain list is empty",
|
||||
"enter_cookie_string": "Enter cookie string",
|
||||
"interceptor_no_support": "Your currently selected interceptor does not support cookies. Select a different Interceptor and try again.",
|
||||
"managed_tab": "Managed",
|
||||
"new_domain_name": "New domain name",
|
||||
"no_cookies_in_domain": "No cookies set for this domain",
|
||||
"raw_tab": "Raw",
|
||||
"set": "Set a cookie"
|
||||
"new_domain_name": "Nouveau nom de domaine",
|
||||
"set": "Définir un cookie",
|
||||
"cookie_string": "Chaîne de caractères de cookie",
|
||||
"enter_cookie_string": "Saisir la chaîne de caractères du cookie",
|
||||
"cookie_name": "Nom",
|
||||
"cookie_value": "Valeur",
|
||||
"cookie_path": "Chemin d'accès",
|
||||
"cookie_expires": "Expiration",
|
||||
"managed_tab": "Gestion",
|
||||
"raw_tab": "Brut",
|
||||
"interceptor_no_support": "L'intercepteur que vous avez sélectionné ne prend pas en charge les cookies. Sélectionnez un autre intercepteur et réessayez.",
|
||||
"empty_domains": "La liste des domaines est vide",
|
||||
"empty_domain": "Le domaine est vide",
|
||||
"no_cookies_in_domain": "Aucun cookie n'est défini pour ce domaine"
|
||||
}
|
||||
},
|
||||
"count": {
|
||||
@@ -238,7 +237,7 @@
|
||||
"profile": "Connectez-vous pour voir votre profil",
|
||||
"protocols": "Les protocoles sont vides",
|
||||
"schema": "Se connecter à un point de terminaison GraphQL",
|
||||
"shared_requests": "Shared requests are empty",
|
||||
"shared_requests": "Il n'y a pas de requêtes partagées",
|
||||
"shared_requests_logout": "Login to view your shared requests or create a new one",
|
||||
"subscription": "Subscriptions are empty",
|
||||
"team_name": "Nom de l'équipe vide",
|
||||
@@ -252,15 +251,15 @@
|
||||
"create_new": "Créer un nouvel environnement",
|
||||
"created": "Environnement créé",
|
||||
"deleted": "Environnement supprimé",
|
||||
"duplicated": "Environment duplicated",
|
||||
"duplicated": "Environnement dupliqué",
|
||||
"edit": "Modifier l'environnement",
|
||||
"empty_variables": "No variables",
|
||||
"global": "Global",
|
||||
"global_variables": "Global variables",
|
||||
"import_or_create": "Import or create a environment",
|
||||
"global_variables": "Variables globales",
|
||||
"import_or_create": "Importer ou créer un environnement",
|
||||
"invalid_name": "Veuillez fournir un nom valide pour l'environnement",
|
||||
"list": "Environment variables",
|
||||
"my_environments": "My Environments",
|
||||
"list": "Variables d'environnement",
|
||||
"my_environments": "Mes environnements",
|
||||
"name": "Name",
|
||||
"nested_overflow": "les variables d'environnement imbriquées sont limitées à 10 niveaux",
|
||||
"new": "Nouvel environnement",
|
||||
@@ -284,11 +283,11 @@
|
||||
"authproviders_load_error": "Unable to load auth providers",
|
||||
"browser_support_sse": "Ce navigateur ne semble pas prendre en charge les événements envoyés par le serveur.",
|
||||
"check_console_details": "Consultez le journal de la console pour plus de détails.",
|
||||
"check_how_to_add_origin": "Check how you can add an origin",
|
||||
"check_how_to_add_origin": "Vérifiez comment vous pouvez ajouter une origine",
|
||||
"curl_invalid_format": "cURL n'est pas formaté correctement",
|
||||
"danger_zone": "Danger zone",
|
||||
"delete_account": "Your account is currently an owner in these teams:",
|
||||
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these teams before you can delete your account.",
|
||||
"danger_zone": "Zone de danger",
|
||||
"delete_account": "Votre compte est actuellement propriétaire de ces équipes :",
|
||||
"delete_account_description": "Vous devez vous retirer, transférer la propriété ou supprimer ces équipes avant de pouvoir supprimer votre compte.",
|
||||
"empty_req_name": "Nom de la requête vide",
|
||||
"f12_details": "(F12 pour les détails)",
|
||||
"gql_prettify_invalid_query": "Impossible de formater une requête non valide, résolvez les erreurs de syntaxe de la requête et réessayer",
|
||||
@@ -300,13 +299,13 @@
|
||||
"json_prettify_invalid_body": "Impossible de formater un corps non valide, résolvez les erreurs de syntaxe json et réessayez",
|
||||
"network_error": "Il semble y avoir une erreur de réseau. Veuillez réessayer.",
|
||||
"network_fail": "Impossible d'envoyer la requête",
|
||||
"no_collections_to_export": "No collections to export. Please create a collection to get started.",
|
||||
"no_collections_to_export": "Aucune collection à exporter. Veuillez créer une collection pour commencer.",
|
||||
"no_duration": "Pas de durée",
|
||||
"no_environments_to_export": "No environments to export. Please create an environment to get started.",
|
||||
"no_environments_to_export": "Aucun environnement à exporter. Veuillez créer un environnement pour commencer.",
|
||||
"no_results_found": "Aucune correspondance trouvée",
|
||||
"page_not_found": "Cette page n'a pas pu être trouvée",
|
||||
"please_install_extension": "Please install the extension and add origin to the extension.",
|
||||
"proxy_error": "Proxy error",
|
||||
"please_install_extension": "Veuillez installer l'extension et ajouter l'origine à l'extension.",
|
||||
"proxy_error": "Erreur de proxy",
|
||||
"script_fail": "Impossible d'exécuter le script de pré-requête",
|
||||
"something_went_wrong": "Quelque chose s'est mal passé",
|
||||
"test_script_fail": "Impossible d'exécuter le script post-requête"
|
||||
@@ -320,9 +319,9 @@
|
||||
"title": "Exportation"
|
||||
},
|
||||
"filter": {
|
||||
"all": "All",
|
||||
"none": "None",
|
||||
"starred": "Starred"
|
||||
"all": "Tout",
|
||||
"none": "Aucun",
|
||||
"starred": "Étoilé"
|
||||
},
|
||||
"folder": {
|
||||
"created": "Dossier créé",
|
||||
@@ -333,19 +332,19 @@
|
||||
"renamed": "Dossier renommé"
|
||||
},
|
||||
"graphql": {
|
||||
"connection_switch_confirm": "Do you want to connect with the latest GraphQL endpoint?",
|
||||
"connection_switch_new_url": "Switching to a tab will disconnected you from the active GraphQL connection. New connection URL is",
|
||||
"connection_switch_url": "You're connected to a GraphQL endpoint the connection URL is",
|
||||
"connection_switch_confirm": "Voulez-vous vous connecter avec le dernier point de terminaison GraphQL ?",
|
||||
"connection_switch_new_url": "Le passage à un autre onglet vous déconnectera de la connexion GraphQL active. La nouvelle URL de connexion est",
|
||||
"connection_switch_url": "Vous êtes connecté à un point de terminaison GraphQL dont l'URL de connexion est",
|
||||
"mutations": "Mutations",
|
||||
"schema": "Schéma",
|
||||
"subscriptions": "Abonnements",
|
||||
"switch_connection": "Switch connection"
|
||||
"switch_connection": "Changer de connexion"
|
||||
},
|
||||
"graphql_collections": {
|
||||
"title": "GraphQL Collections"
|
||||
},
|
||||
"group": {
|
||||
"time": "Time",
|
||||
"time": "Temps",
|
||||
"url": "URL"
|
||||
},
|
||||
"header": {
|
||||
@@ -376,7 +375,7 @@
|
||||
"import": {
|
||||
"collections": "Importer des collections",
|
||||
"curl": "Importer en cURL",
|
||||
"environments_from_gist": "Import From Gist",
|
||||
"environments_from_gist": "Importer depuis Gist",
|
||||
"environments_from_gist_description": "Import Hoppscotch Environments From Gist",
|
||||
"failed": "Échec de l'importation",
|
||||
"from_file": "Import from File",
|
||||
@@ -408,27 +407,27 @@
|
||||
"title": "Importer"
|
||||
},
|
||||
"inspections": {
|
||||
"description": "Inspect possible errors",
|
||||
"description": "Inspecter les erreurs possibles",
|
||||
"environment": {
|
||||
"add_environment": "Add to Environment",
|
||||
"not_found": "Environment variable “{environment}” not found."
|
||||
"add_environment": "Ajouter à l'environnement",
|
||||
"not_found": "La variable d'environnement “{environment}“ n'a pas été trouvée."
|
||||
},
|
||||
"header": {
|
||||
"cookie": "The browser doesn't allow Hoppscotch to set the Cookie Header. While we're working on the Hoppscotch Desktop App (coming soon), please use the Authorization Header instead."
|
||||
"cookie": "Le navigateur ne permet pas à Hoppscotch de définir l'en-tête Cookie. Pendant que nous travaillons sur l'application de bureau Hoppscotch (bientôt disponible), veuillez utiliser l'en-tête d'autorisation à la place."
|
||||
},
|
||||
"response": {
|
||||
"401_error": "Please check your authentication credentials.",
|
||||
"404_error": "Please check your request URL and method type.",
|
||||
"cors_error": "Please check your Cross-Origin Resource Sharing configuration.",
|
||||
"default_error": "Please check your request.",
|
||||
"network_error": "Please check your network connection."
|
||||
"401_error": "Veuillez vérifier vos informations d'authentification.",
|
||||
"404_error": "Veuillez vérifier l'URL de votre demande et le type de méthode.",
|
||||
"cors_error": "Veuillez vérifier la configuration du partage des ressources entre les origines.",
|
||||
"default_error": "Veuillez vérifier votre demande.",
|
||||
"network_error": "Veuillez vérifier votre connexion réseau."
|
||||
},
|
||||
"title": "Inspector",
|
||||
"title": "Inspecteur",
|
||||
"url": {
|
||||
"extension_not_installed": "Extension not installed.",
|
||||
"extension_unknown_origin": "Make sure you've added the API endpoint's origin to the Hoppscotch Browser Extension list.",
|
||||
"extention_enable_action": "Enable Browser Extension",
|
||||
"extention_not_enabled": "Extension not enabled."
|
||||
"extension_not_installed": "L'extension n'est pas installée.",
|
||||
"extension_unknown_origin": "Assurez-vous d'avoir ajouté l'origine du point de terminaison de l'API à la liste des extensions du navigateur Hoppscotch.",
|
||||
"extention_enable_action": "Activer l'extension du navigateur",
|
||||
"extention_not_enabled": "L'extension n'est pas activée."
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
@@ -439,25 +438,25 @@
|
||||
"row": "Disposition horizontale"
|
||||
},
|
||||
"modal": {
|
||||
"close_unsaved_tab": "You have unsaved changes",
|
||||
"close_unsaved_tab": "Vous avez des modifications non enregistrées",
|
||||
"collections": "Collections",
|
||||
"confirm": "Confirmer",
|
||||
"customize_request": "Customize Request",
|
||||
"edit_request": "Modifier la requête",
|
||||
"import_export": "Importer / Exporter",
|
||||
"share_request": "Share Request"
|
||||
"share_request": "Partager une requête"
|
||||
},
|
||||
"mqtt": {
|
||||
"already_subscribed": "You are already subscribed to this topic.",
|
||||
"clean_session": "Clean Session",
|
||||
"clear_input": "Clear input",
|
||||
"clear_input_on_send": "Clear input on send",
|
||||
"already_subscribed": "Vous êtes déjà abonné à ce sujet.",
|
||||
"clean_session": "Effacer la Session",
|
||||
"clear_input": "Effacer la saisie",
|
||||
"clear_input_on_send": "Effacer la saisie lors de l'envoi",
|
||||
"client_id": "Client ID",
|
||||
"color": "Pick a color",
|
||||
"color": "Choisir la couleur",
|
||||
"communication": "Communication",
|
||||
"connection_config": "Connection Config",
|
||||
"connection_not_authorized": "This MQTT connection does not use any authentication.",
|
||||
"invalid_topic": "Please provide a topic for the subscription",
|
||||
"connection_not_authorized": "Cette connexion MQTT n'utilise pas d'authentification.",
|
||||
"invalid_topic": "Veuillez fournir un sujet pour l'abonnement",
|
||||
"keep_alive": "Keep Alive",
|
||||
"log": "Infos",
|
||||
"lw_message": "Last-Will Message",
|
||||
@@ -466,7 +465,7 @@
|
||||
"lw_topic": "Last-Will Topic",
|
||||
"message": "Message",
|
||||
"new": "New Subscription",
|
||||
"not_connected": "Please start a MQTT connection first.",
|
||||
"not_connected": "Veuillez d'abord établir une connexion MQTT.",
|
||||
"publish": "Publier",
|
||||
"qos": "QoS",
|
||||
"ssl": "SSL",
|
||||
@@ -480,7 +479,7 @@
|
||||
"navigation": {
|
||||
"doc": "Documents",
|
||||
"graphql": "GraphQL",
|
||||
"profile": "Profile",
|
||||
"profile": "Profil",
|
||||
"realtime": "Temps réel",
|
||||
"rest": "REST",
|
||||
"settings": "Paramètres"
|
||||
@@ -493,7 +492,7 @@
|
||||
},
|
||||
"profile": {
|
||||
"app_settings": "Réglages de l'application",
|
||||
"default_hopp_displayname": "Unnamed User",
|
||||
"default_hopp_displayname": "Utilisateur anonyme",
|
||||
"editor": "Éditeur",
|
||||
"editor_description": "Les éditeurs peuvent ajouter, modifier et supprimer des demandes.",
|
||||
"email_verification_mail": "Un e-mail de vérification a été envoyé à votre adresse e-mail. Veuillez cliquer sur le lien pour vérifier votre adresse électronique.",
|
||||
@@ -526,17 +525,17 @@
|
||||
"enter_curl": "Entrer cURL",
|
||||
"generate_code": "Générer le code",
|
||||
"generated_code": "Code généré",
|
||||
"go_to_authorization_tab": "Go to Authorization tab",
|
||||
"go_to_body_tab": "Go to Body tab",
|
||||
"go_to_authorization_tab": "Aller à l'autorisation",
|
||||
"header_list": "Liste des en-têtes",
|
||||
"invalid_name": "Veuillez fournir un nom pour la requête",
|
||||
"method": "Méthode",
|
||||
"moved": "Request moved",
|
||||
"name": "Nom de la requête",
|
||||
"new": "Nouvelle requête",
|
||||
"order_changed": "Request Order Updated",
|
||||
"order_changed": "Demande de commande Mise à jour",
|
||||
"override": "Remplacer",
|
||||
"override_help": "Set <xmp>Content-Type</xmp> in Headers",
|
||||
"override_help": "Définir <xmp>Content-Type</xmp> dans les en-têtes",
|
||||
"overriden": "Remplacé",
|
||||
"parameter_list": "Paramètres de requête",
|
||||
"parameters": "Paramètres",
|
||||
@@ -544,7 +543,7 @@
|
||||
"payload": "Charge utile",
|
||||
"query": "Requête",
|
||||
"raw_body": "Corps de requête brut",
|
||||
"rename": "Rename Request",
|
||||
"rename": "Demande de renommage",
|
||||
"renamed": "Requête renommée",
|
||||
"run": "Lancer",
|
||||
"save": "Sauvegarder",
|
||||
@@ -564,7 +563,7 @@
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corps de réponse",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"filter_response_body": "Filtrer le corps de la réponse JSON (utilise la syntaxe JSONPath)",
|
||||
"headers": "En-têtes",
|
||||
"html": "HTML",
|
||||
"image": "Image",
|
||||
@@ -576,14 +575,14 @@
|
||||
"status": "Statut",
|
||||
"time": "Temps",
|
||||
"title": "Réponse",
|
||||
"video": "Video",
|
||||
"video": "Vidéo",
|
||||
"waiting_for_connection": "En attente de connexion",
|
||||
"xml": "XML"
|
||||
},
|
||||
"settings": {
|
||||
"accent_color": "Couleur d'accent",
|
||||
"account": "Compte",
|
||||
"account_deleted": "Your account has been deleted",
|
||||
"account_deleted": "Votre compte a été supprimé",
|
||||
"account_description": "Personnalisez les paramètres de votre compte.",
|
||||
"account_email_description": "Votre adresse e-mail principale.",
|
||||
"account_name_description": "Ceci est votre nom d'affichage.",
|
||||
@@ -592,8 +591,8 @@
|
||||
"black_mode": "Noir",
|
||||
"choose_language": "Choisissez la langue",
|
||||
"dark_mode": "Sombre",
|
||||
"delete_account": "Delete account",
|
||||
"delete_account_description": "Once you delete your account, all your data will be permanently deleted. This action cannot be undone.",
|
||||
"delete_account": "Supprimer le compte",
|
||||
"delete_account_description": "Lorsque vous supprimez votre compte, toutes vos données sont définitivement effacées. Cette action ne peut être annulée.",
|
||||
"expand_navigation": "Expand navigation",
|
||||
"experiments": "Expériences",
|
||||
"experiments_notice": "Il s'agit d'une collection d'expériences sur lesquelles nous travaillons et qui pourraient s'avérer utiles, amusantes, les deux ou aucune. Ils ne sont pas définitifs et peuvent ne pas être stables, donc si quelque chose de trop étrange se produit, ne paniquez pas. Il suffit d'éteindre le truc. Blague à part,",
|
||||
@@ -601,7 +600,7 @@
|
||||
"extension_version": "Version d'extension",
|
||||
"extensions": "Extensions",
|
||||
"extensions_use_toggle": "Utilisez l'extension de navigateur pour envoyer des requêtes (le cas échéant)",
|
||||
"follow": "Follow Us",
|
||||
"follow": "Suivez-nous",
|
||||
"interceptor": "Intercepteur",
|
||||
"interceptor_description": "Middleware entre l'application et les API.",
|
||||
"language": "Langue",
|
||||
@@ -631,7 +630,7 @@
|
||||
"theme_description": "Personnalisez le thème de votre application.",
|
||||
"use_experimental_url_bar": "Utiliser la barre d'URL expérimentale avec mise en évidence de l'environnement",
|
||||
"user": "Utilisateur",
|
||||
"verified_email": "Verified email",
|
||||
"verified_email": "E-mail vérifié",
|
||||
"verify_email": "Vérifier l'email"
|
||||
},
|
||||
"shared_requests": {
|
||||
@@ -684,20 +683,20 @@
|
||||
"title": "Navigation"
|
||||
},
|
||||
"others": {
|
||||
"prettify": "Prettify Editor's Content",
|
||||
"title": "Others"
|
||||
"prettify": "Améliorer le contenu de l'éditeur",
|
||||
"title": "Autres"
|
||||
},
|
||||
"request": {
|
||||
"delete_method": "Sélectionnez la méthode DELETE",
|
||||
"get_method": "Sélectionnez la méthode GET",
|
||||
"head_method": "Sélectionnez la méthode HEAD",
|
||||
"import_curl": "Import cURL",
|
||||
"import_curl": "Importer cURL",
|
||||
"method": "Méthode",
|
||||
"next_method": "Sélectionnez la méthode suivante",
|
||||
"post_method": "Sélectionnez la méthode POST",
|
||||
"previous_method": "Sélectionnez la méthode précédente",
|
||||
"put_method": "Sélectionnez la méthode PUT",
|
||||
"rename": "Rename Request",
|
||||
"rename": "Demande de renommage",
|
||||
"reset_request": "Réinitialiser la requête",
|
||||
"save_request": "Save Request",
|
||||
"save_to_collections": "Enregistrer dans les collections",
|
||||
@@ -728,89 +727,89 @@
|
||||
},
|
||||
"socketio": {
|
||||
"communication": "Communication",
|
||||
"connection_not_authorized": "This SocketIO connection does not use any authentication.",
|
||||
"connection_not_authorized": "Cette connexion SocketIO n'utilise pas d'authentification.",
|
||||
"event_name": "Nom de l'événement",
|
||||
"events": "Événements",
|
||||
"log": "Infos",
|
||||
"url": "URL"
|
||||
},
|
||||
"spotlight": {
|
||||
"change_language": "Change Language",
|
||||
"change_language": "Changer de langue",
|
||||
"environments": {
|
||||
"delete": "Delete current environment",
|
||||
"duplicate": "Duplicate current environment",
|
||||
"duplicate_global": "Duplicate global environment",
|
||||
"edit": "Edit current environment",
|
||||
"edit_global": "Edit global environment",
|
||||
"new": "Create new environment",
|
||||
"new_variable": "Create a new environment variable",
|
||||
"delete": "Supprimer l'environnement actuel",
|
||||
"duplicate": "Dupliquer l'environnement actuel",
|
||||
"duplicate_global": "Duplication de l'environnement global",
|
||||
"edit": "Modifier l'environnement actuel",
|
||||
"edit_global": "Modifier l'environnement mondial",
|
||||
"new": "Créer un nouvel environnement",
|
||||
"new_variable": "Créer une nouvelle variable d'environnement",
|
||||
"title": "Environments"
|
||||
},
|
||||
"general": {
|
||||
"chat": "Chat with support",
|
||||
"help_menu": "Help and support",
|
||||
"open_docs": "Read Documentation",
|
||||
"open_github": "Open GitHub repository",
|
||||
"open_keybindings": "Keyboard shortcuts",
|
||||
"chat": "Chat avec le support",
|
||||
"help_menu": "Aide et assistance",
|
||||
"open_docs": "Lire la documentation",
|
||||
"open_github": "Ouvrir le dépôt GitHub",
|
||||
"open_keybindings": "Raccourcis clavier",
|
||||
"social": "Social",
|
||||
"title": "General"
|
||||
"title": "Général"
|
||||
},
|
||||
"graphql": {
|
||||
"connect": "Connect to server",
|
||||
"disconnect": "Disconnect from server"
|
||||
"connect": "Connexion au serveur",
|
||||
"disconnect": "Déconnexion du serveur"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"invite": "Invite your friends to Hoppscotch",
|
||||
"title": "Miscellaneous"
|
||||
"invite": "Invitez vos amis à Hoppscotch",
|
||||
"title": "Divers"
|
||||
},
|
||||
"request": {
|
||||
"save_as_new": "Save as new request",
|
||||
"select_method": "Select method",
|
||||
"switch_to": "Switch to",
|
||||
"tab_authorization": "Authorization tab",
|
||||
"tab_body": "Body tab",
|
||||
"tab_headers": "Headers tab",
|
||||
"tab_parameters": "Parameters tab",
|
||||
"tab_pre_request_script": "Pre-request script tab",
|
||||
"tab_query": "Query tab",
|
||||
"tab_tests": "Tests tab",
|
||||
"tab_variables": "Variables tab"
|
||||
"save_as_new": "Sauvegarder comme nouvelle demande",
|
||||
"select_method": "Sélectionner la méthode",
|
||||
"switch_to": "Basculer vers",
|
||||
"tab_authorization": "Onglet Autorisation",
|
||||
"tab_body": "Onglet du corps",
|
||||
"tab_headers": "Onglet En-têtes",
|
||||
"tab_parameters": "Onglet Paramètres",
|
||||
"tab_pre_request_script": "Onglet script de pré-demande",
|
||||
"tab_query": "Onglet Requête",
|
||||
"tab_tests": "Onglet Tests",
|
||||
"tab_variables": "Onglet Variables"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Copy response",
|
||||
"download": "Download response as file",
|
||||
"title": "Response"
|
||||
"copy": "Copier la réponse",
|
||||
"download": "Télécharger la réponse sous forme de fichier",
|
||||
"title": "Réponse"
|
||||
},
|
||||
"section": {
|
||||
"interceptor": "Interceptor",
|
||||
"interceptor": "Intercepteur",
|
||||
"interface": "Interface",
|
||||
"theme": "Theme",
|
||||
"user": "User"
|
||||
"theme": "Thème",
|
||||
"user": "Utilisateur"
|
||||
},
|
||||
"settings": {
|
||||
"change_interceptor": "Change Interceptor",
|
||||
"change_language": "Change Language",
|
||||
"change_interceptor": "Changer d'intercepteur",
|
||||
"change_language": "Changer de langue",
|
||||
"theme": {
|
||||
"black": "Black",
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System preference"
|
||||
"black": "Noir",
|
||||
"dark": "Sombre",
|
||||
"light": "Clair",
|
||||
"system": "Préférence du système"
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"close_current": "Close current tab",
|
||||
"close_others": "Close all other tabs",
|
||||
"duplicate": "Duplicate current tab",
|
||||
"new_tab": "Open a new tab",
|
||||
"title": "Tabs"
|
||||
"close_current": "Fermer l'onglet actuel",
|
||||
"close_others": "Fermer tous les autres onglets",
|
||||
"duplicate": "Dupliquer l'onglet actuel",
|
||||
"new_tab": "Ouvrir un nouvel onglet",
|
||||
"title": "Onglets"
|
||||
},
|
||||
"workspace": {
|
||||
"delete": "Delete current team",
|
||||
"edit": "Edit current team",
|
||||
"invite": "Invite people to team",
|
||||
"new": "Create new team",
|
||||
"switch_to_personal": "Switch to your personal workspace",
|
||||
"title": "Teams"
|
||||
"delete": "Supprimer l'équipe actuelle",
|
||||
"edit": "Modifier l'équipe actuelle",
|
||||
"invite": "Inviter les gens à rejoindre l'équipe",
|
||||
"new": "Créer une nouvelle équipe",
|
||||
"switch_to_personal": "Passez à votre espace de travail personnel",
|
||||
"title": "Les équipes"
|
||||
}
|
||||
},
|
||||
"sse": {
|
||||
@@ -836,12 +835,12 @@
|
||||
"disconnected": "Déconnecté",
|
||||
"disconnected_from": "Déconnecté de {name}",
|
||||
"docs_generated": "Documentation générée",
|
||||
"download_failed": "Download failed",
|
||||
"download_started": "Téléchargement commencé",
|
||||
"download_failed": "Téléchargement échoué",
|
||||
"enabled": "Active",
|
||||
"file_imported": "Fichier importé",
|
||||
"finished_in": "Terminé en {duration} ms",
|
||||
"hide": "Hide",
|
||||
"hide": "Cacher",
|
||||
"history_deleted": "Historique supprimé",
|
||||
"linewrap": "Retour à la ligne",
|
||||
"loading": "Chargement...",
|
||||
@@ -852,7 +851,7 @@
|
||||
"published_error": "Quelque chose s'est mal passé lors de la publication du message : {topic} dans le sujet : {message}",
|
||||
"published_message": "Message publié : {message} au sujet : {topic}",
|
||||
"reconnection_error": "Échec de la reconnexion",
|
||||
"show": "Show",
|
||||
"show": "Afficher",
|
||||
"subscribed_failed": "Échec de l'inscription au sujet : {topic}",
|
||||
"subscribed_success": "Inscription réussie au sujet : {topic}",
|
||||
"unsubscribed_failed": "Échec de la désinscription du sujet : {topic}",
|
||||
@@ -861,7 +860,7 @@
|
||||
},
|
||||
"support": {
|
||||
"changelog": "En savoir plus sur les dernières versions",
|
||||
"chat": "Des questions? Discutez avec nous!",
|
||||
"chat": "Des questions ? Discutez avec nous!",
|
||||
"community": "Posez des questions et aidez les autres",
|
||||
"documentation": "En savoir plus sur Hoppscotch",
|
||||
"forum": "Posez des questions et obtenez des réponses",
|
||||
@@ -874,21 +873,21 @@
|
||||
"tab": {
|
||||
"authorization": "Autorisation",
|
||||
"body": "Corps",
|
||||
"close": "Close Tab",
|
||||
"close_others": "Close other Tabs",
|
||||
"close": "Fermer l'onglet",
|
||||
"close_others": "Fermer les autres onglets",
|
||||
"collections": "Collections",
|
||||
"documentation": "Documentation",
|
||||
"duplicate": "Duplicate Tab",
|
||||
"duplicate": "Dupliquer l'onglet",
|
||||
"environments": "Environments",
|
||||
"headers": "En-têtes",
|
||||
"history": "Histoire",
|
||||
"history": "Historique",
|
||||
"mqtt": "MQTT",
|
||||
"parameters": "Paramètres",
|
||||
"pre_request_script": "Script de pré-requête",
|
||||
"queries": "Requêtes",
|
||||
"query": "Requête",
|
||||
"schema": "Schema",
|
||||
"shared_requests": "Shared Requests",
|
||||
"shared_requests": "Requêtes partagées",
|
||||
"socketio": "Socket.IO",
|
||||
"sse": "ESS",
|
||||
"tests": "Tests",
|
||||
@@ -905,7 +904,6 @@
|
||||
"email_do_not_match": "L'email ne correspond pas aux détails de votre compte. Contactez le propriétaire de votre équipe.",
|
||||
"exit": "Quitter l'équipe",
|
||||
"exit_disabled": "Seul le propriétaire ne peut pas quitter l'équipe",
|
||||
"failed_invites": "Failed invites",
|
||||
"invalid_coll_id": "Invalid collection ID",
|
||||
"invalid_email_format": "Le format de l'e-mail n'est pas valide",
|
||||
"invalid_id": "L'email ne correspond pas aux détails de votre compte. Contactez le propriétaire de votre équipe.",
|
||||
@@ -941,21 +939,22 @@
|
||||
"no_request_found": "Request not found.",
|
||||
"not_found": "Équipe non trouvée. Contactez le propriétaire de votre équipe.",
|
||||
"not_valid_viewer": "Vous n'êtes pas un visionneur valide. Contactez le propriétaire de votre équipe.",
|
||||
"parent_coll_move": "Cannot move collection to a child collection",
|
||||
"parent_coll_move": "Impossible de déplacer une collection vers une collection enfant",
|
||||
"success_invites": "Les invitations réussites",
|
||||
"pending_invites": "Invitations en attente",
|
||||
"failed_invites": "Échec des invitations",
|
||||
"permissions": "Autorisations",
|
||||
"same_target_destination": "Same target and destination",
|
||||
"same_target_destination": "Même destinataire et même cible",
|
||||
"saved": "Équipe enregistrée",
|
||||
"select_a_team": "Choisir une équipe",
|
||||
"success_invites": "Success invites",
|
||||
"title": "Équipes",
|
||||
"we_sent_invite_link": "Nous avons envoyé un lien d'invitation à tous les invités !",
|
||||
"we_sent_invite_link_description": "Demandez à tous les invités de vérifier leur boîte de réception. Cliquez sur le lien pour rejoindre l'équipe."
|
||||
},
|
||||
"team_environment": {
|
||||
"deleted": "Environment Deleted",
|
||||
"duplicate": "Environment Duplicated",
|
||||
"not_found": "Environment not found."
|
||||
"deleted": "Environment supprimé",
|
||||
"duplicate": "Environment dupliqué",
|
||||
"not_found": "Environment non trouvé"
|
||||
},
|
||||
"test": {
|
||||
"failed": "Test échoué",
|
||||
@@ -975,10 +974,10 @@
|
||||
"url": "URL"
|
||||
},
|
||||
"workspace": {
|
||||
"change": "Change workspace",
|
||||
"personal": "My Workspace",
|
||||
"team": "Team Workspace",
|
||||
"title": "Workspaces"
|
||||
"change": "Changer d'espace de travail",
|
||||
"personal": "Mon espace de travail",
|
||||
"team": "Espace de travail de l'équipe",
|
||||
"title": "Espaces de travail"
|
||||
},
|
||||
"shortcodes": {
|
||||
"actions": "Actions",
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"action": {
|
||||
"add": "Add",
|
||||
"add": "Hozzáadás",
|
||||
"autoscroll": "Automatikus görgetés",
|
||||
"cancel": "Mégse",
|
||||
"choose_file": "Válasszon egy fájlt",
|
||||
"clear": "Törlés",
|
||||
"clear_all": "Összes törlése",
|
||||
"clear_history": "Clear all History",
|
||||
"clear_history": "Összes előzmény törlése",
|
||||
"close": "Bezárás",
|
||||
"connect": "Kapcsolódás",
|
||||
"connecting": "Kapcsolódás",
|
||||
"copy": "Másolás",
|
||||
"create": "Create",
|
||||
"create": "Létrehozás",
|
||||
"delete": "Törlés",
|
||||
"disconnect": "Leválasztás",
|
||||
"dismiss": "Eltüntetés",
|
||||
@@ -33,16 +33,16 @@
|
||||
"open_workspace": "Munkaterület megnyitása",
|
||||
"paste": "Beillesztés",
|
||||
"prettify": "Csinosítás",
|
||||
"properties": "Properties",
|
||||
"properties": "Tulajdonságok",
|
||||
"remove": "Eltávolítás",
|
||||
"rename": "Rename",
|
||||
"rename": "Átnevezés",
|
||||
"restore": "Visszaállítás",
|
||||
"save": "Mentés",
|
||||
"scroll_to_bottom": "Görgetés az aljára",
|
||||
"scroll_to_top": "Görgetés a tetejére",
|
||||
"search": "Keresés",
|
||||
"send": "Küldés",
|
||||
"share": "Share",
|
||||
"share": "Megosztás",
|
||||
"start": "Indítás",
|
||||
"starting": "Indítás",
|
||||
"stop": "Leállítás",
|
||||
@@ -61,9 +61,9 @@
|
||||
"app": {
|
||||
"chat_with_us": "Csevegjen velünk",
|
||||
"contact_us": "Lépjen kapcsolatba velünk",
|
||||
"cookies": "Cookies",
|
||||
"cookies": "Sütik",
|
||||
"copy": "Másolás",
|
||||
"copy_interface_type": "Copy interface type",
|
||||
"copy_interface_type": "Interface típusának másolása",
|
||||
"copy_user_id": "Felhasználó-hitelesítési token másolása",
|
||||
"developer_option": "Fejlesztői beállítások",
|
||||
"developer_option_description": "Fejlesztői eszközök, amelyek segítenek a Hoppscotch fejlesztésében és karbantartásában.",
|
||||
@@ -79,15 +79,15 @@
|
||||
"keyboard_shortcuts": "Gyorsbillentyűk",
|
||||
"name": "Hoppscotch",
|
||||
"new_version_found": "Új verzió található. Töltse újra az oldalt a frissítéshez.",
|
||||
"open_in_hoppscotch": "Open in Hoppscotch",
|
||||
"open_in_hoppscotch": "Megnyitás Hoppscotch-ban.",
|
||||
"options": "Beállítások",
|
||||
"proxy_privacy_policy": "Proxy adatvédelmi irányelvei",
|
||||
"reload": "Újratöltés",
|
||||
"search": "Keresés",
|
||||
"share": "Megosztás",
|
||||
"shortcuts": "Gyorsbillentyűk",
|
||||
"social_description": "Follow us on social media to stay updated with the latest news, updates and releases.",
|
||||
"social_links": "Social links",
|
||||
"social_description": "Kövess minket a közösségi médiában, hogy ne maradj le a hírekről, frissítésekről és új kiadásokról.",
|
||||
"social_links": "Közösségi média linkek",
|
||||
"spotlight": "Reflektorfény",
|
||||
"status": "Állapot",
|
||||
"status_description": "A weboldal állapotának ellenőrzése",
|
||||
@@ -119,27 +119,27 @@
|
||||
},
|
||||
"authorization": {
|
||||
"generate_token": "Token előállítása",
|
||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||
"graphql_headers": "Azonosító fejléc connection_init tartalmaként elküldve",
|
||||
"include_in_url": "Felvétel az URL-be",
|
||||
"inherited_from": "Inherited from {auth} from Parent Collection {collection} ",
|
||||
"inherited_from": "Örökölt a(z) {auth}-tól, a(z) {collection} gyűjteményből ",
|
||||
"learn": "Tudja meg, hogyan",
|
||||
"oauth": {
|
||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||
"redirect_auth_token_request_failed": "Request to get the auth token failed",
|
||||
"redirect_auth_token_request_invalid_response": "Invalid Response from the Token Endpoint when requesting for an auth token",
|
||||
"redirect_invalid_state": "Invalid State value present in the redirect",
|
||||
"redirect_no_auth_code": "No Authorization Code present in the redirect",
|
||||
"redirect_no_client_id": "No Client ID defined",
|
||||
"redirect_no_client_secret": "No Client Secret Defined",
|
||||
"redirect_no_code_verifier": "No Code Verifier Defined",
|
||||
"redirect_no_token_endpoint": "No Token Endpoint Defined",
|
||||
"something_went_wrong_on_oauth_redirect": "Something went wrong during OAuth Redirect",
|
||||
"something_went_wrong_on_token_generation": "Something went wrong on token generation",
|
||||
"token_generation_oidc_discovery_failed": "Failure on token generation: OpenID Connect Discovery Failed"
|
||||
"redirect_auth_server_returned_error": "Az Auth szerver hibás állapottal tért vissza",
|
||||
"redirect_auth_token_request_failed": "Kérés az auth token lekéréséhez sikertelen",
|
||||
"redirect_auth_token_request_invalid_response": "Érvénytelen válasz a Token Endpoint-tól, az auth token lekérésekpr",
|
||||
"redirect_invalid_state": "Érvénytelen állapotérték az átirányításban",
|
||||
"redirect_no_auth_code": "Nincs azonosítás az átirányításban",
|
||||
"redirect_no_client_id": "Nincs felhasználó azonosító",
|
||||
"redirect_no_client_secret": "Nincs felhasználó jelszó",
|
||||
"redirect_no_code_verifier": "Nincs kódellenőrző",
|
||||
"redirect_no_token_endpoint": "Nincs \"Token Endpoint\"",
|
||||
"something_went_wrong_on_oauth_redirect": "Valami rosszul sikerült az OAuth átirányításakor",
|
||||
"something_went_wrong_on_token_generation": "Valami rosszul sikerült a token generálásakor",
|
||||
"token_generation_oidc_discovery_failed": "Hiba a token generálásakor: OpenID Connect Discovery hiba"
|
||||
},
|
||||
"pass_key_by": "Átadta",
|
||||
"password": "Jelszó",
|
||||
"save_to_inherit": "Please save this request in any collection to inherit the authorization",
|
||||
"save_to_inherit": "Kérjük, mentse el ezt kérést bármelyik gyűjteménybe, hogy az azonosítás örökölhető lehessen",
|
||||
"token": "Token",
|
||||
"type": "Felhatalmazás típusa",
|
||||
"username": "Felhasználónév"
|
||||
@@ -148,7 +148,7 @@
|
||||
"created": "Gyűjtemény létrehozva",
|
||||
"different_parent": "Nem lehet átrendezni a különböző szülővel rendelkező gyűjteményt",
|
||||
"edit": "Gyűjtemény szerkesztése",
|
||||
"import_or_create": "Import or create a collection",
|
||||
"import_or_create": "Gyűjtemény importálása vagy létrehozása",
|
||||
"invalid_name": "Adjon nevet a gyűjteménynek",
|
||||
"invalid_root_move": "A gyűjtemény már a gyökérben van",
|
||||
"moved": "Sikeresen áthelyezve",
|
||||
@@ -157,20 +157,20 @@
|
||||
"name_length_insufficient": "A gyűjtemény nevének legalább 3 karakter hosszúságúnak kell lennie",
|
||||
"new": "Új gyűjtemény",
|
||||
"order_changed": "Gyűjtemény sorrendje frissítve",
|
||||
"properties": "Collection Properties",
|
||||
"properties_updated": "Collection Properties Updated",
|
||||
"properties": "Gyűjtemény tulajdonságok",
|
||||
"properties_updated": "Gyűjtemény tulajdonságai frissítve",
|
||||
"renamed": "Gyűjtemény átnevezve",
|
||||
"request_in_use": "A kérés használatban",
|
||||
"save_as": "Mentés másként",
|
||||
"save_to_collection": "Save to Collection",
|
||||
"save_to_collection": "Mentés egy gyűjteménybe",
|
||||
"select": "Gyűjtemény kiválasztása",
|
||||
"select_location": "Hely kiválasztása",
|
||||
"select_team": "Csapat kiválasztása",
|
||||
"team_collections": "Csapat gyűjteményei"
|
||||
},
|
||||
"confirm": {
|
||||
"close_unsaved_tab": "Are you sure you want to close this tab?",
|
||||
"close_unsaved_tabs": "Are you sure you want to close all tabs? {count} unsaved tabs will be lost.",
|
||||
"close_unsaved_tab": "Biztos, hogy bezárja ezt a lapot?",
|
||||
"close_unsaved_tabs": "Biztos, hogy bezárja az összes lapot? {count} elmentetlen lap el fog veszni.",
|
||||
"exit_team": "Biztosan el szeretné hagyni ezt a csapatot?",
|
||||
"logout": "Biztosan ki szeretne jelentkezni?",
|
||||
"remove_collection": "Biztosan véglegesen törölni szeretné ezt a gyűjteményt?",
|
||||
@@ -178,7 +178,7 @@
|
||||
"remove_folder": "Biztosan véglegesen törölni szeretné ezt a mappát?",
|
||||
"remove_history": "Biztosan véglegesen törölni szeretné az összes előzményt?",
|
||||
"remove_request": "Biztosan véglegesen törölni szeretné ezt a kérést?",
|
||||
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
||||
"remove_shared_request": "Biztos, hogy véglegesen törölni szeretné ezt a megosztott kérést?",
|
||||
"remove_team": "Biztosan törölni szeretné ezt a csapatot?",
|
||||
"remove_telemetry": "Biztosan ki szeretné kapcsolni a telemetriát?",
|
||||
"request_change": "Biztosan el szeretné vetni a jelenlegi kérést? Minden mentetlen változtatás el fog veszni.",
|
||||
@@ -186,26 +186,26 @@
|
||||
"sync": "Szeretné visszaállítani a munkaterületét a felhőből? Ez el fogja vetni a helyi folyamatát."
|
||||
},
|
||||
"context_menu": {
|
||||
"add_parameters": "Add to parameters",
|
||||
"open_request_in_new_tab": "Open request in new tab",
|
||||
"set_environment_variable": "Set as variable"
|
||||
"add_parameters": "Paraméterek hozzáadása",
|
||||
"open_request_in_new_tab": "Kérés megnyitása új lapot",
|
||||
"set_environment_variable": "Változóként való beállítás"
|
||||
},
|
||||
"cookies": {
|
||||
"modal": {
|
||||
"cookie_expires": "Expires",
|
||||
"cookie_name": "Name",
|
||||
"cookie_path": "Path",
|
||||
"cookie_string": "Cookie string",
|
||||
"cookie_value": "Value",
|
||||
"empty_domain": "Domain is empty",
|
||||
"empty_domains": "Domain list is empty",
|
||||
"enter_cookie_string": "Enter cookie string",
|
||||
"interceptor_no_support": "Your currently selected interceptor does not support cookies. Select a different Interceptor and try again.",
|
||||
"managed_tab": "Managed",
|
||||
"new_domain_name": "New domain name",
|
||||
"no_cookies_in_domain": "No cookies set for this domain",
|
||||
"raw_tab": "Raw",
|
||||
"set": "Set a cookie"
|
||||
"cookie_expires": "Lejárat",
|
||||
"cookie_name": "Név",
|
||||
"cookie_path": "Útvonal",
|
||||
"cookie_string": "Süti szöveg",
|
||||
"cookie_value": "Érték",
|
||||
"empty_domain": "Üres domain",
|
||||
"empty_domains": "Domain lista üres",
|
||||
"enter_cookie_string": "Süti szövegének megadása",
|
||||
"interceptor_no_support": "A kiválasztott interceptor nem támogatja a sütiket. Válasszon ki egy másik interceptor-t és próbálja újra.",
|
||||
"managed_tab": "Menedzselt",
|
||||
"new_domain_name": "Új domain neve",
|
||||
"no_cookies_in_domain": "Nincs süti beállítva ehhez a domainhez.",
|
||||
"raw_tab": "Nyers",
|
||||
"set": "Süti beállítása"
|
||||
}
|
||||
},
|
||||
"count": {
|
||||
@@ -221,7 +221,7 @@
|
||||
"generate_message": "Importáljon bármilyen Hoppscotch-gyűjteményt, hogy API-dokumentációt készítsen a folyamat során."
|
||||
},
|
||||
"empty": {
|
||||
"authorization": "Ez a kérés nem használ felhatalmazást",
|
||||
"authorization": "Ez a kérés nem használ azonosítást",
|
||||
"body": "Ennek a kérésnek nincs törzse",
|
||||
"collection": "A gyűjtemény üres",
|
||||
"collections": "A gyűjtemények üresek",
|
||||
@@ -252,39 +252,39 @@
|
||||
"create_new": "Új környezet létrehozása",
|
||||
"created": "Környezet létrehozva",
|
||||
"deleted": "Környezet törlése",
|
||||
"duplicated": "Environment duplicated",
|
||||
"duplicated": "Környezet duplikálása",
|
||||
"edit": "Környezet szerkesztése",
|
||||
"empty_variables": "No variables",
|
||||
"global": "Global",
|
||||
"global_variables": "Global variables",
|
||||
"import_or_create": "Import or create a environment",
|
||||
"empty_variables": "Nincs változó",
|
||||
"global": "Globális",
|
||||
"global_variables": "Globális változók",
|
||||
"import_or_create": "Környezet importálása vagy létrehozása",
|
||||
"invalid_name": "Adjon nevet a környezetnek",
|
||||
"list": "Environment variables",
|
||||
"list": "Környezeti változók",
|
||||
"my_environments": "Saját környezetek",
|
||||
"name": "Name",
|
||||
"name": "Név",
|
||||
"nested_overflow": "az egymásba ágyazott környezeti változók 10 szintre vannak korlátozva",
|
||||
"new": "Új környezet",
|
||||
"no_active_environment": "No active environment",
|
||||
"no_active_environment": "Nincs aktív környezet",
|
||||
"no_environment": "Nincs környezet",
|
||||
"no_environment_description": "Nem lettek környezetek kiválasztva. Válassza ki, hogy mit kell tenni a következő változókkal.",
|
||||
"quick_peek": "Environment Quick Peek",
|
||||
"replace_with_variable": "Replace with variable",
|
||||
"scope": "Scope",
|
||||
"quick_peek": "Környezet gyors megnézése",
|
||||
"replace_with_variable": "Cserélje le egy változóra",
|
||||
"scope": "Hatókör",
|
||||
"select": "Környezet kiválasztása",
|
||||
"set": "Set environment",
|
||||
"set_as_environment": "Set as environment",
|
||||
"set": "Környezet beállítása",
|
||||
"set_as_environment": "Környezetként való beállítás",
|
||||
"team_environments": "Csapatkörnyezetek",
|
||||
"title": "Környezetek",
|
||||
"updated": "Környezet frissítve",
|
||||
"value": "Value",
|
||||
"variable": "Variable",
|
||||
"value": "Érték",
|
||||
"variable": "Változó",
|
||||
"variable_list": "Változólista"
|
||||
},
|
||||
"error": {
|
||||
"authproviders_load_error": "Unable to load auth providers",
|
||||
"authproviders_load_error": "Nem sikerült betölteni az azonosító szolgáltatókat",
|
||||
"browser_support_sse": "Úgy tűnik, hogy ez a böngésző nem támogatja a kiszolgáló által küldött eseményeket.",
|
||||
"check_console_details": "Nézze meg a konzolnaplót a részletekért.",
|
||||
"check_how_to_add_origin": "Check how you can add an origin",
|
||||
"check_how_to_add_origin": "Ellenőrizze, hogy hogyan adhat hozzá forrást",
|
||||
"curl_invalid_format": "A cURL nincs megfelelően formázva",
|
||||
"danger_zone": "Veszélyes zóna",
|
||||
"delete_account": "Az Ön fiókja jelenleg tulajdonos ezekben a csapatokban:",
|
||||
@@ -300,13 +300,13 @@
|
||||
"json_prettify_invalid_body": "Nem sikerült csinosítani egy érvénytelen törzset, oldja meg a JSON szintaktikai hibáit, és próbálja újra",
|
||||
"network_error": "Úgy tűnik, hogy hálózati hiba van. Próbálja újra.",
|
||||
"network_fail": "Nem sikerült elküldeni a kérést",
|
||||
"no_collections_to_export": "No collections to export. Please create a collection to get started.",
|
||||
"no_collections_to_export": "Nincs exportálható gyűjtemény. Kérjük, hozzon létre egyet, hogy elkezdhesse.",
|
||||
"no_duration": "Nincs időtartam",
|
||||
"no_environments_to_export": "No environments to export. Please create an environment to get started.",
|
||||
"no_environments_to_export": "Nincs exportálható környezet. Kérjük, hozzon létre egyet, hogy elkezdhesse.",
|
||||
"no_results_found": "Nincs találat",
|
||||
"page_not_found": "Ez az oldal nem található",
|
||||
"please_install_extension": "Please install the extension and add origin to the extension.",
|
||||
"proxy_error": "Proxy error",
|
||||
"please_install_extension": "Kérjük telepítse a bővítményt és adja hozzá a forráshoz.",
|
||||
"proxy_error": "Proxy hiba",
|
||||
"script_fail": "Nem sikerült végrehajtani a kérés előtti parancsfájlt",
|
||||
"something_went_wrong": "Valami elromlott",
|
||||
"test_script_fail": "Nem sikerült végrehajtani a kérés utáni parancsfájlt"
|
||||
@@ -314,7 +314,7 @@
|
||||
"export": {
|
||||
"as_json": "Exportálás JSON formátumban",
|
||||
"create_secret_gist": "Titkos Gist létrehozása",
|
||||
"failed": "Something went wrong while exporting",
|
||||
"failed": "Valami hiba történt az exportálás közben",
|
||||
"gist_created": "Gist létrehozva",
|
||||
"require_github": "Jelentkezzen be GitHub használatával a titkos Gist létrehozásához",
|
||||
"title": "Exportálás"
|
||||
@@ -333,16 +333,16 @@
|
||||
"renamed": "Mappa átnevezve"
|
||||
},
|
||||
"graphql": {
|
||||
"connection_switch_confirm": "Do you want to connect with the latest GraphQL endpoint?",
|
||||
"connection_switch_new_url": "Switching to a tab will disconnected you from the active GraphQL connection. New connection URL is",
|
||||
"connection_switch_url": "You're connected to a GraphQL endpoint the connection URL is",
|
||||
"connection_switch_confirm": "Szeretne csatlakozni a legújabb GraphQL végponttal?",
|
||||
"connection_switch_new_url": "A tab váltása lecsatlakoztatta az aktív GraphQL kapcsolatról. Az új kapcsolat",
|
||||
"connection_switch_url": "Kapcsolódott a GraphQL végponthoz. A kapcsolat",
|
||||
"mutations": "Mutációk",
|
||||
"schema": "Séma",
|
||||
"subscriptions": "Feliratkozások",
|
||||
"switch_connection": "Switch connection"
|
||||
"switch_connection": "Kapcsolat váltása"
|
||||
},
|
||||
"graphql_collections": {
|
||||
"title": "GraphQL Collections"
|
||||
"title": "GraphQL gyűjtemény"
|
||||
},
|
||||
"group": {
|
||||
"time": "Idő",
|
||||
@@ -354,9 +354,9 @@
|
||||
"save_workspace": "Saját munkaterület mentése"
|
||||
},
|
||||
"helpers": {
|
||||
"authorization": "A felhatalmazási fejléc automatikusan elő lesz állítva a kérés elküldésekor.",
|
||||
"collection_properties_authorization": " This authorization will be set for every request in this collection.",
|
||||
"collection_properties_header": "This header will be set for every request in this collection.",
|
||||
"authorization": "Az Azonosítás fejléc automatikusan elő lesz állítva a kérés elküldésekor.",
|
||||
"collection_properties_authorization": " Ez az azonosítás be lesz állítva minden kéréshez ebben a gyűjteményben.",
|
||||
"collection_properties_header": "Ez a fejléc be lesz állítva mint minden kéréshez ebben a gyűjteményben.",
|
||||
"generate_documentation_first": "Először állítsa elő a dokumentációt",
|
||||
"network_fail": "Nem lehet elérni az API-végpontot. Ellenőrizze a hálózati kapcsolatot vagy válasszon egy másik elfogót, és próbálja újra.",
|
||||
"offline": "Úgy tűnik, hogy kapcsolat nélküli módban van. Előfordulhat, hogy a munkaterületen lévő adatok nem naprakészek.",
|
||||
@@ -376,11 +376,11 @@
|
||||
"import": {
|
||||
"collections": "Gyűjtemények importálása",
|
||||
"curl": "cURL importálása",
|
||||
"environments_from_gist": "Import From Gist",
|
||||
"environments_from_gist_description": "Import Hoppscotch Environments From Gist",
|
||||
"environments_from_gist": "Importálás Gist-ből",
|
||||
"environments_from_gist_description": "Hoppscotch környezetek importálása Gist-ből",
|
||||
"failed": "Hiba az importálás során: a formátum nem azonosítható",
|
||||
"from_file": "Import from File",
|
||||
"from_gist": "Importálás Gistből",
|
||||
"from_file": "Importálás fájlból",
|
||||
"from_gist": "Importálás Gist-ből",
|
||||
"from_gist_description": "Importálás Gist URL-ből",
|
||||
"from_insomnia": "Importálás Insomniából",
|
||||
"from_insomnia_description": "Importálás Insomnia-gyűjteményből",
|
||||
@@ -390,45 +390,45 @@
|
||||
"from_my_collections_description": "Importálás saját gyűjtemények fájlból",
|
||||
"from_openapi": "Importálás OpenAPI-ból",
|
||||
"from_openapi_description": "Importálás OpenAPI specifikációs fájlból (YML/JSON)",
|
||||
"from_postman": "Importálás Postmanből",
|
||||
"from_postman": "Importálás Postman-ből",
|
||||
"from_postman_description": "Importálás Postman-gyűjteményből",
|
||||
"from_url": "Importálás URL-ből",
|
||||
"gist_url": "Gist URL megadása",
|
||||
"gql_collections_from_gist_description": "Import GraphQL Collections From Gist",
|
||||
"hoppscotch_environment": "Hoppscotch Environment",
|
||||
"hoppscotch_environment_description": "Import Hoppscotch Environment JSON file",
|
||||
"gql_collections_from_gist_description": "GraphQL gyűjtemények importálása Gist-ből",
|
||||
"hoppscotch_environment": "Hoppscotch környezet",
|
||||
"hoppscotch_environment_description": "Hoppscotch környezet importálása JSON fájlból",
|
||||
"import_from_url_invalid_fetch": "Nem sikerült lekérni az adatokat az URL-ről",
|
||||
"import_from_url_invalid_file_format": "Hiba a gyűjtemények importálása során",
|
||||
"import_from_url_invalid_type": "Nem támogatott típus. Az elfogadott értékek: „hoppscotch”, „openapi”, „postman” vagy „insomnia”.",
|
||||
"import_from_url_success": "Gyűjtemények importálva",
|
||||
"insomnia_environment_description": "Import Insomnia Environment from a JSON/YAML file",
|
||||
"insomnia_environment_description": "Insomnia környezet importálása JSON/YAML fájlból",
|
||||
"json_description": "Gyűjtemények importálása Hoppscotch-gyűjtemények JSON-fájlból",
|
||||
"postman_environment": "Postman Environment",
|
||||
"postman_environment_description": "Import Postman Environment from a JSON file",
|
||||
"postman_environment": "Postman környezet",
|
||||
"postman_environment_description": "Postman környezet importálása JSON fájlból",
|
||||
"title": "Importálás"
|
||||
},
|
||||
"inspections": {
|
||||
"description": "Inspect possible errors",
|
||||
"description": "Lehetséges hibák ellenőrzése",
|
||||
"environment": {
|
||||
"add_environment": "Add to Environment",
|
||||
"not_found": "Environment variable “{environment}” not found."
|
||||
"add_environment": "Hozzáadás a környezethez",
|
||||
"not_found": "\"{environment}\" környezet nem található."
|
||||
},
|
||||
"header": {
|
||||
"cookie": "The browser doesn't allow Hoppscotch to set the Cookie Header. While we're working on the Hoppscotch Desktop App (coming soon), please use the Authorization Header instead."
|
||||
"cookie": "A böngésző nem engedélyezi a Hoppscotch-nak, hogy süti fejlécet állítson be. Amíg dolgozunk a Hoppscotch asztali alkalmazáson (hamarosan), kérjük használjon Authorization Header fejlécet."
|
||||
},
|
||||
"response": {
|
||||
"401_error": "Please check your authentication credentials.",
|
||||
"404_error": "Please check your request URL and method type.",
|
||||
"cors_error": "Please check your Cross-Origin Resource Sharing configuration.",
|
||||
"default_error": "Please check your request.",
|
||||
"network_error": "Please check your network connection."
|
||||
"401_error": "Kérjük ellenőrizze az autentikációs adatokat.",
|
||||
"404_error": "Kérjük ellenőrizze a kérés URL-jét és típusát.",
|
||||
"cors_error": "Kérjük ellenőrizze a Cross-Origin Resource Sharing beállítást.",
|
||||
"default_error": "Kérjük ellenőrizze a kérését.",
|
||||
"network_error": "Kérjük ellenőrizze a internet elérhetőségét."
|
||||
},
|
||||
"title": "Inspector",
|
||||
"url": {
|
||||
"extension_not_installed": "Extension not installed.",
|
||||
"extension_unknown_origin": "Make sure you've added the API endpoint's origin to the Hoppscotch Browser Extension list.",
|
||||
"extention_enable_action": "Enable Browser Extension",
|
||||
"extention_not_enabled": "Extension not enabled."
|
||||
"extension_not_installed": "Bővítmény nincs telepítve.",
|
||||
"extension_unknown_origin": "Ellenőrizze, hogy hozzáadta az API végpont forrását Hoppscotch Browser bővítmény listájához.",
|
||||
"extention_enable_action": "Bővítmény engedélyezése",
|
||||
"extention_not_enabled": "Bővítmény nincs engedélyezve."
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
@@ -442,10 +442,10 @@
|
||||
"close_unsaved_tab": "Elmentetlen változtatásai vannak",
|
||||
"collections": "Gyűjtemények",
|
||||
"confirm": "Megerősítés",
|
||||
"customize_request": "Customize Request",
|
||||
"customize_request": "Kérés testreszabása",
|
||||
"edit_request": "Kérés szerkesztése",
|
||||
"import_export": "Importálás és exportálás",
|
||||
"share_request": "Share Request"
|
||||
"share_request": "Kérés megosztása"
|
||||
},
|
||||
"mqtt": {
|
||||
"already_subscribed": "Ön már feliratkozott erre a témára.",
|
||||
@@ -511,7 +511,7 @@
|
||||
},
|
||||
"request": {
|
||||
"added": "Kérés hozzáadva",
|
||||
"authorization": "Felhatalmazás",
|
||||
"authorization": "Azonosítás",
|
||||
"body": "Kérés törzse",
|
||||
"choose_language": "Nyelv kiválasztása",
|
||||
"content_type": "Tartalom típusa",
|
||||
@@ -526,8 +526,8 @@
|
||||
"enter_curl": "cURL-parancs megadása",
|
||||
"generate_code": "Kód előállítása",
|
||||
"generated_code": "Előállított kód",
|
||||
"go_to_authorization_tab": "Go to Authorization tab",
|
||||
"go_to_body_tab": "Go to Body tab",
|
||||
"go_to_authorization_tab": "Navigálás az Azonosítás lapra",
|
||||
"go_to_body_tab": "Navigálás a Törzs lapra.",
|
||||
"header_list": "Fejléclista",
|
||||
"invalid_name": "Adjon nevet a kérésnek",
|
||||
"method": "Módszer",
|
||||
@@ -552,8 +552,8 @@
|
||||
"saved": "Kérés elmentve",
|
||||
"share": "Megosztás",
|
||||
"share_description": "A Hoppscotch megosztása az ismerőseivel",
|
||||
"share_request": "Share Request",
|
||||
"stop": "Stop",
|
||||
"share_request": "Kérés megosztása",
|
||||
"stop": "Leállítás",
|
||||
"title": "Kérés",
|
||||
"type": "Kérés típusa",
|
||||
"url": "URL",
|
||||
@@ -587,7 +587,7 @@
|
||||
"account_description": "A fiókbeállítások személyre szabása.",
|
||||
"account_email_description": "Az Ön elsődleges e-mail-címe.",
|
||||
"account_name_description": "Ez a megjelenített neve.",
|
||||
"additional": "Additional Settings",
|
||||
"additional": "További beállítások",
|
||||
"background": "Háttér",
|
||||
"black_mode": "Fekete",
|
||||
"choose_language": "Nyelv kiválasztása",
|
||||
@@ -635,29 +635,29 @@
|
||||
"verify_email": "E-mail-cím ellenőrzése"
|
||||
},
|
||||
"shared_requests": {
|
||||
"button": "Button",
|
||||
"button_info": "Create a 'Run in Hoppscotch' button for your website, blog or a README.",
|
||||
"copy_html": "Copy HTML",
|
||||
"copy_link": "Copy Link",
|
||||
"copy_markdown": "Copy Markdown",
|
||||
"creating_widget": "Creating widget",
|
||||
"customize": "Customize",
|
||||
"deleted": "Shared request deleted",
|
||||
"description": "Select a widget, you can change and customize this later",
|
||||
"embed": "Embed",
|
||||
"embed_info": "Add a mini 'Hoppscotch API Playground' to your website, blog or documentation.",
|
||||
"button": "Gomb",
|
||||
"button_info": "Hozza létre a 'Futtatás Hoppscotch-ban' gombot a weboldalán vagy blogján.",
|
||||
"copy_html": "HTML másolása",
|
||||
"copy_link": "Link másolása",
|
||||
"copy_markdown": "Jelölő másolása",
|
||||
"creating_widget": "Widget létrehozása",
|
||||
"customize": "Testreszabás",
|
||||
"deleted": "Megosztott kérés törölve",
|
||||
"description": "Válasszon ki egy widgetet, ezt később módosíthatja és testreszabhatja",
|
||||
"embed": "Beágyazás",
|
||||
"embed_info": "Adja hozzá a \"Hoppscotch API Playground\"-ot weboldalához vagy blogjához.",
|
||||
"link": "Link",
|
||||
"link_info": "Create a shareable link to share with anyone on the internet with view access.",
|
||||
"modified": "Shared request modified",
|
||||
"not_found": "Shared request not found",
|
||||
"open_new_tab": "Open in new tab",
|
||||
"preview": "Preview",
|
||||
"run_in_hoppscotch": "Run in Hoppscotch",
|
||||
"link_info": "Link létrehozása olvasási joggal való megosztáshoz.",
|
||||
"modified": "Megosztott kérés módosítva",
|
||||
"not_found": "Megosztott kérés nem található.",
|
||||
"open_new_tab": "Megnyitás új lapon.",
|
||||
"preview": "Előnézet",
|
||||
"run_in_hoppscotch": "Futtatás Hoppscotch-ban.",
|
||||
"theme": {
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System",
|
||||
"title": "Theme"
|
||||
"dark": "Sötét",
|
||||
"light": "Világos",
|
||||
"system": "Rendszer",
|
||||
"title": "Téma"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
@@ -669,7 +669,7 @@
|
||||
"title": "Általános"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"invite": "Emberek meghívása a Hoppscotchba",
|
||||
"invite": "Emberek meghívása a Hoppscotch-ba",
|
||||
"title": "Egyebek"
|
||||
},
|
||||
"navigation": {
|
||||
@@ -691,19 +691,19 @@
|
||||
"delete_method": "DELETE módszer kiválasztása",
|
||||
"get_method": "GET módszer kiválasztása",
|
||||
"head_method": "HEAD módszer kiválasztása",
|
||||
"import_curl": "Import cURL",
|
||||
"import_curl": "cURL importálása",
|
||||
"method": "Módszer",
|
||||
"next_method": "Következő módszer kiválasztása",
|
||||
"post_method": "POST módszer kiválasztása",
|
||||
"previous_method": "Előző módszer kiválasztása",
|
||||
"put_method": "PUT módszer kiválasztása",
|
||||
"rename": "Rename Request",
|
||||
"rename": "Kérés átnevezése",
|
||||
"reset_request": "Kérés visszaállítása",
|
||||
"save_request": "Save Request",
|
||||
"save_request": "Kérés mentése",
|
||||
"save_to_collections": "Mentés a gyűjteményekbe",
|
||||
"send_request": "Kérés elküldése",
|
||||
"share_request": "Share Request",
|
||||
"show_code": "Generate code snippet",
|
||||
"share_request": "Kérés megosztása",
|
||||
"show_code": "Kódrészlet generálása",
|
||||
"title": "Kérés",
|
||||
"copy_request_link": "Kérés hivatkozásának másolása"
|
||||
},
|
||||
@@ -735,82 +735,82 @@
|
||||
"url": "URL"
|
||||
},
|
||||
"spotlight": {
|
||||
"change_language": "Change Language",
|
||||
"change_language": "Nyelv váltása",
|
||||
"environments": {
|
||||
"delete": "Delete current environment",
|
||||
"duplicate": "Duplicate current environment",
|
||||
"duplicate_global": "Duplicate global environment",
|
||||
"edit": "Edit current environment",
|
||||
"edit_global": "Edit global environment",
|
||||
"new": "Create new environment",
|
||||
"new_variable": "Create a new environment variable",
|
||||
"title": "Environments"
|
||||
"delete": "Jelenlegi környezet törlése",
|
||||
"duplicate": "Jelenlegi környezet duplikálása",
|
||||
"duplicate_global": "Globális környezet duplikálása",
|
||||
"edit": "Jelenlegi környezet szerkesztése",
|
||||
"edit_global": "Globális környezet szerkesztése",
|
||||
"new": "Új környezet létrehozása",
|
||||
"new_variable": "Új környezeti változó létrehozása",
|
||||
"title": "Környezetek"
|
||||
},
|
||||
"general": {
|
||||
"chat": "Chat with support",
|
||||
"help_menu": "Help and support",
|
||||
"open_docs": "Read Documentation",
|
||||
"open_github": "Open GitHub repository",
|
||||
"open_keybindings": "Keyboard shortcuts",
|
||||
"social": "Social",
|
||||
"title": "General"
|
||||
"chat": "Üzenet a supportnak",
|
||||
"help_menu": "Segítség és support",
|
||||
"open_docs": "Dokumentáció olvasása",
|
||||
"open_github": "GitHub repository megnyitása",
|
||||
"open_keybindings": "Billentyűkombinációk megnyitása",
|
||||
"social": "Közösség",
|
||||
"title": "Általános"
|
||||
},
|
||||
"graphql": {
|
||||
"connect": "Connect to server",
|
||||
"disconnect": "Disconnect from server"
|
||||
"connect": "Csatlakozás a szerverhez",
|
||||
"disconnect": "Lecsatlakozás a szerverről"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"invite": "Invite your friends to Hoppscotch",
|
||||
"title": "Miscellaneous"
|
||||
"invite": "Hívja meg barátait a Hoppscotch-ba",
|
||||
"title": "Egyéb"
|
||||
},
|
||||
"request": {
|
||||
"save_as_new": "Save as new request",
|
||||
"select_method": "Select method",
|
||||
"switch_to": "Switch to",
|
||||
"tab_authorization": "Authorization tab",
|
||||
"tab_body": "Body tab",
|
||||
"tab_headers": "Headers tab",
|
||||
"tab_parameters": "Parameters tab",
|
||||
"tab_pre_request_script": "Pre-request script tab",
|
||||
"tab_query": "Query tab",
|
||||
"tab_tests": "Tests tab",
|
||||
"tab_variables": "Variables tab"
|
||||
"save_as_new": "Mentés új kérésként",
|
||||
"select_method": "Módszer kiválasztása",
|
||||
"switch_to": "Váltás",
|
||||
"tab_authorization": "Azonosítás lap",
|
||||
"tab_body": "Törzs lap",
|
||||
"tab_headers": "Fejlécek lap",
|
||||
"tab_parameters": "Paraméterek lap",
|
||||
"tab_pre_request_script": "Előzetes script lap",
|
||||
"tab_query": "Kérés lap",
|
||||
"tab_tests": "Tesztek lap",
|
||||
"tab_variables": "Változók lap"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Copy response",
|
||||
"download": "Download response as file",
|
||||
"title": "Response"
|
||||
"copy": "Válasz másolása",
|
||||
"download": "Válasz letöltése fájlként",
|
||||
"title": "Válasz"
|
||||
},
|
||||
"section": {
|
||||
"interceptor": "Interceptor",
|
||||
"interface": "Interface",
|
||||
"theme": "Theme",
|
||||
"user": "User"
|
||||
"theme": "Téma",
|
||||
"user": "Felhasználó"
|
||||
},
|
||||
"settings": {
|
||||
"change_interceptor": "Change Interceptor",
|
||||
"change_language": "Change Language",
|
||||
"change_interceptor": "Interceptor váltása",
|
||||
"change_language": "Nyelv váltása",
|
||||
"theme": {
|
||||
"black": "Black",
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System preference"
|
||||
"black": "Fekete",
|
||||
"dark": "Sötét",
|
||||
"light": "Világos",
|
||||
"system": "Rendszer"
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"close_current": "Close current tab",
|
||||
"close_others": "Close all other tabs",
|
||||
"duplicate": "Duplicate current tab",
|
||||
"new_tab": "Open a new tab",
|
||||
"title": "Tabs"
|
||||
"close_current": "Jelenlegi lap bezására",
|
||||
"close_others": "Összes többi lap bezására",
|
||||
"duplicate": "Jelenlegi lap diplikálása",
|
||||
"new_tab": "Új lap megnyitása",
|
||||
"title": "Lapok"
|
||||
},
|
||||
"workspace": {
|
||||
"delete": "Delete current team",
|
||||
"edit": "Edit current team",
|
||||
"invite": "Invite people to team",
|
||||
"new": "Create new team",
|
||||
"switch_to_personal": "Switch to your personal workspace",
|
||||
"title": "Teams"
|
||||
"delete": "Jelenlegi csapat törlése",
|
||||
"edit": "Jelenlegi csapat szerkesztése",
|
||||
"invite": "Emberek meghívása a jelenlegi csapatba",
|
||||
"new": "Új csapat létrehozása",
|
||||
"switch_to_personal": "Váltás a személyes munkaterületére",
|
||||
"title": "Csapatok"
|
||||
}
|
||||
},
|
||||
"sse": {
|
||||
@@ -828,20 +828,20 @@
|
||||
"connection_error": "Nem sikerült kapcsolódni",
|
||||
"connection_failed": "A kapcsolódás sikertelen",
|
||||
"connection_lost": "A kapcsolat elveszett",
|
||||
"copied_interface_to_clipboard": "Copied {language} interface type to clipboard",
|
||||
"copied_interface_to_clipboard": "{language} interface típusa vágólapra másolva",
|
||||
"copied_to_clipboard": "Vágólapra másolva",
|
||||
"deleted": "Törölve",
|
||||
"deprecated": "ELAVULT",
|
||||
"disabled": "Letiltva",
|
||||
"disconnected": "Leválasztva",
|
||||
"disconnected_from": "Leválasztva innen: {name}",
|
||||
"disconnected": "Lecsatlakoztatva",
|
||||
"disconnected_from": "Lecsatlakoztatva innen: {name}",
|
||||
"docs_generated": "Dokumentáció előállítva",
|
||||
"download_failed": "Download failed",
|
||||
"download_failed": "Letöltés sikertelen",
|
||||
"download_started": "A letöltés elkezdődött",
|
||||
"enabled": "Engedélyezve",
|
||||
"file_imported": "Fájl importálva",
|
||||
"finished_in": "Befejeződött {duration} ms alatt",
|
||||
"hide": "Hide",
|
||||
"hide": "Elrejtés",
|
||||
"history_deleted": "Előzmények törölve",
|
||||
"linewrap": "Sorok tördelése",
|
||||
"loading": "Betöltés…",
|
||||
@@ -872,13 +872,13 @@
|
||||
"twitter": "Kövessen minket Twitteren"
|
||||
},
|
||||
"tab": {
|
||||
"authorization": "Felhatalmazás",
|
||||
"authorization": "Azonosítás",
|
||||
"body": "Törzs",
|
||||
"close": "Close Tab",
|
||||
"close_others": "Close other Tabs",
|
||||
"close": "Lap bezárása",
|
||||
"close_others": "Többi lap bezárása",
|
||||
"collections": "Gyűjtemények",
|
||||
"documentation": "Dokumentáció",
|
||||
"duplicate": "Duplicate Tab",
|
||||
"duplicate": "Lap duplikálása",
|
||||
"environments": "Környezetek",
|
||||
"headers": "Fejlécek",
|
||||
"history": "Előzmények",
|
||||
@@ -905,7 +905,7 @@
|
||||
"email_do_not_match": "Az e-mail-cím nem egyezik a fiókja részleteivel. Vegye fel a kapcsolatot a csapat tulajdonosával.",
|
||||
"exit": "Kilépés a csapatból",
|
||||
"exit_disabled": "Csak a tulajdonos nem léphet ki a csapatból",
|
||||
"failed_invites": "Failed invites",
|
||||
"failed_invites": "Hiba a meghívás közben",
|
||||
"invalid_coll_id": "Érvénytelen gyűjteményazonosító",
|
||||
"invalid_email_format": "Az e-mail formátuma érvénytelen",
|
||||
"invalid_id": "Érvénytelen csapatazonosító. Vegye fel a kapcsolatot a csapat tulajdonosával.",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,12 +11,13 @@
|
||||
"connect": "Подключиться",
|
||||
"connecting": "Соединение...",
|
||||
"copy": "Скопировать",
|
||||
"create": "Create",
|
||||
"create": "Создать",
|
||||
"delete": "Удалить",
|
||||
"disconnect": "Отключиться",
|
||||
"dismiss": "Скрыть",
|
||||
"dont_save": "Не сохранять",
|
||||
"download_file": "Скачать файл",
|
||||
"download_here": "Download here",
|
||||
"drag_to_reorder": "Перетягивайте для сортировки",
|
||||
"duplicate": "Дублировать",
|
||||
"edit": "Редактировать",
|
||||
@@ -24,6 +25,7 @@
|
||||
"go_back": "Вернуться",
|
||||
"go_forward": "Вперёд",
|
||||
"group_by": "Сгруппировать по",
|
||||
"hide_secret": "Hide secret",
|
||||
"label": "Название",
|
||||
"learn_more": "Узнать больше",
|
||||
"less": "Меньше",
|
||||
@@ -33,7 +35,7 @@
|
||||
"open_workspace": "Открыть пространство",
|
||||
"paste": "Вставить",
|
||||
"prettify": "Форматировать",
|
||||
"properties": "Properties",
|
||||
"properties": "Параметры",
|
||||
"remove": "Удалить",
|
||||
"rename": "Переименовать",
|
||||
"restore": "Восстановить",
|
||||
@@ -42,13 +44,14 @@
|
||||
"scroll_to_top": "Вверх",
|
||||
"search": "Поиск",
|
||||
"send": "Отправить",
|
||||
"share": "Share",
|
||||
"share": "Поделиться",
|
||||
"show_secret": "Show secret",
|
||||
"start": "Начать",
|
||||
"starting": "Запускаю",
|
||||
"stop": "Стоп",
|
||||
"to_close": "что бы закрыть",
|
||||
"to_close": "закрыть",
|
||||
"to_navigate": "для навигации",
|
||||
"to_select": "выборать",
|
||||
"to_select": "выбрать",
|
||||
"turn_off": "Выключить",
|
||||
"turn_on": "Включить",
|
||||
"undo": "Отменить",
|
||||
@@ -66,12 +69,12 @@
|
||||
"copy_interface_type": "Copy interface type",
|
||||
"copy_user_id": "Копировать токен пользователя",
|
||||
"developer_option": "Настройки разработчика",
|
||||
"developer_option_description": "Инструмент разработчика помогает обслуживить и развивить Hoppscotch",
|
||||
"developer_option_description": "Инструмент разработчика помогает обслуживать и развивать Hoppscotch",
|
||||
"discord": "Discord",
|
||||
"documentation": "Документация",
|
||||
"github": "GitHub",
|
||||
"help": "Справка, отзывы и документация",
|
||||
"home": "Дом",
|
||||
"home": "На главную",
|
||||
"invite": "Пригласить",
|
||||
"invite_description": "В Hoppscotch мы разработали простой и интуитивно понятный интерфейс для создания и управления вашими API. Hoppscotch - это инструмент, который помогает создавать, тестировать, документировать и делиться своими API.",
|
||||
"invite_your_friends": "Пригласить своих друзей",
|
||||
@@ -85,7 +88,7 @@
|
||||
"reload": "Перезагрузить",
|
||||
"search": "Поиск",
|
||||
"share": "Поделиться",
|
||||
"shortcuts": "Ярлыки",
|
||||
"shortcuts": "Горячие клавиши",
|
||||
"social_description": "Подписывайся на наши соц. сети и оставайся всегда в курсе последних новостей, обновлений и релизов.",
|
||||
"social_links": "Социальные сети",
|
||||
"spotlight": "Прожектор",
|
||||
@@ -96,17 +99,19 @@
|
||||
"type_a_command_search": "Введите команду или выполните поиск…",
|
||||
"we_use_cookies": "Мы используем куки",
|
||||
"whats_new": "Что нового?",
|
||||
"wiki": "Вики"
|
||||
"wiki": "Узнать больше"
|
||||
},
|
||||
"auth": {
|
||||
"account_exists": "Учетная запись существует с разными учетными данными - войдите, чтобы связать обе учетные записи",
|
||||
"all_sign_in_options": "Все варианты входа",
|
||||
"continue_with_auth_provider": "Continue with {provider}",
|
||||
"continue_with_email": "Продолжить с электронной почтой",
|
||||
"continue_with_github": "Продолжить с GitHub",
|
||||
"continue_with_github_enterprise": "Continue with GitHub Enterprise",
|
||||
"continue_with_google": "Продолжить с Google",
|
||||
"continue_with_microsoft": "Продолжить с Microsoft",
|
||||
"email": "Электронное письмо",
|
||||
"logged_out": "Вышли из",
|
||||
"logged_out": "Успешно вышли. Будем скучать!",
|
||||
"login": "Авторизоваться",
|
||||
"login_success": "Успешный вход в систему",
|
||||
"login_to_hoppscotch": "Войти в Hoppscotch",
|
||||
@@ -121,7 +126,7 @@
|
||||
"generate_token": "Сгенерировать токен",
|
||||
"graphql_headers": "Authorization Headers are sent as part of the payload to connection_init",
|
||||
"include_in_url": "Добавить в URL",
|
||||
"inherited_from": "Inherited {auth} from parent collection {collection} ",
|
||||
"inherited_from": "Унаследован тип аутентификации {auth} из родительской коллекции {collection}",
|
||||
"learn": "Узнать больше",
|
||||
"oauth": {
|
||||
"redirect_auth_server_returned_error": "Auth Server returned an error state",
|
||||
@@ -135,11 +140,32 @@
|
||||
"redirect_no_token_endpoint": "No Token Endpoint Defined",
|
||||
"something_went_wrong_on_oauth_redirect": "Something went wrong during OAuth Redirect",
|
||||
"something_went_wrong_on_token_generation": "Something went wrong on token generation",
|
||||
"token_generation_oidc_discovery_failed": "Failure on token generation: OpenID Connect Discovery Failed"
|
||||
"token_generation_oidc_discovery_failed": "Failure on token generation: OpenID Connect Discovery Failed",
|
||||
"grant_type": "Grant Type",
|
||||
"grant_type_auth_code": "Authorization Code",
|
||||
"token_fetched_successfully": "Token fetched successfully",
|
||||
"token_fetch_failed": "Failed to fetch token",
|
||||
"validation_failed": "Validation Failed, please check the form fields",
|
||||
"label_authorization_endpoint": "Authorization Endpoint",
|
||||
"label_client_id": "Client ID",
|
||||
"label_client_secret": "Client Secret",
|
||||
"label_code_challenge": "Code Challenge",
|
||||
"label_code_challenge_method": "Code Challenge Method",
|
||||
"label_code_verifier": "Code Verifier",
|
||||
"label_scopes": "Scopes",
|
||||
"label_token_endpoint": "Token Endpoint",
|
||||
"label_use_pkce": "Use PKCE",
|
||||
"label_implicit": "Implicit",
|
||||
"label_password": "Password",
|
||||
"label_username": "Username",
|
||||
"label_auth_code": "Authorization Code",
|
||||
"label_client_credentials": "Client Credentials"
|
||||
},
|
||||
"pass_by_headers_label": "Headers",
|
||||
"pass_by_query_params_label": "Query Parameters",
|
||||
"pass_key_by": "Pass by",
|
||||
"password": "Пароль",
|
||||
"save_to_inherit": "Please save this request in any collection to inherit the authorization",
|
||||
"save_to_inherit": "Чтобы унаследовать аутентификации, нужно сохранить запрос в коллекции",
|
||||
"token": "Токен",
|
||||
"type": "Метод авторизации",
|
||||
"username": "Имя пользователя"
|
||||
@@ -149,6 +175,7 @@
|
||||
"different_parent": "Нельзя сортировать коллекцию с разной родительской коллекцией",
|
||||
"edit": "Редактировать коллекцию",
|
||||
"import_or_create": "Вы можете импортировать существующую или создать новую коллекцию",
|
||||
"import_collection": "Импортировать коллекцию",
|
||||
"invalid_name": "Укажите допустимое название коллекции",
|
||||
"invalid_root_move": "Коллекция уже в корне",
|
||||
"moved": "Перемещено успешно",
|
||||
@@ -157,38 +184,36 @@
|
||||
"name_length_insufficient": "Имя коллекции должно иметь 3 или более символов",
|
||||
"new": "Создать коллекцию",
|
||||
"order_changed": "Порядок коллекции обновлён",
|
||||
"properties": "Collection Properties",
|
||||
"properties_updated": "Collection Properties Updated",
|
||||
"properties": "Параметры коллекции",
|
||||
"properties_updated": "Параметры коллекции обновлены",
|
||||
"renamed": "Коллекция переименована",
|
||||
"request_in_use": "Запрос обрабатывается",
|
||||
"save_as": "Сохранить как",
|
||||
"save_to_collection": "Сохранить в коллекцию",
|
||||
"select": "Выбрать коллекцию",
|
||||
"select_location": "Выберите местоположение",
|
||||
"select_team": "Выберите команду",
|
||||
"team_collections": "Коллекции команд"
|
||||
"select_location": "Выберите местоположение"
|
||||
},
|
||||
"confirm": {
|
||||
"close_unsaved_tab": "Вы уверены что хотите закрыть эту вкладку?",
|
||||
"close_unsaved_tabs": "Вы уверены что хотите закрыть все эти вкладки? Несохранённые данные {count} вкладок будут утеряны.",
|
||||
"close_unsaved_tab": "Вы уверены, что хотите закрыть эту вкладку?",
|
||||
"close_unsaved_tabs": "Вы уверены, что хотите закрыть все эти вкладки? Несохранённые данные {count} вкладок будут утеряны.",
|
||||
"exit_team": "Вы точно хотите покинуть эту команду?",
|
||||
"logout": "Вы действительно хотите выйти?",
|
||||
"remove_collection": "Вы уверены, что хотите навсегда удалить эту коллекцию?",
|
||||
"remove_environment": "Вы действительно хотите удалить эту среду без возможности восстановления?",
|
||||
"remove_environment": "Вы действительно хотите удалить это окружение без возможности восстановления?",
|
||||
"remove_folder": "Вы уверены, что хотите навсегда удалить эту папку?",
|
||||
"remove_history": "Вы уверены, что хотите навсегда удалить всю историю?",
|
||||
"remove_request": "Вы уверены, что хотите навсегда удалить этот запрос?",
|
||||
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
||||
"remove_shared_request": "Вы уверены, что хотите навсегда удалить этот запрос?",
|
||||
"remove_team": "Вы уверены, что хотите удалить эту команду?",
|
||||
"remove_telemetry": "Вы действительно хотите отказаться от телеметрии?",
|
||||
"request_change": "Вы уверены что хотите сбросить текущий запрос, все не сохранённые данные будт утеряны?",
|
||||
"request_change": "Вы уверены, что хотите сбросить текущий запрос, все не сохранённые данные будт утеряны?",
|
||||
"save_unsaved_tab": "Вы хотите сохранить изменения в этой вкладке?",
|
||||
"sync": "Вы уверены, что хотите синхронизировать это рабочее пространство?"
|
||||
},
|
||||
"context_menu": {
|
||||
"add_parameters": "Add to parameters",
|
||||
"open_request_in_new_tab": "Open request in new tab",
|
||||
"set_environment_variable": "Set as variable"
|
||||
"add_parameters": "Добавить в список параметров",
|
||||
"open_request_in_new_tab": "Открыть запрос в новом окне",
|
||||
"set_environment_variable": "Добавить значение в переменную"
|
||||
},
|
||||
"cookies": {
|
||||
"modal": {
|
||||
@@ -227,24 +252,25 @@
|
||||
"collections": "Коллекции пустые",
|
||||
"documentation": "Подключите GraphQL endpoint, чтобы увидеть документацию.",
|
||||
"endpoint": "Endpoint не может быть пустым",
|
||||
"environments": "Окружения пусты",
|
||||
"environments": "Переменных окружения нет",
|
||||
"folder": "Папка пуста",
|
||||
"headers": "У этого запроса нет заголовков",
|
||||
"history": "История пуста",
|
||||
"invites": "Вы еще никого не приглашали",
|
||||
"members": "В этой команде еще нет участников",
|
||||
"parameters": "Этот запрос не имеет параметров",
|
||||
"parameters": "Этот запрос не содержит параметров",
|
||||
"pending_invites": "Пока что нет ожидающих заявок на вступление в команду",
|
||||
"profile": "Войдите, чтобы просмотреть свой профиль",
|
||||
"protocols": "Протоколы пустые",
|
||||
"request_variables": "Этот запрос не содержит никаких переменных",
|
||||
"secret_environments": "Секреты хранятся только на этом устройстве и не синхронизируются с сервером",
|
||||
"schema": "Подключиться к конечной точке GraphQL",
|
||||
"shared_requests": "Shared requests are empty",
|
||||
"shared_requests_logout": "Login to view your shared requests or create a new one",
|
||||
"shared_requests": "Вы еще не делились запросами с другими",
|
||||
"shared_requests_logout": "Нужно войти, чтобы делиться запросами и управлять ими",
|
||||
"subscription": "Нет подписок",
|
||||
"team_name": "Название команды пусто",
|
||||
"teams": "Команды пустые",
|
||||
"tests": "Для этого запроса нет тестов",
|
||||
"shortcodes": "Нет коротких ссылок"
|
||||
"tests": "Для этого запроса нет тестов"
|
||||
},
|
||||
"environment": {
|
||||
"add_to_global": "Добавить в глобальное окружение",
|
||||
@@ -252,53 +278,57 @@
|
||||
"create_new": "Создать новое окружение",
|
||||
"created": "Окружение создано",
|
||||
"deleted": "Окружение удалено",
|
||||
"duplicated": "Environment duplicated",
|
||||
"duplicated": "Окружение продублировано",
|
||||
"edit": "Редактировать окружение",
|
||||
"empty_variables": "No variables",
|
||||
"empty_variables": "Переменные еще не добавлены",
|
||||
"global": "Global",
|
||||
"global_variables": "Global variables",
|
||||
"global_variables": "Глобальные переменные",
|
||||
"import_or_create": "Импортировать или создать новое окружение",
|
||||
"invalid_name": "Укажите допустимое имя для окружения",
|
||||
"list": "Переменные окружения",
|
||||
"my_environments": "Мои окружения",
|
||||
"name": "Name",
|
||||
"name": "Имя",
|
||||
"nested_overflow": "максимальный уровень вложения переменных окружения - 10",
|
||||
"new": "Новая среда",
|
||||
"no_active_environment": "Нет активных окружений",
|
||||
"no_environment": "Нет окружения",
|
||||
"no_environment_description": "Не выбрано окружение, выберите что делать с переменными.",
|
||||
"quick_peek": "Environment Quick Peek",
|
||||
"quick_peek": "Быстрый просмотр переменных",
|
||||
"replace_with_variable": "Replace with variable",
|
||||
"scope": "Scope",
|
||||
"secrets": "Секретные переменные",
|
||||
"secret_value": "Секретное значение",
|
||||
"select": "Выберите среду",
|
||||
"set": "Set environment",
|
||||
"set_as_environment": "Set as environment",
|
||||
"set": "Выбрать окружение",
|
||||
"set_as_environment": "Поместить значение в переменную",
|
||||
"team_environments": "Окружения команды",
|
||||
"title": "Окружения",
|
||||
"updated": "Окружение обновлено",
|
||||
"value": "Value",
|
||||
"variable": "Variable",
|
||||
"value": "Значение",
|
||||
"variable": "Переменная",
|
||||
"variables": "Переменные",
|
||||
"variable_list": "Список переменных"
|
||||
},
|
||||
"error": {
|
||||
"authproviders_load_error": "Unable to load auth providers",
|
||||
"browser_support_sse": "Похоже, в этом браузере нет поддержки событий, отправленных сервером.",
|
||||
"check_console_details": "Подробности смотрите в журнале консоли.",
|
||||
"check_how_to_add_origin": "Инструкция как добавить origin в настройки расширения",
|
||||
"check_how_to_add_origin": "Инструкция как это сделать",
|
||||
"curl_invalid_format": "cURL неправильно отформатирован",
|
||||
"danger_zone": "Опасная зона",
|
||||
"delete_account": "Вы являетесь владельцем этой команды:",
|
||||
"delete_account_description": "Прежде чем удалить аккаунт вам необходимо либо назначить владельцом другого пользователя, либо удалить команды в которых вы являетесь владельцем.",
|
||||
"empty_profile_name": "Имя пользователя не может быть пустым",
|
||||
"empty_req_name": "Пустое имя запроса",
|
||||
"f12_details": "(F12 для подробностей)",
|
||||
"gql_prettify_invalid_query": "Не удалось определить недопустимый запрос, устранить синтаксические ошибки запроса и повторить попытку.",
|
||||
"gql_prettify_invalid_query": "Не удалось отформатировать, т.к. в запросе есть синтаксические ошибки. Устраните их и повторите попытку.",
|
||||
"incomplete_config_urls": "Не заполнены URL конфигурации",
|
||||
"incorrect_email": "Не корректный Email",
|
||||
"invalid_link": "Не корректная ссылка",
|
||||
"invalid_link_description": "Ссылка, по которой вы перешли, - недействительна, либо срок ее действия истек.",
|
||||
"invalid_embed_link": "The embed does not exist or is invalid.",
|
||||
"json_parsing_failed": "Не корректный JSON",
|
||||
"json_prettify_invalid_body": "Не удалось определить недопустимое тело, устранить синтаксические ошибки json и повторить попытку.",
|
||||
"json_prettify_invalid_body": "Не удалось определить формат строки, устраните синтаксические ошибки и повторите попытку.",
|
||||
"network_error": "Похоже, возникла проблема с соединением. Попробуйте еще раз.",
|
||||
"network_fail": "Не удалось отправить запрос",
|
||||
"no_collections_to_export": "Нечего экспортировать. Для начала нужно создать коллекцию.",
|
||||
@@ -306,8 +336,10 @@
|
||||
"no_environments_to_export": "Нечего экспортировать. Для начала нужно создать переменные окружения.",
|
||||
"no_results_found": "Совпадения не найдены",
|
||||
"page_not_found": "Эта страница не найдена",
|
||||
"please_install_extension": "Нужно установить специальное расширение и добавить этот домен как новый origin в настройках расширения.",
|
||||
"please_install_extension": "Ничего страшного. Просто нужно установить специальное расширение в браузере.",
|
||||
"proxy_error": "Proxy error",
|
||||
"reading_files": "Произошла ошибка при чтении файла или нескольких файлов",
|
||||
"same_profile_name": "Задано имя пользователя такое же как и было",
|
||||
"script_fail": "Не удалось выполнить сценарий предварительного запроса",
|
||||
"something_went_wrong": "Что-то пошло не так",
|
||||
"test_script_fail": "Не удалось выполнить тестирование запроса"
|
||||
@@ -315,13 +347,12 @@
|
||||
"export": {
|
||||
"as_json": "Экспорт как JSON",
|
||||
"create_secret_gist": "Создать секретный Gist",
|
||||
"create_secret_gist_tooltip_text": "Export as secret Gist",
|
||||
"failed": "Something went wrong while exporting",
|
||||
"secret_gist_success": "Successfully exported as secret Gist",
|
||||
"create_secret_gist_tooltip_text": "Экспортировать как секретный Gist",
|
||||
"failed": "Произошла ошибка во время экспорта",
|
||||
"secret_gist_success": "Успешно экспортировано как секретный Gist",
|
||||
"require_github": "Войдите через GitHub, чтобы создать секретную суть",
|
||||
"title": "Экспорт",
|
||||
"success": "Successfully exported",
|
||||
"gist_created": "Gist создан"
|
||||
"success": "Успешно экспортировано"
|
||||
},
|
||||
"filter": {
|
||||
"all": "Все",
|
||||
@@ -346,7 +377,7 @@
|
||||
"switch_connection": "Изменить соединение"
|
||||
},
|
||||
"graphql_collections": {
|
||||
"title": "GraphQL Collections"
|
||||
"title": "Коллекции GraphQL"
|
||||
},
|
||||
"group": {
|
||||
"time": "Время",
|
||||
@@ -359,8 +390,8 @@
|
||||
},
|
||||
"helpers": {
|
||||
"authorization": "Заголовок авторизации будет автоматически сгенерирован при отправке запроса.",
|
||||
"collection_properties_authorization": " This authorization will be set for every request in this collection.",
|
||||
"collection_properties_header": "This header will be set for every request in this collection.",
|
||||
"collection_properties_authorization": "Этот заголовок авторизации будет подставляться при каждом запросе в этой коллекции.",
|
||||
"collection_properties_header": "Этот заголовок будет подставляться при каждом запросе в этой коллекции.",
|
||||
"generate_documentation_first": "Сначала создайте документацию",
|
||||
"network_fail": "Невозможно достичь конечной точки API. Проверьте подключение к сети и попробуйте еще раз.",
|
||||
"offline": "Кажется, вы не в сети. Данные в этой рабочей области могут быть устаревшими.",
|
||||
@@ -380,10 +411,12 @@
|
||||
"import": {
|
||||
"collections": "Импортировать коллекции",
|
||||
"curl": "Импортировать из cURL",
|
||||
"environments_from_gist": "Import From Gist",
|
||||
"environments_from_gist_description": "Import Hoppscotch Environments From Gist",
|
||||
"environments_from_gist": "Импортировать из Gist",
|
||||
"environments_from_gist_description": "Импортировать переменные окружения Hoppscotch из Gist",
|
||||
"failed": "Ошибка импорта",
|
||||
"from_file": "Import from File",
|
||||
"file_size_limit_exceeded_warning_multiple_files": "Выбранные файлы превышают рекомендованный лимит в 10MB. Были импортированы только первые {files}",
|
||||
"file_size_limit_exceeded_warning_single_file": "Размер выбранного в данный момент файла превышает рекомендуемый лимит в 10 МБ. Пожалуйста, выберите другой файл.",
|
||||
"from_file": "Импортировать из одного или нескольких файлов",
|
||||
"from_gist": "Импорт из Gist",
|
||||
"from_gist_description": "Импортировать через Gist URL",
|
||||
"from_insomnia": "Импортировать с Insomnia",
|
||||
@@ -398,9 +431,9 @@
|
||||
"from_postman_description": "Импортировать из коллекции Postman",
|
||||
"from_url": "Импортировать из URL",
|
||||
"gist_url": "Введите URL-адрес Gist",
|
||||
"gql_collections_from_gist_description": "Import GraphQL Collections From Gist",
|
||||
"gql_collections_from_gist_description": "Импортировать GraphQL коллекцию из Gist",
|
||||
"hoppscotch_environment": "Hoppscotch Environment",
|
||||
"hoppscotch_environment_description": "Import Hoppscotch Environment JSON file",
|
||||
"hoppscotch_environment_description": "Импортировать окружение Hoppscotch из JSON файла",
|
||||
"import_from_url_invalid_fetch": "Не удалить получить данные по этому URL",
|
||||
"import_from_url_invalid_file_format": "Ошибка при импорте коллекций",
|
||||
"import_from_url_invalid_type": "Неподдерживаемый тип. Поддерживаемые типы: 'hoppscotch', 'openapi', 'postman', 'insomnia'",
|
||||
@@ -409,16 +442,19 @@
|
||||
"json_description": "Импортировать из коллекции Hoppscotch",
|
||||
"postman_environment": "Postman Environment",
|
||||
"postman_environment_description": "Import Postman Environment from a JSON file",
|
||||
"success": "Успешно импортировано",
|
||||
"title": "Импортировать"
|
||||
},
|
||||
"inspections": {
|
||||
"description": "Inspect possible errors",
|
||||
"description": "Показать возможные ошибки",
|
||||
"environment": {
|
||||
"add_environment": "Add to Environment",
|
||||
"not_found": "Environment variable “{environment}” not found."
|
||||
"add_environment": "Добавить переменную",
|
||||
"add_environment_value": "Заполнить значение",
|
||||
"empty_value": "Значение переменной окружения '{variable}' пустое",
|
||||
"not_found": "Переменная окружения “{environment}” не задана."
|
||||
},
|
||||
"header": {
|
||||
"cookie": "The browser doesn't allow Hoppscotch to set the Cookie Header. While we're working on the Hoppscotch Desktop App (coming soon), please use the Authorization Header instead."
|
||||
"cookie": "Из-за ограничений безопасности в веб версии нельзя задать Cookie параметры. Пожалуйста, используйте Hoppscotch Desktop приложение или используйте заголовок Authorization вместо этого."
|
||||
},
|
||||
"response": {
|
||||
"401_error": "Please check your authentication credentials.",
|
||||
@@ -427,12 +463,12 @@
|
||||
"default_error": "Please check your request.",
|
||||
"network_error": "Please check your network connection."
|
||||
},
|
||||
"title": "Inspector",
|
||||
"title": "Помощник",
|
||||
"url": {
|
||||
"extension_not_installed": "Extension not installed.",
|
||||
"extension_unknown_origin": "Make sure you've added the API endpoint's origin to the Hoppscotch Browser Extension list.",
|
||||
"extention_enable_action": "Enable Browser Extension",
|
||||
"extention_not_enabled": "Extension not enabled."
|
||||
"extension_not_installed": "Расширение не установлено.",
|
||||
"extension_unknown_origin": "Убедитесь, что текущий домен добавлен в список доверенных ресурсов в расширении браузера",
|
||||
"extention_enable_action": "Подключить расширение",
|
||||
"extention_not_enabled": "Расширение в браузере не подключено."
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
@@ -445,11 +481,11 @@
|
||||
"modal": {
|
||||
"close_unsaved_tab": "У вас есть не сохранённые изменения",
|
||||
"collections": "Коллекции",
|
||||
"confirm": "Подтверждать",
|
||||
"confirm": "Подтвердите действие",
|
||||
"customize_request": "Customize Request",
|
||||
"edit_request": "Изменить запрос",
|
||||
"import_export": "Импорт Экспорт",
|
||||
"share_request": "Share Request"
|
||||
"share_request": "Поделиться запросом"
|
||||
},
|
||||
"mqtt": {
|
||||
"already_subscribed": "Вы уже подписаны на этот топик",
|
||||
@@ -485,7 +521,7 @@
|
||||
"doc": "Документы",
|
||||
"graphql": "GraphQL",
|
||||
"profile": "Профиль",
|
||||
"realtime": "В реальном времени",
|
||||
"realtime": "Realtime",
|
||||
"rest": "REST",
|
||||
"settings": "Настройки"
|
||||
},
|
||||
@@ -507,8 +543,8 @@
|
||||
"roles": "Роли",
|
||||
"roles_description": "Роли позволяют настраивать доступ конкретным людям к публичным коллекциям.",
|
||||
"updated": "Профиль обновлен",
|
||||
"viewer": "Зритель",
|
||||
"viewer_description": "Зрительно могут только просматривать и использовать запросы."
|
||||
"viewer": "Читатель",
|
||||
"viewer_description": "Могут только просматривать и использовать запросы."
|
||||
},
|
||||
"remove": {
|
||||
"star": "Удалить звезду"
|
||||
@@ -530,11 +566,11 @@
|
||||
"enter_curl": "Введите сюда команду cURL",
|
||||
"generate_code": "Сгенерировать код",
|
||||
"generated_code": "Сгенерированный код",
|
||||
"go_to_authorization_tab": "Go to Authorization",
|
||||
"go_to_body_tab": "Go to Body tab",
|
||||
"go_to_authorization_tab": "Перейти на вкладку авторизации",
|
||||
"go_to_body_tab": "Перейти на вкладку тела запроса",
|
||||
"header_list": "Список заголовков",
|
||||
"invalid_name": "Укажите имя для запроса",
|
||||
"method": "Методика",
|
||||
"method": "Метод",
|
||||
"moved": "Запрос перемещён",
|
||||
"name": "Имя запроса",
|
||||
"new": "Новый запрос",
|
||||
@@ -548,22 +584,22 @@
|
||||
"payload": "Полезная нагрузка",
|
||||
"query": "Запрос",
|
||||
"raw_body": "Необработанное тело запроса",
|
||||
"rename": "Переименость запрос",
|
||||
"rename": "Переименовать запрос",
|
||||
"renamed": "Запрос переименован",
|
||||
"request_variables": "Переменные запроса",
|
||||
"run": "Запустить",
|
||||
"save": "Сохранить",
|
||||
"save_as": "Сохранить как",
|
||||
"saved": "Запрос сохранен",
|
||||
"share": "Делиться",
|
||||
"share": "Поделиться",
|
||||
"share_description": "Поделиться Hoppscotch с друзьями",
|
||||
"share_request": "Share Request",
|
||||
"stop": "Stop",
|
||||
"share_request": "Поделиться запросом",
|
||||
"stop": "Стоп",
|
||||
"title": "Запрос",
|
||||
"type": "Тип запроса",
|
||||
"url": "URL",
|
||||
"variables": "Переменные",
|
||||
"view_my_links": "Посмотреть мои ссылки",
|
||||
"copy_link": "Копировать ссылку"
|
||||
"view_my_links": "Посмотреть мои ссылки"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Аудио",
|
||||
@@ -586,7 +622,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"accent_color": "Основной цвет",
|
||||
"account": "Счет",
|
||||
"account": "Аккаунт",
|
||||
"account_deleted": "Ваш аккаунт был удалён",
|
||||
"account_description": "Настройте параметры своей учетной записи.",
|
||||
"account_email_description": "Ваш основной адрес электронной почты.",
|
||||
@@ -639,29 +675,29 @@
|
||||
"verify_email": "Подтвердить Email"
|
||||
},
|
||||
"shared_requests": {
|
||||
"button": "Button",
|
||||
"button_info": "Create a 'Run in Hoppscotch' button for your website, blog or a README.",
|
||||
"copy_html": "Copy HTML",
|
||||
"copy_link": "Copy Link",
|
||||
"copy_markdown": "Copy Markdown",
|
||||
"creating_widget": "Creating widget",
|
||||
"customize": "Customize",
|
||||
"deleted": "Shared request deleted",
|
||||
"description": "Select a widget, you can change and customize this later",
|
||||
"embed": "Embed",
|
||||
"embed_info": "Add a mini 'Hoppscotch API Playground' to your website, blog or documentation.",
|
||||
"link": "Link",
|
||||
"link_info": "Create a shareable link to share with anyone on the internet with view access.",
|
||||
"modified": "Shared request modified",
|
||||
"not_found": "Shared request not found",
|
||||
"open_new_tab": "Open in new tab",
|
||||
"button": "Кнопка",
|
||||
"button_info": "Создать кнопку 'Run in Hoppscotch' на свой сайт, блог или README.",
|
||||
"copy_html": "Копировать HTML код",
|
||||
"copy_link": "Копировать ссылку",
|
||||
"copy_markdown": "Копировать Markdown",
|
||||
"creating_widget": "Создание виджет",
|
||||
"customize": "Настроить",
|
||||
"deleted": "Запрос удален",
|
||||
"description": "Выберите вид как вы поделитесь запросом, позже вы сможете дополнительно его настроить",
|
||||
"embed": "Встраиваемое окно",
|
||||
"embed_info": "Добавьте небольшую площадку 'Hoppscotch API Playground' на свой веб-сайт, блог или документацию.",
|
||||
"link": "Ссылка",
|
||||
"link_info": "Создайте общедоступную ссылку, которой можно поделиться с любым пользователем, имеющим доступ к просмотру.",
|
||||
"modified": "Запрос изменен",
|
||||
"not_found": "Такой ссылке не нашлось",
|
||||
"open_new_tab": "Открыть в новом окне",
|
||||
"preview": "Preview",
|
||||
"run_in_hoppscotch": "Run in Hoppscotch",
|
||||
"theme": {
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System",
|
||||
"title": "Theme"
|
||||
"dark": "Темная",
|
||||
"light": "Светлая",
|
||||
"system": "Системная",
|
||||
"title": "Тема"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
@@ -669,7 +705,7 @@
|
||||
"close_current_menu": "Закрыть текущее меню",
|
||||
"command_menu": "Меню поиска и команд",
|
||||
"help_menu": "Меню помощи",
|
||||
"show_all": "Горячие клавиши",
|
||||
"show_all": "Список горячих клавиш",
|
||||
"title": "Общий"
|
||||
},
|
||||
"miscellaneous": {
|
||||
@@ -696,20 +732,19 @@
|
||||
"get_method": "Выберите метод GET",
|
||||
"head_method": "Выберите метод HEAD",
|
||||
"import_curl": "Импортировать из cURL",
|
||||
"method": "Методика",
|
||||
"method": "Метод",
|
||||
"next_method": "Выберите следующий метод",
|
||||
"post_method": "Выберите метод POST",
|
||||
"previous_method": "Выбрать предыдущий метод",
|
||||
"put_method": "Выберите метод PUT",
|
||||
"rename": "Переименовать запрос",
|
||||
"reset_request": "Сбросить запрос",
|
||||
"save_request": "Сохарнить запрос",
|
||||
"save_request": "Сохранить запрос",
|
||||
"save_to_collections": "Сохранить в коллекции",
|
||||
"send_request": "Послать запрос",
|
||||
"share_request": "Share Request",
|
||||
"show_code": "Generate code snippet",
|
||||
"title": "Запрос",
|
||||
"copy_request_link": "Копировать ссылку на запрос"
|
||||
"share_request": "Поделиться запросом",
|
||||
"show_code": "Сгенерировать фрагмент кода из запроса",
|
||||
"title": "Запрос"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Копировать запрос в буфер обмена",
|
||||
@@ -717,11 +752,11 @@
|
||||
"title": "Запрос"
|
||||
},
|
||||
"theme": {
|
||||
"black": "Черный режим",
|
||||
"dark": "Тёмный режим",
|
||||
"light": "Светлый режим",
|
||||
"system": "Определяется системой",
|
||||
"title": "Тема"
|
||||
"black": "Переключить на черный режим",
|
||||
"dark": "Переключить на тёмный режим",
|
||||
"light": "Переключить на светлый режим",
|
||||
"system": "Переключить на тему, исходя из настроек системы",
|
||||
"title": "Внешний вид"
|
||||
}
|
||||
},
|
||||
"show": {
|
||||
@@ -730,6 +765,11 @@
|
||||
"more": "Показать больше",
|
||||
"sidebar": "Показать боковую панель"
|
||||
},
|
||||
"site_protection": {
|
||||
"error_fetching_site_protection_status": "Something Went Wrong While Fetching Site Protection Status",
|
||||
"login_to_continue": "Login to continue",
|
||||
"login_to_continue_description": "You need to be logged in to access this Hoppscotch Enterprise Instance."
|
||||
},
|
||||
"socketio": {
|
||||
"communication": "Коммуникация",
|
||||
"connection_not_authorized": "Это SocketIO соединение не использует какую-либо авторизацию.",
|
||||
@@ -739,82 +779,89 @@
|
||||
"url": "URL"
|
||||
},
|
||||
"spotlight": {
|
||||
"change_language": "Change Language",
|
||||
"change_language": "Изменить язык",
|
||||
"environments": {
|
||||
"delete": "Delete current environment",
|
||||
"duplicate": "Duplicate current environment",
|
||||
"duplicate_global": "Duplicate global environment",
|
||||
"edit": "Edit current environment",
|
||||
"edit_global": "Edit global environment",
|
||||
"new": "Create new environment",
|
||||
"new_variable": "Create a new environment variable",
|
||||
"title": "Environments"
|
||||
"delete": "Удалить текущее окружение",
|
||||
"duplicate": "Дублировать текущее окружение",
|
||||
"duplicate_global": "Дублировать глобальное окружение",
|
||||
"edit": "Редактировать текущее окружение",
|
||||
"edit_global": "Редактировать глобальное окружение",
|
||||
"new": "Создать новое окружение",
|
||||
"new_variable": "Создать новую переменную окружения",
|
||||
"title": "Окружение"
|
||||
},
|
||||
"general": {
|
||||
"chat": "Chat with support",
|
||||
"help_menu": "Help and support",
|
||||
"open_docs": "Read Documentation",
|
||||
"open_github": "Open GitHub repository",
|
||||
"open_keybindings": "Keyboard shortcuts",
|
||||
"social": "Social",
|
||||
"title": "General"
|
||||
"chat": "Чат с поддержкой",
|
||||
"help_menu": "Помощь",
|
||||
"open_docs": "Почитать документацию",
|
||||
"open_github": "Открыть GitHub репозиторий",
|
||||
"open_keybindings": "Горячие клавиши",
|
||||
"social": "Соц. сети",
|
||||
"title": "Общее"
|
||||
},
|
||||
"graphql": {
|
||||
"connect": "Connect to server",
|
||||
"disconnect": "Disconnect from server"
|
||||
"connect": "Подключиться к серверу",
|
||||
"disconnect": "Отключиться от сервера"
|
||||
},
|
||||
"miscellaneous": {
|
||||
"invite": "Invite your friends to Hoppscotch",
|
||||
"title": "Miscellaneous"
|
||||
"invite": "Пригласить друзей в Hoppscotch",
|
||||
"title": "Другое"
|
||||
},
|
||||
"phrases": {
|
||||
"create_environment": "Создать окружение",
|
||||
"create_workspace": "Создать пространство",
|
||||
"import_collections": "Импортировать коллекцию",
|
||||
"share_request": "Поделиться запросом",
|
||||
"try": "Попробовать"
|
||||
},
|
||||
"request": {
|
||||
"save_as_new": "Save as new request",
|
||||
"select_method": "Select method",
|
||||
"switch_to": "Switch to",
|
||||
"tab_authorization": "Authorization tab",
|
||||
"tab_body": "Body tab",
|
||||
"tab_headers": "Headers tab",
|
||||
"tab_parameters": "Parameters tab",
|
||||
"tab_pre_request_script": "Pre-request script tab",
|
||||
"tab_query": "Query tab",
|
||||
"tab_tests": "Tests tab",
|
||||
"tab_variables": "Variables tab"
|
||||
"save_as_new": "Сохранить как новый запрос",
|
||||
"select_method": "Выбрать метод",
|
||||
"switch_to": "Переключиться",
|
||||
"tab_authorization": "На вкладку авторизации",
|
||||
"tab_body": "На вкладку тела запроса",
|
||||
"tab_headers": "На вкладку заголовков",
|
||||
"tab_parameters": "На вкладку параметров",
|
||||
"tab_pre_request_script": "На вкладку пред-скрипта запроса",
|
||||
"tab_query": "На вкладку запроса",
|
||||
"tab_tests": "На вкладку тестов",
|
||||
"tab_variables": "На вкладку переменных запроса"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Copy response",
|
||||
"download": "Download response as file",
|
||||
"title": "Response"
|
||||
"copy": "Копировать содержимое ответа",
|
||||
"download": "Сказать содержимое ответа как файл",
|
||||
"title": "Ответ запроса"
|
||||
},
|
||||
"section": {
|
||||
"interceptor": "Interceptor",
|
||||
"interface": "Interface",
|
||||
"theme": "Theme",
|
||||
"user": "User"
|
||||
"interceptor": "Перехватчик",
|
||||
"interface": "Интерфейс",
|
||||
"theme": "Внешний вид",
|
||||
"user": "Пользователь"
|
||||
},
|
||||
"settings": {
|
||||
"change_interceptor": "Change Interceptor",
|
||||
"change_language": "Change Language",
|
||||
"change_interceptor": "Изменить перехватчик",
|
||||
"change_language": "Изменить язык",
|
||||
"theme": {
|
||||
"black": "Black",
|
||||
"dark": "Dark",
|
||||
"light": "Light",
|
||||
"system": "System preference"
|
||||
"black": "Черная",
|
||||
"dark": "Темная",
|
||||
"light": "Светлая",
|
||||
"system": "Как задано в системе"
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"close_current": "Close current tab",
|
||||
"close_others": "Close all other tabs",
|
||||
"duplicate": "Duplicate current tab",
|
||||
"new_tab": "Open a new tab",
|
||||
"title": "Tabs"
|
||||
"close_current": "Закрыть текущую вкладку",
|
||||
"close_others": "Закрыть все вкладки",
|
||||
"duplicate": "Продублировать текущую вкладку",
|
||||
"new_tab": "Открыть в новой вкладке",
|
||||
"title": "Вкладки"
|
||||
},
|
||||
"workspace": {
|
||||
"delete": "Delete current team",
|
||||
"edit": "Edit current team",
|
||||
"invite": "Invite people to team",
|
||||
"new": "Create new team",
|
||||
"switch_to_personal": "Switch to your personal workspace",
|
||||
"title": "Teams"
|
||||
"delete": "Удалить текущую команду",
|
||||
"edit": "Редактировать текущую команду",
|
||||
"invite": "Пригласить людей в команду",
|
||||
"new": "Создать новую команду",
|
||||
"switch_to_personal": "Переключить на персональное пространство",
|
||||
"title": "Команды"
|
||||
}
|
||||
},
|
||||
"sse": {
|
||||
@@ -824,7 +871,7 @@
|
||||
},
|
||||
"state": {
|
||||
"bulk_mode": "Множественное редактирование",
|
||||
"bulk_mode_placeholder": "Каждый параметр должен начинаться с новой строки\nКлючи и значения разедляются двоеточием\nИспользуйте # для комментария",
|
||||
"bulk_mode_placeholder": "Каждый параметр должен начинаться с новой строки\nКлючи и значения разделяются двоеточием\nИспользуйте # для комментария",
|
||||
"cleared": "Очищено",
|
||||
"connected": "Связаны",
|
||||
"connected_to": "Подключено к {name}",
|
||||
@@ -843,20 +890,20 @@
|
||||
"download_failed": "Download failed",
|
||||
"download_started": "Скачивание началось",
|
||||
"enabled": "Включено",
|
||||
"file_imported": "Файл импортирован",
|
||||
"file_imported": "Файл успешно импортирован",
|
||||
"finished_in": "Завершено через {duration} мс",
|
||||
"hide": "Hide",
|
||||
"hide": "Скрыть",
|
||||
"history_deleted": "История удалена",
|
||||
"linewrap": "Обернуть линии",
|
||||
"loading": "Загрузка...",
|
||||
"message_received": "Сообщение: {message} получено по топику: {topic}",
|
||||
"mqtt_subscription_failed": "Что-то пошло не так, при попытке подписаться на топик: {topic}",
|
||||
"none": "Никто",
|
||||
"none": "Не задан",
|
||||
"nothing_found": "Ничего не найдено для",
|
||||
"published_error": "Что-то пошло не так при попытке опубликовать сообщение в топик {topic}: {message}",
|
||||
"published_message": "Опубликовано сообщение: {message} в топик: {topic}",
|
||||
"reconnection_error": "Не удалось переподключиться",
|
||||
"show": "Show",
|
||||
"show": "Показать",
|
||||
"subscribed_failed": "Не удалось подписаться на топик: {topic}",
|
||||
"subscribed_success": "Успешно подписался на топик: {topic}",
|
||||
"unsubscribed_failed": "Не удалось отписаться от топика: {topic}",
|
||||
@@ -871,7 +918,6 @@
|
||||
"forum": "Задавайте вопросы и получайте ответы",
|
||||
"github": "Подпишитесь на нас на Github",
|
||||
"shortcuts": "Просматривайте приложение быстрее",
|
||||
"team": "Свяжитесь с командой",
|
||||
"title": "Служба поддержки",
|
||||
"twitter": "Следуйте за нами на Twitter"
|
||||
},
|
||||
@@ -882,7 +928,7 @@
|
||||
"close_others": "Закрыть остальные вкладки",
|
||||
"collections": "Коллекции",
|
||||
"documentation": "Документация",
|
||||
"duplicate": "Duplicate Tab",
|
||||
"duplicate": "Дублировать вкладку",
|
||||
"environments": "Окружения",
|
||||
"headers": "Заголовки",
|
||||
"history": "История",
|
||||
@@ -892,7 +938,8 @@
|
||||
"queries": "Запросы",
|
||||
"query": "Запрос",
|
||||
"schema": "Схема",
|
||||
"shared_requests": "Shared Requests",
|
||||
"shared_requests": "Запросы в общем доступе",
|
||||
"share_tab_request": "Поделиться запросом",
|
||||
"socketio": "Socket.IO",
|
||||
"sse": "SSE",
|
||||
"tests": "Тесты",
|
||||
@@ -921,7 +968,6 @@
|
||||
"invite_tooltip": "Пригласить людей в Ваше рабочее пространство",
|
||||
"invited_to_team": "{owner} приглашает Вас присоединиться к команде {team}",
|
||||
"join": "Приглашение принято",
|
||||
"join_beta": "Присоединяйтесь к бета-программе, чтобы получить доступ к командам.",
|
||||
"join_team": "Присоединиться к {team}",
|
||||
"joined_team": "Вы присоединились к команде {team}",
|
||||
"joined_team_description": "Теперь Вы участник этой команды",
|
||||
@@ -950,6 +996,7 @@
|
||||
"permissions": "Разрешения",
|
||||
"same_target_destination": "Таже цель и конечная точка",
|
||||
"saved": "Команда сохранена",
|
||||
"search_title": "Team Requests",
|
||||
"select_a_team": "Выбрать команду",
|
||||
"success_invites": "Принятые приглашения",
|
||||
"title": "Команды",
|
||||
@@ -981,16 +1028,8 @@
|
||||
"workspace": {
|
||||
"change": "Изменить пространство",
|
||||
"personal": "Моё пространство",
|
||||
"other_workspaces": "Пространства",
|
||||
"team": "Пространство команды",
|
||||
"title": "Рабочие пространства"
|
||||
},
|
||||
"shortcodes": {
|
||||
"actions": "Действия",
|
||||
"created_on": "Создано",
|
||||
"deleted": "Удалёна",
|
||||
"method": "Метод",
|
||||
"not_found": "Короткая ссылка не найдена",
|
||||
"short_code": "Короткая ссылка",
|
||||
"url": "URL"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,9 +68,9 @@
|
||||
"developer_option": "Developer options",
|
||||
"developer_option_description": "Developer tools which helps in development and maintenance of Hoppscotch.",
|
||||
"discord": "Discord",
|
||||
"documentation": "Dökümanlar",
|
||||
"documentation": "Dokümanlar",
|
||||
"github": "GitHub",
|
||||
"help": "Yardım, geri bildirim ve dökümanlar",
|
||||
"help": "Yardım, geri bildirim ve dokümanlar",
|
||||
"home": "Ana sayfa",
|
||||
"invite": "Davet et",
|
||||
"invite_description": "Hoppscotch'ta API'lerinizi oluşturmak ve yönetmek için basit ve sezgisel bir arayüz tasarladık. Hoppscotch, API'lerinizi oluşturmanıza, test etmenize, belgelemenize ve paylaşmanıza yardımcı olan bir araçtır.",
|
||||
@@ -225,7 +225,7 @@
|
||||
"body": "Bu isteğin bir gövdesi yok",
|
||||
"collection": "Koleksiyon boş",
|
||||
"collections": "Koleksiyonlar boş",
|
||||
"documentation": "Dökümanları görmek için GraphQL uç noktasını bağlayın",
|
||||
"documentation": "Dokümanları görmek için GraphQL uç noktasını bağlayın",
|
||||
"endpoint": "Uç nokta boş olamaz",
|
||||
"environments": "Ortamlar boş",
|
||||
"folder": "Klasör boş",
|
||||
@@ -735,7 +735,7 @@
|
||||
"url": "Bağlantı"
|
||||
},
|
||||
"spotlight": {
|
||||
"change_language": "Change Language",
|
||||
"change_language": "Dil Değiştir",
|
||||
"environments": {
|
||||
"delete": "Delete current environment",
|
||||
"duplicate": "Duplicate current environment",
|
||||
@@ -744,7 +744,7 @@
|
||||
"edit_global": "Edit global environment",
|
||||
"new": "Create new environment",
|
||||
"new_variable": "Create a new environment variable",
|
||||
"title": "Environments"
|
||||
"title": "Ortamlar"
|
||||
},
|
||||
"general": {
|
||||
"chat": "Chat with support",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@hoppscotch/common",
|
||||
"private": true,
|
||||
"version": "2024.3.0",
|
||||
"version": "2024.3.3",
|
||||
"scripts": {
|
||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||
"test": "vitest --run",
|
||||
@@ -50,7 +50,7 @@
|
||||
"axios": "1.6.2",
|
||||
"buffer": "6.0.3",
|
||||
"cookie-es": "1.0.0",
|
||||
"dioc": "1.0.1",
|
||||
"dioc": "3.0.1",
|
||||
"esprima": "4.0.1",
|
||||
"events": "3.3.0",
|
||||
"fp-ts": "2.16.1",
|
||||
@@ -90,7 +90,7 @@
|
||||
"util": "0.12.5",
|
||||
"uuid": "9.0.1",
|
||||
"verzod": "0.2.2",
|
||||
"vue": "3.3.9",
|
||||
"vue": "3.4.27",
|
||||
"vue-i18n": "9.8.0",
|
||||
"vue-pdf-embed": "1.2.1",
|
||||
"vue-router": "4.2.5",
|
||||
|
||||
415
packages/hoppscotch-common/src/components.d.ts
vendored
415
packages/hoppscotch-common/src/components.d.ts
vendored
@@ -3,214 +3,221 @@
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import "@vue/runtime-core"
|
||||
|
||||
export {}
|
||||
|
||||
declare module "@vue/runtime-core" {
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AppActionHandler: (typeof import("./components/app/ActionHandler.vue"))["default"]
|
||||
AppBanner: (typeof import("./components/app/Banner.vue"))["default"]
|
||||
AppContextMenu: (typeof import("./components/app/ContextMenu.vue"))["default"]
|
||||
AppDeveloperOptions: (typeof import("./components/app/DeveloperOptions.vue"))["default"]
|
||||
AppFooter: (typeof import("./components/app/Footer.vue"))["default"]
|
||||
AppGitHubStarButton: (typeof import("./components/app/GitHubStarButton.vue"))["default"]
|
||||
AppHeader: (typeof import("./components/app/Header.vue"))["default"]
|
||||
AppInspection: (typeof import("./components/app/Inspection.vue"))["default"]
|
||||
AppInterceptor: (typeof import("./components/app/Interceptor.vue"))["default"]
|
||||
AppLogo: (typeof import("./components/app/Logo.vue"))["default"]
|
||||
AppOptions: (typeof import("./components/app/Options.vue"))["default"]
|
||||
AppPaneLayout: (typeof import("./components/app/PaneLayout.vue"))["default"]
|
||||
AppShare: (typeof import("./components/app/Share.vue"))["default"]
|
||||
AppShortcuts: (typeof import("./components/app/Shortcuts.vue"))["default"]
|
||||
AppShortcutsEntry: (typeof import("./components/app/ShortcutsEntry.vue"))["default"]
|
||||
AppShortcutsPrompt: (typeof import("./components/app/ShortcutsPrompt.vue"))["default"]
|
||||
AppSidenav: (typeof import("./components/app/Sidenav.vue"))["default"]
|
||||
AppSpotlight: (typeof import("./components/app/spotlight/index.vue"))["default"]
|
||||
AppSpotlightEntry: (typeof import("./components/app/spotlight/Entry.vue"))["default"]
|
||||
AppSpotlightEntryGQLHistory: (typeof import("./components/app/spotlight/entry/GQLHistory.vue"))["default"]
|
||||
AppSpotlightEntryGQLRequest: (typeof import("./components/app/spotlight/entry/GQLRequest.vue"))["default"]
|
||||
AppSpotlightEntryIconSelected: (typeof import("./components/app/spotlight/entry/IconSelected.vue"))["default"]
|
||||
AppSpotlightEntryRESTHistory: (typeof import("./components/app/spotlight/entry/RESTHistory.vue"))["default"]
|
||||
AppSpotlightEntryRESTRequest: (typeof import("./components/app/spotlight/entry/RESTRequest.vue"))["default"]
|
||||
AppSupport: (typeof import("./components/app/Support.vue"))["default"]
|
||||
Collections: (typeof import("./components/collections/index.vue"))["default"]
|
||||
CollectionsAdd: (typeof import("./components/collections/Add.vue"))["default"]
|
||||
CollectionsAddFolder: (typeof import("./components/collections/AddFolder.vue"))["default"]
|
||||
CollectionsAddRequest: (typeof import("./components/collections/AddRequest.vue"))["default"]
|
||||
CollectionsCollection: (typeof import("./components/collections/Collection.vue"))["default"]
|
||||
CollectionsEdit: (typeof import("./components/collections/Edit.vue"))["default"]
|
||||
CollectionsEditFolder: (typeof import("./components/collections/EditFolder.vue"))["default"]
|
||||
CollectionsEditRequest: (typeof import("./components/collections/EditRequest.vue"))["default"]
|
||||
CollectionsGraphql: (typeof import("./components/collections/graphql/index.vue"))["default"]
|
||||
CollectionsGraphqlAdd: (typeof import("./components/collections/graphql/Add.vue"))["default"]
|
||||
CollectionsGraphqlAddFolder: (typeof import("./components/collections/graphql/AddFolder.vue"))["default"]
|
||||
CollectionsGraphqlAddRequest: (typeof import("./components/collections/graphql/AddRequest.vue"))["default"]
|
||||
CollectionsGraphqlCollection: (typeof import("./components/collections/graphql/Collection.vue"))["default"]
|
||||
CollectionsGraphqlEdit: (typeof import("./components/collections/graphql/Edit.vue"))["default"]
|
||||
CollectionsGraphqlEditFolder: (typeof import("./components/collections/graphql/EditFolder.vue"))["default"]
|
||||
CollectionsGraphqlEditRequest: (typeof import("./components/collections/graphql/EditRequest.vue"))["default"]
|
||||
CollectionsGraphqlFolder: (typeof import("./components/collections/graphql/Folder.vue"))["default"]
|
||||
CollectionsGraphqlImportExport: (typeof import("./components/collections/graphql/ImportExport.vue"))["default"]
|
||||
CollectionsGraphqlRequest: (typeof import("./components/collections/graphql/Request.vue"))["default"]
|
||||
CollectionsImportExport: (typeof import("./components/collections/ImportExport.vue"))["default"]
|
||||
CollectionsMyCollections: (typeof import("./components/collections/MyCollections.vue"))["default"]
|
||||
CollectionsProperties: (typeof import("./components/collections/Properties.vue"))["default"]
|
||||
CollectionsRequest: (typeof import("./components/collections/Request.vue"))["default"]
|
||||
CollectionsSaveRequest: (typeof import("./components/collections/SaveRequest.vue"))["default"]
|
||||
CollectionsTeamCollections: (typeof import("./components/collections/TeamCollections.vue"))["default"]
|
||||
CookiesAllModal: (typeof import("./components/cookies/AllModal.vue"))["default"]
|
||||
CookiesEditCookie: (typeof import("./components/cookies/EditCookie.vue"))["default"]
|
||||
Embeds: (typeof import("./components/embeds/index.vue"))["default"]
|
||||
Environments: (typeof import("./components/environments/index.vue"))["default"]
|
||||
EnvironmentsAdd: (typeof import("./components/environments/Add.vue"))["default"]
|
||||
EnvironmentsImportExport: (typeof import("./components/environments/ImportExport.vue"))["default"]
|
||||
EnvironmentsMy: (typeof import("./components/environments/my/index.vue"))["default"]
|
||||
EnvironmentsMyDetails: (typeof import("./components/environments/my/Details.vue"))["default"]
|
||||
EnvironmentsMyEnvironment: (typeof import("./components/environments/my/Environment.vue"))["default"]
|
||||
EnvironmentsSelector: (typeof import("./components/environments/Selector.vue"))["default"]
|
||||
EnvironmentsTeams: (typeof import("./components/environments/teams/index.vue"))["default"]
|
||||
EnvironmentsTeamsDetails: (typeof import("./components/environments/teams/Details.vue"))["default"]
|
||||
EnvironmentsTeamsEnvironment: (typeof import("./components/environments/teams/Environment.vue"))["default"]
|
||||
FirebaseLogin: (typeof import("./components/firebase/Login.vue"))["default"]
|
||||
FirebaseLogout: (typeof import("./components/firebase/Logout.vue"))["default"]
|
||||
GraphqlAuthorization: (typeof import("./components/graphql/Authorization.vue"))["default"]
|
||||
GraphqlField: (typeof import("./components/graphql/Field.vue"))["default"]
|
||||
GraphqlHeaders: (typeof import("./components/graphql/Headers.vue"))["default"]
|
||||
GraphqlQuery: (typeof import("./components/graphql/Query.vue"))["default"]
|
||||
GraphqlRequest: (typeof import("./components/graphql/Request.vue"))["default"]
|
||||
GraphqlRequestOptions: (typeof import("./components/graphql/RequestOptions.vue"))["default"]
|
||||
GraphqlRequestTab: (typeof import("./components/graphql/RequestTab.vue"))["default"]
|
||||
GraphqlResponse: (typeof import("./components/graphql/Response.vue"))["default"]
|
||||
GraphqlSidebar: (typeof import("./components/graphql/Sidebar.vue"))["default"]
|
||||
GraphqlSubscriptionLog: (typeof import("./components/graphql/SubscriptionLog.vue"))["default"]
|
||||
GraphqlTabHead: (typeof import("./components/graphql/TabHead.vue"))["default"]
|
||||
GraphqlType: (typeof import("./components/graphql/Type.vue"))["default"]
|
||||
GraphqlTypeLink: (typeof import("./components/graphql/TypeLink.vue"))["default"]
|
||||
GraphqlVariable: (typeof import("./components/graphql/Variable.vue"))["default"]
|
||||
History: (typeof import("./components/history/index.vue"))["default"]
|
||||
HistoryGraphqlCard: (typeof import("./components/history/graphql/Card.vue"))["default"]
|
||||
HistoryRestCard: (typeof import("./components/history/rest/Card.vue"))["default"]
|
||||
HoppButtonPrimary: (typeof import("@hoppscotch/ui"))["HoppButtonPrimary"]
|
||||
HoppButtonSecondary: (typeof import("@hoppscotch/ui"))["HoppButtonSecondary"]
|
||||
HoppSmartAnchor: (typeof import("@hoppscotch/ui"))["HoppSmartAnchor"]
|
||||
HoppSmartCheckbox: (typeof import("@hoppscotch/ui"))["HoppSmartCheckbox"]
|
||||
HoppSmartConfirmModal: (typeof import("@hoppscotch/ui"))["HoppSmartConfirmModal"]
|
||||
HoppSmartExpand: (typeof import("@hoppscotch/ui"))["HoppSmartExpand"]
|
||||
HoppSmartFileChip: (typeof import("@hoppscotch/ui"))["HoppSmartFileChip"]
|
||||
HoppSmartInput: (typeof import("@hoppscotch/ui"))["HoppSmartInput"]
|
||||
HoppSmartIntersection: (typeof import("@hoppscotch/ui"))["HoppSmartIntersection"]
|
||||
HoppSmartItem: (typeof import("@hoppscotch/ui"))["HoppSmartItem"]
|
||||
HoppSmartLink: (typeof import("@hoppscotch/ui"))["HoppSmartLink"]
|
||||
HoppSmartModal: (typeof import("@hoppscotch/ui"))["HoppSmartModal"]
|
||||
HoppSmartPicture: (typeof import("@hoppscotch/ui"))["HoppSmartPicture"]
|
||||
HoppSmartPlaceholder: (typeof import("@hoppscotch/ui"))["HoppSmartPlaceholder"]
|
||||
HoppSmartProgressRing: (typeof import("@hoppscotch/ui"))["HoppSmartProgressRing"]
|
||||
HoppSmartRadio: (typeof import("@hoppscotch/ui"))["HoppSmartRadio"]
|
||||
HoppSmartRadioGroup: (typeof import("@hoppscotch/ui"))["HoppSmartRadioGroup"]
|
||||
HoppSmartSelectWrapper: (typeof import("@hoppscotch/ui"))["HoppSmartSelectWrapper"]
|
||||
HoppSmartSlideOver: (typeof import("@hoppscotch/ui"))["HoppSmartSlideOver"]
|
||||
HoppSmartSpinner: (typeof import("@hoppscotch/ui"))["HoppSmartSpinner"]
|
||||
HoppSmartTab: (typeof import("@hoppscotch/ui"))["HoppSmartTab"]
|
||||
HoppSmartTabs: (typeof import("@hoppscotch/ui"))["HoppSmartTabs"]
|
||||
HoppSmartToggle: (typeof import("@hoppscotch/ui"))["HoppSmartToggle"]
|
||||
HoppSmartTree: (typeof import("@hoppscotch/ui"))["HoppSmartTree"]
|
||||
HoppSmartWindow: (typeof import("@hoppscotch/ui"))["HoppSmartWindow"]
|
||||
HoppSmartWindows: (typeof import("@hoppscotch/ui"))["HoppSmartWindows"]
|
||||
HttpAuthorization: (typeof import("./components/http/Authorization.vue"))["default"]
|
||||
HttpAuthorizationApiKey: (typeof import("./components/http/authorization/ApiKey.vue"))["default"]
|
||||
HttpAuthorizationBasic: (typeof import("./components/http/authorization/Basic.vue"))["default"]
|
||||
HttpBody: (typeof import("./components/http/Body.vue"))["default"]
|
||||
HttpBodyParameters: (typeof import("./components/http/BodyParameters.vue"))["default"]
|
||||
HttpCodegenModal: (typeof import("./components/http/CodegenModal.vue"))["default"]
|
||||
HttpHeaders: (typeof import("./components/http/Headers.vue"))["default"]
|
||||
HttpImportCurl: (typeof import("./components/http/ImportCurl.vue"))["default"]
|
||||
HttpOAuth2Authorization: (typeof import("./components/http/OAuth2Authorization.vue"))["default"]
|
||||
HttpParameters: (typeof import("./components/http/Parameters.vue"))["default"]
|
||||
HttpPreRequestScript: (typeof import("./components/http/PreRequestScript.vue"))["default"]
|
||||
HttpRawBody: (typeof import("./components/http/RawBody.vue"))["default"]
|
||||
HttpReqChangeConfirmModal: (typeof import("./components/http/ReqChangeConfirmModal.vue"))["default"]
|
||||
HttpRequest: (typeof import("./components/http/Request.vue"))["default"]
|
||||
HttpRequestOptions: (typeof import("./components/http/RequestOptions.vue"))["default"]
|
||||
HttpRequestTab: (typeof import("./components/http/RequestTab.vue"))["default"]
|
||||
HttpResponse: (typeof import("./components/http/Response.vue"))["default"]
|
||||
HttpResponseMeta: (typeof import("./components/http/ResponseMeta.vue"))["default"]
|
||||
HttpSidebar: (typeof import("./components/http/Sidebar.vue"))["default"]
|
||||
HttpTabHead: (typeof import("./components/http/TabHead.vue"))["default"]
|
||||
HttpTestResult: (typeof import("./components/http/TestResult.vue"))["default"]
|
||||
HttpTestResultEntry: (typeof import("./components/http/TestResultEntry.vue"))["default"]
|
||||
HttpTestResultEnv: (typeof import("./components/http/TestResultEnv.vue"))["default"]
|
||||
HttpTestResultReport: (typeof import("./components/http/TestResultReport.vue"))["default"]
|
||||
HttpTests: (typeof import("./components/http/Tests.vue"))["default"]
|
||||
HttpURLEncodedParams: (typeof import("./components/http/URLEncodedParams.vue"))["default"]
|
||||
IconLucideActivity: (typeof import("~icons/lucide/activity"))["default"]
|
||||
IconLucideAlertTriangle: (typeof import("~icons/lucide/alert-triangle"))["default"]
|
||||
IconLucideArrowLeft: (typeof import("~icons/lucide/arrow-left"))["default"]
|
||||
IconLucideArrowUpRight: (typeof import("~icons/lucide/arrow-up-right"))["default"]
|
||||
AppActionHandler: typeof import('./components/app/ActionHandler.vue')['default']
|
||||
AppBanner: typeof import('./components/app/Banner.vue')['default']
|
||||
AppContextMenu: typeof import('./components/app/ContextMenu.vue')['default']
|
||||
AppDeveloperOptions: typeof import('./components/app/DeveloperOptions.vue')['default']
|
||||
AppFooter: typeof import('./components/app/Footer.vue')['default']
|
||||
AppGitHubStarButton: typeof import('./components/app/GitHubStarButton.vue')['default']
|
||||
AppHeader: typeof import('./components/app/Header.vue')['default']
|
||||
AppInspection: typeof import('./components/app/Inspection.vue')['default']
|
||||
AppInterceptor: typeof import('./components/app/Interceptor.vue')['default']
|
||||
AppLogo: typeof import('./components/app/Logo.vue')['default']
|
||||
AppOptions: typeof import('./components/app/Options.vue')['default']
|
||||
AppPaneLayout: typeof import('./components/app/PaneLayout.vue')['default']
|
||||
AppShare: typeof import('./components/app/Share.vue')['default']
|
||||
AppShortcuts: typeof import('./components/app/Shortcuts.vue')['default']
|
||||
AppShortcutsEntry: typeof import('./components/app/ShortcutsEntry.vue')['default']
|
||||
AppShortcutsPrompt: typeof import('./components/app/ShortcutsPrompt.vue')['default']
|
||||
AppSidenav: typeof import('./components/app/Sidenav.vue')['default']
|
||||
AppSpotlight: typeof import('./components/app/spotlight/index.vue')['default']
|
||||
AppSpotlightEntry: typeof import('./components/app/spotlight/Entry.vue')['default']
|
||||
AppSpotlightEntryGQLHistory: typeof import('./components/app/spotlight/entry/GQLHistory.vue')['default']
|
||||
AppSpotlightEntryGQLRequest: typeof import('./components/app/spotlight/entry/GQLRequest.vue')['default']
|
||||
AppSpotlightEntryIconSelected: typeof import('./components/app/spotlight/entry/IconSelected.vue')['default']
|
||||
AppSpotlightEntryRESTHistory: typeof import('./components/app/spotlight/entry/RESTHistory.vue')['default']
|
||||
AppSpotlightEntryRESTRequest: typeof import('./components/app/spotlight/entry/RESTRequest.vue')['default']
|
||||
AppSpotlightEntryRESTTeamRequestEntry: typeof import('./components/app/spotlight/entry/RESTTeamRequestEntry.vue')['default']
|
||||
AppSpotlightSearch: typeof import('./components/app/SpotlightSearch.vue')['default']
|
||||
AppSupport: typeof import('./components/app/Support.vue')['default']
|
||||
Collections: typeof import('./components/collections/index.vue')['default']
|
||||
CollectionsAdd: typeof import('./components/collections/Add.vue')['default']
|
||||
CollectionsAddFolder: typeof import('./components/collections/AddFolder.vue')['default']
|
||||
CollectionsAddRequest: typeof import('./components/collections/AddRequest.vue')['default']
|
||||
CollectionsCollection: typeof import('./components/collections/Collection.vue')['default']
|
||||
CollectionsEdit: typeof import('./components/collections/Edit.vue')['default']
|
||||
CollectionsEditFolder: typeof import('./components/collections/EditFolder.vue')['default']
|
||||
CollectionsEditRequest: typeof import('./components/collections/EditRequest.vue')['default']
|
||||
CollectionsGraphql: typeof import('./components/collections/graphql/index.vue')['default']
|
||||
CollectionsGraphqlAdd: typeof import('./components/collections/graphql/Add.vue')['default']
|
||||
CollectionsGraphqlAddFolder: typeof import('./components/collections/graphql/AddFolder.vue')['default']
|
||||
CollectionsGraphqlAddRequest: typeof import('./components/collections/graphql/AddRequest.vue')['default']
|
||||
CollectionsGraphqlCollection: typeof import('./components/collections/graphql/Collection.vue')['default']
|
||||
CollectionsGraphqlEdit: typeof import('./components/collections/graphql/Edit.vue')['default']
|
||||
CollectionsGraphqlEditFolder: typeof import('./components/collections/graphql/EditFolder.vue')['default']
|
||||
CollectionsGraphqlEditRequest: typeof import('./components/collections/graphql/EditRequest.vue')['default']
|
||||
CollectionsGraphqlFolder: typeof import('./components/collections/graphql/Folder.vue')['default']
|
||||
CollectionsGraphqlImportExport: typeof import('./components/collections/graphql/ImportExport.vue')['default']
|
||||
CollectionsGraphqlRequest: typeof import('./components/collections/graphql/Request.vue')['default']
|
||||
CollectionsImportExport: typeof import('./components/collections/ImportExport.vue')['default']
|
||||
CollectionsMyCollections: typeof import('./components/collections/MyCollections.vue')['default']
|
||||
CollectionsProperties: typeof import('./components/collections/Properties.vue')['default']
|
||||
CollectionsRequest: typeof import('./components/collections/Request.vue')['default']
|
||||
CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
|
||||
CollectionsTeamCollections: typeof import('./components/collections/TeamCollections.vue')['default']
|
||||
CookiesAllModal: typeof import('./components/cookies/AllModal.vue')['default']
|
||||
CookiesEditCookie: typeof import('./components/cookies/EditCookie.vue')['default']
|
||||
Embeds: typeof import('./components/embeds/index.vue')['default']
|
||||
Environments: typeof import('./components/environments/index.vue')['default']
|
||||
EnvironmentsAdd: typeof import('./components/environments/Add.vue')['default']
|
||||
EnvironmentsImportExport: typeof import('./components/environments/ImportExport.vue')['default']
|
||||
EnvironmentsMy: typeof import('./components/environments/my/index.vue')['default']
|
||||
EnvironmentsMyDetails: typeof import('./components/environments/my/Details.vue')['default']
|
||||
EnvironmentsMyEnvironment: typeof import('./components/environments/my/Environment.vue')['default']
|
||||
EnvironmentsSelector: typeof import('./components/environments/Selector.vue')['default']
|
||||
EnvironmentsTeams: typeof import('./components/environments/teams/index.vue')['default']
|
||||
EnvironmentsTeamsDetails: typeof import('./components/environments/teams/Details.vue')['default']
|
||||
EnvironmentsTeamsEnvironment: typeof import('./components/environments/teams/Environment.vue')['default']
|
||||
FirebaseLogin: typeof import('./components/firebase/Login.vue')['default']
|
||||
FirebaseLogout: typeof import('./components/firebase/Logout.vue')['default']
|
||||
GraphqlAuthorization: typeof import('./components/graphql/Authorization.vue')['default']
|
||||
GraphqlField: typeof import('./components/graphql/Field.vue')['default']
|
||||
GraphqlHeaders: typeof import('./components/graphql/Headers.vue')['default']
|
||||
GraphqlQuery: typeof import('./components/graphql/Query.vue')['default']
|
||||
GraphqlRequest: typeof import('./components/graphql/Request.vue')['default']
|
||||
GraphqlRequestOptions: typeof import('./components/graphql/RequestOptions.vue')['default']
|
||||
GraphqlRequestTab: typeof import('./components/graphql/RequestTab.vue')['default']
|
||||
GraphqlResponse: typeof import('./components/graphql/Response.vue')['default']
|
||||
GraphqlSidebar: typeof import('./components/graphql/Sidebar.vue')['default']
|
||||
GraphqlSubscriptionLog: typeof import('./components/graphql/SubscriptionLog.vue')['default']
|
||||
GraphqlTabHead: typeof import('./components/graphql/TabHead.vue')['default']
|
||||
GraphqlType: typeof import('./components/graphql/Type.vue')['default']
|
||||
GraphqlTypeLink: typeof import('./components/graphql/TypeLink.vue')['default']
|
||||
GraphqlVariable: typeof import('./components/graphql/Variable.vue')['default']
|
||||
History: typeof import('./components/history/index.vue')['default']
|
||||
HistoryGraphqlCard: typeof import('./components/history/graphql/Card.vue')['default']
|
||||
HistoryRestCard: typeof import('./components/history/rest/Card.vue')['default']
|
||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
||||
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox']
|
||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||
HoppSmartExpand: typeof import('@hoppscotch/ui')['HoppSmartExpand']
|
||||
HoppSmartFileChip: typeof import('@hoppscotch/ui')['HoppSmartFileChip']
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection']
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||
HoppSmartPlaceholder: typeof import('@hoppscotch/ui')['HoppSmartPlaceholder']
|
||||
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
|
||||
HoppSmartRadio: typeof import('@hoppscotch/ui')['HoppSmartRadio']
|
||||
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
|
||||
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
||||
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
|
||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
|
||||
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
||||
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
||||
HoppSmartTree: typeof import('@hoppscotch/ui')['HoppSmartTree']
|
||||
HoppSmartWindow: typeof import('@hoppscotch/ui')['HoppSmartWindow']
|
||||
HoppSmartWindows: typeof import('@hoppscotch/ui')['HoppSmartWindows']
|
||||
HttpAuthorization: typeof import('./components/http/Authorization.vue')['default']
|
||||
HttpAuthorizationApiKey: typeof import('./components/http/authorization/ApiKey.vue')['default']
|
||||
HttpAuthorizationBasic: typeof import('./components/http/authorization/Basic.vue')['default']
|
||||
HttpBody: typeof import('./components/http/Body.vue')['default']
|
||||
HttpBodyParameters: typeof import('./components/http/BodyParameters.vue')['default']
|
||||
HttpCodegenModal: typeof import('./components/http/CodegenModal.vue')['default']
|
||||
HttpHeaders: typeof import('./components/http/Headers.vue')['default']
|
||||
HttpImportCurl: typeof import('./components/http/ImportCurl.vue')['default']
|
||||
HttpOAuth2Authorization: typeof import('./components/http/OAuth2Authorization.vue')['default']
|
||||
HttpParameters: typeof import('./components/http/Parameters.vue')['default']
|
||||
HttpPreRequestScript: typeof import('./components/http/PreRequestScript.vue')['default']
|
||||
HttpRawBody: typeof import('./components/http/RawBody.vue')['default']
|
||||
HttpReqChangeConfirmModal: typeof import('./components/http/ReqChangeConfirmModal.vue')['default']
|
||||
HttpRequest: typeof import('./components/http/Request.vue')['default']
|
||||
HttpRequestOptions: typeof import('./components/http/RequestOptions.vue')['default']
|
||||
HttpRequestTab: typeof import('./components/http/RequestTab.vue')['default']
|
||||
HttpRequestVariables: typeof import('./components/http/RequestVariables.vue')['default']
|
||||
HttpResponse: typeof import('./components/http/Response.vue')['default']
|
||||
HttpResponseMeta: typeof import('./components/http/ResponseMeta.vue')['default']
|
||||
HttpSidebar: typeof import('./components/http/Sidebar.vue')['default']
|
||||
HttpTabHead: typeof import('./components/http/TabHead.vue')['default']
|
||||
HttpTestResult: typeof import('./components/http/TestResult.vue')['default']
|
||||
HttpTestResultEntry: typeof import('./components/http/TestResultEntry.vue')['default']
|
||||
HttpTestResultEnv: typeof import('./components/http/TestResultEnv.vue')['default']
|
||||
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
|
||||
HttpTests: typeof import('./components/http/Tests.vue')['default']
|
||||
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
|
||||
IconLucideActivity: typeof import('~icons/lucide/activity')['default']
|
||||
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
|
||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
|
||||
IconLucideBrush: (typeof import("~icons/lucide/brush"))["default"]
|
||||
IconLucideCheckCircle: (typeof import("~icons/lucide/check-circle"))["default"]
|
||||
IconLucideChevronRight: (typeof import("~icons/lucide/chevron-right"))["default"]
|
||||
IconLucideGlobe: (typeof import("~icons/lucide/globe"))["default"]
|
||||
IconLucideHelpCircle: (typeof import("~icons/lucide/help-circle"))["default"]
|
||||
IconLucideInbox: (typeof import("~icons/lucide/inbox"))["default"]
|
||||
IconLucideInfo: (typeof import("~icons/lucide/info"))["default"]
|
||||
IconLucideLayers: (typeof import("~icons/lucide/layers"))["default"]
|
||||
IconLucideListEnd: (typeof import("~icons/lucide/list-end"))["default"]
|
||||
IconLucideMinus: (typeof import("~icons/lucide/minus"))["default"]
|
||||
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
||||
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
|
||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||
IconLucideInfo: typeof import('~icons/lucide/info')['default']
|
||||
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
|
||||
IconLucideListEnd: typeof import('~icons/lucide/list-end')['default']
|
||||
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
|
||||
IconLucideRss: (typeof import("~icons/lucide/rss"))["default"]
|
||||
IconLucideSearch: (typeof import("~icons/lucide/search"))["default"]
|
||||
IconLucideUsers: (typeof import("~icons/lucide/users"))["default"]
|
||||
IconLucideX: (typeof import("~icons/lucide/x"))["default"]
|
||||
ImportExportBase: (typeof import("./components/importExport/Base.vue"))["default"]
|
||||
ImportExportImportExportList: (typeof import("./components/importExport/ImportExportList.vue"))["default"]
|
||||
ImportExportImportExportSourcesList: (typeof import("./components/importExport/ImportExportSourcesList.vue"))["default"]
|
||||
ImportExportImportExportStepsFileImport: (typeof import("./components/importExport/ImportExportSteps/FileImport.vue"))["default"]
|
||||
ImportExportImportExportStepsMyCollectionImport: (typeof import("./components/importExport/ImportExportSteps/MyCollectionImport.vue"))["default"]
|
||||
ImportExportImportExportStepsUrlImport: (typeof import("./components/importExport/ImportExportSteps/UrlImport.vue"))["default"]
|
||||
InterceptorsErrorPlaceholder: (typeof import("./components/interceptors/ErrorPlaceholder.vue"))["default"]
|
||||
InterceptorsExtensionSubtitle: (typeof import("./components/interceptors/ExtensionSubtitle.vue"))["default"]
|
||||
LensesHeadersRenderer: (typeof import("./components/lenses/HeadersRenderer.vue"))["default"]
|
||||
LensesHeadersRendererEntry: (typeof import("./components/lenses/HeadersRendererEntry.vue"))["default"]
|
||||
LensesRenderersAudioLensRenderer: (typeof import("./components/lenses/renderers/AudioLensRenderer.vue"))["default"]
|
||||
LensesRenderersHTMLLensRenderer: (typeof import("./components/lenses/renderers/HTMLLensRenderer.vue"))["default"]
|
||||
LensesRenderersImageLensRenderer: (typeof import("./components/lenses/renderers/ImageLensRenderer.vue"))["default"]
|
||||
LensesRenderersJSONLensRenderer: (typeof import("./components/lenses/renderers/JSONLensRenderer.vue"))["default"]
|
||||
LensesRenderersPDFLensRenderer: (typeof import("./components/lenses/renderers/PDFLensRenderer.vue"))["default"]
|
||||
LensesRenderersRawLensRenderer: (typeof import("./components/lenses/renderers/RawLensRenderer.vue"))["default"]
|
||||
LensesRenderersVideoLensRenderer: (typeof import("./components/lenses/renderers/VideoLensRenderer.vue"))["default"]
|
||||
LensesRenderersXMLLensRenderer: (typeof import("./components/lenses/renderers/XMLLensRenderer.vue"))["default"]
|
||||
LensesResponseBodyRenderer: (typeof import("./components/lenses/ResponseBodyRenderer.vue"))["default"]
|
||||
ProfileUserDelete: (typeof import("./components/profile/UserDelete.vue"))["default"]
|
||||
RealtimeCommunication: (typeof import("./components/realtime/Communication.vue"))["default"]
|
||||
RealtimeConnectionConfig: (typeof import("./components/realtime/ConnectionConfig.vue"))["default"]
|
||||
RealtimeLog: (typeof import("./components/realtime/Log.vue"))["default"]
|
||||
RealtimeLogEntry: (typeof import("./components/realtime/LogEntry.vue"))["default"]
|
||||
RealtimeSubscription: (typeof import("./components/realtime/Subscription.vue"))["default"]
|
||||
SettingsExtension: (typeof import("./components/settings/Extension.vue"))["default"]
|
||||
SettingsProxy: (typeof import("./components/settings/Proxy.vue"))["default"]
|
||||
Share: (typeof import("./components/share/index.vue"))["default"]
|
||||
ShareCreateModal: (typeof import("./components/share/CreateModal.vue"))["default"]
|
||||
ShareCustomizeModal: (typeof import("./components/share/CustomizeModal.vue"))["default"]
|
||||
ShareModal: (typeof import("./components/share/Modal.vue"))["default"]
|
||||
ShareRequest: (typeof import("./components/share/Request.vue"))["default"]
|
||||
ShareTemplatesButton: (typeof import("./components/share/templates/Button.vue"))["default"]
|
||||
ShareTemplatesEmbeds: (typeof import("./components/share/templates/Embeds.vue"))["default"]
|
||||
ShareTemplatesLink: (typeof import("./components/share/templates/Link.vue"))["default"]
|
||||
SmartAccentModePicker: (typeof import("./components/smart/AccentModePicker.vue"))["default"]
|
||||
SmartChangeLanguage: (typeof import("./components/smart/ChangeLanguage.vue"))["default"]
|
||||
SmartColorModePicker: (typeof import("./components/smart/ColorModePicker.vue"))["default"]
|
||||
SmartEnvInput: (typeof import("./components/smart/EnvInput.vue"))["default"]
|
||||
TabPrimary: (typeof import("./components/tab/Primary.vue"))["default"]
|
||||
TabSecondary: (typeof import("./components/tab/Secondary.vue"))["default"]
|
||||
Teams: (typeof import("./components/teams/index.vue"))["default"]
|
||||
TeamsAdd: (typeof import("./components/teams/Add.vue"))["default"]
|
||||
TeamsEdit: (typeof import("./components/teams/Edit.vue"))["default"]
|
||||
TeamsInvite: (typeof import("./components/teams/Invite.vue"))["default"]
|
||||
TeamsMemberStack: (typeof import("./components/teams/MemberStack.vue"))["default"]
|
||||
TeamsModal: (typeof import("./components/teams/Modal.vue"))["default"]
|
||||
TeamsTeam: (typeof import("./components/teams/Team.vue"))["default"]
|
||||
Tippy: (typeof import("vue-tippy"))["Tippy"]
|
||||
WorkspaceCurrent: (typeof import("./components/workspace/Current.vue"))["default"]
|
||||
WorkspaceSelector: (typeof import("./components/workspace/Selector.vue"))["default"]
|
||||
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
||||
IconLucideUsers: typeof import('~icons/lucide/users')['default']
|
||||
IconLucideX: typeof import('~icons/lucide/x')['default']
|
||||
ImportExportBase: typeof import('./components/importExport/Base.vue')['default']
|
||||
ImportExportImportExportList: typeof import('./components/importExport/ImportExportList.vue')['default']
|
||||
ImportExportImportExportSourcesList: typeof import('./components/importExport/ImportExportSourcesList.vue')['default']
|
||||
ImportExportImportExportStepsFileImport: typeof import('./components/importExport/ImportExportSteps/FileImport.vue')['default']
|
||||
ImportExportImportExportStepsMyCollectionImport: typeof import('./components/importExport/ImportExportSteps/MyCollectionImport.vue')['default']
|
||||
ImportExportImportExportStepsUrlImport: typeof import('./components/importExport/ImportExportSteps/UrlImport.vue')['default']
|
||||
InterceptorsErrorPlaceholder: typeof import('./components/interceptors/ErrorPlaceholder.vue')['default']
|
||||
InterceptorsExtensionSubtitle: typeof import('./components/interceptors/ExtensionSubtitle.vue')['default']
|
||||
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
|
||||
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
|
||||
LensesRenderersAudioLensRenderer: typeof import('./components/lenses/renderers/AudioLensRenderer.vue')['default']
|
||||
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
|
||||
LensesRenderersImageLensRenderer: typeof import('./components/lenses/renderers/ImageLensRenderer.vue')['default']
|
||||
LensesRenderersJSONLensRenderer: typeof import('./components/lenses/renderers/JSONLensRenderer.vue')['default']
|
||||
LensesRenderersPDFLensRenderer: typeof import('./components/lenses/renderers/PDFLensRenderer.vue')['default']
|
||||
LensesRenderersRawLensRenderer: typeof import('./components/lenses/renderers/RawLensRenderer.vue')['default']
|
||||
LensesRenderersVideoLensRenderer: typeof import('./components/lenses/renderers/VideoLensRenderer.vue')['default']
|
||||
LensesRenderersXMLLensRenderer: typeof import('./components/lenses/renderers/XMLLensRenderer.vue')['default']
|
||||
LensesResponseBodyRenderer: typeof import('./components/lenses/ResponseBodyRenderer.vue')['default']
|
||||
NewCollections: typeof import('./components/new-collections/index.vue')['default']
|
||||
NewCollectionsRest: typeof import('./components/new-collections/rest/index.vue')['default']
|
||||
NewCollectionsRestCollection: typeof import('./components/new-collections/rest/Collection.vue')['default']
|
||||
NewCollectionsRestRequest: typeof import('./components/new-collections/rest/Request.vue')['default']
|
||||
ProfileUserDelete: typeof import('./components/profile/UserDelete.vue')['default']
|
||||
RealtimeCommunication: typeof import('./components/realtime/Communication.vue')['default']
|
||||
RealtimeConnectionConfig: typeof import('./components/realtime/ConnectionConfig.vue')['default']
|
||||
RealtimeLog: typeof import('./components/realtime/Log.vue')['default']
|
||||
RealtimeLogEntry: typeof import('./components/realtime/LogEntry.vue')['default']
|
||||
RealtimeSubscription: typeof import('./components/realtime/Subscription.vue')['default']
|
||||
SettingsExtension: typeof import('./components/settings/Extension.vue')['default']
|
||||
SettingsProxy: typeof import('./components/settings/Proxy.vue')['default']
|
||||
Share: typeof import('./components/share/index.vue')['default']
|
||||
ShareCreateModal: typeof import('./components/share/CreateModal.vue')['default']
|
||||
ShareCustomizeModal: typeof import('./components/share/CustomizeModal.vue')['default']
|
||||
ShareModal: typeof import('./components/share/Modal.vue')['default']
|
||||
ShareRequest: typeof import('./components/share/Request.vue')['default']
|
||||
ShareTemplatesButton: typeof import('./components/share/templates/Button.vue')['default']
|
||||
ShareTemplatesEmbeds: typeof import('./components/share/templates/Embeds.vue')['default']
|
||||
ShareTemplatesLink: typeof import('./components/share/templates/Link.vue')['default']
|
||||
SmartAccentModePicker: typeof import('./components/smart/AccentModePicker.vue')['default']
|
||||
SmartChangeLanguage: typeof import('./components/smart/ChangeLanguage.vue')['default']
|
||||
SmartColorModePicker: typeof import('./components/smart/ColorModePicker.vue')['default']
|
||||
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
||||
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
||||
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
||||
Teams: typeof import('./components/teams/index.vue')['default']
|
||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||
TeamsEdit: typeof import('./components/teams/Edit.vue')['default']
|
||||
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
||||
TeamsMemberStack: typeof import('./components/teams/MemberStack.vue')['default']
|
||||
TeamsModal: typeof import('./components/teams/Modal.vue')['default']
|
||||
TeamsTeam: typeof import('./components/teams/Team.vue')['default']
|
||||
Tippy: typeof import('vue-tippy')['Tippy']
|
||||
WorkspaceCurrent: typeof import('./components/workspace/Current.vue')['default']
|
||||
WorkspacePersonalWorkspaceSelector: typeof import('./components/workspace/PersonalWorkspaceSelector.vue')['default']
|
||||
WorkspaceSelector: typeof import('./components/workspace/Selector.vue')['default']
|
||||
WorkspaceTestWorkspaceSelector: typeof import('./components/workspace/TestWorkspaceSelector.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,28 +2,26 @@
|
||||
<div>
|
||||
<header
|
||||
ref="headerRef"
|
||||
class="grid grid-cols-5 grid-rows-1 gap-2 overflow-x-auto overflow-y-hidden p-2"
|
||||
class="flex flex-1 flex-shrink-0 items-center justify-between space-x-2 overflow-x-auto overflow-y-hidden px-2 py-2"
|
||||
@mousedown.prevent="platform.ui?.appHeader?.onHeaderAreaClick?.()"
|
||||
>
|
||||
<div
|
||||
class="col-span-2 flex items-center justify-between space-x-2"
|
||||
class="inline-flex flex-1 items-center justify-start space-x-2"
|
||||
:style="{
|
||||
paddingTop: platform.ui?.appHeader?.paddingTop?.value,
|
||||
paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
|
||||
}"
|
||||
>
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
:label="t('app.name')"
|
||||
to="/"
|
||||
/>
|
||||
</div>
|
||||
<HoppButtonSecondary
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
:label="t('app.name')"
|
||||
to="/"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-1 flex items-center justify-between space-x-2">
|
||||
<div class="inline-flex flex-1 items-center justify-center space-x-2">
|
||||
<button
|
||||
class="flex h-full flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
||||
@click="invokeAction('modals.search.toggle', undefined, 'mouseclick')"
|
||||
class="flex max-w-[15rem] flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 py-1 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
|
||||
@click="invokeAction('modals.search.toggle')"
|
||||
>
|
||||
<span class="inline-flex flex-1 items-center">
|
||||
<icon-lucide-search class="svg-icons mr-2" />
|
||||
@@ -34,188 +32,192 @@
|
||||
<kbd class="shortcut-key">K</kbd>
|
||||
</span>
|
||||
</button>
|
||||
<HoppButtonSecondary
|
||||
v-if="showInstallButton"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('header.install_pwa')"
|
||||
:icon="IconDownload"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="installPWA()"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||
:title="`${
|
||||
mdAndLarger ? t('support.title') : t('app.options')
|
||||
} <kbd>?</kbd>`"
|
||||
:icon="IconLifeBuoy"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="invokeAction('modals.support.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-2 flex items-center justify-between space-x-2">
|
||||
<div class="flex">
|
||||
<div class="inline-flex flex-1 items-center justify-end space-x-2">
|
||||
<div
|
||||
v-if="currentUser === null"
|
||||
class="inline-flex items-center space-x-2"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-if="showInstallButton"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('header.install_pwa')"
|
||||
:icon="IconDownload"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="installPWA()"
|
||||
:icon="IconUploadCloud"
|
||||
:label="t('header.save_workspace')"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 hidden border border-green-600/25 bg-green-500/[.15] !text-green-500 hover:border-green-800/50 hover:bg-green-400/10 focus-visible:border-green-800/50 focus-visible:bg-green-400/10 md:flex"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip', allowHTML: true }"
|
||||
:title="`${
|
||||
mdAndLarger ? t('support.title') : t('app.options')
|
||||
} <kbd>?</kbd>`"
|
||||
:icon="IconLifeBuoy"
|
||||
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
@click="invokeAction('modals.support.toggle')"
|
||||
<HoppButtonPrimary
|
||||
:label="t('header.login')"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div v-else class="inline-flex items-center space-x-2">
|
||||
<TeamsMemberStack
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam.teamMembers.length > 1
|
||||
"
|
||||
:team-members="selectedTeam.teamMembers"
|
||||
show-count
|
||||
class="mx-2"
|
||||
@handle-click="handleTeamEdit()"
|
||||
/>
|
||||
<div
|
||||
v-if="currentUser === null"
|
||||
class="inline-flex items-center space-x-2"
|
||||
class="flex divide-x divide-green-600/25 rounded border border-green-600/25 bg-green-500/[.15] focus-within:divide-green-800/50 focus-within:border-green-800/50 focus-within:bg-green-400/10 hover:divide-green-800/50 hover:border-green-800/50 hover:bg-green-400/10"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
:icon="IconUploadCloud"
|
||||
:label="t('header.save_workspace')"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 hidden h-8 border border-emerald-600/25 bg-emerald-500/10 !text-emerald-500 hover:border-emerald-600/20 hover:bg-emerald-600/20 focus-visible:border-emerald-600/20 focus-visible:bg-emerald-600/20 md:flex"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.invite_tooltip')"
|
||||
:icon="IconUserPlus"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
||||
@click="handleInvite()"
|
||||
/>
|
||||
<HoppButtonPrimary
|
||||
:label="t('header.login')"
|
||||
class="h-8"
|
||||
@click="invokeAction('modals.login.toggle')"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="inline-flex items-center space-x-2">
|
||||
<TeamsMemberStack
|
||||
<HoppButtonSecondary
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam.teamMembers.length > 1
|
||||
selectedTeam?.myRole === 'OWNER'
|
||||
"
|
||||
:team-members="selectedTeam.teamMembers"
|
||||
show-count
|
||||
class="mx-2"
|
||||
@handle-click="handleTeamEdit()"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.edit')"
|
||||
:icon="IconSettings"
|
||||
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
|
||||
@click="handleTeamEdit()"
|
||||
/>
|
||||
<div
|
||||
class="flex h-8 divide-x divide-emerald-600/25 rounded border border-emerald-600/25 bg-emerald-500/10 focus-within:divide-emerald-600/20 focus-within:border-emerald-600/20 focus-within:bg-emerald-600/20 hover:divide-emerald-600/20 hover:border-emerald-600/20 hover:bg-emerald-600/20"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.invite_tooltip')"
|
||||
:icon="IconUserPlus"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||
@click="handleInvite()"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="
|
||||
workspace.type === 'team' &&
|
||||
selectedTeam &&
|
||||
selectedTeam?.myRole === 'OWNER'
|
||||
"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('team.edit')"
|
||||
:icon="IconSettings"
|
||||
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
|
||||
@click="handleTeamEdit()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => accountActions.focus()"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('workspace.change')"
|
||||
:label="mdAndLarger ? activeWorkspaceName : ``"
|
||||
:icon="activeWorkspaceIcon"
|
||||
class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 rounded border border-blue-600/25 bg-blue-500/[.15] py-[0.4375rem] pr-8 !text-blue-500 hover:border-blue-800/50 hover:bg-blue-400/10 focus-visible:border-blue-800/50 focus-visible:bg-blue-400/10"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="accountActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.escape="hide()"
|
||||
@click="hide()"
|
||||
>
|
||||
<WorkspaceSelector />
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
<span class="px-2">
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => accountActions.focus()"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<HoppSmartSelectWrapper
|
||||
class="!text-blue-500 !focus-visible:text-blue-600 !hover:text-blue-600"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('workspace.change')"
|
||||
:label="mdAndLarger ? workspaceName : ``"
|
||||
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
|
||||
class="!focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
|
||||
/>
|
||||
</HoppSmartSelectWrapper>
|
||||
<HoppSmartPicture
|
||||
v-if="currentUser.photoURL"
|
||||
v-tippy="{
|
||||
theme: 'tooltip',
|
||||
}"
|
||||
:url="currentUser.photoURL"
|
||||
:alt="
|
||||
currentUser.displayName ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
:title="
|
||||
currentUser.displayName ||
|
||||
currentUser.email ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
indicator
|
||||
:indicator-styles="
|
||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
||||
"
|
||||
/>
|
||||
<HoppSmartPicture
|
||||
v-else
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="
|
||||
currentUser.displayName ||
|
||||
currentUser.email ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
:initial="currentUser.displayName || currentUser.email"
|
||||
indicator
|
||||
:indicator-styles="
|
||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
||||
"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="accountActions"
|
||||
ref="tippyActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.p="profile.$el.click()"
|
||||
@keyup.s="settings.$el.click()"
|
||||
@keyup.l="logout.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
@click="hide()"
|
||||
>
|
||||
<WorkspaceSelector />
|
||||
<div class="flex flex-col px-2 text-tiny">
|
||||
<span class="inline-flex truncate font-semibold">
|
||||
{{
|
||||
currentUser.displayName ||
|
||||
t("profile.default_hopp_displayname")
|
||||
}}
|
||||
</span>
|
||||
<span class="inline-flex truncate text-secondaryLight">
|
||||
{{ currentUser.email }}
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
<HoppSmartItem
|
||||
ref="profile"
|
||||
to="/profile"
|
||||
:icon="IconUser"
|
||||
:label="t('navigation.profile')"
|
||||
:shortcut="['P']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="settings"
|
||||
to="/settings"
|
||||
:icon="IconSettings"
|
||||
:label="t('navigation.settings')"
|
||||
:shortcut="['S']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<FirebaseLogout
|
||||
ref="logout"
|
||||
:shortcut="['L']"
|
||||
@confirm-logout="hide()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
<span class="px-2">
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions.focus()"
|
||||
>
|
||||
<HoppSmartPicture
|
||||
v-tippy="{
|
||||
theme: 'tooltip',
|
||||
}"
|
||||
:name="currentUser.uid"
|
||||
:title="
|
||||
currentUser.displayName ||
|
||||
currentUser.email ||
|
||||
t('profile.default_hopp_displayname')
|
||||
"
|
||||
indicator
|
||||
:indicator-styles="
|
||||
network.isOnline ? 'bg-green-500' : 'bg-red-500'
|
||||
"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.p="profile.$el.click()"
|
||||
@keyup.s="settings.$el.click()"
|
||||
@keyup.l="logout.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<div class="flex flex-col px-2">
|
||||
<span class="inline-flex truncate font-semibold">
|
||||
{{
|
||||
currentUser.displayName ||
|
||||
t("profile.default_hopp_displayname")
|
||||
}}
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex truncate text-secondaryLight text-tiny"
|
||||
>
|
||||
{{ currentUser.email }}
|
||||
</span>
|
||||
</div>
|
||||
<hr />
|
||||
<HoppSmartItem
|
||||
ref="profile"
|
||||
to="/profile"
|
||||
:icon="IconUser"
|
||||
:label="t('navigation.profile')"
|
||||
:shortcut="['P']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="settings"
|
||||
to="/settings"
|
||||
:icon="IconSettings"
|
||||
:label="t('navigation.settings')"
|
||||
:shortcut="['S']"
|
||||
@click="hide()"
|
||||
/>
|
||||
<FirebaseLogout
|
||||
ref="logout"
|
||||
:shortcut="['L']"
|
||||
@confirm-logout="hide()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<AppBanner
|
||||
v-if="bannerContent"
|
||||
:banner="bannerContent"
|
||||
@dismiss="dismissOfflineBanner"
|
||||
/>
|
||||
<AppBanner v-if="bannerContent" :banner="bannerContent" />
|
||||
<TeamsModal :show="showTeamsModal" @hide-modal="showTeamsModal = false" />
|
||||
<TeamsInvite
|
||||
v-if="workspace.type === 'team' && workspace.teamID"
|
||||
@@ -231,6 +233,7 @@
|
||||
@invite-team="inviteTeam(editingTeamName, editingTeamID)"
|
||||
@refetch-teams="refetchTeams"
|
||||
/>
|
||||
|
||||
<HoppSmartConfirmModal
|
||||
:show="confirmRemove"
|
||||
:title="t('confirm.remove_team')"
|
||||
@@ -244,30 +247,31 @@
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useReadonlyStream } from "@composables/stream"
|
||||
import { defineActionHandler, invokeAction } from "@helpers/actions"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { useService } from "dioc/vue"
|
||||
import { installPWA, pwaDefferedPrompt } from "@modules/pwa"
|
||||
import { breakpointsTailwind, useBreakpoints, useNetwork } from "@vueuse/core"
|
||||
import { useService } from "dioc/vue"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import { computed, reactive, ref, watch } from "vue"
|
||||
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { GetMyTeamsQuery, TeamMemberRole } from "~/helpers/backend/graphql"
|
||||
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
|
||||
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
||||
import { platform } from "~/platform"
|
||||
import {
|
||||
BANNER_PRIORITY_HIGH,
|
||||
BannerContent,
|
||||
BannerService,
|
||||
} from "~/services/banner.service"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import IconDownload from "~icons/lucide/download"
|
||||
import IconLifeBuoy from "~icons/lucide/life-buoy"
|
||||
import IconSettings from "~icons/lucide/settings"
|
||||
import IconUploadCloud from "~icons/lucide/upload-cloud"
|
||||
import IconUser from "~icons/lucide/user"
|
||||
import IconUserPlus from "~icons/lucide/user-plus"
|
||||
import IconUsers from "~icons/lucide/users"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
|
||||
import {
|
||||
BannerService,
|
||||
BannerContent,
|
||||
BANNER_PRIORITY_HIGH,
|
||||
} from "~/services/banner.service"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
@@ -290,11 +294,10 @@ const bannerContent = computed(() => banner.content.value?.content)
|
||||
let bannerID: number | null = null
|
||||
|
||||
const offlineBanner: BannerContent = {
|
||||
type: "warning",
|
||||
type: "info",
|
||||
text: (t) => t("helpers.offline"),
|
||||
alternateText: (t) => t("helpers.offline_short"),
|
||||
score: BANNER_PRIORITY_HIGH,
|
||||
dismissible: true,
|
||||
}
|
||||
|
||||
const network = reactive(useNetwork())
|
||||
@@ -311,8 +314,6 @@ watch(isOnline, () => {
|
||||
}
|
||||
})
|
||||
|
||||
const dismissOfflineBanner = () => banner.removeBanner(bannerID!)
|
||||
|
||||
const currentUser = useReadonlyStream(
|
||||
platform.auth.getProbableUserStream(),
|
||||
platform.auth.getProbableUser()
|
||||
@@ -330,12 +331,6 @@ const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
||||
|
||||
const workspace = workspaceService.currentWorkspace
|
||||
|
||||
const workspaceName = computed(() => {
|
||||
return workspace.value.type === "personal"
|
||||
? t("workspace.personal")
|
||||
: workspace.value.teamName
|
||||
})
|
||||
|
||||
const refetchTeams = () => {
|
||||
teamListAdapter.fetchList()
|
||||
}
|
||||
@@ -370,6 +365,23 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const newWorkspaceService = useService(NewWorkspaceService)
|
||||
|
||||
const activeWorkspaceName = computed(() => {
|
||||
const activeWorkspaceHandleRef =
|
||||
newWorkspaceService.activeWorkspaceHandle.value?.get()
|
||||
|
||||
if (activeWorkspaceHandleRef?.value.type === "ok") {
|
||||
return activeWorkspaceHandleRef.value.data.name
|
||||
}
|
||||
|
||||
return t("workspace.no_workspace")
|
||||
})
|
||||
|
||||
const activeWorkspaceIcon = computed(() => {
|
||||
return newWorkspaceService.activeWorkspaceDecor.value?.value.headerCurrentIcon
|
||||
})
|
||||
|
||||
const showModalInvite = ref(false)
|
||||
const showModalEdit = ref(false)
|
||||
|
||||
@@ -393,6 +405,8 @@ const inviteTeam = (team: { name: string }, teamID: string) => {
|
||||
|
||||
// Show the workspace selected team invite modal if the user is an owner of the team else show the default invite modal
|
||||
const handleInvite = () => {
|
||||
if (!currentUser.value) return invokeAction("modals.login.toggle")
|
||||
|
||||
if (
|
||||
workspace.value.type === "team" &&
|
||||
workspace.value.teamID &&
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div
|
||||
class="border-animation relative p-[1px] rounded flex-1 self-stretch overflow-hidden flex items-center justify-center"
|
||||
:class="{
|
||||
'before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:aspect-square before:w-full before:absolute before:bg-':
|
||||
!HAS_OPENED_SPOTLIGHT,
|
||||
}"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<button
|
||||
class="relative flex flex-1 cursor-text items-center justify-between self-stretch rounded bg-primaryDark px-2 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary overflow-hidden"
|
||||
@click="
|
||||
() => {
|
||||
invokeAction('modals.search.toggle', undefined, 'mouseclick')
|
||||
!HAS_OPENED_SPOTLIGHT && toggleSetting('HAS_OPENED_SPOTLIGHT')
|
||||
}
|
||||
"
|
||||
>
|
||||
<span class="inline-flex flex-1 items-center">
|
||||
<icon-lucide-search class="svg-icons mr-2" />
|
||||
<span v-if="!HAS_OPENED_SPOTLIGHT" class="flex flex-1">
|
||||
{{ t("spotlight.phrases.try") }}
|
||||
<TransitionGroup tag="div" name="list" class="ml-1 relative">
|
||||
<span
|
||||
v-for="(phrase, index) in phraseToShow"
|
||||
:key="phrase.text"
|
||||
:data-index="index"
|
||||
class="truncate"
|
||||
>
|
||||
"{{ t(phrase.text) }}"
|
||||
</span>
|
||||
</TransitionGroup>
|
||||
</span>
|
||||
<template v-else>
|
||||
{{ t("app.search") }}
|
||||
</template>
|
||||
</span>
|
||||
<span class="flex space-x-1">
|
||||
<kbd class="shortcut-key">{{ getPlatformSpecialKey() }}</kbd>
|
||||
<kbd class="shortcut-key">K</kbd>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed, ref } from "vue"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { useSetting } from "~/composables/settings"
|
||||
import { invokeAction } from "~/helpers/actions"
|
||||
import { getPlatformSpecialKey } from "~/helpers/platformutils"
|
||||
import { toggleSetting } from "~/newstore/settings"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const HAS_OPENED_SPOTLIGHT = useSetting("HAS_OPENED_SPOTLIGHT")
|
||||
|
||||
const phrases = ref([
|
||||
{ text: "spotlight.phrases.import_collections", show: true },
|
||||
{ text: "spotlight.phrases.create_environment", show: false },
|
||||
{ text: "spotlight.phrases.create_workspace", show: false },
|
||||
{ text: "spotlight.phrases.share_request", show: false },
|
||||
])
|
||||
|
||||
let intervalId: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
//cycle through the phrases
|
||||
const showNextPhrase = () => {
|
||||
let i = 0
|
||||
intervalId = setInterval(() => {
|
||||
phrases.value[i].show = false
|
||||
i++
|
||||
if (i >= phrases.value.length) {
|
||||
i = 0
|
||||
}
|
||||
phrases.value[i].show = true
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
const stopPhraseInterval = () => {
|
||||
if (intervalId) clearInterval(intervalId)
|
||||
}
|
||||
|
||||
const phraseToShow = computed(() => {
|
||||
return phrases.value.filter((phrase) => phrase.show)
|
||||
})
|
||||
|
||||
watch(
|
||||
HAS_OPENED_SPOTLIGHT,
|
||||
() => {
|
||||
!HAS_OPENED_SPOTLIGHT.value ? showNextPhrase() : stopPhraseInterval()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Transition Classes */
|
||||
.list-enter-active {
|
||||
transition: all 1s ease;
|
||||
}
|
||||
.list-leave-active {
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
.list-enter-from,
|
||||
.list-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
.list-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Conic gradient */
|
||||
.border-animation::before {
|
||||
background: conic-gradient(
|
||||
transparent 270deg,
|
||||
var(--accent-color),
|
||||
transparent
|
||||
);
|
||||
animation: rotate 4s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: translate(-50%, -50%) scale(1.4) rotate(0turn);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate(-50%, -50%) scale(1.4) rotate(1turn);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -30,9 +30,8 @@ import { defineStep } from "~/composables/step-components"
|
||||
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
||||
import { restCollections$ } from "~/newstore/collections"
|
||||
import MyCollectionImport from "~/components/importExport/ImportExportSteps/MyCollectionImport.vue"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconOpenAPI from "~icons/lucide/file"
|
||||
@@ -48,23 +47,23 @@ import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
||||
|
||||
import { platform } from "~/platform"
|
||||
|
||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
||||
import { myCollectionsExporter } from "~/helpers/import-export/export/myCollections"
|
||||
import { teamCollectionsExporter } from "~/helpers/import-export/export/teamCollections"
|
||||
|
||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||
import { useService } from "dioc/vue"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { TeamWorkspace } from "~/services/workspace.service"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
type CollectionType =
|
||||
| {
|
||||
type: "team-collections"
|
||||
selectedTeam: SelectedTeam
|
||||
selectedTeam: TeamWorkspace
|
||||
}
|
||||
| { type: "my-collections" }
|
||||
|
||||
@@ -86,15 +85,45 @@ const currentUser = useReadonlyStream(
|
||||
|
||||
const myCollections = useReadonlyStream(restCollections$, [])
|
||||
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
|
||||
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle
|
||||
|
||||
const showImportFailedError = () => {
|
||||
toast.error(t("import.failed"))
|
||||
}
|
||||
|
||||
const handleImportToStore = async (collections: HoppCollection[]) => {
|
||||
const importResult =
|
||||
props.collectionsType.type === "my-collections"
|
||||
? await importToPersonalWorkspace(collections)
|
||||
: await importToTeamsWorkspace(collections)
|
||||
if (props.collectionsType.type === "my-collections") {
|
||||
if (!activeWorkspaceHandle.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const collectionHandleResult = await workspaceService.importRESTCollections(
|
||||
activeWorkspaceHandle.value,
|
||||
collections
|
||||
)
|
||||
|
||||
if (E.isLeft(collectionHandleResult)) {
|
||||
// INVALID_WORKSPACE_HANDLE
|
||||
return toast.error(t("import.failed"))
|
||||
}
|
||||
|
||||
const resultHandle = collectionHandleResult.right
|
||||
|
||||
const requestHandleRef = resultHandle.get()
|
||||
|
||||
if (requestHandleRef.value.type === "invalid") {
|
||||
// WORKSPACE_INVALIDATED
|
||||
}
|
||||
|
||||
toast.success(t("state.file_imported"))
|
||||
emit("hide-modal")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const importResult = await importToTeamsWorkspace(collections)
|
||||
|
||||
if (E.isRight(importResult)) {
|
||||
toast.success(t("state.file_imported"))
|
||||
@@ -104,13 +133,6 @@ const handleImportToStore = async (collections: HoppCollection[]) => {
|
||||
}
|
||||
}
|
||||
|
||||
const importToPersonalWorkspace = (collections: HoppCollection[]) => {
|
||||
appendRESTCollections(collections)
|
||||
return E.right({
|
||||
success: true,
|
||||
})
|
||||
}
|
||||
|
||||
function translateToTeamCollectionFormat(x: HoppCollection) {
|
||||
const folders: HoppCollection[] = (x.folders ?? []).map(
|
||||
translateToTeamCollectionFormat
|
||||
@@ -390,28 +412,34 @@ const HoppMyCollectionsExporter: ImporterOrExporter = {
|
||||
applicableTo: ["personal-workspace"],
|
||||
isLoading: isHoppMyCollectionExporterInProgress,
|
||||
},
|
||||
action: () => {
|
||||
action: async () => {
|
||||
if (!myCollections.value.length) {
|
||||
return toast.error(t("error.no_collections_to_export"))
|
||||
}
|
||||
|
||||
if (!activeWorkspaceHandle.value) {
|
||||
return
|
||||
}
|
||||
|
||||
isHoppMyCollectionExporterInProgress.value = true
|
||||
|
||||
const message = initializeDownloadCollection(
|
||||
myCollectionsExporter(myCollections.value),
|
||||
"Collections"
|
||||
const result = await workspaceService.exportRESTCollections(
|
||||
activeWorkspaceHandle.value,
|
||||
myCollections.value
|
||||
)
|
||||
|
||||
if (E.isRight(message)) {
|
||||
toast.success(t(message.right))
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "json",
|
||||
platform: "rest",
|
||||
})
|
||||
if (E.isLeft(result)) {
|
||||
// INVALID_WORKSPACE_HANDLE
|
||||
}
|
||||
|
||||
toast.success(t("state.download_started"))
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "json",
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
isHoppMyCollectionExporterInProgress.value = false
|
||||
},
|
||||
}
|
||||
@@ -433,7 +461,7 @@ const HoppTeamCollectionsExporter: ImporterOrExporter = {
|
||||
props.collectionsType.selectedTeam
|
||||
) {
|
||||
const res = await teamCollectionsExporter(
|
||||
props.collectionsType.selectedTeam.id
|
||||
props.collectionsType.selectedTeam.teamID
|
||||
)
|
||||
|
||||
if (E.isRight(res)) {
|
||||
@@ -445,10 +473,7 @@ const HoppTeamCollectionsExporter: ImporterOrExporter = {
|
||||
return toast.error(t("error.no_collections_to_export"))
|
||||
}
|
||||
|
||||
initializeDownloadCollection(
|
||||
exportCollectionsToJSON,
|
||||
"team-collections"
|
||||
)
|
||||
initializeDownloadFile(exportCollectionsToJSON, "team-collections")
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
@@ -487,7 +512,7 @@ const HoppGistCollectionsExporter: ImporterOrExporter = {
|
||||
const collectionJSON = await getCollectionJSON()
|
||||
const accessToken = currentUser.value?.accessToken
|
||||
|
||||
if (!accessToken) {
|
||||
if (!accessToken || E.isLeft(collectionJSON)) {
|
||||
toast.error(t("error.something_went_wrong"))
|
||||
isHoppGistCollectionExporterInProgress.value = false
|
||||
return
|
||||
@@ -569,8 +594,8 @@ const hasTeamWriteAccess = computed(() => {
|
||||
}
|
||||
|
||||
return (
|
||||
collectionsType.selectedTeam.myRole === "EDITOR" ||
|
||||
collectionsType.selectedTeam.myRole === "OWNER"
|
||||
collectionsType.selectedTeam.role === "EDITOR" ||
|
||||
collectionsType.selectedTeam.role === "OWNER"
|
||||
)
|
||||
})
|
||||
|
||||
@@ -578,26 +603,49 @@ const selectedTeamID = computed(() => {
|
||||
const { collectionsType } = props
|
||||
|
||||
return collectionsType.type === "team-collections"
|
||||
? collectionsType.selectedTeam?.id
|
||||
? collectionsType.selectedTeam?.teamID
|
||||
: undefined
|
||||
})
|
||||
|
||||
const getCollectionJSON = async () => {
|
||||
// TODO: Implement `getRESTCollectionJSONView` for team workspace
|
||||
if (
|
||||
props.collectionsType.type === "team-collections" &&
|
||||
props.collectionsType.selectedTeam?.id
|
||||
props.collectionsType.selectedTeam?.teamID
|
||||
) {
|
||||
const res = await getTeamCollectionJSON(
|
||||
props.collectionsType.selectedTeam?.id
|
||||
props.collectionsType.selectedTeam?.teamID
|
||||
)
|
||||
|
||||
return E.isRight(res)
|
||||
? E.right(res.right.exportCollectionsToJSON)
|
||||
: E.left(res.left)
|
||||
: E.left(res.left.error.toString())
|
||||
}
|
||||
|
||||
if (props.collectionsType.type === "my-collections") {
|
||||
return E.right(JSON.stringify(myCollections.value, null, 2))
|
||||
if (!activeWorkspaceHandle.value) {
|
||||
return E.left("INVALID_WORKSPACE_HANDLE")
|
||||
}
|
||||
|
||||
const collectionJSONHandleResult =
|
||||
await workspaceService.getRESTCollectionJSONView(
|
||||
activeWorkspaceHandle.value
|
||||
)
|
||||
|
||||
if (E.isLeft(collectionJSONHandleResult)) {
|
||||
return E.left(collectionJSONHandleResult.left.error)
|
||||
}
|
||||
|
||||
const collectionJSONHandle = collectionJSONHandleResult.right
|
||||
|
||||
const collectionJSONHandleRef = collectionJSONHandle.get()
|
||||
|
||||
if (collectionJSONHandleRef.value.type === "invalid") {
|
||||
// WORKSPACE_INVALIDATED
|
||||
return E.left("WORKSPACE_INVALIDATED")
|
||||
}
|
||||
|
||||
return E.right(collectionJSONHandleRef.value.data.content)
|
||||
}
|
||||
|
||||
return E.left("INVALID_SELECTED_TEAM_OR_INVALID_COLLECTION_TYPE")
|
||||
|
||||
@@ -75,7 +75,7 @@ import {
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { useService } from "dioc/vue"
|
||||
import { clone } from "lodash-es"
|
||||
import { ref, watch } from "vue"
|
||||
import { ref, toRefs, watch } from "vue"
|
||||
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
import { PersistenceService } from "~/services/persistence"
|
||||
@@ -100,11 +100,15 @@ const props = withDefaults(
|
||||
editingProperties: EditingProperties | null
|
||||
source: "REST" | "GraphQL"
|
||||
modelValue: string
|
||||
// TODO: Purpose of this prop is to maintain backwards compatibility
|
||||
// To be removed after porting all usages of this component
|
||||
emitWithFullCollection: boolean
|
||||
}>(),
|
||||
{
|
||||
show: false,
|
||||
loadingState: false,
|
||||
editingProperties: null,
|
||||
emitWithFullCollection: true,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -178,15 +182,24 @@ watch(
|
||||
const saveEditedCollection = () => {
|
||||
if (!props.editingProperties) return
|
||||
const finalCollection = clone(editableCollection.value)
|
||||
delete finalCollection.body
|
||||
|
||||
const { path } = toRefs(props.editingProperties)
|
||||
|
||||
const collection = {
|
||||
path: props.editingProperties.path,
|
||||
path: path.value,
|
||||
collection: {
|
||||
...props.editingProperties.collection,
|
||||
...finalCollection,
|
||||
},
|
||||
isRootCollection: props.editingProperties.isRootCollection,
|
||||
}
|
||||
emit("set-collection-properties", collection as EditingProperties)
|
||||
|
||||
const data = props.emitWithFullCollection
|
||||
? collection
|
||||
: { ...finalCollection, collIndexPath: path.value }
|
||||
emit("set-collection-properties", data as EditingProperties)
|
||||
|
||||
persistenceService.removeLocalConfig("unsaved_collection_properties")
|
||||
}
|
||||
|
||||
|
||||
@@ -20,19 +20,25 @@
|
||||
<label class="p-4">
|
||||
{{ t("collection.select_location") }}
|
||||
</label>
|
||||
<CollectionsGraphql
|
||||
<!-- <CollectionsGraphql
|
||||
v-if="mode === 'graphql'"
|
||||
:picked="picked"
|
||||
:save-request="true"
|
||||
@select="onSelect"
|
||||
/>
|
||||
<Collections
|
||||
/> -->
|
||||
<!-- <Collections
|
||||
v-else
|
||||
:picked="picked"
|
||||
:save-request="true"
|
||||
@select="onSelect"
|
||||
@update-team="updateTeam"
|
||||
@update-collection-type="updateCollectionType"
|
||||
/> -->
|
||||
<NewCollections
|
||||
:picked="picked"
|
||||
:save-request="true"
|
||||
platform="rest"
|
||||
@select="onSelect"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -56,51 +62,40 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useToast } from "@composables/toast"
|
||||
import {
|
||||
HoppGQLRequest,
|
||||
HoppRESTRequest,
|
||||
isHoppRESTRequest,
|
||||
} from "@hoppscotch/data"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import {
|
||||
createRequestInCollection,
|
||||
updateTeamRequest,
|
||||
} from "~/helpers/backend/mutations/TeamRequest"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useToast } from "@composables/toast"
|
||||
import {
|
||||
cascadeParentCollectionForHeaderAuth,
|
||||
editGraphqlRequest,
|
||||
editRESTRequest,
|
||||
saveGraphqlRequestAs,
|
||||
saveRESTRequestAs,
|
||||
} from "~/newstore/collections"
|
||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||
import { computedWithControl } from "@vueuse/core"
|
||||
import { platform } from "~/platform"
|
||||
import { useService } from "dioc/vue"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import * as E from "fp-ts/Either"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { computed, nextTick, reactive, ref, watch } from "vue"
|
||||
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { cascadeParentCollectionForHeaderAuth } from "~/newstore/collections"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
const RESTTabs = useService(RESTTabService)
|
||||
const GQLTabs = useService(GQLTabService)
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
// type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
type CollectionType =
|
||||
| {
|
||||
type: "team-collections"
|
||||
selectedTeam: SelectedTeam
|
||||
}
|
||||
| { type: "my-collections"; selectedTeam: undefined }
|
||||
// type CollectionType =
|
||||
// | {
|
||||
// type: "team-collections"
|
||||
// selectedTeam: SelectedTeam
|
||||
// }
|
||||
// | { type: "my-collections"; selectedTeam: undefined }
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -168,10 +163,10 @@ const requestData = reactive({
|
||||
requestIndex: undefined as number | undefined,
|
||||
})
|
||||
|
||||
const collectionsType = ref<CollectionType>({
|
||||
type: "my-collections",
|
||||
selectedTeam: undefined,
|
||||
})
|
||||
// const collectionsType = ref<CollectionType>({
|
||||
// type: "my-collections",
|
||||
// selectedTeam: undefined,
|
||||
// })
|
||||
|
||||
const picked = ref<Picked | null>(null)
|
||||
|
||||
@@ -192,13 +187,14 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const updateTeam = (newTeam: SelectedTeam) => {
|
||||
collectionsType.value.selectedTeam = newTeam
|
||||
}
|
||||
// TODO: To be removed
|
||||
// const updateTeam = (newTeam: SelectedTeam) => {
|
||||
// collectionsType.value.selectedTeam = newTeam
|
||||
// }
|
||||
|
||||
const updateCollectionType = (type: CollectionType["type"]) => {
|
||||
collectionsType.value.type = type
|
||||
}
|
||||
// const updateCollectionType = (type: CollectionType["type"]) => {
|
||||
// collectionsType.value.type = type
|
||||
// }
|
||||
|
||||
const onSelect = (pickedVal: Picked | null) => {
|
||||
picked.value = pickedVal
|
||||
@@ -214,104 +210,109 @@ const saveRequestAs = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
const requestUpdated =
|
||||
const updatedRequest =
|
||||
props.mode === "rest"
|
||||
? cloneDeep(RESTTabs.currentActiveTab.value.document.request)
|
||||
: cloneDeep(GQLTabs.currentActiveTab.value.document.request)
|
||||
|
||||
requestUpdated.name = requestName.value
|
||||
updatedRequest.name = requestName.value
|
||||
|
||||
if (picked.value.pickedType === "my-collection") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
if (!workspaceService.activeWorkspaceHandle.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
picked.value.pickedType === "my-collection" ||
|
||||
picked.value.pickedType === "my-folder"
|
||||
) {
|
||||
if (!isHoppRESTRequest(updatedRequest))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
const insertionIndex = saveRESTRequestAs(
|
||||
`${picked.value.collectionIndex}`,
|
||||
requestUpdated
|
||||
const collectionPathIndex =
|
||||
picked.value.pickedType === "my-collection"
|
||||
? picked.value.collectionIndex.toString()
|
||||
: picked.value.folderPath
|
||||
|
||||
const collectionHandleResult = await workspaceService.getCollectionHandle(
|
||||
workspaceService.activeWorkspaceHandle.value,
|
||||
collectionPathIndex
|
||||
)
|
||||
|
||||
if (E.isLeft(collectionHandleResult)) {
|
||||
// INVALID_WORKSPACE_HANDLE | INVALID_COLLECTION_ID | INVALID_PATH
|
||||
return
|
||||
}
|
||||
|
||||
const collectionHandle = collectionHandleResult.right
|
||||
|
||||
const requestHandleResult = await workspaceService.createRESTRequest(
|
||||
collectionHandle,
|
||||
updatedRequest
|
||||
)
|
||||
|
||||
if (E.isLeft(requestHandleResult)) {
|
||||
// WORKSPACE_INVALIDATED | INVALID_COLLECTION_HANDLE
|
||||
return
|
||||
}
|
||||
|
||||
const requestHandle = requestHandleResult.right
|
||||
|
||||
const requestHandleRef = requestHandle.get()
|
||||
|
||||
if (requestHandleRef.value.type === "invalid") {
|
||||
// WORKSPACE_INVALIDATED | INVALID_COLLECTION_HANDLE
|
||||
return
|
||||
}
|
||||
|
||||
RESTTabs.currentActiveTab.value.document = {
|
||||
request: requestUpdated,
|
||||
request: updatedRequest,
|
||||
isDirty: false,
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
folderPath: `${picked.value.collectionIndex}`,
|
||||
requestIndex: insertionIndex,
|
||||
originLocation: "workspace-user-collection",
|
||||
requestHandle,
|
||||
},
|
||||
}
|
||||
|
||||
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
`${picked.value.collectionIndex}`,
|
||||
"rest"
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "my-folder") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
const insertionIndex = saveRESTRequestAs(
|
||||
picked.value.folderPath,
|
||||
requestUpdated
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document = {
|
||||
request: requestUpdated,
|
||||
isDirty: false,
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
folderPath: picked.value.folderPath,
|
||||
requestIndex: insertionIndex,
|
||||
},
|
||||
}
|
||||
|
||||
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"rest"
|
||||
)
|
||||
|
||||
RESTTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "my-request") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
if (!isHoppRESTRequest(updatedRequest))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
editRESTRequest(
|
||||
picked.value.folderPath,
|
||||
picked.value.requestIndex,
|
||||
requestUpdated
|
||||
const requestHandleResult = await workspaceService.getRequestHandle(
|
||||
workspaceService.activeWorkspaceHandle.value,
|
||||
`${picked.value.folderPath}/${picked.value.requestIndex.toString()}`
|
||||
)
|
||||
|
||||
if (E.isLeft(requestHandleResult)) {
|
||||
// INVALID_COLLECTION_HANDLE | INVALID_REQUEST_ID | REQUEST_NOT_FOUND
|
||||
return
|
||||
}
|
||||
|
||||
const requestHandle = requestHandleResult.right
|
||||
|
||||
const requestHandleRef = requestHandle.get()
|
||||
|
||||
if (requestHandleRef.value.type === "invalid") {
|
||||
// WORKSPACE_INVALIDATED
|
||||
return
|
||||
}
|
||||
|
||||
const updateRequestResult = await workspaceService.updateRESTRequest(
|
||||
requestHandle,
|
||||
updatedRequest
|
||||
)
|
||||
|
||||
if (E.isLeft(updateRequestResult)) {
|
||||
// WORKSPACE_INVALIDATED | INVALID_REQUEST_HANDLE
|
||||
return
|
||||
}
|
||||
|
||||
RESTTabs.currentActiveTab.value.document = {
|
||||
request: requestUpdated,
|
||||
request: updatedRequest,
|
||||
isDirty: false,
|
||||
saveContext: {
|
||||
originLocation: "user-collection",
|
||||
folderPath: picked.value.folderPath,
|
||||
requestIndex: picked.value.requestIndex,
|
||||
originLocation: "workspace-user-collection",
|
||||
requestHandle,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -325,152 +326,147 @@ const saveRequestAs = async () => {
|
||||
headers,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: false,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "teams-collection") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
updateTeamCollectionOrFolder(picked.value.collectionID, requestUpdated)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
})
|
||||
} else if (picked.value.pickedType === "teams-folder") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
updateTeamCollectionOrFolder(picked.value.folderID, requestUpdated)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
})
|
||||
} else if (picked.value.pickedType === "teams-request") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
if (
|
||||
collectionsType.value.type !== "team-collections" ||
|
||||
!collectionsType.value.selectedTeam
|
||||
)
|
||||
throw new Error("Collections Type mismatch")
|
||||
|
||||
modalLoadingState.value = true
|
||||
|
||||
const data = {
|
||||
request: JSON.stringify(requestUpdated),
|
||||
title: requestUpdated.name,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: false,
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
pipe(
|
||||
updateTeamRequest(picked.value.requestID, data),
|
||||
TE.match(
|
||||
(err: GQLError<string>) => {
|
||||
toast.error(`${getErrorMessage(err)}`)
|
||||
modalLoadingState.value = false
|
||||
},
|
||||
() => {
|
||||
modalLoadingState.value = false
|
||||
requestSaved()
|
||||
}
|
||||
)
|
||||
)()
|
||||
} else if (picked.value.pickedType === "gql-my-request") {
|
||||
// TODO: Check for GQL request ?
|
||||
editGraphqlRequest(
|
||||
picked.value.folderPath,
|
||||
picked.value.requestIndex,
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: false,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-folder") {
|
||||
// TODO: Check for GQL request ?
|
||||
saveGraphqlRequestAs(
|
||||
picked.value.folderPath,
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
picked.value.folderPath,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-collection") {
|
||||
// TODO: Check for GQL request ?
|
||||
saveGraphqlRequestAs(
|
||||
`${picked.value.collectionIndex}`,
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
`${picked.value.collectionIndex}`,
|
||||
"graphql"
|
||||
)
|
||||
|
||||
GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
auth,
|
||||
headers,
|
||||
}
|
||||
|
||||
requestSaved()
|
||||
}
|
||||
// TODO: To be removed
|
||||
// else if (picked.value.pickedType === "teams-collection") {
|
||||
// if (!isHoppRESTRequest(updatedRequest))
|
||||
// throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
// updateTeamCollectionOrFolder(picked.value.collectionID, updatedRequest)
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: true,
|
||||
// platform: "rest",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
// } else if (picked.value.pickedType === "teams-folder") {
|
||||
// if (!isHoppRESTRequest(updatedRequest))
|
||||
// throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
// updateTeamCollectionOrFolder(picked.value.folderID, updatedRequest)
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: true,
|
||||
// platform: "rest",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
// } else if (picked.value.pickedType === "teams-request") {
|
||||
// if (!isHoppRESTRequest(updatedRequest))
|
||||
// throw new Error("requestUpdated is not a REST Request")
|
||||
|
||||
// if (
|
||||
// collectionsType.value.type !== "team-collections" ||
|
||||
// !collectionsType.value.selectedTeam
|
||||
// )
|
||||
// throw new Error("Collections Type mismatch")
|
||||
|
||||
// modalLoadingState.value = true
|
||||
|
||||
// const data = {
|
||||
// request: JSON.stringify(updatedRequest),
|
||||
// title: updatedRequest.name,
|
||||
// }
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: false,
|
||||
// platform: "rest",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
|
||||
// pipe(
|
||||
// updateTeamRequest(picked.value.requestID, data),
|
||||
// TE.match(
|
||||
// (err: GQLError<string>) => {
|
||||
// toast.error(`${getErrorMessage(err)}`)
|
||||
// modalLoadingState.value = false
|
||||
// },
|
||||
// () => {
|
||||
// modalLoadingState.value = false
|
||||
// requestSaved()
|
||||
// }
|
||||
// )
|
||||
// )()
|
||||
// } else if (picked.value.pickedType === "gql-my-request") {
|
||||
// // TODO: Check for GQL request ?
|
||||
// editGraphqlRequest(
|
||||
// picked.value.folderPath,
|
||||
// picked.value.requestIndex,
|
||||
// updatedRequest as HoppGQLRequest
|
||||
// )
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: false,
|
||||
// platform: "gql",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
|
||||
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
// picked.value.folderPath,
|
||||
// "graphql"
|
||||
// )
|
||||
|
||||
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
// auth,
|
||||
// headers,
|
||||
// }
|
||||
|
||||
// requestSaved()
|
||||
// } else if (picked.value.pickedType === "gql-my-folder") {
|
||||
// // TODO: Check for GQL request ?
|
||||
// saveGraphqlRequestAs(
|
||||
// picked.value.folderPath,
|
||||
// updatedRequest as HoppGQLRequest
|
||||
// )
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: true,
|
||||
// platform: "gql",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
|
||||
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
// picked.value.folderPath,
|
||||
// "graphql"
|
||||
// )
|
||||
|
||||
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
// auth,
|
||||
// headers,
|
||||
// }
|
||||
|
||||
// requestSaved()
|
||||
// } else if (picked.value.pickedType === "gql-my-collection") {
|
||||
// // TODO: Check for GQL request ?
|
||||
// saveGraphqlRequestAs(
|
||||
// `${picked.value.collectionIndex}`,
|
||||
// updatedRequest as HoppGQLRequest
|
||||
// )
|
||||
|
||||
// platform.analytics?.logEvent({
|
||||
// type: "HOPP_SAVE_REQUEST",
|
||||
// createdNow: true,
|
||||
// platform: "gql",
|
||||
// workspaceType: "team",
|
||||
// })
|
||||
|
||||
// const { auth, headers } = cascadeParentCollectionForHeaderAuth(
|
||||
// `${picked.value.collectionIndex}`,
|
||||
// "graphql"
|
||||
// )
|
||||
|
||||
// GQLTabs.currentActiveTab.value.document.inheritedProperties = {
|
||||
// auth,
|
||||
// headers,
|
||||
// }
|
||||
|
||||
// requestSaved()
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,50 +474,50 @@ const saveRequestAs = async () => {
|
||||
* @param collectionID - ID of the collection or folder
|
||||
* @param requestUpdated - Updated request
|
||||
*/
|
||||
const updateTeamCollectionOrFolder = (
|
||||
collectionID: string,
|
||||
requestUpdated: HoppRESTRequest
|
||||
) => {
|
||||
if (
|
||||
collectionsType.value.type !== "team-collections" ||
|
||||
!collectionsType.value.selectedTeam
|
||||
)
|
||||
throw new Error("Collections Type mismatch")
|
||||
// const updateTeamCollectionOrFolder = (
|
||||
// collectionID: string,
|
||||
// requestUpdated: HoppRESTRequest
|
||||
// ) => {
|
||||
// if (
|
||||
// collectionsType.value.type !== "team-collections" ||
|
||||
// !collectionsType.value.selectedTeam
|
||||
// )
|
||||
// throw new Error("Collections Type mismatch")
|
||||
|
||||
modalLoadingState.value = true
|
||||
// modalLoadingState.value = true
|
||||
|
||||
const data = {
|
||||
title: requestUpdated.name,
|
||||
request: JSON.stringify(requestUpdated),
|
||||
teamID: collectionsType.value.selectedTeam.id,
|
||||
}
|
||||
pipe(
|
||||
createRequestInCollection(collectionID, data),
|
||||
TE.match(
|
||||
(err: GQLError<string>) => {
|
||||
toast.error(`${getErrorMessage(err)}`)
|
||||
modalLoadingState.value = false
|
||||
},
|
||||
(result) => {
|
||||
const { createRequestInCollection } = result
|
||||
// const data = {
|
||||
// title: requestUpdated.name,
|
||||
// request: JSON.stringify(requestUpdated),
|
||||
// teamID: collectionsType.value.selectedTeam.id,
|
||||
// }
|
||||
// pipe(
|
||||
// createRequestInCollection(collectionID, data),
|
||||
// TE.match(
|
||||
// (err: GQLError<string>) => {
|
||||
// toast.error(`${getErrorMessage(err)}`)
|
||||
// modalLoadingState.value = false
|
||||
// },
|
||||
// (result) => {
|
||||
// const { createRequestInCollection } = result
|
||||
|
||||
RESTTabs.currentActiveTab.value.document = {
|
||||
request: requestUpdated,
|
||||
isDirty: false,
|
||||
saveContext: {
|
||||
originLocation: "team-collection",
|
||||
requestID: createRequestInCollection.id,
|
||||
collectionID: createRequestInCollection.collection.id,
|
||||
teamID: createRequestInCollection.collection.team.id,
|
||||
},
|
||||
}
|
||||
// RESTTabs.currentActiveTab.value.document = {
|
||||
// request: requestUpdated,
|
||||
// isDirty: false,
|
||||
// saveContext: {
|
||||
// originLocation: "team-collection",
|
||||
// requestID: createRequestInCollection.id,
|
||||
// collectionID: createRequestInCollection.collection.id,
|
||||
// teamID: createRequestInCollection.collection.team.id,
|
||||
// },
|
||||
// }
|
||||
|
||||
modalLoadingState.value = false
|
||||
requestSaved()
|
||||
}
|
||||
)
|
||||
)()
|
||||
}
|
||||
// modalLoadingState.value = false
|
||||
// requestSaved()
|
||||
// }
|
||||
// )
|
||||
// )()
|
||||
// }
|
||||
|
||||
const requestSaved = () => {
|
||||
toast.success(`${t("request.added")}`)
|
||||
@@ -536,24 +532,24 @@ const hideModal = () => {
|
||||
emit("hide-modal")
|
||||
}
|
||||
|
||||
const getErrorMessage = (err: GQLError<string>) => {
|
||||
console.error(err)
|
||||
if (err.type === "network_error") {
|
||||
return t("error.network_error")
|
||||
}
|
||||
switch (err.error) {
|
||||
case "team_coll/short_title":
|
||||
return t("collection.name_length_insufficient")
|
||||
case "team/invalid_coll_id":
|
||||
return t("team.invalid_id")
|
||||
case "team/not_required_role":
|
||||
return t("profile.no_permission")
|
||||
case "team_req/not_required_role":
|
||||
return t("profile.no_permission")
|
||||
case "Forbidden resource":
|
||||
return t("profile.no_permission")
|
||||
default:
|
||||
return t("error.something_went_wrong")
|
||||
}
|
||||
}
|
||||
// const getErrorMessage = (err: GQLError<string>) => {
|
||||
// console.error(err)
|
||||
// if (err.type === "network_error") {
|
||||
// return t("error.network_error")
|
||||
// }
|
||||
// switch (err.error) {
|
||||
// case "team_coll/short_title":
|
||||
// return t("collection.name_length_insufficient")
|
||||
// case "team/invalid_coll_id":
|
||||
// return t("team.invalid_id")
|
||||
// case "team/not_required_role":
|
||||
// return t("profile.no_permission")
|
||||
// case "team_req/not_required_role":
|
||||
// return t("profile.no_permission")
|
||||
// case "Forbidden resource":
|
||||
// return t("profile.no_permission")
|
||||
// default:
|
||||
// return t("error.something_went_wrong")
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
@@ -387,7 +387,6 @@ import IconPlus from "~icons/lucide/plus"
|
||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||
import IconImport from "~icons/lucide/folder-down"
|
||||
import { computed, PropType, Ref, toRef } from "vue"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { TeamCollection } from "~/helpers/teams/TeamCollection"
|
||||
@@ -400,17 +399,16 @@ import * as O from "fp-ts/Option"
|
||||
import { Picked } from "~/helpers/types/HoppPicked.js"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { useService } from "dioc/vue"
|
||||
import { TeamWorkspace } from "~/services/workspace.service"
|
||||
|
||||
const t = useI18n()
|
||||
const colorMode = useColorMode()
|
||||
const tabs = useService(RESTTabService)
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
type CollectionType =
|
||||
| {
|
||||
type: "team-collections"
|
||||
selectedTeam: SelectedTeam
|
||||
selectedTeam: TeamWorkspace
|
||||
}
|
||||
| { type: "my-collections"; selectedTeam: undefined }
|
||||
|
||||
@@ -614,7 +612,7 @@ const hasNoTeamAccess = computed(
|
||||
() =>
|
||||
props.collectionsType.type === "team-collections" &&
|
||||
(props.collectionsType.selectedTeam === undefined ||
|
||||
props.collectionsType.selectedTeam.myRole === "VIEWER")
|
||||
props.collectionsType.selectedTeam.role === "VIEWER")
|
||||
)
|
||||
|
||||
const isSelected = ({
|
||||
|
||||
@@ -21,7 +21,7 @@ import { GistSource } from "~/helpers/import-export/import/import-sources/GistSo
|
||||
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconUser from "~icons/lucide/user"
|
||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
|
||||
import { platform } from "~/platform"
|
||||
@@ -133,12 +133,12 @@ const GqlCollectionsHoppExporter: ImporterOrExporter = {
|
||||
disabled: false,
|
||||
applicableTo: ["personal-workspace", "team-workspace"],
|
||||
},
|
||||
action: () => {
|
||||
action: async () => {
|
||||
if (!gqlCollections.value.length) {
|
||||
return toast.error(t("error.no_collections_to_export"))
|
||||
}
|
||||
|
||||
const message = initializeDownloadCollection(
|
||||
const message = await initializeDownloadFile(
|
||||
gqlCollectionsExporter(gqlCollections.value),
|
||||
"GQLCollections"
|
||||
)
|
||||
|
||||
@@ -192,6 +192,7 @@ import { PersistenceService } from "~/services/persistence"
|
||||
import { PersistedOAuthConfig } from "~/services/oauth/oauth.service"
|
||||
import { GQLOptionTabs } from "~/components/graphql/RequestOptions.vue"
|
||||
import { EditingProperties } from "../Properties.vue"
|
||||
import { defineActionHandler } from "~/helpers/actions"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
@@ -199,7 +200,7 @@ const toast = useToast()
|
||||
defineProps<{
|
||||
// Whether to activate the ability to pick items (activates 'select' events)
|
||||
saveRequest: boolean
|
||||
picked: Picked
|
||||
picked: Picked | null
|
||||
}>()
|
||||
|
||||
const collections = useReadonlyStream(graphqlCollections$, [], "deep")
|
||||
@@ -676,4 +677,11 @@ const resetSelectedData = () => {
|
||||
editingRequest.value = null
|
||||
editingRequestIndex.value = null
|
||||
}
|
||||
|
||||
defineActionHandler("collection.new", () => {
|
||||
displayModalAdd(true)
|
||||
})
|
||||
defineActionHandler("modals.collection.import", () => {
|
||||
displayModalImportExport(true)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -178,7 +178,6 @@ import { useI18n } from "@composables/i18n"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { useLocalState } from "~/newstore/localstate"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import {
|
||||
@@ -245,7 +244,7 @@ import {
|
||||
} from "~/helpers/collection/collection"
|
||||
import { currentReorderingStatus$ } from "~/newstore/reordering"
|
||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { TeamWorkspace, WorkspaceService } from "~/services/workspace.service"
|
||||
import { useService } from "dioc/vue"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
|
||||
@@ -274,16 +273,14 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "select", payload: Picked | null): void
|
||||
(event: "update-team", team: SelectedTeam): void
|
||||
(event: "update-team", team: TeamWorkspace): void
|
||||
(event: "update-collection-type", type: CollectionType["type"]): void
|
||||
}>()
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
type CollectionType =
|
||||
| {
|
||||
type: "team-collections"
|
||||
selectedTeam: SelectedTeam
|
||||
selectedTeam: TeamWorkspace
|
||||
}
|
||||
| { type: "my-collections"; selectedTeam: undefined }
|
||||
|
||||
@@ -330,9 +327,7 @@ const requestMoveLoading = ref<string[]>([])
|
||||
// TeamList-Adapter
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
|
||||
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||
const teamListFetched = ref(false)
|
||||
|
||||
// Team Collection Adapter
|
||||
const teamCollectionAdapter = new TeamCollectionAdapter(null)
|
||||
@@ -378,7 +373,7 @@ watch(
|
||||
filterTexts,
|
||||
(newFilterText) => {
|
||||
if (collectionsType.value.type === "team-collections") {
|
||||
const selectedTeamID = collectionsType.value.selectedTeam?.id
|
||||
const selectedTeamID = collectionsType.value.selectedTeam?.teamID
|
||||
|
||||
selectedTeamID &&
|
||||
debouncedSearch(newFilterText, selectedTeamID)?.catch(() => {})
|
||||
@@ -435,28 +430,6 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => myTeams.value,
|
||||
(newTeams) => {
|
||||
if (newTeams && !teamListFetched.value) {
|
||||
teamListFetched.value = true
|
||||
if (REMEMBERED_TEAM_ID.value && currentUser.value) {
|
||||
const team = newTeams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
||||
if (team) updateSelectedTeam(team)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => collectionsType.value.selectedTeam,
|
||||
(newTeam) => {
|
||||
if (newTeam) {
|
||||
teamCollectionAdapter.changeTeamID(newTeam.id)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const switchToMyCollections = () => {
|
||||
collectionsType.value.type = "my-collections"
|
||||
collectionsType.value.selectedTeam = undefined
|
||||
@@ -488,11 +461,12 @@ const expandTeamCollection = (collectionID: string) => {
|
||||
teamCollectionAdapter.expandCollection(collectionID)
|
||||
}
|
||||
|
||||
const updateSelectedTeam = (team: SelectedTeam) => {
|
||||
const updateSelectedTeam = (team: TeamWorkspace) => {
|
||||
if (team) {
|
||||
collectionsType.value.type = "team-collections"
|
||||
teamCollectionAdapter.changeTeamID(team.teamID)
|
||||
collectionsType.value.selectedTeam = team
|
||||
REMEMBERED_TEAM_ID.value = team.id
|
||||
REMEMBERED_TEAM_ID.value = team.teamID
|
||||
emit("update-team", team)
|
||||
emit("update-collection-type", "team-collections")
|
||||
}
|
||||
@@ -501,23 +475,14 @@ const updateSelectedTeam = (team: SelectedTeam) => {
|
||||
const workspace = workspaceService.currentWorkspace
|
||||
|
||||
// Used to switch collection type and team when user switch workspace in the global workspace switcher
|
||||
// Check if there is a teamID in the workspace, if yes, switch to team collections and select the team
|
||||
// If there is no teamID, switch to my collections
|
||||
watch(
|
||||
() => {
|
||||
const space = workspace.value
|
||||
return space.type === "personal" ? undefined : space.teamID
|
||||
},
|
||||
(teamID) => {
|
||||
if (teamID) {
|
||||
const team = myTeams.value?.find((t) => t.id === teamID)
|
||||
if (team) {
|
||||
updateSelectedTeam(team)
|
||||
}
|
||||
return
|
||||
workspace,
|
||||
(newWorkspace) => {
|
||||
if (newWorkspace.type === "personal") {
|
||||
switchToMyCollections()
|
||||
} else if (newWorkspace.type === "team") {
|
||||
updateSelectedTeam(newWorkspace)
|
||||
}
|
||||
|
||||
return switchToMyCollections()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
@@ -545,7 +510,7 @@ const hasTeamWriteAccess = computed(() => {
|
||||
return false
|
||||
}
|
||||
|
||||
const role = collectionsType.value.selectedTeam?.myRole
|
||||
const role = collectionsType.value.selectedTeam?.role
|
||||
return role === "OWNER" || role === "EDITOR"
|
||||
})
|
||||
|
||||
@@ -760,7 +725,7 @@ const addNewRootCollection = (name: string) => {
|
||||
})
|
||||
|
||||
pipe(
|
||||
createNewRootCollection(name, collectionsType.value.selectedTeam.id),
|
||||
createNewRootCollection(name, collectionsType.value.selectedTeam.teamID),
|
||||
TE.match(
|
||||
(err: GQLError<string>) => {
|
||||
toast.error(`${getErrorMessage(err)}`)
|
||||
@@ -831,7 +796,7 @@ const onAddRequest = (requestName: string) => {
|
||||
|
||||
const data = {
|
||||
request: JSON.stringify(newRequest),
|
||||
teamID: collectionsType.value.selectedTeam.id,
|
||||
teamID: collectionsType.value.selectedTeam.teamID,
|
||||
title: requestName,
|
||||
}
|
||||
|
||||
@@ -1158,7 +1123,7 @@ const duplicateRequest = (payload: {
|
||||
|
||||
const data = {
|
||||
request: JSON.stringify(newRequest),
|
||||
teamID: collectionsType.value.selectedTeam.id,
|
||||
teamID: collectionsType.value.selectedTeam.teamID,
|
||||
title: `${request.name} - ${t("action.duplicate")}`,
|
||||
}
|
||||
|
||||
@@ -2351,4 +2316,7 @@ const getErrorMessage = (err: GQLError<string>) => {
|
||||
defineActionHandler("collection.new", () => {
|
||||
displayModalAdd(true)
|
||||
})
|
||||
defineActionHandler("modals.collection.import", () => {
|
||||
displayModalImportExport(true)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -37,7 +37,7 @@ import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconPostman from "~icons/hopp/postman"
|
||||
import IconInsomnia from "~icons/hopp/insomnia"
|
||||
import IconUser from "~icons/lucide/user"
|
||||
import { initializeDownloadCollection } from "~/helpers/import-export/export"
|
||||
import { initializeDownloadFile } from "~/helpers/import-export/export"
|
||||
import { computed } from "vue"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { environmentsExporter } from "~/helpers/import-export/export/environments"
|
||||
@@ -230,12 +230,12 @@ const HoppEnvironmentsExport: ImporterOrExporter = {
|
||||
disabled: false,
|
||||
applicableTo: ["personal-workspace", "team-workspace"],
|
||||
},
|
||||
action: () => {
|
||||
action: async () => {
|
||||
if (!environmentJson.value.length) {
|
||||
return toast.error(t("error.no_environments_to_export"))
|
||||
}
|
||||
|
||||
const message = initializeDownloadCollection(
|
||||
const message = await initializeDownloadFile(
|
||||
environmentsExporter(environmentJson.value),
|
||||
"Environments"
|
||||
)
|
||||
|
||||
@@ -364,6 +364,7 @@ const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
||||
teamID: team.id,
|
||||
teamName: team.name,
|
||||
type: "team",
|
||||
role: team.myRole,
|
||||
})
|
||||
}
|
||||
watch(
|
||||
|
||||
@@ -46,41 +46,38 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { isEqual } from "lodash-es"
|
||||
import { platform } from "~/platform"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import { useReadonlyStream, useStream } from "@composables/stream"
|
||||
import { Environment } from "@hoppscotch/data"
|
||||
import { useService } from "dioc/vue"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import { isEqual } from "lodash-es"
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { defineActionHandler } from "~/helpers/actions"
|
||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||
import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
||||
import TeamEnvironmentAdapter from "~/helpers/teams/TeamEnvironmentAdapter"
|
||||
import {
|
||||
deleteEnvironment,
|
||||
getSelectedEnvironmentIndex,
|
||||
globalEnv$,
|
||||
selectedEnvironmentIndex$,
|
||||
setSelectedEnvironmentIndex,
|
||||
} from "~/newstore/environments"
|
||||
import TeamEnvironmentAdapter from "~/helpers/teams/TeamEnvironmentAdapter"
|
||||
import { defineActionHandler } from "~/helpers/actions"
|
||||
import { useLocalState } from "~/newstore/localstate"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||
import { deleteEnvironment } from "~/newstore/environments"
|
||||
import { deleteTeamEnvironment } from "~/helpers/backend/mutations/TeamEnvironment"
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { useService } from "dioc/vue"
|
||||
import { Environment } from "@hoppscotch/data"
|
||||
import { platform } from "~/platform"
|
||||
import { TeamWorkspace, WorkspaceService } from "~/services/workspace.service"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
type EnvironmentType = "my-environments" | "team-environments"
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
type EnvironmentsChooseType = {
|
||||
type: EnvironmentType
|
||||
selectedTeam: SelectedTeam
|
||||
selectedTeam: TeamWorkspace | undefined
|
||||
}
|
||||
|
||||
const environmentType = ref<EnvironmentsChooseType>({
|
||||
@@ -102,11 +99,7 @@ const currentUser = useReadonlyStream(
|
||||
platform.auth.getCurrentUser()
|
||||
)
|
||||
|
||||
// TeamList-Adapter
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
const teamListAdapter = workspaceService.acquireTeamListAdapter(null)
|
||||
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
||||
const teamListFetched = ref(false)
|
||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||
|
||||
const adapter = new TeamEnvironmentAdapter(undefined)
|
||||
@@ -118,29 +111,17 @@ const loading = computed(
|
||||
() => adapterLoading.value && teamEnvironmentList.value.length === 0
|
||||
)
|
||||
|
||||
watch(
|
||||
() => myTeams.value,
|
||||
(newTeams) => {
|
||||
if (newTeams && !teamListFetched.value) {
|
||||
teamListFetched.value = true
|
||||
if (REMEMBERED_TEAM_ID.value && currentUser.value) {
|
||||
const team = newTeams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
||||
if (team) updateSelectedTeam(team)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const switchToMyEnvironments = () => {
|
||||
environmentType.value.selectedTeam = undefined
|
||||
updateEnvironmentType("my-environments")
|
||||
adapter.changeTeamID(undefined)
|
||||
}
|
||||
|
||||
const updateSelectedTeam = (newSelectedTeam: SelectedTeam | undefined) => {
|
||||
const updateSelectedTeam = (newSelectedTeam: TeamWorkspace | undefined) => {
|
||||
if (newSelectedTeam) {
|
||||
adapter.changeTeamID(newSelectedTeam.teamID)
|
||||
environmentType.value.selectedTeam = newSelectedTeam
|
||||
REMEMBERED_TEAM_ID.value = newSelectedTeam.id
|
||||
REMEMBERED_TEAM_ID.value = newSelectedTeam.teamID
|
||||
updateEnvironmentType("team-environments")
|
||||
}
|
||||
}
|
||||
@@ -148,15 +129,6 @@ const updateEnvironmentType = (newEnvironmentType: EnvironmentType) => {
|
||||
environmentType.value.type = newEnvironmentType
|
||||
}
|
||||
|
||||
watch(
|
||||
() => environmentType.value.selectedTeam,
|
||||
(newTeam) => {
|
||||
if (newTeam) {
|
||||
adapter.changeTeamID(newTeam.id)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const workspace = workspaceService.currentWorkspace
|
||||
|
||||
// Switch to my environments if workspace is personal and to team environments if workspace is team
|
||||
@@ -170,8 +142,7 @@ watch(workspace, (newWorkspace) => {
|
||||
})
|
||||
}
|
||||
} else if (newWorkspace.type === "team") {
|
||||
const team = myTeams.value?.find((t) => t.id === newWorkspace.teamID)
|
||||
updateSelectedTeam(team)
|
||||
updateSelectedTeam(newWorkspace)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -54,9 +54,7 @@
|
||||
:key="tab.id"
|
||||
:label="tab.label"
|
||||
>
|
||||
<div
|
||||
class="divide-y divide-dividerLight rounded border border-divider"
|
||||
>
|
||||
<div class="divide-y divide-dividerLight">
|
||||
<HoppSmartPlaceholder
|
||||
v-if="tab.variables.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/blockchain.svg`"
|
||||
|
||||
@@ -56,9 +56,7 @@
|
||||
:key="tab.id"
|
||||
:label="tab.label"
|
||||
>
|
||||
<div
|
||||
class="divide-y divide-dividerLight rounded border border-divider"
|
||||
>
|
||||
<div class="divide-y divide-dividerLight">
|
||||
<HoppSmartPlaceholder
|
||||
v-if="tab.variables.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/blockchain.svg`"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class="sticky top-upperPrimaryStickyFold z-10 flex flex-1 flex-shrink-0 justify-between overflow-x-auto border-b border-dividerLight bg-primary"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-if="team === undefined || team.myRole === 'VIEWER'"
|
||||
v-if="team === undefined || team.role === 'VIEWER'"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
disabled
|
||||
class="!rounded-none"
|
||||
@@ -28,7 +28,7 @@
|
||||
:icon="IconHelpCircle"
|
||||
/>
|
||||
<HoppButtonSecondary
|
||||
v-if="team !== undefined && team.myRole === 'VIEWER'"
|
||||
v-if="team !== undefined && team.role === 'VIEWER'"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
disabled
|
||||
:icon="IconImport"
|
||||
@@ -84,7 +84,7 @@
|
||||
)"
|
||||
:key="`environment-${index}`"
|
||||
:environment="environment"
|
||||
:is-viewer="team?.myRole === 'VIEWER'"
|
||||
:is-viewer="team?.role === 'VIEWER'"
|
||||
@edit-environment="editEnvironment(environment)"
|
||||
/>
|
||||
</div>
|
||||
@@ -103,16 +103,16 @@
|
||||
:show="showModalDetails"
|
||||
:action="action"
|
||||
:editing-environment="editingEnvironment"
|
||||
:editing-team-id="team?.id"
|
||||
:editing-team-id="team?.teamID"
|
||||
:editing-variable-name="editingVariableName"
|
||||
:is-secret-option-selected="secretOptionSelected"
|
||||
:is-viewer="team?.myRole === 'VIEWER'"
|
||||
:is-viewer="team?.role === 'VIEWER'"
|
||||
@hide-modal="displayModalEdit(false)"
|
||||
/>
|
||||
<EnvironmentsImportExport
|
||||
v-if="showModalImportExport"
|
||||
:team-environments="teamEnvironments"
|
||||
:team-id="team?.id"
|
||||
:team-id="team?.teamID"
|
||||
environment-type="TEAM_ENV"
|
||||
@hide-modal="displayModalImportExport(false)"
|
||||
/>
|
||||
@@ -129,16 +129,14 @@ import IconPlus from "~icons/lucide/plus"
|
||||
import IconHelpCircle from "~icons/lucide/help-circle"
|
||||
import IconImport from "~icons/lucide/folder-down"
|
||||
import { defineActionHandler } from "~/helpers/actions"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import { TeamWorkspace } from "~/services/workspace.service"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const colorMode = useColorMode()
|
||||
|
||||
type SelectedTeam = GetMyTeamsQuery["myTeams"][number] | undefined
|
||||
|
||||
const props = defineProps<{
|
||||
team: SelectedTeam
|
||||
team: TeamWorkspace | undefined
|
||||
teamEnvironments: TeamEnvironment[]
|
||||
adapterError: GQLError<string> | null
|
||||
loading: boolean
|
||||
@@ -151,7 +149,7 @@ const editingEnvironment = ref<TeamEnvironment | null>(null)
|
||||
const editingVariableName = ref("")
|
||||
const secretOptionSelected = ref(false)
|
||||
|
||||
const isTeamViewer = computed(() => props.team?.myRole === "VIEWER")
|
||||
const isTeamViewer = computed(() => props.team?.role === "VIEWER")
|
||||
|
||||
const displayModalAdd = (shouldDisplay: boolean) => {
|
||||
action.value = "new"
|
||||
|
||||
@@ -595,7 +595,7 @@ const getComputedAuthHeaders = (
|
||||
} else if (request.auth.authType === "api-key") {
|
||||
const { key, addTo } = request.auth
|
||||
|
||||
if (addTo === "Headers" && key) {
|
||||
if (addTo === "HEADERS" && key) {
|
||||
headers.push({
|
||||
active: true,
|
||||
key,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
class="w-full rounded border border-divider bg-primaryLight px-4 py-2 text-secondaryDark"
|
||||
:placeholder="`${t('request.url')}`"
|
||||
:placeholder="`${t('graphql.url_placeholder')}`"
|
||||
:disabled="connected"
|
||||
@keyup.enter="onConnectClick"
|
||||
/>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
>
|
||||
<SmartEnvInput
|
||||
v-model="tab.document.request.endpoint"
|
||||
:placeholder="`${t('request.url')}`"
|
||||
:placeholder="`${t('request.url_placeholder')}`"
|
||||
:auto-complete-source="userHistories"
|
||||
:auto-complete-env="true"
|
||||
:inspection-results="tabResults"
|
||||
@@ -236,16 +236,28 @@ import { useI18n } from "@composables/i18n"
|
||||
import { useSetting } from "@composables/settings"
|
||||
import { useReadonlyStream, useStreamSubscriber } from "@composables/stream"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { useService } from "dioc/vue"
|
||||
import * as E from "fp-ts/Either"
|
||||
import { Ref, computed, ref, onUnmounted } from "vue"
|
||||
import { Ref, computed, onUnmounted, ref } from "vue"
|
||||
import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||
import { runMutation } from "~/helpers/backend/GQLClient"
|
||||
import { UpdateRequestDocument } from "~/helpers/backend/graphql"
|
||||
import { getPlatformSpecialKey as getSpecialKey } from "~/helpers/platformutils"
|
||||
import { runRESTRequest$ } from "~/helpers/RequestRunner"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
import { getMethodLabelColor } from "~/helpers/rest/labelColoring"
|
||||
import { HoppRESTResponse } from "~/helpers/types/HoppRESTResponse"
|
||||
import { editRESTRequest } from "~/newstore/collections"
|
||||
import { RESTHistoryEntry, restHistory$ } from "~/newstore/history"
|
||||
import { platform } from "~/platform"
|
||||
import { InspectionService } from "~/services/inspection"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import IconChevronDown from "~icons/lucide/chevron-down"
|
||||
import IconCode2 from "~icons/lucide/code-2"
|
||||
import IconFileCode from "~icons/lucide/file-code"
|
||||
@@ -253,21 +265,10 @@ import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconRotateCCW from "~icons/lucide/rotate-ccw"
|
||||
import IconSave from "~icons/lucide/save"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { RESTHistoryEntry, restHistory$ } from "~/newstore/history"
|
||||
import { platform } from "~/platform"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
import { useService } from "dioc/vue"
|
||||
import { InspectionService } from "~/services/inspection"
|
||||
import { InterceptorService } from "~/services/interceptor.service"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { getMethodLabelColor } from "~/helpers/rest/labelColoring"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
|
||||
const t = useI18n()
|
||||
const interceptorService = useService(InterceptorService)
|
||||
const newWorkspaceService = useService(NewWorkspaceService)
|
||||
|
||||
const methods = [
|
||||
"GET",
|
||||
@@ -506,34 +507,61 @@ const cycleDownMethod = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const saveRequest = () => {
|
||||
const saveCtx = tab.value.document.saveContext
|
||||
const saveRequest = async () => {
|
||||
const { saveContext } = tab.value.document
|
||||
|
||||
if (!saveCtx) {
|
||||
if (!saveContext) {
|
||||
showSaveRequestModal.value = true
|
||||
return
|
||||
}
|
||||
if (saveCtx.originLocation === "user-collection") {
|
||||
const req = tab.value.document.request
|
||||
|
||||
try {
|
||||
editRESTRequest(saveCtx.folderPath, saveCtx.requestIndex, req)
|
||||
if (saveContext.originLocation === "workspace-user-collection") {
|
||||
const updatedRequest = tab.value.document.request
|
||||
|
||||
tab.value.document.isDirty = false
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
platform: "rest",
|
||||
createdNow: false,
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
toast.success(`${t("request.saved")}`)
|
||||
} catch (e) {
|
||||
tab.value.document.saveContext = undefined
|
||||
saveRequest()
|
||||
if (
|
||||
!newWorkspaceService.activeWorkspaceHandle.value ||
|
||||
!saveContext.requestHandle
|
||||
) {
|
||||
return
|
||||
}
|
||||
} else if (saveCtx.originLocation === "team-collection") {
|
||||
|
||||
const { requestHandle } = saveContext
|
||||
|
||||
const requestHandleRef = requestHandle.get()
|
||||
|
||||
if (!requestHandleRef.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (requestHandleRef.value.type === "invalid") {
|
||||
showSaveRequestModal.value = true
|
||||
return
|
||||
}
|
||||
|
||||
const updateRequestResult = await newWorkspaceService.updateRESTRequest(
|
||||
requestHandle,
|
||||
updatedRequest
|
||||
)
|
||||
|
||||
if (E.isLeft(updateRequestResult)) {
|
||||
// INVALID_REQUEST_HANDLE
|
||||
showSaveRequestModal.value = true
|
||||
|
||||
if (!tab.value.document.isDirty) {
|
||||
tab.value.document.isDirty = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
tab.value.document.isDirty = false
|
||||
|
||||
tab.value.document.saveContext = {
|
||||
...saveContext,
|
||||
requestHandle,
|
||||
}
|
||||
|
||||
toast.success(`${t("request.saved")}`)
|
||||
} else if (saveContext.originLocation === "team-collection") {
|
||||
const req = tab.value.document.request
|
||||
|
||||
// TODO: handle error case (NOTE: overwriteRequestTeams is async)
|
||||
@@ -546,7 +574,7 @@ const saveRequest = () => {
|
||||
})
|
||||
|
||||
runMutation(UpdateRequestDocument, {
|
||||
requestID: saveCtx.requestID,
|
||||
requestID: saveContext.requestID,
|
||||
data: {
|
||||
title: req.name,
|
||||
request: JSON.stringify(req),
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
<script setup lang="ts">
|
||||
import { watch } from "vue"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { isEqualHoppRESTRequest } from "@hoppscotch/data"
|
||||
import { cloneDeep, isEqual } from "lodash-es"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
|
||||
@@ -32,15 +31,42 @@ const emit = defineEmits<{
|
||||
|
||||
const tab = useVModel(props, "modelValue", emit)
|
||||
|
||||
// TODO: Come up with a better dirty check
|
||||
let oldRequest = cloneDeep(tab.value.document.request)
|
||||
|
||||
watch(
|
||||
() => tab.value.document.request,
|
||||
(updatedValue) => {
|
||||
// Request from the collection tree
|
||||
if (
|
||||
!tab.value.document.isDirty &&
|
||||
!isEqualHoppRESTRequest(oldRequest, updatedValue)
|
||||
tab.value.document.saveContext?.originLocation ===
|
||||
"workspace-user-collection"
|
||||
) {
|
||||
const requestHandleRef =
|
||||
tab.value.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
!tab.value.document.isDirty &&
|
||||
!isEqual(oldRequest, requestHandleRef?.value.data.request)
|
||||
) {
|
||||
tab.value.document.isDirty = true
|
||||
}
|
||||
|
||||
if (
|
||||
tab.value.document.isDirty &&
|
||||
isEqual(oldRequest, requestHandleRef?.value.data.request)
|
||||
) {
|
||||
tab.value.document.isDirty = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Unsaved request
|
||||
if (!tab.value.document.isDirty && !isEqual(oldRequest, updatedValue)) {
|
||||
tab.value.document.isDirty = true
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
:icon="IconFolder"
|
||||
:label="`${t('tab.collections')}`"
|
||||
>
|
||||
<Collections />
|
||||
<!-- <Collections /> -->
|
||||
<NewCollections :platform="'rest'" />
|
||||
</HoppSmartTab>
|
||||
<HoppSmartTab
|
||||
:id="'env'"
|
||||
@@ -37,12 +38,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import IconClock from "~icons/lucide/clock"
|
||||
import IconLayers from "~icons/lucide/layers"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
import { ref } from "vue"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { ref } from "vue"
|
||||
|
||||
import IconClock from "~icons/lucide/clock"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconLayers from "~icons/lucide/layers"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
|
||||
@@ -106,15 +106,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { TippyComponent } from "vue-tippy"
|
||||
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconFileEdit from "~icons/lucide/file-edit"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
import IconXCircle from "~icons/lucide/x-circle"
|
||||
import IconXSquare from "~icons/lucide/x-square"
|
||||
import IconFileEdit from "~icons/lucide/file-edit"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
|
||||
@@ -28,7 +28,13 @@
|
||||
>
|
||||
<HoppSmartSelectWrapper>
|
||||
<HoppButtonSecondary
|
||||
:label="auth.addTo || t('state.none')"
|
||||
:label="
|
||||
auth.addTo
|
||||
? auth.addTo === 'HEADERS'
|
||||
? t('authorization.pass_by_headers_label')
|
||||
: t('authorization.pass_by_query_params_label')
|
||||
: t('state.none')
|
||||
"
|
||||
class="ml-2 rounded-none pr-8"
|
||||
/>
|
||||
</HoppSmartSelectWrapper>
|
||||
@@ -40,23 +46,23 @@
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<HoppSmartItem
|
||||
:icon="auth.addTo === 'Headers' ? IconCircleDot : IconCircle"
|
||||
:active="auth.addTo === 'Headers'"
|
||||
:label="'Headers'"
|
||||
:icon="auth.addTo === 'HEADERS' ? IconCircleDot : IconCircle"
|
||||
:active="auth.addTo === 'HEADERS'"
|
||||
:label="t('authorization.pass_by_headers_label')"
|
||||
@click="
|
||||
() => {
|
||||
auth.addTo = 'Headers'
|
||||
auth.addTo = 'HEADERS'
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
:icon="auth.addTo === 'Query params' ? IconCircleDot : IconCircle"
|
||||
:active="auth.addTo === 'Query params'"
|
||||
:label="'Query params'"
|
||||
:icon="auth.addTo === 'QUERY_PARAMS' ? IconCircleDot : IconCircle"
|
||||
:active="auth.addTo === 'QUERY_PARAMS'"
|
||||
:label="t('authorization.pass_by_query_params_label')"
|
||||
@click="
|
||||
() => {
|
||||
auth.addTo = 'Query params'
|
||||
auth.addTo = 'QUERY_PARAMS'
|
||||
hide()
|
||||
}
|
||||
"
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div v-if="!activeWorkspaceHandle">No Workspace Selected.</div>
|
||||
|
||||
<NewCollectionsRest
|
||||
v-else-if="platform === 'rest'"
|
||||
:picked="picked"
|
||||
:save-request="saveRequest"
|
||||
:workspace-handle="activeWorkspaceHandle"
|
||||
@select="(payload) => emit('select', payload)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useService } from "dioc/vue"
|
||||
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
|
||||
defineProps<{
|
||||
picked?: Picked | null
|
||||
platform: "rest" | "gql"
|
||||
saveRequest?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "select", payload: Picked | null): void
|
||||
}>()
|
||||
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
|
||||
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle
|
||||
</script>
|
||||
@@ -0,0 +1,450 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div
|
||||
class="h-1 w-full transition"
|
||||
:class="[
|
||||
{
|
||||
'bg-accentDark': isReorderable,
|
||||
},
|
||||
]"
|
||||
@drop="orderUpdateCollectionEvent"
|
||||
@dragover.prevent="ordering = true"
|
||||
@dragleave="ordering = false"
|
||||
@dragend="resetDragState"
|
||||
></div>
|
||||
|
||||
<div class="relative flex flex-col">
|
||||
<div
|
||||
class="z-[1] pointer-events-none absolute inset-0 bg-accent opacity-0 transition"
|
||||
:class="{
|
||||
'opacity-25':
|
||||
dragging && notSameDestination && notSameParentDestination,
|
||||
}"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="z-[3] group pointer-events-auto relative flex cursor-pointer items-stretch"
|
||||
:draggable="true"
|
||||
@dragstart="dragStart"
|
||||
@dragover="handleDragOver($event)"
|
||||
@dragleave="resetDragState"
|
||||
@dragend="
|
||||
() => {
|
||||
resetDragState()
|
||||
dropItemID = ''
|
||||
}
|
||||
"
|
||||
@drop="handleDrop($event)"
|
||||
@contextmenu.prevent="options?.tippy?.show()"
|
||||
>
|
||||
<div
|
||||
class="flex min-w-0 flex-1 items-center justify-center"
|
||||
@click="emit('toggle-children')"
|
||||
>
|
||||
<span
|
||||
class="pointer-events-none flex items-center justify-center px-4"
|
||||
>
|
||||
<component
|
||||
:is="collectionIcon"
|
||||
class="svg-icons"
|
||||
:class="{ 'text-accent': isSelected }"
|
||||
/>
|
||||
</span>
|
||||
|
||||
<span
|
||||
class="pointer-events-none flex min-w-0 flex-1 py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||
>
|
||||
<span class="truncate" :class="{ 'text-accent': isSelected }">
|
||||
{{ collectionView.name }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconFilePlus"
|
||||
:title="t('request.new')"
|
||||
class="hidden group-hover:inline-flex"
|
||||
@click="addRequest"
|
||||
/>
|
||||
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconFolderPlus"
|
||||
:title="t('folder.new')"
|
||||
class="hidden group-hover:inline-flex"
|
||||
@click="addChildCollection"
|
||||
/>
|
||||
|
||||
<span>
|
||||
<tippy
|
||||
ref="options"
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions!.focus()"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('action.more')"
|
||||
:icon="IconMoreVertical"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.r="requestAction?.$el.click()"
|
||||
@keyup.n="folderAction?.$el.click()"
|
||||
@keyup.e="edit?.$el.click()"
|
||||
@keyup.delete="deleteAction?.$el.click()"
|
||||
@keyup.x="exportAction?.$el.click()"
|
||||
@keyup.p="propertiesAction?.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<HoppSmartItem
|
||||
ref="requestAction"
|
||||
:icon="IconFilePlus"
|
||||
:label="t('request.new')"
|
||||
:shortcut="['R']"
|
||||
@click="
|
||||
() => {
|
||||
addRequest()
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="folderAction"
|
||||
:icon="IconFolderPlus"
|
||||
:label="t('folder.new')"
|
||||
:shortcut="['N']"
|
||||
@click="
|
||||
() => {
|
||||
addChildCollection()
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="edit"
|
||||
:icon="IconEdit"
|
||||
:label="t('action.edit')"
|
||||
:shortcut="['E']"
|
||||
@click="
|
||||
() => {
|
||||
editCollection()
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="exportAction"
|
||||
:icon="IconDownload"
|
||||
:label="t('export.title')"
|
||||
:shortcut="['X']"
|
||||
@click="
|
||||
() => {
|
||||
emit('export-collection', collectionView.collectionID)
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="deleteAction"
|
||||
:icon="IconTrash2"
|
||||
:label="t('action.delete')"
|
||||
:shortcut="['⌫']"
|
||||
@click="
|
||||
() => {
|
||||
removeCollection()
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="propertiesAction"
|
||||
:icon="IconSettings2"
|
||||
:label="t('action.properties')"
|
||||
:shortcut="['P']"
|
||||
@click="
|
||||
() => {
|
||||
emit(
|
||||
'edit-collection-properties',
|
||||
collectionView.collectionID
|
||||
)
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="collectionView.isLastItem"
|
||||
class="w-full transition"
|
||||
:class="[
|
||||
{
|
||||
'bg-accentDark': isLastItemReorderable,
|
||||
'h-1 ': collectionView.isLastItem,
|
||||
},
|
||||
]"
|
||||
@drop="updateLastItemOrder"
|
||||
@dragover.prevent="orderingLastItem = true"
|
||||
@dragleave="orderingLastItem = false"
|
||||
@dragend="resetDragState"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { TippyComponent } from "vue-tippy"
|
||||
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import {
|
||||
currentReorderingStatus$,
|
||||
changeCurrentReorderStatus,
|
||||
} from "~/newstore/reordering"
|
||||
import { RESTCollectionViewCollection } from "~/services/new-workspace/view"
|
||||
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconDownload from "~icons/lucide/download"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconFilePlus from "~icons/lucide/file-plus"
|
||||
import IconFolder from "~icons/lucide/folder"
|
||||
import IconFolderOpen from "~icons/lucide/folder-open"
|
||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconSettings2 from "~icons/lucide/settings-2"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const props = defineProps<{
|
||||
collectionView: RESTCollectionViewCollection
|
||||
isOpen: boolean
|
||||
isSelected?: boolean | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "add-child-collection", parentCollectionIndexPath: string): void
|
||||
(event: "add-request", parentCollectionIndexPath: string): void
|
||||
(event: "dragging", payload: boolean): void
|
||||
(event: "drop-event", payload: DataTransfer): void
|
||||
(event: "drag-event", payload: DataTransfer): void
|
||||
(
|
||||
event: "edit-child-collection",
|
||||
payload: { collectionIndexPath: string; collectionName: string }
|
||||
): void
|
||||
(event: "edit-collection-properties", collectionIndexPath: string): void
|
||||
(
|
||||
event: "edit-root-collection",
|
||||
payload: { collectionIndexPath: string; collectionName: string }
|
||||
): void
|
||||
(event: "export-collection", collectionIndexPath: string): void
|
||||
(event: "remove-child-collection", collectionIndexPath: string): void
|
||||
(event: "remove-root-collection", collectionIndexPath: string): void
|
||||
(event: "toggle-children"): void
|
||||
(event: "update-collection-order", payload: DataTransfer): void
|
||||
(event: "update-last-collection-order", payload: DataTransfer): void
|
||||
}>()
|
||||
|
||||
const tippyActions = ref<TippyComponent | null>(null)
|
||||
const requestAction = ref<HTMLButtonElement | null>(null)
|
||||
const folderAction = ref<HTMLButtonElement | null>(null)
|
||||
const edit = ref<HTMLButtonElement | null>(null)
|
||||
const deleteAction = ref<HTMLButtonElement | null>(null)
|
||||
const exportAction = ref<HTMLButtonElement | null>(null)
|
||||
const propertiesAction = ref<TippyComponent | null>(null)
|
||||
const options = ref<TippyComponent | null>(null)
|
||||
|
||||
const dragging = ref(false)
|
||||
const ordering = ref(false)
|
||||
const orderingLastItem = ref(false)
|
||||
const dropItemID = ref("")
|
||||
|
||||
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||
type: "collection",
|
||||
id: "",
|
||||
parentID: "",
|
||||
})
|
||||
|
||||
// Used to determine if the collection is being dragged to a different destination
|
||||
// This is used to make the highlight effect work
|
||||
watch(
|
||||
() => dragging.value,
|
||||
(val) => {
|
||||
if (val && notSameDestination.value && notSameParentDestination.value) {
|
||||
emit("dragging", true)
|
||||
} else {
|
||||
emit("dragging", false)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const collectionIcon = computed(() => {
|
||||
if (props.isSelected) {
|
||||
return IconCheckCircle
|
||||
}
|
||||
return props.isOpen ? IconFolderOpen : IconFolder
|
||||
})
|
||||
|
||||
const notSameParentDestination = computed(() => {
|
||||
return (
|
||||
currentReorderingStatus.value.parentID !== props.collectionView.collectionID
|
||||
)
|
||||
})
|
||||
|
||||
const isRequestDragging = computed(() => {
|
||||
return currentReorderingStatus.value.type === "request"
|
||||
})
|
||||
|
||||
const isSameParent = computed(() => {
|
||||
return (
|
||||
currentReorderingStatus.value.parentID ===
|
||||
props.collectionView.parentCollectionID
|
||||
)
|
||||
})
|
||||
|
||||
const isReorderable = computed(() => {
|
||||
return (
|
||||
ordering.value &&
|
||||
notSameDestination.value &&
|
||||
!isRequestDragging.value &&
|
||||
isSameParent.value
|
||||
)
|
||||
})
|
||||
const isLastItemReorderable = computed(() => {
|
||||
return (
|
||||
orderingLastItem.value &&
|
||||
notSameDestination.value &&
|
||||
!isRequestDragging.value &&
|
||||
isSameParent.value
|
||||
)
|
||||
})
|
||||
|
||||
const addChildCollection = () => {
|
||||
emit("add-child-collection", props.collectionView.collectionID)
|
||||
}
|
||||
|
||||
const addRequest = () => {
|
||||
emit("add-request", props.collectionView.collectionID)
|
||||
}
|
||||
|
||||
const editCollection = () => {
|
||||
const { collectionID: collectionIndexPath, name: collectionName } =
|
||||
props.collectionView
|
||||
|
||||
const data = {
|
||||
collectionIndexPath,
|
||||
collectionName,
|
||||
}
|
||||
|
||||
collectionIndexPath.split("/").length > 1
|
||||
? emit("edit-child-collection", data)
|
||||
: emit("edit-root-collection", data)
|
||||
}
|
||||
|
||||
const dragStart = ({ dataTransfer }: DragEvent) => {
|
||||
if (dataTransfer) {
|
||||
emit("drag-event", dataTransfer)
|
||||
|
||||
dropItemID.value = dataTransfer.getData("collectionIndex")
|
||||
dragging.value = !dragging.value
|
||||
|
||||
changeCurrentReorderStatus({
|
||||
type: "collection",
|
||||
id: props.collectionView.collectionID,
|
||||
parentID: props.collectionView.parentCollectionID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the re-ordering event when a collection is dragged over another collection's top section
|
||||
const handleDragOver = (e: DragEvent) => {
|
||||
dragging.value = true
|
||||
if (
|
||||
e.offsetY < 10 &&
|
||||
notSameDestination.value &&
|
||||
!isRequestDragging.value &&
|
||||
isSameParent.value
|
||||
) {
|
||||
ordering.value = true
|
||||
dragging.value = false
|
||||
orderingLastItem.value = false
|
||||
} else if (
|
||||
e.offsetY > 18 &&
|
||||
notSameDestination.value &&
|
||||
!isRequestDragging.value &&
|
||||
isSameParent.value &&
|
||||
props.collectionView.isLastItem
|
||||
) {
|
||||
orderingLastItem.value = true
|
||||
dragging.value = false
|
||||
ordering.value = false
|
||||
} else {
|
||||
ordering.value = false
|
||||
orderingLastItem.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleDrop = (e: DragEvent) => {
|
||||
if (ordering.value) {
|
||||
orderUpdateCollectionEvent(e)
|
||||
} else if (orderingLastItem.value) {
|
||||
updateLastItemOrder(e)
|
||||
} else {
|
||||
notSameParentDestination.value ? dropEvent(e) : e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
const dropEvent = (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.stopPropagation()
|
||||
emit("drop-event", e.dataTransfer)
|
||||
resetDragState()
|
||||
}
|
||||
}
|
||||
|
||||
const orderUpdateCollectionEvent = (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.stopPropagation()
|
||||
emit("update-collection-order", e.dataTransfer)
|
||||
resetDragState()
|
||||
}
|
||||
}
|
||||
|
||||
const updateLastItemOrder = (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.stopPropagation()
|
||||
emit("update-last-collection-order", e.dataTransfer)
|
||||
resetDragState()
|
||||
}
|
||||
}
|
||||
|
||||
const notSameDestination = computed(() => {
|
||||
return dropItemID.value !== props.collectionView.collectionID
|
||||
})
|
||||
|
||||
const removeCollection = () => {
|
||||
const { collectionID } = props.collectionView
|
||||
|
||||
collectionID.split("/").length > 1
|
||||
? emit("remove-child-collection", collectionID)
|
||||
: emit("remove-root-collection", collectionID)
|
||||
}
|
||||
|
||||
const resetDragState = () => {
|
||||
dragging.value = false
|
||||
ordering.value = false
|
||||
orderingLastItem.value = false
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,334 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div
|
||||
class="h-1 w-full transition"
|
||||
:class="[
|
||||
{
|
||||
'bg-accentDark': isReorderable,
|
||||
},
|
||||
]"
|
||||
@drop="updateRequestOrder"
|
||||
@dragover.prevent="ordering = true"
|
||||
@dragleave="resetDragState"
|
||||
@dragend="resetDragState"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="group flex items-stretch"
|
||||
:draggable="true"
|
||||
@dragstart="dragStart"
|
||||
@dragover="handleDragOver($event)"
|
||||
@dragleave="resetDragState"
|
||||
@dragend="resetDragState"
|
||||
@drop="handleDrop"
|
||||
@contextmenu.prevent="options?.tippy?.show()"
|
||||
>
|
||||
<div
|
||||
class="pointer-events-auto flex min-w-0 flex-1 cursor-pointer items-center justify-center"
|
||||
@click="selectRequest"
|
||||
>
|
||||
<span
|
||||
class="pointer-events-none flex w-16 items-center justify-center truncate px-2"
|
||||
:class="requestLabelColor"
|
||||
:style="{ color: requestLabelColor }"
|
||||
>
|
||||
<component
|
||||
:is="IconCheckCircle"
|
||||
v-if="isSelected"
|
||||
class="svg-icons"
|
||||
:class="{ 'text-accent': isSelected }"
|
||||
/>
|
||||
<span v-else class="truncate text-tiny font-semibold">
|
||||
{{ requestView.request.method }}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="pointer-events-none flex min-w-0 flex-1 items-center py-2 pr-2 transition group-hover:text-secondaryDark"
|
||||
>
|
||||
<span class="truncate" :class="{ 'text-accent': isSelected }">
|
||||
{{ requestView.request.name }}
|
||||
</span>
|
||||
<span
|
||||
v-if="props.isActive"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
class="relative mx-3 flex h-1.5 w-1.5 flex-shrink-0"
|
||||
:title="`${t('collection.request_in_use')}`"
|
||||
>
|
||||
<span
|
||||
class="absolute inline-flex h-full w-full flex-shrink-0 animate-ping rounded-full bg-green-500 opacity-75"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="relative inline-flex h-1.5 w-1.5 flex-shrink-0 rounded-full bg-green-500"
|
||||
></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconRotateCCW"
|
||||
:title="t('action.restore')"
|
||||
class="hidden group-hover:inline-flex"
|
||||
@click="selectRequest"
|
||||
/>
|
||||
<span>
|
||||
<tippy
|
||||
ref="options"
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions?.focus()"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="t('action.more')"
|
||||
:icon="IconMoreVertical"
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
class="flex flex-col focus:outline-none"
|
||||
tabindex="0"
|
||||
@keyup.e="edit?.$el.click()"
|
||||
@keyup.d="duplicate?.$el.click()"
|
||||
@keyup.delete="deleteAction?.$el.click()"
|
||||
@keyup.s="shareAction?.$el.click()"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<HoppSmartItem
|
||||
ref="edit"
|
||||
:icon="IconEdit"
|
||||
:label="t('action.edit')"
|
||||
:shortcut="['E']"
|
||||
@click="
|
||||
() => {
|
||||
emit('edit-request', {
|
||||
requestIndexPath: requestView.requestID,
|
||||
requestName: requestView.request.name,
|
||||
})
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="duplicate"
|
||||
:icon="IconCopy"
|
||||
:label="t('action.duplicate')"
|
||||
:shortcut="['D']"
|
||||
@click="
|
||||
() => {
|
||||
emit('duplicate-request', requestView.requestID)
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="deleteAction"
|
||||
:icon="IconTrash2"
|
||||
:label="t('action.delete')"
|
||||
:shortcut="['⌫']"
|
||||
@click="
|
||||
() => {
|
||||
emit('remove-request', requestView.requestID)
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
<HoppSmartItem
|
||||
ref="shareAction"
|
||||
:icon="IconShare2"
|
||||
:label="t('action.share')"
|
||||
:shortcut="['S']"
|
||||
@click="
|
||||
() => {
|
||||
emit('share-request', requestView.request)
|
||||
hide()
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="w-full transition"
|
||||
:class="[
|
||||
{
|
||||
'bg-accentDark': isLastItemReorderable,
|
||||
'h-1 ': props.requestView.isLastItem,
|
||||
},
|
||||
]"
|
||||
@drop="handleDrop"
|
||||
@dragover.prevent="orderingLastItem = true"
|
||||
@dragleave="resetDragState"
|
||||
@dragend="resetDragState"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
import { computed, ref } from "vue"
|
||||
import { TippyComponent } from "vue-tippy"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
|
||||
import { getMethodLabelColorClassOf } from "~/helpers/rest/labelColoring"
|
||||
import {
|
||||
currentReorderingStatus$,
|
||||
changeCurrentReorderStatus,
|
||||
} from "~/newstore/reordering"
|
||||
import { RESTCollectionViewRequest } from "~/services/new-workspace/view"
|
||||
|
||||
import IconCheckCircle from "~icons/lucide/check-circle"
|
||||
import IconCopy from "~icons/lucide/copy"
|
||||
import IconEdit from "~icons/lucide/edit"
|
||||
import IconMoreVertical from "~icons/lucide/more-vertical"
|
||||
import IconRotateCCW from "~icons/lucide/rotate-ccw"
|
||||
import IconShare2 from "~icons/lucide/share-2"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
|
||||
type: "collection",
|
||||
id: "",
|
||||
parentID: "",
|
||||
})
|
||||
|
||||
const props = defineProps<{
|
||||
isActive: boolean
|
||||
requestView: RESTCollectionViewRequest
|
||||
isSelected: boolean | null | undefined
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "duplicate-request", requestIndexPath: string): void
|
||||
(
|
||||
event: "edit-request",
|
||||
payload: {
|
||||
requestIndexPath: string
|
||||
requestName: string
|
||||
}
|
||||
): void
|
||||
(event: "remove-request", requestIndexPath: string): void
|
||||
(event: "select-request", requestIndexPath: string): void
|
||||
(event: "share-request", request: HoppRESTRequest): void
|
||||
(event: "drag-request", payload: DataTransfer): void
|
||||
(event: "update-request-order", payload: DataTransfer): void
|
||||
(event: "update-last-request-order", payload: DataTransfer): void
|
||||
}>()
|
||||
|
||||
const tippyActions = ref<TippyComponent | null>(null)
|
||||
const edit = ref<HTMLButtonElement | null>(null)
|
||||
const deleteAction = ref<HTMLButtonElement | null>(null)
|
||||
const options = ref<TippyComponent | null>(null)
|
||||
const duplicate = ref<HTMLButtonElement | null>(null)
|
||||
const shareAction = ref<HTMLButtonElement | null>(null)
|
||||
|
||||
const dragging = ref(false)
|
||||
const ordering = ref(false)
|
||||
const orderingLastItem = ref(false)
|
||||
|
||||
const isCollectionDragging = computed(() => {
|
||||
return currentReorderingStatus.value.type === "collection"
|
||||
})
|
||||
|
||||
const isLastItemReorderable = computed(() => {
|
||||
return (
|
||||
orderingLastItem.value && isSameParent.value && !isCollectionDragging.value
|
||||
)
|
||||
})
|
||||
|
||||
const isReorderable = computed(() => {
|
||||
return (
|
||||
ordering.value &&
|
||||
!isCollectionDragging.value &&
|
||||
isSameParent.value &&
|
||||
!isSameRequest.value
|
||||
)
|
||||
})
|
||||
|
||||
const isSameParent = computed(() => {
|
||||
return (
|
||||
currentReorderingStatus.value.parentID === props.requestView.collectionID
|
||||
)
|
||||
})
|
||||
|
||||
const isSameRequest = computed(() => {
|
||||
return currentReorderingStatus.value.id === props.requestView.requestID
|
||||
})
|
||||
|
||||
const requestLabelColor = computed(() =>
|
||||
getMethodLabelColorClassOf(props.requestView.request)
|
||||
)
|
||||
|
||||
const dragStart = ({ dataTransfer }: DragEvent) => {
|
||||
if (dataTransfer) {
|
||||
emit("drag-request", dataTransfer)
|
||||
dragging.value = !dragging.value
|
||||
|
||||
changeCurrentReorderStatus({
|
||||
type: "request",
|
||||
id: props.requestView.requestID,
|
||||
parentID: props.requestView.collectionID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleDrop = (e: DragEvent) => {
|
||||
if (ordering.value) {
|
||||
updateRequestOrder(e)
|
||||
} else if (orderingLastItem.value) {
|
||||
updateLastItemOrder(e)
|
||||
} else {
|
||||
updateRequestOrder(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the re-ordering event when a request is dragged over another request's top section
|
||||
const handleDragOver = (e: DragEvent) => {
|
||||
dragging.value = true
|
||||
if (e.offsetY < 10) {
|
||||
ordering.value = true
|
||||
dragging.value = false
|
||||
orderingLastItem.value = false
|
||||
} else if (e.offsetY > 18) {
|
||||
orderingLastItem.value = true
|
||||
dragging.value = false
|
||||
ordering.value = false
|
||||
} else {
|
||||
ordering.value = false
|
||||
orderingLastItem.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const resetDragState = () => {
|
||||
dragging.value = false
|
||||
ordering.value = false
|
||||
orderingLastItem.value = false
|
||||
}
|
||||
|
||||
const selectRequest = () => emit("select-request", props.requestView.requestID)
|
||||
|
||||
const updateRequestOrder = (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.stopPropagation()
|
||||
resetDragState()
|
||||
emit("update-request-order", e.dataTransfer)
|
||||
}
|
||||
}
|
||||
|
||||
const updateLastItemOrder = (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.stopPropagation()
|
||||
resetDragState()
|
||||
emit("update-last-request-order", e.dataTransfer)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,13 +37,17 @@ import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { platform } from "~/platform"
|
||||
import { useService } from "dioc/vue"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { useLocalState } from "~/newstore/localstate"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const toast = useToast()
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
switchWorkspaceAfterCreation?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -52,8 +56,12 @@ const emit = defineEmits<{
|
||||
|
||||
const editingName = ref<string | null>(null)
|
||||
|
||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
|
||||
const addNewTeam = async () => {
|
||||
isLoading.value = true
|
||||
await pipe(
|
||||
@@ -76,8 +84,19 @@ const addNewTeam = async () => {
|
||||
// Handle GQL errors (use err obj)
|
||||
}
|
||||
},
|
||||
() => {
|
||||
(team) => {
|
||||
toast.success(`${t("team.new_created")}`)
|
||||
|
||||
if (props.switchWorkspaceAfterCreation) {
|
||||
REMEMBERED_TEAM_ID.value = team.id
|
||||
workspaceService.changeWorkspace({
|
||||
teamID: team.id,
|
||||
teamName: team.name,
|
||||
type: "team",
|
||||
role: team.myRole,
|
||||
})
|
||||
}
|
||||
|
||||
hideModal()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class="flex items-center overflow-x-auto whitespace-nowrap border-b border-dividerLight px-4 py-2 text-tiny text-secondaryLight"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ currentWorkspace }}
|
||||
{{ workspaceName ?? t("workspace.no_workspace") }}
|
||||
</span>
|
||||
<icon-lucide-chevron-right v-if="section" class="mx-2" />
|
||||
{{ section }}
|
||||
@@ -14,29 +14,24 @@
|
||||
import { computed } from "vue"
|
||||
import { useI18n } from "~/composables/i18n"
|
||||
import { useService } from "dioc/vue"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
|
||||
const props = defineProps<{
|
||||
defineProps<{
|
||||
section?: string
|
||||
isOnlyPersonal?: boolean
|
||||
}>()
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
const workspace = workspaceService.currentWorkspace
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle
|
||||
|
||||
const currentWorkspace = computed(() => {
|
||||
if (props.isOnlyPersonal || workspace.value.type === "personal") {
|
||||
return t("workspace.personal")
|
||||
}
|
||||
return teamWorkspaceName.value
|
||||
})
|
||||
const workspaceName = computed(() => {
|
||||
const activeWorkspaceHandleRef = activeWorkspaceHandle.value?.get()
|
||||
|
||||
const teamWorkspaceName = computed(() => {
|
||||
if (workspace.value.type === "team" && workspace.value.teamName) {
|
||||
return workspace.value.teamName
|
||||
if (activeWorkspaceHandleRef?.value.type === "ok") {
|
||||
return activeWorkspaceHandleRef.value.data.name
|
||||
}
|
||||
return `${t("workspace.team")}`
|
||||
|
||||
return undefined
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex flex-col">
|
||||
<HoppSmartItem
|
||||
:label="'Personal Workspace'"
|
||||
:info-icon="
|
||||
activeWorkspaceInfo?.provider ===
|
||||
personalWorkspaceProviderService.providerID &&
|
||||
activeWorkspaceInfo.workspaceID === 'personal'
|
||||
? IconCheck
|
||||
: undefined
|
||||
"
|
||||
:active-info-icon="
|
||||
activeWorkspaceInfo?.provider ===
|
||||
personalWorkspaceProviderService.providerID &&
|
||||
activeWorkspaceInfo.workspaceID === 'personal'
|
||||
"
|
||||
@click="selectWorkspace"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useService } from "dioc/vue"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { computed } from "vue"
|
||||
import { PersonalWorkspaceProviderService } from "~/services/new-workspace/providers/personal.workspace"
|
||||
import IconCheck from "~icons/lucide/check"
|
||||
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
const personalWorkspaceProviderService = useService(
|
||||
PersonalWorkspaceProviderService
|
||||
)
|
||||
|
||||
const activeWorkspaceInfo = computed(() => {
|
||||
const activeWorkspaceHandleRef =
|
||||
workspaceService.activeWorkspaceHandle.value?.get()
|
||||
|
||||
if (activeWorkspaceHandleRef?.value.type === "ok") {
|
||||
return {
|
||||
provider: activeWorkspaceHandleRef.value.data.providerID,
|
||||
workspaceID: activeWorkspaceHandleRef.value.data.workspaceID,
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
function selectWorkspace() {
|
||||
workspaceService.activeWorkspaceHandle.value =
|
||||
personalWorkspaceProviderService.getPersonalWorkspaceHandle()
|
||||
}
|
||||
</script>
|
||||
@@ -1,190 +1,36 @@
|
||||
<template>
|
||||
<div ref="rootEl">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<HoppSmartItem
|
||||
:label="t('workspace.personal')"
|
||||
:icon="IconUser"
|
||||
:info-icon="workspace.type === 'personal' ? IconDone : undefined"
|
||||
:active-info-icon="workspace.type === 'personal'"
|
||||
@click="switchToPersonalWorkspace"
|
||||
/>
|
||||
<div
|
||||
v-for="(selectorComponent, index) in workspaceSelectorComponents"
|
||||
:key="index"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<component :is="selectorComponent" />
|
||||
<hr />
|
||||
</div>
|
||||
<div v-if="loading" class="flex flex-col items-center justify-center p-4">
|
||||
<HoppSmartSpinner class="mb-4" />
|
||||
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
||||
</div>
|
||||
<HoppSmartPlaceholder
|
||||
v-if="!loading && myTeams.length === 0"
|
||||
:src="`/images/states/${colorMode.value}/add_group.svg`"
|
||||
:alt="`${t('empty.teams')}`"
|
||||
:text="`${t('empty.teams')}`"
|
||||
>
|
||||
<template #body>
|
||||
<HoppButtonSecondary
|
||||
:label="t('team.create_new')"
|
||||
filled
|
||||
outline
|
||||
:icon="IconPlus"
|
||||
@click="displayModalAdd(true)"
|
||||
/>
|
||||
</template>
|
||||
</HoppSmartPlaceholder>
|
||||
<div v-else-if="!loading" class="flex flex-col">
|
||||
<div
|
||||
class="sticky top-0 z-10 mb-2 flex items-center justify-between bg-popover py-2 pl-2"
|
||||
>
|
||||
<div class="flex items-center px-2 font-semibold text-secondaryLight">
|
||||
{{ t("workspace.other_workspaces") }}
|
||||
</div>
|
||||
<HoppButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:icon="IconPlus"
|
||||
:title="`${t('team.create_new')}`"
|
||||
outline
|
||||
filled
|
||||
class="ml-8 rounded !p-0.75"
|
||||
@click="displayModalAdd(true)"
|
||||
/>
|
||||
</div>
|
||||
<HoppSmartItem
|
||||
v-for="(team, index) in myTeams"
|
||||
:key="`team-${String(index)}`"
|
||||
:icon="IconUsers"
|
||||
:label="team.name"
|
||||
:info-icon="isActiveWorkspace(team.id) ? IconDone : undefined"
|
||||
:active-info-icon="isActiveWorkspace(team.id)"
|
||||
@click="switchToTeamWorkspace(team)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!loading && teamListAdapterError"
|
||||
class="flex flex-col items-center py-4"
|
||||
>
|
||||
<icon-lucide-help-circle class="svg-icons mb-4" />
|
||||
{{ t("error.something_went_wrong") }}
|
||||
</div>
|
||||
</div>
|
||||
<TeamsAdd :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { platform } from "~/platform"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import IconUser from "~icons/lucide/user"
|
||||
import IconUsers from "~icons/lucide/users"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
import IconDone from "~icons/lucide/check"
|
||||
import { useLocalState } from "~/newstore/localstate"
|
||||
import { defineActionHandler } from "~/helpers/actions"
|
||||
import { WorkspaceService } from "~/services/workspace.service"
|
||||
import { useService } from "dioc/vue"
|
||||
import { useElementVisibility, useIntervalFn } from "@vueuse/core"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { TestWorkspaceProviderService } from "~/services/new-workspace/providers/test.workspace"
|
||||
|
||||
const t = useI18n()
|
||||
const colorMode = useColorMode()
|
||||
useService(TestWorkspaceProviderService)
|
||||
|
||||
const showModalAdd = ref(false)
|
||||
const newWorkspaceService = useService(NewWorkspaceService)
|
||||
const workspaceSelectorComponents =
|
||||
newWorkspaceService.workspaceSelectorComponents
|
||||
|
||||
const currentUser = useReadonlyStream(
|
||||
platform.auth.getProbableUserStream(),
|
||||
platform.auth.getProbableUser()
|
||||
)
|
||||
|
||||
const workspaceService = useService(WorkspaceService)
|
||||
const teamListadapter = workspaceService.acquireTeamListAdapter(null)
|
||||
const myTeams = useReadonlyStream(teamListadapter.teamList$, [])
|
||||
const isTeamListLoading = useReadonlyStream(teamListadapter.loading$, false)
|
||||
const teamListAdapterError = useReadonlyStream(teamListadapter.error$, null)
|
||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||
const teamListFetched = ref(false)
|
||||
|
||||
const rootEl = ref<HTMLElement>()
|
||||
const elVisible = useElementVisibility(rootEl)
|
||||
|
||||
const { pause: pauseListPoll, resume: resumeListPoll } = useIntervalFn(() => {
|
||||
if (teamListadapter.isInitialized) {
|
||||
teamListadapter.fetchList()
|
||||
}
|
||||
}, 10000)
|
||||
|
||||
watch(
|
||||
elVisible,
|
||||
() => {
|
||||
if (elVisible.value) {
|
||||
teamListadapter.fetchList()
|
||||
|
||||
resumeListPoll()
|
||||
} else {
|
||||
pauseListPoll()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(myTeams, (teams) => {
|
||||
if (teams && !teamListFetched.value) {
|
||||
teamListFetched.value = true
|
||||
if (REMEMBERED_TEAM_ID.value && currentUser.value) {
|
||||
const team = teams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
||||
if (team) switchToTeamWorkspace(team)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const loading = computed(
|
||||
() => isTeamListLoading.value && myTeams.value.length === 0
|
||||
)
|
||||
|
||||
const workspace = workspaceService.currentWorkspace
|
||||
|
||||
const isActiveWorkspace = computed(() => (id: string) => {
|
||||
if (workspace.value.type === "personal") return false
|
||||
return workspace.value.teamID === id
|
||||
})
|
||||
|
||||
const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
||||
REMEMBERED_TEAM_ID.value = team.id
|
||||
workspaceService.changeWorkspace({
|
||||
teamID: team.id,
|
||||
teamName: team.name,
|
||||
type: "team",
|
||||
})
|
||||
}
|
||||
|
||||
const switchToPersonalWorkspace = () => {
|
||||
REMEMBERED_TEAM_ID.value = undefined
|
||||
workspaceService.changeWorkspace({
|
||||
type: "personal",
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => currentUser.value,
|
||||
(user) => {
|
||||
if (!user) {
|
||||
switchToPersonalWorkspace()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const displayModalAdd = (shouldDisplay: boolean) => {
|
||||
showModalAdd.value = shouldDisplay
|
||||
teamListadapter.fetchList()
|
||||
}
|
||||
|
||||
defineActionHandler("modals.team.new", () => {
|
||||
displayModalAdd(true)
|
||||
})
|
||||
|
||||
defineActionHandler("workspace.switch.personal", switchToPersonalWorkspace)
|
||||
defineActionHandler("workspace.switch", ({ teamId }) => {
|
||||
const team = myTeams.value.find((t) => t.id === teamId)
|
||||
if (team) switchToTeamWorkspace(team)
|
||||
})
|
||||
// TODO: Handle the updates to these actions
|
||||
// defineActionHandler("modals.team.new", () => {
|
||||
// displayModalAdd(true)
|
||||
// })
|
||||
//
|
||||
// defineActionHandler("workspace.switch.personal", switchToPersonalWorkspace)
|
||||
// defineActionHandler("workspace.switch", ({ teamId }) => {
|
||||
// const team = myTeams.value.find((t) => t.id === teamId)
|
||||
// if (team) switchToTeamWorkspace(team)
|
||||
// })
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex flex-col">
|
||||
<HoppSmartItem
|
||||
v-for="candidate in candidates"
|
||||
:key="candidate.id"
|
||||
:label="candidate.name"
|
||||
:info-icon="
|
||||
activeWorkspaceInfo?.provider ===
|
||||
testWorkspaceProviderService.providerID &&
|
||||
activeWorkspaceInfo.workspaceID === candidate.id
|
||||
? IconCheck
|
||||
: undefined
|
||||
"
|
||||
:active-info-icon="
|
||||
activeWorkspaceInfo?.provider ===
|
||||
testWorkspaceProviderService.providerID &&
|
||||
activeWorkspaceInfo.workspaceID === candidate.id
|
||||
"
|
||||
@click="selectWorkspace(candidate.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useService } from "dioc/vue"
|
||||
import { computed } from "vue"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { TestWorkspaceProviderService } from "~/services/new-workspace/providers/test.workspace"
|
||||
import IconCheck from "~icons/lucide/check"
|
||||
import * as E from "fp-ts/Either"
|
||||
|
||||
const workspaceService = useService(NewWorkspaceService)
|
||||
const testWorkspaceProviderService = useService(TestWorkspaceProviderService)
|
||||
|
||||
const candidates = testWorkspaceProviderService.getWorkspaceCandidates()
|
||||
|
||||
const activeWorkspaceInfo = computed(() => {
|
||||
const activeWorkspaceHandle = workspaceService.activeWorkspaceHandle.value
|
||||
const activeWorkspaceHandleRef = activeWorkspaceHandle?.get()
|
||||
|
||||
if (activeWorkspaceHandleRef?.value.type === "ok") {
|
||||
return {
|
||||
provider: activeWorkspaceHandleRef.value.data.providerID,
|
||||
workspaceID: activeWorkspaceHandleRef.value.data.workspaceID,
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
async function selectWorkspace(workspaceID: string) {
|
||||
const result =
|
||||
await testWorkspaceProviderService.getWorkspaceHandle(workspaceID)
|
||||
|
||||
// TODO: Re-evaluate this ?
|
||||
if (E.isLeft(result)) {
|
||||
console.error(result)
|
||||
return
|
||||
}
|
||||
|
||||
workspaceService.activeWorkspaceHandle.value = result.right
|
||||
}
|
||||
</script>
|
||||
@@ -36,6 +36,7 @@ export type HoppAction =
|
||||
| "collection.new" // Create root collection
|
||||
| "flyouts.chat.open" // Shows the keybinds flyout
|
||||
| "flyouts.keybinds.toggle" // Shows the keybinds flyout
|
||||
| "modals.collection.import" // Shows the collection import modal
|
||||
| "modals.search.toggle" // Shows the search modal
|
||||
| "modals.support.toggle" // Shows the support modal
|
||||
| "modals.share.toggle" // Shows the share modal
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import { HoppCollection } from "@hoppscotch/data"
|
||||
import { ChildrenResult, SmartTreeAdapter } from "@hoppscotch/ui"
|
||||
import { Ref, computed, ref } from "vue"
|
||||
import { navigateToFolderWithIndexPath } from "~/newstore/collections"
|
||||
import { RESTCollectionViewItem } from "~/services/new-workspace/view"
|
||||
|
||||
export class WorkspaceRESTSearchCollectionTreeAdapter
|
||||
implements SmartTreeAdapter<RESTCollectionViewItem>
|
||||
{
|
||||
constructor(public data: Ref<HoppCollection[]>) {}
|
||||
|
||||
getChildren(
|
||||
nodeID: string | null
|
||||
): Ref<ChildrenResult<RESTCollectionViewItem>> {
|
||||
const result = ref<ChildrenResult<RESTCollectionViewItem>>({
|
||||
status: "loading",
|
||||
})
|
||||
|
||||
return computed(() => {
|
||||
if (nodeID === null) {
|
||||
result.value = {
|
||||
status: "loaded",
|
||||
data: this.data.value.map((item, index) => ({
|
||||
id: index.toString(),
|
||||
|
||||
data: <RESTCollectionViewItem>{
|
||||
type: "collection",
|
||||
value: {
|
||||
collectionID: index.toString(),
|
||||
isLastItem: index === this.data.value.length - 1,
|
||||
name: item.name,
|
||||
parentCollectionID: null,
|
||||
},
|
||||
},
|
||||
})),
|
||||
}
|
||||
} else {
|
||||
const indexPath = nodeID.split("/").map((x) => parseInt(x))
|
||||
|
||||
const item = navigateToFolderWithIndexPath(this.data.value, indexPath)
|
||||
|
||||
if (item) {
|
||||
const collections = item.folders.map(
|
||||
(childCollection, childCollectionID) => {
|
||||
return {
|
||||
id: `${nodeID}/${childCollectionID}`,
|
||||
data: <RESTCollectionViewItem>{
|
||||
type: "collection",
|
||||
value: {
|
||||
isLastItem:
|
||||
item.folders?.length > 1
|
||||
? childCollectionID === item.folders.length - 1
|
||||
: false,
|
||||
collectionID: `${nodeID}/${childCollectionID}`,
|
||||
name: childCollection.name,
|
||||
parentCollectionID: nodeID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const requests = item.requests.map((request, requestID) => {
|
||||
return {
|
||||
id: `${nodeID}/${requestID}`,
|
||||
data: <RESTCollectionViewItem>{
|
||||
type: "request",
|
||||
value: {
|
||||
isLastItem:
|
||||
item.requests?.length > 1
|
||||
? requestID === item.requests.length - 1
|
||||
: false,
|
||||
parentCollectionID: nodeID,
|
||||
collectionID: nodeID,
|
||||
requestID: `${nodeID}/${requestID}`,
|
||||
request,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
result.value = {
|
||||
status: "loaded",
|
||||
data: [...collections, ...requests],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.value
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import {
|
||||
ChildrenResult,
|
||||
SmartTreeAdapter,
|
||||
} from "@hoppscotch/ui/dist/src/helpers/treeAdapter"
|
||||
import * as E from "fp-ts/Either"
|
||||
import { Ref, ref, watchEffect } from "vue"
|
||||
import { NewWorkspaceService } from "~/services/new-workspace"
|
||||
import { Handle } from "~/services/new-workspace/handle"
|
||||
import { RESTCollectionViewItem } from "~/services/new-workspace/view"
|
||||
import { Workspace } from "~/services/new-workspace/workspace"
|
||||
|
||||
export class WorkspaceRESTCollectionTreeAdapter
|
||||
implements SmartTreeAdapter<RESTCollectionViewItem>
|
||||
{
|
||||
constructor(
|
||||
private workspaceHandle: Handle<Workspace>,
|
||||
private workspaceService: NewWorkspaceService
|
||||
) {}
|
||||
|
||||
public getChildren(
|
||||
nodeID: string | null,
|
||||
nodeType?: string
|
||||
): Ref<ChildrenResult<RESTCollectionViewItem>> {
|
||||
const workspaceHandleRef = this.workspaceHandle.get()
|
||||
|
||||
if (workspaceHandleRef.value.type !== "ok") {
|
||||
throw new Error("Cannot issue children with invalid workspace handle")
|
||||
}
|
||||
|
||||
const result = ref<ChildrenResult<RESTCollectionViewItem>>({
|
||||
status: "loading",
|
||||
})
|
||||
|
||||
if (nodeID !== null) {
|
||||
;(async () => {
|
||||
if (nodeType === "request") {
|
||||
result.value = {
|
||||
status: "loaded",
|
||||
data: [],
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const collectionHandleResult =
|
||||
await this.workspaceService.getCollectionHandle(
|
||||
this.workspaceHandle,
|
||||
nodeID
|
||||
)
|
||||
|
||||
// TODO: Better error handling
|
||||
if (E.isLeft(collectionHandleResult)) {
|
||||
throw new Error(JSON.stringify(collectionHandleResult.left.error))
|
||||
}
|
||||
|
||||
const collectionHandle = collectionHandleResult.right
|
||||
|
||||
const collectionChildrenResult =
|
||||
await this.workspaceService.getRESTCollectionChildrenView(
|
||||
collectionHandle
|
||||
)
|
||||
|
||||
// TODO: Better error handling
|
||||
if (E.isLeft(collectionChildrenResult)) {
|
||||
throw new Error(JSON.stringify(collectionChildrenResult.left.error))
|
||||
}
|
||||
|
||||
const collectionChildrenViewHandle =
|
||||
collectionChildrenResult.right.get()
|
||||
|
||||
watchEffect(() => {
|
||||
if (collectionChildrenViewHandle.value.type !== "ok") return
|
||||
|
||||
if (collectionChildrenViewHandle.value.data.loading.value) {
|
||||
result.value = {
|
||||
status: "loading",
|
||||
}
|
||||
} else {
|
||||
result.value = {
|
||||
status: "loaded",
|
||||
data: collectionChildrenViewHandle.value.data.content.value.map(
|
||||
(item) => ({
|
||||
id:
|
||||
item.type === "request"
|
||||
? item.value.requestID
|
||||
: item.value.collectionID,
|
||||
|
||||
data: item,
|
||||
})
|
||||
),
|
||||
}
|
||||
}
|
||||
})
|
||||
})()
|
||||
} else {
|
||||
;(async () => {
|
||||
const viewResult =
|
||||
await this.workspaceService.getRESTRootCollectionView(
|
||||
this.workspaceHandle
|
||||
)
|
||||
|
||||
// TODO: Better error handling
|
||||
if (E.isLeft(viewResult)) {
|
||||
throw new Error(JSON.stringify(viewResult.left.error))
|
||||
}
|
||||
|
||||
const viewHandle = viewResult.right.get()
|
||||
|
||||
watchEffect(() => {
|
||||
if (viewHandle.value.type !== "ok") return
|
||||
|
||||
if (viewHandle.value.data.loading.value) {
|
||||
result.value = {
|
||||
status: "loading",
|
||||
}
|
||||
} else {
|
||||
result.value = {
|
||||
status: "loaded",
|
||||
data: viewHandle.value.data.collections.value.map((coll) => ({
|
||||
id: coll.collectionID,
|
||||
|
||||
data: {
|
||||
type: "collection",
|
||||
value: coll,
|
||||
},
|
||||
})),
|
||||
}
|
||||
}
|
||||
})
|
||||
})()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
import { HoppCollection } from "@hoppscotch/data"
|
||||
import { getAffectedIndexes } from "./affectedIndex"
|
||||
import { GetSingleRequestDocument } from "../backend/graphql"
|
||||
import { runGQLQuery } from "../backend/GQLClient"
|
||||
import * as E from "fp-ts/Either"
|
||||
|
||||
import { getService } from "~/modules/dioc"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||
import { GQLTabService } from "~/services/tab/graphql"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { runGQLQuery } from "../backend/GQLClient"
|
||||
import { GetSingleRequestDocument } from "../backend/graphql"
|
||||
import { HoppGQLSaveContext } from "../graphql/document"
|
||||
import { HoppRESTSaveContext } from "../rest/document"
|
||||
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||
import { getAffectedIndexes } from "./affectedIndex"
|
||||
|
||||
/**
|
||||
* Resolve save context on reorder
|
||||
@@ -18,15 +21,12 @@ import { GQLTabService } from "~/services/tab/graphql"
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export function resolveSaveContextOnCollectionReorder(
|
||||
payload: {
|
||||
lastIndex: number
|
||||
newIndex: number
|
||||
folderPath: string
|
||||
length?: number // better way to do this? now it could be undefined
|
||||
},
|
||||
type: "remove" | "drop" = "remove"
|
||||
) {
|
||||
export function resolveSaveContextOnCollectionReorder(payload: {
|
||||
lastIndex: number
|
||||
newIndex: number
|
||||
folderPath: string
|
||||
length?: number // better way to do this? now it could be undefined
|
||||
}) {
|
||||
const { lastIndex, folderPath, length } = payload
|
||||
let { newIndex } = payload
|
||||
|
||||
@@ -41,12 +41,6 @@ export function resolveSaveContextOnCollectionReorder(
|
||||
if (newIndex === -1) {
|
||||
// if (newIndex === -1) remove it from the map because it will be deleted
|
||||
affectedIndexes.delete(lastIndex)
|
||||
// when collection deleted opended requests from that collection be affected
|
||||
if (type === "remove") {
|
||||
resetSaveContextForAffectedRequests(
|
||||
folderPath ? `${folderPath}/${lastIndex}` : lastIndex.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// add folder path as prefix to the affected indexes
|
||||
@@ -62,10 +56,27 @@ export function resolveSaveContextOnCollectionReorder(
|
||||
const tabService = getService(RESTTabService)
|
||||
|
||||
const tabs = tabService.getTabsRefTo((tab) => {
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||
affectedPaths.has(tab.document.saveContext.folderPath)
|
||||
)
|
||||
if (tab.document.saveContext?.originLocation === "user-collection") {
|
||||
return affectedPaths.has(tab.document.saveContext.folderPath)
|
||||
}
|
||||
|
||||
if (
|
||||
tab.document.saveContext?.originLocation !== "workspace-user-collection"
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
const requestHandleRef = tab.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return false
|
||||
}
|
||||
|
||||
const { requestID } = requestHandleRef.value.data
|
||||
|
||||
const collectionID = requestID.split("/").slice(0, -1).join("/")
|
||||
|
||||
return affectedPaths.has(collectionID)
|
||||
})
|
||||
|
||||
for (const tab of tabs) {
|
||||
@@ -75,6 +86,34 @@ export function resolveSaveContextOnCollectionReorder(
|
||||
)!
|
||||
tab.value.document.saveContext.folderPath = newPath
|
||||
}
|
||||
|
||||
if (
|
||||
tab.value.document.saveContext?.originLocation !==
|
||||
"workspace-user-collection"
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
const requestHandleRef = tab.value.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return false
|
||||
}
|
||||
|
||||
const { requestID } = requestHandleRef.value.data
|
||||
|
||||
const collectionID = requestID.split("/").slice(0, -1).join("/")
|
||||
|
||||
const newCollectionID = affectedPaths.get(collectionID)
|
||||
const newRequestID = `${newCollectionID}/${
|
||||
requestID.split("/").slice(-1)[0]
|
||||
}`
|
||||
|
||||
requestHandleRef.value.data = {
|
||||
...requestHandleRef.value.data,
|
||||
collectionID: newCollectionID!,
|
||||
requestID: newRequestID,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,25 +125,63 @@ export function resolveSaveContextOnCollectionReorder(
|
||||
*/
|
||||
|
||||
export function updateSaveContextForAffectedRequests(
|
||||
oldFolderPath: string,
|
||||
newFolderPath: string
|
||||
draggedCollectionIndex: string,
|
||||
destinationCollectionIndex: string
|
||||
) {
|
||||
const tabService = getService(RESTTabService)
|
||||
const tabs = tabService.getTabsRefTo((tab) => {
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||
tab.document.saveContext.folderPath.startsWith(oldFolderPath)
|
||||
)
|
||||
})
|
||||
|
||||
for (const tab of tabs) {
|
||||
if (tab.value.document.saveContext?.originLocation === "user-collection") {
|
||||
tab.value.document.saveContext = {
|
||||
...tab.value.document.saveContext,
|
||||
folderPath: tab.value.document.saveContext.folderPath.replace(
|
||||
oldFolderPath,
|
||||
newFolderPath
|
||||
),
|
||||
const activeTabs = tabService.getActiveTabs()
|
||||
|
||||
for (const tab of activeTabs.value) {
|
||||
if (tab.document.saveContext?.originLocation === "user-collection") {
|
||||
const { folderPath } = tab.document.saveContext
|
||||
|
||||
if (folderPath.startsWith(draggedCollectionIndex)) {
|
||||
const newFolderPath = folderPath.replace(
|
||||
draggedCollectionIndex,
|
||||
destinationCollectionIndex
|
||||
)
|
||||
|
||||
tab.document.saveContext = {
|
||||
...tab.document.saveContext,
|
||||
folderPath: newFolderPath,
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
tab.document.saveContext?.originLocation === "workspace-user-collection"
|
||||
) {
|
||||
const requestHandleRef = tab.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return false
|
||||
}
|
||||
|
||||
const { requestID } = requestHandleRef.value.data
|
||||
|
||||
const collectionID = requestID.split("/").slice(0, -1).join("/")
|
||||
const requestIndex = requestID.split("/").slice(-1)[0]
|
||||
|
||||
if (collectionID.startsWith(draggedCollectionIndex)) {
|
||||
const newCollectionID = collectionID.replace(
|
||||
draggedCollectionIndex,
|
||||
destinationCollectionIndex
|
||||
)
|
||||
const newRequestID = `${newCollectionID}/${requestIndex}`
|
||||
|
||||
tab.document.saveContext = {
|
||||
...tab.document.saveContext,
|
||||
requestID: newRequestID,
|
||||
}
|
||||
|
||||
requestHandleRef.value.data = {
|
||||
...requestHandleRef.value.data,
|
||||
collectionID: newCollectionID,
|
||||
requestID: newRequestID,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,6 +243,33 @@ function removeDuplicatesAndKeepLast(arr: HoppInheritedProperty["headers"]) {
|
||||
return result
|
||||
}
|
||||
|
||||
function getSaveContextCollectionID(
|
||||
saveContext: HoppRESTSaveContext | HoppGQLSaveContext | undefined
|
||||
): string | undefined {
|
||||
if (!saveContext) {
|
||||
return
|
||||
}
|
||||
|
||||
const { originLocation } = saveContext
|
||||
|
||||
if (originLocation === "team-collection") {
|
||||
return saveContext.collectionID
|
||||
}
|
||||
|
||||
if (originLocation === "user-collection") {
|
||||
return saveContext.folderPath
|
||||
}
|
||||
|
||||
const requestHandleRef = saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Remove `collectionID` and obtain it from `requestID`
|
||||
return requestHandleRef.value.data.collectionID
|
||||
}
|
||||
|
||||
export function updateInheritedPropertiesForAffectedRequests(
|
||||
path: string,
|
||||
inheritedProperties: HoppInheritedProperty,
|
||||
@@ -177,22 +281,17 @@ export function updateInheritedPropertiesForAffectedRequests(
|
||||
const effectedTabs = tabService.getTabsRefTo((tab) => {
|
||||
const saveContext = tab.document.saveContext
|
||||
|
||||
const saveContextPath =
|
||||
saveContext?.originLocation === "team-collection"
|
||||
? saveContext.collectionID
|
||||
: saveContext?.folderPath
|
||||
|
||||
return saveContextPath?.startsWith(path) ?? false
|
||||
const collectionID = getSaveContextCollectionID(saveContext)
|
||||
return collectionID?.startsWith(path) ?? false
|
||||
})
|
||||
|
||||
effectedTabs.map((tab) => {
|
||||
const inheritedParentID =
|
||||
tab.value.document.inheritedProperties?.auth.parentID
|
||||
|
||||
const contextPath =
|
||||
tab.value.document.saveContext?.originLocation === "team-collection"
|
||||
? tab.value.document.saveContext.collectionID
|
||||
: tab.value.document.saveContext?.folderPath
|
||||
const contextPath = getSaveContextCollectionID(
|
||||
tab.value.document.saveContext
|
||||
)
|
||||
|
||||
const effectedPath = folderPathCloseToSaveContext(
|
||||
inheritedParentID,
|
||||
@@ -227,21 +326,6 @@ export function updateInheritedPropertiesForAffectedRequests(
|
||||
})
|
||||
}
|
||||
|
||||
function resetSaveContextForAffectedRequests(folderPath: string) {
|
||||
const tabService = getService(RESTTabService)
|
||||
const tabs = tabService.getTabsRefTo((tab) => {
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||
tab.document.saveContext.folderPath.startsWith(folderPath)
|
||||
)
|
||||
})
|
||||
|
||||
for (const tab of tabs) {
|
||||
tab.value.document.saveContext = null
|
||||
tab.value.document.isDirty = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset save context to null if requests are deleted from the team collection or its folder
|
||||
* only runs when collection or folder is deleted
|
||||
|
||||
@@ -3,9 +3,10 @@ import {
|
||||
HoppGQLRequest,
|
||||
HoppRESTRequest,
|
||||
} from "@hoppscotch/data"
|
||||
import { getAffectedIndexes } from "./affectedIndex"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
|
||||
import { getService } from "~/modules/dioc"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { getAffectedIndexes } from "./affectedIndex"
|
||||
|
||||
/**
|
||||
* Resolve save context on reorder
|
||||
@@ -29,30 +30,76 @@ export function resolveSaveContextOnRequestReorder(payload: {
|
||||
if (newIndex > lastIndex) newIndex-- // there is a issue when going down? better way to resolve this?
|
||||
if (lastIndex === newIndex) return
|
||||
|
||||
const affectedIndexes = getAffectedIndexes(
|
||||
const affectedIndices = getAffectedIndexes(
|
||||
lastIndex,
|
||||
newIndex === -1 ? length! : newIndex
|
||||
)
|
||||
|
||||
// if (newIndex === -1) remove it from the map because it will be deleted
|
||||
if (newIndex === -1) affectedIndexes.delete(lastIndex)
|
||||
if (newIndex === -1) affectedIndices.delete(lastIndex)
|
||||
|
||||
const tabService = getService(RESTTabService)
|
||||
const tabs = tabService.getTabsRefTo((tab) => {
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "user-collection" &&
|
||||
tab.document.saveContext.folderPath === folderPath &&
|
||||
affectedIndexes.has(tab.document.saveContext.requestIndex)
|
||||
)
|
||||
if (tab.document.saveContext?.originLocation === "user-collection") {
|
||||
return (
|
||||
tab.document.saveContext.folderPath === folderPath &&
|
||||
affectedIndices.has(tab.document.saveContext.requestIndex)
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
tab.document.saveContext?.originLocation !== "workspace-user-collection"
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
const requestHandleRef = tab.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return false
|
||||
}
|
||||
|
||||
const { requestID } = requestHandleRef.value.data
|
||||
const collectionID = requestID.split("/").slice(0, -1).join("/")
|
||||
const requestIndex = parseInt(requestID.split("/").slice(-1)[0])
|
||||
|
||||
return collectionID === folderPath && affectedIndices.has(requestIndex)
|
||||
})
|
||||
|
||||
for (const tab of tabs) {
|
||||
if (tab.value.document.saveContext?.originLocation === "user-collection") {
|
||||
const newIndex = affectedIndexes.get(
|
||||
const newIndex = affectedIndices.get(
|
||||
tab.value.document.saveContext?.requestIndex
|
||||
)!
|
||||
tab.value.document.saveContext.requestIndex = newIndex
|
||||
}
|
||||
|
||||
if (
|
||||
tab.value.document.saveContext?.originLocation !==
|
||||
"workspace-user-collection"
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const requestHandleRef = tab.value.document.saveContext.requestHandle?.get()
|
||||
|
||||
if (!requestHandleRef || requestHandleRef.value.type === "invalid") {
|
||||
return
|
||||
}
|
||||
|
||||
const { requestID } = requestHandleRef.value.data
|
||||
|
||||
const requestIDArr = requestID.split("/")
|
||||
const requestIndex = affectedIndices.get(
|
||||
parseInt(requestIDArr[requestIDArr.length - 1])
|
||||
)!
|
||||
|
||||
requestIDArr[requestIDArr.length - 1] = requestIndex.toString()
|
||||
|
||||
requestHandleRef.value.data.requestID = requestIDArr.join("/")
|
||||
requestHandleRef.value.data.collectionID = requestIDArr
|
||||
.slice(0, -1)
|
||||
.join("/")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +114,7 @@ export function getRequestsByPath(
|
||||
|
||||
if (pathArray.length === 1) {
|
||||
const latestVersionedRequests = currentCollection.requests.filter(
|
||||
(req): req is HoppRESTRequest => req.v === "3"
|
||||
(req): req is HoppRESTRequest => req.v === "4"
|
||||
)
|
||||
|
||||
return latestVersionedRequests
|
||||
@@ -78,7 +125,7 @@ export function getRequestsByPath(
|
||||
}
|
||||
|
||||
const latestVersionedRequests = currentCollection.requests.filter(
|
||||
(req): req is HoppRESTRequest => req.v === "3"
|
||||
(req): req is HoppRESTRequest => req.v === "4"
|
||||
)
|
||||
|
||||
return latestVersionedRequests
|
||||
|
||||
@@ -281,9 +281,9 @@ export const runGQLOperation = async (options: RunQueryOptions) => {
|
||||
}
|
||||
} else if (auth.authType === "api-key") {
|
||||
const { key, value, addTo } = auth
|
||||
if (addTo === "Headers") {
|
||||
if (addTo === "HEADERS") {
|
||||
finalHeaders[key] = value
|
||||
} else if (addTo === "Query params") {
|
||||
} else if (addTo === "QUERY_PARAMS") {
|
||||
params[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
import * as E from "fp-ts/Either"
|
||||
|
||||
import { platform } from "~/platform"
|
||||
|
||||
/**
|
||||
* Create a downloadable file from a collection and prompts the user to download it.
|
||||
* @param collectionJSON - JSON string of the collection
|
||||
* @param name - Name of the collection set as the file name
|
||||
*/
|
||||
export const initializeDownloadCollection = (
|
||||
export const initializeDownloadFile = async (
|
||||
collectionJSON: string,
|
||||
name: string | null
|
||||
) => {
|
||||
const file = new Blob([collectionJSON], { type: "application/json" })
|
||||
const a = document.createElement("a")
|
||||
const url = URL.createObjectURL(file)
|
||||
a.href = url
|
||||
const result = await platform.io.saveFileWithDialog({
|
||||
data: collectionJSON,
|
||||
contentType: "application/json",
|
||||
suggestedFilename: `${name ?? "collection"}.json`,
|
||||
filters: [
|
||||
{
|
||||
name: "Hoppscotch Collection/Environment JSON file",
|
||||
extensions: ["json"],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
if (name) {
|
||||
a.download = `${name}.json`
|
||||
} else {
|
||||
a.download = `${url.split("/").pop()!.split("#")[0].split("?")[0]}.json`
|
||||
if (result.type === "unknown" || result.type === "saved") {
|
||||
return E.right("state.download_started")
|
||||
}
|
||||
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a)
|
||||
URL.revokeObjectURL(url)
|
||||
}, 1000)
|
||||
|
||||
return E.right("state.download_started")
|
||||
return E.left("state.download_failed")
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { HoppCollection } from "@hoppscotch/data"
|
||||
|
||||
export const myCollectionsExporter = (myCollections: HoppCollection[]) => {
|
||||
return JSON.stringify(myCollections, null, 2)
|
||||
}
|
||||
@@ -260,7 +260,7 @@ const resolveOpenAPIV3SecurityObj = (
|
||||
return {
|
||||
authType: "api-key",
|
||||
authActive: true,
|
||||
addTo: "Headers",
|
||||
addTo: "HEADERS",
|
||||
key: scheme.name,
|
||||
value: "",
|
||||
}
|
||||
@@ -268,7 +268,7 @@ const resolveOpenAPIV3SecurityObj = (
|
||||
return {
|
||||
authType: "api-key",
|
||||
authActive: true,
|
||||
addTo: "Query params",
|
||||
addTo: "QUERY_PARAMS",
|
||||
key: scheme.in,
|
||||
value: "",
|
||||
}
|
||||
@@ -430,7 +430,7 @@ const resolveOpenAPIV2SecurityScheme = (
|
||||
// V2 only supports in: header and in: query
|
||||
return {
|
||||
authType: "api-key",
|
||||
addTo: scheme.in === "header" ? "Headers" : "Query params",
|
||||
addTo: scheme.in === "header" ? "HEADERS" : "QUERY_PARAMS",
|
||||
authActive: true,
|
||||
key: scheme.name,
|
||||
value: "",
|
||||
|
||||
@@ -150,8 +150,8 @@ const getHoppReqAuth = (item: Item): HoppRESTAuth => {
|
||||
),
|
||||
addTo:
|
||||
(getVariableValue(auth.apikey, "in") ?? "query") === "query"
|
||||
? "Query params"
|
||||
: "Headers",
|
||||
? "QUERY_PARAMS"
|
||||
: "HEADERS",
|
||||
}
|
||||
} else if (auth.type === "bearer") {
|
||||
return {
|
||||
|
||||
@@ -132,30 +132,23 @@ function generateKeybindingString(ev: KeyboardEvent): ShortcutKey | null {
|
||||
|
||||
function getPressedKey(ev: KeyboardEvent): Key | null {
|
||||
// Sometimes the property code is not available on the KeyboardEvent object
|
||||
const val = (ev.code ?? "").toLowerCase()
|
||||
const key = (ev.key ?? "").toLowerCase()
|
||||
|
||||
// Check arrow keys
|
||||
if (val === "arrowup") return "up"
|
||||
else if (val === "arrowdown") return "down"
|
||||
else if (val === "arrowleft") return "left"
|
||||
else if (val === "arrowright") return "right"
|
||||
if (key.startsWith("arrow")) {
|
||||
return key.slice(5) as Key
|
||||
}
|
||||
|
||||
// Check letter keys
|
||||
const isLetter = val.startsWith("key")
|
||||
if (isLetter) return val.substring(3) as Key
|
||||
const isLetter = key.length === 1 && key >= "a" && key <= "z"
|
||||
if (isLetter) return key as Key
|
||||
|
||||
// Check if number keys
|
||||
const isDigit = val.startsWith("digit")
|
||||
if (isDigit) return val.substring(5) as Key
|
||||
const isDigit = key.length === 1 && key >= "0" && key <= "9"
|
||||
if (isDigit) return key as Key
|
||||
|
||||
// Check if slash
|
||||
if (val === "slash") return "/"
|
||||
|
||||
// Check if period
|
||||
if (val === "period") return "."
|
||||
|
||||
// Check if enter
|
||||
if (val === "enter") return "enter"
|
||||
// Check if slash, period or enter
|
||||
if (key === "/" || key === "." || key === "enter") return key
|
||||
|
||||
// If no other cases match, this is not a valid key
|
||||
return null
|
||||
|
||||
@@ -3,8 +3,37 @@ import { HoppRESTResponse } from "../types/HoppRESTResponse"
|
||||
import { HoppTestResult } from "../types/HoppTestResult"
|
||||
import { RESTOptionTabs } from "~/components/http/RequestOptions.vue"
|
||||
import { HoppInheritedProperty } from "../types/HoppInheritedProperties"
|
||||
import { Handle } from "~/services/new-workspace/handle"
|
||||
import { WorkspaceRequest } from "~/services/new-workspace/workspace"
|
||||
|
||||
export type HoppRESTSaveContext =
|
||||
| {
|
||||
/**
|
||||
* The origin source of the request
|
||||
*/
|
||||
// TODO: Make this `user-collection` after porting all usages
|
||||
// Future TODO: Keep separate types for the IDs (specific to persistence) & `requestHandle` (only existing at runtime)
|
||||
originLocation: "workspace-user-collection"
|
||||
/**
|
||||
* ID of the workspace
|
||||
*/
|
||||
workspaceID?: string
|
||||
|
||||
/**
|
||||
* ID of the provider
|
||||
*/
|
||||
providerID?: string
|
||||
|
||||
/**
|
||||
* Path to the request in the collection tree
|
||||
*/
|
||||
requestID?: string
|
||||
|
||||
/**
|
||||
* Handle to the request open in the tab
|
||||
*/
|
||||
requestHandle?: Handle<WorkspaceRequest>
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* The origin source of the request
|
||||
|
||||
@@ -50,6 +50,7 @@ export default class TeamListAdapter {
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.teamList$.next([])
|
||||
this.isDispose = true
|
||||
clearTimeout(this.timeoutHandle as any)
|
||||
this.timeoutHandle = null
|
||||
|
||||
@@ -201,7 +201,7 @@ export class TeamSearchService extends Service {
|
||||
expandingCollections: Ref<string[]> = ref([])
|
||||
expandedCollections: Ref<string[]> = ref([])
|
||||
|
||||
// FUTURE-TODO: ideally this should return the search results / formatted results instead of directly manipulating the result set
|
||||
// TODO: ideally this should return the search results / formatted results instead of directly manipulating the result set
|
||||
// eg: do the spotlight formatting in the spotlight searcher and not here
|
||||
searchTeams = async (query: string, teamID: string) => {
|
||||
if (!query.length) {
|
||||
|
||||
@@ -17,3 +17,24 @@ export type HoppInheritedProperty = {
|
||||
inheritedHeader: HoppRESTHeader | GQLHeader
|
||||
}[]
|
||||
}
|
||||
|
||||
type ModifiedAuth<T, AuthType> = {
|
||||
[K in keyof T]: K extends "inheritedAuth" ? Extract<T[K], AuthType> : T[K]
|
||||
}
|
||||
|
||||
type ModifiedHeaders<T, HeaderType> = {
|
||||
[K in keyof T]: K extends "inheritedHeader" ? Extract<T[K], HeaderType> : T[K]
|
||||
}
|
||||
|
||||
type ModifiedHoppInheritedProperty<AuthType, HeaderType> = {
|
||||
auth: ModifiedAuth<HoppInheritedProperty["auth"], AuthType>
|
||||
headers: ModifiedHeaders<
|
||||
HoppInheritedProperty["headers"][number],
|
||||
HeaderType
|
||||
>[]
|
||||
}
|
||||
|
||||
export type HoppInheritedRESTProperty = ModifiedHoppInheritedProperty<
|
||||
HoppRESTAuth,
|
||||
HoppRESTHeader
|
||||
>
|
||||
|
||||
@@ -20,28 +20,29 @@ export type Picked =
|
||||
pickedType: "my-collection"
|
||||
collectionIndex: number
|
||||
}
|
||||
| {
|
||||
pickedType: "teams-request"
|
||||
requestID: string
|
||||
}
|
||||
| {
|
||||
pickedType: "teams-folder"
|
||||
folderID: string
|
||||
}
|
||||
| {
|
||||
pickedType: "teams-collection"
|
||||
collectionID: string
|
||||
}
|
||||
| {
|
||||
pickedType: "gql-my-request"
|
||||
folderPath: string
|
||||
requestIndex: number
|
||||
}
|
||||
| {
|
||||
pickedType: "gql-my-folder"
|
||||
folderPath: string
|
||||
}
|
||||
| {
|
||||
pickedType: "gql-my-collection"
|
||||
collectionIndex: number
|
||||
}
|
||||
// TODO: Enable this when rest of the implementation is in place
|
||||
// | {
|
||||
// pickedType: "teams-request"
|
||||
// requestID: string
|
||||
// }
|
||||
// | {
|
||||
// pickedType: "teams-folder"
|
||||
// folderID: string
|
||||
// }
|
||||
// | {
|
||||
// pickedType: "teams-collection"
|
||||
// collectionID: string
|
||||
// }
|
||||
// | {
|
||||
// pickedType: "gql-my-request"
|
||||
// folderPath: string
|
||||
// requestIndex: number
|
||||
// }
|
||||
// | {
|
||||
// pickedType: "gql-my-folder"
|
||||
// folderPath: string
|
||||
// }
|
||||
// | {
|
||||
// pickedType: "gql-my-collection"
|
||||
// collectionIndex: number
|
||||
// }
|
||||
|
||||
@@ -96,7 +96,7 @@ export const getComputedAuthHeaders = (
|
||||
})
|
||||
} else if (request.auth.authType === "api-key") {
|
||||
const { key, addTo } = request.auth
|
||||
if (addTo === "Headers" && key) {
|
||||
if (addTo === "HEADERS" && key) {
|
||||
headers.push({
|
||||
active: true,
|
||||
key: parseTemplateString(key, envVars),
|
||||
|
||||
17
packages/hoppscotch-common/src/helpers/utils/lazy.ts
Normal file
17
packages/hoppscotch-common/src/helpers/utils/lazy.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Create a function that will only run the given function once and caches the result.
|
||||
*/
|
||||
export function lazy<T>(fn: () => T): () => T {
|
||||
let funcRan = false
|
||||
let result: T | null = null
|
||||
|
||||
return () => {
|
||||
if (!funcRan) {
|
||||
result = fn()
|
||||
funcRan = true
|
||||
|
||||
return result
|
||||
}
|
||||
return result!
|
||||
}
|
||||
}
|
||||
@@ -3,36 +3,40 @@ import { createApp } from "vue"
|
||||
import { initializeApp } from "./helpers/app"
|
||||
import { initBackendGQLClient } from "./helpers/backend/GQLClient"
|
||||
import { performMigrations } from "./helpers/migrations"
|
||||
import { getService } from "./modules/dioc"
|
||||
import { PlatformDef, setPlatformDef } from "./platform"
|
||||
import { PersonalWorkspaceProviderService } from "./services/new-workspace/providers/personal.workspace"
|
||||
import { TestWorkspaceProviderService } from "./services/new-workspace/providers/test.workspace"
|
||||
|
||||
import { PersistenceService } from "./services/persistence"
|
||||
|
||||
import "nprogress/nprogress.css"
|
||||
import "../assets/scss/styles.scss"
|
||||
import "../assets/scss/tailwind.scss"
|
||||
import "../assets/themes/themes.scss"
|
||||
import "../assets/scss/styles.scss"
|
||||
import "nprogress/nprogress.css"
|
||||
|
||||
import "unfonts.css"
|
||||
|
||||
import App from "./App.vue"
|
||||
import { getService } from "./modules/dioc"
|
||||
import { PersistenceService } from "./services/persistence"
|
||||
|
||||
export function createHoppApp(el: string | Element, platformDef: PlatformDef) {
|
||||
setPlatformDef(platformDef)
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
// Some basic work that needs to be done before module inits even
|
||||
initBackendGQLClient()
|
||||
initializeApp()
|
||||
|
||||
HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app))
|
||||
platformDef.addedHoppModules?.forEach((mod) => mod.onVueAppInit?.(app))
|
||||
|
||||
// Some basic work that needs to be done before module inits even
|
||||
initBackendGQLClient()
|
||||
initializeApp()
|
||||
// TODO: Explore possibilities of moving this invocation to the service constructor
|
||||
// `toast` was coming up as `null` in the previous attempts
|
||||
getService(PersistenceService).setupLocalPersistence()
|
||||
performMigrations()
|
||||
|
||||
// TODO: Remove this
|
||||
getService(TestWorkspaceProviderService)
|
||||
getService(PersonalWorkspaceProviderService)
|
||||
|
||||
app.mount(el)
|
||||
|
||||
console.info(
|
||||
|
||||
@@ -73,7 +73,7 @@ import { useI18n } from "~/composables/i18n"
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { InvocationTriggers, defineActionHandler } from "~/helpers/actions"
|
||||
import { hookKeybindingsListener } from "~/helpers/keybindings"
|
||||
import { applySetting } from "~/newstore/settings"
|
||||
import { applySetting, toggleSetting } from "~/newstore/settings"
|
||||
import { platform } from "~/platform"
|
||||
import { HoppSpotlightSessionEventData } from "~/platform/analytics"
|
||||
import { PersistenceService } from "~/services/persistence"
|
||||
@@ -97,6 +97,8 @@ const t = useI18n()
|
||||
const persistenceService = useService(PersistenceService)
|
||||
const spotlightService = useService(SpotlightService)
|
||||
|
||||
const HAS_OPENED_SPOTLIGHT = useSetting("HAS_OPENED_SPOTLIGHT")
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!mdAndLarger.value) {
|
||||
rightSidebar.value = false
|
||||
@@ -160,6 +162,7 @@ defineActionHandler("modals.search.toggle", (_, trigger) => {
|
||||
})
|
||||
|
||||
showSearch.value = !showSearch.value
|
||||
!HAS_OPENED_SPOTLIGHT.value && toggleSetting("HAS_OPENED_SPOTLIGHT")
|
||||
})
|
||||
|
||||
defineActionHandler("modals.support.toggle", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { HoppModule } from "."
|
||||
import { Container, Service } from "dioc"
|
||||
import { Container, ServiceClassInstance } from "dioc"
|
||||
import { diocPlugin } from "dioc/vue"
|
||||
import { DebugService } from "~/services/debug.service"
|
||||
import { platform } from "~/platform"
|
||||
@@ -22,7 +22,7 @@ if (import.meta.env.DEV) {
|
||||
* services. Please use `useService` if within components or try to convert your
|
||||
* legacy subsystem into a service if possible.
|
||||
*/
|
||||
export function getService<T extends typeof Service<any> & { ID: string }>(
|
||||
export function getService<T extends ServiceClassInstance<any>>(
|
||||
service: T
|
||||
): InstanceType<T> {
|
||||
return serviceContainer.bind(service)
|
||||
@@ -30,11 +30,10 @@ export function getService<T extends typeof Service<any> & { ID: string }>(
|
||||
|
||||
export default <HoppModule>{
|
||||
onVueAppInit(app) {
|
||||
// TODO: look into this
|
||||
// @ts-expect-error Something weird with Vue versions
|
||||
app.use(diocPlugin, {
|
||||
container: serviceContainer,
|
||||
})
|
||||
|
||||
for (const service of platform.addedServices ?? []) {
|
||||
serviceContainer.bind(service)
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ const restCollectionDispatchers = defineDispatchers({
|
||||
)
|
||||
return {}
|
||||
}
|
||||
|
||||
// We get the index path to the folder itself,
|
||||
// we have to find the folder containing the target folder,
|
||||
// so we pop the last path index
|
||||
@@ -690,17 +691,11 @@ const restCollectionDispatchers = defineDispatchers({
|
||||
|
||||
// if the destination is null, we are moving to the end of the list
|
||||
if (destinationRequestIndex === null) {
|
||||
// move to the end of the list
|
||||
// TODO: Verify if this can be safely removed
|
||||
targetLocation.requests.push(
|
||||
targetLocation.requests.splice(requestIndex, 1)[0]
|
||||
)
|
||||
|
||||
resolveSaveContextOnRequestReorder({
|
||||
lastIndex: requestIndex,
|
||||
newIndex: targetLocation.requests.length,
|
||||
folderPath: destinationCollectionPath,
|
||||
})
|
||||
|
||||
return {
|
||||
state: newState,
|
||||
}
|
||||
@@ -708,12 +703,6 @@ const restCollectionDispatchers = defineDispatchers({
|
||||
|
||||
reorderItems(targetLocation.requests, requestIndex, destinationRequestIndex)
|
||||
|
||||
resolveSaveContextOnRequestReorder({
|
||||
lastIndex: requestIndex,
|
||||
newIndex: destinationRequestIndex,
|
||||
folderPath: destinationCollectionPath,
|
||||
})
|
||||
|
||||
return {
|
||||
state: newState,
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { pluck, distinctUntilChanged } from "rxjs/operators"
|
||||
import { cloneDeep, defaultsDeep, has } from "lodash-es"
|
||||
import { Observable } from "rxjs"
|
||||
|
||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||
import { distinctUntilChanged, pluck } from "rxjs/operators"
|
||||
import { nextTick } from "vue"
|
||||
import { platform } from "~/platform"
|
||||
import type { KeysMatching } from "~/types/ts-utils"
|
||||
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
|
||||
|
||||
export const HoppBgColors = ["system", "light", "dark", "black"] as const
|
||||
|
||||
@@ -65,51 +66,67 @@ export type SettingsDef = {
|
||||
SIDEBAR: boolean
|
||||
SIDEBAR_ON_LEFT: boolean
|
||||
COLUMN_LAYOUT: boolean
|
||||
|
||||
HAS_OPENED_SPOTLIGHT: boolean
|
||||
}
|
||||
|
||||
export const getDefaultSettings = (): SettingsDef => ({
|
||||
syncCollections: true,
|
||||
syncHistory: true,
|
||||
syncEnvironments: true,
|
||||
export const getDefaultSettings = (): SettingsDef => {
|
||||
const defaultSettings: SettingsDef = {
|
||||
syncCollections: true,
|
||||
syncHistory: true,
|
||||
syncEnvironments: true,
|
||||
|
||||
WRAP_LINES: {
|
||||
httpRequestBody: true,
|
||||
httpResponseBody: true,
|
||||
httpHeaders: true,
|
||||
httpParams: true,
|
||||
httpUrlEncoded: true,
|
||||
httpPreRequest: true,
|
||||
httpTest: true,
|
||||
httpRequestVariables: true,
|
||||
graphqlQuery: true,
|
||||
graphqlResponseBody: true,
|
||||
graphqlHeaders: false,
|
||||
graphqlVariables: false,
|
||||
graphqlSchema: true,
|
||||
importCurl: true,
|
||||
codeGen: true,
|
||||
cookie: true,
|
||||
},
|
||||
WRAP_LINES: {
|
||||
httpRequestBody: true,
|
||||
httpResponseBody: true,
|
||||
httpHeaders: true,
|
||||
httpParams: true,
|
||||
httpUrlEncoded: true,
|
||||
httpPreRequest: true,
|
||||
httpTest: true,
|
||||
httpRequestVariables: true,
|
||||
graphqlQuery: true,
|
||||
graphqlResponseBody: true,
|
||||
graphqlHeaders: false,
|
||||
graphqlVariables: false,
|
||||
graphqlSchema: true,
|
||||
importCurl: true,
|
||||
codeGen: true,
|
||||
cookie: true,
|
||||
},
|
||||
|
||||
CURRENT_INTERCEPTOR_ID: "browser", // TODO: Allow the platform definition to take this place
|
||||
CURRENT_INTERCEPTOR_ID: "",
|
||||
|
||||
// TODO: Interceptor related settings should move under the interceptor systems
|
||||
PROXY_URL: "https://proxy.hoppscotch.io/",
|
||||
URL_EXCLUDES: {
|
||||
auth: true,
|
||||
httpUser: true,
|
||||
httpPassword: true,
|
||||
bearerToken: true,
|
||||
oauth2Token: true,
|
||||
},
|
||||
THEME_COLOR: "indigo",
|
||||
BG_COLOR: "system",
|
||||
TELEMETRY_ENABLED: true,
|
||||
EXPAND_NAVIGATION: false,
|
||||
SIDEBAR: true,
|
||||
SIDEBAR_ON_LEFT: false,
|
||||
COLUMN_LAYOUT: true,
|
||||
})
|
||||
// TODO: Interceptor related settings should move under the interceptor systems
|
||||
PROXY_URL: "https://proxy.hoppscotch.io/",
|
||||
URL_EXCLUDES: {
|
||||
auth: true,
|
||||
httpUser: true,
|
||||
httpPassword: true,
|
||||
bearerToken: true,
|
||||
oauth2Token: true,
|
||||
},
|
||||
THEME_COLOR: "indigo",
|
||||
BG_COLOR: "system",
|
||||
TELEMETRY_ENABLED: true,
|
||||
EXPAND_NAVIGATION: false,
|
||||
SIDEBAR: true,
|
||||
SIDEBAR_ON_LEFT: false,
|
||||
COLUMN_LAYOUT: true,
|
||||
|
||||
HAS_OPENED_SPOTLIGHT: false,
|
||||
}
|
||||
|
||||
// Wait for platform to initialize before setting CURRENT_INTERCEPTOR_ID
|
||||
nextTick(() => {
|
||||
applySetting(
|
||||
"CURRENT_INTERCEPTOR_ID",
|
||||
platform?.interceptors.default || "browser"
|
||||
)
|
||||
})
|
||||
|
||||
return defaultSettings
|
||||
}
|
||||
|
||||
type ApplySettingPayload = {
|
||||
[K in keyof SettingsDef]: {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</template>
|
||||
<template #suffix>
|
||||
<span
|
||||
v-if="tab.document.isDirty"
|
||||
v-if="getTabDirtyStatus(tab)"
|
||||
class="flex w-4 items-center justify-center text-secondary group-hover:hidden"
|
||||
>
|
||||
<svg
|
||||
@@ -95,24 +95,24 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue"
|
||||
import { safelyExtractRESTRequest } from "@hoppscotch/data"
|
||||
import { translateExtURLParams } from "~/helpers/RESTExtURLParams"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||
import { platform } from "~/platform"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { safelyExtractRESTRequest } from "@hoppscotch/data"
|
||||
import { useService } from "dioc/vue"
|
||||
import { InspectionService } from "~/services/inspection"
|
||||
import { HeaderInspectorService } from "~/services/inspection/inspectors/header.inspector"
|
||||
import { EnvironmentInspectorService } from "~/services/inspection/inspectors/environment.inspector"
|
||||
import { ResponseInspectorService } from "~/services/inspection/inspectors/response.inspector"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { onMounted, ref } from "vue"
|
||||
import { useRoute } from "vue-router"
|
||||
import { useReadonlyStream } from "~/composables/stream"
|
||||
import { translateExtURLParams } from "~/helpers/RESTExtURLParams"
|
||||
import { defineActionHandler, invokeAction } from "~/helpers/actions"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { HoppRESTDocument } from "~/helpers/rest/document"
|
||||
import { platform } from "~/platform"
|
||||
import { InspectionService } from "~/services/inspection"
|
||||
import { EnvironmentInspectorService } from "~/services/inspection/inspectors/environment.inspector"
|
||||
import { HeaderInspectorService } from "~/services/inspection/inspectors/header.inspector"
|
||||
import { ResponseInspectorService } from "~/services/inspection/inspectors/response.inspector"
|
||||
import { HoppTab } from "~/services/tab"
|
||||
import { RESTTabService } from "~/services/tab/rest"
|
||||
|
||||
const savingRequest = ref(false)
|
||||
const confirmingCloseForTabID = ref<string | null>(null)
|
||||
@@ -193,7 +193,7 @@ const inspectionService = useService(InspectionService)
|
||||
const removeTab = (tabID: string) => {
|
||||
const tabState = tabs.getTabRef(tabID).value
|
||||
|
||||
if (tabState.document.isDirty) {
|
||||
if (getTabDirtyStatus(tabState)) {
|
||||
confirmingCloseForTabID.value = tabID
|
||||
} else {
|
||||
tabs.closeTab(tabState.id)
|
||||
@@ -202,8 +202,10 @@ const removeTab = (tabID: string) => {
|
||||
}
|
||||
|
||||
const closeOtherTabsAction = (tabID: string) => {
|
||||
const isTabDirty = tabs.getTabRef(tabID).value?.document.isDirty
|
||||
const dirtyTabCount = tabs.getDirtyTabsCount()
|
||||
|
||||
const isTabDirty = getTabDirtyStatus(tabs.getTabRef(tabID).value)
|
||||
|
||||
// If current tab is dirty, so we need to subtract 1 from the dirty tab count
|
||||
const balanceDirtyTabCount = isTabDirty ? dirtyTabCount - 1 : dirtyTabCount
|
||||
|
||||
@@ -268,15 +270,24 @@ const onCloseConfirmSaveTab = () => {
|
||||
* Called when the user confirms they want to save the tab
|
||||
*/
|
||||
const onResolveConfirmSaveTab = () => {
|
||||
if (tabs.currentActiveTab.value.document.saveContext) {
|
||||
invokeAction("request.save")
|
||||
const { saveContext } = tabs.currentActiveTab.value.document
|
||||
|
||||
if (confirmingCloseForTabID.value) {
|
||||
tabs.closeTab(confirmingCloseForTabID.value)
|
||||
confirmingCloseForTabID.value = null
|
||||
}
|
||||
} else {
|
||||
savingRequest.value = true
|
||||
// There're two cases where the save request under a collection modal should open
|
||||
// 1. Attempting to save a request that is not under a collection (When the save context is not available)
|
||||
// 2. Deleting a request from the collection tree and attempting to save it while closing the respective tab (When the request handle is invalid)
|
||||
if (
|
||||
!saveContext ||
|
||||
(saveContext.originLocation === "workspace-user-collection" &&
|
||||
saveContext.requestHandle?.get().value.type === "invalid")
|
||||
) {
|
||||
return (savingRequest.value = true)
|
||||
}
|
||||
|
||||
invokeAction("request.save")
|
||||
|
||||
if (confirmingCloseForTabID.value) {
|
||||
tabs.closeTab(confirmingCloseForTabID.value)
|
||||
confirmingCloseForTabID.value = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +315,17 @@ const shareTabRequest = (tabID: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getTabDirtyStatus = (tab: HoppTab<HoppRESTDocument>) => {
|
||||
if (tab.document.isDirty) {
|
||||
return true
|
||||
}
|
||||
|
||||
return (
|
||||
tab.document.saveContext?.originLocation === "workspace-user-collection" &&
|
||||
tab.document.saveContext.requestHandle?.get().value.type === "invalid"
|
||||
)
|
||||
}
|
||||
|
||||
defineActionHandler("contextmenu.open", ({ position, text }) => {
|
||||
if (text) {
|
||||
contextMenu.value = {
|
||||
|
||||
@@ -8,14 +8,15 @@ import { AnalyticsPlatformDef } from "./analytics"
|
||||
import { InterceptorsPlatformDef } from "./interceptors"
|
||||
import { HoppModule } from "~/modules"
|
||||
import { InspectorsPlatformDef } from "./inspectors"
|
||||
import { Service } from "dioc"
|
||||
import { ServiceClassInstance } from "dioc"
|
||||
import { IOPlatformDef } from "./io"
|
||||
import { SpotlightPlatformDef } from "./spotlight"
|
||||
import { Ref } from "vue"
|
||||
|
||||
export type PlatformDef = {
|
||||
ui?: UIPlatformDef
|
||||
addedHoppModules?: HoppModule[]
|
||||
addedServices?: Array<typeof Service<unknown> & { ID: string }>
|
||||
addedServices?: Array<ServiceClassInstance<unknown>>
|
||||
auth: AuthPlatformDef
|
||||
analytics?: AnalyticsPlatformDef
|
||||
io: IOPlatformDef
|
||||
@@ -45,6 +46,11 @@ export type PlatformDef = {
|
||||
* If a value is not given, then the value is assumed to be true
|
||||
*/
|
||||
promptAsUsingCookies?: boolean
|
||||
|
||||
/**
|
||||
* Whether to show the A/B testing workspace switcher click login flow or not
|
||||
*/
|
||||
workspaceSwitcherLogin?: Ref<boolean>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Service } from "dioc"
|
||||
import { Container, ServiceClassInstance } from "dioc"
|
||||
import { Inspector } from "~/services/inspection"
|
||||
|
||||
/**
|
||||
@@ -8,8 +8,9 @@ export type PlatformInspectorsDef = {
|
||||
// We are keeping this as the only mode for now
|
||||
// So that if we choose to add other modes, we can do without breaking
|
||||
type: "service"
|
||||
service: typeof Service<unknown> & { ID: string } & {
|
||||
new (): Service & Inspector
|
||||
// TODO: I don't think this type is effective, we have to come up with a better impl
|
||||
service: ServiceClassInstance<unknown> & {
|
||||
new (c: Container): Inspector
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Service } from "dioc"
|
||||
import { Container, ServiceClassInstance } from "dioc"
|
||||
import { Interceptor } from "~/services/interceptor.service"
|
||||
|
||||
export type PlatformInterceptorDef =
|
||||
| { type: "standalone"; interceptor: Interceptor }
|
||||
| {
|
||||
type: "service"
|
||||
service: typeof Service<unknown> & { ID: string } & {
|
||||
new (): Service & Interceptor
|
||||
// TODO: I don't think this type is effective, we have to come up with a better impl
|
||||
service: ServiceClassInstance<unknown> & {
|
||||
new (c: Container): Interceptor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Service } from "dioc"
|
||||
import { Container, ServiceClassInstance } from "dioc"
|
||||
import { SpotlightSearcher } from "~/services/spotlight"
|
||||
|
||||
export type SpotlightPlatformDef = {
|
||||
additionalSearchers?: Array<
|
||||
typeof Service<unknown> & { ID: string } & {
|
||||
new (): Service & SpotlightSearcher
|
||||
ServiceClassInstance<unknown> & {
|
||||
new (c: Container): SpotlightSearcher
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
@@ -31,9 +31,7 @@ export class ExtensionInspectorService extends Service implements Inspector {
|
||||
|
||||
private readonly inspection = this.bind(InspectionService)
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
override onServiceInit() {
|
||||
this.inspection.registerInspector(this)
|
||||
}
|
||||
|
||||
|
||||
@@ -133,9 +133,7 @@ export class ExtensionInterceptorService
|
||||
|
||||
public selectable = { type: "selectable" as const }
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
override onServiceInit() {
|
||||
this.listenForExtensionStatus()
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,17 @@ export const browserIODef: IOPlatformDef = {
|
||||
const url = URL.createObjectURL(file)
|
||||
|
||||
a.href = url
|
||||
a.download = pipe(
|
||||
url,
|
||||
S.split("/"),
|
||||
RNEA.last,
|
||||
S.split("#"),
|
||||
RNEA.head,
|
||||
S.split("?"),
|
||||
RNEA.head
|
||||
)
|
||||
a.download =
|
||||
opts.suggestedFilename ??
|
||||
pipe(
|
||||
url,
|
||||
S.split("/"),
|
||||
RNEA.last,
|
||||
S.split("#"),
|
||||
RNEA.head,
|
||||
S.split("?"),
|
||||
RNEA.head
|
||||
)
|
||||
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
|
||||
@@ -24,9 +24,7 @@ export class EnvironmentMenuService extends Service implements ContextMenu {
|
||||
|
||||
private readonly contextMenu = this.bind(ContextMenuService)
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
override onServiceInit() {
|
||||
this.contextMenu.registerMenu(this)
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user