Compare commits
23 Commits
revert-311
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
399a238bf4 | ||
|
|
b20ab72298 | ||
|
|
f723e6496a | ||
|
|
8c0aff8863 | ||
|
|
64c5077506 | ||
|
|
2afc87847d | ||
|
|
878ec833ce | ||
|
|
039de8015f | ||
|
|
f67b366b90 | ||
|
|
77e8a36ab0 | ||
|
|
d7cc9f5dbc | ||
|
|
4ba135f3b9 | ||
|
|
24894e05dc | ||
|
|
84b0c30d64 | ||
|
|
e3dd9e99a1 | ||
|
|
e3091cb6db | ||
|
|
270f796683 | ||
|
|
24c6bce02d | ||
|
|
2db567589f | ||
|
|
1fe83ebdc8 | ||
|
|
8320d4f222 | ||
|
|
e76c1bc64c | ||
|
|
1f3f8464ea |
@@ -31,6 +31,7 @@ MICROSOFT_CLIENT_ID="************************************************"
|
||||
MICROSOFT_CLIENT_SECRET="************************************************"
|
||||
MICROSOFT_CALLBACK_URL="http://localhost:3170/v1/auth/microsoft/callback"
|
||||
MICROSOFT_SCOPE="user.read"
|
||||
MICROSOFT_TENANT="common"
|
||||
|
||||
# Mailer config
|
||||
MAILER_SMTP_URL="smtps://user@domain.com:pass@smtp.domain.com"
|
||||
|
||||
42
.github/workflows/ui.yml
vendored
Normal file
42
.github/workflows/ui.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Deploy to Netlify (ui)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
# run this workflow only if an update is made to the ui package
|
||||
paths:
|
||||
- "packages/hoppscotch-ui/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup environment
|
||||
run: mv .env.example .env
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
with:
|
||||
version: 8
|
||||
run_install: true
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Build site
|
||||
run: pnpm run generate-ui
|
||||
|
||||
# Deploy the ui site with netlify-cli
|
||||
- name: Deploy to Netlify (ui)
|
||||
run: npx netlify-cli deploy --dir=packages/hoppscotch-ui/.histoire/dist --prod
|
||||
env:
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_UI_SITE_ID }}
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hoppscotch-backend",
|
||||
"version": "2023.4.5",
|
||||
"version": "2023.4.7",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -236,11 +236,11 @@ export class AdminService {
|
||||
const user = await this.userService.findUserByEmail(userEmail);
|
||||
if (O.isNone(user)) return E.left(USER_NOT_FOUND);
|
||||
|
||||
const isUserAlreadyMember = await this.teamService.getTeamMemberTE(
|
||||
const teamMember = await this.teamService.getTeamMemberTE(
|
||||
teamID,
|
||||
user.value.uid,
|
||||
)();
|
||||
if (E.left(isUserAlreadyMember)) {
|
||||
if (E.isLeft(teamMember)) {
|
||||
const addedUser = await this.teamService.addMemberToTeamWithEmail(
|
||||
teamID,
|
||||
userEmail,
|
||||
@@ -248,6 +248,18 @@ export class AdminService {
|
||||
);
|
||||
if (E.isLeft(addedUser)) return E.left(addedUser.left);
|
||||
|
||||
const userInvitation =
|
||||
await this.teamInvitationService.getTeamInviteByEmailAndTeamID(
|
||||
userEmail,
|
||||
teamID,
|
||||
);
|
||||
|
||||
if (E.isRight(userInvitation)) {
|
||||
await this.teamInvitationService.revokeInvitation(
|
||||
userInvitation.right.id,
|
||||
)();
|
||||
}
|
||||
|
||||
return E.right(addedUser.right);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy) {
|
||||
clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
|
||||
callbackURL: process.env.MICROSOFT_CALLBACK_URL,
|
||||
scope: [process.env.MICROSOFT_SCOPE],
|
||||
passReqToCallback: true,
|
||||
tenant: process.env.MICROSOFT_TENANT,
|
||||
store: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const AUTH_FAIL = 'auth/fail';
|
||||
export const JSON_INVALID = 'json_invalid';
|
||||
|
||||
/**
|
||||
* Tried to delete an user data document from fb firestore but failed.
|
||||
* Tried to delete a user data document from fb firestore but failed.
|
||||
* (FirebaseService)
|
||||
*/
|
||||
export const USER_FB_DOCUMENT_DELETION_FAILED =
|
||||
@@ -231,7 +231,7 @@ export const TEAM_COLL_INVALID_JSON = 'team_coll/invalid_json';
|
||||
export const TEAM_NOT_OWNER = 'team_coll/team_not_owner' as const;
|
||||
|
||||
/**
|
||||
* Tried to perform action on a request that doesn't accept their member role level
|
||||
* Tried to perform an action on a request that doesn't accept their member role level
|
||||
* (GqlRequestTeamMemberGuard)
|
||||
*/
|
||||
export const TEAM_REQ_NOT_REQUIRED_ROLE = 'team_req/not_required_role';
|
||||
@@ -262,7 +262,7 @@ export const TEAM_REQ_REORDERING_FAILED = 'team_req/reordering_failed' as const;
|
||||
export const SENDER_EMAIL_INVALID = 'mailer/sender_email_invalid' as const;
|
||||
|
||||
/**
|
||||
* Tried to perform action on a request when the user is not even member of the team
|
||||
* Tried to perform an action on a request when the user is not even a member of the team
|
||||
* (GqlRequestTeamMemberGuard, GqlCollectionTeamMemberGuard)
|
||||
*/
|
||||
export const TEAM_REQ_NOT_MEMBER = 'team_req/not_member';
|
||||
@@ -307,7 +307,7 @@ export const SHORTCODE_INVALID_JSON = 'shortcode/invalid_json' as const;
|
||||
export const SHORTCODE_ALREADY_EXISTS = 'shortcode/already_exists' as const;
|
||||
|
||||
/**
|
||||
* Invalid or non-existent TEAM ENVIRONMMENT ID
|
||||
* Invalid or non-existent TEAM ENVIRONMENT ID
|
||||
* (TeamEnvironmentsService)
|
||||
*/
|
||||
export const TEAM_ENVIRONMENT_NOT_FOUND = 'team_environment/not_found' as const;
|
||||
@@ -340,7 +340,7 @@ export const USER_SETTINGS_NULL_SETTINGS =
|
||||
'user_settings/null_settings' as const;
|
||||
|
||||
/*
|
||||
* Global environment doesnt exists for the user
|
||||
* Global environment doesn't exist for the user
|
||||
* (UserEnvironmentsService)
|
||||
*/
|
||||
export const USER_ENVIRONMENT_GLOBAL_ENV_DOES_NOT_EXISTS =
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as T from 'fp-ts/Task';
|
||||
import * as O from 'fp-ts/Option';
|
||||
import * as TO from 'fp-ts/TaskOption';
|
||||
import * as TE from 'fp-ts/TaskEither';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { pipe, flow, constVoid } from 'fp-ts/function';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { Team, TeamMemberRole } from 'src/team/team.model';
|
||||
@@ -10,6 +11,7 @@ import { Email } from 'src/types/Email';
|
||||
import { User } from 'src/user/user.model';
|
||||
import { TeamService } from 'src/team/team.service';
|
||||
import {
|
||||
INVALID_EMAIL,
|
||||
TEAM_INVITE_ALREADY_MEMBER,
|
||||
TEAM_INVITE_EMAIL_DO_NOT_MATCH,
|
||||
TEAM_INVITE_MEMBER_HAS_INVITE,
|
||||
@@ -19,6 +21,7 @@ import { TeamInvitation } from './team-invitation.model';
|
||||
import { MailerService } from 'src/mailer/mailer.service';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { validateEmail } from '../utils';
|
||||
|
||||
@Injectable()
|
||||
export class TeamInvitationService {
|
||||
@@ -63,6 +66,32 @@ export class TeamInvitationService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the team invite for an invitee with email and teamID.
|
||||
* @param inviteeEmail invitee email
|
||||
* @param teamID team id
|
||||
* @returns an Either of team invitation for the invitee or error
|
||||
*/
|
||||
async getTeamInviteByEmailAndTeamID(inviteeEmail: string, teamID: string) {
|
||||
const isEmailValid = validateEmail(inviteeEmail);
|
||||
if (!isEmailValid) return E.left(INVALID_EMAIL);
|
||||
|
||||
try {
|
||||
const teamInvite = await this.prisma.teamInvitation.findUniqueOrThrow({
|
||||
where: {
|
||||
teamID_inviteeEmail: {
|
||||
inviteeEmail: inviteeEmail,
|
||||
teamID: teamID,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return E.right(teamInvite);
|
||||
} catch (e) {
|
||||
return E.left(TEAM_INVITE_NO_INVITE_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
createInvitation(
|
||||
creator: User,
|
||||
team: Team,
|
||||
|
||||
@@ -32,7 +32,7 @@ export class TeamInviteViewerGuard implements CanActivate {
|
||||
// Get user
|
||||
TE.bindW('user', ({ gqlCtx }) =>
|
||||
pipe(
|
||||
O.fromNullable(gqlCtx.getContext<{ user?: User }>().user),
|
||||
O.fromNullable(gqlCtx.getContext().req.user),
|
||||
TE.fromOption(() => BUG_AUTH_NO_USER_CTX),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -33,7 +33,7 @@ export class TeamInviteeGuard implements CanActivate {
|
||||
// Get user
|
||||
TE.bindW('user', ({ gqlCtx }) =>
|
||||
pipe(
|
||||
O.fromNullable(gqlCtx.getContext<{ user?: User }>().user),
|
||||
O.fromNullable(gqlCtx.getContext().req.user),
|
||||
TE.fromOption(() => BUG_AUTH_NO_USER_CTX),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { HttpStatus } from '@nestjs/common';
|
||||
|
||||
/**
|
||||
** Custom interface to handle errors specific to Auth module
|
||||
** Since its REST we need to return HTTP status code along with error message
|
||||
** Since its REST we need to return the HTTP status code along with the error message
|
||||
*/
|
||||
export type AuthError = {
|
||||
message: string;
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Reaksie liggaam",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Opskrifte",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tyd",
|
||||
"title": "Reaksie",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "wag vir verbinding",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "هيئة الاستجابة",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "الرؤوس",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "حالة",
|
||||
"time": "وقت",
|
||||
"title": "إجابة",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "في انتظار الاتصال",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Visualitzar els meus enllaços"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Cos de resposta",
|
||||
"filter_response_body": "Filtrar el cos de la resposta JSON (utilitza la sintaxi JSONPath)",
|
||||
"headers": "Capçaleres",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Estat",
|
||||
"time": "Temps",
|
||||
"title": "Resposta",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "esperant la connexió",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "查看我的链接"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "响应体",
|
||||
"filter_response_body": "筛选JSON响应本体(使用JSONPath语法)",
|
||||
"headers": "响应头",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "状态",
|
||||
"time": "时间",
|
||||
"title": "响应",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "等待连接",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Odpovědní orgán",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Záhlaví",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Postavení",
|
||||
"time": "Čas",
|
||||
"title": "Odezva",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "čekání na připojení",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Svarorgan",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Overskrifter",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tid",
|
||||
"title": "Respons",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "venter på forbindelse",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Antworttext",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Header",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Zeit",
|
||||
"title": "Antwort",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "auf Verbindung warten",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Προβολή των links μου"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Σώμα απόκρισης",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Κεφαλίδες",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Κατάσταση",
|
||||
"time": "χρόνος",
|
||||
"title": "Απάντηση",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "περιμένοντας τη σύνδεση",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Ver mis enlaces"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Cuerpo de respuesta",
|
||||
"filter_response_body": "Filtrar el cuerpo de la respuesta JSON (utiliza la sintaxis JSONPath)",
|
||||
"headers": "Encabezados",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Estado",
|
||||
"time": "Tiempo",
|
||||
"title": "Respuesta",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "esperando la conexión",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Vastauselin",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Otsikot",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Tila",
|
||||
"time": "Aika",
|
||||
"title": "Vastaus",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "yhteyttä odotellessa",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Voir mes liens"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corps de réponse",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "En-têtes",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Statut",
|
||||
"time": "Temps",
|
||||
"title": "Réponse",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "En attente de connexion",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "גוף תגובה",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "כותרות",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "סטָטוּס",
|
||||
"time": "זְמַן",
|
||||
"title": "תְגוּבָה",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "מחכה לחיבור",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -433,6 +433,7 @@
|
||||
"view_my_links": "मेरे लिंक देखें"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "प्रतिक्रिया निकाय",
|
||||
"filter_response_body": "फ़िल्टर JSON रिस्पांस बॉडी (JSONPATH सिंटैक्स का उपयोग करता है)",
|
||||
"headers": "हेडर",
|
||||
@@ -446,6 +447,7 @@
|
||||
"status": "दर्जा",
|
||||
"time": "समय",
|
||||
"title": "जवाब",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "जुडने के लिए इंतजार",
|
||||
"xml": "एक्सएमएल"
|
||||
},
|
||||
|
||||
@@ -5,29 +5,29 @@
|
||||
"choose_file": "Válasszon egy fájlt",
|
||||
"clear": "Törlés",
|
||||
"clear_all": "Összes törlése",
|
||||
"close": "Close",
|
||||
"close": "Bezárás",
|
||||
"connect": "Kapcsolódás",
|
||||
"connecting": "Connecting",
|
||||
"connecting": "Kapcsolódás",
|
||||
"copy": "Másolás",
|
||||
"delete": "Törlés",
|
||||
"disconnect": "Leválasztás",
|
||||
"dismiss": "Eltüntetés",
|
||||
"dont_save": "Ne mentse",
|
||||
"download_file": "Fájl letöltése",
|
||||
"drag_to_reorder": "Drag to reorder",
|
||||
"drag_to_reorder": "Húzza az átrendezéshez",
|
||||
"duplicate": "Kettőzés",
|
||||
"edit": "Szerkesztés",
|
||||
"filter": "Filter",
|
||||
"filter": "Szűrő",
|
||||
"go_back": "Vissza",
|
||||
"go_forward": "Go forward",
|
||||
"group_by": "Group by",
|
||||
"go_forward": "Előre",
|
||||
"group_by": "Csoportosítás",
|
||||
"label": "Címke",
|
||||
"learn_more": "Tudjon meg többet",
|
||||
"less": "Kevesebb",
|
||||
"more": "Több",
|
||||
"new": "Új",
|
||||
"no": "Nem",
|
||||
"open_workspace": "Open workspace",
|
||||
"open_workspace": "Munkaterület megnyitása",
|
||||
"paste": "Beillesztés",
|
||||
"prettify": "Csinosítás",
|
||||
"remove": "Eltávolítás",
|
||||
@@ -38,7 +38,7 @@
|
||||
"search": "Keresés",
|
||||
"send": "Küldés",
|
||||
"start": "Indítás",
|
||||
"starting": "Starting",
|
||||
"starting": "Indítás",
|
||||
"stop": "Leállítás",
|
||||
"to_close": "a bezáráshoz",
|
||||
"to_navigate": "a navigáláshoz",
|
||||
@@ -118,16 +118,16 @@
|
||||
},
|
||||
"collection": {
|
||||
"created": "Gyűjtemény létrehozva",
|
||||
"different_parent": "Cannot reorder collection with different parent",
|
||||
"different_parent": "Nem lehet átrendezni a különböző szülővel rendelkező gyűjteményt",
|
||||
"edit": "Gyűjtemény szerkesztése",
|
||||
"invalid_name": "Adjon nevet a gyűjteménynek",
|
||||
"invalid_root_move": "Collection already in the root",
|
||||
"moved": "Moved Successfully",
|
||||
"invalid_root_move": "A gyűjtemény már a gyökérben van",
|
||||
"moved": "Sikeresen áthelyezve",
|
||||
"my_collections": "Saját gyűjtemények",
|
||||
"name": "Saját új gyűjtemény",
|
||||
"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": "Collection Order Updated",
|
||||
"order_changed": "Gyűjtemény sorrendje frissítve",
|
||||
"renamed": "Gyűjtemény átnevezve",
|
||||
"request_in_use": "A kérés használatban",
|
||||
"save_as": "Mentés másként",
|
||||
@@ -147,7 +147,7 @@
|
||||
"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.",
|
||||
"save_unsaved_tab": "Do you want to save changes made in this tab?",
|
||||
"save_unsaved_tab": "Szeretné menteni az ezen a lapon elvégzett változtatásokat?",
|
||||
"sync": "Szeretné visszaállítani a munkaterületét a felhőből? Ez el fogja vetni a helyi folyamatát."
|
||||
},
|
||||
"count": {
|
||||
@@ -180,8 +180,8 @@
|
||||
"profile": "Jelentkezzen be a profilja megtekintéséhez",
|
||||
"protocols": "A protokollok üresek",
|
||||
"schema": "Kapcsolódjon egy GraphQL-végponthoz a séma megtekintéséhez",
|
||||
"shortcodes": "Shortcodes are empty",
|
||||
"subscription": "Subscriptions are empty",
|
||||
"shortcodes": "A rövid kódok üresek",
|
||||
"subscription": "A feliratkozások üresek",
|
||||
"team_name": "A csapat neve üres",
|
||||
"teams": "Ön nem tartozik semmilyen csapathoz",
|
||||
"tests": "Nincsenek tesztek ehhez a kéréshez"
|
||||
@@ -194,13 +194,13 @@
|
||||
"deleted": "Környezet törlése",
|
||||
"edit": "Környezet szerkesztése",
|
||||
"invalid_name": "Adjon nevet a környezetnek",
|
||||
"my_environments": "My Environments",
|
||||
"my_environments": "Saját környezetek",
|
||||
"nested_overflow": "az egymásba ágyazott környezeti változók 10 szintre vannak korlátozva",
|
||||
"new": "Új 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.",
|
||||
"select": "Környezet kiválasztása",
|
||||
"team_environments": "Team Environments",
|
||||
"team_environments": "Csapatkörnyezetek",
|
||||
"title": "Környezetek",
|
||||
"updated": "Környezet frissítve",
|
||||
"variable_list": "Változólista"
|
||||
@@ -209,9 +209,9 @@
|
||||
"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.",
|
||||
"curl_invalid_format": "A cURL nincs megfelelően formázva",
|
||||
"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": "Veszélyes zóna",
|
||||
"delete_account": "Az Ön fiókja jelenleg tulajdonos ezekben a csapatokban:",
|
||||
"delete_account_description": "El kell távolítani magát, át kell adnia a tulajdonjogot vagy törölnie kell ezeket a csapatokat, mielőtt törölhetné a fiókját.",
|
||||
"empty_req_name": "Üres kérésnév",
|
||||
"f12_details": "(F12 a részletekért)",
|
||||
"gql_prettify_invalid_query": "Nem sikerült csinosítani egy érvénytelen lekérdezést, oldja meg a lekérdezés szintaktikai hibáit, és próbálja újra",
|
||||
@@ -219,13 +219,13 @@
|
||||
"incorrect_email": "Hibás e-mail",
|
||||
"invalid_link": "Érvénytelen hivatkozás",
|
||||
"invalid_link_description": "A kattintott hivatkozás érvénytelen vagy lejárt.",
|
||||
"json_parsing_failed": "Invalid JSON",
|
||||
"json_parsing_failed": "Érvénytelen JSON",
|
||||
"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_duration": "Nincs időtartam",
|
||||
"no_results_found": "No matches found",
|
||||
"page_not_found": "This page could not be found",
|
||||
"no_results_found": "Nincs találat",
|
||||
"page_not_found": "Ez az oldal nem található",
|
||||
"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"
|
||||
@@ -238,9 +238,9 @@
|
||||
"title": "Exportálás"
|
||||
},
|
||||
"filter": {
|
||||
"all": "All",
|
||||
"none": "None",
|
||||
"starred": "Starred"
|
||||
"all": "Összes",
|
||||
"none": "Nincs",
|
||||
"starred": "Csillagozott"
|
||||
},
|
||||
"folder": {
|
||||
"created": "Mappa létrehozva",
|
||||
@@ -256,7 +256,7 @@
|
||||
"subscriptions": "Feliratkozások"
|
||||
},
|
||||
"group": {
|
||||
"time": "Time",
|
||||
"time": "Idő",
|
||||
"url": "URL"
|
||||
},
|
||||
"header": {
|
||||
@@ -316,32 +316,32 @@
|
||||
"zen_mode": "Zen mód"
|
||||
},
|
||||
"modal": {
|
||||
"close_unsaved_tab": "You have unsaved changes",
|
||||
"close_unsaved_tab": "Elmentetlen változtatásai vannak",
|
||||
"collections": "Gyűjtemények",
|
||||
"confirm": "Megerősítés",
|
||||
"edit_request": "Kérés szerkesztése",
|
||||
"import_export": "Importálás és exportálás"
|
||||
},
|
||||
"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",
|
||||
"client_id": "Client ID",
|
||||
"color": "Pick a color",
|
||||
"already_subscribed": "Ön már feliratkozott erre a témára.",
|
||||
"clean_session": "Munkamenet törlése",
|
||||
"clear_input": "Bevitel törlése",
|
||||
"clear_input_on_send": "Bevitel törlése küldéskor",
|
||||
"client_id": "Ügyfél-azonosító",
|
||||
"color": "Válasszon színt",
|
||||
"communication": "Kommunikáció",
|
||||
"connection_config": "Connection Config",
|
||||
"connection_not_authorized": "This MQTT connection does not use any authentication.",
|
||||
"invalid_topic": "Please provide a topic for the subscription",
|
||||
"keep_alive": "Keep Alive",
|
||||
"connection_config": "Kapcsolat beállításai",
|
||||
"connection_not_authorized": "Ez az MQTT-kapcsolat nem használ semmilyen hitelesítést.",
|
||||
"invalid_topic": "Adjon témát a feliratkozáshoz",
|
||||
"keep_alive": "Életben tartás",
|
||||
"log": "Napló",
|
||||
"lw_message": "Last-Will Message",
|
||||
"lw_qos": "Last-Will QoS",
|
||||
"lw_retain": "Last-Will Retain",
|
||||
"lw_topic": "Last-Will Topic",
|
||||
"lw_message": "Utolsó kívánság üzenet",
|
||||
"lw_qos": "Utolsó kívánság QoS",
|
||||
"lw_retain": "Utolsó kívánság megtartás",
|
||||
"lw_topic": "Utolsó kívánság téma",
|
||||
"message": "Üzenet",
|
||||
"new": "New Subscription",
|
||||
"not_connected": "Please start a MQTT connection first.",
|
||||
"new": "Új feliratkozás",
|
||||
"not_connected": "Először indítson egy MQTT-kapcsolatot.",
|
||||
"publish": "Közzététel",
|
||||
"qos": "QoS",
|
||||
"ssl": "SSL",
|
||||
@@ -368,7 +368,7 @@
|
||||
},
|
||||
"profile": {
|
||||
"app_settings": "Alkalmazás beállításai",
|
||||
"default_hopp_displayname": "Unnamed User",
|
||||
"default_hopp_displayname": "Névtelen felhasználó",
|
||||
"editor": "Szerkesztő",
|
||||
"editor_description": "A szerkesztők hozzáadhatnak, szerkeszthetnek és törölhetnek kéréseket.",
|
||||
"email_verification_mail": "Egy ellenőrző e-mail el lett küldve az e-mail-címére. Kattintson a hivatkozásra az e-mail-címe ellenőrzéséhez.",
|
||||
@@ -391,26 +391,26 @@
|
||||
"choose_language": "Nyelv kiválasztása",
|
||||
"content_type": "Tartalom típusa",
|
||||
"content_type_titles": {
|
||||
"others": "Others",
|
||||
"structured": "Structured",
|
||||
"text": "Text"
|
||||
"others": "Egyebek",
|
||||
"structured": "Szerkesztett",
|
||||
"text": "Szöveg"
|
||||
},
|
||||
"copy_link": "Hivatkozás másolása",
|
||||
"different_collection": "Cannot reorder requests from different collections",
|
||||
"duplicated": "Request duplicated",
|
||||
"different_collection": "Nem lehet átrendezni a különböző gyűjteményekből érkező kéréseket",
|
||||
"duplicated": "Kérés megkettőzve",
|
||||
"duration": "Időtartam",
|
||||
"enter_curl": "cURL megadása",
|
||||
"enter_curl": "cURL-parancs megadása",
|
||||
"generate_code": "Kód előállítása",
|
||||
"generated_code": "Előállított kód",
|
||||
"header_list": "Fejléclista",
|
||||
"invalid_name": "Adjon nevet a kérésnek",
|
||||
"method": "Módszer",
|
||||
"moved": "Request moved",
|
||||
"moved": "Kérés áthelyezve",
|
||||
"name": "Kérés neve",
|
||||
"new": "Új kérés",
|
||||
"order_changed": "Request Order Updated",
|
||||
"order_changed": "Kérés sorrendje frissítve",
|
||||
"override": "Felülbírálás",
|
||||
"override_help": "A <kbd>Content-Type</kbd> beállítása a fejlécekben",
|
||||
"override_help": "<kbd>Content-Type</kbd> beállítása a fejlécekben",
|
||||
"overriden": "Felülbírálva",
|
||||
"parameter_list": "Lekérdezési paraméterek",
|
||||
"parameters": "Paraméterek",
|
||||
@@ -429,11 +429,12 @@
|
||||
"type": "Kérés típusa",
|
||||
"url": "URL",
|
||||
"variables": "Változók",
|
||||
"view_my_links": "View my links"
|
||||
"view_my_links": "Saját hivatkozások megtekintése"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Hang",
|
||||
"body": "Válasz törzse",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"filter_response_body": "JSON-válasz törzsének szűrése (JSONPath szintaxist használ)",
|
||||
"headers": "Fejlécek",
|
||||
"html": "HTML",
|
||||
"image": "Kép",
|
||||
@@ -445,13 +446,14 @@
|
||||
"status": "Állapot",
|
||||
"time": "Idő",
|
||||
"title": "Válasz",
|
||||
"video": "Videó",
|
||||
"waiting_for_connection": "várakozás kapcsolódásra",
|
||||
"xml": "XML"
|
||||
},
|
||||
"settings": {
|
||||
"accent_color": "Kiemelőszín",
|
||||
"account": "Fiók",
|
||||
"account_deleted": "Your account has been deleted",
|
||||
"account_deleted": "A fiókja törölve lett",
|
||||
"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.",
|
||||
@@ -460,8 +462,8 @@
|
||||
"change_font_size": "Betűméret megváltoztatása",
|
||||
"choose_language": "Nyelv kiválasztása",
|
||||
"dark_mode": "Sötét",
|
||||
"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": "Fiók törlése",
|
||||
"delete_account_description": "Ha törli a fiókját, akkor az összes adata véglegesen törlésre kerül. Ezt a műveletet nem lehet visszavonni.",
|
||||
"expand_navigation": "Navigáció kinyitása",
|
||||
"experiments": "Kísérletek",
|
||||
"experiments_notice": "Ez olyan kísérletek gyűjteménye, amelyeken dolgozunk, és amelyek hasznosak, szórakoztatóak lehetnek, mindkettő, vagy egyik sem. Ezek nem véglegesek és nem stabilak, ezért ha valami túl furcsa dolog történik, ne essen pánikba. Egyszerűen kapcsolja ki a hibás dolgot. Viccet félretéve, ",
|
||||
@@ -488,8 +490,8 @@
|
||||
"proxy_use_toggle": "A proxy középprogram használata a kérések küldéséhez",
|
||||
"read_the": "Olvassa el:",
|
||||
"reset_default": "Visszaállítás az alapértelmezettre",
|
||||
"short_codes": "Short codes",
|
||||
"short_codes_description": "Short codes which were created by you.",
|
||||
"short_codes": "Rövid kódok",
|
||||
"short_codes_description": "Az Ön által létrehozott rövid kódok.",
|
||||
"sidebar_on_left": "Oldalsáv a bal oldalon",
|
||||
"sync": "Szinkronizálás",
|
||||
"sync_collections": "Gyűjtemények",
|
||||
@@ -503,16 +505,16 @@
|
||||
"theme_description": "Az alkalmazás témájának személyre szabása.",
|
||||
"use_experimental_url_bar": "Kísérleti URL-sáv használata a környezet kiemelésével",
|
||||
"user": "Felhasználó",
|
||||
"verified_email": "Verified email",
|
||||
"verified_email": "Ellenőrzött e-mail-cím",
|
||||
"verify_email": "E-mail-cím ellenőrzése"
|
||||
},
|
||||
"shortcodes": {
|
||||
"actions": "Actions",
|
||||
"created_on": "Created on",
|
||||
"deleted": "Shortcode deleted",
|
||||
"method": "Method",
|
||||
"not_found": "Shortcode not found",
|
||||
"short_code": "Short code",
|
||||
"actions": "Műveletek",
|
||||
"created_on": "Létrehozva",
|
||||
"deleted": "Rövid kód törölve",
|
||||
"method": "Módszer",
|
||||
"not_found": "A rövid kód nem található",
|
||||
"short_code": "Rövid kód",
|
||||
"url": "URL"
|
||||
},
|
||||
"shortcut": {
|
||||
@@ -554,9 +556,9 @@
|
||||
"title": "Kérés"
|
||||
},
|
||||
"response": {
|
||||
"copy": "Copy response to clipboard",
|
||||
"download": "Download response as file",
|
||||
"title": "Response"
|
||||
"copy": "Válasz másolása a vágólapra",
|
||||
"download": "Válasz letöltés fájlként",
|
||||
"title": "Válasz"
|
||||
},
|
||||
"theme": {
|
||||
"black": "Téma átváltása fekete módra",
|
||||
@@ -574,8 +576,8 @@
|
||||
},
|
||||
"socketio": {
|
||||
"communication": "Kommunikáció",
|
||||
"connection_not_authorized": "This SocketIO connection does not use any authentication.",
|
||||
"event_name": "Esemény neve",
|
||||
"connection_not_authorized": "Ez a SocketIO-kapcsolat nem használ semmilyen hitelesítést.",
|
||||
"event_name": "Esemény vagy téma neve",
|
||||
"events": "Események",
|
||||
"log": "Napló",
|
||||
"url": "URL"
|
||||
@@ -592,9 +594,9 @@
|
||||
"connected": "Kapcsolódva",
|
||||
"connected_to": "Kapcsolódva ehhez: {name}",
|
||||
"connecting_to": "Kapcsolódás ehhez: {name}…",
|
||||
"connection_error": "Failed to connect",
|
||||
"connection_failed": "Connection failed",
|
||||
"connection_lost": "Connection lost",
|
||||
"connection_error": "Nem sikerült kapcsolódni",
|
||||
"connection_failed": "A kapcsolódás sikertelen",
|
||||
"connection_lost": "A kapcsolat elveszett",
|
||||
"copied_to_clipboard": "Vágólapra másolva",
|
||||
"deleted": "Törölve",
|
||||
"deprecated": "ELAVULT",
|
||||
@@ -609,17 +611,17 @@
|
||||
"history_deleted": "Előzmények törölve",
|
||||
"linewrap": "Sorok tördelése",
|
||||
"loading": "Betöltés…",
|
||||
"message_received": "Message: {message} arrived on topic: {topic}",
|
||||
"mqtt_subscription_failed": "Something went wrong while subscribing to topic: {topic}",
|
||||
"message_received": "Üzenet: {message} érkezett ehhez a témához: {topic}",
|
||||
"mqtt_subscription_failed": "Valami elromlott a következő témára való feliratkozás során: {topic}",
|
||||
"none": "Nincs",
|
||||
"nothing_found": "Semmi sem található ehhez:",
|
||||
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}",
|
||||
"published_message": "Published message: {message} to topic: {topic}",
|
||||
"reconnection_error": "Failed to reconnect",
|
||||
"subscribed_failed": "Failed to subscribe to topic: {topic}",
|
||||
"subscribed_success": "Successfully subscribed to topic: {topic}",
|
||||
"unsubscribed_failed": "Failed to unsubscribe from topic: {topic}",
|
||||
"unsubscribed_success": "Successfully unsubscribed from topic: {topic}",
|
||||
"published_error": "Valami elromlott a következő üzenet közzététele során: {topic}, ehhez a témához: {message}",
|
||||
"published_message": "Közzétett üzenet: {message}, ehhez a témához: {topic}",
|
||||
"reconnection_error": "Nem sikerült újrakapcsolódni",
|
||||
"subscribed_failed": "Nem sikerült feliratkozni erre a témára: {topic}",
|
||||
"subscribed_success": "Sikeresen feliratkozott erre a témára: {topic}",
|
||||
"unsubscribed_failed": "Nem sikerült leiratkozni erről a témáról: {topic}",
|
||||
"unsubscribed_success": "Sikeresen leiratkozott erről a témáról: {topic}",
|
||||
"waiting_send_request": "Várakozás a kérés elküldésére"
|
||||
},
|
||||
"support": {
|
||||
@@ -639,7 +641,7 @@
|
||||
"body": "Törzs",
|
||||
"collections": "Gyűjtemények",
|
||||
"documentation": "Dokumentáció",
|
||||
"environments": "Environments",
|
||||
"environments": "Környezetek",
|
||||
"headers": "Fejlécek",
|
||||
"history": "Előzmények",
|
||||
"mqtt": "MQTT",
|
||||
@@ -664,7 +666,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",
|
||||
"invalid_coll_id": "Invalid collection ID",
|
||||
"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.",
|
||||
"invalid_invite_link": "Érvénytelen meghívási hivatkozás",
|
||||
@@ -688,7 +690,7 @@
|
||||
"member_removed": "Felhasználó eltávolítva",
|
||||
"member_role_updated": "Felhasználói szerepek frissítve",
|
||||
"members": "Tagok",
|
||||
"more_members": "+{count} more",
|
||||
"more_members": "+{count} további",
|
||||
"name_length_insufficient": "A csapat nevének legalább 6 karakter hosszúságúnak kell lennie",
|
||||
"name_updated": "Csapatnév frissítve",
|
||||
"new": "Új csapat",
|
||||
@@ -696,13 +698,13 @@
|
||||
"new_name": "Saját új csapat",
|
||||
"no_access": "Nincs szerkesztési jogosultsága ezekhez a gyűjteményekhez",
|
||||
"no_invite_found": "A meghívás nem található. Vegye fel a kapcsolatot a csapat tulajdonosával.",
|
||||
"no_request_found": "Request not found.",
|
||||
"no_request_found": "A kérés nem található.",
|
||||
"not_found": "A csapat nem található. Vegye fel a kapcsolatot a csapat tulajdonosával.",
|
||||
"not_valid_viewer": "Ön nem érvényes megtekintő. Vegye fel a kapcsolatot a csapat tulajdonosával.",
|
||||
"parent_coll_move": "Cannot move collection to a child collection",
|
||||
"parent_coll_move": "Nem lehet áthelyezni a gyűjteményt egy gyermekgyűjteménybe",
|
||||
"pending_invites": "Függőben lévő meghívások",
|
||||
"permissions": "Jogosultságok",
|
||||
"same_target_destination": "Same target and destination",
|
||||
"same_target_destination": "Ugyanaz a cél és célhely",
|
||||
"saved": "Csapat elmentve",
|
||||
"select_a_team": "Csapat kiválasztása",
|
||||
"title": "Csapatok",
|
||||
@@ -710,9 +712,9 @@
|
||||
"we_sent_invite_link_description": "Kérje meg az összes meghívottat, hogy nézzék meg a beérkező leveleiket. Kattintsanak a hivatkozásra a csapathoz való csatlakozáshoz."
|
||||
},
|
||||
"team_environment": {
|
||||
"deleted": "Environment Deleted",
|
||||
"duplicate": "Environment Duplicated",
|
||||
"not_found": "Environment not found."
|
||||
"deleted": "Környezet törölve",
|
||||
"duplicate": "Környezet megkettőzve",
|
||||
"not_found": "A környezet nem található."
|
||||
},
|
||||
"test": {
|
||||
"failed": "teszt sikertelen",
|
||||
@@ -732,9 +734,9 @@
|
||||
"url": "URL"
|
||||
},
|
||||
"workspace": {
|
||||
"change": "Change workspace",
|
||||
"personal": "My Workspace",
|
||||
"team": "Team Workspace",
|
||||
"title": "Workspaces"
|
||||
"change": "Munkaterület váltása",
|
||||
"personal": "Saját munkaterület",
|
||||
"team": "Csapat-munkaterület",
|
||||
"title": "Munkaterületek"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Lihat tautan saya"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Response Body",
|
||||
"filter_response_body": "Filter body respons JSON (menggunakan sintaks JSONPath)",
|
||||
"headers": "Headers",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Waktu",
|
||||
"title": "Response",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "Menunggu koneksi",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corpo della risposta",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Intestazioni",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Stato",
|
||||
"time": "Tempo impiegato",
|
||||
"title": "Risposta",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "In attesa di connessione",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "自分のリンクを見る"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "レスポンスボディ",
|
||||
"filter_response_body": "JSONレスポンスボディをフィルタ (JSONPathシンタックスを使用)",
|
||||
"headers": "ヘッダー",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "ステータス",
|
||||
"time": "時間",
|
||||
"title": "レスポンス",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "接続を待っています",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "내 링크 보기"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "응답 본문",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "헤더",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "상태",
|
||||
"time": "시간",
|
||||
"title": "제목",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "연결 대기 중",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Reactie inhoud",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Headers",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tijd",
|
||||
"title": "Antwoord",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "wachten op verbinding",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Svarkropp",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Overskrifter",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tid",
|
||||
"title": "Respons",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "venter på tilkobling",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Ciało odpowiedzi",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Nagłówki",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Czas",
|
||||
"title": "Odpowiedź",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "oczekiwanie na połączenie",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corpo de Resposta",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Cabeçalhos",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tempo",
|
||||
"title": "Resposta",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "aguardando conexão",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corpo de Resposta",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Cabeçalhos",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tempo",
|
||||
"title": "Resposta",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "aguardando conexão",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Vizualizare link-uri"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Corpul de răspuns",
|
||||
"filter_response_body": "Filtrează corpul răspunsului JSON (folosește sintaxa JSONPath)",
|
||||
"headers": "Anteturi",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Stare",
|
||||
"time": "Timp",
|
||||
"title": "Raspuns",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "Așteptând conexiunea",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Тело ответа",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Заголовки",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Статус",
|
||||
"time": "Время",
|
||||
"title": "Ответ",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "Ожидание соединения",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Тело за одговор",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Заглавља",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Статус",
|
||||
"time": "време",
|
||||
"title": "Одговор",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "чека везу",
|
||||
"xml": "КСМЛ"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Svarskommitté",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Rubriker",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Status",
|
||||
"time": "Tid",
|
||||
"title": "Svar",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "väntar på anslutning",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
"edit": "Koleksiyonu düzenle",
|
||||
"invalid_name": "Lütfen koleksiyon için geçerli bir ad girin",
|
||||
"invalid_root_move": "Collection already in the root",
|
||||
"moved": "Moved Successfully",
|
||||
"moved": "Başarıyla taşındı",
|
||||
"my_collections": "Koleksiyonlarım",
|
||||
"name": "Yeni Koleksiyonum",
|
||||
"name_length_insufficient": "Koleksiyon adı en az 3 karakter uzunluğunda olmalıdır",
|
||||
@@ -147,7 +147,7 @@
|
||||
"remove_team": "Bu takımı silmek istediğinizden emin misiniz?",
|
||||
"remove_telemetry": "Telemetriden çıkmak istediğinizden emin misiniz?",
|
||||
"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?",
|
||||
"save_unsaved_tab": "Bu sekmede yapılan değişiklikleri kaydetmek istiyor musunuz?",
|
||||
"sync": "Bu çalışma alanını senkronize etmek istediğinizden emin misiniz?"
|
||||
},
|
||||
"count": {
|
||||
@@ -368,9 +368,9 @@
|
||||
},
|
||||
"profile": {
|
||||
"app_settings": "Uygulama ayarları",
|
||||
"default_hopp_displayname": "Unnamed User",
|
||||
"editor": "Düzenleyici",
|
||||
"editor_description": "Editors can add, edit, and delete requests.",
|
||||
"default_hopp_displayname": "Adsız Kullanıcı",
|
||||
"editor": "Editör",
|
||||
"editor_description": "Editörler istekleri ekleyebilir, düzenleyebilir ve silebilir.",
|
||||
"email_verification_mail": "Doğrulama bağlantısı e-postanıza gönderildi. E-postanızı doğrulamak için gelen bağlantıya tıklayınız.",
|
||||
"no_permission": "Bu eylemi gerçekleştirmek için gerekli yetkiniz yok.",
|
||||
"owner": "Kurucu",
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Yanıt gövdesi",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Başlıklar",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Durum",
|
||||
"time": "Zaman",
|
||||
"title": "Cevap",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "Bağlantı için bekleniyor",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "檢視我的連結"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "回應本體",
|
||||
"filter_response_body": "篩選 JSON 回應本體 (使用 JSONPath 語法)",
|
||||
"headers": "回應標頭",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "狀態",
|
||||
"time": "時間",
|
||||
"title": "回應",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "等待連線",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "Переглянути мої посилання"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Орган реагування",
|
||||
"filter_response_body": "Фільтр тіла відповідей JSON (використовує синтаксис JSONPath)",
|
||||
"headers": "Заголовки",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Статус",
|
||||
"time": "Час",
|
||||
"title": "Відповідь",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "очікування підключення",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"cancel": "Hủy bỏ",
|
||||
"choose_file": "Chọn một tệp",
|
||||
"clear": "Thông thoáng",
|
||||
"clear_all": "Quet sạch tât cả",
|
||||
"clear_all": "Quet sạch tất cả",
|
||||
"close": "Close",
|
||||
"connect": "Liên kết",
|
||||
"connecting": "Connecting",
|
||||
@@ -432,6 +432,7 @@
|
||||
"view_my_links": "View my links"
|
||||
},
|
||||
"response": {
|
||||
"audio": "Audio",
|
||||
"body": "Cơ quan phản hồi",
|
||||
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)",
|
||||
"headers": "Tiêu đề",
|
||||
@@ -445,6 +446,7 @@
|
||||
"status": "Tình trạng",
|
||||
"time": "Thời gian",
|
||||
"title": "Phản ứng",
|
||||
"video": "Video",
|
||||
"waiting_for_connection": "Đang đợi kết nối",
|
||||
"xml": "XML"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@hoppscotch/common",
|
||||
"private": true,
|
||||
"version": "2023.4.5",
|
||||
"version": "2023.4.7",
|
||||
"scripts": {
|
||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||
"dev:vite": "vite",
|
||||
|
||||
@@ -86,6 +86,7 @@ declare module '@vue/runtime-core' {
|
||||
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']
|
||||
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
|
||||
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
|
||||
@@ -134,11 +135,13 @@ declare module '@vue/runtime-core' {
|
||||
IconLucideUsers: typeof import('~icons/lucide/users')['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']
|
||||
ProfileShortcode: typeof import('./components/profile/Shortcode.vue')['default']
|
||||
|
||||
@@ -44,8 +44,9 @@
|
||||
class="flex flex-col items-center justify-center p-4 text-secondaryLight"
|
||||
>
|
||||
<icon-lucide-search class="pb-2 opacity-75 svg-icons" />
|
||||
<span class="my-2 text-center">
|
||||
{{ t("state.nothing_found") }} "{{ filterText }}"
|
||||
<span class="my-2 text-center flex flex-col">
|
||||
{{ t("state.nothing_found") }}
|
||||
<span class="break-all">"{{ filterText }}"</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -284,6 +284,14 @@ const importerAction = async (stepResults: StepReturnValue[]) => {
|
||||
emit("import-to-teams", result)
|
||||
} else {
|
||||
appendRESTCollections(result)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_IMPORT_COLLECTION",
|
||||
importer: importerModule.value!.name,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
fileImported()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-1 bg-primary">
|
||||
<div class="flex flex-col flex-1">
|
||||
<div
|
||||
class="sticky z-10 flex justify-between flex-1 border-b bg-primary border-dividerLight"
|
||||
:style="
|
||||
|
||||
@@ -89,6 +89,7 @@ import {
|
||||
import { GQLError } from "~/helpers/backend/GQLClient"
|
||||
import { computedWithControl } from "@vueuse/core"
|
||||
import { currentActiveTab } from "~/helpers/rest/tab"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
@@ -223,6 +224,13 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "my-folder") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
@@ -243,6 +251,13 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "my-request") {
|
||||
if (!isHoppRESTRequest(requestUpdated))
|
||||
@@ -264,17 +279,38 @@ const saveRequestAs = async () => {
|
||||
},
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -292,6 +328,13 @@ const saveRequestAs = async () => {
|
||||
title: requestUpdated.name,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: false,
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
pipe(
|
||||
updateTeamRequest(picked.value.requestID, data),
|
||||
TE.match(
|
||||
@@ -313,6 +356,13 @@ const saveRequestAs = async () => {
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: false,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-folder") {
|
||||
// TODO: Check for GQL request ?
|
||||
@@ -321,6 +371,13 @@ const saveRequestAs = async () => {
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
} else if (picked.value.pickedType === "gql-my-collection") {
|
||||
// TODO: Check for GQL request ?
|
||||
@@ -329,6 +386,13 @@ const saveRequestAs = async () => {
|
||||
requestUpdated as HoppGQLRequest
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
createdNow: true,
|
||||
platform: "gql",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
requestSaved()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-1 bg-primary">
|
||||
<div class="flex flex-col flex-1">
|
||||
<div
|
||||
class="sticky z-10 flex justify-between flex-1 border-b bg-primary border-dividerLight"
|
||||
:style="
|
||||
|
||||
@@ -46,6 +46,7 @@ import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { HoppGQLRequest, makeCollection } from "@hoppscotch/data"
|
||||
import { addGraphqlCollection } from "~/newstore/collections"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -79,6 +80,13 @@ export default defineComponent({
|
||||
)
|
||||
|
||||
this.hideModal()
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
isRootCollection: true,
|
||||
platform: "gql",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
},
|
||||
hideModal() {
|
||||
this.name = null
|
||||
|
||||
@@ -244,6 +244,14 @@ const importFromJSON = () => {
|
||||
return
|
||||
}
|
||||
appendGraphqlCollections(collections)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_IMPORT_COLLECTION",
|
||||
importer: "json",
|
||||
workspaceType: "personal",
|
||||
platform: "gql",
|
||||
})
|
||||
|
||||
fileImported()
|
||||
}
|
||||
reader.readAsText(inputChooseFileToImportFrom.value.files[0])
|
||||
@@ -257,6 +265,12 @@ const exportJSON = () => {
|
||||
const url = URL.createObjectURL(file)
|
||||
a.href = url
|
||||
|
||||
platform?.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "json",
|
||||
platform: "gql",
|
||||
})
|
||||
|
||||
// TODO: get uri from meta
|
||||
a.download = `${url.split("/").pop()!.split("#")[0].split("?")[0]}.json`
|
||||
document.body.appendChild(a)
|
||||
|
||||
@@ -153,6 +153,7 @@ import IconArchive from "~icons/lucide/archive"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useReadonlyStream } from "@composables/stream"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -285,6 +286,13 @@ export default defineComponent({
|
||||
response: "",
|
||||
})
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
platform: "gql",
|
||||
createdNow: true,
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
this.displayModalAddRequest(false)
|
||||
},
|
||||
addRequest(payload) {
|
||||
@@ -294,6 +302,14 @@ export default defineComponent({
|
||||
},
|
||||
onAddFolder({ name, path }) {
|
||||
addGraphqlFolder(name, path)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
isRootCollection: false,
|
||||
platform: "gql",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
this.displayModalAddFolder(false)
|
||||
},
|
||||
addFolder(payload) {
|
||||
|
||||
@@ -125,8 +125,8 @@
|
||||
@hide-modal="displayModalEditFolder(false)"
|
||||
/>
|
||||
<CollectionsEditRequest
|
||||
v-model="editingRequestName"
|
||||
:show="showModalEditRequest"
|
||||
:model-value="editingRequest ? editingRequest.name : ''"
|
||||
:loading-state="modalLoadingState"
|
||||
@submit="updateEditingRequest"
|
||||
@hide-modal="displayModalEditRequest(false)"
|
||||
@@ -157,7 +157,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, PropType, ref, watch } from "vue"
|
||||
import { computed, nextTick, PropType, ref, watch } from "vue"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { Picked } from "~/helpers/types/HoppPicked"
|
||||
@@ -288,6 +288,7 @@ const editingFolder = ref<
|
||||
const editingFolderName = ref<string | null>(null)
|
||||
const editingFolderPath = ref<string | null>(null)
|
||||
const editingRequest = ref<HoppRESTRequest | null>(null)
|
||||
const editingRequestName = ref("")
|
||||
const editingRequestIndex = ref<number | null>(null)
|
||||
const editingRequestID = ref<string | null>(null)
|
||||
|
||||
@@ -598,11 +599,25 @@ const addNewRootCollection = (name: string) => {
|
||||
})
|
||||
)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
isRootCollection: true,
|
||||
})
|
||||
|
||||
displayModalAdd(false)
|
||||
} else if (hasTeamWriteAccess.value) {
|
||||
if (!collectionsType.value.selectedTeam) return
|
||||
modalLoadingState.value = true
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
isRootCollection: true,
|
||||
})
|
||||
|
||||
pipe(
|
||||
createNewRootCollection(name, collectionsType.value.selectedTeam.id),
|
||||
TE.match(
|
||||
@@ -651,6 +666,13 @@ const onAddRequest = (requestName: string) => {
|
||||
},
|
||||
})
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
workspaceType: "personal",
|
||||
createdNow: true,
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
displayModalAddRequest(false)
|
||||
} else if (hasTeamWriteAccess.value) {
|
||||
const folder = editingFolder.value
|
||||
@@ -666,6 +688,13 @@ const onAddRequest = (requestName: string) => {
|
||||
title: requestName,
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
workspaceType: "team",
|
||||
platform: "rest",
|
||||
createdNow: true,
|
||||
})
|
||||
|
||||
pipe(
|
||||
createRequestInCollection(folder.id, data),
|
||||
TE.match(
|
||||
@@ -711,6 +740,14 @@ const onAddFolder = (folderName: string) => {
|
||||
if (collectionsType.value.type === "my-collections") {
|
||||
if (!path) return
|
||||
addRESTFolder(folderName, path)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
workspaceType: "personal",
|
||||
isRootCollection: false,
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
displayModalAddFolder(false)
|
||||
} else if (hasTeamWriteAccess.value) {
|
||||
const folder = editingFolder.value
|
||||
@@ -718,6 +755,13 @@ const onAddFolder = (folderName: string) => {
|
||||
|
||||
modalLoadingState.value = true
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_COLLECTION",
|
||||
workspaceType: "personal",
|
||||
isRootCollection: false,
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
pipe(
|
||||
createChildCollection(folderName, folder.id),
|
||||
TE.match(
|
||||
@@ -860,6 +904,7 @@ const editRequest = (payload: {
|
||||
}) => {
|
||||
const { folderPath, requestIndex, request } = payload
|
||||
editingRequest.value = request
|
||||
editingRequestName.value = request.name ?? ""
|
||||
if (collectionsType.value.type === "my-collections" && folderPath) {
|
||||
editingFolderPath.value = folderPath
|
||||
editingRequestIndex.value = parseInt(requestIndex)
|
||||
@@ -893,6 +938,9 @@ const updateEditingRequest = (newName: string) => {
|
||||
|
||||
if (possibleActiveTab) {
|
||||
possibleActiveTab.value.document.request.name = requestUpdated.name
|
||||
nextTick(() => {
|
||||
possibleActiveTab.value.document.isDirty = false
|
||||
})
|
||||
}
|
||||
|
||||
displayModalEditRequest(false)
|
||||
@@ -931,6 +979,9 @@ const updateEditingRequest = (newName: string) => {
|
||||
|
||||
if (possibleTab) {
|
||||
possibleTab.value.document.request.name = requestName
|
||||
nextTick(() => {
|
||||
possibleTab.value.document.isDirty = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1876,6 +1927,12 @@ const exportData = async (
|
||||
}
|
||||
|
||||
const exportJSONCollection = async () => {
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "json",
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
await getJSONCollection()
|
||||
|
||||
initializeDownloadCollection(collectionJSON.value, null)
|
||||
@@ -1887,6 +1944,12 @@ const createCollectionGist = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "gist",
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
creatingGistCollection.value = true
|
||||
await getJSONCollection()
|
||||
|
||||
@@ -1917,6 +1980,12 @@ const importToTeams = async (collection: HoppCollection<HoppRESTRequest>[]) => {
|
||||
|
||||
importingMyCollections.value = true
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_COLLECTION",
|
||||
exporter: "import-to-teams",
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
pipe(
|
||||
importJSONToTeam(
|
||||
JSON.stringify(collection),
|
||||
|
||||
@@ -190,6 +190,12 @@ const createEnvironmentGist = async () => {
|
||||
)
|
||||
|
||||
toast.success(t("export.gist_created").toString())
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_EXPORT_ENVIRONMENT",
|
||||
platform: "rest",
|
||||
})
|
||||
|
||||
window.open(res.data.html_url)
|
||||
} catch (e) {
|
||||
toast.error(t("error.something_went_wrong").toString())
|
||||
@@ -249,6 +255,13 @@ const openDialogChooseFileToImportFrom = () => {
|
||||
|
||||
const importToTeams = async (content: Environment[]) => {
|
||||
loading.value = true
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_IMPORT_ENVIRONMENT",
|
||||
platform: "rest",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
for (const [i, env] of content.entries()) {
|
||||
if (i === content.length - 1) {
|
||||
await pipe(
|
||||
@@ -301,6 +314,12 @@ const importFromJSON = () => {
|
||||
return
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_IMPORT_ENVIRONMENT",
|
||||
platform: "rest",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = ({ target }) => {
|
||||
@@ -352,6 +371,7 @@ const importFromPostman = ({
|
||||
const environment: Environment = { name, variables: [] }
|
||||
values.forEach(({ key, value }) => environment.variables.push({ key, value }))
|
||||
const environments = [environment]
|
||||
|
||||
importFromHoppscotch(environments)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
/>
|
||||
<HoppSmartTabs
|
||||
v-model="selectedEnvTab"
|
||||
styles="sticky overflow-x-auto my-2 border border-divider rounded flex-shrink-0 z-0 top-0 bg-primary"
|
||||
styles="sticky overflow-x-auto my-2 border border-divider rounded flex-shrink-0 z-10 top-0 bg-primary"
|
||||
render-inactive-tabs
|
||||
>
|
||||
<HoppSmartTab
|
||||
@@ -97,7 +97,7 @@
|
||||
<HoppSmartSpinner class="my-4" />
|
||||
<span class="text-secondaryLight">{{ t("state.loading") }}</span>
|
||||
</div>
|
||||
<div v-if="isTeamSelected" class="flex flex-col">
|
||||
<div v-else-if="isTeamSelected" class="flex flex-col">
|
||||
<HoppSmartItem
|
||||
v-for="(gen, index) in teamEnvironmentList"
|
||||
:key="`gen-team-${index}`"
|
||||
@@ -161,10 +161,14 @@ import {
|
||||
selectedEnvironmentIndex$,
|
||||
setSelectedEnvironmentIndex,
|
||||
} from "~/newstore/environments"
|
||||
import { workspaceStatus$ } from "~/newstore/workspace"
|
||||
import { changeWorkspace, workspaceStatus$ } from "~/newstore/workspace"
|
||||
import TeamEnvironmentAdapter from "~/helpers/teams/TeamEnvironmentAdapter"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
|
||||
import TeamListAdapter from "~/helpers/teams/TeamListAdapter"
|
||||
import { useLocalState } from "~/newstore/localstate"
|
||||
import { onLoggedIn } from "~/composables/auth"
|
||||
import { GetMyTeamsQuery } from "~/helpers/backend/graphql"
|
||||
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
const mdAndLarger = breakpoints.greater("md")
|
||||
@@ -213,6 +217,38 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
// TeamList-Adapter
|
||||
const teamListAdapter = new TeamListAdapter(true)
|
||||
const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
||||
const teamListFetched = ref(false)
|
||||
const REMEMBERED_TEAM_ID = useLocalState("REMEMBERED_TEAM_ID")
|
||||
|
||||
onLoggedIn(() => {
|
||||
!teamListAdapter.isInitialized && teamListAdapter.initialize()
|
||||
})
|
||||
|
||||
const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
||||
REMEMBERED_TEAM_ID.value = team.id
|
||||
changeWorkspace({
|
||||
teamID: team.id,
|
||||
teamName: team.name,
|
||||
type: "team",
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => myTeams.value,
|
||||
(newTeams) => {
|
||||
if (newTeams && !teamListFetched.value) {
|
||||
teamListFetched.value = true
|
||||
if (REMEMBERED_TEAM_ID.value) {
|
||||
const team = newTeams.find((t) => t.id === REMEMBERED_TEAM_ID.value)
|
||||
if (team) switchToTeamWorkspace(team)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const selectedEnv = computed(() => {
|
||||
if (selectedEnvironmentIndex.value.type === "MY_ENV") {
|
||||
return {
|
||||
|
||||
@@ -148,6 +148,7 @@ import { useToast } from "@composables/toast"
|
||||
import { useReadonlyStream } from "@composables/stream"
|
||||
import { useColorMode } from "@composables/theming"
|
||||
import { environmentsStore } from "~/newstore/environments"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
type EnvironmentVariable = {
|
||||
id: number
|
||||
@@ -311,6 +312,11 @@ const saveEnvironment = () => {
|
||||
index: envList.value.length - 1,
|
||||
})
|
||||
toast.success(`${t("environment.created")}`)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_ENVIRONMENT",
|
||||
workspaceType: "personal",
|
||||
})
|
||||
} else if (props.editingEnvironmentIndex === "Global") {
|
||||
// Editing the Global environment
|
||||
setGlobalEnvVariables(environmentUpdated.variables)
|
||||
|
||||
@@ -156,6 +156,7 @@ import IconTrash from "~icons/lucide/trash"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import IconDone from "~icons/lucide/check"
|
||||
import IconPlus from "~icons/lucide/plus"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
type EnvironmentVariable = {
|
||||
id: number
|
||||
@@ -294,6 +295,11 @@ const saveEnvironment = async () => {
|
||||
)
|
||||
|
||||
if (props.action === "new") {
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_ENVIRONMENT",
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
await pipe(
|
||||
createTeamEnvironment(
|
||||
JSON.stringify(filterdVariables),
|
||||
|
||||
@@ -143,33 +143,51 @@
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput
|
||||
v-model="basicUsername"
|
||||
:environment-highlights="false"
|
||||
:placeholder="t('authorization.username')"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput
|
||||
v-model="basicPassword"
|
||||
:environment-highlights="false"
|
||||
:placeholder="t('authorization.password')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="authType === 'bearer'">
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput v-model="bearerToken" placeholder="Token" />
|
||||
<SmartEnvInput
|
||||
v-model="bearerToken"
|
||||
:environment-highlights="false"
|
||||
placeholder="Token"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="authType === 'oauth-2'">
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput v-model="oauth2Token" placeholder="Token" />
|
||||
<SmartEnvInput
|
||||
v-model="oauth2Token"
|
||||
:environment-highlights="false"
|
||||
placeholder="Token"
|
||||
/>
|
||||
</div>
|
||||
<HttpOAuth2Authorization />
|
||||
</div>
|
||||
<div v-if="authType === 'api-key'">
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput v-model="apiKey" placeholder="Key" />
|
||||
<SmartEnvInput
|
||||
v-model="apiKey"
|
||||
:environment-highlights="false"
|
||||
placeholder="Key"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 border-b border-dividerLight">
|
||||
<SmartEnvInput v-model="apiValue" placeholder="Value" />
|
||||
<SmartEnvInput
|
||||
v-model="apiValue"
|
||||
:environment-highlights="false"
|
||||
placeholder="Value"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center border-b border-dividerLight">
|
||||
<span class="flex items-center">
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<HoppButtonPrimary
|
||||
id="get"
|
||||
name="get"
|
||||
:loading="isLoading"
|
||||
:label="!connected ? t('action.connect') : t('action.disconnect')"
|
||||
class="w-32"
|
||||
@click="onConnectClick"
|
||||
@@ -31,7 +32,12 @@ import { GQLConnection } from "~/helpers/GQLConnection"
|
||||
import { getCurrentStrategyID } from "~/helpers/network"
|
||||
import { useReadonlyStream, useStream } from "@composables/stream"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { gqlHeaders$, gqlURL$, setGQLURL } from "~/newstore/GQLSession"
|
||||
import {
|
||||
gqlAuth$,
|
||||
gqlHeaders$,
|
||||
gqlURL$,
|
||||
setGQLURL,
|
||||
} from "~/newstore/GQLSession"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -40,15 +46,21 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const connected = useReadonlyStream(props.conn.connected$, false)
|
||||
const isLoading = useReadonlyStream(props.conn.isLoading$, false)
|
||||
const headers = useReadonlyStream(gqlHeaders$, [])
|
||||
const auth = useReadonlyStream(gqlAuth$, {
|
||||
authType: "none",
|
||||
authActive: true,
|
||||
})
|
||||
|
||||
const url = useStream(gqlURL$, "", setGQLURL)
|
||||
|
||||
const onConnectClick = () => {
|
||||
if (!connected.value) {
|
||||
props.conn.connect(url.value, headers.value as any)
|
||||
props.conn.connect(url.value, headers.value as any, auth.value)
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "graphql-schema",
|
||||
strategy: getCurrentStrategyID(),
|
||||
})
|
||||
|
||||
@@ -748,7 +748,8 @@ const runQuery = async () => {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "graphql-query",
|
||||
strategy: getCurrentStrategyID(),
|
||||
})
|
||||
|
||||
@@ -72,9 +72,11 @@
|
||||
class="flex items-center justify-between flex-1 min-w-0 transition cursor-pointer focus:outline-none text-secondaryLight text-tiny group"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center justify-center px-4 py-2 transition group-hover:text-secondary"
|
||||
class="inline-flex items-center justify-center px-4 py-2 transition group-hover:text-secondary truncate"
|
||||
>
|
||||
<icon-lucide-chevron-right class="mr-2 indicator" />
|
||||
<icon-lucide-chevron-right
|
||||
class="mr-2 indicator flex flex-shrink-0"
|
||||
/>
|
||||
<span
|
||||
:class="[
|
||||
{ 'capitalize-first': groupSelection === 'TIME' },
|
||||
|
||||
@@ -165,6 +165,7 @@ import IconCheck from "~icons/lucide/check"
|
||||
import IconWrapText from "~icons/lucide/wrap-text"
|
||||
import { currentActiveTab } from "~/helpers/rest/tab"
|
||||
import cloneDeep from "lodash-es/cloneDeep"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -248,6 +249,10 @@ watch(
|
||||
(goingToShow) => {
|
||||
if (goingToShow) {
|
||||
request.value = cloneDeep(currentActiveTab.value.document.request)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REST_CODEGEN_OPENED",
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -338,7 +338,7 @@ watch(workingHeaders, (headersList) => {
|
||||
|
||||
// Sync logic between headers and working/bulk headers
|
||||
watch(
|
||||
request.value.headers,
|
||||
() => request.value.headers,
|
||||
(newHeadersList) => {
|
||||
// Sync should overwrite working headers
|
||||
const filteredWorkingHeaders = pipe(
|
||||
|
||||
@@ -94,6 +94,7 @@ import IconClipboard from "~icons/lucide/clipboard"
|
||||
import IconCheck from "~icons/lucide/check"
|
||||
import IconTrash2 from "~icons/lucide/trash-2"
|
||||
import { currentActiveTab } from "~/helpers/rest/tab"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -144,6 +145,10 @@ const handleImport = () => {
|
||||
try {
|
||||
const req = parseCurlToHoppRESTReq(text)
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REST_IMPORT_CURL",
|
||||
})
|
||||
|
||||
currentActiveTab.value.document.request = req
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
||||
@@ -217,6 +217,7 @@
|
||||
@hide-modal="showCodegenModal = false"
|
||||
/>
|
||||
<CollectionsSaveRequest
|
||||
v-if="showSaveRequestModal"
|
||||
mode="rest"
|
||||
:show="showSaveRequestModal"
|
||||
@hide-modal="showSaveRequestModal = false"
|
||||
@@ -323,7 +324,8 @@ const newSendRequest = async () => {
|
||||
loading.value = true
|
||||
|
||||
// Log the request run into analytics
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "rest",
|
||||
strategy: getCurrentStrategyID(),
|
||||
})
|
||||
@@ -445,6 +447,11 @@ const copyRequest = async () => {
|
||||
shareLink.value = ""
|
||||
fetchingShareLink.value = true
|
||||
const shortcodeResult = await createShortcode(tab.value.document.request)()
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SHORTCODE_CREATED",
|
||||
})
|
||||
|
||||
if (E.isLeft(shortcodeResult)) {
|
||||
toast.error(`${shortcodeResult.left.error}`)
|
||||
shareLink.value = `${t("error.something_went_wrong")}`
|
||||
@@ -515,6 +522,14 @@ const saveRequest = () => {
|
||||
editRESTRequest(saveCtx.folderPath, saveCtx.requestIndex, req)
|
||||
|
||||
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
|
||||
@@ -525,6 +540,13 @@ const saveRequest = () => {
|
||||
|
||||
// TODO: handle error case (NOTE: overwriteRequestTeams is async)
|
||||
try {
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SAVE_REQUEST",
|
||||
platform: "rest",
|
||||
createdNow: false,
|
||||
workspaceType: "team",
|
||||
})
|
||||
|
||||
runMutation(UpdateRequestDocument, {
|
||||
requestID: saveCtx.requestID,
|
||||
data: {
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { HoppRESTRequest } from "@hoppscotch/data"
|
||||
import { computed, ref, watch } from "vue"
|
||||
import { useVModel } from "@vueuse/core"
|
||||
import { computed, ref } from "vue"
|
||||
|
||||
export type RequestOptionTabs =
|
||||
| "params"
|
||||
@@ -70,15 +71,7 @@ const emit = defineEmits<{
|
||||
(e: "update:modelValue", value: HoppRESTRequest): void
|
||||
}>()
|
||||
|
||||
const request = ref(props.modelValue)
|
||||
|
||||
watch(
|
||||
() => request.value,
|
||||
(newVal) => {
|
||||
emit("update:modelValue", newVal)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
const request = useVModel(props, "modelValue", emit)
|
||||
|
||||
const selectedRealtimeTab = ref<RequestOptionTabs>("params")
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
class="flex items-center justify-between flex-1 min-w-0 transition cursor-pointer focus:outline-none text-secondaryLight text-tiny group"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center justify-center px-4 py-2 transition group-hover:text-secondary"
|
||||
class="inline-flex items-center justify-center px-4 py-2 transition group-hover:text-secondary truncate"
|
||||
>
|
||||
<icon-lucide-chevron-right class="mr-2 indicator" />
|
||||
<icon-lucide-chevron-right
|
||||
class="mr-2 indicator flex flex-shrink-0"
|
||||
/>
|
||||
<span class="truncate capitalize-first">
|
||||
{{ t("environment.title") }}
|
||||
</span>
|
||||
|
||||
@@ -44,6 +44,7 @@ const props = withDefaults(
|
||||
envs?: { key: string; value: string; source: string }[] | null
|
||||
focus?: boolean
|
||||
selectTextOnMount?: boolean
|
||||
environmentHighlights?: boolean
|
||||
readonly?: boolean
|
||||
}>(),
|
||||
{
|
||||
@@ -53,6 +54,7 @@ const props = withDefaults(
|
||||
envs: null,
|
||||
focus: false,
|
||||
readonly: false,
|
||||
environmentHighlights: true,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -142,7 +144,7 @@ const initView = (el: any) => {
|
||||
tooltips({
|
||||
position: "absolute",
|
||||
}),
|
||||
envTooltipPlugin,
|
||||
props.environmentHighlights ? envTooltipPlugin : [],
|
||||
placeholderExt(props.placeholder),
|
||||
EditorView.domEventHandlers({
|
||||
paste(ev) {
|
||||
|
||||
@@ -44,6 +44,7 @@ import { createTeam } from "~/helpers/backend/mutations/Team"
|
||||
import { TeamNameCodec } from "~/helpers/backend/types/TeamName"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { useToast } from "@composables/toast"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -68,6 +69,12 @@ const addNewTeam = async () => {
|
||||
TE.fromEither,
|
||||
TE.mapLeft(() => "invalid_name" as const),
|
||||
TE.chainW(createTeam),
|
||||
TE.chainFirstIOK(
|
||||
() => () =>
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_CREATE_TEAM",
|
||||
})
|
||||
),
|
||||
TE.match(
|
||||
(err) => {
|
||||
// err is of type "invalid_name" | GQLError<Err>
|
||||
|
||||
@@ -99,7 +99,7 @@ export class GQLConnection {
|
||||
|
||||
private timeoutSubscription: any
|
||||
|
||||
public connect(url: string, headers: GQLHeader[]) {
|
||||
public connect(url: string, headers: GQLHeader[], auth: HoppGQLAuth) {
|
||||
if (this.connected$.value) {
|
||||
throw new Error(
|
||||
"A connection is already running. Close it before starting another."
|
||||
@@ -110,7 +110,7 @@ export class GQLConnection {
|
||||
this.connected$.next(true)
|
||||
|
||||
const poll = async () => {
|
||||
await this.getSchema(url, headers)
|
||||
await this.getSchema(url, headers, auth)
|
||||
this.timeoutSubscription = setTimeout(() => {
|
||||
poll()
|
||||
}, GQL_SCHEMA_POLL_INTERVAL)
|
||||
@@ -135,7 +135,11 @@ export class GQLConnection {
|
||||
this.schema$.next(null)
|
||||
}
|
||||
|
||||
private async getSchema(url: string, headers: GQLHeader[]) {
|
||||
private async getSchema(
|
||||
url: string,
|
||||
reqHeaders: GQLHeader[],
|
||||
auth: HoppGQLAuth
|
||||
) {
|
||||
try {
|
||||
this.isLoading$.next(true)
|
||||
|
||||
@@ -143,10 +147,38 @@ export class GQLConnection {
|
||||
query: getIntrospectionQuery(),
|
||||
})
|
||||
|
||||
const headers = reqHeaders.filter((x) => x.active && x.key !== "")
|
||||
|
||||
// TODO: Support a better b64 implementation than btoa ?
|
||||
if (auth.authType === "basic") {
|
||||
const username = auth.username
|
||||
const password = auth.password
|
||||
|
||||
headers.push({
|
||||
active: true,
|
||||
key: "Authorization",
|
||||
value: `Basic ${btoa(`${username}:${password}`)}`,
|
||||
})
|
||||
} else if (auth.authType === "bearer" || auth.authType === "oauth-2") {
|
||||
headers.push({
|
||||
active: true,
|
||||
key: "Authorization",
|
||||
value: `Bearer ${auth.token}`,
|
||||
})
|
||||
} else if (auth.authType === "api-key") {
|
||||
const { key, value, addTo } = auth
|
||||
|
||||
if (addTo === "Headers") {
|
||||
headers.push({
|
||||
active: true,
|
||||
key,
|
||||
value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const finalHeaders: Record<string, string> = {}
|
||||
headers
|
||||
.filter((x) => x.active && x.key !== "")
|
||||
.forEach((x) => (finalHeaders[x.key] = x.value))
|
||||
headers.forEach((x) => (finalHeaders[x.key] = x.value))
|
||||
|
||||
const reqOptions = {
|
||||
method: "POST",
|
||||
|
||||
@@ -6,14 +6,18 @@ import { isJSONContentType } from "./utils/contenttypes"
|
||||
* Handles translations for all the hopp.io REST Shareable URL params
|
||||
*/
|
||||
export function translateExtURLParams(
|
||||
urlParams: Record<string, any>
|
||||
urlParams: Record<string, any>,
|
||||
initialReq?: HoppRESTRequest
|
||||
): HoppRESTRequest {
|
||||
if (urlParams.v) return parseV1ExtURL(urlParams)
|
||||
else return parseV0ExtURL(urlParams)
|
||||
if (urlParams.v) return parseV1ExtURL(urlParams, initialReq)
|
||||
else return parseV0ExtURL(urlParams, initialReq)
|
||||
}
|
||||
|
||||
function parseV0ExtURL(urlParams: Record<string, any>): HoppRESTRequest {
|
||||
const resolvedReq = getDefaultRESTRequest()
|
||||
function parseV0ExtURL(
|
||||
urlParams: Record<string, any>,
|
||||
initialReq?: HoppRESTRequest
|
||||
): HoppRESTRequest {
|
||||
const resolvedReq = initialReq ?? getDefaultRESTRequest()
|
||||
|
||||
if (urlParams.method && typeof urlParams.method === "string") {
|
||||
resolvedReq.method = urlParams.method
|
||||
@@ -89,8 +93,11 @@ function parseV0ExtURL(urlParams: Record<string, any>): HoppRESTRequest {
|
||||
return resolvedReq
|
||||
}
|
||||
|
||||
function parseV1ExtURL(urlParams: Record<string, any>): HoppRESTRequest {
|
||||
const resolvedReq = getDefaultRESTRequest()
|
||||
function parseV1ExtURL(
|
||||
urlParams: Record<string, any>,
|
||||
initialReq?: HoppRESTRequest
|
||||
): HoppRESTRequest {
|
||||
const resolvedReq = initialReq ?? getDefaultRESTRequest()
|
||||
|
||||
if (urlParams.headers && typeof urlParams.headers === "string") {
|
||||
resolvedReq.headers = JSON.parse(urlParams.headers)
|
||||
|
||||
@@ -71,9 +71,11 @@ const parseURL = (urlText: string | number) =>
|
||||
* @returns URL object
|
||||
*/
|
||||
export function getURLObject(parsedArguments: parser.Arguments) {
|
||||
const location = parsedArguments.location ?? undefined
|
||||
|
||||
return pipe(
|
||||
// contains raw url strings
|
||||
parsedArguments._.slice(1),
|
||||
[...parsedArguments._.slice(1), location],
|
||||
A.findFirstMap(parseURL),
|
||||
// no url found
|
||||
O.getOrElse(() => new URL(defaultRESTReq.endpoint))
|
||||
|
||||
@@ -105,7 +105,8 @@ export class MQTTConnection {
|
||||
this.handleError(e)
|
||||
}
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "mqtt",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -113,7 +113,8 @@ export class SIOConnection {
|
||||
this.handleError(error, "CONNECTION")
|
||||
}
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "socketio",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ export class SSEConnection {
|
||||
})
|
||||
}
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "sse",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,7 +71,8 @@ export class WSConnection {
|
||||
this.handleError(error as SyntaxError)
|
||||
}
|
||||
|
||||
platform.analytics?.logHoppRequestRunToAnalytics({
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REQUEST_RUN",
|
||||
platform: "wss",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { refWithControl } from "@vueuse/core"
|
||||
import { HoppRESTResponse } from "../types/HoppRESTResponse"
|
||||
import { getDefaultRESTRequest } from "./default"
|
||||
import { HoppTestResult } from "../types/HoppTestResult"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
export type HoppRESTTab = {
|
||||
id: string
|
||||
@@ -147,6 +148,10 @@ export function createNewTab(document: HoppRESTDocument, switchToIt = true) {
|
||||
currentTabID.value = id
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_REST_NEW_TAB_OPENED",
|
||||
})
|
||||
|
||||
return tab
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +275,4 @@ export const gqlResponse$ = gqlSessionStore.subject$.pipe(
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
export const gqlAuth$ = gqlSessionStore.subject$.pipe(
|
||||
pluck("request", "auth"),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
export const gqlAuth$ = gqlSessionStore.subject$.pipe(pluck("request", "auth"))
|
||||
|
||||
@@ -47,6 +47,8 @@ import {
|
||||
loadTabsFromPersistedState,
|
||||
persistableTabState,
|
||||
} from "~/helpers/rest/tab"
|
||||
import { debounceTime } from "rxjs"
|
||||
import { gqlSessionStore, setGQLSession } from "./GQLSession"
|
||||
|
||||
function checkAndMigrateOldSettings() {
|
||||
if (window.localStorage.getItem("selectedEnvIndex")) {
|
||||
@@ -333,12 +335,35 @@ export function setupRESTTabsPersistence() {
|
||||
)
|
||||
}
|
||||
|
||||
// temporary persistence for GQL session
|
||||
export function setupGQLPersistence() {
|
||||
try {
|
||||
const state = window.localStorage.getItem("gqlState")
|
||||
if (state) {
|
||||
const data = JSON.parse(state)
|
||||
data["schema"] = ""
|
||||
data["response"] = ""
|
||||
setGQLSession(data)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Failed parsing persisted GraphQL state, state:`,
|
||||
window.localStorage.getItem("gqlState")
|
||||
)
|
||||
}
|
||||
|
||||
gqlSessionStore.subject$.pipe(debounceTime(500)).subscribe((state) => {
|
||||
window.localStorage.setItem("gqlState", JSON.stringify(state))
|
||||
})
|
||||
}
|
||||
|
||||
export function setupLocalPersistence() {
|
||||
checkAndMigrateOldSettings()
|
||||
|
||||
setupLocalStatePersistence()
|
||||
setupSettingsPersistence()
|
||||
setupRESTTabsPersistence()
|
||||
setupGQLPersistence()
|
||||
setupHistoryPersistence()
|
||||
setupCollectionsPersistence()
|
||||
setupGlobalEnvsPersistence()
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, watch } from "vue"
|
||||
import { useReadonlyStream } from "@composables/stream"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { usePageHead } from "@composables/head"
|
||||
import { startPageProgress, completePageProgress } from "@modules/loadingbar"
|
||||
import { useI18n } from "@composables/i18n"
|
||||
import { GQLConnection } from "@helpers/GQLConnection"
|
||||
import { computed, onBeforeUnmount } from "vue"
|
||||
|
||||
const t = useI18n()
|
||||
|
||||
@@ -28,16 +26,10 @@ usePageHead({
|
||||
})
|
||||
|
||||
const gqlConn = new GQLConnection()
|
||||
const isLoading = useReadonlyStream(gqlConn.isLoading$, false)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (gqlConn.connected$.value) {
|
||||
gqlConn.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
watch(isLoading, () => {
|
||||
if (isLoading.value) startPageProgress()
|
||||
else completePageProgress()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -79,8 +79,9 @@
|
||||
@resolve="onResolveConfirmSaveTab"
|
||||
/>
|
||||
<CollectionsSaveRequest
|
||||
v-if="savingRequest"
|
||||
mode="rest"
|
||||
:show="savingRequest"
|
||||
:mode="'rest'"
|
||||
@hide-modal="onSaveModalClose"
|
||||
/>
|
||||
</div>
|
||||
@@ -153,8 +154,11 @@ function bindRequestToURLParams() {
|
||||
// If query params are empty, or contains code or error param (these are from Oauth Redirect)
|
||||
// We skip URL params parsing
|
||||
if (Object.keys(query).length === 0 || query.code || query.error) return
|
||||
|
||||
const request = currentActiveTab.value.document.request
|
||||
|
||||
currentActiveTab.value.document.request = safelyExtractRESTRequest(
|
||||
translateExtURLParams(query),
|
||||
translateExtURLParams(query, request),
|
||||
getDefaultRESTRequest()
|
||||
)
|
||||
})
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
<p class="mt-2 text-center">
|
||||
{{ t("error.invalid_link_description") }}
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
<HoppButtonSecondary
|
||||
to="/"
|
||||
:icon="IconHome"
|
||||
filled
|
||||
:label="t('app.home')"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="flex flex-col items-center justify-center flex-1 p-4">
|
||||
<div
|
||||
@@ -76,6 +84,7 @@ import IconHome from "~icons/lucide/home"
|
||||
import IconRefreshCW from "~icons/lucide/refresh-cw"
|
||||
import { createNewTab } from "~/helpers/rest/tab"
|
||||
import { getDefaultRESTRequest } from "~/helpers/rest/default"
|
||||
import { platform } from "~/platform"
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -107,6 +116,15 @@ const addRequestToTab = () => {
|
||||
const data = shortcodeDetails.data
|
||||
|
||||
if (E.isRight(data)) {
|
||||
if (!data.right.shortcode?.request) {
|
||||
invalidLink.value = true
|
||||
return
|
||||
}
|
||||
|
||||
platform.analytics?.logEvent({
|
||||
type: "HOPP_SHORTCODE_RESOLVED",
|
||||
})
|
||||
|
||||
const request: unknown = JSON.parse(data.right.shortcode?.request as string)
|
||||
|
||||
createNewTab({
|
||||
|
||||
@@ -5,8 +5,50 @@ export type HoppRequestEvent =
|
||||
}
|
||||
| { platform: "wss" | "sse" | "socketio" | "mqtt" }
|
||||
|
||||
export type AnalyticsEvent =
|
||||
| ({ type: "HOPP_REQUEST_RUN" } & HoppRequestEvent)
|
||||
| {
|
||||
type: "HOPP_CREATE_ENVIRONMENT"
|
||||
workspaceType: "personal" | "team"
|
||||
}
|
||||
| {
|
||||
type: "HOPP_CREATE_COLLECTION"
|
||||
platform: "rest" | "gql"
|
||||
isRootCollection: boolean
|
||||
workspaceType: "personal" | "team"
|
||||
}
|
||||
| { type: "HOPP_CREATE_TEAM" }
|
||||
| {
|
||||
type: "HOPP_SAVE_REQUEST"
|
||||
createdNow: boolean
|
||||
workspaceType: "personal" | "team"
|
||||
platform: "rest" | "gql"
|
||||
}
|
||||
| { type: "HOPP_SHORTCODE_CREATED" }
|
||||
| { type: "HOPP_SHORTCODE_RESOLVED" }
|
||||
| { type: "HOPP_REST_NEW_TAB_OPENED" }
|
||||
| {
|
||||
type: "HOPP_IMPORT_COLLECTION"
|
||||
importer: string
|
||||
workspaceType: "personal" | "team"
|
||||
platform: "rest" | "gql"
|
||||
}
|
||||
| {
|
||||
type: "HOPP_IMPORT_ENVIRONMENT"
|
||||
workspaceType: "personal" | "team"
|
||||
platform: "rest" | "gql"
|
||||
}
|
||||
| {
|
||||
type: "HOPP_EXPORT_COLLECTION"
|
||||
exporter: string
|
||||
platform: "rest" | "gql"
|
||||
}
|
||||
| { type: "HOPP_EXPORT_ENVIRONMENT"; platform: "rest" | "gql" }
|
||||
| { type: "HOPP_REST_CODEGEN_OPENED" }
|
||||
| { type: "HOPP_REST_IMPORT_CURL" }
|
||||
|
||||
export type AnalyticsPlatformDef = {
|
||||
initAnalytics: () => void
|
||||
logHoppRequestRunToAnalytics: (ev: HoppRequestEvent) => void
|
||||
logEvent: (ev: AnalyticsEvent) => void
|
||||
logPageView: (pagePath: string) => void
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@hoppscotch/selfhost-web",
|
||||
"private": true,
|
||||
"version": "2023.4.5",
|
||||
"version": "2023.4.7",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev:vite": "vite",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "hoppscotch-sh-admin",
|
||||
"private": true,
|
||||
"version": "2023.4.5",
|
||||
"version": "2023.4.7",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||
|
||||
@@ -383,7 +383,7 @@ export const auth = {
|
||||
await this.signInWithEmailLink(deviceIdentifier, window.location.href);
|
||||
|
||||
removeLocalConfig('deviceIdentifier');
|
||||
window.location.href = '/';
|
||||
window.location.href = import.meta.env.VITE_ADMIN_URL;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -115,7 +115,9 @@
|
||||
}"
|
||||
:style="[
|
||||
`--thumb-width: ${scrollThumb.width}px`,
|
||||
`width: calc(100% - ${hasActions ? mdAndLarger ? '19rem' : '7rem' : '3rem'})`,
|
||||
`width: calc(100% - ${
|
||||
hasActions ? (mdAndLarger ? '19rem' : '7rem') : '3rem'
|
||||
})`,
|
||||
]"
|
||||
id="myRange"
|
||||
/>
|
||||
@@ -144,7 +146,11 @@ import {
|
||||
nextTick,
|
||||
useSlots,
|
||||
} from "vue"
|
||||
import { breakpointsTailwind, useBreakpoints, useElementSize } from "@vueuse/core"
|
||||
import {
|
||||
breakpointsTailwind,
|
||||
useBreakpoints,
|
||||
useElementSize,
|
||||
} from "@vueuse/core"
|
||||
import type { Slot } from "vue"
|
||||
import draggable from "vuedraggable-es"
|
||||
import { HoppUIPluginOptions, HOPP_UI_OPTIONS } from "./../../index"
|
||||
@@ -350,8 +356,8 @@ watch(
|
||||
rootMargin: "0px",
|
||||
threshold: 1.0,
|
||||
})
|
||||
observer.observe(element!)
|
||||
|
||||
if (element) observer.observe(element)
|
||||
element?.scrollIntoView({ behavior: "smooth", inline: "center" })
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user