Compare commits

...

441 Commits

Author SHA1 Message Date
liyasthomas
def1b494f4 refactor: polish request section 2021-12-02 21:47:07 +05:30
liyasthomas
99b9ffd293 refactor: clean up boilerplate + init request section 2021-12-02 10:28:29 +05:30
liyasthomas
63005c01ce refactor: clean up boilerplate 2021-12-01 23:15:14 +05:30
liyasthomas
190a4c43ef refactor: clean up boilerplate 2021-11-30 18:52:28 +05:30
liyasthomas
c3fcc6e35d feat: init hoppscotch-embed package 2021-11-30 18:36:52 +05:30
Deepanshu Dhruw
520ac8ede5 fix: code generators (#1985)
Co-authored-by: liyasthomas <liyascthomas@gmail.com>
2021-11-30 07:46:45 +05:30
liyasthomas
2a59557851 chore(deps): bump 2021-11-29 06:19:32 +05:30
liyasthomas
4089bc288c chore: updated i18n translations 2021-11-29 06:14:52 +05:30
liyasthomas
1999819846 chore(deps): bump 2021-11-28 19:48:53 +05:30
liyasthomas
0bf856291c refactor: lint + minor ui fixes 2021-11-27 19:59:28 +05:30
liyasthomas
da8c446ad7 chore(deps): bump 2021-11-27 19:58:08 +05:30
liyasthomas
3614877964 fix: broken scroll to definition in graphql documentation 2021-11-26 07:22:06 +05:30
liyasthomas
85c8171aa8 refactor: use smart confirm modal instead of native confirm modal 2021-11-25 11:37:23 +05:30
liyasthomas
b58278d55e chore: hide scrollbar 2021-11-24 19:27:25 +05:30
liyasthomas
b398ed1e90 fix: improve readability on input placeholders - fixed #1974 2021-11-23 20:22:38 +05:30
liyasthomas
afa750e409 fix: validate empty endpoints before sending request - resolved #1968 2021-11-23 20:01:45 +05:30
liyasthomas
fdf12a24ed refactor: sort windi class names 2021-11-23 08:47:09 +05:30
liyasthomas
4c5ca1b31d Merge branch 'main' of https://github.com/hoppscotch/hoppscotch 2021-11-23 05:31:22 +05:30
liyasthomas
bcb9b97b6b Merge branch 'i18n' 2021-11-23 05:31:01 +05:30
Andrew Bastin
757294ae38 feat: bump dependencies 2021-11-22 19:34:23 +05:30
liyasthomas
8d4dd8c428 chore: better error message in invalid link 2021-11-22 16:31:10 +05:30
liyasthomas
508809eba1 chore: cleanup - remove writing request object to url 2021-11-22 15:02:29 +05:30
liyasthomas
d0386ef86f chore: cleanup 2021-11-22 14:52:14 +05:30
liyasthomas
56cdb79773 Merge branch 'main' into feat/short-code 2021-11-22 11:35:16 +05:30
liyasthomas
6ed4211004 feat: short code redirection 2021-11-22 11:26:43 +05:30
liyasthomas
222f0800d2 chore: better short code fetching 2021-11-22 08:26:22 +05:30
liyasthomas
12a9dd1058 feat: fetch, display and copy short code 2021-11-21 23:50:31 +05:30
Andrew Bastin
4a32fc6180 feat: mutations and queries for shortcode management 2021-11-21 20:02:09 +05:30
liyasthomas
1e08e7f73d chore(deps): bump 2021-11-21 19:47:06 +05:30
liyasthomas
8b05b063ff fix: minor ui improvements 2021-11-21 19:40:15 +05:30
SiderealArt
0bcfeb86ae chore(i18n): update tw translations (#1965) 2021-11-21 08:22:15 +05:30
liyasthomas
03a056b6c1 perf: updated issue templates 2021-11-20 22:43:19 +05:30
liyasthomas
d57e465806 fix: minor ui improvements 2021-11-20 08:28:38 +05:30
liyasthomas
5ab24d1439 docs: updated links + editor theme 2021-11-20 07:27:50 +05:30
liyasthomas
47661de974 refactor: composables for i18n and toast 2021-11-19 22:49:11 +05:30
liyasthomas
26429466e9 refactor: remove icons from toast 2021-11-19 21:13:58 +05:30
Andrew Bastin
cad8f3e856 refactor: add i18n composable 2021-11-19 21:06:04 +05:30
liyasthomas
1a4eb1fabe chore: handle short code states 2021-11-19 12:47:47 +05:30
Liyas Thomas
680f61b7dc docs: create security policy - skip ci 2021-11-19 11:07:26 +05:30
liyasthomas
f602a1e2d3 feat: loading indicator to fetch short code 2021-11-19 09:15:31 +05:30
liyasthomas
1572ff9e67 fix: regression in bulk mode to key-value pair translation 2021-11-19 08:52:58 +05:30
liyasthomas
fe7b236ad9 fix: enable native select on editor - fixed #1960 2021-11-18 18:26:48 +05:30
liyasthomas
3080af1ea5 refactor: migrate more components to setup script + fix a race condition with power search 2021-11-18 07:00:51 +05:30
liyasthomas
0f83c8b490 refactor: hightlight active only when editor is focused 2021-11-17 21:01:43 +05:30
liyasthomas
114c37645a refactor: convert to script setup 2021-11-17 19:59:32 +05:30
liyasthomas
8f9bb621b8 fix: parse mqtt pathname - fixed #1959 2021-11-17 17:43:04 +05:30
liyasthomas
48a6c87d9d refactor: convert to script setup 2021-11-17 17:25:18 +05:30
BrainCrumbz
f28b55dd4d chore(i18n): update it translations (#1958)
* i18n(it): review action group

* i18n(it): review 'add' and 'app' groups

* i18n(it): review auth, authorization and collection groups

* i18n(it): review confirm, count, documentation and empty groups

* i18n(it): review environment, error, export, folder, graphql and header groups

* i18n(it): review helpers, hide, import, layout, modal and mqtt groups

* i18n(it): review navigation, preRequest, profile and remove groups

* i18n(it): review request and response groups

* i18n(it): review settings group

* i18n(it): review shortcut and show group

* i18n(it): review socketio, sse, state and support group

* i18n(it): review tab and team groups

* i18n(it): review test and websocket groups
2021-11-17 15:55:39 +05:30
Sobolev Sergey
8a8b4b0245 chore(i18n): update ru translations (#1957) 2021-11-17 13:37:48 +05:30
liyasthomas
7d590ab966 feat: init short code ui 2021-11-17 02:36:40 +05:30
liyasthomas
0afbc57012 chore: remove absolute packages 2021-11-16 22:09:40 +05:30
Wilson G
c651f2440f feat: add undo when parameters and headers are deleted, resolves #1951 (#1955)
Co-authored-by: liyasthomas <liyascthomas@gmail.com>
2021-11-16 16:34:11 +05:30
Andrew Bastin
8c05084994 fix: issue with the request body from duplication being linked in memory fixes #1954 2021-11-16 15:37:19 +05:30
liyasthomas
6813be47f0 fix: append protocol if empty - resolved #1927 2021-11-16 09:25:25 +05:30
liyasthomas
30327e8d27 feat: scroll logs to the bottom on update 2021-11-16 08:09:44 +05:30
liyasthomas
8096ed300d feat: add authentication to MQTT - resolved #1772 2021-11-16 07:52:26 +05:30
liyasthomas
4a8efbf426 feat: better empty state illustratils in profile and error pages 2021-11-15 20:59:07 +05:30
liyasthomas
7a6d117a76 feat: checkbox component 2021-11-15 20:25:40 +05:30
Andrew Bastin
73568043f1 feat: remove broken test system in codemirror-lang-graphql 2021-11-15 17:03:04 +05:30
liyasthomas
76a3b35e9e Merge branch 'feat/codemirror-6' 2021-11-15 16:45:20 +05:30
liyasthomas
feb1991da3 fix: error on updating readonly editor 2021-11-15 16:43:10 +05:30
liyasthomas
2bee4342b8 chore: cleanup 2021-11-15 16:25:56 +05:30
Andrew Bastin
7e9fc486f2 feat: placeholder implementation 2021-11-15 16:22:54 +05:30
liyasthomas
1d99b79926 feat: style autocomplete tooltips in codemirror 2021-11-15 07:49:07 +05:30
liyasthomas
eb8347f942 chore(deps): bump 2021-11-14 20:16:40 +05:30
liyasthomas
d383b48916 chore: minor fixes and improvements 2021-11-14 20:15:24 +05:30
Andrew Bastin
e88c40db0a feat: graphql language improvements 2021-11-13 20:14:58 +05:30
liyasthomas
f228f37bb8 feat: configure interceptor when request fail 2021-11-13 08:37:43 +05:30
Andrew Bastin
503a54fc5e fix: fix graphql history sync issue 2021-11-12 22:01:42 +05:30
liyasthomas
48b21aa0bf chore(i18n): updated translations 2021-11-12 18:53:56 +05:30
Andrew Bastin
ca40cc5271 feat: fix reactivity issues in graphql 2021-11-12 17:54:34 +05:30
liyasthomas
1c641c6d11 Merge branch 'i18n' 2021-11-12 17:54:02 +05:30
liyasthomas
32b362f9cc chore(ui): minor ui improvements 2021-11-12 17:52:27 +05:30
liyasthomas
103ef8ee0d fix: remove basic-setup and drawSelection on codemirror instance to resolve ::selection property 2021-11-12 07:05:34 +05:30
Tony
4a6239e017 chore(i18n): update tw translations (#1944) 2021-11-12 05:24:26 +05:30
liyasthomas
1f637edd36 feat: better prompts on actions for team members without admin role 2021-11-11 21:43:45 +05:30
Andrew Bastin
25878b9bb1 fix: fix history not writing when formdata is present 2021-11-11 18:36:26 +05:30
liyasthomas
521a96bffb fix: respect url parameters before settings bulk editor value 2021-11-11 15:02:31 +05:30
liyasthomas
ead1f3954f chore: use i18n 'duplicate' instead of 'copy' 2021-11-10 19:53:44 +05:30
0xc0Der
0ac84b58e3 allow environment variables in request body. (#1942)
* feat: allow environment variables in request body

* chore(ui): minor ui improvements

* chore(deps): bump

* fix: track env vars changes

* feat: allow environment variables in request body

* refactor: better implementation

Co-authored-by: liyasthomas <liyascthomas@gmail.com>
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-11-10 19:52:11 +05:30
0xc0Der
a2f1e37ad2 refactor: added space 2021-11-10 19:09:40 +05:30
Andrew Bastin
373343fea1 refactor: adding space between the copy hyphen 2021-11-10 19:09:40 +05:30
0xc0Der
2ef99026e5 fix: added '-Copy' to duplicated request name 2021-11-10 19:09:40 +05:30
0xc0Der
29aff9accc feat: duplicate request 2021-11-10 19:09:40 +05:30
Andrew Bastin
7d7f628f6e fix: compiling issues for codemirror-lang-graphql 2021-11-10 17:09:44 +05:30
liyasthomas
8f6cf07e82 feat: more syntax hightlight colors 2021-11-10 16:27:12 +05:30
Andrew Bastin
245b8a6e3c fix: compiling issues for codemirror-lang-graphql 2021-11-10 14:31:00 +05:30
liyasthomas
a967100be8 feat: more syntax hightlight colors 2021-11-10 13:53:10 +05:30
Andrew Bastin
a9bca8e1f8 feat: initial graphql language definition 2021-11-10 01:16:08 +05:30
liyasthomas
7de8e6be5e refactor: updated editot theme colors 2021-11-09 22:26:53 +05:30
liyasthomas
6b70a39f02 feat: css variable on themes 2021-11-09 22:05:39 +05:30
liyasthomas
d538d722d7 fix: light theme 2021-11-09 20:28:10 +05:30
liyasthomas
13bd831c5f refactor: init codemirror theming support 2021-11-09 18:46:29 +05:30
Andrew Bastin
9b297ba882 feat: implement reactive theming 2021-11-09 14:35:20 +05:30
liyasthomas
be6c802745 feat: init base theme for codemirror 2021-11-08 17:42:34 +05:30
Andrew Bastin
564cce2462 feat: autocomplete cm6 2021-11-08 16:33:36 +05:30
Andrew Bastin
8f166b8b3f feat: add linting cm6 2021-11-08 15:21:09 +05:30
Andrew Bastin
fe7192ae61 feat: add line wrapping 2021-11-08 14:32:17 +05:30
Liyas Thomas
6d54f21c1e docs: update CODE OF CONDUCT 2021-11-08 13:49:12 +05:30
liyasthomas
87f8f61163 chore(deps): bump 2021-11-07 20:38:15 +05:30
liyasthomas
510ba376e5 chore(ui): minor ui improvements 2021-11-07 11:46:21 +05:30
liyasthomas
40c88b3e35 refactor(ui): better spacing and font-weight 2021-11-06 21:15:28 +05:30
Andrew Bastin
7c65da4cf3 feat: cm 6 json mode + readonly + cursor update 2021-11-06 15:12:35 +05:30
Andrew Bastin
0f07c47e9f fix: race condition on gql client subscription client 2021-11-05 20:22:46 +05:30
liyasthomas
17c45fee11 refactor: migrate icons to lucide.dev 2021-11-05 18:24:16 +05:30
liyasthomas
a63c0817cc perf: remove console (log, debug, and warn) messages 2021-11-05 13:41:25 +05:30
Andrew Bastin
68aa54bdb7 fix: json parsing error when using extension (HOPP-110) 2021-11-05 13:32:27 +05:30
Satoshi Jek
41cb6eb190 i18n: Update Chinese translations (#1940) 2021-11-05 10:46:03 +05:30
liyasthomas
61e5a48b02 perf: improve native image tags 2021-11-05 09:13:04 +05:30
Iagor Moraes
9e4d7df7d0 fix: 100% HTML preview area size (#1938) 2021-11-05 06:25:50 +05:30
Andrew Bastin
e83dbc2e5c feat: early codemirror v6 implementation 2021-11-05 00:33:15 +05:30
liyasthomas
03ab6a208d perf: remove absolute files 2021-11-04 23:23:46 +05:30
liyasthomas
dbd39ba0d8 fix: ignore vue files from stylelint 2021-11-04 20:59:01 +05:30
0xc0Der
136b1ff63b fix: bind key-value with bulk editor at startup. (#1936) 2021-11-04 20:43:21 +05:30
Andrew Bastin
69a6207a4d refactor: move firebase initialization to a plugin 2021-11-04 18:59:35 +05:30
liyasthomas
9e74a8c2e7 chore: lint + bump deps 2021-11-04 18:23:50 +05:30
liyasthomas
ad76d100ee feat: bind key-value pairs and bulk editor 2021-11-04 13:36:51 +05:30
0xc0Der
235968073a sync request params with bulk editor. (#1930) 2021-11-04 13:01:56 +05:30
Andrew Bastin
ad7b8da37e fix: windows issues with sandbox not building initially 2021-11-04 12:47:09 +05:30
liyasthomas
7d3e1a700f chore(release): v2.1.0 2021-11-04 11:14:50 +05:30
liyasthomas
d3a1898dad feat: support to move sidebar to left - fixed #1933 2021-11-04 09:58:15 +05:30
Andrew Bastin
45e508fc36 refactor: pwa install prompt (#1932) 2021-11-03 23:44:01 +05:30
0xc0Der
8edad7ded7 persist environment selection. (#1925)
* feat: persist environment selection

* refactor: minor change to selectedEnvIndex calculation

Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-11-03 23:15:52 +05:30
liyasthomas
75e1adb7b3 refactor: empty state illustrations 2021-11-03 16:10:06 +05:30
Andrew Bastin
22ac13f2f0 fix: docker action issues 2021-11-02 21:22:37 +05:30
liyasthomas
7f0246eb47 Merge branch 'refactor/backend' of https://github.com/hoppscotch/hoppscotch into refactor/backend 2021-11-02 19:48:34 +05:30
liyasthomas
5f0800760f chore: clean up 2021-11-02 19:45:41 +05:30
liyasthomas
6db99c9e37 chore(deps): bump 2021-11-02 19:42:44 +05:30
liyasthomas
3b2cabd3f3 fix: typo 2021-11-02 19:39:39 +05:30
Andrew Bastin
b0dd6b0bd6 feat: fix gqlclient race condition 2021-11-02 19:33:09 +05:30
liyasthomas
874b846e60 fix: fix broken edit team modal
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-11-02 19:33:09 +05:30
liyasthomas
dbe2525c6f docs: updated feature list 2021-11-02 19:33:09 +05:30
Andrew Bastin
afd414fa3f feat: introducing gql polling 2021-11-02 19:33:09 +05:30
liyasthomas
94763dcb31 fix: prompt user on actions with no permission 2021-11-02 19:33:09 +05:30
Andrew Bastin
6314740f46 feat: reinit gql client after login 2021-11-02 19:33:09 +05:30
liyasthomas
d7332120e3 fix: hide popover on click on update role 2021-11-02 19:33:09 +05:30
liyasthomas
8c74fe9925 feat: user's roles prompt on invite modal 2021-11-02 19:33:09 +05:30
liyasthomas
c74ddeb530 fix: team invitation error states 2021-11-02 19:33:09 +05:30
Andrew Bastin
e31c0a9d02 feat: fix subscription auth refresh issues 2021-11-02 19:33:09 +05:30
Andrew Bastin
d9e5d4aec5 feat: add subscriptions for team invitations added and removed 2021-11-02 19:33:09 +05:30
liyasthomas
c1ee8f5dd0 feat: subscriptions on edit team modal 2021-11-02 19:33:09 +05:30
Andrew Bastin
dd59de3de0 feat: add subscription support for useGQLQuery 2021-11-02 19:33:07 +05:30
liyasthomas
511a3c55f3 fix: broken edit team modal 2021-11-02 19:32:49 +05:30
liyasthomas
c9021ab3ca fix: broken edit team action 2021-11-02 19:32:49 +05:30
liyasthomas
a765c4a7cc feat: successfully joined team prompt 2021-11-02 19:32:48 +05:30
Andrew Bastin
ea99732474 refactor: use the unpaginated teamMembers field instead of members 2021-11-02 19:32:48 +05:30
liyasthomas
6c64ffe833 feat: invite system error states and user prompts 2021-11-02 19:32:48 +05:30
Andrew Bastin
5fa6c6cdb3 fix: improper parsed error checks 2021-11-02 19:32:48 +05:30
Andrew Bastin
d94759870e refactor: add error info to send invite results 2021-11-02 19:32:48 +05:30
Andrew Bastin
f0a6fc641a feat: team invitation caching 2021-11-02 19:32:48 +05:30
Andrew Bastin
7ba00bee0b feat: update graphcache keys typings 2021-11-02 19:32:48 +05:30
liyasthomas
dc2bdf81b9 fix: invitation acceptance flow 2021-11-02 19:32:48 +05:30
liyasthomas
187a30abac feat: init loading states, minor ui improvements 2021-11-02 19:32:48 +05:30
liyasthomas
5b824ccb17 feat: minor ui improvements on invite flow 2021-11-02 19:32:48 +05:30
liyasthomas
3bdf2baf97 feat: init invitation wiring
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-11-02 19:32:48 +05:30
Andrew Bastin
9af8a24a89 feat: initial team invites implementation
Co-authored-by: Liyas Thomas <hi@liyasthomas.com>
2021-11-02 19:32:48 +05:30
liyasthomas
57c4759bdb chore: minor fixes and improvements 2021-11-02 19:32:48 +05:30
Andrew Bastin
d9d7261bc5 feat: team invitation mutations 2021-11-02 19:32:48 +05:30
Andrew Bastin
a12315d81a refactor: add graphcache codegen and update types 2021-11-02 19:32:47 +05:30
liyasthomas
9f0956556f feat: support updating user's display name 2021-11-02 19:32:13 +05:30
liyasthomas
748318d44e feat: compact mode for team component 2021-11-02 19:32:13 +05:30
liyasthomas
ff3062cdfc chore: clean up 2021-11-02 19:32:13 +05:30
liyasthomas
48d67fe7e1 fix: init local persistence 2021-11-02 19:32:13 +05:30
liyasthomas
2c9918f9a7 feat: init theming in empty layout 2021-11-02 19:32:13 +05:30
liyasthomas
ee03952201 feat: init teams invite page 2021-11-02 19:32:13 +05:30
liyasthomas
43dcd3c443 feat: invite modal mvp 2021-11-02 19:32:13 +05:30
Andrew Bastin
8f8c42a92a feat: gql codegen + caching + optimistic 2021-11-02 19:32:11 +05:30
liyasthomas
6496aded25 feat: teams modal wrapper 2021-11-02 19:25:36 +05:30
Andrew Bastin
eacf8113af feat: initial setup of new backend comms 2021-11-02 19:20:07 +05:30
liyasthomas
c4a1527153 chore(deps): bump 2021-11-02 19:17:30 +05:30
liyasthomas
4a89a6aafc feat: teams invite modal 2021-11-02 19:17:11 +05:30
Andrew Bastin
52539b084d feat: gql codegen + caching + optimistic 2021-11-02 19:17:09 +05:30
Andrew Bastin
8d5bd051a1 refactor: extract cache info to separate files and add more mutations 2021-11-02 19:15:44 +05:30
liyasthomas
3809e9853e chore(ui): minor ui improvements, empty teams state 2021-11-02 19:15:44 +05:30
Andrew Bastin
5f795acd61 feat: probable user is displayed as authenticated 2021-11-02 19:15:44 +05:30
liyasthomas
17c550404f refactor: updated lint script 2021-11-02 19:15:44 +05:30
Andrew Bastin
a840079119 feat: add persistent cache and optimistic updates 2021-11-02 19:15:42 +05:30
Andrew Bastin
2761894164 fix: queries not waiting for authentication 2021-11-02 19:15:20 +05:30
liyasthomas
6b8bc618dc feat: teams modal wrapper 2021-11-02 19:15:02 +05:30
liyasthomas
258f79604f refactor: remove EAInvite flag 2021-11-02 19:15:02 +05:30
Andrew Bastin
81ae70ee04 fix: fix issue with team queries not updating correctly after mutation 2021-11-02 19:15:02 +05:30
Andrew Bastin
6b02d290a5 feat: team mutation 2021-11-02 19:15:02 +05:30
Andrew Bastin
7ab1bbaf62 refactor: refactor create team modal to new system 2021-11-02 19:15:02 +05:30
liyasthomas
079083d0f2 fix: i18n usage 2021-11-02 19:15:02 +05:30
liyasthomas
0504707aab feat: init profile page 2021-11-02 19:14:59 +05:30
Andrew Bastin
fb4aab875d feat: introduce updated mutation system and team.vue rewrite 2021-11-02 19:14:25 +05:30
Andrew Bastin
7bb32ecf7e feat: initial setup of new backend comms 2021-11-02 19:14:21 +05:30
Andrew Bastin
e129a5c179 feat: fix gqlclient race condition 2021-11-02 19:11:16 +05:30
liyasthomas
8045f26c19 fix: fix broken edit team modal
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-11-02 14:25:38 +05:30
liyasthomas
86516421b5 fix(ci): run build command from root 2021-11-02 07:01:48 +05:30
liyasthomas
bce88ccd44 docs: updated feature list 2021-11-02 06:41:18 +05:30
0xc0Der
66d408b7db Allow duplication of global environment (#1924) 2021-11-02 06:16:16 +05:30
Andrew Bastin
297bf3205f feat: introducing gql polling 2021-11-01 22:27:06 +05:30
liyasthomas
7366b32349 fix: prompt user on actions with no permission 2021-11-01 17:51:01 +05:30
Andrew Bastin
b7e0169c9b feat: reinit gql client after login 2021-11-01 17:30:16 +05:30
liyasthomas
6b6f85cc7e fix: hide popover on click on update role 2021-11-01 15:25:19 +05:30
liyasthomas
2c014a2f4b feat: user's roles prompt on invite modal 2021-11-01 15:04:46 +05:30
liyasthomas
d6df675821 fix: team invitation error states 2021-11-01 14:20:35 +05:30
liyasthomas
427baf4c79 chore: bump dep + minor ui fixes 2021-11-01 13:10:48 +05:30
liyasthomas
4f2b682341 chore(deps): bump 2021-10-31 19:53:05 +05:30
Andrew Bastin
e03f888cb2 feat: fix subscription auth refresh issues 2021-10-31 17:40:03 +05:30
Andrew Bastin
513396d498 feat: add subscriptions for team invitations added and removed 2021-10-30 18:56:34 +05:30
liyasthomas
8f04f0758b fix: use hoppscotch's realtime echo servers - resolved #1913 2021-10-29 08:55:31 +05:30
liyasthomas
7a77bfc248 feat: subscriptions on edit team modal 2021-10-28 20:29:49 +05:30
Andrew Bastin
ddd29374ea feat: add subscription support for useGQLQuery 2021-10-27 22:41:32 +05:30
liyasthomas
4b0d7a6c3d fix: broken edit team modal 2021-10-27 18:32:11 +05:30
liyasthomas
20bfc02a4e fix: disable spellcheck on contenteditable - resolved #1908 2021-10-27 18:17:22 +05:30
Darío Hereñú
2511724b73 chore: updated spanish translation (#1907) 2021-10-27 06:10:17 +05:30
liyasthomas
a851ee3fab fix: broken edit team action 2021-10-26 23:16:56 +05:30
liyasthomas
40f6e6f8a8 fix: typo in test result 2021-10-26 15:36:59 +05:30
liyasthomas
e2fd104c2d feat: test results indicator in response section's tests tab 2021-10-26 13:48:09 +05:30
Andrew Bastin
a3eafa54fa fix: test script not parsing json object if json content type 2021-10-26 13:19:15 +05:30
Sergio Guzmán Mayorga
b90b4a1910 chore: update spanish translations (#1904) 2021-10-26 06:47:28 +05:30
liyasthomas
247df4d5b9 chore: bump deps + fix broken links 2021-10-25 21:04:28 +05:30
Burak Saraloglu
4a3889a76e chore (i18n): updated Turkish translations (#1893) 2021-10-25 05:02:30 +05:30
liyasthomas
224a6e069c chore(deps): bump 2021-10-24 20:06:22 +05:30
liyasthomas
2c3097eeb7 feat: successfully joined team prompt 2021-10-24 14:46:32 +05:30
Andrew Bastin
3289ede0e8 refactor: use the unpaginated teamMembers field instead of members 2021-10-22 15:34:20 +05:30
liyasthomas
ddf21c17d2 feat: invite system error states and user prompts 2021-10-21 18:17:32 +05:30
Andrew Bastin
c9a24a0d28 fix: improper parsed error checks 2021-10-20 16:49:58 +05:30
Andrew Bastin
fa4b130b18 refactor: add error info to send invite results 2021-10-20 15:50:21 +05:30
Andrew Bastin
8561a7547f feat: team invitation caching 2021-10-20 15:33:20 +05:30
liyasthomas
e85f7b8232 feat: collapse collections/folders on clicking side border 2021-10-20 13:55:18 +05:30
Chun-Hao Lien
2f91d25ed4 chore: add json file extension (#1889) 2021-10-20 12:06:01 +05:30
Andrew Bastin
ae304b5af7 feat: update graphcache keys typings 2021-10-19 23:12:47 +05:30
hms5232
363d34b5e5 chore(i18n): update tw translations (#1887) 2021-10-19 14:48:50 +05:30
Andrew Bastin
1c51f8b32e fix: bug with search box key listeners still active after close 2021-10-19 14:42:39 +05:30
liyasthomas
aaff07bba2 Merge remote-tracking branch 'origin/keyboard-navigation-on-power-search' 2021-10-19 13:45:48 +05:30
Francisco Emanuel de Sales Pereira
4bc38d5e0f Feature: Adds arrow keys navigation on power search (#1888) 2021-10-19 13:44:14 +05:30
liyasthomas
fdfca00886 feat: set active on hover + minor ui improvements 2021-10-19 13:40:47 +05:30
Liyas Thomas
d872e393f8 Merge branch 'main' into keyboard-navigation-on-power-search 2021-10-19 10:56:00 +05:30
franciscoemanuel
686d8e5be7 feat: adds arrow keys navigation on powersearch 2021-10-19 02:20:30 -03:00
liyasthomas
4e30efd737 fix: invitation acceptance flow 2021-10-18 21:43:13 +05:30
rubjo
aa4935c505 chore(i18n): updated Norwegian translations (#1886) 2021-10-18 12:20:27 +05:30
liyasthomas
0e381ab850 feat: init loading states, minor ui improvements 2021-10-18 09:36:33 +05:30
liyasthomas
4a03ee4518 chore(deps): bump 2021-10-18 07:34:26 +05:30
Geert Wirken
be414d8279 Improve Dutch translations (#1880) 2021-10-17 22:43:18 +05:30
liyasthomas
c47b1f2413 chore(deps): bump 2021-10-17 19:42:53 +05:30
liyasthomas
ba9ee052a6 feat: minor ui improvements on invite flow 2021-10-17 18:53:24 +05:30
liyasthomas
b1c6708762 feat: init invitation wiring
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-10-17 16:45:48 +05:30
Andrew Bastin
0ba31b6c79 feat: initial team invites implementation
Co-authored-by: Liyas Thomas <hi@liyasthomas.com>
2021-10-17 15:05:43 +05:30
liyasthomas
14f402f186 feat: minor ui improvements to power search 2021-10-17 11:37:06 +05:30
liyasthomas
b811e97ea5 feat: set hoppscotch graphql echo server as default 2021-10-17 00:49:36 +05:30
Oscar Dominguez
6d167ce1d6 ci(workflow): add cache to workflows using actions/setup-node (#1872) 2021-10-16 22:50:16 +05:30
liyasthomas
9ac1d23fd9 chore: minor fixes and improvements 2021-10-16 20:54:19 +05:30
Andrew Bastin
dea3a34e3d feat: team invitation mutations 2021-10-16 15:14:07 +05:30
Andrew Bastin
39de34f083 refactor: add graphcache codegen and update types 2021-10-16 15:14:07 +05:30
liyasthomas
02d5f0fdf3 feat: support updating user's display name 2021-10-16 15:01:32 +05:30
liyasthomas
0bb7cbe8d9 feat: compact mode for team component 2021-10-16 11:14:33 +05:30
liyasthomas
3e3b88b8c2 feat: native email input validation on login modal 2021-10-16 00:00:33 +05:30
liyasthomas
1438beb93b chore: clean up 2021-10-15 08:15:43 +05:30
liyasthomas
c1ec5dc60d feat: promote environment aware input to stable 2021-10-14 13:00:32 +05:30
prasanth
3f513f2f4d fix(request): multipart payload not working while using proxy 2021-10-13 21:32:27 +05:30
liyasthomas
d1b573f6f9 fix: init local persistence 2021-10-13 19:42:13 +05:30
liyasthomas
0e08abc46f feat: init theming in empty layout 2021-10-13 17:00:56 +05:30
liyasthomas
49bdf9f203 feat: init teams invite page 2021-10-13 16:12:02 +05:30
liyasthomas
b3e9df4f3d fix: introduce X-Frame-Options header to prevent clickjacking 2021-10-13 08:58:40 +05:30
Andrew Bastin
3b8cf4a60a fix: single character shortcuts not working 2021-10-12 21:43:06 +05:30
Akash Hamirwasia
b7ccb9a34c feat: disable inputs in realtime and graphql connections when active (#1870) 2021-10-12 21:19:29 +05:30
Akash Hamirwasia
b8ffa872c7 feat: add socket.io-client version selector menu (#1867) 2021-10-12 11:22:47 +05:30
liyasthomas
ef866f7851 feat: invite modal mvp 2021-10-11 06:51:43 +05:30
liyasthomas
f27515bf1d Merge branch 'refactor/backend' of https://github.com/hoppscotch/hoppscotch into refactor/backend 2021-10-10 20:49:27 +05:30
liyasthomas
ddf74c5d7c chore(deps): bump 2021-10-10 20:48:16 +05:30
liyasthomas
8ea12695b3 feat: teams invite modal 2021-10-10 20:44:21 +05:30
Andrew Bastin
d6324e6ba6 feat: gql codegen + caching + optimistic 2021-10-10 20:44:18 +05:30
Andrew Bastin
2325982801 refactor: extract cache info to separate files and add more mutations 2021-10-10 20:43:19 +05:30
liyasthomas
b103c45e65 chore(ui): minor ui improvements, empty teams state 2021-10-10 20:43:18 +05:30
Andrew Bastin
409989eddb feat: probable user is displayed as authenticated 2021-10-10 20:43:18 +05:30
liyasthomas
3f5fcae280 refactor: updated lint script 2021-10-10 20:43:18 +05:30
Andrew Bastin
d5123c793a feat: add persistent cache and optimistic updates 2021-10-10 20:43:16 +05:30
Andrew Bastin
e6707c1e4a fix: queries not waiting for authentication 2021-10-10 20:42:46 +05:30
liyasthomas
41be5cc4a8 feat: teams modal wrapper 2021-10-10 20:41:57 +05:30
liyasthomas
e82a4a1d23 refactor: remove EAInvite flag 2021-10-10 20:41:57 +05:30
Andrew Bastin
e30e4edfce fix: fix issue with team queries not updating correctly after mutation 2021-10-10 20:41:57 +05:30
Andrew Bastin
bd72ef7950 feat: team mutation 2021-10-10 20:41:57 +05:30
Andrew Bastin
539034df2a refactor: refactor create team modal to new system 2021-10-10 20:41:57 +05:30
liyasthomas
6da6afc5a1 fix: i18n usage 2021-10-10 20:41:57 +05:30
liyasthomas
fea523972d feat: init profile page 2021-10-10 20:41:57 +05:30
Andrew Bastin
5cfc6c2949 feat: introduce updated mutation system and team.vue rewrite 2021-10-10 20:41:57 +05:30
Andrew Bastin
6dd0c25d49 feat: initial setup of new backend comms 2021-10-10 20:41:54 +05:30
liyasthomas
ab9b3e47b9 chore(deps): bump 2021-10-10 20:24:31 +05:30
James George
33ebdf2831 chore: cleanup .husky directory (#1865) 2021-10-10 15:00:57 +05:30
liyasthomas
ef95939763 feat: teams invite modal 2021-10-09 16:10:51 +05:30
Rishabh kalra
0394deaeef route navigation no longer happening in typable areas (#1862) 2021-10-09 06:45:17 +05:30
Andrew Bastin
337a60c8a4 feat: gql codegen + caching + optimistic 2021-10-08 23:51:06 +05:30
Andrew Bastin
47b341d50e fix: fix conditional tabs not rerendering 2021-10-06 21:55:05 +05:30
Andrew Bastin
a5fd39adf8 refactor: extract cache info to separate files and add more mutations 2021-10-06 19:32:27 +05:30
liyasthomas
5772117dc8 fix: respect localePath on router - fixed #1859 2021-10-06 12:38:50 +05:30
liyasthomas
f73c8a45d9 chore(ui): minor ui improvements, empty teams state 2021-10-05 22:17:29 +05:30
Andrew Bastin
109d4190ae feat: probable user is displayed as authenticated 2021-10-05 22:06:19 +05:30
liyasthomas
317de82be6 refactor: updated lint script 2021-10-05 21:48:10 +05:30
Boris K
3604d69463 chore(i18n): fixed french translations (#1858) 2021-10-05 15:16:36 +05:30
Andrew Bastin
96cf774652 feat: add persistent cache and optimistic updates 2021-10-05 02:09:39 +05:30
liyasthomas
d2b39976ba chore(deps): bump 2021-10-04 08:16:40 +05:30
Stephane
06161bc963 Show graphql error message (#1852)
Co-authored-by: StephaneBischoffSSENSE <stephane.bischoff@ssense.com>
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2021-10-04 08:01:47 +05:30
bblumenwiese
2ab1d3dbfa docs: fix broken link to .env.example in README (#1854)
Refs #1852
2021-10-04 00:29:45 +05:30
Andrew Bastin
ecdc7919ae fix: queries not waiting for authentication 2021-10-03 19:14:32 +05:30
liyasthomas
a24541ac2b chore(deps): bump 2021-10-03 19:13:44 +05:30
liyasthomas
d832690548 refactor: better name for duplicated environment 2021-10-03 18:53:27 +05:30
Stephane
2844710ea8 feat: add ability to copy environments (#1848)
Co-authored-by: StephaneBischoffSSENSE <stephane.bischoff@ssense.com>
2021-10-03 18:38:36 +05:30
liyasthomas
84ad4071ad feat: teams modal wrapper 2021-10-03 18:14:52 +05:30
liyasthomas
7f501241f0 refactor: remove EAInvite flag 2021-10-03 15:49:04 +05:30
Manda Putra
5dcfa66c5d fix: parsing 2021-10-03 12:28:49 +05:30
Manda Putra
f428a21279 feat: parse body from url params 2021-10-03 12:28:49 +05:30
Andrew Bastin
ccdd4963cd fix: fix issue with team queries not updating correctly after mutation 2021-10-03 01:31:06 +05:30
Andrew Bastin
2092a3729c feat: team mutation 2021-10-02 13:50:08 +05:30
Andrew Bastin
a628420adb refactor: refactor create team modal to new system 2021-10-02 13:50:08 +05:30
liyasthomas
23de147ca1 fix: i18n usage 2021-10-02 13:46:51 +05:30
liyasthomas
93f55f5619 feat: init profile page 2021-10-02 13:22:07 +05:30
Liyas Thomas
b10933898f Merge pull request #1845 from YasiOnFire/fix-polish-localization
chore(i18n): fix polish translation
2021-10-02 07:34:24 +05:30
Yasio
1727b754d4 chore(i18n): fix polish translation 2021-10-01 20:36:12 +02:00
Andrew Bastin
ffb0c12c08 feat: introduce updated mutation system and team.vue rewrite 2021-10-01 15:13:48 +05:30
Andrew Bastin
c332808fe4 feat: initial setup of new backend comms 2021-10-01 13:46:22 +05:30
liyasthomas
8f0538c886 chore(i18n): updated translations 2021-10-01 11:24:34 +05:30
Khaleel Gibran
e6bb7e2ca9 Remove random </br>s in locale footers (#1844) 2021-10-01 10:12:10 +05:30
liyasthomas
2a012520d0 fix: proper type for ID 2021-09-30 16:05:40 +05:30
Andrew Bastin
c71333d9cb refactor: update ID based backend queries to proper types 2021-09-30 12:52:31 +05:30
liyasthomas
728515c225 chore: bump deps 2021-09-26 19:16:23 +05:30
Andrew Bastin
e0f88e01f9 Update js-sandbox README 2021-09-26 11:27:46 +05:30
Andrew Bastin
1aa94a12c0 Merge pull request #1836 from AndrewBastin/refactor/js-sandbox
Move to JS code execution sandbox (HOPP-67, HOPP-66)
2021-09-25 23:05:41 +05:30
Andrew Bastin
de2d3361a7 refactor: bump js-sandbox version to 1.0.0 2021-09-25 22:25:33 +05:30
Andrew Bastin
680937e50b feat: fix issue with the pre-request envs 2021-09-25 21:21:01 +05:30
liyasthomas
6751c50514 fix: build 2021-09-25 12:21:32 +05:30
liyasthomas
0c389701fe chore(docs): updated readme 2021-09-25 12:21:19 +05:30
Andrew Bastin
9454d8c100 feat: move testing code to js-sandbox 2021-09-25 01:09:48 +05:30
Andrew Bastin
166f9e817b feat: project level testing + add fp-ts and sandbox as deps 2021-09-25 01:07:24 +05:30
Andrew Bastin
d2865c637c refactor: bring js-sandbox project to the monorepo 2021-09-25 01:01:22 +05:30
liyasthomas
9698932bde refactor(ui): minor ui improvements 2021-09-20 21:33:36 +05:30
liyasthomas
44026fcd41 fix: show scrollbars inside menu 2021-09-20 14:56:25 +05:30
liyasthomas
d938af0c2c fix: better responsiveness on horizontal layout 2021-09-20 14:18:40 +05:30
liyasthomas
fd658400a6 refactor: updated logo 2021-09-20 11:15:09 +05:30
liyasthomas
dcbb17b164 feat: vertical and horizontal layout support 2021-09-20 10:17:31 +05:30
liyasthomas
49741875bd chore: minor ui improvements 2021-09-19 20:27:20 +05:30
liyasthomas
0fcd9733ff chore: bump deps 2021-09-19 20:26:25 +05:30
Andrew Bastin
62d50169d7 Merge pull request #1832 from AndrewBastin/refactor/teams-list
fix: teams list not properly showing (HOPP-61)
2021-09-19 00:48:30 +05:30
Andrew Bastin
1d3d5a1e6a Merge branch 'main' into refactor/teams-list 2021-09-19 00:47:58 +05:30
Liyas Thomas
d309fa745e Update packages/hoppscotch-app/components/teams/index.vue 2021-09-19 00:33:21 +05:30
liyasthomas
f7031992d5 fix: enforce name for SmartTab component 2021-09-19 00:09:35 +05:30
Andrew Bastin
fcdf68ea15 fix: teams list not properly showing 2021-09-18 23:56:19 +05:30
liyasthomas
b0a6692179 feat: vertical tabs for right sidebars 2021-09-18 23:50:42 +05:30
liyasthomas
e1e763575d perf: template literals 2021-09-18 16:09:58 +05:30
Andrew Bastin
4236d1179c fix: save request crashing on teams 2021-09-18 15:11:54 +05:30
Andrew Bastin
09365bcabe fix: environments not being written correctly 2021-09-18 14:39:43 +05:30
Andrew Bastin
be29ddcbd6 fix: volar shim gitignore issue 2021-09-17 18:49:38 +05:30
liyasthomas
522194ca8d chore: remove absolute files 2021-09-17 17:30:55 +05:30
liyasthomas
5af8f584f6 chore(deps): bump 2021-09-17 15:25:52 +05:30
liyasthomas
adc08f8865 perf(ci): remove absolute branch hooks 2021-09-17 15:20:30 +05:30
liyasthomas
0f39d54c3c fix: netlify builds 2021-09-17 14:17:48 +05:30
liyasthomas
9e6659e842 fix: netlify builds 2021-09-17 14:11:30 +05:30
liyasthomas
46a0f6e3f8 refactor: update build docs 2021-09-17 13:57:56 +05:30
Andrew Bastin
e90b26ebed fix: standardized build scripts 2021-09-17 13:46:23 +05:30
Andrew Bastin
4407f260ae fix: updated to better dockerfile 2021-09-17 13:12:49 +05:30
Andrew Bastin
d4392416c8 fix: fix broken tests 2021-09-16 22:59:29 +05:30
liyasthomas
2d3cbd26b8 fix: ci builds 2021-09-16 22:44:34 +05:30
Andrew Bastin
98b9660956 refactor: merge branch 'main' into refactor/monorepo 2021-09-16 22:24:21 +05:30
liyasthomas
4e8a4e8914 refactor: typescript support 2021-09-15 17:30:04 +05:30
liyasthomas
96bcbc80f8 fix(ci): bump deps + fix tests 2021-09-14 23:43:20 +05:30
liyasthomas
1dfc8e2973 perf: remove absolute files 2021-09-14 23:32:43 +05:30
liyasthomas
311886f6c9 Merge remote-tracking branch 'origin/feat/codemirror' 2021-09-14 23:30:04 +05:30
liyasthomas
4a332f40e5 fix: json outline line index 2021-09-14 23:28:39 +05:30
liyasthomas
93a97a2f4c refactor: json outline ui 2021-09-14 23:11:10 +05:30
Andrew Bastin
1dee098ca2 feat: fix outline 2021-09-14 21:33:13 +05:30
liyasthomas
a07cc7e560 refactor: minor ui improvements 2021-09-14 13:19:10 +05:30
Andrew Bastin
c26f7f5ebc fix: autocompletion eating non-identifier tokens 2021-09-13 09:18:37 +05:30
liyasthomas
5d801cf566 fix: missing '?' in query parameter string for code generators 2021-09-13 09:07:06 +05:30
Andrew Bastin
631b2d869e fix: autocompletion position messing up 2021-09-12 21:56:56 +05:30
liyasthomas
c02f54cc18 chore(deps): bump 2021-09-12 19:45:23 +05:30
liyasthomas
827a95515d feat: select suggestion on enter key for autocomplete 2021-09-12 10:51:46 +05:30
liyasthomas
9082152f1a fix: editor width 2021-09-12 02:08:37 +05:30
Liyas Thomas
0efbddeda4 Merge pull request #1822 from hoppscotch/fix/gql-save-req 2021-09-12 00:07:22 +05:30
liyasthomas
b2e186957c fix: repetitive use of () in setup script 2021-09-12 00:02:07 +05:30
Andrew Bastin
d855e5cffb fix: gql request save issue 2021-09-11 23:43:35 +05:30
Andrew Bastin
f3747edaa3 Merge pull request #1820 from hoppscotch/fix/gql-headers
fix: gql headers not passed properly (HOPP-55)
2021-09-11 21:15:17 +05:30
Andrew Bastin
752932ef3d fix: gql headers not passed properly 2021-09-11 21:01:48 +05:30
liyasthomas
948cf9dae3 perf: cleanup 2021-09-11 10:34:06 +05:30
liyasthomas
b2f93aa549 feat: highlight active line in codemirror when focused 2021-09-11 09:19:16 +05:30
liyasthomas
108f228edf refactor: minor ui improvements 2021-09-11 08:26:54 +05:30
liyasthomas
fe6030140f feat: graphql mode for schema editor 2021-09-10 19:57:52 +05:30
Andrew Bastin
003400cfa8 feat: introduce graphql mode for codemirror 2021-09-10 19:01:35 +05:30
liyasthomas
41a02f059d perf: remove ace editor 2021-09-10 18:52:58 +05:30
liyasthomas
b4ed6fd107 feat: codemirror for import curl and codegens 2021-09-10 18:27:31 +05:30
Andrew Bastin
36246da9e1 feat: fix up jest tests 2021-09-10 17:50:22 +05:30
liyasthomas
457b6b982c feat: codemirror for graphql query, scheme and response 2021-09-10 16:12:04 +05:30
liyasthomas
05a07dc4a1 perf: ci 2021-09-10 13:05:31 +05:30
Andrew Bastin
85889c2cb9 fix: fix tests.yml 2021-09-10 12:55:59 +05:30
liyasthomas
be6ceaab04 perf: ci 2021-09-10 12:46:50 +05:30
liyasthomas
f1b18688bb fix: ci 2021-09-10 12:15:08 +05:30
liyasthomas
80c7decb81 feat: husky + commitlint 2021-09-10 12:02:18 +05:30
liyasthomas
3ef5a1e21a feat: codemirror editor for pre-request and test scripts 2021-09-10 11:12:08 +05:30
liyasthomas
2eb0a4c754 feat: reactive syntax + line wrap on raw body 2021-09-10 10:46:58 +05:30
liyasthomas
10f5af5dda feat: codemirror editot for raw body 2021-09-10 01:35:46 +05:30
liyasthomas
8b27ebb96b feat: mixed html syntax, light theme for codemiror 2021-09-10 00:44:14 +05:30
Andrew Bastin
b28f82a881 refactor: monorepo+pnpm (removed husky) 2021-09-10 00:28:28 +05:30
liyasthomas
c921606f3f Merge remote-tracking branch 'origin/exp/volar-types' into feat/codemirror 2021-09-09 20:50:58 +05:30
liyasthomas
c6c08f6c60 feat: reactive line wrap on codemirror
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-09-09 20:50:04 +05:30
liyasthomas
02cf620090 feat: port ace editor to codemirror
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-09-09 17:47:27 +05:30
Andrew Bastin
4a12cc76fa feat: improve shim generation for index components 2021-09-09 01:56:43 +05:30
Andrew Bastin
f4f74e223f refactor: a volar types shim generator 2021-09-09 01:03:46 +05:30
liyasthomas
8b4535c131 Merge branch 'feat/codemirror' of https://github.com/hoppscotch/hoppscotch into feat/codemirror 2021-09-08 21:54:00 +05:30
liyasthomas
b15fd6c75a feat: port bulk editor textareas to codemirror 2021-09-08 21:52:26 +05:30
liyasthomas
e1a25fa894 fix: broken conditional rendering of codemirror
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-09-08 21:41:02 +05:30
Andrew Bastin
2bb3b71a70 refactor: map ctrl-space to autocomplete by default in codemirror 2021-09-08 21:41:02 +05:30
Andrew Bastin
4c55b9c304 fix: codemirror theme not changing when color mode is updated 2021-09-08 21:41:02 +05:30
Andrew Bastin
639a629809 feat: gql query autocompletion on codemirror 2021-09-08 21:41:02 +05:30
Andrew Bastin
d6e3bd09b4 refactor: pass current token position to auto completers on codemirror 2021-09-08 21:41:02 +05:30
Andrew Bastin
8d67a0d95f feat: test script auto completion for codemirror 2021-09-08 21:41:02 +05:30
Andrew Bastin
b9fc0175e7 feat: implement base autocomplete implementation for codemirror along with preRequest autocompletion 2021-09-08 21:41:02 +05:30
liyasthomas
dc5f52cc0d refactor: github flavored codemirror light theme 2021-09-08 21:40:55 +05:30
liyasthomas
602aabdeb8 feat: reactive codemirror theme 2021-09-08 21:40:11 +05:30
Andrew Bastin
2f8aa79ec1 feat: json linter support for codemirror 2021-09-08 21:40:11 +05:30
Andrew Bastin
8af90432cf feat: implement gql query linting in codemirror 2021-09-08 21:40:11 +05:30
Andrew Bastin
61da0733c2 feat: codemirror editor options are reactive 2021-09-08 21:40:11 +05:30
liyasthomas
33951482d5 feat: placeholder, auto-close brackets, search, line wrap 2021-09-08 21:40:11 +05:30
Andrew Bastin
4e8484ee7c feat: linter for prerequest and testscripts 2021-09-08 21:40:11 +05:30
Andrew Bastin
071761a61e feat: codemirror linting system 2021-09-08 21:40:11 +05:30
Andrew Bastin
10a11d6725 refactor: add types for esprima 2021-09-08 21:40:11 +05:30
Andrew Bastin
c81178ae26 refactor: extract common codemirror logic out to composable 2021-09-08 21:40:10 +05:30
liyasthomas
2bafae5397 feat: line wrap, auto close brackets, placeholder on codemirror 2021-09-08 21:40:10 +05:30
liyasthomas
6a1d201e0e refactor: ts codemirror 2021-09-08 21:40:10 +05:30
liyasthomas
8de544696d feat: init codemirror 2021-09-08 21:40:06 +05:30
liyasthomas
66c489da8f fix: broken conditional rendering of codemirror
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-09-08 20:27:36 +05:30
Andrew Bastin
26c8f35688 refactor: map ctrl-space to autocomplete by default in codemirror 2021-09-08 19:51:43 +05:30
Andrew Bastin
28aeac4533 fix: codemirror theme not changing when color mode is updated 2021-09-08 06:00:23 +05:30
Andrew Bastin
162b3d6192 feat: gql query autocompletion on codemirror 2021-09-08 05:38:03 +05:30
Andrew Bastin
b016d3fd9d refactor: pass current token position to auto completers on codemirror 2021-09-08 05:36:46 +05:30
Andrew Bastin
f64ff58dbc feat: test script auto completion for codemirror 2021-09-08 04:58:30 +05:30
Andrew Bastin
d4d3d96bbb feat: implement base autocomplete implementation for codemirror along with preRequest autocompletion 2021-09-07 22:15:47 +05:30
liyasthomas
a5197ee544 refactor: github flavored codemirror light theme 2021-09-07 16:26:26 +05:30
liyasthomas
8a5fd4f745 feat: reactive codemirror theme 2021-09-07 12:14:13 +05:30
Andrew Bastin
12cd7940c6 feat: json linter support for codemirror 2021-09-06 23:47:26 +05:30
Andrew Bastin
0c2cec46a7 feat: implement gql query linting in codemirror 2021-09-06 23:30:43 +05:30
Andrew Bastin
8430921e4e feat: codemirror editor options are reactive 2021-09-01 20:32:33 +05:30
liyasthomas
c938abf606 feat: placeholder, auto-close brackets, search, line wrap 2021-09-01 17:33:54 +05:30
Andrew Bastin
3addfe8d4b feat: linter for prerequest and testscripts 2021-09-01 16:45:49 +05:30
Andrew Bastin
5276556837 feat: codemirror linting system 2021-09-01 16:41:14 +05:30
Andrew Bastin
e47ad94666 refactor: add types for esprima 2021-09-01 16:34:02 +05:30
liyasthomas
7065763c7c Merge branch 'main' into feat/codemirror 2021-09-01 10:34:52 +05:30
Andrew Bastin
86489d95c2 refactor: extract common codemirror logic out to composable 2021-08-31 22:20:42 +05:30
liyasthomas
e2b1c83698 feat: line wrap, auto close brackets, placeholder on codemirror 2021-08-31 16:10:35 +05:30
liyasthomas
15373be63e refactor: ts codemirror 2021-08-31 10:47:00 +05:30
liyasthomas
8c9cd079b7 feat: init codemirror 2021-08-31 00:03:07 +05:30
770 changed files with 48088 additions and 74749 deletions

View File

@@ -0,0 +1,57 @@
name: Bug report
description: Create a bug report to help us improve Hoppscotch
title: "[bug]: "
labels: [bug, need testing]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out this bug report.
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Current behavior
description: A concise description of what you're experiencing and what you expect
placeholder: |
When I do <X>, <Y> happens and I see the error message attached below:
```...```
What I expect is <Z>
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Add steps to reproduce this behaviour, include console or network logs and screenshots
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: dropdown
id: env
attributes:
label: Environment
options:
- Production
- Release
- Deploy preview
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
options:
- Cloud
- Self-hosted
- Local
validations:
required: true

View File

@@ -0,0 +1,28 @@
name: Feature request
description: Suggest a feature to improve Hoppscotch
title: "[feature]: "
labels: [feature]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to request a feature for Hoppscotch
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue related to this feature request already exists
options:
- label: I have searched the existing issues
required: true
- type: textarea
attributes:
label: Summary
description: One paragraph description of the feature
validations:
required: true
- type: textarea
attributes:
label: Why should this be worked on?
description: A concise description of the problems or use cases for this feature request
validations:
required: true

View File

@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

7
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
contact_links:
- name: Help and support
url: https://github.com/hoppscotch/hoppscotch#support
about: Reach out to us on our Discord server or Telegram group or GitHub discussions.
- name: Dedicated support
url: mailto:support@hoppscotch.io
about: Write to us if you'd like dedicated support using Hoppscotch

View File

@@ -1,8 +0,0 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -2,13 +2,12 @@ name: Node.js CI
on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
@@ -17,9 +16,13 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- name: Install pnpm
run: curl -f https://get.pnpm.io/v6.14.js | node - add --global pnpm@6
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
cache: pnpm
- name: Run tests
run: pnpm i && pnpm -r test

6
.gitignore vendored
View File

@@ -104,3 +104,9 @@ tests/*/screenshots
# Tests videos
tests/*/videos
# Local Netlify folder
.netlify
# Andrew's crazy Volar shim generator
shims-volar.d.ts

1
.husky/.gitignore vendored
View File

@@ -1 +0,0 @@
_

View File

@@ -6,7 +6,7 @@ We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual identity
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
support@hoppscotch.io.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
@@ -116,17 +116,13 @@ the community.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][mozilla coc].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][faq]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[mozilla coc]: https://github.com/mozilla/diversity
[faq]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,4 +1,4 @@
FROM node:12-alpine
FROM node:lts-alpine
LABEL maintainer="Hoppscotch (support@hoppscotch.io)"
@@ -9,17 +9,19 @@ RUN apk add --update --no-cache \
# Create app directory
WORKDIR /app
COPY package*.json ./
RUN npm install
ADD . /app/
COPY . .
RUN npm install -g pnpm
RUN pnpm i --unsafe-perm=true
ENV HOST 0.0.0.0
EXPOSE 3000
RUN mv .env.example .env
RUN mv packages/hoppscotch-app/.env.example packages/hoppscotch-app/.env
CMD ["npm", "run", "dev"]
RUN pnpm run generate
CMD ["pnpm", "run", "start"]

View File

@@ -1,7 +1,7 @@
<div align="center">
<a href="https://hoppscotch.io">
<img
src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/logo.png"
src="https://avatars.githubusercontent.com/u/56705483"
alt="Hoppscotch Logo"
height="64"
/>
@@ -36,7 +36,7 @@
<p>
<a href="https://hoppscotch.io">
<img
src="https://tiny.cc/hoppscotch_screenshot_1"
src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/packages/hoppscotch-app/static/banner.png"
alt="Screenshot"
width="100%"
/>
@@ -46,7 +46,7 @@
#### **Support**
[![Chat on Discord](https://img.shields.io/badge/chat-Discord-7289DA?logo=discord)](https://hoppscotch.io/discord) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-2CA5E0?logo=Telegram)](https://hoppscotch.io/telegram)
[![Chat on Discord](https://img.shields.io/badge/chat-Discord-7289DA?logo=discord)](https://hoppscotch.io/discord) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-2CA5E0?logo=telegram)](https://hoppscotch.io/telegram) [![Discuss on GitHub](https://img.shields.io/badge/discussions-GitHub-333333?logo=github)](https://github.com/hoppscotch/hoppscotch/discussions)
<details open>
<summary><b>Table of contents</b></summary>
@@ -89,7 +89,7 @@
- `TRACE` - Performs a message loop-back test along the path to the target resource
- `<custom>` - Some APIs use custom request methods such as `LIST`. Type in your custom methods.
🌈 **Make it yours:** Customizable combinations for background, foreground and accent colors — [customize now](https://hoppscotch.io/settings).
🌈 **Make it yours:** Customizable combinations for background, foreground and accent colors — [customize now](https://hoppscotch.io/settings).
**Theming**
@@ -173,7 +173,7 @@ _Collections are synced with cloud / local session storage_
- Hide your IP address
- Fixes [`CORS`](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) (Cross Origin Resource Sharing) issues
- Access APIs served in non-HTTPS `[http://]` endpoints
- Access APIs served in non-HTTPS (`http://`) endpoints
- Use your own Proxy URL
_Official proxy server is hosted by Hoppscotch - **[GitHub](https://github.com/hoppscotch/proxyscotch)** - **[Privacy Policy](https://docs.hoppscotch.io/privacy)**_
@@ -256,9 +256,12 @@ _Add-ons are developed and maintained under **[Hoppscotch Organization](https://
👨‍👩‍👧‍👦 **Teams β:** Helps you collaborate across your team to design, develop, and test APIs faster.
- Unlimited team collections and shared requests
- Unlimited teams
- Unlimited shared collections
- Unlimited team members
- User roles
- Role-based access control
- Cloud sync
- Multiple devices
🚚 **Bulk Edit:** Edit key-value pairs in bulk.
@@ -290,7 +293,7 @@ _Add-ons are developed and maintained under **[Hoppscotch Organization](https://
## **Developing**
0. Update [`.env.example`](https://github.com/hoppscotch/hoppscotch/blob/main/.env.example) file found in repository's root directory with your own keys and rename it to `.env`.
0. Update [`.env.example`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/.env.example) file found in `packages/hoppscotch-app` with your own keys and rename it to `.env`.
_Sample keys only works with the [production build](https://hoppscotch.io)._
@@ -302,9 +305,10 @@ _Sample keys only works with the [production build](https://hoppscotch.io)._
### Local development environment
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
2. Install dependencies by running `npm install` within the directory that you cloned (probably `hoppscotch`).
3. Start the development server with `npm run dev`.
4. Open development site by going to [`http://localhost:3000`](http://localhost:3000) in your browser.
2. Install pnpm using npm by running `npm install -g pnpm`.
3. Install dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
4. Start the development server with `pnpm run dev`.
5. Open development site by going to [`http://localhost:3000`](http://localhost:3000) in your browser.
### Docker compose
@@ -323,9 +327,10 @@ docker run --rm --name hoppscotch -p 3000:3000 hoppscotch/hoppscotch:latest
## **Releasing**
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
2. Install dependencies by running `npm install` within the directory that you cloned (probably `hoppscotch`).
3. Build the release files with `npm run generate`.
4. Find the built project in `./dist`.
2. Install pnpm using npm by running `npm install -g pnpm`.
3. Install dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
4. Build the release files with `pnpm run generate`.
5. Find the built project in `packages/hoppscotch-app/dist`.
## **Contributing**

26
SECURITY.md Normal file
View File

@@ -0,0 +1,26 @@
# Security Policy
This document outlines security procedures and general policies for the Hoppscotch project.
1. [Reporting a security vulnerability](#reporting-a-security-vulnerability)
3. [Incident response process](#incident-response-process)
## Reporting a security vulnerability
Report security vulnerabilities by emailing the Hoppscotch Support team at support@hoppscotch.io.
The primary security point of contact from Hoppscotch Support team will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
**Do not create a GitHub issue ticket to report a security vulnerability.**
The Hoppscotch team and community take all security vulnerability reports in Hoppscotch seriously. Thank you for improving the security of Hoppscotch. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions.
Report security bugs in third-party modules to the person or team maintaining the module.
## Incident response process
In case an incident is discovered or reported, we will follow the following process to contain, respond, and remediate:
1. Confirm the problem and determine the affected versions.
2. Audit code to find any potential similar problems.
3. Prepare fixes for all releases still under maintenance. These fixes will be deployed as fast as possible to production.

View File

@@ -9,16 +9,19 @@ Before you start working on a new language, please look through the [open pull r
if there is no existing translation, you can create a new one by following these steps:
1. **[Fork the repository](https://github.com/hoppscotch/hoppscotch/fork).**
2. **Create a new branch for your translation.**
3. **Create target language file in the [`locales`](https://github.com/hoppscotch/hoppscotch/tree/main/locales) directory.**
4. **Copy the contents of the source file [`locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/locales/en.json) to the target language file.**
5. **Translate the strings in the target language file.**
6. **Add your language entry to [`languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/languages.json).**
7. **Save & commit changes.**
8. **Send a pull request.**
2. **Checkout the `i18n` branch for latest translations.**
3. **Create a new branch for your translation with base branch `i18n`.**
4. **Create target language file in the [`locales`](https://github.com/hoppscotch/hoppscotch/tree/main/packages/hoppscotch-app/locales) directory.**
5. **Copy the contents of the source file [`locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/locales/en.json) to the target language file.**
6. **Translate the strings in the target language file.**
7. **Add your language entry to [`languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/languages.json).**
8. **Save & commit changes.**
9. **Send a pull request.**
_You may send a pull request before all steps above are complete: e.g., you may want to ask for help with translations, or getting tests to pass. However, your pull request will not be merged until all steps above are complete._
`i18n` branch will be merged into `main` branch once every week.
Completing an initial translation of the whole site is a fairly large task. One way to break that task up is to work with other translators through pull requests on your fork. You can also [add collaborators to your fork](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) if you'd like to invite other translators to commit directly to your fork and share responsibility for merging pull requests.
## Updating a translation

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-align-left"><line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line></svg>

Before

Width:  |  Height:  |  Size: 396 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="21 8 21 21 3 21 3 8"></polyline><rect x="1" y="3" width="22" height="5"></rect><line x1="10" y1="12" x2="14" y2="12"></line></svg>

Before

Width:  |  Height:  |  Size: 330 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>

Before

Width:  |  Height:  |  Size: 278 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>

Before

Width:  |  Height:  |  Size: 279 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"></path></svg>

Before

Width:  |  Height:  |  Size: 291 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></svg>

Before

Width:  |  Height:  |  Size: 306 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>

Before

Width:  |  Height:  |  Size: 317 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>

Before

Width:  |  Height:  |  Size: 292 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>

Before

Width:  |  Height:  |  Size: 279 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>

Before

Width:  |  Height:  |  Size: 323 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>

Before

Width:  |  Height:  |  Size: 338 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>

Before

Width:  |  Height:  |  Size: 337 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>

Before

Width:  |  Height:  |  Size: 351 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>

Before

Width:  |  Height:  |  Size: 429 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>

Before

Width:  |  Height:  |  Size: 289 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="12" y1="18" x2="12" y2="12"></line><line x1="9" y1="15" x2="15" y2="15"></line></svg>

Before

Width:  |  Height:  |  Size: 398 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>

Before

Width:  |  Height:  |  Size: 440 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>

Before

Width:  |  Height:  |  Size: 309 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path><line x1="9" y1="14" x2="15" y2="14"></line></svg>

Before

Width:  |  Height:  |  Size: 325 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path><line x1="12" y1="11" x2="12" y2="17"></line><line x1="9" y1="14" x2="15" y2="14"></line></svg>

Before

Width:  |  Height:  |  Size: 370 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>

Before

Width:  |  Height:  |  Size: 281 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 12 20 22 4 22 4 12"></polyline><rect x="2" y="7" width="20" height="5"></rect><line x1="12" y1="22" x2="12" y2="7"></line><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"></path><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"></path></svg>

Before

Width:  |  Height:  |  Size: 453 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>

Before

Width:  |  Height:  |  Size: 497 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>

Before

Width:  |  Height:  |  Size: 380 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>

Before

Width:  |  Height:  |  Size: 330 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>

Before

Width:  |  Height:  |  Size: 304 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path></svg>

Before

Width:  |  Height:  |  Size: 376 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>

Before

Width:  |  Height:  |  Size: 319 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path></svg>

Before

Width:  |  Height:  |  Size: 325 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>

Before

Width:  |  Height:  |  Size: 335 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="4"></circle><line x1="4.93" y1="4.93" x2="9.17" y2="9.17"></line><line x1="14.83" y1="14.83" x2="19.07" y2="19.07"></line><line x1="14.83" y1="9.17" x2="19.07" y2="4.93"></line><line x1="14.83" y1="9.17" x2="18.36" y2="5.64"></line><line x1="4.93" y1="19.07" x2="9.17" y2="14.83"></line></svg>

Before

Width:  |  Height:  |  Size: 542 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line></svg>

Before

Width:  |  Height:  |  Size: 325 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="2" x2="12" y2="6"></line><line x1="12" y1="18" x2="12" y2="22"></line><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line><line x1="2" y1="12" x2="6" y2="12"></line><line x1="18" y1="12" x2="22" y2="12"></line><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line></svg>

Before

Width:  |  Height:  |  Size: 584 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>

Before

Width:  |  Height:  |  Size: 293 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>

Before

Width:  |  Height:  |  Size: 336 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>

Before

Width:  |  Height:  |  Size: 326 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" y1="3" x2="14" y2="10"></line><line x1="3" y1="21" x2="10" y2="14"></line></svg>

Before

Width:  |  Height:  |  Size: 366 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path></svg>

Before

Width:  |  Height:  |  Size: 299 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>

Before

Width:  |  Height:  |  Size: 390 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 14 10 14 10 20"></polyline><polyline points="20 10 14 10 14 4"></polyline><line x1="14" y1="10" x2="21" y2="3"></line><line x1="3" y1="21" x2="10" y2="14"></line></svg>

Before

Width:  |  Height:  |  Size: 370 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"></path></svg>

Before

Width:  |  Height:  |  Size: 299 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line></svg>

Before

Width:  |  Height:  |  Size: 339 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>

Before

Width:  |  Height:  |  Size: 253 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="5" r="1"></circle><circle cx="12" cy="19" r="1"></circle></svg>

Before

Width:  |  Height:  |  Size: 304 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>

Before

Width:  |  Height:  |  Size: 319 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>

Before

Width:  |  Height:  |  Size: 316 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>

Before

Width:  |  Height:  |  Size: 276 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>

Before

Width:  |  Height:  |  Size: 366 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>

Before

Width:  |  Height:  |  Size: 283 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>

Before

Width:  |  Height:  |  Size: 364 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>

Before

Width:  |  Height:  |  Size: 278 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>

Before

Width:  |  Height:  |  Size: 978 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg>

Before

Width:  |  Height:  |  Size: 414 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="9" y1="3" x2="9" y2="21"></line></svg>

Before

Width:  |  Height:  |  Size: 292 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>

Before

Width:  |  Height:  |  Size: 319 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>

Before

Width:  |  Height:  |  Size: 311 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>

Before

Width:  |  Height:  |  Size: 623 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>

Before

Width:  |  Height:  |  Size: 278 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>

Before

Width:  |  Height:  |  Size: 417 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>

Before

Width:  |  Height:  |  Size: 327 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>

Before

Width:  |  Height:  |  Size: 377 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line></svg>

Before

Width:  |  Height:  |  Size: 324 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 16 12 12 8 16"></polyline><line x1="12" y1="12" x2="12" y2="21"></line><path d="M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3"></path><polyline points="16 16 12 12 8 16"></polyline></svg>

Before

Width:  |  Height:  |  Size: 395 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="20" y1="8" x2="20" y2="14"></line><line x1="23" y1="11" x2="17" y2="11"></line></svg>

Before

Width:  |  Height:  |  Size: 375 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>

Before

Width:  |  Height:  |  Size: 285 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>

Before

Width:  |  Height:  |  Size: 371 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>

Before

Width:  |  Height:  |  Size: 274 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>

Before

Width:  |  Height:  |  Size: 255 B

View File

@@ -1,26 +0,0 @@
<template>
<div class="bg-error flex justify-between">
<span
class="
flex
py-2
px-4
transition
relative
items-center
justify-center
group
"
>
<i class="mr-2 material-icons">info_outline</i>
<span class="text-secondaryDark">
<span class="md:hidden">
{{ $t("helpers.offline_short") }}
</span>
<span class="hidden md:inline">
{{ $t("helpers.offline") }}
</span>
</span>
</span>
</div>
</template>

View File

@@ -1,185 +0,0 @@
<template>
<div>
<div class="flex justify-between">
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="LEFT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
svg="sidebar"
:class="{ 'transform -rotate-180': !LEFT_SIDEBAR }"
@click.native="LEFT_SIDEBAR = !LEFT_SIDEBAR"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${
ZEN_MODE ? $t('action.turn_off') : $t('action.turn_on')
} ${$t('layout.zen_mode')}`"
:svg="ZEN_MODE ? 'minimize' : 'maximize'"
:class="{
'!text-accent !focus-visible:text-accentDark !hover:text-accentDark':
ZEN_MODE,
}"
@click.native="ZEN_MODE = !ZEN_MODE"
/>
</div>
<div class="flex">
<span>
<tippy
ref="options"
interactive
trigger="click"
theme="popover"
arrow
>
<template #trigger>
<ButtonSecondary
svg="help-circle"
class="!rounded-none"
:label="$t('app.help')"
/>
</template>
<div class="flex flex-col">
<SmartItem
svg="book"
:label="$t('app.documentation')"
to="https://docs.hoppscotch.io"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
svg="zap"
:label="$t('app.keyboard_shortcuts')"
@click.native="
showShortcuts = true
$refs.options.tippy().hide()
"
/>
<SmartItem
svg="gift"
:label="$t('app.whats_new')"
to="https://docs.hoppscotch.io/changelog"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
svg="message-circle"
:label="$t('app.chat_with_us')"
@click.native="
chatWithUs()
$refs.options.tippy().hide()
"
/>
<hr />
<SmartItem
svg="twitter"
:label="$t('app.twitter')"
to="https://hoppscotch.io/twitter"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
svg="user-plus"
:label="$t('app.invite')"
@click.native="
showShare = true
$refs.options.tippy().hide()
"
/>
<SmartItem
svg="lock"
:label="$t('app.terms_and_privacy')"
to="https://docs.hoppscotch.io/privacy"
blank
@click.native="$refs.options.tippy().hide()"
/>
<!-- <SmartItem :label="$t('app.status')" /> -->
<div class="flex opacity-50 py-2 px-4">
{{ `${$t("app.name")} ${$t("app.version")}` }}
</div>
</div>
</tippy>
</span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
svg="zap"
:title="$t('app.shortcuts')"
@click.native="showShortcuts = true"
/>
<ButtonSecondary
v-if="navigatorShare"
v-tippy="{ theme: 'tooltip' }"
svg="share-2"
:title="$t('request.share')"
@click.native="nativeShare()"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="RIGHT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
svg="sidebar"
class="transform rotate-180"
:class="{ 'rotate-360': !RIGHT_SIDEBAR }"
@click.native="RIGHT_SIDEBAR = !RIGHT_SIDEBAR"
/>
</div>
</div>
<AppShortcuts :show="showShortcuts" @close="showShortcuts = false" />
<AppShare :show="showShare" @hide-modal="showShare = false" />
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api"
import { defineActionHandler } from "~/helpers/actions"
import { showChat } from "~/helpers/support"
import { useSetting } from "~/newstore/settings"
export default defineComponent({
setup() {
const showShortcuts = ref(false)
const showShare = ref(false)
defineActionHandler("flyouts.keybinds.toggle", () => {
showShortcuts.value = !showShortcuts.value
})
defineActionHandler("modals.share.toggle", () => {
showShare.value = !showShare.value
})
return {
LEFT_SIDEBAR: useSetting("LEFT_SIDEBAR"),
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
ZEN_MODE: useSetting("ZEN_MODE"),
navigatorShare: !!navigator.share,
showShortcuts,
showShare,
}
},
watch: {
ZEN_MODE() {
this.LEFT_SIDEBAR = !this.ZEN_MODE
},
},
methods: {
nativeShare() {
if (navigator.share) {
navigator
.share({
title: "Hoppscotch",
text: "Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.",
url: "https://hoppscotch.io",
})
.then(() => {})
.catch(console.error)
} else {
// fallback
}
},
chatWithUs() {
showChat()
},
},
})
</script>

View File

@@ -1,38 +0,0 @@
<template>
<div key="outputHash">
<AppPowerSearchEntry
v-for="(shortcut, shortcutIndex) in searchResults"
:key="`shortcut-${shortcutIndex}`"
:ref="`item-${shortcutIndex}`"
:shortcut="shortcut.item"
@action="$emit('action', shortcut.item.action)"
/>
<div
v-if="searchResults.length === 0"
class="flex flex-col text-secondaryLight p-4 items-center justify-center"
>
<i class="opacity-75 pb-2 material-icons">manage_search</i>
<span class="text-center">
{{ $t("state.nothing_found") }} "{{ search }}"
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from "@nuxtjs/composition-api"
import Fuse from "fuse.js"
const props = defineProps<{
input: Record<string, any>[]
search: string
}>()
const options = {
keys: ["keys", "label", "action", "tags"],
}
const fuse = new Fuse(props.input, options)
const searchResults = computed(() => fuse.search(props.search))
</script>

View File

@@ -1,166 +0,0 @@
<template>
<div>
<header
class="flex space-x-2 flex-1 py-2 px-2 items-center justify-between"
>
<div class="space-x-2 inline-flex items-center">
<ButtonSecondary
class="tracking-wide !font-bold !text-secondaryDark"
label="HOPPSCOTCH"
to="/"
/>
<AppGitHubStarButton class="mt-1.5 transition hidden sm:flex" />
</div>
<div class="space-x-2 inline-flex items-center">
<ButtonSecondary
id="installPWA"
v-tippy="{ theme: 'tooltip' }"
:title="$t('header.install_pwa')"
svg="download"
class="rounded"
@click.native="showInstallPrompt()"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${$t('app.search')} <kbd>/</kbd>`"
svg="search"
class="rounded"
@click.native="showSearch = true"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${$t('support.title')} <kbd>?</kbd>`"
svg="life-buoy"
class="rounded"
@click.native="showSupport = true"
/>
<ButtonSecondary
v-if="currentUser === null"
svg="upload-cloud"
:label="$t('header.save_workspace')"
filled
class="hidden !font-semibold md:flex"
@click.native="showLogin = true"
/>
<ButtonPrimary
v-if="currentUser === null"
:label="$t('header.login')"
@click.native="showLogin = true"
/>
<span v-else class="px-2">
<tippy ref="user" interactive trigger="click" theme="popover" arrow>
<template #trigger>
<ProfilePicture
v-if="currentUser.photoURL"
v-tippy="{
theme: 'tooltip',
}"
:url="currentUser.photoURL"
:alt="currentUser.displayName"
:title="currentUser.displayName"
indicator
:indicator-styles="isOnLine ? 'bg-green-500' : 'bg-red-500'"
/>
<ButtonSecondary
v-else
v-tippy="{ theme: 'tooltip' }"
:title="$t('header.account')"
class="rounded"
svg="user"
/>
</template>
<SmartItem
to="/settings"
svg="settings"
:label="$t('navigation.settings')"
@click.native="$refs.user.tippy().hide()"
/>
<FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" />
</tippy>
</span>
</div>
</header>
<AppAnnouncement v-if="!isOnLine" />
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
<AppSupport :show="showSupport" @hide-modal="showSupport = false" />
<AppPowerSearch :show="showSearch" @hide-modal="showSearch = false" />
</div>
</template>
<script>
import { defineComponent, ref } from "@nuxtjs/composition-api"
import intializePwa from "~/helpers/pwa"
import { currentUser$ } from "~/helpers/fb/auth"
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
import { useReadonlyStream } from "~/helpers/utils/composables"
import { defineActionHandler } from "~/helpers/actions"
export default defineComponent({
setup() {
const showSupport = ref(false)
const showSearch = ref(false)
defineActionHandler("modals.support.toggle", () => {
showSupport.value = !showSupport.value
})
defineActionHandler("modals.search.toggle", () => {
showSearch.value = !showSearch.value
})
return {
currentUser: useReadonlyStream(currentUser$, null),
showSupport,
showSearch,
}
},
data() {
return {
// Once the PWA code is initialized, this holds a method
// that can be called to show the user the installation
// prompt.
showInstallPrompt: null,
showLogin: false,
isOnLine: navigator.onLine,
}
},
async mounted() {
window.addEventListener("online", () => {
this.isOnLine = true
})
window.addEventListener("offline", () => {
this.isOnLine = false
})
// Initializes the PWA code - checks if the app is installed,
// etc.
this.showInstallPrompt = await intializePwa()
const cookiesAllowed = getLocalConfig("cookiesAllowed") === "yes"
if (!cookiesAllowed) {
this.$toast.show(this.$t("app.we_use_cookies").toString(), {
icon: "cookie",
duration: 0,
action: [
{
text: this.$t("action.learn_more").toString(),
onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0)
window
.open("https://docs.hoppscotch.io/privacy", "_blank")
.focus()
},
},
{
text: this.$t("action.dismiss").toString(),
onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0)
},
},
],
})
}
},
})
</script>

View File

@@ -1,77 +0,0 @@
<template>
<SmartModal v-if="show" full-width @close="$emit('hide-modal')">
<template #body>
<input
id="command"
v-model="search"
v-focus
type="text"
autocomplete="off"
name="command"
:placeholder="$t('app.type_a_command_search').toString()"
class="
bg-transparent
border-b border-dividerLight
flex flex-shrink-0
text-secondaryDark text-base
p-6
"
/>
<AppFuse
v-if="search"
:input="fuse"
:search="search"
@action="runAction"
/>
<div
v-else
class="
divide-y divide-dividerLight
flex flex-col
space-y-4
flex-1
overflow-auto
hide-scrollbar
"
>
<div v-for="(map, mapIndex) in mappings" :key="`map-${mapIndex}`">
<h5 class="my-2 text-secondaryLight py-2 px-6">
{{ $t(map.section) }}
</h5>
<AppPowerSearchEntry
v-for="(shortcut, shortcutIndex) in map.shortcuts"
:key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
:shortcut="shortcut"
@action="runAction"
/>
</div>
</div>
</template>
</SmartModal>
</template>
<script setup lang="ts">
import { ref } from "@nuxtjs/composition-api"
import { HoppAction, invokeAction } from "~/helpers/actions"
import { spotlight as mappings, fuse } from "~/helpers/shortcuts"
defineProps<{
show: boolean
}>()
const emit = defineEmits<{
(e: "hide-modal"): void
}>()
const search = ref("")
const hideModal = () => {
search.value = ""
emit("hide-modal")
}
const runAction = (command: HoppAction) => {
invokeAction(command)
hideModal()
}
</script>

View File

@@ -1,66 +0,0 @@
<template>
<div
class="
cursor-pointer
flex
py-2
px-6
transition
items-center
group
hover:bg-primaryLight
focus:outline-none
focus-visible:bg-primaryLight
"
tabindex="0"
@click="$emit('action', shortcut.action)"
@keydown.enter="$emit('action', shortcut.action)"
>
<SmartIcon
class="
mr-4
opacity-75
transition
svg-icons
group-hover:opacity-100
group-focus:opacity-100
"
:name="shortcut.icon"
/>
<span
class="
flex flex-1
mr-4
transition
group-hover:text-secondaryDark
group-focus:text-secondaryDark
"
>
{{ $t(shortcut.label) }}
</span>
<span
v-for="(key, keyIndex) in shortcut.keys"
:key="`key-${keyIndex}`"
class="shortcut-key"
>
{{ key }}
</span>
</div>
</template>
<script setup lang="ts">
defineProps<{
shortcut: Object
}>()
</script>
<style lang="scss" scoped>
.shortcut-key {
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply py-1;
@apply px-2;
@apply inline-flex;
}
</style>

View File

@@ -1,18 +0,0 @@
<template>
<section :id="label.toLowerCase()" class="flex flex-col flex-1 relative">
<slot></slot>
</section>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
export default defineComponent({
props: {
label: {
type: String,
default: "Section",
},
},
})
</script>

View File

@@ -1,125 +0,0 @@
<template>
<SmartModal
v-if="show"
:title="$t('app.invite_your_friends')"
@close="$emit('hide-modal')"
>
<template #body>
<p class="text-secondaryLight mb-8 px-2">
{{ $t("app.invite_description") }}
</p>
<div class="flex flex-col space-y-2 px-2">
<div class="grid gap-4 grid-cols-3">
<a
v-for="(platform, index) in platforms"
:key="`platform-${index}`"
:href="platform.link"
target="_blank"
class="share-link"
>
<SmartIcon :name="platform.icon" class="h-6 w-6" />
<span class="mt-3">
{{ platform.name }}
</span>
</a>
<button class="share-link" @click="copyAppLink">
<SmartIcon class="h-6 text-xl w-6" :name="copyIcon" />
<span class="mt-3">
{{ $t("app.copy") }}
</span>
</button>
</div>
</div>
</template>
</SmartModal>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { copyToClipboard } from "~/helpers/utils/clipboard"
export default defineComponent({
props: {
show: Boolean,
},
data() {
const url = "https://hoppscotch.io"
const text = "Hoppscotch - Open source API development ecosystem."
const description =
"Helps you create requests faster, saving precious time on development."
const subject =
"Checkout Hoppscotch - an open source API development ecosystem"
const summary = `Hi there!%0D%0A%0D%0AI thought youll like this new platform that I joined called Hoppscotch - https://hoppscotch.io.%0D%0AIt is a simple and intuitive interface for creating and managing your APIs. You can build, test, document, and share your APIs.%0D%0A%0D%0AThe best part about Hoppscotch is that it is open source and free to get started.%0D%0A%0D%0A`
const twitter = "hoppscotch_io"
return {
url: "https://hoppscotch.io",
copyIcon: "copy",
platforms: [
{
name: "Email",
icon: "mail",
link: `mailto:?subject=${subject}&body=${summary}`,
},
{
name: "Twitter",
icon: "brands/twitter",
link: `https://twitter.com/intent/tweet?text=${text} ${description}&url=${url}&via=${twitter}`,
},
{
name: "Facebook",
icon: "brands/facebook",
link: `https://www.facebook.com/sharer/sharer.php?u=${url}`,
},
{
name: "Reddit",
icon: "brands/reddit",
link: `https://www.reddit.com/submit?url=${url}&title=${text}`,
},
{
name: "LinkedIn",
icon: "brands/linkedin",
link: `https://www.linkedin.com/sharing/share-offsite/?url=${url}`,
},
],
}
},
methods: {
copyAppLink() {
copyToClipboard(this.url)
this.copyIcon = "check"
this.$toast.success(this.$t("state.copied_to_clipboard").toString(), {
icon: "content_paste",
})
setTimeout(() => (this.copyIcon = "copy"), 1000)
},
hideModal() {
this.$emit("hide-modal")
},
},
})
</script>
<style lang="scss" scoped>
.share-link {
@apply border border-dividerLight;
@apply rounded;
@apply flex-col flex;
@apply p-4;
@apply items-center;
@apply justify-center;
@apply hover:(bg-primaryLight text-secondaryDark);
@apply focus:outline-none;
@apply focus-visible:border-divider;
svg {
@apply opacity-80;
}
&:hover {
svg {
@apply opacity-100;
}
}
}
</style>

View File

@@ -1,69 +0,0 @@
<template>
<div>
<transition v-if="show" name="fade" appear>
<div class="inset-0 transition-opacity z-20 fixed" @keydown.esc="close()">
<div
class="bg-primaryDark opacity-90 inset-0 absolute"
tabindex="0"
@click="close()"
></div>
</div>
</transition>
<aside
class="
bg-primary
flex flex-col
h-full
max-w-full
transform
transition
top-0
ease-in-out
right-0
w-96
z-30
duration-300
fixed
overflow-auto
"
:class="show ? 'shadow-xl translate-x-0' : 'translate-x-full'"
>
<slot name="content"></slot>
</aside>
</div>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
export default defineComponent({
props: {
show: {
type: Boolean,
required: true,
default: false,
},
},
watch: {
show: {
immediate: true,
handler(show) {
if (process.client) {
if (show) document.body.style.setProperty("overflow", "hidden")
else document.body.style.removeProperty("overflow")
}
},
},
},
mounted() {
document.addEventListener("keydown", (e) => {
if (e.keyCode === 27 && this.show) this.close()
})
},
methods: {
close() {
this.$emit("close")
},
},
})
</script>

View File

@@ -1,243 +0,0 @@
<template>
<SmartModal v-if="show" :title="$t('collection.save_as')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<div class="flex relative">
<input
id="selectLabelSaveReq"
v-model="requestName"
v-focus
class="input floating-input"
placeholder=" "
type="text"
autocomplete="off"
@keyup.enter="saveRequestAs"
/>
<label for="selectLabelSaveReq">
{{ $t("request.name") }}
</label>
</div>
<label class="px-4 pt-4 pb-4">
{{ $t("collection.select_location") }}
</label>
<CollectionsGraphql
v-if="mode === 'graphql'"
:doc="false"
:show-coll-actions="false"
:picked="picked"
:saving-mode="true"
@select="onSelect"
/>
<Collections
v-else
:picked="picked"
:save-request="true"
@select="onSelect"
@update-collection="collectionsType.type = $event"
@update-coll-type="onUpdateCollType"
/>
</div>
</template>
<template #footer>
<span>
<ButtonPrimary
:label="$t('action.save')"
@click.native="saveRequestAs"
/>
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import * as teamUtils from "~/helpers/teams/utils"
import {
saveRESTRequestAs,
editRESTRequest,
editGraphqlRequest,
saveGraphqlRequestAs,
} from "~/newstore/collections"
import { getGQLSession, useGQLRequestName } from "~/newstore/GQLSession"
import {
getRESTRequest,
useRESTRequestName,
setRESTSaveContext,
} from "~/newstore/RESTSession"
export default defineComponent({
props: {
// mode can be either "graphql" or "rest"
mode: { type: String, default: "rest" },
show: Boolean,
},
setup(props) {
return {
requestName:
props.mode === "rest" ? useRESTRequestName() : useGQLRequestName(),
}
},
data() {
return {
requestData: {
name: this.requestName,
collectionIndex: undefined,
folderName: undefined,
requestIndex: undefined,
},
collectionsType: {
type: "my-collections",
selectedTeam: undefined,
},
picked: null,
}
},
watch: {
"requestData.collectionIndex": function resetFolderAndRequestIndex() {
// if user has chosen some folder, than selected other collection, which doesn't have any folders
// than `requestUpdateData.folderName` won't be reseted
this.$data.requestData.folderName = undefined
this.$data.requestData.requestIndex = undefined
},
"requestData.folderName": function resetRequestIndex() {
this.$data.requestData.requestIndex = undefined
},
editingRequest({ name }) {
this.$data.requestData.name = name || this.$data.defaultRequestName
},
},
methods: {
onUpdateCollType(newCollType) {
this.collectionsType = newCollType
},
onSelect({ picked }) {
this.picked = picked
},
async saveRequestAs() {
if (!this.requestName) {
this.$toast.error(this.$t("error.empty_req_name"), {
icon: "error_outline",
})
return
}
if (this.picked == null) {
this.$toast.error(this.$t("collection.select"), {
icon: "error_outline",
})
return
}
const requestUpdated =
this.mode === "rest" ? getRESTRequest() : getGQLSession()
// Filter out all REST file inputs
if (this.mode === "rest" && requestUpdated.bodyParams) {
requestUpdated.bodyParams = requestUpdated.bodyParams.map((param) =>
param?.value?.[0] instanceof File ? { ...param, value: "" } : param
)
}
if (this.picked.pickedType === "my-request") {
editRESTRequest(
this.picked.folderPath,
this.picked.requestIndex,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: this.picked.folderPath,
requestIndex: this.picked.requestIndex,
})
} else if (this.picked.pickedType === "my-folder") {
const insertionIndex = saveRESTRequestAs(
this.picked.folderPath,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: this.picked.folderPath,
requestIndex: insertionIndex,
})
} else if (this.picked.pickedType === "my-collection") {
const insertionIndex = saveRESTRequestAs(
`${this.picked.collectionIndex}`,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: `${this.picked.collectionIndex}`,
requestIndex: insertionIndex,
})
} else if (this.picked.pickedType === "teams-request") {
teamUtils.overwriteRequestTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.picked.requestID
)
setRESTSaveContext({
originLocation: "team-collection",
requestID: this.picked.requestID,
})
} else if (this.picked.pickedType === "teams-folder") {
const req = await teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.folderID
)
if (req && req.id) {
setRESTSaveContext({
originLocation: "team-collection",
requestID: req.id,
teamID: this.collectionsType.selectedTeam.id,
collectionID: this.picked.folderID,
})
}
} else if (this.picked.pickedType === "teams-collection") {
const req = await teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.collectionID
)
if (req && req.id) {
setRESTSaveContext({
originLocation: "team-collection",
requestID: req.id,
teamID: this.collectionsType.selectedTeam.id,
collectionID: this.picked.collectionID,
})
}
} else if (this.picked.pickedType === "gql-my-request") {
editGraphqlRequest(
this.picked.folderPath,
this.picked.requestIndex,
requestUpdated
)
} else if (this.picked.pickedType === "gql-my-folder") {
saveGraphqlRequestAs(this.picked.folderPath, requestUpdated)
} else if (this.picked.pickedType === "gql-my-collection") {
saveGraphqlRequestAs(`${this.picked.collectionIndex}`, requestUpdated)
}
this.$toast.success(this.$t("request.added"), {
icon: "post_add",
})
this.hideModal()
},
hideModal() {
this.picked = null
this.$emit("hide-modal")
},
},
})
</script>

View File

@@ -1,254 +0,0 @@
<template>
<div class="opacity-0 show-if-initialized" :class="{ initialized }">
<pre ref="editor" :class="styles"></pre>
</div>
</template>
<script>
import ace from "ace-builds"
import "ace-builds/webpack-resolver"
import "ace-builds/src-noconflict/ext-language_tools"
import "ace-builds/src-noconflict/mode-graphqlschema"
import * as gql from "graphql"
import { getAutocompleteSuggestions } from "graphql-language-service-interface"
import { defineComponent } from "@nuxtjs/composition-api"
import { defineGQLLanguageMode } from "~/helpers/syntax/gqlQueryLangMode"
import debounce from "~/helpers/utils/debounce"
export default defineComponent({
props: {
value: {
type: String,
default: "",
},
theme: {
type: String,
required: false,
default: null,
},
onRunGQLQuery: {
type: Function,
default: () => {},
},
options: {
type: Object,
default: () => {},
},
styles: {
type: String,
default: "",
},
},
data() {
return {
initialized: false,
editor: null,
cacheValue: "",
validationSchema: null,
}
},
computed: {
appFontSize() {
return getComputedStyle(document.documentElement).getPropertyValue(
"--body-font-size"
)
},
},
watch: {
value(value) {
if (value !== this.cacheValue) {
this.editor.session.setValue(value, 1)
this.cacheValue = value
}
},
theme() {
this.initialized = false
this.editor.setTheme(`ace/theme/${this.defineTheme()}`, () => {
this.$nextTick().then(() => {
this.initialized = true
})
})
},
options(value) {
this.editor.setOptions(value)
},
},
mounted() {
defineGQLLanguageMode(ace)
const langTools = ace.require("ace/ext/language_tools")
const editor = ace.edit(this.$refs.editor, {
mode: `ace/mode/gql-query`,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
...this.options,
})
// Set the theme and show the editor only after it's been set to prevent FOUC.
editor.setTheme(`ace/theme/${this.defineTheme()}`, () => {
this.$nextTick().then(() => {
this.initialized = true
})
})
// Set the theme and show the editor only after it's been set to prevent FOUC.
editor.setTheme(`ace/theme/${this.defineTheme()}`, () => {
this.$nextTick().then(() => {
this.initialized = true
})
})
editor.setFontSize(this.appFontSize)
const completer = {
getCompletions: (
editor,
_session,
{ row, column },
_prefix,
callback
) => {
if (this.validationSchema) {
const completions = getAutocompleteSuggestions(
this.validationSchema,
editor.getValue(),
{
line: row,
character: column,
}
)
callback(
null,
completions.map(({ label, detail }) => ({
name: label,
value: label,
score: 1.0,
meta: detail,
}))
)
} else {
callback(null, [])
}
},
}
langTools.setCompleters([completer])
if (this.value) editor.setValue(this.value, 1)
this.editor = editor
this.cacheValue = this.value
editor.commands.addCommand({
name: "runGQLQuery",
exec: () => this.onRunGQLQuery(this.editor.getValue()),
bindKey: {
mac: "cmd-enter",
win: "ctrl-enter",
},
})
editor.commands.addCommand({
name: "prettifyGQLQuery",
exec: () => this.prettifyQuery(),
bindKey: {
mac: "cmd-p",
win: "ctrl-p",
},
})
editor.on("change", () => {
const content = editor.getValue()
this.$emit("input", content)
this.parseContents(content)
this.cacheValue = content
})
this.parseContents(this.value)
},
beforeDestroy() {
this.editor.destroy()
},
methods: {
prettifyQuery() {
try {
this.$emit("update-query", gql.print(gql.parse(this.editor.getValue())))
} catch (e) {
this.$toast.error(this.$t("error.gql_prettify_invalid_query"), {
icon: "error_outline",
})
}
},
defineTheme() {
if (this.theme) {
return this.theme
}
const strip = (str) =>
str.replace(/#/g, "").replace(/ /g, "").replace(/"/g, "")
return strip(
window
.getComputedStyle(document.documentElement)
.getPropertyValue("--editor-theme")
)
},
setValidationSchema(schema) {
this.validationSchema = schema
this.parseContents(this.cacheValue)
},
parseContents: debounce(function (content) {
if (content !== "") {
try {
const doc = gql.parse(content)
if (this.validationSchema) {
this.editor.session.setAnnotations(
gql
.validate(this.validationSchema, doc)
.map(({ locations, message }) => ({
row: locations[0].line - 1,
column: locations[0].column - 1,
text: message,
type: "error",
}))
)
}
} catch (e) {
this.editor.session.setAnnotations([
{
row: e.locations[0].line - 1,
column: e.locations[0].column - 1,
text: e.message,
type: "error",
},
])
}
} else {
this.editor.session.setAnnotations([])
}
}, 2000),
},
})
</script>
<style scoped lang="scss">
.show-if-initialized {
&.initialized {
@apply opacity-100;
}
& > * {
@apply transition-none;
}
}
</style>

View File

@@ -1,77 +0,0 @@
<template>
<div class="bg-primary flex p-4 top-0 z-10 sticky">
<div class="space-x-2 flex-1 inline-flex">
<input
id="url"
v-model="url"
v-focus
type="url"
autocomplete="off"
spellcheck="false"
class="
bg-primaryLight
border border-divider
rounded
text-secondaryDark
w-full
py-2
px-4
hover:border-dividerDark
focus-visible:bg-transparent focus-visible:border-dividerDark
"
:placeholder="$t('request.url')"
@keyup.enter="onConnectClick"
/>
<ButtonPrimary
id="get"
name="get"
:label="!connected ? $t('action.connect') : $t('action.disconnect')"
class="w-32"
@click.native="onConnectClick"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "@nuxtjs/composition-api"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import { GQLConnection } from "~/helpers/GQLConnection"
import { getCurrentStrategyID } from "~/helpers/network"
import { useReadonlyStream, useStream } from "~/helpers/utils/composables"
import { gqlHeaders$, gqlURL$, setGQLURL } from "~/newstore/GQLSession"
export default defineComponent({
props: {
conn: {
type: Object as PropType<GQLConnection>,
required: true,
},
},
setup(props) {
const connected = useReadonlyStream(props.conn.connected$, false)
const headers = useReadonlyStream(gqlHeaders$, [])
const url = useStream(gqlURL$, "", setGQLURL)
const onConnectClick = () => {
if (!connected.value) {
props.conn.connect(url.value, headers.value as any)
logHoppRequestRunToAnalytics({
platform: "graphql-schema",
strategy: getCurrentStrategyID(),
})
} else {
props.conn.disconnect()
}
}
return {
url,
connected,
onConnectClick,
}
},
})
</script>

View File

@@ -1,555 +0,0 @@
<template>
<div>
<SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10">
<SmartTab :id="'query'" :label="$t('tab.query')" :selected="true">
<AppSection label="query">
<div
class="
bg-primary
border-b border-dividerLight
flex flex-1
top-upperSecondaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
gqlRunQuery
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("request.query") }}
</label>
<div class="flex">
<ButtonSecondary
:label="$t('request.run')"
svg="play"
class="rounded-none !text-accent"
@click.native="runQuery()"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')"
:svg="copyQueryIcon"
@click.native="copyQuery"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${$t(
'action.prettify'
)} <kbd>${getSpecialKey()}</kbd><kbd>P</kbd>`"
:svg="prettifyQueryIcon"
@click.native="prettifyQuery"
/>
<ButtonSecondary
ref="saveRequest"
v-tippy="{ theme: 'tooltip' }"
:title="$t('request.save')"
svg="folder-plus"
@click.native="saveRequest"
/>
</div>
</div>
<GraphqlQueryEditor
ref="queryEditor"
v-model="gqlQueryString"
:on-run-g-q-l-query="runQuery"
:options="{
maxLines: Infinity,
minLines: 16,
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false,
}"
styles="border-b border-dividerLight"
@update-query="updateQuery"
/>
</AppSection>
</SmartTab>
<SmartTab :id="'variables'" :label="$t('tab.variables')">
<AppSection label="variables">
<div
class="
bg-primary
border-b border-dividerLight
flex flex-1
top-upperSecondaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("request.variables") }}
</label>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')"
:svg="copyVariablesIcon"
@click.native="copyVariables"
/>
</div>
</div>
<SmartAceEditor
ref="variableEditor"
v-model="variableString"
:lang="'json'"
:options="{
maxLines: Infinity,
minLines: 16,
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false,
}"
styles="border-b border-dividerLight"
/>
</AppSection>
</SmartTab>
<SmartTab :id="'headers'" :label="$t('tab.headers')">
<AppSection label="headers">
<div
class="
bg-primary
border-b border-dividerLight
flex flex-1
top-upperSecondaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("tab.headers") }}
</label>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')"
svg="trash-2"
:disabled="bulkMode"
@click.native="headers = []"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')"
svg="edit"
:class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')"
svg="plus"
:disabled="bulkMode"
@click.native="addRequestHeader"
/>
</div>
</div>
<div v-if="bulkMode" class="flex">
<textarea-autosize
v-model="bulkHeaders"
v-focus
name="bulk-parameters"
class="
bg-transparent
border-b border-dividerLight
flex
font-mono
flex-1
py-2
px-4
whitespace-pre
resize-y
overflow-auto
"
rows="10"
:placeholder="$t('state.bulk_mode_placeholder')"
/>
</div>
<div v-else>
<div
v-for="(header, index) in headers"
:key="`header-${index}`"
class="
divide-x divide-dividerLight
border-b border-dividerLight
flex
"
>
<SmartAutoComplete
:placeholder="$t('count.header', { count: index + 1 })"
:source="commonHeaders"
:spellcheck="false"
:value="header.key"
autofocus
styles="
bg-transparent
flex
flex-1
py-1
px-4
truncate
focus:outline-none
"
@input="
updateGQLHeader(index, {
key: $event,
value: header.value,
active: header.active,
})
"
/>
<input
class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('count.value', { count: index + 1 })"
:name="`value ${index}`"
:value="header.value"
autofocus
@change="
updateGQLHeader(index, {
key: header.key,
value: $event.target.value,
active: header.active,
})
"
/>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="
header.hasOwnProperty('active')
? header.active
? $t('action.turn_off')
: $t('action.turn_on')
: $t('action.turn_off')
"
:svg="
header.hasOwnProperty('active')
? header.active
? 'check-circle'
: 'circle'
: 'check-circle'
"
color="green"
@click.native="
updateGQLHeader(index, {
key: header.key,
value: header.value,
active: !header.active,
})
"
/>
</span>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')"
svg="trash"
color="red"
@click.native="removeRequestHeader(index)"
/>
</span>
</div>
<div
v-if="headers.length === 0"
class="
flex flex-col
text-secondaryLight
p-4
items-center
justify-center
"
>
<span class="text-center pb-4">
{{ $t("empty.headers") }}
</span>
<ButtonSecondary
:label="$t('add.new')"
filled
svg="plus"
@click.native="addRequestHeader"
/>
</div>
</div>
</AppSection>
</SmartTab>
</SmartTabs>
<CollectionsSaveRequest
mode="graphql"
:show="showSaveRequestModal"
@hide-modal="hideRequestModal"
/>
</div>
</template>
<script lang="ts">
import {
defineComponent,
onMounted,
PropType,
ref,
useContext,
watch,
} from "@nuxtjs/composition-api"
import clone from "lodash/clone"
import { getPlatformSpecialKey } from "~/helpers/platformutils"
import { copyToClipboard } from "~/helpers/utils/clipboard"
import {
useNuxt,
useReadonlyStream,
useStream,
} from "~/helpers/utils/composables"
import {
addGQLHeader,
gqlHeaders$,
gqlQuery$,
gqlResponse$,
gqlURL$,
gqlVariables$,
removeGQLHeader,
setGQLHeaders,
setGQLQuery,
setGQLResponse,
setGQLVariables,
updateGQLHeader,
} from "~/newstore/GQLSession"
import { commonHeaders } from "~/helpers/headers"
import { GQLConnection } from "~/helpers/GQLConnection"
import { makeGQLHistoryEntry, addGraphqlHistoryEntry } from "~/newstore/history"
import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
import { getCurrentStrategyID } from "~/helpers/network"
import { makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
export default defineComponent({
props: {
conn: {
type: Object as PropType<GQLConnection>,
required: true,
},
},
setup(props) {
const {
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const nuxt = useNuxt()
const bulkMode = ref(false)
const bulkHeaders = ref("")
watch(bulkHeaders, () => {
try {
const transformation = bulkHeaders.value.split("\n").map((item) => ({
key: item.substring(0, item.indexOf(":")).trim().replace(/^\/\//, ""),
value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"),
}))
setGQLHeaders(transformation)
} catch (e) {
$toast.error(t("error.something_went_wrong").toString(), {
icon: "error_outline",
})
console.error(e)
}
})
const url = useReadonlyStream(gqlURL$, "")
const gqlQueryString = useStream(gqlQuery$, "", setGQLQuery)
const variableString = useStream(gqlVariables$, "", setGQLVariables)
const headers = useStream(gqlHeaders$, [], setGQLHeaders)
const queryEditor = ref<any | null>(null)
const copyQueryIcon = ref("copy")
const prettifyQueryIcon = ref("align-left")
const copyVariablesIcon = ref("copy")
const showSaveRequestModal = ref(false)
const schema = useReadonlyStream(props.conn.schemaString$, "")
watch(
headers,
() => {
if (
(headers.value[headers.value.length - 1]?.key !== "" ||
headers.value[headers.value.length - 1]?.value !== "") &&
headers.value.length
)
addRequestHeader()
},
{ deep: true }
)
onMounted(() => {
if (!headers.value?.length) {
addRequestHeader()
}
})
const copyQuery = () => {
copyToClipboard(gqlQueryString.value)
copyQueryIcon.value = "check"
setTimeout(() => (copyQueryIcon.value = "copy"), 1000)
}
const response = useStream(gqlResponse$, "", setGQLResponse)
const runQuery = async () => {
const startTime = Date.now()
nuxt.value.$loading.start()
response.value = t("state.loading").toString()
try {
const runURL = clone(url.value)
const runHeaders = clone(headers.value)
const runQuery = clone(gqlQueryString.value)
const runVariables = clone(variableString.value)
const responseText = await props.conn.runQuery(
runURL,
runHeaders,
runQuery,
runVariables
)
const duration = Date.now() - startTime
nuxt.value.$loading.finish()
response.value = JSON.stringify(JSON.parse(responseText), null, 2)
addGraphqlHistoryEntry(
makeGQLHistoryEntry({
request: makeGQLRequest({
name: "",
url: runURL,
query: runQuery,
headers: runHeaders,
variables: runVariables,
}),
response: response.value,
star: false,
})
)
$toast.success(t("state.finished_in", { duration }).toString(), {
icon: "done",
})
} catch (e: any) {
response.value = `${e}. ${t("error.check_console_details")}`
nuxt.value.$loading.finish()
$toast.error(`${e} ${t("error.f12_details").toString()}`, {
icon: "error_outline",
})
console.error(e)
}
logHoppRequestRunToAnalytics({
platform: "graphql-query",
strategy: getCurrentStrategyID(),
})
}
const hideRequestModal = () => {
showSaveRequestModal.value = false
}
const prettifyQuery = () => {
queryEditor.value.prettifyQuery()
prettifyQueryIcon.value = "check"
setTimeout(() => (prettifyQueryIcon.value = "align-left"), 1000)
}
const saveRequest = () => {
showSaveRequestModal.value = true
}
// Why ?
const updateQuery = (updatedQuery: string) => {
gqlQueryString.value = updatedQuery
}
const copyVariables = () => {
copyToClipboard(variableString.value)
copyVariablesIcon.value = "check"
setTimeout(() => (copyVariablesIcon.value = "copy"), 1000)
}
const addRequestHeader = () => {
addGQLHeader({
key: "",
value: "",
active: true,
})
}
const removeRequestHeader = (index: number) => {
removeGQLHeader(index)
}
return {
gqlQueryString,
variableString,
headers,
copyQueryIcon,
prettifyQueryIcon,
copyVariablesIcon,
queryEditor,
showSaveRequestModal,
hideRequestModal,
schema,
copyQuery,
runQuery,
prettifyQuery,
saveRequest,
updateQuery,
copyVariables,
addRequestHeader,
removeRequestHeader,
getSpecialKey: getPlatformSpecialKey,
commonHeaders,
updateGQLHeader,
bulkMode,
bulkHeaders,
}
},
})
</script>

View File

@@ -1,188 +0,0 @@
<template>
<AppSection ref="response" label="response">
<div
v-if="responseString"
class="
bg-primary
border-b border-dividerLight
flex flex-1
pl-4
top-0
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("response.title") }}
</label>
<div class="flex">
<ButtonSecondary
ref="downloadResponse"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')"
:svg="downloadResponseIcon"
@click.native="downloadResponse"
/>
<ButtonSecondary
ref="copyResponseButton"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')"
:svg="copyResponseIcon"
@click.native="copyResponse"
/>
</div>
</div>
<SmartAceEditor
v-if="responseString"
:value="responseString"
:lang="'json'"
:lint="false"
:options="{
maxLines: Infinity,
minLines: 16,
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false,
}"
styles="border-b border-dividerLight"
/>
<div
v-else
class="
flex flex-col flex-1
text-secondaryLight
p-4
items-center
justify-center
"
>
<div class="flex space-x-2 pb-4">
<div class="flex flex-col space-y-4 items-end">
<span class="flex flex-1 items-center">
{{ $t("shortcut.request.send_request") }}
</span>
<span class="flex flex-1 items-center">
{{ $t("shortcut.general.show_all") }}
</span>
<!-- <span class="flex flex-1 items-center">
{{ $t("shortcut.general.command_menu") }}
</span>
<span class="flex flex-1 items-center">
{{ $t("shortcut.general.help_menu") }}
</span> -->
</div>
<div class="flex flex-col space-y-4">
<div class="flex">
<span class="shortcut-key">{{ getSpecialKey() }}</span>
<span class="shortcut-key">G</span>
</div>
<div class="flex">
<span class="shortcut-key">{{ getSpecialKey() }}</span>
<span class="shortcut-key">K</span>
</div>
<!-- <div class="flex">
<span class="shortcut-key">/</span>
</div>
<div class="flex">
<span class="shortcut-key">?</span>
</div> -->
</div>
</div>
<ButtonSecondary
:label="$t('app.documentation')"
to="https://docs.hoppscotch.io"
svg="external-link"
blank
outline
reverse
/>
</div>
</AppSection>
</template>
<script lang="ts">
import {
defineComponent,
PropType,
ref,
useContext,
} from "@nuxtjs/composition-api"
import { GQLConnection } from "~/helpers/GQLConnection"
import { getPlatformSpecialKey } from "~/helpers/platformutils"
import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useReadonlyStream } from "~/helpers/utils/composables"
import { gqlResponse$ } from "~/newstore/GQLSession"
export default defineComponent({
props: {
conn: {
type: Object as PropType<GQLConnection>,
required: true,
},
},
setup() {
const {
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const responseString = useReadonlyStream(gqlResponse$, "")
const downloadResponseIcon = ref("download")
const copyResponseIcon = ref("copy")
const copyResponse = () => {
copyToClipboard(responseString.value!)
copyResponseIcon.value = "check"
setTimeout(() => (copyResponseIcon.value = "copy"), 1000)
}
const downloadResponse = () => {
const dataToWrite = responseString.value
const file = new Blob([dataToWrite!], { type: "application/json" })
const a = document.createElement("a")
const url = URL.createObjectURL(file)
a.href = url
a.download = `${url.split("/").pop()!.split("#")[0].split("?")[0]}`
document.body.appendChild(a)
a.click()
downloadResponseIcon.value = "check"
$toast.success(t("state.download_started").toString(), {
icon: "downloading",
})
setTimeout(() => {
document.body.removeChild(a)
URL.revokeObjectURL(url)
downloadResponseIcon.value = "download"
}, 1000)
}
return {
responseString,
downloadResponseIcon,
copyResponseIcon,
downloadResponse,
copyResponse,
getSpecialKey: getPlatformSpecialKey,
}
},
})
</script>
<style lang="scss" scoped>
.shortcut-key {
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply py-1;
@apply px-2;
@apply inline-flex;
}
</style>

View File

@@ -1,470 +0,0 @@
<template>
<aside>
<SmartTabs styles="sticky bg-primary z-10 top-0">
<SmartTab :id="'docs'" :label="`Docs`" :selected="true">
<AppSection label="docs">
<div class="bg-primary flex top-sidebarPrimaryStickyFold z-10 sticky">
<input
v-model="graphqlFieldsFilterText"
type="search"
autocomplete="off"
:placeholder="$t('action.search')"
class="bg-transparent flex w-full p-4 py-2"
/>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/quickstart/graphql"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
</div>
</div>
<SmartTabs
ref="gqlTabs"
styles="border-t border-dividerLight bg-primary sticky z-10 top-sidebarSecondaryStickyFold"
>
<div class="gqlTabs">
<SmartTab
v-if="queryFields.length > 0"
:id="'queries'"
:label="$t('tab.queries')"
:selected="true"
class="divide-y divide-dividerLight"
>
<GraphqlField
v-for="(field, index) in filteredQueryFields"
:key="`field-${index}`"
:gql-field="field"
:jump-type-callback="handleJumpToType"
class="p-4"
/>
</SmartTab>
<SmartTab
v-if="mutationFields.length > 0"
:id="'mutations'"
:label="$t('graphql.mutations')"
class="divide-y divide-dividerLight"
>
<GraphqlField
v-for="(field, index) in filteredMutationFields"
:key="`field-${index}`"
:gql-field="field"
:jump-type-callback="handleJumpToType"
class="p-4"
/>
</SmartTab>
<SmartTab
v-if="subscriptionFields.length > 0"
:id="'subscriptions'"
:label="$t('graphql.subscriptions')"
class="divide-y divide-dividerLight"
>
<GraphqlField
v-for="(field, index) in filteredSubscriptionFields"
:key="`field-${index}`"
:gql-field="field"
:jump-type-callback="handleJumpToType"
class="p-4"
/>
</SmartTab>
<SmartTab
v-if="graphqlTypes.length > 0"
:id="'types'"
ref="typesTab"
:label="$t('tab.types')"
class="divide-y divide-dividerLight"
>
<GraphqlType
v-for="(type, index) in filteredGraphqlTypes"
:key="`type-${index}`"
:gql-type="type"
:gql-types="graphqlTypes"
:is-highlighted="isGqlTypeHighlighted(type)"
:highlighted-fields="getGqlTypeHighlightedFields(type)"
:jump-type-callback="handleJumpToType"
/>
</SmartTab>
</div>
</SmartTabs>
<div
v-if="
queryFields.length === 0 &&
mutationFields.length === 0 &&
subscriptionFields.length === 0 &&
graphqlTypes.length === 0
"
class="
flex flex-col
text-secondaryLight
p-4
items-center
justify-center
"
>
<i class="opacity-75 pb-2 material-icons">link</i>
<span class="text-center">
{{ $t("empty.schema") }}
</span>
</div>
</AppSection>
</SmartTab>
<SmartTab :id="'history'" :label="$t('tab.history')">
<History
ref="graphqlHistoryComponent"
:page="'graphql'"
@useHistory="handleUseHistory"
/>
</SmartTab>
<SmartTab :id="'collections'" :label="$t('tab.collections')">
<CollectionsGraphql />
</SmartTab>
<SmartTab :id="'schema'" :label="`Schema`">
<AppSection ref="schema" label="schema">
<div
v-if="schemaString"
class="
bg-primary
flex flex-1
top-sidebarPrimaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("graphql.schema") }}
</label>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/quickstart/graphql"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
ref="downloadSchema"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')"
:svg="downloadSchemaIcon"
@click.native="downloadSchema"
/>
<ButtonSecondary
ref="copySchemaCode"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.copy')"
:svg="copySchemaIcon"
@click.native="copySchema"
/>
</div>
</div>
<SmartAceEditor
v-if="schemaString"
v-model="schemaString"
:lang="'graphqlschema'"
:options="{
maxLines: Infinity,
minLines: 16,
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false,
}"
styles="border-b border-dividerLight"
/>
<div
v-else
class="
flex flex-col
text-secondaryLight
p-4
items-center
justify-center
"
>
<i class="opacity-75 pb-2 material-icons">link</i>
<span class="text-center">
{{ $t("empty.schema") }}
</span>
</div>
</AppSection>
</SmartTab>
</SmartTabs>
</aside>
</template>
<script lang="ts">
import {
computed,
defineComponent,
nextTick,
PropType,
ref,
useContext,
} from "@nuxtjs/composition-api"
import { GraphQLField, GraphQLType } from "graphql"
import { map } from "rxjs/operators"
import { GQLConnection } from "~/helpers/GQLConnection"
import { GQLHeader } from "~/helpers/types/HoppGQLRequest"
import { copyToClipboard } from "~/helpers/utils/clipboard"
import { useReadonlyStream } from "~/helpers/utils/composables"
import {
setGQLHeaders,
setGQLQuery,
setGQLResponse,
setGQLURL,
setGQLVariables,
} from "~/newstore/GQLSession"
function isTextFoundInGraphqlFieldObject(
text: string,
field: GraphQLField<any, any>
) {
const normalizedText = text.toLowerCase()
const isFilterTextFoundInDescription = field.description
? field.description.toLowerCase().includes(normalizedText)
: false
const isFilterTextFoundInName = field.name
.toLowerCase()
.includes(normalizedText)
return isFilterTextFoundInDescription || isFilterTextFoundInName
}
function getFilteredGraphqlFields(
filterText: string,
fields: GraphQLField<any, any>[]
) {
if (!filterText) return fields
return fields.filter((field) =>
isTextFoundInGraphqlFieldObject(filterText, field)
)
}
function getFilteredGraphqlTypes(filterText: string, types: GraphQLType[]) {
if (!filterText) return types
return types.filter((type) => {
const isFilterTextMatching = isTextFoundInGraphqlFieldObject(
filterText,
type as any
)
if (isFilterTextMatching) {
return true
}
const isFilterTextMatchingAtLeastOneField = Object.values(
(type as any)._fields || {}
).some((field) => isTextFoundInGraphqlFieldObject(filterText, field as any))
return isFilterTextMatchingAtLeastOneField
})
}
function resolveRootType(type: GraphQLType) {
let t: any = type
while (t.ofType) t = t.ofType
return t
}
type GQLHistoryEntry = {
url: string
headers: GQLHeader[]
query: string
response: string
variables: string
}
export default defineComponent({
props: {
conn: {
type: Object as PropType<GQLConnection>,
required: true,
},
},
setup(props) {
const {
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const queryFields = useReadonlyStream(
props.conn.queryFields$.pipe(map((x) => x ?? [])),
[]
)
const mutationFields = useReadonlyStream(
props.conn.mutationFields$.pipe(map((x) => x ?? [])),
[]
)
const subscriptionFields = useReadonlyStream(
props.conn.subscriptionFields$.pipe(map((x) => x ?? [])),
[]
)
const graphqlTypes = useReadonlyStream(
props.conn.graphqlTypes$.pipe(map((x) => x ?? [])),
[]
)
const downloadSchemaIcon = ref("download")
const copySchemaIcon = ref("copy")
const graphqlFieldsFilterText = ref("")
const gqlTabs = ref<any | null>(null)
const typesTab = ref<any | null>(null)
const filteredQueryFields = computed(() => {
return getFilteredGraphqlFields(
graphqlFieldsFilterText.value,
queryFields.value as any
)
})
const filteredMutationFields = computed(() => {
return getFilteredGraphqlFields(
graphqlFieldsFilterText.value,
mutationFields.value as any
)
})
const filteredSubscriptionFields = computed(() => {
return getFilteredGraphqlFields(
graphqlFieldsFilterText.value,
subscriptionFields.value as any
)
})
const filteredGraphqlTypes = computed(() => {
return getFilteredGraphqlTypes(
graphqlFieldsFilterText.value,
graphqlTypes.value as any
)
})
const isGqlTypeHighlighted = (gqlType: GraphQLType) => {
if (!graphqlFieldsFilterText.value) return false
return isTextFoundInGraphqlFieldObject(
graphqlFieldsFilterText.value,
gqlType as any
)
}
const getGqlTypeHighlightedFields = (gqlType: GraphQLType) => {
if (!graphqlFieldsFilterText.value) return []
const fields = Object.values((gqlType as any)._fields || {})
if (!fields || fields.length === 0) return []
return fields.filter((field) =>
isTextFoundInGraphqlFieldObject(
graphqlFieldsFilterText.value,
field as any
)
)
}
const handleJumpToType = async (type: GraphQLType) => {
gqlTabs.value.selectTab(typesTab.value)
await nextTick()
const rootTypeName = resolveRootType(type).name
const target = document.getElementById(`type_${rootTypeName}`)
if (target) {
gqlTabs.value.$el
.querySelector(".gqlTabs")
.scrollTo({ top: target.offsetTop, behavior: "smooth" })
}
}
const schemaString = useReadonlyStream(
props.conn.schemaString$.pipe(map((x) => x ?? "")),
""
)
const downloadSchema = () => {
const dataToWrite = JSON.stringify(schemaString.value, null, 2)
const file = new Blob([dataToWrite], { type: "application/graphql" })
const a = document.createElement("a")
const url = URL.createObjectURL(file)
a.href = url
a.download = `${
url.split("/").pop()!.split("#")[0].split("?")[0]
}.graphql`
document.body.appendChild(a)
a.click()
downloadSchemaIcon.value = "check"
$toast.success(t("state.download_started").toString(), {
icon: "downloading",
})
setTimeout(() => {
document.body.removeChild(a)
URL.revokeObjectURL(url)
downloadSchemaIcon.value = "download"
}, 1000)
}
const copySchema = () => {
if (!schemaString.value) return
copyToClipboard(schemaString.value)
copySchemaIcon.value = "check"
setTimeout(() => (copySchemaIcon.value = "copy"), 1000)
}
const handleUseHistory = (entry: GQLHistoryEntry) => {
const url = entry.url
const headers = entry.headers
const gqlQueryString = entry.query
const variableString = entry.variables
const responseText = entry.response
setGQLURL(url)
setGQLHeaders(headers)
setGQLQuery(gqlQueryString)
setGQLVariables(variableString)
setGQLResponse(responseText)
props.conn.reset()
}
return {
queryFields,
mutationFields,
subscriptionFields,
graphqlTypes,
schemaString,
graphqlFieldsFilterText,
filteredQueryFields,
filteredMutationFields,
filteredSubscriptionFields,
filteredGraphqlTypes,
isGqlTypeHighlighted,
getGqlTypeHighlightedFields,
gqlTabs,
typesTab,
handleJumpToType,
downloadSchema,
downloadSchemaIcon,
copySchemaIcon,
copySchema,
handleUseHistory,
}
},
})
</script>

View File

@@ -1,288 +0,0 @@
<template>
<AppSection label="headers">
<div
class="
bg-primary
border-b border-dividerLight
flex flex-1
top-upperSecondaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("request.header_list") }}
</label>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/headers"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')"
svg="trash-2"
:disabled="bulkMode"
@click.native="clearContent"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')"
svg="edit"
:class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')"
svg="plus"
:disabled="bulkMode"
@click.native="addHeader"
/>
</div>
</div>
<div v-if="bulkMode" class="flex">
<textarea-autosize
v-model="bulkHeaders"
v-focus
name="bulk-headers"
class="
bg-transparent
border-b border-dividerLight
flex
font-mono
flex-1
py-2
px-4
whitespace-pre
resize-y
overflow-auto
"
rows="10"
:placeholder="$t('state.bulk_mode_placeholder')"
/>
</div>
<div v-else>
<div
v-for="(header, index) in headers$"
:key="`header-${index}`"
class="divide-x divide-dividerLight border-b border-dividerLight flex"
>
<SmartAutoComplete
:placeholder="$t('count.header', { count: index + 1 })"
:source="commonHeaders"
:spellcheck="false"
:value="header.key"
autofocus
styles="
bg-transparent
flex
flex-1
py-1
px-4
truncate
"
:class="{ '!flex flex-1': EXPERIMENTAL_URL_BAR_ENABLED }"
@input="
updateHeader(index, {
key: $event,
value: header.value,
active: header.active,
})
"
/>
<SmartEnvInput
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
v-model="header.value"
:placeholder="$t('count.value', { count: index + 1 })"
styles="
bg-transparent
flex
flex-1
py-1
px-4
"
@change="
updateHeader(index, {
key: header.key,
value: $event,
active: header.active,
})
"
/>
<input
v-else
class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('count.value', { count: index + 1 })"
:name="'value' + index"
:value="header.value"
@change="
updateHeader(index, {
key: header.key,
value: $event.target.value,
active: header.active,
})
"
/>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="
header.hasOwnProperty('active')
? header.active
? $t('action.turn_off')
: $t('action.turn_on')
: $t('action.turn_off')
"
:svg="
header.hasOwnProperty('active')
? header.active
? 'check-circle'
: 'circle'
: 'check-circle'
"
color="green"
@click.native="
updateHeader(index, {
key: header.key,
value: header.value,
active: header.hasOwnProperty('active')
? !header.active
: false,
})
"
/>
</span>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')"
svg="trash"
color="red"
@click.native="deleteHeader(index)"
/>
</span>
</div>
<div
v-if="headers$.length === 0"
class="
flex flex-col
text-secondaryLight
p-4
items-center
justify-center
"
>
<span class="text-center pb-4">
{{ $t("empty.headers") }}
</span>
<ButtonSecondary
filled
:label="$t('add.new')"
svg="plus"
@click.native="addHeader"
/>
</div>
</div>
</AppSection>
</template>
<script lang="ts">
import {
defineComponent,
ref,
useContext,
watch,
} from "@nuxtjs/composition-api"
import {
restHeaders$,
addRESTHeader,
updateRESTHeader,
deleteRESTHeader,
deleteAllRESTHeaders,
setRESTHeaders,
} from "~/newstore/RESTSession"
import { commonHeaders } from "~/helpers/headers"
import { useSetting } from "~/newstore/settings"
import { useReadonlyStream } from "~/helpers/utils/composables"
import { HoppRESTHeader } from "~/helpers/types/HoppRESTRequest"
export default defineComponent({
setup() {
const {
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const bulkMode = ref(false)
const bulkHeaders = ref("")
watch(bulkHeaders, () => {
try {
const transformation = bulkHeaders.value.split("\n").map((item) => ({
key: item.substring(0, item.indexOf(":")).trim().replace(/^\/\//, ""),
value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"),
}))
setRESTHeaders(transformation)
} catch (e) {
$toast.error(t("error.something_went_wrong").toString(), {
icon: "error_outline",
})
console.error(e)
}
})
return {
headers$: useReadonlyStream(restHeaders$, []),
EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"),
bulkMode,
bulkHeaders,
}
},
data() {
return {
commonHeaders,
}
},
watch: {
headers$: {
handler(newValue) {
if (
(newValue[newValue.length - 1]?.key !== "" ||
newValue[newValue.length - 1]?.value !== "") &&
newValue.length
)
this.addHeader()
},
deep: true,
},
},
// mounted() {
// if (!this.headers$?.length) {
// this.addHeader()
// }
// },
methods: {
addHeader() {
addRESTHeader({ key: "", value: "", active: true })
},
updateHeader(index: number, item: HoppRESTHeader) {
updateRESTHeader(index, item)
},
deleteHeader(index: number) {
deleteRESTHeader(index)
},
clearContent() {
deleteAllRESTHeaders()
},
},
})
</script>

View File

@@ -1,137 +0,0 @@
<template>
<SmartModal v-if="show" :title="$t('import.curl')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<textarea-autosize
id="import-curl"
v-model="curl"
class="font-mono textarea floating-input"
autofocus
rows="8"
placeholder=" "
/>
<label for="import-curl">
{{ $t("request.enter_curl") }}
</label>
</div>
</template>
<template #footer>
<span>
<ButtonPrimary
:label="$t('import.title')"
@click.native="handleImport"
/>
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import parseCurlCommand from "~/helpers/curlparser"
import {
HoppRESTHeader,
HoppRESTParam,
makeRESTRequest,
} from "~/helpers/types/HoppRESTRequest"
import { setRESTRequest } from "~/newstore/RESTSession"
export default defineComponent({
props: {
show: Boolean,
},
emits: ["hide-modal"],
data() {
return {
curl: "",
}
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
handleImport() {
const text = this.curl
try {
const parsedCurl = parseCurlCommand(text)
const { origin, pathname } = new URL(
parsedCurl.url.replace(/"/g, "").replace(/'/g, "")
)
const endpoint = origin + pathname
const headers: HoppRESTHeader[] = []
const params: HoppRESTParam[] = []
if (parsedCurl.query) {
for (const key of Object.keys(parsedCurl.query)) {
const val = parsedCurl.query[key]!
if (Array.isArray(val)) {
val.forEach((value) => {
params.push({
key,
value,
active: true,
})
})
} else {
params.push({
key,
value: val!,
active: true,
})
}
}
}
if (parsedCurl.headers) {
for (const key of Object.keys(parsedCurl.headers)) {
headers.push({
key,
value: parsedCurl.headers[key],
active: true,
})
}
}
const method = parsedCurl.method.toUpperCase()
// let rawInput = false
// let rawParams: any | null = null
// if (parsedCurl.data) {
// rawInput = true
// rawParams = parsedCurl.data
// }
this.showCurlImportModal = false
setRESTRequest(
makeRESTRequest({
name: "Untitled request",
endpoint,
method,
params,
headers,
preRequestScript: "",
testScript: "",
auth: {
authType: "none",
authActive: true,
},
body: {
contentType: "application/json",
body: "",
},
})
)
} catch (e) {
console.error(e)
this.$toast.error(this.$t("error.curl_invalid_format").toString(), {
icon: "error_outline",
})
}
this.hideModal()
},
},
})
</script>

View File

@@ -1,291 +0,0 @@
<template>
<AppSection label="parameters">
<div
class="
bg-primary
border-b border-dividerLight
flex flex-1
top-upperSecondaryStickyFold
pl-4
z-10
sticky
items-center
justify-between
"
>
<label class="font-semibold text-secondaryLight">
{{ $t("request.parameter_list") }}
</label>
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://docs.hoppscotch.io/features/parameters"
blank
:title="$t('app.wiki')"
svg="help-circle"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.clear_all')"
svg="trash-2"
:disabled="bulkMode"
@click.native="clearContent"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('state.bulk_mode')"
svg="edit"
:class="{ '!text-accent': bulkMode }"
@click.native="bulkMode = !bulkMode"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('add.new')"
svg="plus"
:disabled="bulkMode"
@click.native="addParam"
/>
</div>
</div>
<div v-if="bulkMode" class="flex">
<textarea-autosize
v-model="bulkParams"
v-focus
name="bulk-parameters"
class="
bg-transparent
border-b border-dividerLight
flex
font-mono font-medium
flex-1
py-2
px-4
whitespace-pre
resize-y
overflow-auto
"
rows="10"
:placeholder="$t('state.bulk_mode_placeholder')"
/>
</div>
<div v-else>
<div
v-for="(param, index) in params$"
:key="`param-${index}`"
class="divide-x divide-dividerLight border-b border-dividerLight flex"
>
<SmartEnvInput
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
v-model="param.key"
:placeholder="$t('count.parameter', { count: index + 1 })"
styles="
bg-transparent
flex
flex-1
py-1
px-4
"
@change="
updateParam(index, {
key: $event,
value: param.value,
active: param.active,
})
"
/>
<input
v-else
class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('count.parameter', { count: index + 1 })"
:name="'param' + index"
:value="param.key"
autofocus
@change="
updateParam(index, {
key: $event.target.value,
value: param.value,
active: param.active,
})
"
/>
<SmartEnvInput
v-if="EXPERIMENTAL_URL_BAR_ENABLED"
v-model="param.value"
:placeholder="$t('count.value', { count: index + 1 })"
styles="
bg-transparent
flex
flex-1
py-1
px-4
"
@change="
updateParam(index, {
key: param.key,
value: $event,
active: param.active,
})
"
/>
<input
v-else
class="bg-transparent flex flex-1 py-2 px-4"
:placeholder="$t('count.value', { count: index + 1 })"
:name="'value' + index"
:value="param.value"
@change="
updateParam(index, {
key: param.key,
value: $event.target.value,
active: param.active,
})
"
/>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="
param.hasOwnProperty('active')
? param.active
? $t('action.turn_off')
: $t('action.turn_on')
: $t('action.turn_off')
"
:svg="
param.hasOwnProperty('active')
? param.active
? 'check-circle'
: 'circle'
: 'check-circle'
"
color="green"
@click.native="
updateParam(index, {
key: param.key,
value: param.value,
active: param.hasOwnProperty('active') ? !param.active : false,
})
"
/>
</span>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.remove')"
svg="trash"
color="red"
@click.native="deleteParam(index)"
/>
</span>
</div>
<div
v-if="params$.length === 0"
class="
flex flex-col
text-secondaryLight
p-4
items-center
justify-center
"
>
<span class="text-center pb-4">
{{ $t("empty.parameters") }}
</span>
<ButtonSecondary
:label="$t('add.new')"
svg="plus"
filled
@click.native="addParam"
/>
</div>
</div>
</AppSection>
</template>
<script lang="ts">
import {
defineComponent,
ref,
useContext,
watch,
} from "@nuxtjs/composition-api"
import { HoppRESTParam } from "~/helpers/types/HoppRESTRequest"
import { useReadonlyStream } from "~/helpers/utils/composables"
import {
restParams$,
addRESTParam,
updateRESTParam,
deleteRESTParam,
deleteAllRESTParams,
setRESTParams,
} from "~/newstore/RESTSession"
import { useSetting } from "~/newstore/settings"
export default defineComponent({
setup() {
const {
$toast,
app: { i18n },
} = useContext()
const t = i18n.t.bind(i18n)
const bulkMode = ref(false)
const bulkParams = ref("")
watch(bulkParams, () => {
try {
const transformation = bulkParams.value.split("\n").map((item) => ({
key: item.substring(0, item.indexOf(":")).trim().replace(/^\/\//, ""),
value: item.substring(item.indexOf(":") + 1).trim(),
active: !item.trim().startsWith("//"),
}))
setRESTParams(transformation)
} catch (e) {
$toast.error(t("error.something_went_wrong").toString(), {
icon: "error_outline",
})
console.error(e)
}
})
return {
params$: useReadonlyStream(restParams$, []),
EXPERIMENTAL_URL_BAR_ENABLED: useSetting("EXPERIMENTAL_URL_BAR_ENABLED"),
bulkMode,
bulkParams,
}
},
watch: {
params$: {
handler(newValue) {
if (
(newValue[newValue.length - 1]?.key !== "" ||
newValue[newValue.length - 1]?.value !== "") &&
newValue.length
)
this.addParam()
},
deep: true,
},
},
// mounted() {
// if (!this.params$?.length) {
// this.addParam()
// }
// },
methods: {
addParam() {
addRESTParam({ key: "", value: "", active: true })
},
updateParam(index: number, item: HoppRESTParam) {
updateRESTParam(index, item)
},
deleteParam(index: number) {
deleteRESTParam(index)
},
clearContent() {
deleteAllRESTParams()
},
},
})
</script>

Some files were not shown because too many files have changed in this diff Show More