Compare commits

..

12 Commits

Author SHA1 Message Date
amk-dev
a9814a6bce refactor: make the calculation more expressive 2023-09-18 11:16:24 +05:30
nivedin
34220ba814 fix: dirty tab count incorrect when closing tabs 2023-09-18 11:16:24 +05:30
Nivedin
53ec605963 fix: duplicate tab reference bug (#3356) 2023-09-18 11:15:18 +05:30
Yuri Grand
75193a7aa8 i18n: translate locales to russian (#3312)
chore: translate locales to russian
2023-09-13 12:53:10 +05:30
tyo
b269c239d9 chore(i18n): update translation for Indonesian (#3284) 2023-09-13 12:48:46 +05:30
Liyas Thomas
72b4a1fc4e fix: typo in "twitter link" and "invite to hoppscotch" action (#3346) 2023-09-13 11:55:58 +05:30
DNT
d2d1674d31 i18n: update vi.json (#3241) 2023-09-13 11:52:37 +05:30
Joel Jacob Stephen
a6b57777e3 refactor: remove font sizes from the app (#3341)
* refactor: remove font size from settings

* refactor: remove font size from themes

* refactor: remove font size from spotlight

* refactor: remove default font size

* chore: clean up

---------

Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2023-09-13 11:45:38 +05:30
Joel Jacob Stephen
65ef4db86f refactor: remove zen mode from the app (#3337)
* refactor: remove zen mode from settings

* refactor: remove zen mode from footer and options
2023-09-12 14:10:38 +05:30
Nivedin
7201147b55 fix: context-menu position fixed while scrolling (#3340) 2023-09-12 12:43:10 +05:30
Anwarul Islam
dd143c95a9 fix: unusual behavior while scrolling through spotlight entries (#3324)
* fix: spotlight scroll issue

* fix: entry hidden issue

* chore: back to loop mode
2023-09-12 12:42:44 +05:30
James George
005581ee7d fix: broken link to REST API Testing docs (#3333)
fix: broken link to REST API Testing docs
2023-09-12 12:32:10 +05:30
36 changed files with 1043 additions and 1896 deletions

View File

@@ -20,7 +20,7 @@ services:
- PORT=3170 - PORT=3170
volumes: volumes:
# Uncomment the line below when modifying code. Only applicable when using the "dev" target. # Uncomment the line below when modifying code. Only applicable when using the "dev" target.
- ./packages/hoppscotch-backend/:/usr/src/app/packages/hoppscotch-backend # - ./packages/hoppscotch-backend/:/usr/src/app
- /usr/src/app/node_modules/ - /usr/src/app/node_modules/
depends_on: depends_on:
hoppscotch-db: hoppscotch-db:

View File

@@ -21,8 +21,7 @@
"test:cov": "jest --coverage", "test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json", "test:e2e": "jest --config ./test/jest-e2e.json",
"do-test": "pnpm run test", "do-test": "pnpm run test"
"seed": "node --loader ts-node/esm prisma/seed.ts"
}, },
"dependencies": { "dependencies": {
"@nestjs-modules/mailer": "^1.8.1", "@nestjs-modules/mailer": "^1.8.1",
@@ -58,7 +57,6 @@
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"passport-microsoft": "^1.0.0", "passport-microsoft": "^1.0.0",
"pg": "^8.11.3",
"prisma": "^4.16.2", "prisma": "^4.16.2",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",

View File

@@ -1,2 +0,0 @@
-- CreateIndex
CREATE INDEX "TeamMember_userUid_idx" ON "TeamMember"("userUid");

View File

@@ -26,7 +26,6 @@ model TeamMember {
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade) team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
@@unique([teamID, userUid]) @@unique([teamID, userUid])
@@index([userUid])
} }
model TeamInvitation { model TeamInvitation {

View File

@@ -1,58 +0,0 @@
import { PrismaClient, TeamMemberRole } from '@prisma/client';
const prisma = new PrismaClient();
const noOfUsers = 600000;
const getAllUser = async () => {
const users = await prisma.user.findMany();
return users;
};
const createUsers = async () => {
for (let i = 1; i <= noOfUsers; i++) {
try {
await prisma.user.create({
data: {
email: `${i}@gmail.com`,
},
});
} catch (_) {}
}
};
const createTeams = async () => {
const users = await getAllUser();
for (let i = 0; i < users.length; i++) {
try {
await prisma.team.create({
data: {
name: `Team ${i + 1}`,
members: {
create: {
userUid: users[i].uid,
role: TeamMemberRole.OWNER,
},
},
},
});
} catch (_) {}
}
};
async function main() {
console.log('Seeding...');
await createUsers();
await createTeams();
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});

View File

@@ -20,7 +20,6 @@ import { ShortcodeModule } from './shortcode/shortcode.module';
import { COOKIES_NOT_FOUND } from './errors'; import { COOKIES_NOT_FOUND } from './errors';
import { ThrottlerModule } from '@nestjs/throttler'; import { ThrottlerModule } from '@nestjs/throttler';
import { AppController } from './app.controller'; import { AppController } from './app.controller';
import { DbModule } from './db/db.module';
@Module({ @Module({
imports: [ imports: [
@@ -67,7 +66,6 @@ import { DbModule } from './db/db.module';
ttl: +process.env.RATE_LIMIT_TTL, ttl: +process.env.RATE_LIMIT_TTL,
limit: +process.env.RATE_LIMIT_MAX, limit: +process.env.RATE_LIMIT_MAX,
}), }),
DbModule,
UserModule, UserModule,
AuthModule, AuthModule,
AdminModule, AdminModule,

View File

@@ -1 +0,0 @@
export const PG_CONNECTION = 'PG_CONNECTION';

View File

@@ -1,21 +0,0 @@
import { Global, Module } from '@nestjs/common';
import { Pool } from 'pg';
import { PG_CONNECTION } from 'src/constants';
const dbProvider = {
provide: PG_CONNECTION,
useValue: new Pool({
user: 'postgres',
host: 'hoppscotch-db',
database: 'hoppscotch',
password: 'testpass',
port: 5432,
}),
};
@Global()
@Module({
providers: [dbProvider],
exports: [dbProvider],
})
export class DbModule {}

View File

@@ -7,11 +7,7 @@ export class PrismaService
implements OnModuleInit, OnModuleDestroy implements OnModuleInit, OnModuleDestroy
{ {
constructor() { constructor() {
super( super();
{
log: ['query', 'info', 'warn', 'error'],
}
);
} }
async onModuleInit() { async onModuleInit() {
await this.$connect(); await this.$connect();

View File

@@ -22,7 +22,6 @@ import { throwErr } from 'src/utils';
import { AuthUser } from 'src/types/AuthUser'; import { AuthUser } from 'src/types/AuthUser';
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard'; import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
import { SkipThrottle } from '@nestjs/throttler'; import { SkipThrottle } from '@nestjs/throttler';
import { cons } from 'fp-ts/lib/ReadonlyNonEmptyArray';
@UseGuards(GqlThrottlerGuard) @UseGuards(GqlThrottlerGuard)
@Resolver(() => Team) @Resolver(() => Team)
@@ -56,13 +55,8 @@ export class TeamResolver {
description: 'Returns the list of members of a team', description: 'Returns the list of members of a team',
complexity: 10, complexity: 10,
}) })
async teamMembers(@Parent() team: Team): Promise<TeamMember[]> { teamMembers(@Parent() team: Team): Promise<TeamMember[]> {
const startR = Date.now(); return this.teamService.getTeamMembers(team.id);
const members = await this.teamService.getTeamMembers(team.id);
const endR = Date.now();
console.log('response generation: (teamMembers)', endR - startR, 'ms');
return members;
} }
@ResolveField(() => TeamMemberRole, { @ResolveField(() => TeamMemberRole, {
@@ -70,61 +64,41 @@ export class TeamResolver {
nullable: true, nullable: true,
}) })
@UseGuards(GqlAuthGuard) @UseGuards(GqlAuthGuard)
async myRole( myRole(
@Parent() team: Team, @Parent() team: Team,
@GqlUser() user: AuthUser, @GqlUser() user: AuthUser,
): Promise<TeamMemberRole | null> { ): Promise<TeamMemberRole | null> {
const startR = Date.now(); return this.teamService.getRoleOfUserInTeam(team.id, user.uid);
const role = await this.teamService.getRoleOfUserInTeam(team.id, user.uid);
const endR = Date.now();
console.log('response generation: (myRole)', endR - startR, 'ms');
return role;
} }
@ResolveField(() => Int, { @ResolveField(() => Int, {
description: 'The number of users with the OWNER role in the team', description: 'The number of users with the OWNER role in the team',
}) })
async ownersCount(@Parent() team: Team): Promise<number> { ownersCount(@Parent() team: Team): Promise<number> {
const startR = Date.now(); return this.teamService.getCountOfUsersWithRoleInTeam(
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id, team.id,
TeamMemberRole.OWNER, TeamMemberRole.OWNER,
); );
const endR = Date.now();
console.log('response generation: (ownersCount)', endR - startR, 'ms');
return count;
} }
@ResolveField(() => Int, { @ResolveField(() => Int, {
description: 'The number of users with the EDITOR role in the team', description: 'The number of users with the EDITOR role in the team',
}) })
async editorsCount(@Parent() team: Team): Promise<number> { editorsCount(@Parent() team: Team): Promise<number> {
const startR = Date.now(); return this.teamService.getCountOfUsersWithRoleInTeam(
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id, team.id,
TeamMemberRole.EDITOR, TeamMemberRole.EDITOR,
); );
const endR = Date.now();
console.log('response generation: (editorsCount)', endR - startR, 'ms');
return count;
} }
@ResolveField(() => Int, { @ResolveField(() => Int, {
description: 'The number of users with the VIEWER role in the team', description: 'The number of users with the VIEWER role in the team',
}) })
async viewersCount(@Parent() team: Team): Promise<number> { viewersCount(@Parent() team: Team): Promise<number> {
const startR = Date.now(); return this.teamService.getCountOfUsersWithRoleInTeam(
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id, team.id,
TeamMemberRole.VIEWER, TeamMemberRole.VIEWER,
); );
const endR = Date.now();
console.log('response generation: (viewersCount)', endR - startR, 'ms');
return count;
} }
// Query // Query
@@ -132,7 +106,7 @@ export class TeamResolver {
description: 'List of teams that the executing user belongs to.', description: 'List of teams that the executing user belongs to.',
}) })
@UseGuards(GqlAuthGuard) @UseGuards(GqlAuthGuard)
async myTeams( myTeams(
@GqlUser() user: AuthUser, @GqlUser() user: AuthUser,
@Args({ @Args({
name: 'cursor', name: 'cursor',
@@ -143,15 +117,7 @@ export class TeamResolver {
}) })
cursor?: string, cursor?: string,
): Promise<Team[]> { ): Promise<Team[]> {
const startR = Date.now(); return this.teamService.getTeamsOfUser(user.uid, cursor ?? null);
const teams = await this.teamService.getTeamsOfUser(
user.uid,
cursor ?? null,
);
const endR = Date.now();
console.log('response generation: (myTeams)', endR - startR, 'ms');
return teams;
} }
@Query(() => Team, { @Query(() => Team, {
@@ -164,7 +130,7 @@ export class TeamResolver {
TeamMemberRole.EDITOR, TeamMemberRole.EDITOR,
TeamMemberRole.OWNER, TeamMemberRole.OWNER,
) )
async team( team(
@Args({ @Args({
name: 'teamID', name: 'teamID',
type: () => ID, type: () => ID,
@@ -172,12 +138,7 @@ export class TeamResolver {
}) })
teamID: string, teamID: string,
): Promise<Team | null> { ): Promise<Team | null> {
const startR = Date.now(); return this.teamService.getTeamWithID(teamID);
const team = await this.teamService.getTeamWithID(teamID);
const endR = Date.now();
console.log('response generation: (team)', endR - startR, 'ms');
return team;
} }
// Mutation // Mutation
@@ -190,11 +151,7 @@ export class TeamResolver {
@Args({ name: 'name', description: 'Displayed name of the team' }) @Args({ name: 'name', description: 'Displayed name of the team' })
name: string, name: string,
): Promise<Team> { ): Promise<Team> {
const startR = Date.now();
const team = await this.teamService.createTeam(name, user.uid); const team = await this.teamService.createTeam(name, user.uid);
const endR = Date.now();
console.log('response generation: (createTeam)', endR - startR, 'ms');
if (E.isLeft(team)) throwErr(team.left); if (E.isLeft(team)) throwErr(team.left);
return team.right; return team.right;
} }
@@ -212,11 +169,7 @@ export class TeamResolver {
}) })
teamID: string, teamID: string,
): Promise<boolean> { ): Promise<boolean> {
const startR = Date.now();
const isUserLeft = await this.teamService.leaveTeam(teamID, user.uid); const isUserLeft = await this.teamService.leaveTeam(teamID, user.uid);
const endR = Date.now();
console.log('response generation: (leaveTeam)', endR - startR, 'ms');
if (E.isLeft(isUserLeft)) throwErr(isUserLeft.left); if (E.isLeft(isUserLeft)) throwErr(isUserLeft.left);
return isUserLeft.right; return isUserLeft.right;
} }
@@ -241,11 +194,7 @@ export class TeamResolver {
}) })
userUid: string, userUid: string,
): Promise<boolean> { ): Promise<boolean> {
const startR = Date.now();
const isRemoved = await this.teamService.leaveTeam(teamID, userUid); const isRemoved = await this.teamService.leaveTeam(teamID, userUid);
const endR = Date.now();
console.log('response generation: (removeTeamMember)', endR - startR, 'ms');
if (E.isLeft(isRemoved)) throwErr(isRemoved.left); if (E.isLeft(isRemoved)) throwErr(isRemoved.left);
return isRemoved.right; return isRemoved.right;
} }
@@ -261,11 +210,7 @@ export class TeamResolver {
@Args({ name: 'newName', description: 'The updated name of the team' }) @Args({ name: 'newName', description: 'The updated name of the team' })
newName: string, newName: string,
): Promise<Team> { ): Promise<Team> {
const startR = Date.now();
const team = await this.teamService.renameTeam(teamID, newName); const team = await this.teamService.renameTeam(teamID, newName);
const endR = Date.now();
console.log('response generation: (renameTeam)', endR - startR, 'ms');
if (E.isLeft(team)) throwErr(team.left); if (E.isLeft(team)) throwErr(team.left);
return team.right; return team.right;
} }
@@ -279,11 +224,7 @@ export class TeamResolver {
@Args({ name: 'teamID', description: 'ID of the team', type: () => ID }) @Args({ name: 'teamID', description: 'ID of the team', type: () => ID })
teamID: string, teamID: string,
): Promise<boolean> { ): Promise<boolean> {
const startR = Date.now();
const isDeleted = await this.teamService.deleteTeam(teamID); const isDeleted = await this.teamService.deleteTeam(teamID);
const endR = Date.now();
console.log('response generation: (deleteTeam)', endR - startR, 'ms');
if (E.isLeft(isDeleted)) throwErr(isDeleted.left); if (E.isLeft(isDeleted)) throwErr(isDeleted.left);
return isDeleted.right; return isDeleted.right;
} }
@@ -313,19 +254,11 @@ export class TeamResolver {
}) })
newRole: TeamMemberRole, newRole: TeamMemberRole,
): Promise<TeamMember> { ): Promise<TeamMember> {
const startR = Date.now();
const teamMember = await this.teamService.updateTeamMemberRole( const teamMember = await this.teamService.updateTeamMemberRole(
teamID, teamID,
userUid, userUid,
newRole, newRole,
); );
const endR = Date.now();
console.log(
'response generation: (updateTeamMemberRole)',
endR - startR,
'ms',
);
if (E.isLeft(teamMember)) throwErr(teamMember.left); if (E.isLeft(teamMember)) throwErr(teamMember.left);
return teamMember.right; return teamMember.right;
} }

View File

