mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-05 10:28:32 +00:00
Compare commits
114 Commits
feat/new-r
...
fix/oauth-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
148d3f0e7d | ||
|
|
75e17610f0 | ||
|
|
154c45d87d | ||
|
|
0bf169562b | ||
|
|
967b073ded | ||
|
|
725dfeacac | ||
|
|
923d26ce56 | ||
|
|
7e258003d5 | ||
|
|
7689288763 | ||
|
|
81faa57808 | ||
|
|
bac9616de4 | ||
|
|
9ab1ed3d90 | ||
|
|
408c9d4a4e | ||
|
|
ebafdd813c | ||
|
|
6642f4d0b0 | ||
|
|
4f75474c87 | ||
|
|
e5b7aa5ab4 | ||
|
|
875df38501 | ||
|
|
a724f010ff | ||
|
|
f9423d1238 | ||
|
|
51e36519f7 | ||
|
|
bd0894ede0 | ||
|
|
b1e6a707bf | ||
|
|
c51381888a | ||
|
|
8b1b18cc39 | ||
|
|
707ed63be6 | ||
|
|
bc0bb64400 | ||
|
|
4c110900c1 | ||
|
|
65ed6d3cfb | ||
|
|
7b28b05bc1 | ||
|
|
b0f27d01b9 | ||
|
|
3351bf990a | ||
|
|
07fff423bb | ||
|
|
36d10ab480 | ||
|
|
c918c679d7 | ||
|
|
7e3386b1b8 | ||
|
|
f4162e1ce6 | ||
|
|
e6a48a73bf | ||
|
|
fceb99edc2 | ||
|
|
ebc105d42e | ||
|
|
32d56f6942 | ||
|
|
e4a1fca3b1 | ||
|
|
59ff9bdafb | ||
|
|
071ee9ab2e | ||
|
|
176646f983 | ||
|
|
d76a574c51 | ||
|
|
734ee16fe1 | ||
|
|
33594bdcec | ||
|
|
2acfe60a5f | ||
|
|
aecaab84dd | ||
|
|
45264bfcc5 | ||
|
|
b01b8d7bc4 | ||
|
|
58a38ac5a1 | ||
|
|
7328988e59 | ||
|
|
39a6fc837d | ||
|
|
5b1b1b5541 | ||
|
|
578fa72dc8 | ||
|
|
4708e8e589 | ||
|
|
2a9386ef6b | ||
|
|
9483dbf4af | ||
|
|
0b436e2c9f | ||
|
|
9005e17eb5 | ||
|
|
efe94d9c90 | ||
|
|
848825f16a | ||
|
|
4d60425a05 | ||
|
|
c03fe301f8 | ||
|
|
c8371410c2 | ||
|
|
dcbf38bf61 | ||
|
|
a57ecde1d0 | ||
|
|
791843174e | ||
|
|
1174f22d88 | ||
|
|
8300abe086 | ||
|
|
a3809ce4b9 | ||
|
|
adb46110dd | ||
|
|
7cc4c0993e | ||
|
|
1030d02ac7 | ||
|
|
d616be7271 | ||
|
|
afd49d146f | ||
|
|
97e43c4489 | ||
|
|
f9af22d586 | ||
|
|
8590bacd79 | ||
|
|
a7d1a349e3 | ||
|
|
d03d8f01a1 | ||
|
|
97c700beba | ||
|
|
b6a27bc66c | ||
|
|
76a2889206 | ||
|
|
d506c37516 | ||
|
|
0c4ad0ed60 | ||
|
|
30dbe34e2e | ||
|
|
c83c055654 | ||
|
|
33f47ca5e4 | ||
|
|
475707848e | ||
|
|
2d76c444f6 | ||
|
|
33361ba659 | ||
|
|
1e3a0d9af3 | ||
|
|
2a5ec854cc | ||
|
|
d758645144 | ||
|
|
902d9ff968 | ||
|
|
781def844d | ||
|
|
15065eb2f1 | ||
|
|
481fa4ed12 | ||
|
|
a35b455041 | ||
|
|
bfc8968e24 | ||
|
|
f90f256f5f | ||
|
|
4253080f6b | ||
|
|
7a83641436 | ||
|
|
7105e4e8ed | ||
|
|
849465d62a | ||
|
|
058d2e0e61 | ||
|
|
c03c5eb927 | ||
|
|
156e798f90 | ||
|
|
a1a90d19e8 | ||
|
|
ec40d7fc85 | ||
|
|
5fda0866f8 |
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -58,6 +58,8 @@ jobs:
|
||||
run: npm run test --workspace=packages/bruno-converters
|
||||
- name: Test Package bruno-electron
|
||||
run: npm run test --workspace=packages/bruno-electron
|
||||
- name: Test Package bruno-requests
|
||||
run: npm run test --workspace=packages/bruno-requests
|
||||
|
||||
cli-test:
|
||||
name: CLI Tests
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -48,6 +48,7 @@ yarn-error.log*
|
||||
bruno.iml
|
||||
.idea
|
||||
.vscode
|
||||
.cursor
|
||||
|
||||
# Playwright
|
||||
/blob-report/
|
||||
|
||||
BIN
assets/images/landing-2-dark.png
Normal file
BIN
assets/images/landing-2-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 346 KiB |
BIN
assets/images/landing-2-light.png
Normal file
BIN
assets/images/landing-2-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 347 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 584 KiB |
@@ -3,7 +3,7 @@
|
||||
|
||||
### برونو - بيئة تطوير مفتوحة المصدر لاستكشاف واختبار واجهات برمجة التطبيقات (APIs).
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### ব্রুনো - API অন্বেষণ এবং পরীক্ষা করার জন্য ওপেনসোর্স IDE।
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - 开源 IDE,用于探索和测试 API。
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - Opensource IDE zum Erkunden und Testen von APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - IDE de código abierto para explorar y probar APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### برونو یا Bruno - محیط توسعه متن باز برای تست و توسعه API ها
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - IDE Opensource pour explorer et tester des APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - Opensource IDE per esplorare e testare gli APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - API の検証・動作テストのためのオープンソース IDE.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### ბრუნო - ღია წყაროების IDE API-ების შესწავლისა და ტესტირებისათვის.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - API 탐색 및 테스트를 위한 오픈소스 IDE.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - Open source IDE voor het verkennen en testen van API's.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - Otwartoźródłowe IDE do eksploracji i testów APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - IDE de código aberto para explorar e testar APIs.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - Mediu integrat de dezvoltare cu sursă deschisă pentru explorarea și testarea API-urilor.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - IDE с открытым исходным кодом для изучения и тестирования API.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - API'leri keşfetmek ve test etmek için açık kaynaklı IDE.
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - IDE із відкритим кодом для тестування та дослідження API
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
### Bruno - 探索和測試 API 的開源 IDE 工具
|
||||
|
||||
[](https://badge.fury.io/gh/usebruno%bruno)
|
||||
[](https://badge.fury.io/gh/usebruno%2Fbruno)
|
||||
[](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
|
||||
[](https://github.com/usebruno/bruno/pulse)
|
||||
[](https://twitter.com/use_bruno)
|
||||
|
||||
527
package-lock.json
generated
527
package-lock.json
generated
@@ -29,7 +29,7 @@
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@jest/globals": "^29.2.0",
|
||||
"@opencollection/types": "~0.5.0",
|
||||
"@opencollection/types": "~0.7.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@storybook/addon-webpack5-compiler-babel": "^4.0.0",
|
||||
@@ -6100,9 +6100,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@opencollection/types": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@opencollection/types/-/types-0.5.0.tgz",
|
||||
"integrity": "sha512-9rpu5agMrMLcMVU2UgyV+PYV3Zf/sHBJDHMQoq8XiMEUH8lt9f7yGtlerm/9dS3SHMpGX4A8ik0OFtc0dX4r1Q==",
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@opencollection/types/-/types-0.7.0.tgz",
|
||||
"integrity": "sha512-CSwdaHNPa2bNNBAOy++t6W9gBTExUJZW3aPkWyhAjasusThbvjymD/0uCLR50gCXSs0ezv61jsd19m9x+2DMtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -6458,56 +6458,6 @@
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@postman/form-data": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz",
|
||||
"integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@postman/tough-cookie": {
|
||||
"version": "4.1.3-postman.1",
|
||||
"resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz",
|
||||
"integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.2.0",
|
||||
"url-parse": "^1.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@postman/tough-cookie/node_modules/universalify": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@postman/tunnel-agent": {
|
||||
"version": "0.6.4",
|
||||
"resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz",
|
||||
"integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@prantlf/jsonlint": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@prantlf/jsonlint/-/jsonlint-16.0.0.tgz",
|
||||
@@ -11429,15 +11379,6 @@
|
||||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1.js": {
|
||||
"version": "4.10.1",
|
||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
|
||||
@@ -11476,6 +11417,7 @@
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
@@ -11626,15 +11568,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/aws4": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
|
||||
@@ -12028,15 +11961,6 @@
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/big.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
@@ -12229,15 +12153,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brotli": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
|
||||
"integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
@@ -12750,12 +12665,6 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
|
||||
@@ -14375,18 +14284,6 @@
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
|
||||
@@ -15110,22 +15007,6 @@
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn/node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
@@ -16424,12 +16305,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/extract-files": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz",
|
||||
@@ -16555,6 +16430,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
@@ -17037,15 +16913,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz",
|
||||
@@ -17524,15 +17391,6 @@
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/github-markdown-css": {
|
||||
"version": "5.8.1",
|
||||
"resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.8.1.tgz",
|
||||
@@ -17815,57 +17673,12 @@
|
||||
"@grpc/grpc-js": "^1.12.6"
|
||||
}
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"deprecated": "this library is no longer supported",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator-compiled": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-validator-compiled/-/har-validator-compiled-1.0.0.tgz",
|
||||
"integrity": "sha512-dher7nFSx+Ef6OoqVveLClh8itAR3vd8Qx70Lh/hEgP1iGeARAolbci7Y8JBrHIYgFCT6xRdvvL16AR9Zh07Dw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/har-validator/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@@ -18338,20 +18151,6 @@
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/http-signature": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
|
||||
"integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^2.0.2",
|
||||
"sshpk": "^1.14.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
@@ -19168,12 +18967,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-valid-path": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
|
||||
@@ -19236,12 +19029,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/istanbul-lib-coverage": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
|
||||
@@ -20822,12 +20609,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"license": "(AFL-2.1 OR BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
@@ -20851,7 +20632,9 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"license": "ISC"
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
@@ -20892,44 +20675,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/jsprim": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
|
||||
"integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsprim/node_modules/extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsprim/node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
@@ -22030,15 +21775,6 @@
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mustache": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
|
||||
"integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mustache": "bin/mustache"
|
||||
}
|
||||
},
|
||||
"node_modules/mz": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||
@@ -22259,44 +21995,6 @@
|
||||
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-vault": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/node-vault/-/node-vault-0.10.2.tgz",
|
||||
"integrity": "sha512-//uc9/YImE7Dx0QHdwMiAzLaOumiKUnOUP8DymgtkZ8nsq6/V2LKvEu6kw91Lcruw8lWUfj4DO7CIXNPRWBuuA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
"mustache": "^4.2.0",
|
||||
"postman-request": "^2.88.1-postman.33",
|
||||
"tv4": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-vault/node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-vault/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -22367,15 +22065,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -23090,12 +22779,6 @@
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@@ -24075,57 +23758,6 @@
|
||||
"node": ">=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postman-request": {
|
||||
"version": "2.88.1-postman.40",
|
||||
"resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.40.tgz",
|
||||
"integrity": "sha512-uE4AiIqhjtHKp4pj9ei7fkdfNXEX9IqDBlK1plGAQne6y79UUlrTdtYLhwXoO0AMOvqyl9Ar+BU6Eo6P/MPgfg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@postman/form-data": "~3.1.1",
|
||||
"@postman/tough-cookie": "~4.1.3-postman.1",
|
||||
"@postman/tunnel-agent": "^0.6.4",
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.12.0",
|
||||
"brotli": "^1.3.3",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.3.1",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "^2.1.35",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.3",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"stream-length": "^1.0.2",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/postman-request/node_modules/qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/postman-request/node_modules/uuid": {
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@@ -24427,6 +24059,7 @@
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
@@ -24471,6 +24104,7 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -27386,37 +27020,6 @@
|
||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
|
||||
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sshpk/node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
@@ -27587,21 +27190,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-length": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz",
|
||||
"integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==",
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"bluebird": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-length/node_modules/bluebird": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
|
||||
"integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
@@ -29184,12 +28772,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@@ -29454,6 +29036,7 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"devOptional": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
@@ -30477,7 +30060,7 @@
|
||||
"polished": "^4.3.1",
|
||||
"posthog-node": "4.2.1",
|
||||
"prettier": "^2.7.1",
|
||||
"qs": "^6.11.0",
|
||||
"qs": "^6.14.1",
|
||||
"query-string": "^7.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
@@ -30492,6 +30075,7 @@
|
||||
"react-player": "^2.16.0",
|
||||
"react-redux": "^7.2.9",
|
||||
"react-tooltip": "^5.5.2",
|
||||
"react-virtuoso": "^4.18.1",
|
||||
"sass": "^1.46.0",
|
||||
"semver": "^7.7.1",
|
||||
"shell-quote": "^1.8.3",
|
||||
@@ -31932,6 +31516,31 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"packages/bruno-app/node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"packages/bruno-app/node_modules/react-virtuoso": {
|
||||
"version": "4.18.1",
|
||||
"resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.18.1.tgz",
|
||||
"integrity": "sha512-KF474cDwaSb9+SJ380xruBB4P+yGWcVkcu26HtMqYNMTYlYbrNy8vqMkE+GpAApPPufJqgOLMoWMFG/3pJMXUA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": ">=16 || >=17 || >= 18 || >= 19",
|
||||
"react-dom": ">=16 || >=17 || >= 18 || >=19"
|
||||
}
|
||||
},
|
||||
"packages/bruno-app/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
@@ -32017,7 +31626,7 @@
|
||||
"iconv-lite": "^0.6.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"qs": "^6.11.0",
|
||||
"qs": "^6.14.1",
|
||||
"socks-proxy-agent": "^8.0.2",
|
||||
"xmlbuilder": "^15.1.1",
|
||||
"yargs": "^17.6.2"
|
||||
@@ -33067,6 +32676,21 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"packages/bruno-cli/node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"packages/bruno-common": {
|
||||
"name": "@usebruno/common",
|
||||
"version": "0.1.0",
|
||||
@@ -33081,6 +32705,7 @@
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@types/jest": "^29.5.14",
|
||||
"babel-jest": "^29.7.0",
|
||||
"form-data": "^4.0.0",
|
||||
"is-ip": "^5.0.1",
|
||||
"moment": "^2.29.4",
|
||||
"rollup": "3.29.5",
|
||||
@@ -33643,10 +33268,17 @@
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
},
|
||||
"packages/bruno-converters/node_modules/@opencollection/types": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@opencollection/types/-/types-0.5.0.tgz",
|
||||
"integrity": "sha512-9rpu5agMrMLcMVU2UgyV+PYV3Zf/sHBJDHMQoq8XiMEUH8lt9f7yGtlerm/9dS3SHMpGX4A8ik0OFtc0dX4r1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"packages/bruno-converters/node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
|
||||
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -33749,7 +33381,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.35",
|
||||
"nanoid": "3.3.8",
|
||||
"qs": "^6.11.0",
|
||||
"qs": "^6.14.1",
|
||||
"socks-proxy-agent": "^8.0.2",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"uuid": "^9.0.0",
|
||||
@@ -35235,6 +34867,21 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"packages/bruno-electron/node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"packages/bruno-electron/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
@@ -35484,7 +35131,6 @@
|
||||
"moment": "^2.29.4",
|
||||
"nanoid": "3.3.8",
|
||||
"node-fetch": "^2.7.0",
|
||||
"node-vault": "^0.10.2",
|
||||
"path": "^0.12.7",
|
||||
"quickjs-emscripten": "^0.29.2",
|
||||
"tv4": "^1.3.0",
|
||||
@@ -35599,7 +35245,10 @@
|
||||
"debug": "^4.4.3",
|
||||
"google-protobuf": "^4.0.0",
|
||||
"grpc-js-reflection-client": "^1.3.0",
|
||||
"http-proxy-agent": "~7.0.2",
|
||||
"https-proxy-agent": "~7.0.6",
|
||||
"is-ip": "^5.0.1",
|
||||
"socks-proxy-agent": "~8.0.5",
|
||||
"system-ca": "^2.0.1",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"ws": "^8.18.3"
|
||||
@@ -35699,9 +35348,7 @@
|
||||
"version": "0.7.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "3.3.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"nanoid": "3.3.8",
|
||||
"yup": "^0.32.11"
|
||||
}
|
||||
},
|
||||
@@ -35996,4 +35643,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@jest/globals": "^29.2.0",
|
||||
"@opencollection/types": "~0.5.0",
|
||||
"@opencollection/types": "~0.7.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@storybook/addon-webpack5-compiler-babel": "^4.0.0",
|
||||
@@ -78,6 +78,7 @@
|
||||
"build:electron:rpm": "./scripts/build-electron.sh rpm",
|
||||
"build:electron:snap": "./scripts/build-electron.sh snap",
|
||||
"watch:common": "npm run watch --workspace=packages/bruno-common",
|
||||
"watch:requests": "npm run watch --workspace=packages/bruno-requests",
|
||||
"test:codegen": "node playwright/codegen.ts",
|
||||
"test:e2e": "playwright test --project=default",
|
||||
"test:e2e:ssl": "playwright test --project=ssl",
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"polished": "^4.3.1",
|
||||
"posthog-node": "4.2.1",
|
||||
"prettier": "^2.7.1",
|
||||
"qs": "^6.11.0",
|
||||
"qs": "^6.14.1",
|
||||
"query-string": "^7.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
@@ -84,6 +84,7 @@
|
||||
"react-player": "^2.16.0",
|
||||
"react-redux": "^7.2.9",
|
||||
"react-tooltip": "^5.5.2",
|
||||
"react-virtuoso": "^4.18.1",
|
||||
"sass": "^1.46.0",
|
||||
"semver": "^7.7.1",
|
||||
"shell-quote": "^1.8.3",
|
||||
|
||||
@@ -55,10 +55,10 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.cm-variable-valid {
|
||||
color: green;
|
||||
color: ${(props) => props.theme.codemirror.variable.valid};
|
||||
}
|
||||
.cm-variable-invalid {
|
||||
color: red;
|
||||
color: ${(props) => props.theme.codemirror.variable.invalid};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ const FileEditor = ({ apiSpec }) => {
|
||||
/>
|
||||
<IconDeviceFloppy
|
||||
onClick={onSave}
|
||||
color={hasChanges ? theme.colors.text.yellow : theme.requestTabs.icon.color}
|
||||
color={hasChanges ? theme.draftColor : theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={22}
|
||||
className={`absolute right-0 top-0 m-4 ${
|
||||
|
||||
@@ -18,9 +18,9 @@ import ImportWorkspace from 'components/WorkspaceSidebar/ImportWorkspace';
|
||||
|
||||
import IconBottombarToggle from 'components/Icons/IconBottombarToggle/index';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import { toTitleCase } from 'utils/common/index';
|
||||
import ResponseLayoutToggle from 'components/ResponsePane/ResponseLayoutToggle';
|
||||
import { isMacOS, isWindowsOS, isLinuxOS } from 'utils/common/platform';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const getOsClass = () => {
|
||||
if (isMacOS()) return 'os-mac';
|
||||
@@ -29,6 +29,12 @@ const getOsClass = () => {
|
||||
return 'os-other';
|
||||
};
|
||||
|
||||
// Helper to get display name for workspace
|
||||
export const getWorkspaceDisplayName = (name) => {
|
||||
if (!name) return 'Untitled Workspace';
|
||||
return name;
|
||||
};
|
||||
|
||||
const AppTitleBar = () => {
|
||||
const dispatch = useDispatch();
|
||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||
@@ -115,7 +121,7 @@ const AppTitleBar = () => {
|
||||
const WorkspaceName = forwardRef((props, ref) => {
|
||||
return (
|
||||
<div ref={ref} className="workspace-name-container" {...props}>
|
||||
<span className="workspace-name">{toTitleCase(activeWorkspace?.name) || 'Default Workspace'}</span>
|
||||
<span data-testid="workspace-name" className={classNames('workspace-name', { 'italic text-muted': !activeWorkspace?.name })}>{getWorkspaceDisplayName(activeWorkspace?.name)}</span>
|
||||
<IconChevronDown size={14} stroke={1.5} className="chevron-icon" />
|
||||
</div>
|
||||
);
|
||||
@@ -127,7 +133,7 @@ const AppTitleBar = () => {
|
||||
|
||||
const handleWorkspaceSwitch = (workspaceUid) => {
|
||||
dispatch(switchWorkspace(workspaceUid));
|
||||
toast.success(`Switched to ${workspaces.find((w) => w.uid === workspaceUid)?.name}`);
|
||||
toast.success(`Switched to ${getWorkspaceDisplayName(workspaces.find((w) => w.uid === workspaceUid)?.name)}`);
|
||||
};
|
||||
|
||||
const handleOpenWorkspace = async () => {
|
||||
@@ -178,7 +184,7 @@ const AppTitleBar = () => {
|
||||
|
||||
return {
|
||||
id: workspace.uid,
|
||||
label: toTitleCase(workspace.name),
|
||||
label: getWorkspaceDisplayName(workspace.name),
|
||||
onClick: () => handleWorkspaceSwitch(workspace.uid),
|
||||
className: `workspace-item ${isActive ? 'active' : ''}`,
|
||||
rightSection: (
|
||||
@@ -190,11 +196,7 @@ const AppTitleBar = () => {
|
||||
label={isPinned ? 'Unpin workspace' : 'Pin workspace'}
|
||||
size="sm"
|
||||
>
|
||||
{isPinned ? (
|
||||
<IconPinned size={14} stroke={1.5} />
|
||||
) : (
|
||||
<IconPin size={14} stroke={1.5} />
|
||||
)}
|
||||
{isPinned ? <IconPinned size={14} stroke={1.5} /> : <IconPin size={14} stroke={1.5} />}
|
||||
</ActionIcon>
|
||||
)}
|
||||
{isActive && <IconCheck size={16} stroke={1.5} className="check-icon" />}
|
||||
@@ -247,12 +249,7 @@ const AppTitleBar = () => {
|
||||
<div className="titlebar-content">
|
||||
{/* Left section: Home + Workspace */}
|
||||
<div className="titlebar-left">
|
||||
<ActionIcon
|
||||
onClick={handleHomeClick}
|
||||
label="Home"
|
||||
size="lg"
|
||||
className="home-button"
|
||||
>
|
||||
<ActionIcon onClick={handleHomeClick} label="Home" size="lg" className="home-button">
|
||||
<IconHome size={16} stroke={1.5} />
|
||||
</ActionIcon>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.selected-body-mode {
|
||||
color: ${(props) => props.theme.brand};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import CodeEditor from 'components/CodeEditor';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import { useSelector } from 'react-redux';
|
||||
@@ -21,7 +22,8 @@ const BulkEditor = ({ params, onChange, onToggle, onSave, onRun }) => {
|
||||
<CodeEditor
|
||||
mode="text/plain"
|
||||
theme={displayedTheme}
|
||||
font={preferences.codeFont || 'default'}
|
||||
font={get(preferences, 'font.codeFont', 'default')}
|
||||
fontSize={get(preferences, 'font.codeFontSize')}
|
||||
value={parsedParams}
|
||||
onEdit={handleEdit}
|
||||
onSave={onSave}
|
||||
|
||||
@@ -36,12 +36,12 @@ const StyledWrapper = styled.div`
|
||||
|
||||
/* Style line numbers when there's a lint issue */
|
||||
.CodeMirror-lint-line-error .CodeMirror-linenumber {
|
||||
color: #d32f2f !important;
|
||||
color: ${(props) => props.theme.colors.text.danger} !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.CodeMirror-lint-line-warning .CodeMirror-linenumber {
|
||||
color: #f57c00 !important;
|
||||
color: ${(props) => props.theme.colors.text.warning} !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ const StyledWrapper = styled.div`
|
||||
|
||||
/* Variable validation colors */
|
||||
.cm-variable-valid {
|
||||
color: #5fad89 !important; /* Soft sage */
|
||||
color: ${(props) => props.theme.codemirror.variable.valid} !important;
|
||||
}
|
||||
.cm-variable-invalid {
|
||||
color: #d17b7b !important; /* Soft coral */
|
||||
color: ${(props) => props.theme.codemirror.variable.invalid} !important;
|
||||
}
|
||||
|
||||
.CodeMirror-search-hint {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import React from 'react';
|
||||
import { isEqual, escapeRegExp } from 'lodash';
|
||||
import { defineCodeMirrorBrunoVariablesMode } from 'utils/common/codemirror';
|
||||
import { setupAutoComplete } from 'utils/codemirror/autocomplete';
|
||||
import { setupAutoComplete, showRootHints } from 'utils/codemirror/autocomplete';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import * as jsonlint from '@prantlf/jsonlint';
|
||||
import { JSHINT } from 'jshint';
|
||||
@@ -111,8 +111,12 @@ export default class CodeEditor extends React.Component {
|
||||
: cm.replaceSelection(' ', 'end');
|
||||
},
|
||||
'Shift-Tab': 'indentLess',
|
||||
'Ctrl-Space': 'autocomplete',
|
||||
'Cmd-Space': 'autocomplete',
|
||||
'Ctrl-Space': (cm) => {
|
||||
showRootHints(cm, this.props.showHintsFor);
|
||||
},
|
||||
'Cmd-Space': (cm) => {
|
||||
showRootHints(cm, this.props.showHintsFor);
|
||||
},
|
||||
'Ctrl-Y': 'foldAll',
|
||||
'Cmd-Y': 'foldAll',
|
||||
'Ctrl-I': 'unfoldAll',
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
background: transparent;
|
||||
|
||||
.auth-mode-label {
|
||||
color: ${(props) => props.theme.brand};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
|
||||
.caret {
|
||||
color: rgb(140, 140, 140);
|
||||
|
||||
@@ -69,7 +69,7 @@ const Info = ({ collection }) => {
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="text-sm text-link cursor-pointer hover:underline text-left bg-transparent"
|
||||
className="text-link cursor-pointer hover:underline text-left bg-transparent"
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
addTab({
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
import styled from 'styled-components';
|
||||
import { rgba } from 'polished';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
&.card {
|
||||
background-color: ${(props) => props.theme.requestTabPanel.card.bg};
|
||||
|
||||
.title {
|
||||
border-top: 1px solid ${(props) => props.theme.border.BORDER0};
|
||||
border-left: 1px solid ${(props) => props.theme.border.BORDER0};
|
||||
border-right: 1px solid ${(props) => props.theme.border.BORDER0};
|
||||
border-top: 1px solid ${(props) => props.theme.table.border};
|
||||
border-left: 1px solid ${(props) => props.theme.table.border};
|
||||
border-right: 1px solid ${(props) => props.theme.table.border};
|
||||
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
|
||||
background-color: ${(props) => props.theme.status.warning.background};
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
color: ${(props) => props.theme.status.warning.text};
|
||||
}
|
||||
|
||||
.table {
|
||||
|
||||
@@ -41,8 +41,8 @@ const RequestsNotLoaded = ({ collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full card my-2">
|
||||
<div className="flex items-center gap-2 px-3 py-2 title bg-yellow-50 dark:bg-yellow-900/20">
|
||||
<IconAlertTriangle size={16} className="text-yellow-500" />
|
||||
<div className="flex items-center gap-2 px-3 py-2 title">
|
||||
<IconAlertTriangle size={16} className="warning-icon" />
|
||||
<span className="font-medium">Following requests were not loaded</span>
|
||||
</div>
|
||||
<table className="w-full border-collapse">
|
||||
|
||||
@@ -36,7 +36,7 @@ const PresetsSettings = ({ collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="h-full w-full">
|
||||
<div className="text-xs mb-4 mt-4 text-muted">
|
||||
<div className="text-xs mb-4 text-muted">
|
||||
These presets will be used as the default values for new requests in this collection.
|
||||
</div>
|
||||
<div className="bruno-form">
|
||||
|
||||
@@ -56,7 +56,7 @@ const Script = ({ collection }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full flex flex-col h-full pt-4">
|
||||
<StyledWrapper className="w-full flex flex-col h-full">
|
||||
<div className="text-xs mb-4 text-muted">
|
||||
Write pre and post-request scripts that will run before and after any request in this collection is sent.
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,10 @@ const StyledWrapper = styled.div`
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: ${(props) => props.theme.tabs.active.fontWeight} !important;
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
|
||||
@@ -14,7 +14,7 @@ const Vars = ({ collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full flex flex-col">
|
||||
<div className="flex-1 mt-2">
|
||||
<div className="flex-1">
|
||||
<div className="mb-3 title text-xs">Pre Request</div>
|
||||
<VarsTable collection={collection} vars={requestVars} varType="request" />
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ const StyledWrapper = styled.div`
|
||||
/* Checkbox */
|
||||
input[type='checkbox'] {
|
||||
cursor: pointer;
|
||||
accent-color: ${(props) => props.theme.colors.accent};
|
||||
accent-color: ${(props) => props.theme.primary.solid};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -38,20 +38,6 @@ const StyledWrapper = styled.div`
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: transparent;
|
||||
border: 1px solid ${(props) => props.theme.console.border};
|
||||
border-radius: 4px;
|
||||
color: ${(props) => props.theme.console.buttonColor};
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.debug-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -32,12 +32,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.network-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.network-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
@@ -81,11 +75,10 @@ const StyledWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: 80px 80px 150px 1fr 100px 80px 80px;
|
||||
gap: 12px;
|
||||
padding: 8px 16px;
|
||||
padding: 4px 16px;
|
||||
background: ${(props) => props.theme.console.headerBg};
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
font-weight: 500;
|
||||
font-size: 10px;
|
||||
color: ${(props) => props.theme.console.titleColor};
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
@@ -103,8 +96,7 @@ const StyledWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: 80px 80px 150px 1fr 100px 80px 80px;
|
||||
gap: 12px;
|
||||
padding: 6px 16px;
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
padding: 2px 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.1s ease;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
@@ -115,7 +107,8 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
padding-left: 13px;
|
||||
background: ${(props) => props.theme.console.logHoverBg};
|
||||
border-left: 3px solid ${(props) => props.theme.console.checkboxColor};
|
||||
}
|
||||
}
|
||||
@@ -123,25 +116,19 @@ const StyledWrapper = styled.div`
|
||||
.method-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
justify-content: start;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
min-width: 45px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
font-weight: 500;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
}
|
||||
|
||||
.request-domain {
|
||||
color: ${(props) => props.theme.console.messageColor};
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -174,120 +161,6 @@ const StyledWrapper = styled.div`
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.filter-dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.filter-dropdown-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 8px;
|
||||
background: transparent;
|
||||
border: 1px solid ${(props) => props.theme.console.border};
|
||||
border-radius: 4px;
|
||||
color: ${(props) => props.theme.console.buttonColor};
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
color: ${(props) => props.theme.console.buttonHoverColor};
|
||||
}
|
||||
|
||||
.filter-summary {
|
||||
font-weight: 500;
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-dropdown-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
right: 0;
|
||||
min-width: 200px;
|
||||
max-width: 250px;
|
||||
background: ${(props) => props.theme.console.dropdownBg};
|
||||
border: 1px solid ${(props) => props.theme.console.border};
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.filter-dropdown-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background: ${(props) => props.theme.console.dropdownHeaderBg};
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.console.titleColor};
|
||||
}
|
||||
|
||||
.filter-toggle-all {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: ${(props) => props.theme.console.buttonColor};
|
||||
cursor: pointer;
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
font-weight: 500;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
}
|
||||
}
|
||||
|
||||
.filter-dropdown-options {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.filter-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.optionHoverBg};
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin: 0 8px 0 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
accent-color: ${(props) => props.theme.console.checkboxColor};
|
||||
}
|
||||
}
|
||||
|
||||
.filter-option-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter-option-label {
|
||||
color: ${(props) => props.theme.console.optionLabelColor};
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.filter-option-count {
|
||||
color: ${(props) => props.theme.console.optionCountColor};
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
font-weight: 400;
|
||||
margin-left: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -1,128 +1,33 @@
|
||||
import React, { useState, useRef, useEffect, useMemo } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import {
|
||||
IconFilter,
|
||||
IconChevronDown,
|
||||
IconNetwork
|
||||
} from '@tabler/icons';
|
||||
import {
|
||||
updateNetworkFilter,
|
||||
toggleAllNetworkFilters,
|
||||
setSelectedRequest
|
||||
} from 'providers/ReduxStore/slices/logs';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const MethodBadge = ({ method }) => {
|
||||
const getMethodColor = (method) => {
|
||||
switch (method?.toUpperCase()) {
|
||||
case 'GET': return '#10b981';
|
||||
case 'POST': return '#8b5cf6';
|
||||
case 'PUT': return '#f59e0b';
|
||||
case 'DELETE': return '#ef4444';
|
||||
case 'PATCH': return '#06b6d4';
|
||||
case 'HEAD': return '#6b7280';
|
||||
case 'OPTIONS': return '#84cc16';
|
||||
default: return '#6b7280';
|
||||
}
|
||||
};
|
||||
const methodLower = method?.toLowerCase() || 'get';
|
||||
|
||||
return (
|
||||
<span
|
||||
className="method-badge"
|
||||
style={{ backgroundColor: getMethodColor(method) }}
|
||||
>
|
||||
<span className={`method-badge ${methodLower}`}>
|
||||
{method?.toUpperCase() || 'GET'}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const StatusBadge = ({ status, statusCode }) => {
|
||||
const getStatusColor = (code) => {
|
||||
if (code >= 200 && code < 300) return '#10b981';
|
||||
if (code >= 300 && code < 400) return '#f59e0b';
|
||||
if (code >= 400 && code < 500) return '#ef4444';
|
||||
if (code >= 500) return '#dc2626';
|
||||
return '#6b7280';
|
||||
};
|
||||
|
||||
const displayStatus = statusCode || status;
|
||||
|
||||
return (
|
||||
<span
|
||||
className="status-badge"
|
||||
style={{ color: getStatusColor(statusCode) }}
|
||||
>
|
||||
<span className="status-badge">
|
||||
{displayStatus}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const NetworkFilterDropdown = ({ filters, requestCounts, onFilterToggle, onToggleAll }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
const allFiltersEnabled = Object.values(filters).every((f) => f);
|
||||
const activeFilters = Object.entries(filters).filter(([_, enabled]) => enabled);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="filter-dropdown" ref={dropdownRef}>
|
||||
<button
|
||||
className="filter-dropdown-trigger"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
title="Filter requests by method"
|
||||
>
|
||||
<IconFilter size={16} strokeWidth={1.5} />
|
||||
<span className="filter-summary">
|
||||
{activeFilters.length === Object.keys(filters).length ? 'All' : `${activeFilters.length}/${Object.keys(filters).length}`}
|
||||
</span>
|
||||
<IconChevronDown size={14} strokeWidth={1.5} />
|
||||
</button>
|
||||
|
||||
{isOpen && (
|
||||
<div className="filter-dropdown-menu right">
|
||||
<div className="filter-dropdown-header">
|
||||
<span>Filter by Method</span>
|
||||
<button
|
||||
className="filter-toggle-all"
|
||||
onClick={() => onToggleAll(!allFiltersEnabled)}
|
||||
>
|
||||
{allFiltersEnabled ? 'Hide All' : 'Show All'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="filter-dropdown-options">
|
||||
{Object.keys(filters).map((method) => (
|
||||
<label key={method} className="filter-option">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={filters[method]}
|
||||
onChange={(e) => onFilterToggle(method, e.target.checked)}
|
||||
/>
|
||||
<div className="filter-option-content">
|
||||
<MethodBadge method={method} />
|
||||
<span className="filter-option-label">{method}</span>
|
||||
<span className="filter-option-count">({requestCounts[method] || 0})</span>
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const RequestRow = ({ request, isSelected, onClick }) => {
|
||||
const { data } = request;
|
||||
const { request: req, response: res, timestamp } = data;
|
||||
@@ -241,22 +146,6 @@ const NetworkTab = () => {
|
||||
});
|
||||
}, [allRequests, networkFilters]);
|
||||
|
||||
const requestCounts = useMemo(() => {
|
||||
return allRequests.reduce((counts, request) => {
|
||||
const method = request.data?.request?.method?.toUpperCase() || 'GET';
|
||||
counts[method] = (counts[method] || 0) + 1;
|
||||
return counts;
|
||||
}, {});
|
||||
}, [allRequests]);
|
||||
|
||||
const handleFilterToggle = (method, enabled) => {
|
||||
dispatch(updateNetworkFilter({ method, enabled }));
|
||||
};
|
||||
|
||||
const handleToggleAllFilters = (enabled) => {
|
||||
dispatch(toggleAllNetworkFilters(enabled));
|
||||
};
|
||||
|
||||
const handleRequestClick = (request) => {
|
||||
dispatch(setSelectedRequest(request));
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px;
|
||||
padding: 2px 8px;
|
||||
background: ${(props) => props.theme.console.headerBg};
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
flex-shrink: 0;
|
||||
@@ -27,7 +27,6 @@ const StyledWrapper = styled.div`
|
||||
gap: 8px;
|
||||
color: ${(props) => props.theme.console.titleColor};
|
||||
font-size: ${(props) => props.theme.font.size.base};
|
||||
font-weight: 500;
|
||||
|
||||
.request-time {
|
||||
color: ${(props) => props.theme.console.countColor};
|
||||
@@ -66,7 +65,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 16px;
|
||||
padding: 4px 8px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
@@ -92,7 +91,7 @@ const StyledWrapper = styled.div`
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 16px;
|
||||
padding: 8px;
|
||||
min-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
@@ -170,8 +169,7 @@ const StyledWrapper = styled.div`
|
||||
z-index: 10;
|
||||
|
||||
td {
|
||||
padding: 8px 12px;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
color: ${(props) => props.theme.console.titleColor};
|
||||
text-transform: uppercase;
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
@@ -198,7 +196,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 8px 12px;
|
||||
padding: 2px 8px;
|
||||
vertical-align: top;
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -256,7 +254,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.response-body-container {
|
||||
border-radius: 4px;
|
||||
border-radius: ${(props) => props.theme.border.radius.sm};
|
||||
overflow: hidden;
|
||||
height: 400px;
|
||||
display: flex;
|
||||
@@ -270,7 +268,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
div[role="tablist"] {
|
||||
padding: 8px 12px;
|
||||
padding: 4px 8px;
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
display: flex !important;
|
||||
gap: 8px !important;
|
||||
@@ -319,7 +317,7 @@ const StyledWrapper = styled.div`
|
||||
height: 100% !important;
|
||||
max-height: 400px !important;
|
||||
padding: 0.5rem !important;
|
||||
|
||||
|
||||
.network-logs-pre {
|
||||
color: ${(props) => props.theme.console.messageColor} !important;
|
||||
font-size: ${(props) => props.theme.font.size.xs} !important;
|
||||
|
||||
@@ -13,7 +13,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
padding: 0 8px;
|
||||
background: ${(props) => props.theme.console.headerBg};
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
flex-shrink: 0;
|
||||
@@ -30,7 +30,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
padding: 4px 8px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
@@ -38,8 +38,6 @@ const StyledWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
font-weight: 500;
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
@@ -47,9 +45,9 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: ${(props) => props.theme.console.checkboxColor};
|
||||
border-bottom-color: ${(props) => props.theme.console.checkboxColor};
|
||||
background: ${(props) => props.theme.console.contentBg};
|
||||
color: ${(props) => props.theme.primary.strong};
|
||||
border-bottom-color: ${(props) => props.theme.primary.strong};
|
||||
background: ${(props) => props.theme.background.mantle};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,9 +142,6 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-right: 8px;
|
||||
padding-right: 8px;
|
||||
border-right: 1px solid ${(props) => props.theme.console.border};
|
||||
}
|
||||
|
||||
.action-controls {
|
||||
@@ -159,23 +154,21 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: ${(props) => props.theme.console.buttonColor};
|
||||
color: ${(props) => props.theme.text};
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
color: ${(props) => props.theme.console.buttonHoverColor};
|
||||
background: ${(props) => props.theme.background.surface0};
|
||||
}
|
||||
|
||||
&.close-button:hover {
|
||||
background: #e81123;
|
||||
color: white;
|
||||
background: ${(props) => props.theme.background.surface0};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,19 +180,17 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 8px;
|
||||
padding: 2px 8px;
|
||||
background: transparent;
|
||||
border: 1px solid ${(props) => props.theme.console.border};
|
||||
border-radius: 4px;
|
||||
color: ${(props) => props.theme.console.buttonColor};
|
||||
border: 1px solid ${(props) => props.theme.border.border0};
|
||||
border-radius: ${(props) => props.theme.border.radius.sm};
|
||||
color: ${(props) => props.theme.text};
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.console.buttonHoverBg};
|
||||
color: ${(props) => props.theme.console.buttonHoverColor};
|
||||
border-color: ${(props) => props.theme.console.border};
|
||||
background: ${(props) => props.theme.background.surface0};
|
||||
}
|
||||
|
||||
.filter-summary {
|
||||
@@ -232,7 +223,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
padding: 4px 12px;
|
||||
background: ${(props) => props.theme.console.dropdownHeaderBg};
|
||||
border-bottom: 1px solid ${(props) => props.theme.console.border};
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
@@ -263,7 +254,7 @@ const StyledWrapper = styled.div`
|
||||
.filter-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
padding: 4px 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
@@ -325,20 +316,6 @@ const StyledWrapper = styled.div`
|
||||
.logs-container {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.method-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
min-width: 45px;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
display: flex;
|
||||
|
||||
@@ -5,10 +5,9 @@ import ToolHint from 'components/ToolHint/index';
|
||||
|
||||
const StyledSessionList = styled.div`
|
||||
.session-list-item {
|
||||
padding: 10px 12px;
|
||||
padding: 2px 6px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid ${(props) => props.theme.border || 'rgba(255, 255, 255, 0.05)'};
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
@@ -24,7 +23,8 @@ const StyledSessionList = styled.div`
|
||||
|
||||
&.active {
|
||||
background: ${(props) => props.theme.sidebarActive || 'rgba(59, 142, 234, 0.12)'};
|
||||
border-left: 2px solid ${(props) => props.theme.brandColor || '#3b8eea'};
|
||||
border-left: 2px solid ${(props) => props.theme.primary.subtle};
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
|
||||
@@ -30,7 +30,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.terminal-sessions-header {
|
||||
padding: 12px;
|
||||
padding: 6px 8px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: ${(props) => props.theme.text};
|
||||
|
||||
@@ -182,19 +182,6 @@ const NetworkFilterDropdown = ({ filters, requestCounts, onFilterToggle, onToggl
|
||||
const allFiltersEnabled = Object.values(filters).every((f) => f);
|
||||
const activeFilters = Object.entries(filters).filter(([_, enabled]) => enabled);
|
||||
|
||||
const getMethodColor = (method) => {
|
||||
switch (method?.toUpperCase()) {
|
||||
case 'GET': return '#10b981';
|
||||
case 'POST': return '#8b5cf6';
|
||||
case 'PUT': return '#f59e0b';
|
||||
case 'DELETE': return '#ef4444';
|
||||
case 'PATCH': return '#06b6d4';
|
||||
case 'HEAD': return '#6b7280';
|
||||
case 'OPTIONS': return '#84cc16';
|
||||
default: return '#6b7280';
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||
@@ -241,9 +228,6 @@ const NetworkFilterDropdown = ({ filters, requestCounts, onFilterToggle, onToggl
|
||||
onChange={(e) => onFilterToggle(method, e.target.checked)}
|
||||
/>
|
||||
<div className="filter-option-content">
|
||||
<span className="method-badge" style={{ backgroundColor: getMethodColor(method) }}>
|
||||
{method}
|
||||
</span>
|
||||
<span className="filter-option-label">{method}</span>
|
||||
<span className="filter-option-count">({requestCounts[method] || 0})</span>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { darken } from 'polished';
|
||||
import Console from './Console';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
|
||||
const MIN_DEVTOOLS_HEIGHT = 150;
|
||||
const MAX_DEVTOOLS_HEIGHT = window.innerHeight * 0.7;
|
||||
@@ -10,6 +12,9 @@ const Devtools = ({ mainSectionRef }) => {
|
||||
const isDevtoolsOpen = useSelector((state) => state.logs.isConsoleOpen);
|
||||
const [devtoolsHeight, setDevtoolsHeight] = useState(DEFAULT_DEVTOOLS_HEIGHT);
|
||||
const [isResizingDevtools, setIsResizingDevtools] = useState(false);
|
||||
const { theme } = useTheme();
|
||||
|
||||
const dragHandleColor = useMemo(() => darken(0.1, theme.primary.subtle), [theme.primary.subtle]);
|
||||
|
||||
const handleDevtoolsResizeStart = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
@@ -68,15 +73,15 @@ const Devtools = ({ mainSectionRef }) => {
|
||||
<div
|
||||
onMouseDown={handleDevtoolsResizeStart}
|
||||
style={{
|
||||
height: '4px',
|
||||
height: '2px',
|
||||
cursor: 'row-resize',
|
||||
backgroundColor: isResizingDevtools ? '#0078d4' : 'transparent',
|
||||
backgroundColor: isResizingDevtools ? dragHandleColor : 'transparent',
|
||||
transition: 'background-color 0.2s ease',
|
||||
zIndex: 20,
|
||||
position: 'relative'
|
||||
}}
|
||||
onMouseEnter={(e) => e.target.style.backgroundColor = '#0078d4'}
|
||||
onMouseLeave={(e) => e.target.style.backgroundColor = isResizingDevtools ? '#0078d4' : 'transparent'}
|
||||
onMouseEnter={(e) => e.target.style.backgroundColor = dragHandleColor}
|
||||
onMouseLeave={(e) => e.target.style.backgroundColor = isResizingDevtools ? dragHandleColor : 'transparent'}
|
||||
/>
|
||||
<div style={{ height: `${devtoolsHeight}px`, overflow: 'hidden', position: 'relative' }}>
|
||||
<Console />
|
||||
|
||||
@@ -83,7 +83,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.tooltip-mod {
|
||||
font-size: 11px !important;
|
||||
max-width: 200px !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ const ConfirmCloseEnvironment = ({ onCancel, onCloseWithoutSave, onSaveAndClose,
|
||||
Don't Save
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Button className="mr-2" color="secondary" variant="ghost" onClick={onCancel}>
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" color="secondary" variant="ghost" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={onSaveAndClose}>
|
||||
|
||||
@@ -59,7 +59,7 @@ const CreateEnvironment = ({ collection, onClose, onEnvironmentCreated }) => {
|
||||
return (
|
||||
<Portal>
|
||||
<Modal
|
||||
size="sm"
|
||||
size="md"
|
||||
title="Create Environment"
|
||||
confirmText="Create"
|
||||
handleConfirm={onSubmit}
|
||||
|
||||
@@ -76,7 +76,6 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.tooltip-mod {
|
||||
font-size: 11px !important;
|
||||
max-width: 200px !important;
|
||||
}
|
||||
|
||||
@@ -155,7 +154,7 @@ const Wrapper = styled.div`
|
||||
border-radius: ${(props) => props.theme.border.radius.base};
|
||||
background: transparent;
|
||||
color: ${(props) => props.theme.text};
|
||||
border: ${(props) => props.theme.sidebar.collection.item.indentBorder};
|
||||
border: 1px solid ${(props) => props.theme.border.border1};
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useCallback, useRef, useMemo, useEffect } from 'react';
|
||||
import { TableVirtuoso } from 'react-virtuoso';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { get } from 'lodash';
|
||||
import { IconTrash, IconAlertCircle, IconInfoCircle } from '@tabler/icons';
|
||||
@@ -18,14 +19,28 @@ import { getGlobalEnvironmentVariables, flattenItems, isItemARequest } from 'uti
|
||||
import SensitiveFieldWarning from 'components/SensitiveFieldWarning';
|
||||
import { sensitiveFields } from './constants';
|
||||
|
||||
const TableRow = React.memo(({ children, item }) => <tr key={item.uid} data-testid={`env-var-row-${item.name}`}>{children}</tr>, (prevProps, nextProps) => {
|
||||
const prevUid = prevProps?.item?.uid;
|
||||
const nextUid = nextProps?.item?.uid;
|
||||
return prevUid === nextUid && prevProps.children === nextProps.children;
|
||||
});
|
||||
|
||||
const MIN_H = 35 * 2; // 2 rows worth of height
|
||||
|
||||
const EnvironmentVariables = ({ environment, setIsModified, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { storedTheme } = useTheme();
|
||||
const { globalEnvironments, activeGlobalEnvironmentUid } = useSelector((state) => state.globalEnvironments);
|
||||
|
||||
const [tableHeight, setTableHeight] = React.useState(MIN_H);
|
||||
|
||||
const environmentsDraft = collection?.environmentsDraft;
|
||||
const hasDraftForThisEnv = environmentsDraft?.environmentUid === environment.uid;
|
||||
|
||||
const handleTotalHeightChanged = React.useCallback((h) => {
|
||||
setTableHeight(h);
|
||||
}, []);
|
||||
|
||||
// Track environment changes for draft restoration
|
||||
const prevEnvUidRef = React.useRef(null);
|
||||
const mountedRef = React.useRef(false);
|
||||
@@ -384,111 +399,114 @@ const EnvironmentVariables = ({ environment, setIsModified, collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td className="text-center"></td>
|
||||
<td>Name</td>
|
||||
<td>Value</td>
|
||||
<td className="text-center">Secret</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{formik.values.map((variable, index) => {
|
||||
const isLastRow = index === formik.values.length - 1;
|
||||
const isEmptyRow = !variable.name || variable.name.trim() === '';
|
||||
const isLastEmptyRow = isLastRow && isEmptyRow;
|
||||
<TableVirtuoso
|
||||
className="table-container"
|
||||
style={{ height: tableHeight }}
|
||||
components={{ TableRow }}
|
||||
data={formik.values}
|
||||
totalListHeightChanged={handleTotalHeightChanged}
|
||||
fixedHeaderContent={() => (
|
||||
<tr>
|
||||
<td className="text-center"></td>
|
||||
<td>Name</td>
|
||||
<td>Value</td>
|
||||
<td className="text-center">Secret</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
)}
|
||||
fixedItemHeight={35}
|
||||
computeItemKey={(index, variable) => variable.uid}
|
||||
itemContent={(index, variable) => {
|
||||
const isLastRow = index === formik.values.length - 1;
|
||||
const isEmptyRow = !variable.name || variable.name.trim() === '';
|
||||
const isLastEmptyRow = isLastRow && isEmptyRow;
|
||||
|
||||
return (
|
||||
<tr key={variable.uid} data-testid={`env-var-row-${variable.name}`}>
|
||||
<td className="text-center">
|
||||
{!isLastEmptyRow && (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="mousetrap"
|
||||
name={`${index}.enabled`}
|
||||
checked={variable.enabled}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
className="mousetrap"
|
||||
id={`${index}.name`}
|
||||
name={`${index}.name`}
|
||||
value={variable.name}
|
||||
placeholder={isLastEmptyRow ? 'Name' : ''}
|
||||
onChange={(e) => handleNameChange(index, e)}
|
||||
onBlur={() => handleNameBlur(index)}
|
||||
onKeyDown={(e) => handleNameKeyDown(index, e)}
|
||||
/>
|
||||
<ErrorMessage name={`${index}.name`} index={index} />
|
||||
</div>
|
||||
</td>
|
||||
<td className="flex flex-row flex-nowrap items-center">
|
||||
<div className="overflow-hidden grow w-full relative">
|
||||
<MultiLineEditor
|
||||
theme={storedTheme}
|
||||
collection={_collection}
|
||||
name={`${index}.value`}
|
||||
value={variable.value}
|
||||
placeholder={isLastEmptyRow ? 'Value' : ''}
|
||||
isSecret={variable.secret}
|
||||
readOnly={typeof variable.value !== 'string'}
|
||||
onChange={(newValue) => formik.setFieldValue(`${index}.value`, newValue, true)}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
</div>
|
||||
{typeof variable.value !== 'string' && (
|
||||
<span className="ml-2 flex items-center">
|
||||
<IconInfoCircle id={`${variable.uid}-disabled-info-icon`} className="text-muted" size={16} />
|
||||
<Tooltip
|
||||
anchorId={`${variable.uid}-disabled-info-icon`}
|
||||
content="Non-string values set via scripts are read-only and can only be updated through scripts."
|
||||
place="top"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{!variable.secret && hasSensitiveUsage(variable.name) && (
|
||||
<SensitiveFieldWarning
|
||||
fieldName={variable.name}
|
||||
warningMessage="This variable is used in sensitive fields. Mark it as a secret for security"
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className="text-center">
|
||||
{!isLastEmptyRow && (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="mousetrap"
|
||||
name={`${index}.secret`}
|
||||
checked={variable.secret}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{!isLastEmptyRow && (
|
||||
<button onClick={() => handleRemoveVar(variable.uid)}>
|
||||
<IconTrash strokeWidth={1.5} size={18} />
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
return (
|
||||
<>
|
||||
<td className="text-center">
|
||||
{!isLastEmptyRow && (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="mousetrap"
|
||||
name={`${index}.enabled`}
|
||||
checked={variable.enabled}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
className="mousetrap"
|
||||
id={`${index}.name`}
|
||||
name={`${index}.name`}
|
||||
value={variable.name}
|
||||
placeholder={isLastEmptyRow ? 'Name' : ''}
|
||||
onChange={(e) => handleNameChange(index, e)}
|
||||
onBlur={() => handleNameBlur(index)}
|
||||
onKeyDown={(e) => handleNameKeyDown(index, e)}
|
||||
/>
|
||||
<ErrorMessage name={`${index}.name`} index={index} />
|
||||
</div>
|
||||
</td>
|
||||
<td className="flex flex-row flex-nowrap items-center">
|
||||
<div className="overflow-hidden grow w-full relative">
|
||||
<MultiLineEditor
|
||||
theme={storedTheme}
|
||||
collection={_collection}
|
||||
name={`${index}.value`}
|
||||
value={variable.value}
|
||||
placeholder={isLastEmptyRow ? 'Value' : ''}
|
||||
isSecret={variable.secret}
|
||||
readOnly={typeof variable.value !== 'string'}
|
||||
onChange={(newValue) => formik.setFieldValue(`${index}.value`, newValue, true)}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
</div>
|
||||
{typeof variable.value !== 'string' && (
|
||||
<span className="ml-2 flex items-center">
|
||||
<IconInfoCircle id={`${variable.uid}-disabled-info-icon`} className="text-muted" size={16} />
|
||||
<Tooltip
|
||||
anchorId={`${variable.uid}-disabled-info-icon`}
|
||||
content="Non-string values set via scripts are read-only and can only be updated through scripts."
|
||||
place="top"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{!variable.secret && hasSensitiveUsage(variable.name) && (
|
||||
<SensitiveFieldWarning
|
||||
fieldName={variable.name}
|
||||
warningMessage="This variable is used in sensitive fields. Mark it as a secret for security"
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className="text-center">
|
||||
{!isLastEmptyRow && (
|
||||
<input
|
||||
type="checkbox"
|
||||
className="mousetrap"
|
||||
name={`${index}.secret`}
|
||||
checked={variable.secret}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{!isLastEmptyRow && (
|
||||
<button onClick={() => handleRemoveVar(variable.uid)}>
|
||||
<IconTrash strokeWidth={1.5} size={18} />
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="button-container">
|
||||
<div className="flex items-center">
|
||||
|
||||
@@ -5,7 +5,6 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: ${(props) => props.theme.bg};
|
||||
position: relative;
|
||||
|
||||
.environments-container {
|
||||
@@ -23,14 +22,12 @@ const StyledWrapper = styled.div`
|
||||
z-index: 10;
|
||||
background: ${(props) => props.theme.bg};
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid ${(props) => props.theme.sidebar.collection.item.indentBorder};
|
||||
}
|
||||
|
||||
/* Left Sidebar */
|
||||
.sidebar {
|
||||
width: 240px;
|
||||
min-width: 240px;
|
||||
border-right: 1px solid ${(props) => props.theme.sidebar.collection.item.indentBorder};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -87,7 +84,7 @@ const StyledWrapper = styled.div`
|
||||
padding: 6px 8px 6px 28px;
|
||||
font-size: 12px;
|
||||
background: transparent;
|
||||
border: ${(props) => props.theme.sidebar.collection.item.indentBorder};
|
||||
border: 1px solid ${(props) => props.theme.border.border1};
|
||||
border-radius: 5px;
|
||||
color: ${(props) => props.theme.text};
|
||||
transition: all 0.15s ease;
|
||||
@@ -194,9 +191,12 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.environment-name-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
@@ -213,12 +213,14 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
margin-left: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.creating {
|
||||
.environment-name-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
@@ -235,6 +237,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
margin-left: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
|
||||
.file-picker-btn {
|
||||
display: flex;
|
||||
@@ -18,6 +20,9 @@ const StyledWrapper = styled.div`
|
||||
transition: color 0.15s ease;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
|
||||
&:hover {
|
||||
color: ${(props) => props.theme.text} !important;
|
||||
@@ -30,6 +35,7 @@ const StyledWrapper = styled.div`
|
||||
|
||||
&.icon-only {
|
||||
padding: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.icon-right {
|
||||
@@ -39,6 +45,9 @@ const StyledWrapper = styled.div`
|
||||
|
||||
span {
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
||||
@@ -12,7 +12,7 @@ const Wrapper = styled.div`
|
||||
background-color: ${(props) => props.theme.input.bg};
|
||||
}
|
||||
.inherit-mode-text {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
.auth-mode-label {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
|
||||
@@ -3,7 +3,7 @@ import get from 'lodash/get';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import { saveFolderRoot } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import OAuth2AuthorizationCode from 'components/RequestPane/Auth/OAuth2/AuthorizationCode/index';
|
||||
import { updateFolderAuth } from 'providers/ReduxStore/slices/collections';
|
||||
import { updateFolderAuth as _updateFolderAuth } from 'providers/ReduxStore/slices/collections';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import OAuth2PasswordCredentials from 'components/RequestPane/Auth/OAuth2/PasswordCredentials/index';
|
||||
import OAuth2ClientCredentials from 'components/RequestPane/Auth/OAuth2/ClientCredentials/index';
|
||||
@@ -20,7 +20,7 @@ import AwsV4Auth from 'components/RequestPane/Auth/AwsV4Auth';
|
||||
import { humanizeRequestAuthMode, getTreePathFromCollectionToItem } from 'utils/collections/index';
|
||||
import Button from 'ui/Button';
|
||||
|
||||
const GrantTypeComponentMap = ({ collection, folder }) => {
|
||||
const GrantTypeComponentMap = ({ collection, folder, updateFolderAuth }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const save = () => {
|
||||
@@ -90,6 +90,13 @@ const Auth = ({ collection, folder }) => {
|
||||
dispatch(saveFolderRoot(collection.uid, folder.uid));
|
||||
};
|
||||
|
||||
const updateFolderAuth = ({ itemUid, ...rest }) => {
|
||||
return _updateFolderAuth({
|
||||
...rest,
|
||||
folderUid: folder.uid
|
||||
});
|
||||
};
|
||||
|
||||
const getAuthView = () => {
|
||||
switch (authMode) {
|
||||
case 'basic': {
|
||||
@@ -178,7 +185,7 @@ const Auth = ({ collection, folder }) => {
|
||||
collection={collection}
|
||||
item={folder}
|
||||
/>
|
||||
<GrantTypeComponentMap collection={collection} folder={folder} />
|
||||
<GrantTypeComponentMap collection={collection} folder={folder} updateFolderAuth={updateFolderAuth} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const StyledWrapper = styled.div`
|
||||
background: transparent;
|
||||
|
||||
.auth-mode-label {
|
||||
color: ${(props) => props.theme.brand};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
|
||||
.caret {
|
||||
color: rgb(140, 140, 140);
|
||||
|
||||
@@ -38,7 +38,7 @@ const Documentation = ({ collection, folder }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-1 w-full relative flex flex-col">
|
||||
<StyledWrapper className="w-full relative flex flex-col">
|
||||
<div className="editing-mode flex justify-between items-center flex-shrink-0" role="tab" onClick={toggleViewMode}>
|
||||
{isEditing ? 'Preview' : 'Edit'}
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ const Script = ({ collection, folder }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full flex flex-col h-full pt-4">
|
||||
<StyledWrapper className="w-full flex flex-col h-full">
|
||||
<div className="text-xs mb-4 text-muted">
|
||||
Pre and post-request scripts that will run before and after any request inside this folder is sent.
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,10 @@ const StyledWrapper = styled.div`
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: ${(props) => props.theme.tabs.active.fontWeight} !important;
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
|
||||
@@ -14,11 +14,11 @@ const Vars = ({ collection, folder }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full flex flex-col">
|
||||
<div className="flex-1 mt-2">
|
||||
<div>
|
||||
<div className="mb-3 title text-xs">Pre Request</div>
|
||||
<VarsTable folder={folder} collection={collection} vars={requestVars} varType="request" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div>
|
||||
<div className="mt-3 mb-3 title text-xs">Post Response</div>
|
||||
<VarsTable folder={folder} collection={collection} vars={responseVars} varType="response" />
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ const RenameWorkspace = ({ onClose, workspace }) => {
|
||||
return (
|
||||
<Portal>
|
||||
<Modal
|
||||
size="sm"
|
||||
size="md"
|
||||
title="Rename Workspace"
|
||||
confirmText="Rename"
|
||||
handleConfirm={onSubmit}
|
||||
|
||||
@@ -14,6 +14,7 @@ import DeleteWorkspace from './DeleteWorkspace';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import MenuDropdown from 'ui/MenuDropdown/index';
|
||||
import Button from 'ui/Button';
|
||||
import { getRevealInFolderLabel } from 'utils/common/platform';
|
||||
|
||||
const ManageWorkspace = () => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -133,7 +134,7 @@ const ManageWorkspace = () => {
|
||||
onClick={() => handleShowInFolder(workspace)}
|
||||
>
|
||||
<IconFolder size={14} strokeWidth={1.5} />
|
||||
<span>Show in folder</span>
|
||||
<span>{getRevealInFolderLabel()}</span>
|
||||
</button>
|
||||
)}
|
||||
{!isDefault && (
|
||||
|
||||
@@ -127,6 +127,15 @@ const Wrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
select.textbox {
|
||||
appearance: none;
|
||||
padding-right: 30px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 0.5rem center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bruno-form {
|
||||
color: ${(props) => props.theme.modal.body.color};
|
||||
}
|
||||
@@ -167,6 +176,16 @@ const Wrapper = styled.div`
|
||||
border-bottom-right-radius: ${(props) => props.theme.border.radius.base};
|
||||
}
|
||||
}
|
||||
|
||||
input[type='radio'] {
|
||||
cursor: pointer;
|
||||
accent-color: ${(props) => props.theme.primary.solid};
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
cursor: pointer;
|
||||
accent-color: ${(props) => props.theme.primary.solid};
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
|
||||
@@ -96,9 +96,8 @@ const Modal = ({
|
||||
return closeModal({ type: 'esc' });
|
||||
}
|
||||
case ENTER_KEY_CODE: {
|
||||
// Skip if a submit button is focused - let native button click handle it to avoid double-fire
|
||||
const isSubmitButton = event.target?.type === 'submit';
|
||||
if (!shiftKey && !ctrlKey && !altKey && !metaKey && handleConfirm && !isSubmitButton) {
|
||||
if (!shiftKey && !ctrlKey && !altKey && !metaKey && handleConfirm && !isSubmitButton && !confirmDisabled) {
|
||||
return handleConfirm();
|
||||
}
|
||||
}
|
||||
@@ -117,7 +116,7 @@ const Modal = ({
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeydown);
|
||||
};
|
||||
}, [disableEscapeKey, document, handleConfirm]);
|
||||
}, [disableEscapeKey, document, handleConfirm, confirmDisabled]);
|
||||
|
||||
let classes = 'bruno-modal';
|
||||
if (isClosing) {
|
||||
|
||||
@@ -367,6 +367,7 @@ const General = ({ close }) => {
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
readOnly={true}
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.defaultCollectionLocation || ''}
|
||||
onClick={browseDefaultLocation}
|
||||
|
||||
@@ -61,7 +61,7 @@ const ApiKeyAuth = ({ item, collection, updateAuth, request, save }) => {
|
||||
}, [apikeyAuth]);
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-2 w-full">
|
||||
<StyledWrapper className="w-full">
|
||||
<label className="block mb-1">Key</label>
|
||||
<div className="single-line-editor-wrapper mb-3">
|
||||
<SingleLineEditor
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
background: transparent;
|
||||
|
||||
.auth-mode-label {
|
||||
color: ${(props) => props.theme.brand};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
|
||||
.caret {
|
||||
color: rgb(140, 140, 140);
|
||||
|
||||
@@ -52,7 +52,7 @@ const BasicAuth = ({ item, collection, updateAuth, request, save }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-2 w-full">
|
||||
<StyledWrapper className="w-full">
|
||||
<label className="block mb-1">Username</label>
|
||||
<div className="single-line-editor-wrapper mb-3">
|
||||
<SingleLineEditor
|
||||
|
||||
@@ -38,7 +38,7 @@ const BearerAuth = ({ item, collection, updateAuth, request, save }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-2 w-full">
|
||||
<StyledWrapper className="w-full">
|
||||
<label className="block mb-1">Token</label>
|
||||
<div className="single-line-editor-wrapper flex items-center">
|
||||
<SingleLineEditor
|
||||
|
||||
@@ -19,18 +19,18 @@ const StyledWrapper = styled.div`
|
||||
border: none !important;
|
||||
border-bottom: none !important;
|
||||
margin-right: 0;
|
||||
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props) => rgba(props.theme.primary.solid, 0.1)};
|
||||
}
|
||||
|
||||
|
||||
&.active {
|
||||
background-color: ${(props) => {
|
||||
return props.theme.mode === 'dark'
|
||||
? rgba(props.theme.primary.solid, 0.2)
|
||||
: rgba(props.theme.primary.solid, 0.1);
|
||||
}};
|
||||
color: ${(props) => props.theme.primary.solid} !important;
|
||||
color: ${(props) => props.theme.primary.text} !important;
|
||||
border-bottom: none !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ const StyledWrapper = styled.div`
|
||||
padding: 6px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.additional-parameter-sends-in-selector {
|
||||
select {
|
||||
height: 32px;
|
||||
@@ -65,14 +65,14 @@ const StyledWrapper = styled.div`
|
||||
border: 1px solid ${(props) => props.theme.input.border};
|
||||
border-radius: 4px;
|
||||
padding: 0 8px;
|
||||
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: ${(props) => props.theme.primary.solid};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.add-additional-param-actions {
|
||||
&:hover {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.oauth2-icon {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
label {
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.oauth2-icon {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
label {
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.oauth2-icon {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
font-size: ${(props) => props.theme.font.size.base};
|
||||
@@ -38,7 +38,7 @@ const Wrapper = styled.div`
|
||||
|
||||
.grant-type-label {
|
||||
width: fit-content;
|
||||
color: ${(props) => props.theme.brand};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
justify-content: space-between;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ const GrantTypeSelector = ({ item = {}, request, updateAuth, collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="flex items-center gap-2.5 my-4">
|
||||
<div className="flex items-center gap-2.5 mb-4">
|
||||
<div className="flex items-center px-2.5 py-1.5 oauth2-icon-container rounded-md">
|
||||
<IconKey size={14} className="oauth2-icon" />
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.oauth2-icon {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
label {
|
||||
@@ -62,7 +62,7 @@ const Wrapper = styled.div`
|
||||
padding: 0.2rem 0.6rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.checkbox-label {
|
||||
color: ${(props) => props.theme.colors.text.primary};
|
||||
user-select: none;
|
||||
|
||||
@@ -133,7 +133,7 @@ const Oauth2ActionButtons = ({ item, request, collection, url: accessTokenUrl, c
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-row gap-4 mt-4">
|
||||
<div className="flex flex-row gap-2 mt-4">
|
||||
<Button
|
||||
size="sm"
|
||||
color="secondary"
|
||||
@@ -171,6 +171,7 @@ const Oauth2ActionButtons = ({ item, request, collection, url: accessTokenUrl, c
|
||||
<Button
|
||||
size="sm"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
onClick={handleClearCache}
|
||||
>
|
||||
Clear Cache
|
||||
|
||||
@@ -7,7 +7,7 @@ const Wrapper = styled.div`
|
||||
}
|
||||
|
||||
.oauth2-icon {
|
||||
color: ${(props) => props.theme.primary.solid};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
|
||||
label {
|
||||
|
||||
@@ -47,7 +47,7 @@ const OAuth2 = ({ item, collection }) => {
|
||||
let request = item.draft ? get(item, 'draft.request', {}) : get(item, 'request', {});
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-2 w-full">
|
||||
<StyledWrapper className="w-full">
|
||||
<GrantTypeSelector item={item} request={request} updateAuth={updateAuth} collection={collection} />
|
||||
<GrantTypeComponentMap item={item} collection={collection} />
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -2,7 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
.inherit-mode-text {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
.inherit-mode-label {
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const WsseAuth = ({ item, collection, updateAuth, request, save }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="mt-2 w-full">
|
||||
<StyledWrapper className="w-full">
|
||||
<label className="block mb-1">Username</label>
|
||||
<div className="single-line-editor-wrapper mb-3">
|
||||
<SingleLineEditor
|
||||
|
||||
@@ -103,7 +103,7 @@ const Auth = ({ item, collection }) => {
|
||||
const source = getEffectiveAuthSource();
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div className="flex flex-row w-full gap-2">
|
||||
<div>Auth inherited from {source.name}: </div>
|
||||
<div className="inherit-mode-text">{humanizeRequestAuthMode(source.auth?.mode)}</div>
|
||||
</div>
|
||||
@@ -114,7 +114,7 @@ const Auth = ({ item, collection }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full mt-1 overflow-auto">
|
||||
<StyledWrapper className="w-full overflow-auto">
|
||||
{getAuthView()}
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -20,8 +20,7 @@ import GraphQLSchemaActions from '../GraphQLSchemaActions/index';
|
||||
import HeightBoundContainer from 'ui/HeightBoundContainer';
|
||||
import Settings from 'components/RequestPane/Settings';
|
||||
import ResponsiveTabs from 'ui/ResponsiveTabs';
|
||||
|
||||
const MULTIPLE_CONTENT_TABS = new Set(['script', 'vars', 'auth', 'docs']);
|
||||
import AuthMode from '../Auth/AuthMode/index';
|
||||
|
||||
const TAB_CONFIG = [
|
||||
{ key: 'query', label: 'Query' },
|
||||
@@ -136,13 +135,15 @@ const GraphQLRequestPane = ({ item, collection, onSchemaLoad, toggleDocs, handle
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
|
||||
const isMultipleContentTab = MULTIPLE_CONTENT_TABS.has(requestPaneTab);
|
||||
|
||||
const rightContent = (
|
||||
const rightContent = requestPaneTab === 'auth' ? (
|
||||
<div ref={schemaActionsRef} className="flex flex-grow justify-start items-center">
|
||||
<AuthMode item={item} collection={collection} />
|
||||
</div>
|
||||
) : requestPaneTab === 'query' ? (
|
||||
<div ref={schemaActionsRef}>
|
||||
<GraphQLSchemaActions item={item} collection={collection} onSchemaLoad={setSchema} toggleDocs={toggleDocs} />
|
||||
</div>
|
||||
);
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full relative">
|
||||
@@ -151,10 +152,10 @@ const GraphQLRequestPane = ({ item, collection, onSchemaLoad, toggleDocs, handle
|
||||
activeTab={requestPaneTab}
|
||||
onTabSelect={selectTab}
|
||||
rightContent={rightContent}
|
||||
rightContentRef={schemaActionsRef}
|
||||
rightContentRef={rightContent ? schemaActionsRef : null}
|
||||
/>
|
||||
|
||||
<section className={classnames('flex w-full flex-1', { 'mt-5': !isMultipleContentTab })}>
|
||||
<section className={classnames('flex w-full flex-1 mt-4')}>
|
||||
<HeightBoundContainer>{tabPanel}</HeightBoundContainer>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -50,6 +50,7 @@ const Wrapper = styled.div`
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
padding: 4px 0px;
|
||||
padding-top: 0px;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.method-dropdown-trigger {
|
||||
|
||||
@@ -60,7 +60,7 @@ const StyledWrapper = styled.div`
|
||||
|
||||
.proto-file-dropdown-reflection-message {
|
||||
padding: 0.5rem 0.75rem;
|
||||
color: ${(props) => props.theme.overlay.overlay1};
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -150,7 +150,7 @@ const ProtoFileDropdown = ({
|
||||
<div className="proto-file-dropdown-mode-controls">
|
||||
<span>Mode</span>
|
||||
<div className="proto-file-dropdown-mode-options">
|
||||
<span className={`proto-file-dropdown-mode-option ${!isReflectionMode ? 'proto-file-dropdown-mode-option--active' : ''}`} style={{ color: !isReflectionMode ? theme.primary.solid : undefined }}>
|
||||
<span className={`proto-file-dropdown-mode-option ${!isReflectionMode ? 'proto-file-dropdown-mode-option--active' : ''}`} style={{ color: !isReflectionMode ? theme.primary.text : undefined }}>
|
||||
Proto File
|
||||
</span>
|
||||
<ToggleSwitch
|
||||
@@ -159,7 +159,7 @@ const ProtoFileDropdown = ({
|
||||
size="2xs"
|
||||
activeColor={theme.primary.solid}
|
||||
/>
|
||||
<span className={`proto-file-dropdown-mode-option ${isReflectionMode ? 'proto-file-dropdown-mode-option--active' : ''}`} style={{ color: isReflectionMode ? theme.primary.solid : undefined }}>
|
||||
<span className={`proto-file-dropdown-mode-option ${isReflectionMode ? 'proto-file-dropdown-mode-option--active' : ''}`} style={{ color: isReflectionMode ? theme.primary.text : undefined }}>
|
||||
Reflection
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -296,11 +296,11 @@ const GrpcQueryUrl = ({ item, collection, handleRun }) => {
|
||||
return (
|
||||
<StyledWrapper className="flex items-center relative" data-testid="grpc-query-url-container">
|
||||
<div className="flex items-center h-full method-selector-container">
|
||||
<div className="flex items-center justify-center h-full w-16" data-testid="grpc-method-indicator">
|
||||
<span className="text-xs font-bold" style={{ color: theme.request.grpc }}>gRPC</span>
|
||||
<div className="flex items-center justify-center h-full px-[10px]" data-testid="grpc-method-indicator">
|
||||
<span className="text-xs font-medium" style={{ color: theme.request.grpc }}>gRPC</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center w-full input-container h-full relative">
|
||||
<div className="flex items-center w-full input-container h-full relative overflow-auto">
|
||||
<SingleLineEditor
|
||||
ref={editorRef}
|
||||
value={url}
|
||||
@@ -313,117 +313,118 @@ const GrpcQueryUrl = ({ item, collection, handleRun }) => {
|
||||
item={item}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex items-center h-full mx-2 gap-3" id="send-request">
|
||||
<MethodDropdown
|
||||
grpcMethods={grpcMethods}
|
||||
selectedGrpcMethod={selectedGrpcMethod}
|
||||
onMethodSelect={handleGrpcMethodSelect}
|
||||
onMethodDropdownCreate={onMethodDropdownCreate}
|
||||
/>
|
||||
<div className="flex items-center h-full mr-2 gap-3" id="send-request">
|
||||
<ProtoFileDropdown
|
||||
collection={collection}
|
||||
item={item}
|
||||
isReflectionMode={isReflectionMode}
|
||||
protoFilePath={protoFilePath}
|
||||
showProtoDropdown={showProtoDropdown}
|
||||
setShowProtoDropdown={setShowProtoDropdown}
|
||||
onProtoDropdownCreate={onProtoDropdownCreate}
|
||||
onReflectionModeToggle={handleReflectionModeToggle}
|
||||
onProtoFileLoad={handleProtoFileLoad}
|
||||
<ProtoFileDropdown
|
||||
collection={collection}
|
||||
item={item}
|
||||
isReflectionMode={isReflectionMode}
|
||||
protoFilePath={protoFilePath}
|
||||
showProtoDropdown={showProtoDropdown}
|
||||
setShowProtoDropdown={setShowProtoDropdown}
|
||||
onProtoDropdownCreate={onProtoDropdownCreate}
|
||||
onReflectionModeToggle={handleReflectionModeToggle}
|
||||
onProtoFileLoad={handleProtoFileLoad}
|
||||
/>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (isReflectionMode) {
|
||||
handleReflection(url, true);
|
||||
} else if (protoFilePath) {
|
||||
handleProtoFileLoad(protoFilePath, true);
|
||||
} else {
|
||||
toast.error('No proto file selected');
|
||||
}
|
||||
}}
|
||||
>
|
||||
<IconRefresh
|
||||
color={theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
className={`${(isReflectionMode ? reflectionManagement.isLoadingMethods : protoFileManagement.isLoadingMethods) ? 'animate-spin' : 'cursor-pointer'}`}
|
||||
data-testid="refresh-methods-icon"
|
||||
/>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (isReflectionMode) {
|
||||
handleReflection(url, true);
|
||||
} else if (protoFilePath) {
|
||||
handleProtoFileLoad(protoFilePath, true);
|
||||
} else {
|
||||
toast.error('No proto file selected');
|
||||
}
|
||||
}}
|
||||
>
|
||||
<IconRefresh
|
||||
color={theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
className={`${(isReflectionMode ? reflectionManagement.isLoadingMethods : protoFileManagement.isLoadingMethods) ? 'animate-spin' : 'cursor-pointer'}`}
|
||||
data-testid="refresh-methods-icon"
|
||||
/>
|
||||
<span className="infotip-text text-xs">
|
||||
{isReflectionMode ? 'Refresh server reflection' : 'Refresh proto file methods'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleGrpcurl(url);
|
||||
}}
|
||||
>
|
||||
<IconCode
|
||||
color={theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
/>
|
||||
<span className="infotip-text text-xs">Generate grpcurl command</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (!item.draft) return;
|
||||
onSave();
|
||||
}}
|
||||
>
|
||||
<IconDeviceFloppy
|
||||
color={item.draft ? theme.colors.text.yellow : theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
className={`${item.draft ? 'cursor-pointer' : 'cursor-default'}`}
|
||||
/>
|
||||
<span className="infotip-text text-xs">
|
||||
Save <span className="shortcut">({saveShortcut})</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{isConnectionActive && isStreamingMethod && (
|
||||
<div className="connection-controls relative flex items-center h-full gap-3">
|
||||
<div className="infotip" onClick={handleCancelConnection} data-testid="grpc-cancel-connection-button">
|
||||
<IconX color={theme.requestTabs.icon.color} strokeWidth={1.5} size={20} className="cursor-pointer" />
|
||||
<span className="infotip-text text-xs">Cancel</span>
|
||||
</div>
|
||||
|
||||
{isClientStreamingMethod && (
|
||||
<div onClick={handleEndConnection} data-testid="grpc-end-connection-button">
|
||||
<IconCheck
|
||||
color={theme.colors.text.green}
|
||||
strokeWidth={2}
|
||||
size={20}
|
||||
className="cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(!isConnectionActive || !isStreamingMethod) && (
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
data-testid="grpc-send-request-button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleRun(e);
|
||||
}}
|
||||
>
|
||||
<IconArrowRight color={theme.requestTabPanel.url.icon} strokeWidth={1.5} size={20} />
|
||||
</div>
|
||||
)}
|
||||
<span className="infotip-text text-xs">
|
||||
{isReflectionMode ? 'Refresh server reflection' : 'Refresh proto file methods'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleGrpcurl(url);
|
||||
}}
|
||||
>
|
||||
<IconCode
|
||||
color={theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
/>
|
||||
<span className="infotip-text text-xs">Generate grpcurl command</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="infotip"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (!item.draft) return;
|
||||
onSave();
|
||||
}}
|
||||
>
|
||||
<IconDeviceFloppy
|
||||
color={item.draft ? theme.draftColor : theme.requestTabs.icon.color}
|
||||
strokeWidth={1.5}
|
||||
size={20}
|
||||
className={`${item.draft ? 'cursor-pointer' : 'cursor-default'}`}
|
||||
/>
|
||||
<span className="infotip-text text-xs">
|
||||
Save <span className="shortcut">({saveShortcut})</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{isConnectionActive && isStreamingMethod && (
|
||||
<div className="connection-controls relative flex items-center h-full gap-3">
|
||||
<div className="infotip" onClick={handleCancelConnection} data-testid="grpc-cancel-connection-button">
|
||||
<IconX color={theme.requestTabs.icon.color} strokeWidth={1.5} size={20} className="cursor-pointer" />
|
||||
<span className="infotip-text text-xs">Cancel</span>
|
||||
</div>
|
||||
|
||||
{isClientStreamingMethod && (
|
||||
<div onClick={handleEndConnection} data-testid="grpc-end-connection-button">
|
||||
<IconCheck
|
||||
color={theme.colors.text.green}
|
||||
strokeWidth={2}
|
||||
size={20}
|
||||
className="cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(!isConnectionActive || !isStreamingMethod) && (
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
data-testid="grpc-send-request-button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleRun(e);
|
||||
}}
|
||||
>
|
||||
<IconArrowRight color={theme.requestTabPanel.url.icon} strokeWidth={1.5} size={20} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{isConnectionActive && isStreamingMethod && (
|
||||
<div className="connection-status-strip"></div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
.inherit-mode-text {
|
||||
color: ${(props) => props.theme.colors.text.yellow};
|
||||
color: ${(props) => props.theme.primary.text};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ const GrpcAuth = ({ item, collection }) => {
|
||||
|
||||
const getAuthView = () => {
|
||||
switch (authMode) {
|
||||
case 'none': {
|
||||
return <div>No Auth</div>;
|
||||
}
|
||||
case 'basic': {
|
||||
return <BasicAuth collection={collection} item={item} updateAuth={updateAuth} request={request} save={save} />;
|
||||
}
|
||||
@@ -98,7 +101,7 @@ const GrpcAuth = ({ item, collection }) => {
|
||||
if (source && supportedGrpcAuthModes.includes(source.auth?.mode)) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div className="flex flex-row w-full gap-2">
|
||||
<div>Auth inherited from {source.name}: </div>
|
||||
<div className="inherit-mode-text">{humanizeRequestAuthMode(source.auth?.mode)}</div>
|
||||
</div>
|
||||
@@ -107,7 +110,7 @@ const GrpcAuth = ({ item, collection }) => {
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row w-full mt-2 gap-2">
|
||||
<div className="flex flex-row w-full gap-2">
|
||||
<div>Inherited auth not supported by gRPC. Using no auth instead.</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -121,10 +124,7 @@ const GrpcAuth = ({ item, collection }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full mt-1 overflow-y-scroll">
|
||||
<div className="flex flex-grow justify-start items-center">
|
||||
<GrpcAuthMode item={item} collection={collection} />
|
||||
</div>
|
||||
<StyledWrapper className="w-full overflow-y-scroll">
|
||||
{getAuthView()}
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -1,35 +1,6 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
div.tabs {
|
||||
div.tab {
|
||||
padding: 6px 0px;
|
||||
border: none;
|
||||
border-bottom: solid 2px transparent;
|
||||
margin-right: ${(props) => props.theme.tabs.marginRight};
|
||||
color: ${(props) => props.theme.colors.text.subtext0};
|
||||
cursor: pointer;
|
||||
|
||||
&:focus,
|
||||
&:active,
|
||||
&:focus-within,
|
||||
&:focus-visible,
|
||||
&:target {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: ${(props) => props.theme.tabs.active.fontWeight} !important;
|
||||
color: ${(props) => props.theme.tabs.active.color} !important;
|
||||
border-bottom: solid 2px ${(props) => props.theme.tabs.active.border} !important;
|
||||
}
|
||||
|
||||
.content-indicator {
|
||||
color: ${(props) => props.theme.text}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import React, { useMemo, useCallback, useEffect, useRef } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { updateRequestPaneTab } from 'providers/ReduxStore/slices/tabs';
|
||||
import RequestHeaders from 'components/RequestPane/RequestHeaders';
|
||||
import GrpcBody from 'components/RequestPane/GrpcBody';
|
||||
import GrpcAuth from './GrpcAuth/index';
|
||||
import GrpcAuthMode from './GrpcAuth/GrpcAuthMode/index';
|
||||
import StatusDot from 'components/StatusDot/index';
|
||||
import HeightBoundContainer from 'ui/HeightBoundContainer';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import { find, get } from 'lodash';
|
||||
import find from 'lodash/find';
|
||||
import Documentation from 'components/Documentation/index';
|
||||
import { useEffect } from 'react';
|
||||
import { getPropertyFromDraftOrRequest } from 'utils/collections/index';
|
||||
import ResponsiveTabs from 'ui/ResponsiveTabs';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const GrpcRequestPane = ({ item, collection, handleRun }) => {
|
||||
const dispatch = useDispatch();
|
||||
const tabs = useSelector((state) => state.tabs.tabs);
|
||||
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
|
||||
const rightContentRef = useRef(null);
|
||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||
const requestPaneTab = focusedTab?.requestPaneTab;
|
||||
|
||||
const selectTab = (tab) => {
|
||||
const selectTab = useCallback((tab) => {
|
||||
dispatch(
|
||||
updateRequestPaneTab({
|
||||
uid: item.uid,
|
||||
requestPaneTab: tab
|
||||
})
|
||||
);
|
||||
};
|
||||
}, [dispatch, item.uid]);
|
||||
|
||||
const getTabPanel = (tab) => {
|
||||
switch (tab) {
|
||||
const tabPanel = useMemo(() => {
|
||||
switch (requestPaneTab) {
|
||||
case 'body': {
|
||||
return <GrpcBody item={item} collection={collection} hideModeSelector={true} hidePrettifyButton={true} handleRun={handleRun} />;
|
||||
}
|
||||
@@ -45,24 +48,8 @@ const GrpcRequestPane = ({ item, collection, handleRun }) => {
|
||||
return <div className="mt-4">404 | Not found</div>;
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [requestPaneTab, item, collection, handleRun]);
|
||||
|
||||
if (!activeTabUid) {
|
||||
return <div>Something went wrong</div>;
|
||||
}
|
||||
|
||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||
if (!focusedTab || !focusedTab.uid || !focusedTab.requestPaneTab) {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
|
||||
const getTabClassname = (tabName) => {
|
||||
return classnames(`tab select-none ${tabName}`, {
|
||||
active: tabName === focusedTab.requestPaneTab
|
||||
});
|
||||
};
|
||||
|
||||
const isMultipleContentTab = ['script', 'vars', 'auth', 'docs'].includes(focusedTab.requestPaneTab);
|
||||
const body = getPropertyFromDraftOrRequest(item, 'request.body');
|
||||
const headers = getPropertyFromDraftOrRequest(item, 'request.headers');
|
||||
const docs = getPropertyFromDraftOrRequest(item, 'request.docs');
|
||||
@@ -75,46 +62,80 @@ const GrpcRequestPane = ({ item, collection, handleRun }) => {
|
||||
const request = item.draft ? item.draft.request : item.request;
|
||||
const isClientStreaming = request.methodType === 'client-streaming' || request.methodType === 'bidi-streaming';
|
||||
|
||||
const allTabs = useMemo(() => {
|
||||
const getMessageIndicator = () => {
|
||||
if (grpcMessagesCount > 0) {
|
||||
return isClientStreaming ? (
|
||||
<sup className="ml-[.125rem] font-medium">{grpcMessagesCount}</sup>
|
||||
) : (
|
||||
<StatusDot />
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
key: 'body',
|
||||
label: 'Message',
|
||||
indicator: getMessageIndicator()
|
||||
},
|
||||
{
|
||||
key: 'headers',
|
||||
label: 'Metadata',
|
||||
indicator: activeHeadersLength > 0 ? <sup className="ml-[.125rem] font-medium">{activeHeadersLength}</sup> : null
|
||||
},
|
||||
{
|
||||
key: 'auth',
|
||||
label: 'Auth',
|
||||
indicator: auth?.mode && auth.mode !== 'none' ? <StatusDot type="default" /> : null
|
||||
},
|
||||
{
|
||||
key: 'docs',
|
||||
label: 'Docs',
|
||||
indicator: docs && docs.length > 0 ? <StatusDot type="default" /> : null
|
||||
}
|
||||
];
|
||||
}, [grpcMessagesCount, isClientStreaming, activeHeadersLength, auth?.mode, docs]);
|
||||
|
||||
// Initialize tab to 'body' if no tab is currently set
|
||||
useEffect(() => {
|
||||
// Only set the tab to 'body' if no tab is currently set
|
||||
if (!focusedTab?.requestPaneTab) {
|
||||
if (activeTabUid && focusedTab?.uid && !requestPaneTab) {
|
||||
selectTab('body');
|
||||
}
|
||||
}, []);
|
||||
}, [activeTabUid, focusedTab?.uid, requestPaneTab, selectTab]);
|
||||
|
||||
// Return error for truly missing active/focused tabs
|
||||
if (!activeTabUid || !focusedTab?.uid) {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
|
||||
// Return null during initialization while requestPaneTab is being set by useEffect
|
||||
if (!requestPaneTab) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rightContent = requestPaneTab === 'auth' ? (
|
||||
<div ref={rightContentRef} className="flex flex-grow justify-start items-center">
|
||||
<GrpcAuthMode item={item} collection={collection} />
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex flex-col h-full relative">
|
||||
<div className="flex flex-wrap items-center tabs" role="tablist">
|
||||
<div className={getTabClassname('body')} role="tab" onClick={() => selectTab('body')}>
|
||||
Message
|
||||
{grpcMessagesCount > 0 && (
|
||||
isClientStreaming ? (
|
||||
<sup className="ml-[.125rem] font-medium">{grpcMessagesCount}</sup>
|
||||
) : (
|
||||
<StatusDot />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className={getTabClassname('headers')} role="tab" onClick={() => selectTab('headers')}>
|
||||
Metadata
|
||||
{activeHeadersLength > 0 && <sup className="ml-[.125rem] font-medium">{activeHeadersLength}</sup>}
|
||||
</div>
|
||||
<div className={getTabClassname('auth')} role="tab" onClick={() => selectTab('auth')}>
|
||||
Auth
|
||||
{auth.mode !== 'none' && <StatusDot type="default" />}
|
||||
</div>
|
||||
<div className={getTabClassname('docs')} role="tab" onClick={() => selectTab('docs')}>
|
||||
Docs
|
||||
{docs && docs.length > 0 && <StatusDot type="default" />}
|
||||
</div>
|
||||
</div>
|
||||
<ResponsiveTabs
|
||||
tabs={allTabs}
|
||||
activeTab={requestPaneTab}
|
||||
onTabSelect={selectTab}
|
||||
rightContent={rightContent}
|
||||
rightContentRef={rightContent ? rightContentRef : null}
|
||||
/>
|
||||
|
||||
<section
|
||||
className={classnames('flex w-full flex-1 h-full', {
|
||||
'mt-2': !isMultipleContentTab
|
||||
})}
|
||||
className="flex w-full flex-1 h-full mt-4"
|
||||
>
|
||||
<HeightBoundContainer>
|
||||
{getTabPanel(focusedTab.requestPaneTab)}
|
||||
{tabPanel}
|
||||
</HeightBoundContainer>
|
||||
</section>
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -19,8 +19,6 @@ import ResponsiveTabs from 'ui/ResponsiveTabs';
|
||||
import HeightBoundContainer from 'ui/HeightBoundContainer';
|
||||
import AuthMode from '../Auth/AuthMode/index';
|
||||
|
||||
const MULTIPLE_CONTENT_TABS = new Set(['params', 'script', 'vars', 'auth', 'docs']);
|
||||
|
||||
const TAB_CONFIG = [
|
||||
{ key: 'params', label: 'Params' },
|
||||
{ key: 'body', label: 'Body' },
|
||||
@@ -120,8 +118,6 @@ const HttpRequestPane = ({ item, collection }) => {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
|
||||
const isMultipleContentTab = MULTIPLE_CONTENT_TABS.has(requestPaneTab);
|
||||
|
||||
const rightContent = requestPaneTab === 'body' ? (
|
||||
<div ref={rightContentRef}>
|
||||
<RequestBodyMode item={item} collection={collection} />
|
||||
@@ -143,7 +139,7 @@ const HttpRequestPane = ({ item, collection }) => {
|
||||
delayedTabs={['body']}
|
||||
/>
|
||||
|
||||
<section className={classnames('flex w-full flex-1', { 'mt-3': !isMultipleContentTab })}>
|
||||
<section className={classnames('flex w-full flex-1 mt-4')}>
|
||||
<HeightBoundContainer>{tabPanel}</HeightBoundContainer>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -22,46 +22,54 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.cm-s-monokai span.cm-property,
|
||||
.cm-s-monokai span.cm-attribute {
|
||||
color: #9cdcfe !important;
|
||||
}
|
||||
|
||||
.cm-s-monokai span.cm-property,
|
||||
.cm-s-monokai span.cm-attribute {
|
||||
color: #9cdcfe !important;
|
||||
}
|
||||
|
||||
.cm-s-monokai span.cm-string {
|
||||
color: #ce9178 !important;
|
||||
}
|
||||
|
||||
.cm-s-monokai span.cm-number {
|
||||
color: #b5cea8 !important;
|
||||
}
|
||||
|
||||
.cm-s-monokai span.cm-atom {
|
||||
color: #569cd6 !important;
|
||||
.cm-s-default, .cm-s-monokai {
|
||||
span.cm-def {
|
||||
color: ${(props) => props.theme.codemirror.tokens.definition} !important;
|
||||
}
|
||||
span.cm-property {
|
||||
color: ${(props) => props.theme.codemirror.tokens.property} !important;
|
||||
}
|
||||
span.cm-string {
|
||||
color: ${(props) => props.theme.codemirror.tokens.string} !important;
|
||||
}
|
||||
span.cm-number {
|
||||
color: ${(props) => props.theme.codemirror.tokens.number} !important;
|
||||
}
|
||||
span.cm-atom {
|
||||
color: ${(props) => props.theme.codemirror.tokens.atom} !important;
|
||||
}
|
||||
span.cm-variable, span.cm-variable-2 {
|
||||
color: ${(props) => props.theme.codemirror.tokens.variable} !important;
|
||||
}
|
||||
span.cm-keyword {
|
||||
color: ${(props) => props.theme.codemirror.tokens.keyword} !important;
|
||||
}
|
||||
span.cm-comment {
|
||||
color: ${(props) => props.theme.codemirror.tokens.comment} !important;
|
||||
}
|
||||
span.cm-operator {
|
||||
color: ${(props) => props.theme.codemirror.tokens.operator} !important;
|
||||
}
|
||||
span.cm-tag {
|
||||
color: ${(props) => props.theme.codemirror.tokens.tag} !important;
|
||||
}
|
||||
span.cm-tag.cm-bracket {
|
||||
color: ${(props) => props.theme.codemirror.tokens.tagBracket} !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Variable validation colors */
|
||||
.cm-variable-valid {
|
||||
color: green;
|
||||
color: ${(props) => props.theme.codemirror.variable.valid};
|
||||
}
|
||||
.cm-variable-invalid {
|
||||
color: red;
|
||||
color: ${(props) => props.theme.codemirror.variable.invalid};
|
||||
}
|
||||
|
||||
|
||||
.CodeMirror-search-hint {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.cm-s-default span.cm-property {
|
||||
color: #1f61a0 !important;
|
||||
}
|
||||
|
||||
.cm-s-default span.cm-variable {
|
||||
color: #397d13 !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -135,7 +135,7 @@ const QueryParams = ({ item, collection }) => {
|
||||
|
||||
return (
|
||||
<StyledWrapper className="w-full flex flex-col">
|
||||
<div className="flex-1 mt-2">
|
||||
<div className="flex-1">
|
||||
<div className="mb-3 title text-xs">Query</div>
|
||||
<EditableTable
|
||||
columns={queryColumns}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user