@@ -1,4 +1,4 @@
import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import { Injectable, OnModuleInit } from '@nestjs/common';
import { TeamMember, TeamMemberRole, Team } from './team.model'; import { TeamMember, TeamMemberRole, Team } from './team.model';
import { PrismaService } from '../prisma/prisma.service'; import { PrismaService } from '../prisma/prisma.service';
import { TeamMember as DbTeamMember } from '@prisma/client'; import { TeamMember as DbTeamMember } from '@prisma/client';
@@ -23,8 +23,6 @@ import * as T from 'fp-ts/Task';
import * as A from 'fp-ts/Array'; import * as A from 'fp-ts/Array';
import { throwErr } from 'src/utils'; import { throwErr } from 'src/utils';
import { AuthUser } from '../types/AuthUser'; import { AuthUser } from '../types/AuthUser';
import { PG_CONNECTION } from 'src/constants';
import { Client } from 'pg';
@Injectable() @Injectable()
export class TeamService implements UserDataHandler, OnModuleInit { export class TeamService implements UserDataHandler, OnModuleInit {
@@ -32,11 +30,8 @@ export class TeamService implements UserDataHandler, OnModuleInit {
private readonly prisma: PrismaService, private readonly prisma: PrismaService,
private readonly userService: UserService, private readonly userService: UserService,
private readonly pubsub: PubSubService, private readonly pubsub: PubSubService,
@Inject(PG_CONNECTION) private conn: Client,
) {} ) {}
enableRawSql: boolean = false;
onModuleInit() { onModuleInit() {
this.userService.registerUserDataHandler(this); this.userService.registerUserDataHandler(this);
} }
@@ -57,37 +52,12 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string, teamID: string,
role: TeamMemberRole, role: TeamMemberRole,
): Promise<number> { ): Promise<number> {
if (this.enableRawSql) { return await this.prisma.teamMember.count({
const startQ = Date.now();
const count = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${role}';`,
);
const endQ = Date.now();
console.log(
'getCountOfUsersWithRoleInTeam >>>>>>>>>>',
endQ - startQ,
'ms >>>>>',
count.rows,
);
return count.rows[0].count;
}
const startQ = Date.now();
const count = await this.prisma.teamMember.count({
where: { where: {
teamID, teamID,
role, role,
}, },
}); });
const endQ = Date.now();
console.log(
'getCountOfUsersWithRoleInTeam >>>>>>>>>>',
endQ - startQ,
'ms >>>>>',
count,
);
return count;
} }
async addMemberToTeamWithEmail( async addMemberToTeamWithEmail(
@@ -107,11 +77,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
uid: string, uid: string,
role: TeamMemberRole, role: TeamMemberRole,
): Promise<TeamMember> { ): Promise<TeamMember> {
const tm = await this.conn.query(
`INSERT INTO "TeamMember" (id, userUid, teamID, role) VALUES ('${new Date().toISOString()}', '${uid}', '${teamID}', '${role}') RETURNING *;`,
);
console.log('addMemberToTeam >>>>>>>>>>', tm.rows[0]);
const teamMember = await this.prisma.teamMember.create({ const teamMember = await this.prisma.teamMember.create({
data: { data: {
userUid: uid, userUid: uid,
@@ -136,31 +101,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
} }
async deleteTeam(teamID: string): Promise<E.Left<string> | E.Right<boolean>> { async deleteTeam(teamID: string): Promise<E.Left<string> | E.Right<boolean>> {
if (this.enableRawSql) {
const startQ = Date.now();
const t = await this.conn.query(
`SELECT * FROM "Team" WHERE "id" = '${teamID}'`,
);
if (t.rows.length === 0) return E.left(TEAM_INVALID_ID);
await this.conn.query(
`DELETE FROM "TeamMember" WHERE "teamID" = '${teamID}' RETURNING *`,
);
await this.conn.query(`DELETE FROM "Team" WHERE "id" = '${teamID}'`);
const endQ = Date.now();
console.log(
'deleteTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
t.rows[0],
);
return E.right(true);
}
const startQ = Date.now();
const team = await this.prisma.team.findUnique({ const team = await this.prisma.team.findUnique({
where: { where: {
id: teamID, id: teamID,
@@ -179,8 +119,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
id: teamID, id: teamID,
}, },
}); });
const endQ = Date.now();
console.log('deleteTeam >>>>>>>>>>', endQ - startQ, 'ms', '>>>>>', team);
return E.right(true); return E.right(true);
} }
@@ -197,26 +135,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
const isValidTitle = this.validateTeamName(newName); const isValidTitle = this.validateTeamName(newName);
if (E.isLeft(isValidTitle)) return isValidTitle; if (E.isLeft(isValidTitle)) return isValidTitle;
if (this.enableRawSql) {
const startQ = Date.now();
const ut = await this.conn.query(
`UPDATE "Team" SET "name" = '${newName}' WHERE "id" = '${teamID}' RETURNING *`,
);
const endQ = Date.now();
console.log(
'renameTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
ut.rows[0],
);
return E.right(<Team>{
id: ut.rows[0].id,
name: ut.rows[0].name,
});
}
try { try {
const updatedTeam = await this.prisma.team.update({ const updatedTeam = await this.prisma.team.update({
where: { where: {
@@ -238,48 +156,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
userUid: string, userUid: string,
newRole: TeamMemberRole, newRole: TeamMemberRole,
): Promise<E.Left<string> | E.Right<TeamMember>> { ): Promise<E.Left<string> | E.Right<TeamMember>> {
if (this.enableRawSql) {
const startQ = Date.now();
const oc = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${TeamMemberRole.OWNER}';`,
);
const tm = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
if (tm.rows.length === 0) return E.left(TEAM_MEMBER_NOT_FOUND);
const ownerCount = oc.rows[0].count;
if (
tm.rows[0].role === TeamMemberRole.OWNER &&
newRole != TeamMemberRole.OWNER &&
ownerCount === 1
) {
return E.left(TEAM_ONLY_ONE_OWNER);
}
const utm = await this.conn.query(
`UPDATE "teamMember" SET "role" = '${newRole}' WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
const endQ = Date.now();
console.log(
'updateTeamMemberRole >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
utm.rows[0],
);
const updatedMember: TeamMember = {
membershipID: utm.rows[0].id,
userUid: utm.rows[0].userUid,
role: TeamMemberRole[utm.rows[0].role],
};
this.pubsub.publish(`team/${teamID}/member_updated`, updatedMember);
return E.right(updatedMember);
}
const startQ = Date.now();
const ownerCount = await this.prisma.teamMember.count({ const ownerCount = await this.prisma.teamMember.count({
where: { where: {
teamID, teamID,
@@ -316,14 +192,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
role: newRole, role: newRole,
}, },
}); });
const endQ = Date.now();
console.log(
'updateTeamMemberRole >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
result,
);
const updatedMember: TeamMember = { const updatedMember: TeamMember = {
membershipID: result.id, membershipID: result.id,
@@ -340,30 +208,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string, teamID: string,
userUid: string, userUid: string,
): Promise<E.Left<string> | E.Right<boolean>> { ): Promise<E.Left<string> | E.Right<boolean>> {
if (this.enableRawSql) {
const oc = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${TeamMemberRole.OWNER}';`,
);
const ownerCount = oc.rows[0].count;
console.log('leaveTeam >>>>>>>>>>', oc.rows);
const member = await this.getTeamMember(teamID, userUid);
if (!member) return E.left(TEAM_INVALID_ID_OR_USER);
if (ownerCount === 1 && member.role === TeamMemberRole.OWNER) {
return E.left(TEAM_ONLY_ONE_OWNER);
}
const dtm = await this.conn.query(
`DELETE FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
console.log('leaveTeam >>>>>>>>>>', dtm);
this.pubsub.publish(`team/${teamID}/member_removed`, userUid);
return E.right(true);
}
const ownerCount = await this.prisma.teamMember.count({ const ownerCount = await this.prisma.teamMember.count({
where: { where: {
teamID, teamID,
@@ -404,34 +248,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
const isValidName = this.validateTeamName(name); const isValidName = this.validateTeamName(name);
if (E.isLeft(isValidName)) return isValidName; if (E.isLeft(isValidName)) return isValidName;
if (this.enableRawSql) {
const startQ = Date.now();
const t = await this.conn.query(
`INSERT INTO "Team" (id, name) VALUES ('${new Date().toISOString()}', '${name}') RETURNING *`,
);
const tm = await this.conn.query(
`INSERT INTO "TeamMember" ("id", "userUid", "teamID", "role") VALUES ('${new Date().toISOString()}', '${creatorUid}' , '${
t.rows[0].id
}', '${TeamMemberRole.OWNER}') RETURNING *`,
);
const endQ = Date.now();
``;
console.log(
'createTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
t.rows[0],
tm.rows[0],
);
return E.right(<Team>{
id: t.rows[0].id,
name: t.rows[0].name,
});
}
const startQ = Date.now();
const team = await this.prisma.team.create({ const team = await this.prisma.team.create({
data: { data: {
name: name, name: name,
@@ -443,42 +259,12 @@ export class TeamService implements UserDataHandler, OnModuleInit {
}, },
}, },
}); });
const endQ = Date.now();
console.log('createTeam >>>>>>>>>> ', endQ - startQ, 'ms', '>>>>>', team);
return E.right(team); return E.right(team);
} }
async getTeamsOfUser(uid: string, cursor: string | null): Promise<Team[]> { async getTeamsOfUser(uid: string, cursor: string | null): Promise<Team[]> {
if (this.enableRawSql) {
const startQ = Date.now();
let users;
if (cursor) {
users = await this.conn.query(
`SELECT * FROM "TeamMember" LEFT JOIN "Team" ON "TeamMember"."teamID" = "Team"."id" WHERE "TeamMember"."userUid" = '${uid}' and "TeamMember"."teamID" > '${cursor}' LIMIT 10`,
);
} else {
users = await this.conn.query(
`SELECT * FROM "TeamMember" LEFT JOIN "Team" ON "TeamMember"."teamID" = "Team"."id" WHERE "TeamMember"."userUid" = '${uid}' LIMIT 10`,
);
}
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
users.rows,
);
return users.rows.map((entry) => ({
id: entry.teamID,
name: entry.name,
}));
}
if (!cursor) { if (!cursor) {
const startQ = Date.now();
const entries = await this.prisma.teamMember.findMany({ const entries = await this.prisma.teamMember.findMany({
take: 10, take: 10,
where: { where: {
@@ -488,18 +274,9 @@ export class TeamService implements UserDataHandler, OnModuleInit {
team: true, team: true,
}, },
}); });
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
entries,
);
return entries.map((entry) => entry.team); return entries.map((entry) => entry.team);
} else { } else {
const startQ = Date.now();
const entries = await this.prisma.teamMember.findMany({ const entries = await this.prisma.teamMember.findMany({
take: 10, take: 10,
skip: 1, skip: 1,
@@ -516,56 +293,17 @@ export class TeamService implements UserDataHandler, OnModuleInit {
team: true, team: true,
}, },
}); });
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
entries,
);
return entries.map((entry) => entry.team); return entries.map((entry) => entry.team);
} }
} }
async getTeamWithID(teamID: string): Promise<Team | null> { async getTeamWithID(teamID: string): Promise<Team | null> {
if (this.enableRawSql) {
const startQ = Date.now();
const team = await this.conn.query(
`SELECT * FROM "Team" WHERE "id" = '${teamID}'`,
);
const endQ = Date.now();
console.log(
'getTeamWithID >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
team.rows,
);
if (team.rows.length === 0) return null;
return <Team>{
id: team.rows[0].id,
name: team.rows[0].name,
};
}
try { try {
const startQ = Date.now();
const team = await this.prisma.team.findUnique({ const team = await this.prisma.team.findUnique({
where: { where: {
id: teamID, id: teamID,
}, },
}); });
const endQ = Date.now();
console.log(
'getTeamWithID >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
team,
);
return team; return team;
} catch (_e) { } catch (_e) {
@@ -615,30 +353,7 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string, teamID: string,
userUid: string, userUid: string,
): Promise<TeamMember | null> { ): Promise<TeamMember | null> {
if (this.enableRawSql) {
const startQ = Date.now();
const member = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
const endQ = Date.now();
console.log(
'getTeamMember >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
member.rows,
);
if (member.rows.length === 0) return null;
return <TeamMember>{
membershipID: member.rows[0].id,
userUid: member.rows[0].userUid,
role: TeamMemberRole[member.rows[0].role],
};
}
try { try {
const startQ = Date.now();
const teamMember = await this.prisma.teamMember.findUnique({ const teamMember = await this.prisma.teamMember.findUnique({
where: { where: {
teamID_userUid: { teamID_userUid: {
@@ -647,14 +362,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
}, },
}, },
}); });
const endQ = Date.now();
console.log(
'getTeamMember >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
teamMember,
);
if (!teamMember) return null; if (!teamMember) return null;
@@ -726,44 +433,11 @@ export class TeamService implements UserDataHandler, OnModuleInit {
} }
async getTeamMembers(teamID: string): Promise<TeamMember[]> { async getTeamMembers(teamID: string): Promise<TeamMember[]> {
if (this.enableRawSql) {
const startQ = Date.now();
const members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}'`,
);
const endQ = Date.now();
console.log(
'getTeamMembers >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
members.rows,
);
return members.rows.map((entry) => {
return {
membershipID: entry.id,
userUid: entry.userUid,
role: TeamMemberRole[entry.role],
};
});
}
const startQ = Date.now();
const dbTeamMembers = await this.prisma.teamMember.findMany({ const dbTeamMembers = await this.prisma.teamMember.findMany({
where: { where: {
teamID, teamID,
}, },
}); });
const endQ = Date.now();
console.log(
'getTeamMembers >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
dbTeamMembers,
);
const members = dbTeamMembers.map( const members = dbTeamMembers.map(
(entry) => (entry) =>
@@ -796,39 +470,8 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string, teamID: string,
cursor: string | null, cursor: string | null,
): Promise<TeamMember[]> { ): Promise<TeamMember[]> {
if (this.enableRawSql) {
const startQ = Date.now();
let members;
if (cursor) {
members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "id" > '${cursor}' LIMIT 10`,
);
}
members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' LIMIT 10`,
);
const endQ = Date.now();
console.log(
'getMembersOfTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
members.rows,
);
return members.rows.map(
(entry) =>
<TeamMember>{
membershipID: entry.id,
userUid: entry.userUid,
role: TeamMemberRole[entry.role],
},
);
}
let teamMembers: DbTeamMember[]; let teamMembers: DbTeamMember[];
const startQ = Date.now();
if (!cursor) { if (!cursor) {
teamMembers = await this.prisma.teamMember.findMany({ teamMembers = await this.prisma.teamMember.findMany({
take: 10, take: 10,
@@ -848,14 +491,6 @@ export class TeamService implements UserDataHandler, OnModuleInit {
}, },
}); });
} }
const endQ = Date.now();
console.log(
'getMembersOfTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
teamMembers,
);
const members = teamMembers.map( const members = teamMembers.map(
(entry) => (entry) =>

View File

@@ -2,7 +2,20 @@
--font-sans: "Inter Variable", sans-serif; --font-sans: "Inter Variable", sans-serif;
--font-icon: "Material Symbols Rounded Variable"; --font-icon: "Material Symbols Rounded Variable";
--font-mono: "Roboto Mono Variable", monospace; --font-mono: "Roboto Mono Variable", monospace;
--font-size-tiny: calc(var(--font-size-body) - 0.062rem); --font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
} }
@mixin dark-theme { @mixin dark-theme {
@@ -200,8 +213,8 @@
:root { :root {
@include base-theme; @include base-theme;
@include dark-theme; @include dark-theme;
@include green-theme;
@include dark-editor-theme; @include dark-editor-theme;
@include green-theme;
} }
:root.light { :root.light {
@@ -257,63 +270,3 @@
:root[data-accent="yellow"] { :root[data-accent="yellow"] {
@include yellow-theme; @include yellow-theme;
} }
@mixin font-small {
--font-size-body: 0.75rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
}
@mixin font-medium {
--font-size-body: 0.875rem;
--line-height-body: 1.25rem;
--upper-primary-sticky-fold: 4.375rem;
--upper-secondary-sticky-fold: 6.688rem;
--upper-tertiary-sticky-fold: 9rem;
--upper-mobile-primary-sticky-fold: 7.125rem;
--upper-mobile-secondary-sticky-fold: 9.438rem;
--upper-mobile-sticky-fold: 11.75rem;
--upper-mobile-tertiary-sticky-fold: 9rem;
--lower-primary-sticky-fold: 3.25rem;
--lower-secondary-sticky-fold: 5.563rem;
--lower-tertiary-sticky-fold: 7.875rem;
--sidebar-primary-sticky-fold: 2.25rem;
}
@mixin font-large {
--font-size-body: 1rem;
--line-height-body: 1.5rem;
--upper-primary-sticky-fold: 4.625rem;
--upper-secondary-sticky-fold: 7.188rem;
--upper-tertiary-sticky-fold: 9.75rem;
--upper-mobile-primary-sticky-fold: 7.625rem;
--upper-mobile-secondary-sticky-fold: 10.188rem;
--upper-mobile-sticky-fold: 12.75rem;
--upper-mobile-tertiary-sticky-fold: 9.75rem;
--lower-primary-sticky-fold: 3.5rem;
--lower-secondary-sticky-fold: 6.063rem;
--lower-tertiary-sticky-fold: 8.625rem;
--sidebar-primary-sticky-fold: 2.5rem;
}
:root[data-font-size="small"] {
@include font-small;
}
:root[data-font-size="medium"] {
@include font-medium;
}
:root[data-font-size="large"] {
@include font-large;
}

View File

@@ -118,22 +118,22 @@
}, },
"collection": { "collection": {
"created": "Koleksi dibuat", "created": "Koleksi dibuat",
"different_parent": "Cannot reorder collection with different parent", "different_parent": "Tidak dapat mengubah urutan koleksi dengan induk yang berbeda",
"edit": "Mengubah Koleksi", "edit": "Mengubah Koleksi",
"invalid_name": "Berikan nama untuk Koleksi", "invalid_name": "Berikan nama untuk Koleksi",
"invalid_root_move": "Collection already in the root", "invalid_root_move": "Koleksi sudah berada di akar direktori",
"moved": "Moved Successfully", "moved": "Berhasil Dipindahkan",
"my_collections": "Koleksi Saya", "my_collections": "Koleksi Saya",
"name": "Koleksi Baru Saya", "name": "Koleksi Baru Saya",
"name_length_insufficient": "Nama koleksi harus minimal 3 karakter", "name_length_insufficient": "Nama koleksi harus minimal 3 karakter",
"new": "Koleksi baru", "new": "Koleksi baru",
"order_changed": "Collection Order Updated", "order_changed": "Pembaruan Urutan Koleksi",
"renamed": "Koleksi berganti nama", "renamed": "Koleksi berganti nama",
"request_in_use": "Permintaan sedang digunakan", "request_in_use": "Permintaan sedang digunakan",
"save_as": "Simpan Sebagai", "save_as": "Simpan Sebagai",
"select": "Pilih Koleksi", "select": "Pilih Koleksi",
"select_location": "Pilih lokasi", "select_location": "Pilih lokasi",
"select_team": "Pilih team", "select_team": "Pilih tim",
"team_collections": "Koleksi Tim" "team_collections": "Koleksi Tim"
}, },
"confirm": { "confirm": {
@@ -147,7 +147,7 @@
"remove_team": "Apakah Anda yakin ingin menghapus tim ini?", "remove_team": "Apakah Anda yakin ingin menghapus tim ini?",
"remove_telemetry": "Apakah Anda yakin ingin menyisih dari Telemetri?", "remove_telemetry": "Apakah Anda yakin ingin menyisih dari Telemetri?",
"request_change": "Apakah Anda yakin ingin membuang permintaan saat ini, perubahan yang belum disimpan akan hilang.", "request_change": "Apakah Anda yakin ingin membuang permintaan saat ini, perubahan yang belum disimpan akan hilang.",
"save_unsaved_tab": "Do you want to save changes made in this tab?", "save_unsaved_tab": "Apakah Anda ingin menyimpan perubahan yang dibuat di tab ini?",
"sync": "Apakah Anda ingin memulihkan ruang kerja Anda dari cloud? Ini akan membuang kemajuan lokal Anda." "sync": "Apakah Anda ingin memulihkan ruang kerja Anda dari cloud? Ini akan membuang kemajuan lokal Anda."
}, },
"count": { "count": {
@@ -180,8 +180,8 @@
"profile": "Masuk untuk melihat profil Anda", "profile": "Masuk untuk melihat profil Anda",
"protocols": "Protokol kosong", "protocols": "Protokol kosong",
"schema": "Hubungkan ke endpoint GraphQL untuk melihat skema", "schema": "Hubungkan ke endpoint GraphQL untuk melihat skema",
"shortcodes": "Shortcodes are empty", "shortcodes": "Shortcodes kosong",
"subscription": "Subscriptions are empty", "subscription": "Langganan kosong",
"team_name": "Nama team kosong", "team_name": "Nama team kosong",
"teams": "Kamu bukan di team manapun", "teams": "Kamu bukan di team manapun",
"tests": "Tidak ada tes untuk permintaan ini" "tests": "Tidak ada tes untuk permintaan ini"
@@ -189,19 +189,19 @@
"environment": { "environment": {
"add_to_global": "Tambahkan ke Global", "add_to_global": "Tambahkan ke Global",
"added": "Tambahan Environment", "added": "Tambahan Environment",
"create_new": "Membuat baru environment", "create_new": "Membuat environment baru",
"created": "Environment dibuat", "created": "Environment dibuat",
"deleted": "Environment dihapus", "deleted": "Environment dihapus",
"edit": "Sunting Environment", "edit": "Sunting Environment",
"invalid_name": "Tolong beri nama untuk environment", "invalid_name": "Tolong beri nama untuk environment",
"my_environments": "My Environments", "my_environments": "Environment Saya",
"nested_overflow": "variabel environment bersarang dibatasi hingga 10 level", "nested_overflow": "Variabel environment bersarang dibatasi hingga 10 level",
"new": "Environment Baru", "new": "Environment Baru",
"no_environment": "No environment", "no_environment": "No environment",
"no_environment_description": "Tidak ada environment yang dipilih. Pilih apa yang harus dilakukan dengan variabel berikut.", "no_environment_description": "Tidak ada environment yang dipilih. Pilih apa yang harus dilakukan dengan variabel berikut.",
"select": "Pilih environment", "select": "Pilih environment",
"team_environments": "Team Environments", "team_environments": "Environment Tim",
"title": "Environments", "title": "Environment",
"updated": "Environment diperbarui", "updated": "Environment diperbarui",
"variable_list": "Daftar Variable" "variable_list": "Daftar Variable"
}, },
@@ -210,8 +210,8 @@
"check_console_details": "Periksa console log untuk detailnya.", "check_console_details": "Periksa console log untuk detailnya.",
"curl_invalid_format": "cURL tidak diformat dengan benar", "curl_invalid_format": "cURL tidak diformat dengan benar",
"danger_zone": "Danger zone", "danger_zone": "Danger zone",
"delete_account": "Your account is currently an owner in these teams:", "delete_account": "Akun Anda saat ini merupakan pemilik dalam tim-tim ini:",
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these teams before you can delete your account.", "delete_account_description": "Anda harus menghapus diri Anda dari tim-tim ini, mentransfer kepemilikan, atau menghapus tim-tim ini sebelum Anda dapat menghapus akun Anda.",
"empty_req_name": "Nama Permintaan Kosong", "empty_req_name": "Nama Permintaan Kosong",
"f12_details": "(F12 untuk detailnya)", "f12_details": "(F12 untuk detailnya)",
"gql_prettify_invalid_query": "Tidak dapat prettify kueri yang tidak valid, menyelesaikan kesalahan sintaksis kueri, dan coba lagi", "gql_prettify_invalid_query": "Tidak dapat prettify kueri yang tidak valid, menyelesaikan kesalahan sintaksis kueri, dan coba lagi",
@@ -294,7 +294,7 @@
"from_json_description": "Impor dari Hoppscotch berkas koleksi", "from_json_description": "Impor dari Hoppscotch berkas koleksi",
"from_my_collections": "Impor dari Koleksi Saya", "from_my_collections": "Impor dari Koleksi Saya",
"from_my_collections_description": "Impor dari Berkas Koleksi Saya", "from_my_collections_description": "Impor dari Berkas Koleksi Saya",
"from_openapi": "Import dari OpenAPI", "from_openapi": "Impor dari OpenAPI",
"from_openapi_description": "Impor dari OpenAPI syarat berkas (YML/JSON)", "from_openapi_description": "Impor dari OpenAPI syarat berkas (YML/JSON)",
"from_postman": "Impor dari Postman", "from_postman": "Impor dari Postman",
"from_postman_description": "Impor dari Koleksi Postman", "from_postman_description": "Impor dari Koleksi Postman",
@@ -316,23 +316,23 @@
"zen_mode": "Zen mode" "zen_mode": "Zen mode"
}, },
"modal": { "modal": {
"close_unsaved_tab": "You have unsaved changes", "close_unsaved_tab": "Anda memiliki perubahan yang belum disimpan",
"collections": "Koleksi", "collections": "Koleksi",
"confirm": "Mengonfirmasi", "confirm": "Mengonfirmasi",
"edit_request": "Edit Request", "edit_request": "Edit Request",
"import_export": "Impor / Ekspor" "import_export": "Impor / Ekspor"
}, },
"mqtt": { "mqtt": {
"already_subscribed": "You are already subscribed to this topic.", "already_subscribed": "Anda sudah berlangganan topik ini.",
"clean_session": "Clean Session", "clean_session": "Sesi Bersih",
"clear_input": "Clear input", "clear_input": "Hapus input",
"clear_input_on_send": "Clear input on send", "clear_input_on_send": "Hapus input saat mengirim",
"client_id": "Client ID", "client_id": "Client ID",
"color": "Pick a color", "color": "Pilih warna",
"communication": "Komunikasi", "communication": "Komunikasi",
"connection_config": "Connection Config", "connection_config": "Konfigurasi Koneksi",
"connection_not_authorized": "This MQTT connection does not use any authentication.", "connection_not_authorized": "Koneksi MQTT ini tidak menggunakan otentikasi",
"invalid_topic": "Please provide a topic for the subscription", "invalid_topic": "Harap berikan topik untuk langganan",
"keep_alive": "Keep Alive", "keep_alive": "Keep Alive",
"log": "Log", "log": "Log",
"lw_message": "Last-Will Message", "lw_message": "Last-Will Message",
@@ -340,8 +340,8 @@
"lw_retain": "Last-Will Retain", "lw_retain": "Last-Will Retain",
"lw_topic": "Last-Will Topic", "lw_topic": "Last-Will Topic",
"message": "Pesan", "message": "Pesan",
"new": "New Subscription", "new": "Langganan Baru",
"not_connected": "Please start a MQTT connection first.", "not_connected": "Mulai koneksi MQTT terlebih dahulu",
"publish": "Menerbitkan", "publish": "Menerbitkan",
"qos": "QoS", "qos": "QoS",
"ssl": "SSL", "ssl": "SSL",
@@ -396,19 +396,19 @@
"text": "Text" "text": "Text"
}, },
"copy_link": "Salin tautan", "copy_link": "Salin tautan",
"different_collection": "Cannot reorder requests from different collections", "different_collection": "Tidak dapat mengubah urutan permintaan dari koleksi yang berbeda",
"duplicated": "Request duplicated", "duplicated": "Request duplicated",
"duration": "Durasi", "duration": "Durasi",
"enter_curl": "Masukkan cURL", "enter_curl": "Masukkan cURL",
"generate_code": "Generate code", "generate_code": "Hasilkan kode",
"generated_code": "Generated code", "generated_code": "Hasilkan kode",
"header_list": "Daftar Header", "header_list": "Daftar Header",
"invalid_name": "Harap berikan nama untuk request", "invalid_name": "Harap berikan nama untuk request",
"method": "Method", "method": "Method",
"moved": "Request moved", "moved": "Request moved",
"name": "Request nama", "name": "Request nama",
"new": "Request baru", "new": "Request baru",
"order_changed": "Request Order Updated", "order_changed": "Urutan Request Diperbarui",
"override": "Membatalkan", "override": "Membatalkan",
"override_help": "Set <kbd>Content-Type</kbd> in Headers", "override_help": "Set <kbd>Content-Type</kbd> in Headers",
"overriden": "Diganti", "overriden": "Diganti",
@@ -453,7 +453,7 @@
"settings": { "settings": {
"accent_color": "Accent color", "accent_color": "Accent color",
"account": "Akun", "account": "Akun",
"account_deleted": "Your account has been deleted", "account_deleted": "Akun Anda telah dihapus",
"account_description": "Sesuaikan pengaturan akun Anda.", "account_description": "Sesuaikan pengaturan akun Anda.",
"account_email_description": "Alamat surel utama Anda.", "account_email_description": "Alamat surel utama Anda.",
"account_name_description": "Ini adalah nama tampilan Anda.", "account_name_description": "Ini adalah nama tampilan Anda.",
@@ -609,7 +609,7 @@
"file_imported": "File diimpor", "file_imported": "File diimpor",
"finished_in": "Selesai dalam {duration} ms", "finished_in": "Selesai dalam {duration} ms",
"history_deleted": "Riwayat dihapus", "history_deleted": "Riwayat dihapus",
"linewrap": "Wrap lines", "linewrap": "Bungkus baris",
"loading": "Memuat...", "loading": "Memuat...",
"message_received": "Pesan: {message} tiba di topik: {topic}", "message_received": "Pesan: {message} tiba di topik: {topic}",
"mqtt_subscription_failed": "Terjadi masalah saat berlangganan topik: {topic}", "mqtt_subscription_failed": "Terjadi masalah saat berlangganan topik: {topic}",
@@ -666,7 +666,7 @@
"email_do_not_match": "Surel tidak cocok dengan detail akun Anda. Hubungi pemilik tim Anda.", "email_do_not_match": "Surel tidak cocok dengan detail akun Anda. Hubungi pemilik tim Anda.",
"exit": "Keluar dari Tim", "exit": "Keluar dari Tim",
"exit_disabled": "Hanya pemilik yang tidak dapat keluar dari tim", "exit_disabled": "Hanya pemilik yang tidak dapat keluar dari tim",
"invalid_coll_id": "Invalid collection ID", "invalid_coll_id": "ID koleksi tidak valid",
"invalid_email_format": "Format surel tidak valid", "invalid_email_format": "Format surel tidak valid",
"invalid_id": "ID tim tidak valid. Hubungi pemilik tim Anda.", "invalid_id": "ID tim tidak valid. Hubungi pemilik tim Anda.",
"invalid_invite_link": "Tautan undangan tidak valid", "invalid_invite_link": "Tautan undangan tidak valid",
@@ -690,7 +690,7 @@
"member_removed": "Pengguna dihapus", "member_removed": "Pengguna dihapus",
"member_role_updated": "Peran pengguna diperbarui", "member_role_updated": "Peran pengguna diperbarui",
"members": "Anggota", "members": "Anggota",
"more_members": "+{count} more", "more_members": "+{count} lebih",
"name_length_insufficient": "Nama tim harus setidaknya 6 karakter", "name_length_insufficient": "Nama tim harus setidaknya 6 karakter",
"name_updated": "Nama tim diperbarui", "name_updated": "Nama tim diperbarui",
"new": "Tim Baru", "new": "Tim Baru",
@@ -698,13 +698,13 @@
"new_name": "Tim baru saya", "new_name": "Tim baru saya",
"no_access": "Anda tidak memiliki akses edit ke collections ini", "no_access": "Anda tidak memiliki akses edit ke collections ini",
"no_invite_found": "Undangan tidak ditemukan. Hubungi pemilik tim Anda.", "no_invite_found": "Undangan tidak ditemukan. Hubungi pemilik tim Anda.",
"no_request_found": "Request not found.", "no_request_found": "Request tidak ditemukan.",
"not_found": "Tim tidak ditemukan. Hubungi pemilik tim Anda.", "not_found": "Tim tidak ditemukan. Hubungi pemilik tim Anda.",
"not_valid_viewer": "Anda bukan penonton yang valid. Hubungi pemilik tim Anda.", "not_valid_viewer": "Anda bukan penonton yang valid. Hubungi pemilik tim Anda.",
"parent_coll_move": "Cannot move collection to a child collection", "parent_coll_move": "Tidak dapat memindahkan koleksi ke dalam koleksi anak",
"pending_invites": "Undangan tertunda", "pending_invites": "Undangan tertunda",
"permissions": "Izin", "permissions": "Izin",
"same_target_destination": "Same target and destination", "same_target_destination": "Sama tujuan dan destinasi",
"saved": "Tim disimpan", "saved": "Tim disimpan",
"select_a_team": "Pilih tim", "select_a_team": "Pilih tim",
"title": "tim", "title": "tim",
@@ -712,9 +712,9 @@
"we_sent_invite_link_description": "Minta semua undangan untuk memeriksa kotak masuk mereka. Klik tautan untuk bergabung dengan tim." "we_sent_invite_link_description": "Minta semua undangan untuk memeriksa kotak masuk mereka. Klik tautan untuk bergabung dengan tim."
}, },
"team_environment": { "team_environment": {
"deleted": "Environment Deleted", "deleted": "Environment dihapus",
"duplicate": "Environment Duplicated", "duplicate": "Environment diduplikasi",
"not_found": "Environment not found." "not_found": "Environment tidak ditemukan."
}, },
"test": { "test": {
"failed": "Tes gagal", "failed": "Tes gagal",
@@ -734,9 +734,9 @@
"url": "URL" "url": "URL"
}, },
"workspace": { "workspace": {
"change": "Change workspace", "change": "Beralih workspace",
"personal": "My Workspace", "personal": "Workspace Saya",
"team": "Team Workspace", "team": "Workspace Tim",
"title": "Workspaces" "title": "Workspaces"
} }
} }

View File

@@ -1,48 +1,50 @@
{ {
"action": { "action": {
"autoscroll": "Autoscroll", "autoscroll": "Автоскрол",
"cancel": "Отменить", "cancel": "Отменить",
"choose_file": "Выберите файл", "choose_file": "Выберите файл",
"clear": "Очистить", "clear": "Очистить",
"clear_all": "Очистить все", "clear_all": "Очистить все",
"close": "Close", "clear_history": "Очистить всю историю",
"close": "Закрыть",
"connect": "Подключиться", "connect": "Подключиться",
"connecting": "Connecting", "connecting": "Соединение...",
"copy": "Скопировать", "copy": "Скопировать",
"delete": "Удалить", "delete": "Удалить",
"disconnect": "Отключиться", "disconnect": "Отключиться",
"dismiss": "Скрыть", "dismiss": "Скрыть",
"dont_save": "Don't save", "dont_save": "Не сохранять",
"download_file": "Скачать файл", "download_file": "Скачать файл",
"drag_to_reorder": "Drag to reorder", "drag_to_reorder": "Перетягивайте для сортировки",
"duplicate": "Дублировать", "duplicate": "Дублировать",
"edit": "Редактировать", "edit": "Редактировать",
"filter": "Filter", "filter": "Фильтр",
"go_back": "Вернуться", "go_back": "Вернуться",
"go_forward": "Go forward", "go_forward": "Вперёд",
"group_by": "Group by", "group_by": "Сгруппировать по",
"label": "Название", "label": "Название",
"learn_more": "Узнать больше", "learn_more": "Узнать больше",
"less": "Less", "less": "Меньше",
"more": "Больше", "more": "Больше",
"new": "Создать новый", "new": "Создать новый",
"no": "Нет", "no": "Нет",
"open_workspace": "Open workspace", "open_workspace": "Открыть пространство",
"paste": "Paste", "paste": "Вставить",
"prettify": "Форматировать", "prettify": "Форматировать",
"rename": "Переименовать",
"remove": "Удалить", "remove": "Удалить",
"restore": "Восстановить", "restore": "Восстановить",
"save": "Сохранить", "save": "Сохранить",
"scroll_to_bottom": "Scroll to bottom", "scroll_to_bottom": "Вниз",
"scroll_to_top": "Scroll to top", "scroll_to_top": "Вверх",
"search": "Поиск", "search": "Поиск",
"send": "Отправить", "send": "Отправить",
"start": "Начать", "start": "Начать",
"starting": "Starting", "starting": "Запускаю",
"stop": "Стоп", "stop": "Стоп",
"to_close": "to close", "to_close": "что бы закрыть",
"to_navigate": "to navigate", "to_navigate": "для навигации",
"to_select": "to select", "to_select": "выборать",
"turn_off": "Выключить", "turn_off": "Выключить",
"turn_on": "Включить", "turn_on": "Включить",
"undo": "Отменить", "undo": "Отменить",
@@ -56,9 +58,9 @@
"chat_with_us": "Связаться с нами", "chat_with_us": "Связаться с нами",
"contact_us": "Свяжитесь с нами", "contact_us": "Свяжитесь с нами",
"copy": "Копировать", "copy": "Копировать",
"copy_user_id": "Copy User Auth Token", "copy_user_id": "Копировать токен пользователя",
"developer_option": "Developer options", "developer_option": "Настройки разработчика",
"developer_option_description": "Developer tools which helps in development and maintenance of Hoppscotch.", "developer_option_description": "Инструмент разработчика помогает обслуживить и развивить Hoppscotch",
"discord": "Discord", "discord": "Discord",
"documentation": "Документация", "documentation": "Документация",
"github": "GitHub", "github": "GitHub",
@@ -67,11 +69,13 @@
"invite": "Пригласить", "invite": "Пригласить",
"invite_description": "В Hoppscotch мы разработали простой и интуитивно понятный интерфейс для создания и управления вашими API. Hoppscotch - это инструмент, который помогает создавать, тестировать, документировать и делиться своими API.", "invite_description": "В Hoppscotch мы разработали простой и интуитивно понятный интерфейс для создания и управления вашими API. Hoppscotch - это инструмент, который помогает создавать, тестировать, документировать и делиться своими API.",
"invite_your_friends": "Пригласить своих друзей", "invite_your_friends": "Пригласить своих друзей",
"social_links": "Социальные сети",
"social_description": "Подписывайся на наши соц. сети и оставайся всегда в курсе последних новостей, обновлений и релизов.",
"join_discord_community": "Присоединяйтесь к нашему сообществу Discord", "join_discord_community": "Присоединяйтесь к нашему сообществу Discord",
"keyboard_shortcuts": "Горячие клавиши", "keyboard_shortcuts": "Горячие клавиши",
"name": "Hoppscotch", "name": "Hoppscotch",
"new_version_found": "Найдена новая версия. Перезагрузите для обновления.", "new_version_found": "Найдена новая версия. Перезагрузите для обновления.",
"options": "Options", "options": "Настройки",
"proxy_privacy_policy": "Политика конфиденциальности прокси", "proxy_privacy_policy": "Политика конфиденциальности прокси",
"reload": "Перезагрузить", "reload": "Перезагрузить",
"search": "Поиск", "search": "Поиск",
@@ -79,7 +83,7 @@
"shortcuts": "Ярлыки", "shortcuts": "Ярлыки",
"spotlight": "Прожектор", "spotlight": "Прожектор",
"status": "Статус", "status": "Статус",
"status_description": "Check the status of the website", "status_description": "Проверить состояние сайта",
"terms_and_privacy": "Условия и конфиденциальность", "terms_and_privacy": "Условия и конфиденциальность",
"twitter": "Twitter", "twitter": "Twitter",
"type_a_command_search": "Введите команду или выполните поиск…", "type_a_command_search": "Введите команду или выполните поиск…",
@@ -93,7 +97,7 @@
"continue_with_email": "Продолжить с электронной почтой", "continue_with_email": "Продолжить с электронной почтой",
"continue_with_github": "Продолжить с GitHub", "continue_with_github": "Продолжить с GitHub",
"continue_with_google": "Продолжить с Google", "continue_with_google": "Продолжить с Google",
"continue_with_microsoft": "Continue with Microsoft", "continue_with_microsoft": "Продолжить с Microsoft",
"email": "Электронное письмо", "email": "Электронное письмо",
"logged_out": "Вышли из", "logged_out": "Вышли из",
"login": "Авторизоваться", "login": "Авторизоваться",
@@ -118,19 +122,20 @@
}, },
"collection": { "collection": {
"created": "Коллекция создана", "created": "Коллекция создана",
"different_parent": "Cannot reorder collection with different parent", "different_parent": "Нельзя сортировать коллекцию с разной родительской коллекцией",
"edit": "Редактировать коллекцию", "edit": "Редактировать коллекцию",
"invalid_name": "Укажите допустимое название коллекции", "invalid_name": "Укажите допустимое название коллекции",
"invalid_root_move": "Collection already in the root", "invalid_root_move": "Коллекция уже в корне",
"moved": "Moved Successfully", "moved": "Перемещено успешно",
"my_collections": "Мои коллекции", "my_collections": "Мои коллекции",
"name": "Новая коллекция", "name": "Новая коллекция",
"name_length_insufficient": "Collection name should be at least 3 characters long", "name_length_insufficient": "Имя коллекции должно иметь 3 или более символов",
"new": "Создать коллекцию", "new": "Создать коллекцию",
"order_changed": "Collection Order Updated", "order_changed": "Порядок коллекции обновлён",
"renamed": "Коллекция переименована", "renamed": "Коллекция переименована",
"request_in_use": "Запрос обрабатывается", "request_in_use": "Запрос обрабатывается",
"save_as": "Сохранить как", "save_as": "Сохранить как",
"save_to_collection": "Сохранить в коллекцию",
"select": "Выбрать коллекцию", "select": "Выбрать коллекцию",
"select_location": "Выберите местоположение", "select_location": "Выберите местоположение",
"select_team": "Выберите команду", "select_team": "Выберите команду",
@@ -146,10 +151,17 @@
"remove_request": "Вы уверены, что хотите навсегда удалить этот запрос?", "remove_request": "Вы уверены, что хотите навсегда удалить этот запрос?",
"remove_team": "Вы уверены, что хотите удалить эту команду?", "remove_team": "Вы уверены, что хотите удалить эту команду?",
"remove_telemetry": "Вы действительно хотите отказаться от телеметрии?", "remove_telemetry": "Вы действительно хотите отказаться от телеметрии?",
"request_change": "Are you sure you want to discard current request, unsaved changes will be lost.", "request_change": "Вы уверены что хотите сбросить текущий запрос, все не сохранённые данные будт утеряны?",
"save_unsaved_tab": "Do you want to save changes made in this tab?", "save_unsaved_tab": "Вы хотите сохранить изменения в этой вкладке?",
"close_unsaved_tab": "Вы уверены что хотите закрыть эту вкладку?",
"close_unsaved_tabs": "ВЫ уверены что хотите закрыть все эти вкладки? Несохранённые данные {count} вкладок будут утеряны.",
"sync": "Вы уверены, что хотите синхронизировать это рабочее пространство?" "sync": "Вы уверены, что хотите синхронизировать это рабочее пространство?"
}, },
"context_menu": {
"set_environment_variable": "Назначить как переменную",
"add_parameters": "Добавить в параметры",
"open_request_in_new_tab": "Открыть в новой вкладке"
},
"count": { "count": {
"header": "Заголовок {count}", "header": "Заголовок {count}",
"message": "Тело {count}", "message": "Тело {count}",
@@ -180,83 +192,102 @@
"profile": "Войдите, чтобы просмотреть свой профиль", "profile": "Войдите, чтобы просмотреть свой профиль",
"protocols": "Протоколы пустые", "protocols": "Протоколы пустые",
"schema": "Подключиться к конечной точке GraphQL", "schema": "Подключиться к конечной точке GraphQL",
"shortcodes": "Shortcodes are empty", "shortcodes": "Нет коротких ссылок",
"subscription": "Subscriptions are empty", "subscription": "Нет подписок",
"team_name": "Название команды пусто", "team_name": "Название команды пусто",
"teams": "Команды пустые", "teams": "Команды пустые",
"tests": "Для этого запроса нет тестов" "tests": "Для этого запроса нет тестов"
}, },
"environment": { "environment": {
"add_to_global": "Add to Global", "add_to_global": "Добавить в глобальное окружение",
"added": "Environment addition", "added": "Окружение добавлено",
"create_new": "Создать новую среду", "create_new": "Создать новое окружение",
"created": "Environment created", "created": "Окружение создано",
"deleted": "Environment deletion", "deleted": "Окружение удалено",
"edit": "Редактировать среду", "duplicated": "Окружение скопировано",
"invalid_name": "Укажите допустимое имя для среды", "global": "Глобальное окружение",
"my_environments": "My Environments", "empty_variables": "Нет переменных",
"nested_overflow": "nested environment variables are limited to 10 levels", "global_variables": "Глобальные переменные",
"edit": "Редактировать окружение",
"invalid_name": "Укажите допустимое имя для окружения",
"list": "Переменные окружения",
"my_environments": "Мои окружения",
"name": "Название",
"nested_overflow": "максимальный уровень вложения переменных окружения - 10",
"new": "Новая среда", "new": "Новая среда",
"no_environment": "Нет окружающей среды", "no_active_environment": "Нет активных окружений",
"no_environment_description": "No environments were selected. Choose what to do with the following variables.", "no_environment": "Нет окружения",
"no_environment_description": "Не выбрано окружение, выберите что делать с переменными.",
"quick_peek": "Быстрый просмотр окружения",
"replace_with_variable": "Заменить переменной",
"scope": "Scope",
"select": "Выберите среду", "select": "Выберите среду",
"team_environments": "Team Environments", "set": "Выбрать окружение",
"title": "Среды", "set_as_environment": "Установить как окружение",
"updated": "Environment updation", "team_environments": "Окружения команды",
"title": "Окружения",
"updated": "Окружение обновлено",
"value": "Значение",
"variable": "Переменная",
"variable_list": "Список переменных" "variable_list": "Список переменных"
}, },
"error": { "error": {
"browser_support_sse": "Похоже, в этом браузере нет поддержки событий, отправленных сервером.", "browser_support_sse": "Похоже, в этом браузере нет поддержки событий, отправленных сервером.",
"check_console_details": "Подробности смотрите в журнале консоли.", "check_console_details": "Подробности смотрите в журнале консоли.",
"curl_invalid_format": "cURL неправильно отформатирован", "curl_invalid_format": "cURL неправильно отформатирован",
"danger_zone": "Danger zone", "danger_zone": "Опасная зона",
"delete_account": "Your account is currently an owner in these teams:", "delete_account": "Вы являетесь владельцем этой команды:",
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these teams before you can delete your account.", "delete_account_description": "Прежде чем удалить аккаунт вам необходимо либо назначить владельцом другого пользователя, либо удалить команды в которых вы являетесь владельцем.",
"empty_req_name": "Пустое имя запроса", "empty_req_name": "Пустое имя запроса",
"f12_details": "(F12 для подробностей)", "f12_details": "(F12 для подробностей)",
"gql_prettify_invalid_query": "Не удалось определить недопустимый запрос, устранить синтаксические ошибки запроса и повторить попытку.", "gql_prettify_invalid_query": "Не удалось определить недопустимый запрос, устранить синтаксические ошибки запроса и повторить попытку.",
"incomplete_config_urls": "Incomplete configuration URLs", "incomplete_config_urls": "Не заполнены URL конфигурации",
"incorrect_email": "Incorrect email", "incorrect_email": "Не корректный Email",
"invalid_link": "Invalid link", "invalid_link": "Не корректная ссылка",
"invalid_link_description": "Ссылка, по которой вы перешли, - недействительна, либо срок ее действия истек.", "invalid_link_description": "Ссылка, по которой вы перешли, - недействительна, либо срок ее действия истек.",
"json_parsing_failed": "Invalid JSON", "json_parsing_failed": "Не корректный JSON",
"json_prettify_invalid_body": "Не удалось определить недопустимое тело, устранить синтаксические ошибки json и повторить попытку.", "json_prettify_invalid_body": "Не удалось определить недопустимое тело, устранить синтаксические ошибки json и повторить попытку.",
"network_error": "Похоже, возникла проблема с соединением. Попробуйте еще раз.", "network_error": "Похоже, возникла проблема с соединением. Попробуйте еще раз.",
"network_fail": "Не удалось отправить запрос", "network_fail": "Не удалось отправить запрос",
"no_duration": "Без продолжительности", "no_duration": "Без продолжительности",
"no_results_found": "No matches found", "no_results_found": "Совпадения не найдены",
"page_not_found": "This page could not be found", "page_not_found": "Эта страница не найдена",
"proxy_error": "Ошибка прокси",
"script_fail": "Не удалось выполнить сценарий предварительного запроса", "script_fail": "Не удалось выполнить сценарий предварительного запроса",
"something_went_wrong": "Что-то пошло не так", "something_went_wrong": "Что-то пошло не так",
"test_script_fail": "Could not execute post-request script" "test_script_fail": "Не удалось выполнить тестирование запроса"
}, },
"export": { "export": {
"as_json": "Экспорт как JSON", "as_json": "Экспорт как JSON",
"create_secret_gist": "Создать секретный Gist", "create_secret_gist": "Создать секретный Gist",
"gist_created": "Gist создан", "gist_created": "Gist создан",
"require_github": "Войдите через GitHub, чтобы создать секретную суть", "require_github": "Войдите через GitHub, чтобы создать секретную суть",
"title": "Export" "title": "Экспорт"
}, },
"filter": { "filter": {
"all": "All", "all": "Все",
"none": "None", "none": "Не указано",
"starred": "Starred" "starred": "Отмечено"
}, },
"folder": { "folder": {
"created": "Папка создана", "created": "Папка создана",
"edit": "Редактировать папку", "edit": "Редактировать папку",
"invalid_name": "Укажите имя для папки", "invalid_name": "Укажите имя для папки",
"name_length_insufficient": "Folder name should be at least 3 characters long", "name_length_insufficient": "Имя папки должно содержать 3 или более символов",
"new": "Новая папка", "new": "Новая папка",
"renamed": "Папка переименована" "renamed": "Папка переименована"
}, },
"graphql": { "graphql": {
"mutations": "Мутации", "mutations": "Мутации",
"schema": "Схема", "schema": "Схема",
"subscriptions": "Подписки" "subscriptions": "Подписки",
"switch_connection": "Изменить соединение",
"connection_switch_url": "Вы присоединились к GraphQL, URL соединения",
"connection_switch_new_url": "Смена вкладки разорвёт текущее GraphQL соединение. Новый URL соединения будет",
"connection_switch_confirm": "Вы желаете соединиться с последним GraphQL сервером?"
}, },
"group": { "group": {
"time": "Time", "time": "Время",
"url": "URL" "url": "URL"
}, },
"header": { "header": {
@@ -273,11 +304,11 @@
"post_request_tests": "Сценарии тестирования написаны на JavaScript и запускаются после получения ответа.", "post_request_tests": "Сценарии тестирования написаны на JavaScript и запускаются после получения ответа.",
"pre_request_script": "Скрипты предварительного запроса написаны на JavaScript и запускаются перед отправкой запроса.", "pre_request_script": "Скрипты предварительного запроса написаны на JavaScript и запускаются перед отправкой запроса.",
"script_fail": "Похоже, в скрипте предварительного запроса есть сбой. Проверьте ошибку ниже и исправьте скрипт соответствующим образом.", "script_fail": "Похоже, в скрипте предварительного запроса есть сбой. Проверьте ошибку ниже и исправьте скрипт соответствующим образом.",
"test_script_fail": "There seems to be an error with test script. Please fix the errors and run tests again", "test_script_fail": "Похоже, что скрипт тестирования содержит ошибку. Пожалуйста исправьте её и попробуйте снова",
"tests": "Напишите тестовый сценарий для автоматизации отладки." "tests": "Напишите тестовый сценарий для автоматизации отладки."
}, },
"hide": { "hide": {
"collection": "Collapse Collection Panel", "collection": "Свернуть панель соединения",
"more": "Скрыть больше", "more": "Скрыть больше",
"preview": "Скрыть предварительный просмотр", "preview": "Скрыть предварительный просмотр",
"sidebar": "Скрыть боковую панель" "sidebar": "Скрыть боковую панель"
@@ -287,61 +318,85 @@
"curl": "Импортировать cURL", "curl": "Импортировать cURL",
"failed": "Ошибка импорта", "failed": "Ошибка импорта",
"from_gist": "Импорт из Gist", "from_gist": "Импорт из Gist",
"from_gist_description": "Import from Gist URL", "from_gist_description": "Импортировать через Gist URL",
"from_insomnia": "Import from Insomnia", "from_insomnia": "Импортировать с Insomnia",
"from_insomnia_description": "Import from Insomnia collection", "from_insomnia_description": "Импортировать из коллекции Insomnia",
"from_json": "Import from Hoppscotch", "from_json": "Импортировать из Hoppscotch",
"from_json_description": "Import from Hoppscotch collection file", "from_json_description": "Импортировать из файла коллекции Hoppscotch",
"from_my_collections": "Импортировать из моих коллекций", "from_my_collections": "Импортировать из моих коллекций",
"from_my_collections_description": "Import from My Collections file", "from_my_collections_description": "Импортировать коллекции из моего файла",
"from_openapi": "Import from OpenAPI", "from_openapi": "Импортировать из OpenAPI",
"from_openapi_description": "Import from OpenAPI specification file (YML/JSON)", "from_openapi_description": "Импортировать из OpenAPI файла описания API (YML/JSON)",
"from_postman": "Import from Postman", "from_postman": "Импортировать из Postman",
"from_postman_description": "Import from Postman collection", "from_postman_description": "Импортировать из коллекции Postman",
"from_url": "Import from URL", "from_url": "Импортировать из URL",
"gist_url": "Введите URL-адрес Gist", "gist_url": "Введите URL-адрес Gist",
"import_from_url_invalid_fetch": "Couldn't get data from the url", "import_from_url_invalid_fetch": "Не удалить получить данные по этому URL",
"import_from_url_invalid_file_format": "Error while importing collections", "import_from_url_invalid_file_format": "Ошибка при импорте коллекций",
"import_from_url_invalid_type": "Unsupported type. accepted values are 'hoppscotch', 'openapi', 'postman', 'insomnia'", "import_from_url_invalid_type": "Неподдерживаемый тип. Поддерживаемые типы: 'hoppscotch', 'openapi', 'postman', 'insomnia'",
"import_from_url_success": "Collections Imported", "import_from_url_success": "Коллекция импортирована",
"json_description": "Import collections from a Hoppscotch Collections JSON file", "json_description": "Импортировать из коллекции Hoppscotch",
"title": "Импортировать" "title": "Импортировать"
}, },
"inspections": {
"title": "Инспектор",
"description": "Помогает обноружить возможные проблемы",
"environment": {
"add_environment": "Добавить в окружение",
"not_found": "Переменная окружения “{environment}” не найдена."
},
"header": {
"cookie": "Браузерная версия Hoppscotch не может использовать Cookie Header. Пока мы работаем над созданием десктоп версии Hoppscotch, пожалуйста используйте Authorization Header."
},
"response": {
"401_error": "Пожалуйста проверьте ваши параметры авторизации",
"404_error": "Пожалуйста проверьте URL и Метод вашего запроса",
"network_error": "Пожалуйста проверьте соединение",
"cors_error": "Пожалуйста проверьте вашу Cross-Origin Resource Sharing настройку сервера.",
"default_error": "Проверьте ваш запрос."
},
"url": {
"extension_not_installed": "Расширение не установлено",
"extention_not_enabled": "Расширение не включено",
"extention_enable_action": "Включить расширение браузера",
"extension_unknown_origin": "Убедитесь что вы добавили адрес сервера в Hoppscotch расширение."
}
},
"layout": { "layout": {
"collapse_collection": "Collapse or Expand Collections", "collapse_collection": "Свернуть или развернуть коллекции",
"collapse_sidebar": "Collapse or Expand the sidebar", "collapse_sidebar": "Свернуть или развернуть боковую панель",
"column": "Вертикальное оформление", "column": "Вертикальная развёртка",
"name": "Layout", "name": "Развёртка",
"row": "Горизонтальное оформление", "row": "Горизонтальная развертка",
"zen_mode": "Спокойный режим" "zen_mode": "Спокойный режим"
}, },
"modal": { "modal": {
"close_unsaved_tab": "You have unsaved changes", "close_unsaved_tab": "У вас есть не сохранённые изменения",
"collections": "Коллекции", "collections": "Коллекции",
"confirm": "Подтверждать", "confirm": "Подтверждать",
"edit_request": "Изменить запрос", "edit_request": "Изменить запрос",
"import_export": "Импорт Экспорт" "import_export": "Импорт Экспорт"
}, },
"mqtt": { "mqtt": {
"already_subscribed": "You are already subscribed to this topic.", "already_subscribed": "Вы уже подписаны на этот топик",
"clean_session": "Clean Session", "clean_session": "Очистить сессию",
"clear_input": "Clear input", "clear_input": "Очистить ввод",
"clear_input_on_send": "Clear input on send", "clear_input_on_send": "Очистить ввод перед отправкой",
"client_id": "Client ID", "client_id": "Client ID",
"color": "Pick a color", "color": "Выбрать цвет",
"communication": "Коммуникация", "communication": "Коммуникация",
"connection_config": "Connection Config", "connection_config": "Конфигурация соединения",
"connection_not_authorized": "This MQTT connection does not use any authentication.", "connection_not_authorized": "Это соединение MQTT не использует какую-либо авторизацию.",
"invalid_topic": "Please provide a topic for the subscription", "invalid_topic": "Пожалуйста выберите topic для подписки",
"keep_alive": "Keep Alive", "keep_alive": "Поддерживать соединение",
"log": "Лог", "log": "Лог",
"lw_message": "Last-Will Message", "lw_message": "Last-Will Message",
"lw_qos": "Last-Will QoS", "lw_qos": "Last-Will QoS",
"lw_retain": "Last-Will Retain", "lw_retain": "Last-Will Retain",
"lw_topic": "Last-Will Topic", "lw_topic": "Last-Will Topic",
"message": "Сообщение", "message": "Сообщение",
"new": "New Subscription", "new": "Новая подписка",
"not_connected": "Please start a MQTT connection first.", "not_connected": "Пожалуйста, сначала запустите MQTT соединение.",
"publish": "Публиковать", "publish": "Публиковать",
"qos": "QoS", "qos": "QoS",
"ssl": "SSL", "ssl": "SSL",
@@ -355,7 +410,7 @@
"navigation": { "navigation": {
"doc": "Документы", "doc": "Документы",
"graphql": "GraphQL", "graphql": "GraphQL",
"profile": "Profile", "profile": "Профиль",
"realtime": "В реальном времени", "realtime": "В реальном времени",
"rest": "REST", "rest": "REST",
"settings": "Настройки" "settings": "Настройки"
@@ -363,12 +418,12 @@
"preRequest": { "preRequest": {
"javascript_code": "Код JavaScript", "javascript_code": "Код JavaScript",
"learn": "Читать документацию", "learn": "Читать документацию",
"script": "Сценарий предварительного запроса", "script": "Предворительный скрипт запроса",
"snippets": "Фрагменты" "snippets": "Готовый код"
}, },
"profile": { "profile": {
"app_settings": "Настройки приложения", "app_settings": "Настройки приложения",
"default_hopp_displayname": "Unnamed User", "default_hopp_displayname": "Безымянный",
"editor": "Редактор", "editor": "Редактор",
"editor_description": "Редакторы могут добавлять, редактировать, а так же удалять запросы.", "editor_description": "Редакторы могут добавлять, редактировать, а так же удалять запросы.",
"email_verification_mail": "На вашу электронную почту отправлено письмо для подтверждения. Перейдите по ссылке из письма, чтобы подтвердить свой электронный адрес.", "email_verification_mail": "На вашу электронную почту отправлено письмо для подтверждения. Перейдите по ссылке из письма, чтобы подтвердить свой электронный адрес.",
@@ -391,13 +446,13 @@
"choose_language": "Выберите язык", "choose_language": "Выберите язык",
"content_type": "Тип содержимого", "content_type": "Тип содержимого",
"content_type_titles": { "content_type_titles": {
"others": "Others", "others": "Другие",
"structured": "Structured", "structured": "Структурированный",
"text": "Text" "text": "Текст"
}, },
"copy_link": "Копировать ссылку", "copy_link": "Копировать ссылку",
"different_collection": "Cannot reorder requests from different collections", "different_collection": "Нельзя изменять порядок запросов из разных коллекций",
"duplicated": "Request duplicated", "duplicated": "Запрос скопирован",
"duration": "Продолжительность", "duration": "Продолжительность",
"enter_curl": "Введите cURL", "enter_curl": "Введите cURL",
"generate_code": "Сгенерировать код", "generate_code": "Сгенерировать код",
@@ -405,13 +460,13 @@
"header_list": "Список заголовков", "header_list": "Список заголовков",
"invalid_name": "Укажите имя для запроса", "invalid_name": "Укажите имя для запроса",
"method": "Методика", "method": "Методика",
"moved": "Request moved", "moved": "Запрос перемещён",
"name": "Имя запроса", "name": "Имя запроса",
"new": "New Request", "new": "Новый запрос",
"order_changed": "Request Order Updated", "order_changed": "Порядок запроса изменён",
"override": "Override", "override": "Переопределить",
"override_help": "Set <kbd>Content-Type</kbd> in Headers", "override_help": "Установить <kbd>Content-Type</kbd> в Заголовках",
"overriden": "Overridden", "overriden": "Переопределено",
"parameter_list": "Параметры запроса", "parameter_list": "Параметры запроса",
"parameters": "Параметры", "parameters": "Параметры",
"path": "Путь", "path": "Путь",
@@ -424,17 +479,17 @@
"save_as": "Сохранить как", "save_as": "Сохранить как",
"saved": "Запрос сохранен", "saved": "Запрос сохранен",
"share": "Делиться", "share": "Делиться",
"share_description": "Share Hoppscotch with your friends", "share_description": "Поделиться Hoppscotch с друзьями",
"title": "Запрос", "title": "Запрос",
"type": "Тип запроса", "type": "Тип запроса",
"url": "URL", "url": "URL",
"variables": "Переменные", "variables": "Переменные",
"view_my_links": "View my links" "view_my_links": "Посмотреть мои ссылки"
}, },
"response": { "response": {
"audio": "Audio", "audio": "Аудио",
"body": "Тело ответа", "body": "Тело ответа",
"filter_response_body": "Filter JSON response body (uses JSONPath syntax)", "filter_response_body": "Отфильтровать ответ в формате JSON (используется синтаксис JSONPath)",
"headers": "Заголовки", "headers": "Заголовки",
"html": "HTML", "html": "HTML",
"image": "Изображение", "image": "Изображение",
@@ -446,14 +501,14 @@
"status": "Статус", "status": "Статус",
"time": "Время", "time": "Время",
"title": "Ответ", "title": "Ответ",
"video": "Video", "video": "Видео",
"waiting_for_connection": "Ожидание соединения", "waiting_for_connection": "Ожидание соединения",
"xml": "XML" "xml": "XML"
}, },
"settings": { "settings": {
"accent_color": "Основной цвет", "accent_color": "Основной цвет",
"account": "Счет", "account": "Счет",
"account_deleted": "Your account has been deleted", "account_deleted": "Ваш аккаунт был удалён",
"account_description": "Настройте параметры своей учетной записи.", "account_description": "Настройте параметры своей учетной записи.",
"account_email_description": "Ваш основной адрес электронной почты.", "account_email_description": "Ваш основной адрес электронной почты.",
"account_name_description": "Это ваше отображаемое имя.", "account_name_description": "Это ваше отображаемое имя.",
@@ -462,8 +517,8 @@
"change_font_size": "Изменить размер шрифта", "change_font_size": "Изменить размер шрифта",
"choose_language": "Выберите язык", "choose_language": "Выберите язык",
"dark_mode": "Темный", "dark_mode": "Темный",
"delete_account": "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_description": "Удаление аккаунта нельзя отменить",
"expand_navigation": "Раскрыть панель навигации", "expand_navigation": "Раскрыть панель навигации",
"experiments": "Эксперименты", "experiments": "Эксперименты",
"experiments_notice": "Это набор экспериментов, над которыми мы работаем, которые могут оказаться полезными, интересными, и тем, и другим, или ни тем, ни другим. Они не окончательные и могут быть нестабильными, поэтому, если произойдет что-то слишком странное, не паникуйте. Просто выключи эту чертову штуку. Шутки в сторону,", "experiments_notice": "Это набор экспериментов, над которыми мы работаем, которые могут оказаться полезными, интересными, и тем, и другим, или ни тем, ни другим. Они не окончательные и могут быть нестабильными, поэтому, если произойдет что-то слишком странное, не паникуйте. Просто выключи эту чертову штуку. Шутки в сторону,",
@@ -490,8 +545,8 @@
"proxy_use_toggle": "Используйте промежуточное ПО прокси для отправки запросов", "proxy_use_toggle": "Используйте промежуточное ПО прокси для отправки запросов",
"read_the": "Прочтите", "read_the": "Прочтите",
"reset_default": "Восстановление значений по умолчанию", "reset_default": "Восстановление значений по умолчанию",
"short_codes": "Short codes", "short_codes": "Короткие ссылки",
"short_codes_description": "Short codes which were created by you.", "short_codes_description": "Короткие ссылки, созданные вами",
"sidebar_on_left": "Панель слева", "sidebar_on_left": "Панель слева",
"sync": "Синхронизировать", "sync": "Синхронизировать",
"sync_collections": "Коллекции", "sync_collections": "Коллекции",
@@ -505,16 +560,16 @@
"theme_description": "Настройте тему своего приложения.", "theme_description": "Настройте тему своего приложения.",
"use_experimental_url_bar": "Использовать экспериментальную строку URL с выделением среды", "use_experimental_url_bar": "Использовать экспериментальную строку URL с выделением среды",
"user": "Пользователь", "user": "Пользователь",
"verified_email": "Verified email", "verified_email": "Проверенный Email",
"verify_email": "Подтвердить почту" "verify_email": "Подтвердить Email"
}, },
"shortcodes": { "shortcodes": {
"actions": "Actions", "actions": "Действия",
"created_on": "Created on", "created_on": "Создано",
"deleted": "Shortcode deleted", "deleted": "Удалёна",
"method": "Method", "method": "Метод",
"not_found": "Shortcode not found", "not_found": "Короткая ссылка не найдена",
"short_code": "Short code", "short_code": "Короткая ссылка",
"url": "URL" "url": "URL"
}, },
"shortcut": { "shortcut": {
@@ -525,6 +580,10 @@
"show_all": "Горячие клавиши", "show_all": "Горячие клавиши",
"title": "Общий" "title": "Общий"
}, },
"others": {
"title": "Другие",
"prettify": "Прекрасные редакторы"
},
"miscellaneous": { "miscellaneous": {
"invite": "Пригласите людей в Hoppscotch", "invite": "Пригласите людей в Hoppscotch",
"title": "Разное" "title": "Разное"
@@ -545,6 +604,9 @@
"delete_method": "Выберите метод DELETE", "delete_method": "Выберите метод DELETE",
"get_method": "Выберите метод GET", "get_method": "Выберите метод GET",
"head_method": "Выберите метод HEAD", "head_method": "Выберите метод HEAD",
"rename": "Переименовать запрос",
"import_curl": "Импорт из cURL",
"show_code": "Сгенерировать готовый код",
"method": "Методика", "method": "Методика",
"next_method": "Выберите следующий метод", "next_method": "Выберите следующий метод",
"post_method": "Выберите метод POST", "post_method": "Выберите метод POST",
@@ -553,35 +615,120 @@
"reset_request": "Сбросить запрос", "reset_request": "Сбросить запрос",
"save_to_collections": "Сохранить в коллекции", "save_to_collections": "Сохранить в коллекции",
"send_request": "Послать запрос", "send_request": "Послать запрос",
"save_request": "Сохарнить запрос",
"title": "Запрос" "title": "Запрос"
}, },
"response": { "response": {
"copy": "Copy response to clipboard", "copy": "Копировать запрос в буфер обмена",
"download": "Download response as file", "download": "Скачать запрос как файл",
"title": "Response" "title": "Запрос"
}, },
"theme": { "theme": {
"black": "Switch theme to black mode", "black": "Черный режим",
"dark": "Switch theme to dark mode", "dark": "Тёмный режим",
"light": "Switch theme to light mode", "light": "Светлый режим",
"system": "Switch theme to system mode", "system": "Определяется системой",
"title": "Theme" "title": "Тема"
} }
}, },
"show": { "show": {
"code": "Показать код", "code": "Показать код",
"collection": "Expand Collection Panel", "collection": "Развернуть панель коллекций",
"more": "Показать больше", "more": "Показать больше",
"sidebar": "Показать боковую панель" "sidebar": "Показать боковую панель"
}, },
"socketio": { "socketio": {
"communication": "Коммуникация", "communication": "Коммуникация",
"connection_not_authorized": "This SocketIO connection does not use any authentication.", "connection_not_authorized": "Это SocketIO соединение не использует какую-либо авторизацию.",
"event_name": "Название события", "event_name": "Название события",
"events": "События", "events": "События",
"log": "Лог", "log": "Лог",
"url": "URL" "url": "URL"
}, },
"spotlight": {
"general": {
"help_menu": "Помощь и поддержка",
"chat": "Чат с поддержкой",
"open_docs": "Прочитать документацию",
"open_keybindings": "Горячие клавиши",
"open_github": "Открыть GitHub репозиторий",
"social": "Соц. сети",
"title": "Основное"
},
"miscellaneous": {
"invite": "Пригласите друзей в Hoppscotch",
"title": "Разное"
},
"request": {
"switch_to": "Перейти к",
"select_method": "Выбрать метод",
"save_as_new": "Сохранить как новый запрос",
"tab_parameters": "Параметры",
"tab_body": "Тело",
"tab_headers": "Заголовки",
"tab_authorization": "Авторизация",
"tab_pre_request_script": "Пред-скрипт",
"tab_tests": "Тесты",
"tab_query": "Запрос",
"tab_variables": "Переменные"
},
"graphql": {
"connect": "Соединиться",
"disconnect": "Разъединить"
},
"response": {
"copy": "Копировать ответ",
"download": "Скачать ответ",
"title": "Ответ"
},
"environments": {
"new": "Создать новое окружение",
"new_variable": "Создать новую переменную в окружении",
"edit": "Изменить текущее окружение",
"delete": "Удалить текущее окружение",
"duplicate": "Скопировать текущее окружение",
"edit_global": "Изменить глобальное окружение",
"duplicate_global": "Скопировать глобальное окружение",
"title": "Окружения"
},
"workspace": {
"new": "Создать новую команду",
"edit": "Изменить текущую команду",
"delete": "Удалить текущую команду",
"invite": "Пригласить людей в команду",
"switch_to_personal": "Переключиться на личное пространство",
"title": "Команды"
},
"tab": {
"duplicate": "Скопировать вкладку",
"close_current": "Закрыть вкладку",
"close_others": "Закрыть все кроме этой",
"new_tab": "Открыть в новой вкладке",
"title": "Вкладки"
},
"section": {
"user": "Пользователь",
"theme": "Тема",
"interface": "Интерфейс",
"interceptor": "Перехватчик"
},
"change_language": "Изменить язык",
"settings": {
"theme": {
"black": "Чёрная",
"dark": "Тёмная",
"light": "Светлая",
"system": "Определяется системой"
},
"font": {
"size_sm": "Маленький",
"size_md": "Средний",
"size_lg": "Большой"
},
"change_interceptor": "Изменить перехватчик",
"change_language": "Изменить язык"
}
},
"sse": { "sse": {
"event_type": "Тип события", "event_type": "Тип события",
"log": "Лог", "log": "Лог",
@@ -589,14 +736,14 @@
}, },
"state": { "state": {
"bulk_mode": "Множественное редактирование", "bulk_mode": "Множественное редактирование",
"bulk_mode_placeholder": "Entries are separated by newline\nKeys and values are separated by :\nPrepend # to any row you want to add but keep disabled", "bulk_mode_placeholder": "Каждый параметр должен начинаться с новой строки\nКлючи и значения разедляются двоеточием\nИспользуйте # для комментария",
"cleared": "Очищено", "cleared": "Очищено",
"connected": "Связаны", "connected": "Связаны",
"connected_to": "Подключено к {name}", "connected_to": "Подключено к {name}",
"connecting_to": "Подключение к {name} ...", "connecting_to": "Подключение к {name} ...",
"connection_error": "Failed to connect", "connection_error": "Ошибка подключения",
"connection_failed": "Connection failed", "connection_failed": "Не удалось установить соединение",
"connection_lost": "Connection lost", "connection_lost": "Соединение утеряно",
"copied_to_clipboard": "Скопировано в буфер обмена", "copied_to_clipboard": "Скопировано в буфер обмена",
"deleted": "Удалено", "deleted": "Удалено",
"deprecated": "УСТАРЕЛО", "deprecated": "УСТАРЕЛО",
@@ -611,17 +758,17 @@
"history_deleted": "История удалена", "history_deleted": "История удалена",
"linewrap": "Обернуть линии", "linewrap": "Обернуть линии",
"loading": "Загрузка...", "loading": "Загрузка...",
"message_received": "Message: {message} arrived on topic: {topic}", "message_received": "Сообщение: {message} получено по топику: {topic}",
"mqtt_subscription_failed": "Something went wrong while subscribing to topic: {topic}", "mqtt_subscription_failed": "Что-то пошло не так, при попытке подписаться на топик: {topic}",
"none": "Никто", "none": "Никто",
"nothing_found": "Ничего не найдено для", "nothing_found": "Ничего не найдено для",
"published_error": "Something went wrong while publishing msg: {topic} to topic: {message}", "published_error": "Что-то пошло не так при попытке опубликовать сообщение в топик {topic}: {message}",
"published_message": "Published message: {message} to topic: {topic}", "published_message": "Опубликовано сообщение: {message} в топик: {topic}",
"reconnection_error": "Failed to reconnect", "reconnection_error": "Не удалось переподключиться",
"subscribed_failed": "Failed to subscribe to topic: {topic}", "subscribed_failed": "Не удалось подписаться на топик: {topic}",
"subscribed_success": "Successfully subscribed to topic: {topic}", "subscribed_success": "Успешно подписался на топик: {topic}",
"unsubscribed_failed": "Failed to unsubscribe from topic: {topic}", "unsubscribed_failed": "Не удалось отписаться от топика: {topic}",
"unsubscribed_success": "Successfully unsubscribed from topic: {topic}", "unsubscribed_success": "Успешно отписался от топика: {topic}",
"waiting_send_request": "Ожидание отправки запроса" "waiting_send_request": "Ожидание отправки запроса"
}, },
"support": { "support": {
@@ -630,7 +777,7 @@
"community": "Задавайте вопросы и помогайте другим", "community": "Задавайте вопросы и помогайте другим",
"documentation": "Узнать больше о Hoppscotch", "documentation": "Узнать больше о Hoppscotch",
"forum": "Задавайте вопросы и получайте ответы", "forum": "Задавайте вопросы и получайте ответы",
"github": "Follow us on Github", "github": "Подпишитесь на нас на Github",
"shortcuts": "Просматривайте приложение быстрее", "shortcuts": "Просматривайте приложение быстрее",
"team": "Свяжитесь с командой", "team": "Свяжитесь с командой",
"title": "Служба поддержки", "title": "Служба поддержки",
@@ -641,15 +788,15 @@
"body": "Тело", "body": "Тело",
"collections": "Коллекции", "collections": "Коллекции",
"documentation": "Документация", "documentation": "Документация",
"environments": "Environments", "environments": "Окружения",
"headers": "Заголовки", "headers": "Заголовки",
"history": "История", "history": "История",
"mqtt": "MQTT", "mqtt": "MQTT",
"parameters": "Параметры", "parameters": "Параметры",
"pre_request_script": "Скрипт предварительного запроса", "pre_request_script": "Пред-скрипт",
"queries": "Запросы", "queries": "Запросы",
"query": "Запрос", "query": "Запрос",
"schema": "Schema", "schema": "Схема",
"socketio": "Socket.IO", "socketio": "Socket.IO",
"sse": "SSE", "sse": "SSE",
"tests": "Тесты", "tests": "Тесты",
@@ -666,7 +813,7 @@
"email_do_not_match": "Электронная почта, которой Вы воспользовались не соответсвует указанной в данных Вашей учетной записи.", "email_do_not_match": "Электронная почта, которой Вы воспользовались не соответсвует указанной в данных Вашей учетной записи.",
"exit": "Выйти из команды", "exit": "Выйти из команды",
"exit_disabled": "Только владелец не может выйти из команды", "exit_disabled": "Только владелец не может выйти из команды",
"invalid_coll_id": "Invalid collection ID", "invalid_coll_id": "Не верный идентификатор коллекции",
"invalid_email_format": "Формат электронной почты недействителен", "invalid_email_format": "Формат электронной почты недействителен",
"invalid_id": "Некорректный ID команды. Свяжитесь с руководителем команды.", "invalid_id": "Некорректный ID команды. Свяжитесь с руководителем команды.",
"invalid_invite_link": "Ссылка недействительна", "invalid_invite_link": "Ссылка недействительна",
@@ -690,7 +837,7 @@
"member_removed": "Пользователь удален", "member_removed": "Пользователь удален",
"member_role_updated": "Роли пользователей обновлены", "member_role_updated": "Роли пользователей обновлены",
"members": "Участники", "members": "Участники",
"more_members": "+{count} more", "more_members": "+{count}",
"name_length_insufficient": "Название команды должно быть не менее 6 символов.", "name_length_insufficient": "Название команды должно быть не менее 6 символов.",
"name_updated": "Название команды обновлено", "name_updated": "Название команды обновлено",
"new": "Новая команда", "new": "Новая команда",
@@ -698,13 +845,13 @@
"new_name": "Моя новая команда", "new_name": "Моя новая команда",
"no_access": "У вас нет прав на редактирование этих коллекций", "no_access": "У вас нет прав на редактирование этих коллекций",
"no_invite_found": "Такое приглашение мы не смогли найти. Свяжитесь с руководителем команды.", "no_invite_found": "Такое приглашение мы не смогли найти. Свяжитесь с руководителем команды.",
"no_request_found": "Request not found.", "no_request_found": "Запрос не найден",
"not_found": "Team not found. Contact your team owner.", "not_found": "Команда не найдена, свяжитесь с владельцем команды",
"not_valid_viewer": "У Вас нет прав просматривать это. Свяжитесь с руководителем команды.", "not_valid_viewer": "У Вас нет прав просматривать это. Свяжитесь с руководителем команды.",
"parent_coll_move": "Cannot move collection to a child collection", "parent_coll_move": "Не удалось переместить коллекцию в дочернюю",
"pending_invites": "Ожидающие приглашения", "pending_invites": "Ожидающие приглашения",
"permissions": "Разрешения", "permissions": "Разрешения",
"same_target_destination": "Same target and destination", "same_target_destination": "Таже цель и конечная точка",
"saved": "Команда сохранена", "saved": "Команда сохранена",
"select_a_team": "Выбрать команду", "select_a_team": "Выбрать команду",
"title": "Команды", "title": "Команды",
@@ -712,9 +859,9 @@
"we_sent_invite_link_description": "Попросите тех, кого Вы пригласили, проверить их почтовые ящики. Им нужно перейди по ссылке, чтобы подтвердить вступление в эту команду." "we_sent_invite_link_description": "Попросите тех, кого Вы пригласили, проверить их почтовые ящики. Им нужно перейди по ссылке, чтобы подтвердить вступление в эту команду."
}, },
"team_environment": { "team_environment": {
"deleted": "Environment Deleted", "deleted": "Окружение удалено",
"duplicate": "Environment Duplicated", "duplicate": "Окружение скопировано",
"not_found": "Environment not found." "not_found": "Окружение не найдено"
}, },
"test": { "test": {
"failed": "Тест не пройден", "failed": "Тест не пройден",
@@ -734,9 +881,9 @@
"url": "URL" "url": "URL"
}, },
"workspace": { "workspace": {
"change": "Change workspace", "change": "Изменить пространство",
"personal": "My Workspace", "personal": "Моё пространство",
"team": "Team Workspace", "team": "Пространство команды",
"title": "Workspaces" "title": "Рабочие пространства"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -10,18 +10,6 @@
:class="{ '-rotate-180': !EXPAND_NAVIGATION }" :class="{ '-rotate-180': !EXPAND_NAVIGATION }"
@click="EXPAND_NAVIGATION = !EXPAND_NAVIGATION" @click="EXPAND_NAVIGATION = !EXPAND_NAVIGATION"
/> />
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${ZEN_MODE ? t('action.turn_off') : t('action.turn_on')} ${t(
'layout.zen_mode'
)}`"
:icon="ZEN_MODE ? IconMinimize : IconMaximize"
:class="{
'!text-accent !focus-visible:text-accentDark !hover:text-accentDark':
ZEN_MODE,
}"
@click="ZEN_MODE = !ZEN_MODE"
/>
<tippy interactive trigger="click" theme="popover"> <tippy interactive trigger="click" theme="popover">
<HoppButtonSecondary <HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
@@ -211,11 +199,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from "vue" import { ref } from "vue"
import { version } from "~/../package.json" import { version } from "~/../package.json"
import IconSidebar from "~icons/lucide/sidebar" import IconSidebar from "~icons/lucide/sidebar"
import IconMinimize from "~icons/lucide/minimize"
import IconMaximize from "~icons/lucide/maximize"
import IconZap from "~icons/lucide/zap" import IconZap from "~icons/lucide/zap"
import IconShare2 from "~icons/lucide/share-2" import IconShare2 from "~icons/lucide/share-2"
import IconColumns from "~icons/lucide/columns" import IconColumns from "~icons/lucide/columns"
@@ -241,7 +227,6 @@ const showDeveloperOptions = ref(false)
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION") const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
const SIDEBAR = useSetting("SIDEBAR") const SIDEBAR = useSetting("SIDEBAR")
const ZEN_MODE = useSetting("ZEN_MODE")
const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT") const COLUMN_LAYOUT = useSetting("COLUMN_LAYOUT")
const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT") const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
@@ -252,13 +237,6 @@ const currentUser = useReadonlyStream(
platform.auth.getCurrentUser() platform.auth.getCurrentUser()
) )
watch(
() => ZEN_MODE.value,
() => {
EXPAND_NAVIGATION.value = !ZEN_MODE.value
}
)
const nativeShare = () => { const nativeShare = () => {
if (navigator.share) { if (navigator.share) {
navigator navigator

View File

@@ -67,7 +67,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { watch } from "vue"
import IconSidebar from "~icons/lucide/sidebar" import IconSidebar from "~icons/lucide/sidebar"
import IconSidebarOpen from "~icons/lucide/sidebar-open" import IconSidebarOpen from "~icons/lucide/sidebar-open"
import IconChevronRight from "~icons/lucide/chevron-right" import IconChevronRight from "~icons/lucide/chevron-right"
@@ -77,17 +76,9 @@ import { platform } from "~/platform"
const t = useI18n() const t = useI18n()
const ZEN_MODE = useSetting("ZEN_MODE")
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION") const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
const SIDEBAR = useSetting("SIDEBAR") const SIDEBAR = useSetting("SIDEBAR")
watch(
() => ZEN_MODE.value,
() => {
EXPAND_NAVIGATION.value = !ZEN_MODE.value
}
)
defineProps<{ defineProps<{
show: boolean show: boolean
}>() }>()

View File

@@ -119,5 +119,8 @@ watch(
&.active { &.active {
@apply after:bg-accentLight; @apply after:bg-accentLight;
} }
scroll-padding: 4rem !important;
scroll-margin: 4rem !important;
} }
</style> </style>

View File

@@ -40,7 +40,7 @@
:key="`result-${result.id}`" :key="`result-${result.id}`"
:entry="result" :entry="result"
:active="isEqual(selectedEntry, [sectionIndex, entryIndex])" :active="isEqual(selectedEntry, [sectionIndex, entryIndex])"
@mouseover="selectedEntry = [sectionIndex, entryIndex]" @mouseover="onMouseOver($event, sectionIndex, entryIndex)"
@action="runAction(sectionID, result)" @action="runAction(sectionID, result)"
/> />
</div> </div>
@@ -178,6 +178,24 @@ function runAction(searcherID: string, result: SpotlightSearcherResult) {
emit("hide-modal") emit("hide-modal")
} }
let lastMousePosition: { x: number; y: number }
const onMouseOver = (
e: MouseEvent,
sectionIndex: number,
entryIndex: number
) => {
const mousePosition = {
x: e.clientX,
y: e.clientY,
}
// if the position is same, do nothing
if (isEqual(lastMousePosition, mousePosition)) return
selectedEntry.value = [sectionIndex, entryIndex]
lastMousePosition = mousePosition
}
function newUseArrowKeysForNavigation() { function newUseArrowKeysForNavigation() {
const selectedEntry = ref<[number, number]>([0, 0]) // [sectionIndex, entryIndex] const selectedEntry = ref<[number, number]>([0, 0]) // [sectionIndex, entryIndex]

View File

@@ -9,7 +9,7 @@
<div class="flex"> <div class="flex">
<HoppButtonSecondary <HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/documentation/getting-started/rest/using-parameters" to="https://docs.hoppscotch.io/documentation/features/rest-api-testing"
blank blank
:title="t('app.wiki')" :title="t('app.wiki')"
:icon="IconHelpCircle" :icon="IconHelpCircle"

View File

@@ -17,7 +17,7 @@
<span <span
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="relativeTime" :title="relativeTime"
class="mx-auto truncate ts-font text-secondaryLight hover:text-secondary hover:text-center" class="mx-auto truncate text-tiny text-secondaryLight hover:text-secondary hover:text-center"
> >
{{ shortDateTime(entry.ts) }} {{ shortDateTime(entry.ts) }}
</span> </span>
@@ -406,8 +406,4 @@ const icon = computed(() => markRaw(ICONS[props.entry.source].icon))
@apply transition; @apply transition;
@apply hover: text-secondary; @apply hover: text-secondary;
} }
.ts-font {
font-size: 0.6rem;
}
</style> </style>

View File

@@ -311,35 +311,36 @@ const envVars = computed(() =>
const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view) const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view)
const initView = (el: any) => { function handleTextSelection() {
function handleTextSelection() { const selection = view.value?.state.selection.main
const selection = view.value?.state.selection.main if (selection) {
if (selection) { const from = selection.from
const from = selection.from const to = selection.to
const to = selection.to if (from === to) return
const text = view.value?.state.doc.sliceString(from, to) const text = view.value?.state.doc.sliceString(from, to)
const { top, left } = view.value?.coordsAtPos(from) const { top, left } = view.value?.coordsAtPos(from)
if (text) { if (text) {
invokeAction("contextmenu.open", { invokeAction("contextmenu.open", {
position: { position: {
top, top,
left, left,
}, },
text, text,
}) })
showSuggestionPopover.value = false showSuggestionPopover.value = false
} else { } else {
invokeAction("contextmenu.open", { invokeAction("contextmenu.open", {
position: { position: {
top, top,
left, left,
}, },
text: null, text: null,
}) })
}
} }
} }
}
const initView = (el: any) => {
// Debounce to prevent double click from selecting the word // Debounce to prevent double click from selecting the word
const debounceFn = useDebounceFn(() => { const debounceFn = useDebounceFn(() => {
handleTextSelection() handleTextSelection()
@@ -381,6 +382,11 @@ const initView = (el: any) => {
drop(ev) { drop(ev) {
ev.preventDefault() ev.preventDefault()
}, },
scroll(event) {
if (event.target) {
handleTextSelection()
}
},
}), }),
ViewPlugin.fromClass( ViewPlugin.fromClass(
class { class {

View File

@@ -1,71 +0,0 @@
<template>
<span class="inline-flex">
<tippy
interactive
trigger="click"
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('settings.change_font_size')"
class="pr-8"
:icon="IconType"
outline
:label="`${getFontSizeName(
fontSizes.find((size) => size === active)
)}`"
/>
</span>
<template #content="{ hide }">
<div
ref="tippyActions"
class="flex flex-col focus:outline-none"
tabindex="0"
@keyup.escape="hide()"
>
<HoppSmartItem
v-for="(size, index) in fontSizes"
:key="`size-${index}`"
:label="`${getFontSizeName(size)}`"
:icon="size === active ? IconCircleDot : IconCircle"
:active="size === active"
@click="
() => {
setActiveFont(size)
hide()
}
"
/>
</div>
</template>
</tippy>
</span>
</template>
<script setup lang="ts">
import IconCircleDot from "~icons/lucide/circle-dot"
import IconCircle from "~icons/lucide/circle"
import IconType from "~icons/lucide/type"
import { HoppFontSizes, HoppFontSize, applySetting } from "~/newstore/settings"
import { useSetting } from "@composables/settings"
import { useI18n } from "@composables/i18n"
import { ref } from "vue"
const t = useI18n()
const fontSizes = HoppFontSizes
const active = useSetting("FONT_SIZE")
const getFontSizeName = (size: HoppFontSize) => {
return t(`settings.font_size_${size}`)
}
const setActiveFont = (size: HoppFontSize) => {
applySetting("FONT_SIZE", size)
}
// Template refs
const tippyActions = ref<any | null>(null)
</script>

View File

@@ -216,6 +216,33 @@ export function useCodemirror(
? new HoppEnvironmentPlugin(subscribeToStream, view) ? new HoppEnvironmentPlugin(subscribeToStream, view)
: null : null
function handleTextSelection() {
const selection = view.value?.state.selection.main
if (selection) {
const from = selection.from
const to = selection.to
const text = view.value?.state.doc.sliceString(from, to)
const { top, left } = view.value?.coordsAtPos(from)
if (text) {
invokeAction("contextmenu.open", {
position: {
top,
left,
},
text,
})
} else {
invokeAction("contextmenu.open", {
position: {
top,
left,
},
text: null,
})
}
}
}
const initView = (el: any) => { const initView = (el: any) => {
if (el) platform.ui?.onCodemirrorInstanceMount?.(el) if (el) platform.ui?.onCodemirrorInstanceMount?.(el)
@@ -226,33 +253,6 @@ export function useCodemirror(
ViewPlugin.fromClass( ViewPlugin.fromClass(
class { class {
update(update: ViewUpdate) { update(update: ViewUpdate) {
function handleTextSelection() {
const selection = view.value?.state.selection.main
if (selection) {
const from = selection.from
const to = selection.to
const text = view.value?.state.doc.sliceString(from, to)
const { top, left } = view.value?.coordsAtPos(from)
if (text) {
invokeAction("contextmenu.open", {
position: {
top,
left,
},
text,
})
} else {
invokeAction("contextmenu.open", {
position: {
top,
left,
},
text: null,
})
}
}
}
// Debounce to prevent double click from selecting the word // Debounce to prevent double click from selecting the word
const debounceFn = useDebounceFn(() => { const debounceFn = useDebounceFn(() => {
handleTextSelection() handleTextSelection()
@@ -296,6 +296,13 @@ export function useCodemirror(
} }
} }
), ),
EditorView.domEventHandlers({
scroll(event) {
if (event.target) {
handleTextSelection()
}
},
}),
EditorView.updateListener.of((update) => { EditorView.updateListener.of((update) => {
if (options.extendedEditorConfig.readOnly) { if (options.extendedEditorConfig.readOnly) {
update.view.contentDOM.inputMode = "none" update.view.contentDOM.inputMode = "none"

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="flex w-screen h-screen"> <div class="flex w-screen h-screen">
<Splitpanes class="no-splitter" :dbl-click-splitter="false" horizontal> <Splitpanes class="no-splitter" :dbl-click-splitter="false" horizontal>
<Pane v-if="!zenMode" style="height: auto"> <Pane style="height: auto">
<AppHeader /> <AppHeader />
</Pane> </Pane>
<Pane :class="spacerClass" class="flex flex-1 !overflow-auto md:mb-0"> <Pane :class="spacerClass" class="flex flex-1 !overflow-auto md:mb-0">
@@ -79,9 +79,7 @@ const router = useRouter()
const showSearch = ref(false) const showSearch = ref(false)
const showSupport = ref(false) const showSupport = ref(false)
const fontSize = useSetting("FONT_SIZE")
const expandNavigation = useSetting("EXPAND_NAVIGATION") const expandNavigation = useSetting("EXPAND_NAVIGATION")
const zenMode = useSetting("ZEN_MODE")
const rightSidebar = useSetting("SIDEBAR") const rightSidebar = useSetting("SIDEBAR")
const columnLayout = useSetting("COLUMN_LAYOUT") const columnLayout = useSetting("COLUMN_LAYOUT")
@@ -133,24 +131,9 @@ watch(mdAndLarger, () => {
columnLayout.value = true columnLayout.value = true
} }
}) })
const spacerClass = computed(() =>
const spacerClass = computed(() => { expandNavigation.value ? "spacer-small" : "spacer-expand"
if (fontSize.value === "small" && expandNavigation.value) )
return "spacer-small"
if (fontSize.value === "medium" && expandNavigation.value)
return "spacer-medium"
if (fontSize.value === "large" && expandNavigation.value)
return "spacer-large"
if (
(fontSize.value === "small" ||
fontSize.value === "medium" ||
fontSize.value === "large") &&
!expandNavigation.value
)
return "spacer-expand"
return ""
})
defineActionHandler("modals.search.toggle", () => { defineActionHandler("modals.search.toggle", () => {
showSearch.value = !showSearch.value showSearch.value = !showSearch.value

View File

@@ -68,23 +68,9 @@ const applyAccentColor = (_app: App) => {
) )
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const applyFontSize = (_app: App) => {
const [pref] = useSettingStatic("FONT_SIZE")
watch(
pref,
(newPref) => {
document.documentElement.setAttribute("data-font-size", newPref)
},
{ immediate: true }
)
}
export default <HoppModule>{ export default <HoppModule>{
onVueAppInit(app) { onVueAppInit(app) {
applyColorMode(app) applyColorMode(app)
applyAccentColor(app) applyAccentColor(app)
applyFontSize(app)
}, },
} }

View File

@@ -23,10 +23,6 @@ export const HoppAccentColors = [
export type HoppAccentColor = (typeof HoppAccentColors)[number] export type HoppAccentColor = (typeof HoppAccentColors)[number]
export const HoppFontSizes = ["small", "medium", "large"] as const
export type HoppFontSize = (typeof HoppFontSizes)[number]
export type SettingsDef = { export type SettingsDef = {
syncCollections: boolean syncCollections: boolean
syncHistory: boolean syncHistory: boolean
@@ -49,8 +45,6 @@ export type SettingsDef = {
EXPAND_NAVIGATION: boolean EXPAND_NAVIGATION: boolean
SIDEBAR: boolean SIDEBAR: boolean
SIDEBAR_ON_LEFT: boolean SIDEBAR_ON_LEFT: boolean
ZEN_MODE: boolean
FONT_SIZE: HoppFontSize
COLUMN_LAYOUT: boolean COLUMN_LAYOUT: boolean
} }
@@ -76,8 +70,6 @@ export const getDefaultSettings = (): SettingsDef => ({
EXPAND_NAVIGATION: true, EXPAND_NAVIGATION: true,
SIDEBAR: true, SIDEBAR: true,
SIDEBAR_ON_LEFT: true, SIDEBAR_ON_LEFT: true,
ZEN_MODE: false,
FONT_SIZE: "small",
COLUMN_LAYOUT: true, COLUMN_LAYOUT: true,
}) })

View File

@@ -141,6 +141,7 @@ import { InspectionService } from "~/services/inspection"
import { HeaderInspectorService } from "~/services/inspection/inspectors/header.inspector" import { HeaderInspectorService } from "~/services/inspection/inspectors/header.inspector"
import { EnvironmentInspectorService } from "~/services/inspection/inspectors/environment.inspector" import { EnvironmentInspectorService } from "~/services/inspection/inspectors/environment.inspector"
import { ResponseInspectorService } from "~/services/inspection/inspectors/response.inspector" import { ResponseInspectorService } from "~/services/inspection/inspectors/response.inspector"
import { cloneDeep } from "lodash-es"
const savingRequest = ref(false) const savingRequest = ref(false)
const confirmingCloseForTabID = ref<string | null>(null) const confirmingCloseForTabID = ref<string | null>(null)
@@ -228,11 +229,14 @@ const removeTab = (tabID: string) => {
} }
const closeOtherTabsAction = (tabID: string) => { const closeOtherTabsAction = (tabID: string) => {
const isTabDirty = getTabRef(tabID).value?.document.isDirty
const dirtyTabCount = getDirtyTabsCount() const dirtyTabCount = getDirtyTabsCount()
// If current tab is dirty, so we need to subtract 1 from the dirty tab count
const balanceDirtyTabCount = isTabDirty ? dirtyTabCount - 1 : dirtyTabCount
// If there are dirty tabs, show the confirm modal // If there are dirty tabs, show the confirm modal
if (dirtyTabCount > 0) { if (balanceDirtyTabCount > 0) {
confirmingCloseAllTabs.value = true confirmingCloseAllTabs.value = true
unsavedTabsCount.value = dirtyTabCount unsavedTabsCount.value = balanceDirtyTabCount
exceptedTabID.value = tabID exceptedTabID.value = tabID
} else { } else {
closeOtherTabs(tabID) closeOtherTabs(tabID)
@@ -243,7 +247,7 @@ const duplicateTab = (tabID: string) => {
const tab = getTabRef(tabID) const tab = getTabRef(tabID)
if (tab.value) { if (tab.value) {
const newTab = createNewTab({ const newTab = createNewTab({
request: tab.value.document.request, request: cloneDeep(tab.value.document.request),
isDirty: true, isDirty: true,
}) })
currentTabID.value = newTab.id currentTabID.value = newTab.id

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<div class="container space-y-8 divide-y divide-dividerLight"> <div class="container divide-y divide-dividerLight">
<div class="md:grid md:gap-4 md:grid-cols-3"> <div class="md:grid md:gap-4 md:grid-cols-3">
<div class="p-8 md:col-span-1"> <div class="p-8 md:col-span-1">
<h3 class="heading"> <h3 class="heading">
@@ -36,14 +36,6 @@
<SmartAccentModePicker /> <SmartAccentModePicker />
</div> </div>
</section> </section>
<section>
<h4 class="font-semibold text-secondaryDark">
{{ t("settings.font_size") }}
</h4>
<div class="mt-4">
<SmartFontSizePicker />
</div>
</section>
<section> <section>
<h4 class="font-semibold text-secondaryDark"> <h4 class="font-semibold text-secondaryDark">
{{ t("settings.language") }} {{ t("settings.language") }}
@@ -90,14 +82,6 @@
{{ t("settings.sidebar_on_left") }} {{ t("settings.sidebar_on_left") }}
</HoppSmartToggle> </HoppSmartToggle>
</div> </div>
<div class="flex items-center">
<HoppSmartToggle
:on="ZEN_MODE"
@change="toggleSetting('ZEN_MODE')"
>
{{ t("layout.zen_mode") }}
</HoppSmartToggle>
</div>
</div> </div>
</section> </section>
</div> </div>
@@ -178,7 +162,6 @@ const PROXY_URL = useSetting("PROXY_URL")
const TELEMETRY_ENABLED = useSetting("TELEMETRY_ENABLED") const TELEMETRY_ENABLED = useSetting("TELEMETRY_ENABLED")
const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION") const EXPAND_NAVIGATION = useSetting("EXPAND_NAVIGATION")
const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT") const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
const ZEN_MODE = useSetting("ZEN_MODE")
const confirmRemove = ref(false) const confirmRemove = ref(false)
@@ -186,10 +169,6 @@ const proxySettings = computed(() => ({
url: PROXY_URL.value, url: PROXY_URL.value,
})) }))
watch(ZEN_MODE, (mode) => {
applySetting("EXPAND_NAVIGATION", !mode)
})
watch( watch(
proxySettings, proxySettings,
({ url }) => { ({ url }) => {

View File

@@ -72,7 +72,7 @@ export const twitter: HoppSupportOptionsMenuItem = {
icon: IconTwitter, icon: IconTwitter,
action: { action: {
type: "link", type: "link",
href: "https://hoppscotch.io/discord", href: "https://hoppscotch.io/twitter",
}, },
} }
@@ -84,17 +84,7 @@ export const invite: HoppSupportOptionsMenuItem = {
action: { action: {
type: "custom", type: "custom",
do() { do() {
if (navigator.share) { invokeAction("modals.share.toggle")
navigator
.share({
title: "Hoppscotch",
text: "Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.",
url: "https://hoppscotch.io",
})
.catch(console.error)
} else {
// fallback
}
}, },
}, },
} }

View File

@@ -14,7 +14,6 @@ import IconGlobe from "~icons/lucide/globe"
import IconMonitor from "~icons/lucide/monitor" import IconMonitor from "~icons/lucide/monitor"
import IconMoon from "~icons/lucide/moon" import IconMoon from "~icons/lucide/moon"
import IconSun from "~icons/lucide/sun" import IconSun from "~icons/lucide/sun"
import IconCircle from "~icons/lucide/circle"
import IconCheckCircle from "~icons/lucide/check-circle" import IconCheckCircle from "~icons/lucide/check-circle"
type Doc = { type Doc = {
@@ -34,7 +33,6 @@ export class SettingsSpotlightSearcherService extends StaticSpotlightSearcherSer
private t = getI18n() private t = getI18n()
private activeFontSize = useSetting("FONT_SIZE")
private activeTheme = useSetting("BG_COLOR") private activeTheme = useSetting("BG_COLOR")
public readonly searcherID = "settings" public readonly searcherID = "settings"
@@ -91,60 +89,7 @@ export class SettingsSpotlightSearcherService extends StaticSpotlightSearcherSer
: markRaw(IconMoon) : markRaw(IconMoon)
), ),
}, },
font_size_sm: {
text: [
this.t("settings.font_size"),
this.t("spotlight.settings.font.size_sm"),
],
onClick: () => {
console.log("clicked")
},
alternates: [
"font size",
"change font size",
"change font",
"increase font",
],
icon: computed(() =>
this.activeFontSize.value === "small"
? markRaw(IconCheckCircle)
: markRaw(IconCircle)
),
},
font_size_md: {
text: [
this.t("settings.font_size"),
this.t("spotlight.settings.font.size_md"),
],
alternates: [
"font size",
"change font size",
"change font",
"increase font",
],
icon: computed(() =>
this.activeFontSize.value === "medium"
? markRaw(IconCheckCircle)
: markRaw(IconCircle)
),
},
font_size_lg: {
text: [
this.t("settings.font_size"),
this.t("spotlight.settings.font.size_lg"),
],
alternates: [
"font size",
"change font size",
"change font",
"increase font",
],
icon: computed(() =>
this.activeFontSize.value === "large"
? markRaw(IconCheckCircle)
: markRaw(IconCircle)
),
},
change_lang: { change_lang: {
text: [ text: [
this.t("spotlight.section.interface"), this.t("spotlight.section.interface"),
@@ -202,17 +147,6 @@ export class SettingsSpotlightSearcherService extends StaticSpotlightSearcherSer
case "theme_black": case "theme_black":
invokeAction("settings.theme.black") invokeAction("settings.theme.black")
break break
// font size actions
case "font_size_sm":
this.activeFontSize.value = "small"
break
case "font_size_md":
this.activeFontSize.value = "medium"
break
case "font_size_lg":
this.activeFontSize.value = "large"
break
} }
} }
} }

View File

@@ -1,8 +1,21 @@
@mixin base-theme { @mixin base-theme {
--font-sans: "Inter Variable", sans-serif; --font-sans: 'Inter Variable', sans-serif;
--font-icon: "Material Symbols Rounded Variable"; --font-icon: 'Material Symbols Rounded Variable';
--font-mono: "Roboto Mono Variable", monospace; --font-mono: 'Roboto Mono Variable', monospace;
--font-size-tiny: calc(var(--font-size-body) - 0.062rem); --font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
} }
@mixin dark-theme { @mixin dark-theme {
@@ -200,8 +213,8 @@
:root { :root {
@include base-theme; @include base-theme;
@include dark-theme; @include dark-theme;
@include green-theme;
@include dark-editor-theme; @include dark-editor-theme;
@include green-theme;
} }
:root.light { :root.light {
@@ -257,63 +270,3 @@
:root[data-accent='yellow'] { :root[data-accent='yellow'] {
@include yellow-theme; @include yellow-theme;
} }
@mixin font-small {
--font-size-body: 0.75rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
}
@mixin font-medium {
--font-size-body: 0.875rem;
--line-height-body: 1.25rem;
--upper-primary-sticky-fold: 4.375rem;
--upper-secondary-sticky-fold: 6.688rem;
--upper-tertiary-sticky-fold: 9rem;
--upper-mobile-primary-sticky-fold: 7.125rem;
--upper-mobile-secondary-sticky-fold: 9.438rem;
--upper-mobile-sticky-fold: 11.75rem;
--upper-mobile-tertiary-sticky-fold: 9rem;
--lower-primary-sticky-fold: 3.25rem;
--lower-secondary-sticky-fold: 5.563rem;
--lower-tertiary-sticky-fold: 7.875rem;
--sidebar-primary-sticky-fold: 2.25rem;
}
@mixin font-large {
--font-size-body: 1rem;
--line-height-body: 1.5rem;
--upper-primary-sticky-fold: 4.625rem;
--upper-secondary-sticky-fold: 7.188rem;
--upper-tertiary-sticky-fold: 9.75rem;
--upper-mobile-primary-sticky-fold: 7.625rem;
--upper-mobile-secondary-sticky-fold: 10.188rem;
--upper-mobile-sticky-fold: 12.75rem;
--upper-mobile-tertiary-sticky-fold: 9.75rem;
--lower-primary-sticky-fold: 3.5rem;
--lower-secondary-sticky-fold: 6.063rem;
--lower-tertiary-sticky-fold: 8.625rem;
--sidebar-primary-sticky-fold: 2.5rem;
}
:root[data-font-size='small'] {
@include font-small;
}
:root[data-font-size='medium'] {
@include font-medium;
}
:root[data-font-size='large'] {
@include font-large;
}

View File

@@ -1,20 +1,17 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" data-font-size="medium"> <html lang="en">
<head>
<head> <script>
<script> globalThis.import_meta_env = JSON.parse('"import_meta_env_placeholder"');
globalThis.import_meta_env = JSON.parse('"import_meta_env_placeholder"') </script>
</script> <meta charset="UTF-8" />
<meta charset="UTF-8"> <link rel="icon" href="/favicon.ico" />
<link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hoppscotch Admin</title>
<title>Hoppscotch Admin</title> <meta property="og:image" content="/cover.jpg" />
<meta property="og:image" content="/cover.jpg" /> </head>
</head> <body>
<div id="app"></div>
<body> <script type="module" src="/src/main.ts"></script>
<div id="app"></div> </body>
<script type="module" src="/src/main.ts"></script>
</body>
</html> </html>

View File

@@ -2,7 +2,20 @@
--font-sans: "Inter Variable", sans-serif; --font-sans: "Inter Variable", sans-serif;
--font-icon: "Material Symbols Rounded Variable"; --font-icon: "Material Symbols Rounded Variable";
--font-mono: "Roboto Mono Variable", monospace; --font-mono: "Roboto Mono Variable", monospace;
--font-size-tiny: calc(var(--font-size-body) - 0.062rem); --font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
} }
@mixin dark-theme { @mixin dark-theme {
@@ -200,8 +213,8 @@
:root { :root {
@include base-theme; @include base-theme;
@include dark-theme; @include dark-theme;
@include green-theme;
@include dark-editor-theme; @include dark-editor-theme;
@include green-theme;
} }
:root.light { :root.light {
@@ -257,63 +270,3 @@
:root[data-accent="yellow"] { :root[data-accent="yellow"] {
@include yellow-theme; @include yellow-theme;
} }
@mixin font-small {
--font-size-body: 0.75rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
}
@mixin font-medium {
--font-size-body: 0.875rem;
--line-height-body: 1.25rem;
--upper-primary-sticky-fold: 4.375rem;
--upper-secondary-sticky-fold: 6.688rem;
--upper-tertiary-sticky-fold: 9rem;
--upper-mobile-primary-sticky-fold: 7.125rem;
--upper-mobile-secondary-sticky-fold: 9.438rem;
--upper-mobile-sticky-fold: 11.75rem;
--upper-mobile-tertiary-sticky-fold: 9rem;
--lower-primary-sticky-fold: 3.25rem;
--lower-secondary-sticky-fold: 5.563rem;
--lower-tertiary-sticky-fold: 7.875rem;
--sidebar-primary-sticky-fold: 2.25rem;
}
@mixin font-large {
--font-size-body: 1rem;
--line-height-body: 1.5rem;
--upper-primary-sticky-fold: 4.625rem;
--upper-secondary-sticky-fold: 7.188rem;
--upper-tertiary-sticky-fold: 9.75rem;
--upper-mobile-primary-sticky-fold: 7.625rem;
--upper-mobile-secondary-sticky-fold: 10.188rem;
--upper-mobile-sticky-fold: 12.75rem;
--upper-mobile-tertiary-sticky-fold: 9.75rem;
--lower-primary-sticky-fold: 3.5rem;
--lower-secondary-sticky-fold: 6.063rem;
--lower-tertiary-sticky-fold: 8.625rem;
--sidebar-primary-sticky-fold: 2.5rem;
}
:root[data-font-size="small"] {
@include font-small;
}
:root[data-font-size="medium"] {
@include font-medium;
}
:root[data-font-size="large"] {
@include font-large;
}

167
pnpm-lock.yaml generated
View File

@@ -184,9 +184,6 @@ importers:
passport-microsoft: passport-microsoft:
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0 version: 1.0.0
pg:
specifier: ^8.11.3
version: 8.11.3
prisma: prisma:
specifier: ^4.16.2 specifier: ^4.16.2
version: 4.16.2 version: 4.16.2
@@ -1342,7 +1339,7 @@ importers:
version: 0.13.1(vite@3.2.4)(workbox-build@6.6.0)(workbox-window@6.6.0) version: 0.13.1(vite@3.2.4)(workbox-build@6.6.0)(workbox-window@6.6.0)
vite-plugin-vue-layouts: vite-plugin-vue-layouts:
specifier: ^0.7.0 specifier: ^0.7.0
version: 0.7.0(vite@3.2.4)(vue-router@4.2.4)(vue@3.2.45) version: 0.7.0(vite@3.2.4)(vue-router@4.1.0)(vue@3.2.45)
vite-plugin-windicss: vite-plugin-windicss:
specifier: ^1.8.8 specifier: ^1.8.8
version: 1.8.8(vite@3.2.4) version: 1.8.8(vite@3.2.4)
@@ -6065,8 +6062,8 @@ packages:
vue-i18n: vue-i18n:
optional: true optional: true
dependencies: dependencies:
'@intlify/message-compiler': 9.3.0 '@intlify/message-compiler': 9.3.0-beta.26
'@intlify/shared': 9.3.0 '@intlify/shared': 9.3.0-beta.26
jsonc-eslint-parser: 1.4.1 jsonc-eslint-parser: 1.4.1
source-map: 0.6.1 source-map: 0.6.1
vue-i18n: 9.2.2(vue@3.3.4) vue-i18n: 9.2.2(vue@3.3.4)
@@ -6119,14 +6116,6 @@ packages:
'@intlify/shared': 9.2.2 '@intlify/shared': 9.2.2
source-map: 0.6.1 source-map: 0.6.1
/@intlify/message-compiler@9.3.0:
resolution: {integrity: sha512-D8tSJEhTCSFcCzkThjE4Sbk1tIdvzkYa1FaVIzUtZ8hKPATvokNrOiDw1i/h671m8A80l9Ywq594i/LPTB6EJA==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 9.3.0
source-map-js: 1.0.2
dev: true
/@intlify/message-compiler@9.3.0-beta.20: /@intlify/message-compiler@9.3.0-beta.20:
resolution: {integrity: sha512-hwqQXyTnDzAVZ300SU31jO0+3OJbpOdfVU6iBkrmNpS7t2HRnVACo0EwcEXzJa++4EVDreqz5OeqJbt+PeSGGA==} resolution: {integrity: sha512-hwqQXyTnDzAVZ300SU31jO0+3OJbpOdfVU6iBkrmNpS7t2HRnVACo0EwcEXzJa++4EVDreqz5OeqJbt+PeSGGA==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
@@ -6135,17 +6124,25 @@ packages:
source-map-js: 1.0.2 source-map-js: 1.0.2
dev: true dev: true
/@intlify/message-compiler@9.3.0-beta.26:
resolution: {integrity: sha512-qsfU6Lca7mI80ts1vgy+pfNvGm2gHy0nERpT/K1GYgnECmsKwud0e8SG1PPxKPEHKa5Mdngzs4pS7X1wH0SCGA==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 9.3.0-beta.26
source-map-js: 1.0.2
dev: true
/@intlify/shared@9.2.2: /@intlify/shared@9.2.2:
resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==} resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
/@intlify/shared@9.3.0: /@intlify/shared@9.3.0-beta.20:
resolution: {integrity: sha512-MMGRz6zWxtz7rHtxIIdnyb8SYOIaaseN1IvUhAEs9tOW4u77RD4DFp4qgPXesp2Gxo/5QitH9kwSs0jnxGUNEw==} resolution: {integrity: sha512-RucSPqh8O9FFxlYUysQTerSw0b9HIRpyoN1Zjogpm0qLiHK+lBNSa5sh1nCJ4wSsNcjphzgpLQCyR60GZlRV8g==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
dev: true dev: true
/@intlify/shared@9.3.0-beta.20: /@intlify/shared@9.3.0-beta.26:
resolution: {integrity: sha512-RucSPqh8O9FFxlYUysQTerSw0b9HIRpyoN1Zjogpm0qLiHK+lBNSa5sh1nCJ4wSsNcjphzgpLQCyR60GZlRV8g==} resolution: {integrity: sha512-RpCtfSYIg4tSskrazTr5+WCHyw6qpgwdIxC+x3nCnrPGxyk+en9FoSbadVfx/w7uDTdyhKslEw4d2+qhNc0s4Q==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
dev: true dev: true
@@ -6165,7 +6162,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@intlify/bundle-utils': 7.0.0 '@intlify/bundle-utils': 7.0.0
'@intlify/shared': 9.3.0 '@intlify/shared': 9.3.0-beta.26
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2) debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.2.11 fast-glob: 3.2.11
@@ -6192,7 +6189,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2) '@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2)
'@intlify/shared': 9.3.0 '@intlify/shared': 9.3.0-beta.26
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2) debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.3.1 fast-glob: 3.3.1
@@ -6220,7 +6217,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2) '@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2)
'@intlify/shared': 9.3.0 '@intlify/shared': 9.3.0-beta.26
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2) debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.3.1 fast-glob: 3.3.1
@@ -6247,7 +6244,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2) '@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2)
'@intlify/shared': 9.3.0 '@intlify/shared': 9.3.0-beta.26
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2) debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.3.1 fast-glob: 3.3.1
@@ -11141,11 +11138,6 @@ packages:
/buffer-from@1.1.2: /buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
/buffer-writer@2.0.0:
resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==}
engines: {node: '>=4'}
dev: false
/buffer@5.7.1: /buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
dependencies: dependencies:
@@ -18945,10 +18937,6 @@ packages:
netmask: 2.0.2 netmask: 2.0.2
dev: false dev: false
/packet-reader@1.0.0:
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
dev: false
/paho-mqtt@1.1.0: /paho-mqtt@1.1.0:
resolution: {integrity: sha512-KPbL9KAB0ASvhSDbOrZBaccXS+/s7/LIofbPyERww8hM5Ko71GUJQ6Nmg0BWqj8phAIT8zdf/Sd/RftHU9i2HA==} resolution: {integrity: sha512-KPbL9KAB0ASvhSDbOrZBaccXS+/s7/LIofbPyERww8hM5Ko71GUJQ6Nmg0BWqj8phAIT8zdf/Sd/RftHU9i2HA==}
dev: false dev: false
@@ -19230,70 +19218,6 @@ packages:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
dev: false dev: false
/pg-cloudflare@1.1.1:
resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
requiresBuild: true
dev: false
optional: true
/pg-connection-string@2.6.2:
resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==}
dev: false
/pg-int8@1.0.1:
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
engines: {node: '>=4.0.0'}
dev: false
/pg-pool@3.6.1(pg@8.11.3):
resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==}
peerDependencies:
pg: '>=8.0'
dependencies:
pg: 8.11.3
dev: false
/pg-protocol@1.6.0:
resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==}
dev: false
/pg-types@2.2.0:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
dependencies:
pg-int8: 1.0.1
postgres-array: 2.0.0
postgres-bytea: 1.0.0
postgres-date: 1.0.7
postgres-interval: 1.2.0
dev: false
/pg@8.11.3:
resolution: {integrity: sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==}
engines: {node: '>= 8.0.0'}
peerDependencies:
pg-native: '>=3.0.1'
peerDependenciesMeta:
pg-native:
optional: true
dependencies:
buffer-writer: 2.0.0
packet-reader: 1.0.0
pg-connection-string: 2.6.2
pg-pool: 3.6.1(pg@8.11.3)
pg-protocol: 1.6.0
pg-types: 2.2.0
pgpass: 1.0.5
optionalDependencies:
pg-cloudflare: 1.1.1
dev: false
/pgpass@1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
dependencies:
split2: 4.2.0
dev: false
/pick-util@1.1.5: /pick-util@1.1.5:
resolution: {integrity: sha512-H0MaM8T7wpQ/azvB12ChZw7kpSFzjsgv3Z+N7fUWnL1McTGSEeroCngcK4eOPiFQq08rAyKX3hadcAB1kUqfXA==} resolution: {integrity: sha512-H0MaM8T7wpQ/azvB12ChZw7kpSFzjsgv3Z+N7fUWnL1McTGSEeroCngcK4eOPiFQq08rAyKX3hadcAB1kUqfXA==}
dependencies: dependencies:
@@ -19403,28 +19327,6 @@ packages:
picocolors: 1.0.0 picocolors: 1.0.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/postgres-array@2.0.0:
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
engines: {node: '>=4'}
dev: false
/postgres-bytea@1.0.0:
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
engines: {node: '>=0.10.0'}
dev: false
/postgres-date@1.0.7:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
dev: false
/postgres-interval@1.2.0:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
dependencies:
xtend: 4.0.2
dev: false
/postman-collection@4.2.0: /postman-collection@4.2.0:
resolution: {integrity: sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==} resolution: {integrity: sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -20839,11 +20741,6 @@ packages:
readable-stream: 3.6.0 readable-stream: 3.6.0
dev: true dev: true
/split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
dev: false
/split@1.0.1: /split@1.0.1:
resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==}
dependencies: dependencies:
@@ -23174,23 +23071,6 @@ packages:
- supports-color - supports-color
dev: true dev: true
/vite-plugin-vue-layouts@0.7.0(vite@3.2.4)(vue-router@4.2.4)(vue@3.2.45):
resolution: {integrity: sha512-k5XDmRNFo4M/GmUjhbRXj2WmJiFcGoVI8l/uZ72RHyRDQr4wE/6Zq/KFq0lqXomWQxTSzakQRUswzNwtvZLE8A==}
peerDependencies:
vite: ^2.5.0 || ^3.0.0-0
vue: ^2.6.12 || ^3.2.4
vue-router: ^3.5.1 || ^ 4.0.11
dependencies:
'@vue/compiler-sfc': 3.3.4
debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.3.1
vite: 3.2.4(@types/node@17.0.45)(sass@1.53.0)(terser@5.19.2)
vue: 3.2.45
vue-router: 4.2.4(vue@3.2.45)
transitivePeerDependencies:
- supports-color
dev: true
/vite-plugin-vue-layouts@0.8.0(vite@4.4.9)(vue-router@4.2.4)(vue@3.3.4): /vite-plugin-vue-layouts@0.8.0(vite@4.4.9)(vue-router@4.2.4)(vue@3.3.4):
resolution: {integrity: sha512-UZW2nSV2LraTSe7gsAL46hfdi7a0X1RvkGGoJVtA2O8beu7anzpXFwQLou8+kHy31CzVycT4gIPySBsHhtBN5g==} resolution: {integrity: sha512-UZW2nSV2LraTSe7gsAL46hfdi7a0X1RvkGGoJVtA2O8beu7anzpXFwQLou8+kHy31CzVycT4gIPySBsHhtBN5g==}
peerDependencies: peerDependencies:
@@ -23894,15 +23774,6 @@ packages:
'@vue/devtools-api': 6.5.0 '@vue/devtools-api': 6.5.0
vue: 3.2.45 vue: 3.2.45
/vue-router@4.2.4(vue@3.2.45):
resolution: {integrity: sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==}
peerDependencies:
vue: ^3.2.0
dependencies:
'@vue/devtools-api': 6.5.0
vue: 3.2.45
dev: true
/vue-router@4.2.4(vue@3.3.4): /vue-router@4.2.4(vue@3.3.4):
resolution: {integrity: sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==} resolution: {integrity: sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==}
peerDependencies: peerDependencies:

View File

@@ -18,11 +18,11 @@ RUN pnpm exec prisma generate
RUN pnpm run build RUN pnpm run build
# Remove the env file to avoid backend copying it in and using it # Remove the env file to avoid backend copying it in and using it
RUN rm "../../.env" RUN rm "../../.env"
ENV PRODUCTION="false" ENV PRODUCTION="true"
ENV PORT=3170 ENV PORT=3170
ENV APP_PORT=${PORT} ENV APP_PORT=${PORT}
ENV DB_URL=${DATABASE_URL} ENV DB_URL=${DATABASE_URL}
CMD ["pnpm", "run", "start:dev"] CMD ["pnpm", "run", "start:prod"]
EXPOSE 3170 EXPOSE 3170
FROM base_builder as fe_builder FROM base_builder as fe_builder