Compare commits

..

614 Commits

Author SHA1 Message Date
liyasthomas
da368a2d72 feat: show keys on press plugin 2021-09-24 19:42:10 +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
liyasthomas
917550ff4d feat: tooltips on primary navigation in zenmode 2021-09-09 13:10:48 +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
liyasthomas
c3e881ed77 fix: tooltip position on containers with overflow 2021-09-08 15:22:38 +05:30
liyasthomas
2cf55cbb96 refactor: hide right sidebars by default on mobile devices 2021-09-08 13:56:02 +05:30
liyasthomas
73f22abf56 feat: mobile responsive right sidbars + composable window size 2021-09-08 12:27:46 +05:30
liyasthomas
dbae90a193 refactor: replace lunr with fuse 2021-09-08 09:21:22 +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
liyasthomas
84457ddc86 chore(deps+i18n): updated deps and translations 2021-09-06 20:32:45 +05:30
Liyas Thomas
d6d20e5d49 Merge pull request #1815 from bokub/patch-1
chore(i18n): fixed french translations
2021-09-06 20:26:20 +05:30
Boris K
9acdca1059 chore: french i18n translations 2021-09-06 16:48:10 +02:00
liyasthomas
66c4fd4d2f chore(i18n): updated translations 2021-09-05 20:51:54 +05:30
liyasthomas
f2defb3a31 chore(deps): bump 2021-09-05 20:51:25 +05:30
Andrew Bastin
aa66c10608 fix: improved volar integration 2021-09-03 23:06:23 +05:30
liyasthomas
28d20a9c61 refactor: updated svg icon assets 2021-09-03 11:27:11 +05:30
liyasthomas
94fcc0a6a9 perf: workflows 2021-09-02 20:33:34 +05:30
Andrew Bastin
91abdd5415 Merge pull request #1802 from AndrewBastin/bugfix/1798
fix: auth header doubling in codegen
2021-09-02 20:19:15 +05:30
Andrew Bastin
58e940d193 fix: auth header doubling in codegen 2021-09-02 20:04:56 +05:30
liyasthomas
6991dd48f3 feat: publish docker image 2021-09-02 17:44:36 +05:30
liyasthomas
270a077539 chore: updated social banner image 2021-09-02 09:04:02 +05:30
liyasthomas
ff326acfc8 chore: updated screenshots 2021-09-02 01:46:08 +05:30
liyasthomas
af1446233c chore: i18n translations 2021-09-02 00:28:38 +05:30
liyasthomas
67d66e2b2f Merge remote-tracking branch 'origin/i18n-de' 2021-09-01 23:19:56 +05:30
Liyas Thomas
753ce5bd6e Merge pull request #1800 from JorgeFerrer/patch-1
Improvements for the translation to Spanish #1799
2021-09-01 23:18:37 +05:30
Jorge Ferrer
e7d71ef301 Improvements for the translation to Spanish #1799
I have fixed REST as well as some wrong automatic translations and also applied consistency in terms used across all translations
2021-09-01 19:35:15 +02:00
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
f357c4f171 fix: response section's font weight 2021-08-31 22:16:49 +05:30
Liyas Thomas
36e34fe667 Merge pull request #1796 from hoppscotch/feat/bulk-edit
feat: bulk edit
2021-08-31 22:03:39 +05:30
liyasthomas
dcc59f42fa fix: remove // from key on disabled bulk edit entries 2021-08-31 21:54:24 +05:30
Liyas Thomas
f6fbff2b42 Merge pull request #1797 from jenskeiner/jenskeiner-fix-mistranslations-and-typos
Fix some mistranslations an typos.
2021-08-31 18:23:14 +05:30
Jens Keiner
67ce20ef62 Fix some mistranslations an typos.
Fixed up some apparent mistranslated items and typos.
2021-08-31 14:37:19 +02:00
liyasthomas
788e0dc851 chore: lint 2021-08-31 17:38:54 +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
liyasthomas
6f67a97ade feat: textare autoresize 2021-08-30 22:03:59 +05:30
liyasthomas
ada568cb75 feat: bulk edit for graphql headers 2021-08-30 18:49:35 +05:30
liyasthomas
b9fa254ab5 feat: disable bulk edit entries with // 2021-08-30 18:35:33 +05:30
liyasthomas
174ba90fb5 feat: bulk edit transformation 2021-08-30 14:34:43 +05:30
liyasthomas
de8c7c1ca3 Merge branch 'main' into feat/bulk-edit 2021-08-30 13:23:24 +05:30
liyasthomas
407a125533 feat: search
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-30 11:27:36 +05:30
liyasthomas
d8881ba6a3 feat: init bulk edit 2021-08-29 23:26:27 +05:30
liyasthomas
755540fb81 Merge branch 'main' into feat/search 2021-08-29 20:59:47 +05:30
liyasthomas
add358c752 chore(deps): bump 2021-08-29 20:53:59 +05:30
liyasthomas
91352ade20 feat: typescript support in auth components
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-29 19:31:23 +05:30
Liyas Thomas
39fbf4ef33 Merge pull request #1790 from AndrewBastin/refactor/firebase-v9
refactor: bump firebase to v9
2021-08-29 18:28:33 +05:30
liyasthomas
d9547c6654 fix: mobile responsiveness 2021-08-29 17:11:37 +05:30
liyasthomas
04f9428267 feat: disable autocomplete on inputs + keyboard navigation focus 2021-08-29 16:44:18 +05:30
liyasthomas
ebd8f43219 refactor: minor ui improvements 2021-08-29 13:25:01 +05:30
liyasthomas
f75b2e26a3 chore: cleanup, typescript 2021-08-29 12:00:19 +05:30
Andrew Bastin
2e654c143f refactor: bump firebase to v9 2021-08-29 10:51:31 +05:30
liyasthomas
5bcee265a6 fix: show empty state for search results, es6 2021-08-29 10:02:19 +05:30
liyasthomas
647599e5aa refactor: full-width modal for search, transparent tabs 2021-08-29 09:44:46 +05:30
liyasthomas
16b9a2b06e feat: search 2021-08-28 23:23:16 +05:30
liyasthomas
7da427c669 feat: share and support modals 2021-08-28 20:48:13 +05:30
liyasthomas
405e6c1e4e chore: minor fixes and improvements 2021-08-28 10:57:21 +05:30
liyasthomas
efbc21826b Merge branch 'refactor/ui' 2021-08-28 05:56:58 +05:30
liyasthomas
7a1f1c9df7 feat: updated screenshots 2021-08-28 05:56:07 +05:30
liyasthomas
476bfbaef0 feat: svg icons 2021-08-28 05:47:33 +05:30
Andrew Bastin
8231157cdb feat: bump version to 2.0.0 2021-08-28 02:21:37 +05:30
liyasthomas
e397e3fb6f feat: add newsletter link 2021-08-27 22:13:15 +05:30
liyasthomas
8f1cafc80d chore: i18n 2021-08-27 15:22:21 +05:30
liyasthomas
71619cf84b feat: test report pie chart 2021-08-27 14:32:07 +05:30
liyasthomas
a3551c6719 fix: broken test results 2021-08-27 12:38:03 +05:30
Andrew Bastin
e9043e6762 refactor: update test components to use setup scripts 2021-08-27 11:45:08 +05:30
liyasthomas
6b7d30a701 fix: restore v1 test API 2021-08-27 09:42:53 +05:30
liyasthomas
76eab2632e fix: failed tests 2021-08-27 09:38:29 +05:30
liyasthomas
bba4d7fcd9 chore: cleanup 2021-08-27 09:37:29 +05:30
Andrew Bastin
46eb7d6786 fix: test scripts response respects the old api and the new structure 2021-08-26 13:08:06 +05:30
Andrew Bastin
f5c84b57b2 fix: improved codegen compat 2021-08-26 13:08:06 +05:30
liyasthomas
0b12901344 feat: sample pre-request and test snippets 2021-08-26 12:18:28 +05:30
liyasthomas
5e3c303aaf fix: tippy on request + lint 2021-08-26 11:04:52 +05:30
liyasthomas
f02b1639c3 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-26 11:03:30 +05:30
Andrew Bastin
94e0c3ef64 refactor: update codegen code 2021-08-26 11:02:05 +05:30
liyasthomas
17366f5e6e fix: sync modal 2021-08-26 10:44:01 +05:30
liyasthomas
f7a6f899d4 Merge branch 'refactor/oauth' of https://github.com/hoppscotch/hoppscotch into refactor/oauth 2021-08-26 10:03:05 +05:30
liyasthomas
62205919a3 feat: env variable support in authorization
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-26 10:00:21 +05:30
liyasthomas
ee44a48994 feat: ui for oauth 2021-08-26 09:21:37 +05:30
liyasthomas
fedc230c9f feat: add OAuth 2.0 support 2021-08-26 09:21:37 +05:30
Andrew Bastin
8796cec493 fix: tippy not disappearing on request component modals 2021-08-26 09:19:18 +05:30
Andrew Bastin
b3b76adec4 feat: antfu's setup script transform + request component in setup sugar 2021-08-26 08:56:22 +05:30
liyasthomas
4362760461 feat: ui for oauth 2021-08-25 22:20:35 +05:30
liyasthomas
bc9236c9a7 feat: add OAuth 2.0 support 2021-08-25 21:30:13 +05:30
liyasthomas
9e16cff62a chore: minor fixes and improvements 2021-08-25 21:26:53 +05:30
Andrew Bastin
b04d8dde2b feat: request local persistence 2021-08-25 18:29:04 +05:30
liyasthomas
2a23c95f34 fix: empty github auth provider info 2021-08-25 16:15:31 +05:30
Andrew Bastin
cb9aa33ad0 fix: req.id undefined issues 2021-08-25 09:43:16 +05:30
Andrew Bastin
31258b1108 refactor: improved teams migrations 2021-08-25 08:41:09 +05:30
Andrew Bastin
6e9f16d8f1 refactor: collections versioning, migration and types 2021-08-24 23:12:53 +05:30
Andrew Bastin
d1b2539d67 refactor: gql request object and history typing updates 2021-08-24 21:58:04 +05:30
liyasthomas
c5f8ab3394 chore: minor fixes and improvements 2021-08-24 13:45:11 +05:30
liyasthomas
12c28f4efc fix: broken component import in prod 2021-08-24 09:14:46 +05:30
Andrew Bastin
f20fed444a fix: history entries becoming undefined over reloads 2021-08-23 12:57:36 +05:30
Andrew Bastin
97b92ba35b feat: history migration from legacy request object 2021-08-23 11:49:43 +05:30
liyasthomas
91df36ccca fix: ctrl+c shortcut, minor ui issues 2021-08-23 10:22:07 +05:30
liyasthomas
294b1a5a7c fix: cors when content-type is set for simple requests 2021-08-22 22:44:07 +05:30
liyasthomas
5f27b59dc0 fix: typo 2021-08-22 17:02:18 +05:30
Andrew Bastin
af0efc1e7f fix: migration of request url from old to new format 2021-08-22 16:31:09 +05:30
Andrew Bastin
db25346505 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-22 13:06:58 +05:30
Andrew Bastin
1a4fc1f539 feat: remove authName from HoppRESTAuth type definitions 2021-08-22 13:06:19 +05:30
liyasthomas
1bea0a42d7 refactor(ui): better button, tab caomponents 2021-08-22 12:58:43 +05:30
liyasthomas
22e73a4d83 Merge branch 'main' into refactor/ui 2021-08-22 00:55:02 +05:30
liyasthomas
3ab3c09982 chore(deps): bump 2021-08-22 00:43:58 +05:30
liyasthomas
0fb0ae1826 refactor(ui): better tabs 2021-08-22 00:39:05 +05:30
Andrew Bastin
08fe4ae71f feat: shift based keyboard shortcuts and save as action 2021-08-21 21:59:55 +05:30
Andrew Bastin
883c787c0b fix: global variables not applying on codegen 2021-08-21 20:08:32 +05:30
Andrew Bastin
732dc07ec5 fix: history sync issues and crashes 2021-08-21 12:37:26 +05:30
Andrew Bastin
c00c8f249e fix: environments being cringe :) 2021-08-21 10:38:35 +05:30
Andrew Bastin
77d876d443 fix: error on empty environment sync 2021-08-21 08:08:39 +05:30
liyasthomas
822e7b4630 refactor: improve lighthouse score 2021-08-20 21:35:54 +05:30
liyasthomas
275a7fc113 fix: save context indicatior + added unplug save on double click 2021-08-20 20:21:22 +05:30
Andrew Bastin
b08b06c4d4 fix: save request context set on teams 2021-08-20 18:27:52 +05:30
liyasthomas
7082eb27db refactor(ui): minor ui improvements 2021-08-20 15:08:54 +05:30
liyasthomas
a121445b1e feat: active request indication in collections 2021-08-19 23:15:10 +05:30
liyasthomas
95547108bf docs: updated wiki links 2021-08-19 22:38:50 +05:30
Andrew Bastin
fc4e945a7e refactor: reactive stream of save context 2021-08-19 19:38:32 +05:30
Andrew Bastin
1fdb6488fd feat: save request context 2021-08-19 12:06:56 +05:30
liyasthomas
51142e5c77 feat: added docs links 2021-08-19 11:46:22 +05:30
liyasthomas
57ce7ccfdf chore: i18n 2021-08-19 01:38:30 +05:30
liyasthomas
c1ce90dad0 feat: finish new i18n translation format 2021-08-19 00:10:57 +05:30
liyasthomas
ceb8bdf0fd refactor: more i18n translation strings 2021-08-18 22:17:31 +05:30
liyasthomas
b9c233cdf9 refactor(ui): better remove, delete icons, and select components 2021-08-18 13:30:01 +05:30
liyasthomas
4f5de51104 refactor: change default env name from 'global' to 'Global' 2021-08-18 10:44:58 +05:30
liyasthomas
c949783698 feat: show global envs on hover 2021-08-18 10:34:20 +05:30
Andrew Bastin
6af42e5e08 fix: issues with global environment writes 2021-08-18 09:52:13 +05:30
liyasthomas
f312ed32be refactor(ui): global environment 2021-08-18 02:29:05 +05:30
Andrew Bastin
91fee8d2d0 refactor: remove legacy global env preRequest reference 2021-08-17 14:51:10 +05:30
Andrew Bastin
c23a4bf75d feat: aggregated environment variable stream 2021-08-17 14:51:10 +05:30
Andrew Bastin
e38af0bebe feat: firestore sync for global environment 2021-08-17 14:51:10 +05:30
Andrew Bastin
b968756be2 feat: global env variable migration and local persistence 2021-08-17 14:51:10 +05:30
Andrew Bastin
ed5b4b6dc5 refactor: custom space for global variables 2021-08-17 14:51:10 +05:30
liyasthomas
956ca44ef0 refactor: remove absolute classes 2021-08-17 12:56:36 +05:30
Andrew Bastin
3534e133af fix: eslint being dumb 2021-08-17 10:25:27 +05:30
Andrew Bastin
7744e2eb03 feat: add success test descriptions 2021-08-17 10:05:19 +05:30
Andrew Bastin
078c5e8d8a refactor: update postwomanTesting to typescript 2021-08-17 09:06:04 +05:30
liyasthomas
6c3607d7e7 refactor: i18n 2021-08-16 23:15:06 +05:30
liyasthomas
c04435108b refactor: i18n SEO 2021-08-16 22:02:18 +05:30
liyasthomas
e5c8d05850 feat: added remaining i18n translations 2021-08-16 17:06:43 +05:30
liyasthomas
bf0278aa00 feat: init i18n with gitlocalize 2021-08-16 14:18:45 +05:30
Liyas Thomas
33d05eaa77 Merge pull request #1779 from hoppscotch/gitlocalize-16541 2021-08-16 14:11:19 +05:30
mt-gitlocalize
5b074409fc Translate zh.json via GitLocalize 2021-08-16 08:41:02 +00:00
Liyas Thomas
bdc3cf2150 Merge pull request #1778 from hoppscotch/gitlocalize-16540 2021-08-16 14:03:57 +05:30
mt-gitlocalize
c3b7d45502 Translate pt.json via GitLocalize 2021-08-16 08:33:36 +00:00
Liyas Thomas
2ef4bc1b36 Merge pull request #1777 from hoppscotch/gitlocalize-16539 2021-08-16 14:02:58 +05:30
mt-gitlocalize
2f87549dac Translate ru.json via GitLocalize 2021-08-16 08:32:35 +00:00
Liyas Thomas
c596012bb5 Merge pull request #1776 from hoppscotch/gitlocalize-16538 2021-08-16 13:57:43 +05:30
mt-gitlocalize
04c6faf5da Translate de.json via GitLocalize 2021-08-16 08:27:25 +00:00
Liyas Thomas
b2f50547a9 Merge pull request #1775 from hoppscotch/gitlocalize-16537 2021-08-16 13:48:39 +05:30
mt-gitlocalize
e221741a6a Translate fr.json via GitLocalize 2021-08-16 08:17:15 +00:00
Liyas Thomas
fe43ae9e81 Merge pull request #1774 from hoppscotch/gitlocalize-16536 2021-08-16 13:37:02 +05:30
mt-gitlocalize
c5d4b9f0ae Translate es.json via GitLocalize 2021-08-16 08:05:48 +00:00
liyasthomas
b9156cdf7f refactor: init english glossary for i18n 2021-08-16 13:11:50 +05:30
liyasthomas
c6a3b784b5 fix: proper state indicatior in teams collections 2021-08-16 08:18:48 +05:30
Andrew Bastin
33e2afab7b feat: send formdata over network 2021-08-16 07:12:33 +05:30
Andrew Bastin
5eb6fb38e0 fix: crash on switch from formdata to non-formdata 2021-08-16 01:00:44 +05:30
liyasthomas
c2ae333a12 refactor(ui): better CTAs, expanded app bar 2021-08-16 00:38:57 +05:30
liyasthomas
d462242927 chore(deps): bump 2021-08-15 19:16:31 +05:30
liyasthomas
c1d2f12e48 Merge branch 'main' into refactor/ui 2021-08-15 19:11:00 +05:30
liyasthomas
74d472e76e chore(deps): bump 2021-08-15 19:06:20 +05:30
liyasthomas
bfc0282e49 refactor: minor ui improvements 2021-08-15 15:18:04 +05:30
liyasthomas
8c70f83297 fix: broken contenteditable support in macOS 2021-08-15 13:11:12 +05:30
liyasthomas
1e6e826426 fix: broken expand / collapse graphql history card 2021-08-15 12:16:33 +05:30
liyasthomas
872ba2d48e fix: catch network failed error and show prompt in response section 2021-08-15 11:57:20 +05:30
Andrew Bastin
7acde1c174 feat: rest request sync with firestore 2021-08-15 10:45:26 +05:30
liyasthomas
bb6d9a88ec refactor: minoe fixes and improvements 2021-08-14 23:46:03 +05:30
liyasthomas
29305a8e1e Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-14 21:41:38 +05:30
liyasthomas
9f639378ec feat: reactive font size for ace editor + i18n support for font size settings strings 2021-08-14 21:40:56 +05:30
Andrew Bastin
92a42269e7 refactor: remove vuex dependency 2021-08-14 21:27:22 +05:30
liyasthomas
691629890f fix: form data request as body
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-14 19:11:05 +05:30
liyasthomas
2051b8788a refactor: minor ui improvements 2021-08-14 16:14:08 +05:30
liyasthomas
a129d7eb13 refactor: init newstore for request body
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-14 14:31:16 +05:30
liyasthomas
e9eee0703d refactor: set placement as top by edfault for modals, better response header layout 2021-08-13 22:39:47 +05:30
liyasthomas
11816111ea refactor(ui): better font weight, icon hover states, etc 2021-08-13 16:44:02 +05:30
Andrew Bastin
08e3cffff8 refactor: decouple REST params and URL params 2021-08-13 12:12:05 +05:30
Andrew Bastin
ab63735a89 fix: bump deps 2021-08-13 12:00:22 +05:30
Andrew Bastin
560c6e0d6a refactor: add prettier-ignore to Key type def 2021-08-13 10:23:40 +05:30
Andrew Bastin
f688099f2c fix: improper theme application on initial load 2021-08-13 08:11:06 +05:30
liyasthomas
877f1e343a Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-12 18:42:11 +05:30
liyasthomas
32660c5251 refactor: move test results to request response section 2021-08-12 18:41:55 +05:30
Andrew Bastin
a1dc224007 feat: graphql request history and collection restore 2021-08-12 16:15:17 +05:30
liyasthomas
55bcb34fd5 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-12 13:56:51 +05:30
liyasthomas
b18f7af28f feat: enable / disable authorization 2021-08-12 13:56:11 +05:30
Andrew Bastin
c273ded97d refactor: remove vue-rx dependency 2021-08-12 13:44:10 +05:30
liyasthomas
971b35a252 refactor: auth
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-08-12 09:56:05 +05:30
Andrew Bastin
dad18aabcb feat: expose actively bound actions via activeActions$ 2021-08-11 22:07:47 +05:30
liyasthomas
0738ad1c15 refactor: better toast messages + minor ui improvements 2021-08-11 16:57:40 +05:30
liyasthomas
829e116e04 feat: more actions & shortcuts 2021-08-11 14:16:43 +05:30
liyasthomas
384e4ce43e chore: lint 2021-08-11 10:27:36 +05:30
Andrew Bastin
da3f55c910 feat: graphql rewrite to new state system 2021-08-11 08:23:49 +05:30
liyasthomas
87833f1e9f fix: broken team's add / edit member action 2021-08-10 20:45:57 +05:30
liyasthomas
ba5d1666d6 feat: placement option (center, top) in modals 2021-08-10 20:45:45 +05:30
liyasthomas
b612feea41 feat: search 2021-08-10 13:46:42 +05:30
Andrew Bastin
da74fb5241 refactor: remove nuxt eslint module 2021-08-10 05:27:34 +05:30
liyasthomas
aa8b4231e2 feat: share and support modals 2021-08-09 17:55:30 +05:30
Andrew Bastin
6b4bd44807 Merge pull request #1769 from s-r-x/fix/settings-persistence
fix: broken settings persistence on the home page
2021-08-09 13:34:20 +05:30
Andrew Bastin
058c1090e3 fix: remove settings entries from postwoman.js 2021-08-09 12:56:20 +05:30
s-r-x
6aa6fb5c0a fix: broken settings persistence 2021-08-09 09:07:17 +05:00
liyasthomas
cbf99d2daf feat: auto focus directive, auto focus primary action by default 2021-08-08 22:44:05 +05:30
liyasthomas
a71f70644f chore(deps): bump 2021-08-08 20:47:50 +05:30
liyasthomas
b41d08007a Merge branch 'main' into refactor/ui 2021-08-08 19:52:39 +05:30
liyasthomas
0e1900b36a chore(deps): bump 2021-08-08 19:49:06 +05:30
Andrew Bastin
e6c503253b fix: firebase imports to allow tree shaking 2021-08-08 13:25:54 +05:30
Andrew Bastin
846c1426cf fix: proper implementation of isCustomMethod 2021-08-08 13:16:14 +05:30
Andrew Bastin
c97f8aa148 fix: cancel request 2021-08-08 13:08:10 +05:30
liyasthomas
b99c4fe5c1 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-08 12:42:44 +05:30
liyasthomas
42d2dd284f refactor(ui): title and actions slot on modals 2021-08-08 12:42:29 +05:30
Andrew Bastin
b7e3f2a4ee feat: reimplement request time loading bar 2021-08-08 12:41:52 +05:30
Andrew Bastin
6599c5f5bf feat: introduce useNuxt composable 2021-08-08 12:39:02 +05:30
Andrew Bastin
13f6e5ff43 fix: remove keydown log 2021-08-08 12:13:59 +05:30
liyasthomas
4d76c83328 refactor: improved input validations 2021-08-08 12:01:36 +05:30
liyasthomas
fee19f3d7a Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-08-07 19:19:49 +05:30
Andrew Bastin
200fc738e8 fix: remove unused focus listeners in keybindings 2021-08-07 19:18:55 +05:30
Andrew Bastin
05294ac556 fix: remove unused focus listeners in keybindings 2021-08-07 18:51:14 +05:30
Andrew Bastin
93dfed74f8 feat: singlecharacter shortcuts 2021-08-07 18:43:38 +05:30
liyasthomas
3d963a7719 feat: floating input label 2021-08-07 14:51:13 +05:30
liyasthomas
92abbc4ce6 Merge branch 'main' into refactor/ui 2021-08-07 11:28:39 +05:30
Liyas Thomas
d111893302 Merge pull request #1766 from hughobrien/fix-well-known
fix: bad var names from oauth well.known config
2021-08-07 11:23:49 +05:30
Hugh O'Brien
967ad773eb Update oauth.js 2021-08-07 06:29:49 +01:00
Liyas Thomas
b036863dda Merge pull request #1765 from hughobrien/fix-oauth-param-names 2021-08-07 10:31:59 +05:30
Hugh O'Brien
ead9c23d9e fix: oauth token exchange param naming convention
https://developer.okta.com/docs/guides/implement-auth-code-pkce/exchange-code-token/
2021-08-07 05:48:44 +01:00
liyasthomas
8c60a4c032 refactor(ui): sort classes 2021-08-07 09:07:26 +05:30
liyasthomas
d08f15430c Merge branch 'main' into refactor/ui 2021-08-06 23:39:03 +05:30
Liyas Thomas
f71d93a684 Merge pull request #1762 from hughobrien/oauth-pkce-paramname-fix
fix: pkce params match rfc naming convention
2021-08-06 23:23:10 +05:30
Hugh O'Brien
44d1ad7422 fix: pkce params match okta naming convension 2021-08-06 18:45:09 +01:00
liyasthomas
346ece94b7 refactor(ui): a11y improvements 2021-08-06 21:40:26 +05:30
liyasthomas
3a96eb003b refactor(ui): group windi classes 2021-08-05 22:52:02 +05:30
liyasthomas
3bd78869a0 fix: responsiveness 2021-08-05 21:29:05 +05:30
liyasthomas
4b416586b7 fix: build 2021-08-05 19:43:46 +05:30
liyasthomas
20ffbe906f fix: sse, refactor(ui): tabs, feat: help button 2021-08-05 11:06:37 +05:30
liyasthomas
b2baeb0a5d fix(ui): realtime pages 2021-08-04 22:07:12 +05:30
Andrew Bastin
b524af174a feat: disable keybindings when a modal is open 2021-08-04 10:48:41 -04:00
liyasthomas
a4caeac584 refactor(ui): better select popovers 2021-08-04 11:20:23 +05:30
liyasthomas
b03565a816 fix: broken sticky sections on font size 2021-08-04 01:00:06 +05:30
liyasthomas
d0c0a543cf feat: font size picker 2021-08-03 21:35:01 +05:30
liyasthomas
17192c898b refactor(ui): teams 2021-08-03 16:50:28 +05:30
liyasthomas
7d913b0ee7 fix: build - lock deps 2021-08-03 10:45:11 +05:30
liyasthomas
db4521db5a fix: build - retire storybook 2021-08-03 10:24:32 +05:30
Andrew Bastin
10b7da0558 feat: live request url under the new system 2021-08-02 17:57:13 -04:00
Andrew Bastin
05f19cbb60 fix: remove legacy code in index.vue 2021-08-02 17:57:13 -04:00
liyasthomas
6d9ac84859 fix: use build commands mentioned in Netlify UI 2021-08-03 00:29:42 +05:30
liyasthomas
d9834d0fd1 feat: more storybook stories 2021-08-03 00:23:04 +05:30
liyasthomas
d84e2a8e9b feat: storybook 2021-08-02 21:38:04 +05:30
liyasthomas
13dbeaba35 Merge branch 'refactor/ui' into feat/storybook 2021-08-02 21:00:09 +05:30
liyasthomas
b615fe7529 feat: init new i18n format 2021-08-02 20:57:18 +05:30
liyasthomas
8a268ee6de refactor(ui): improved empty state for env variables and response sections 2021-08-02 10:00:50 +05:30
liyasthomas
2ae2acc003 fix: prevent enter key on content editable 2021-08-02 09:08:37 +05:30
Andrew Bastin
13d89b323e fix: tippy not appearing on envinput when typing and then hover 2021-08-01 23:15:15 -04:00
Andrew Bastin
6acb9be48c feat: envinput revalidates with environment changes 2021-08-01 23:05:15 -04:00
liyasthomas
d9d61b5b1d feat: tooltip on hovering environment variables 2021-08-02 08:08:41 +05:30
liyasthomas
2ee65e69dc fix: color contrast 2021-08-01 23:03:54 +05:30
liyasthomas
fd3b5ecf08 feat: actions in empty state 2021-08-01 20:04:25 +05:30
liyasthomas
6d67b1e51f chore(deps): bump 2021-08-01 20:03:27 +05:30
liyasthomas
79cea34fac Merge branch 'main' into refactor/ui 2021-08-01 18:19:40 +05:30
liyasthomas
b0b758a9c6 chore(deps): bump 2021-08-01 18:18:30 +05:30
liyasthomas
462d17de17 feat: auto increment headers and parameters list on input 2021-08-01 15:01:31 +05:30
liyasthomas
9afe415c2d feat: indicated valid and invalid environment variables with its value on hover 2021-08-01 14:42:32 +05:30
liyasthomas
1e4bb65db2 feat: environment aware smart input in parameters and headers 2021-08-01 13:07:07 +05:30
Andrew Bastin
fcb194d08a feat: effective url environment templates work with headers, url and params 2021-07-31 22:21:14 -04:00
Andrew Bastin
7354951d5a refactor: move Request.vue to composition api fully 2021-07-31 21:21:09 -04:00
Andrew Bastin
369bca90fc feat: use navigator clipboard to copy text is possible 2021-07-31 20:43:17 -04:00
liyasthomas
5275d365cb feat: selectable response headers entry 2021-08-01 00:11:45 +05:30
liyasthomas
e2fc056488 feat: make smart url feild the default input 2021-07-31 23:58:34 +05:30
liyasthomas
98d2b2ee9c feat: supported copy to clipboard utlity 2021-07-31 22:50:08 +05:30
Andrew Bastin
9441c76a12 fix: fix copy request link 2021-07-31 11:42:01 -04:00
liyasthomas
1ef7b52425 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-07-31 21:04:16 +05:30
liyasthomas
d88725b998 fix: inconsistent icon size 2021-07-31 21:04:03 +05:30
Andrew Bastin
a48ca25fa2 fix: and redeclaration 2021-07-31 11:32:50 -04:00
Andrew Bastin
28d636fa0d fix: update Netlify build Node version to 14 2021-07-30 23:39:50 -04:00
liyasthomas
2904084853 refactor: tests and results section 2021-07-31 00:51:41 +05:30
liyasthomas
a1eac2f348 refactor: cleanup documentation page 2021-07-30 21:06:25 +05:30
liyasthomas
203b45f4d5 refactor: cleanup 2021-07-30 13:52:43 +05:30
liyasthomas
2891da3c74 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-07-30 13:15:10 +05:30
Andrew Bastin
09d552b17a fix: fix cancel request issues and stream setup issues 2021-07-29 22:44:43 -04:00
Andrew Bastin
b524fa7248 feat: revamped keybinding implementation 2021-07-29 22:13:06 -04:00
Andrew Bastin
e138a5f846 fix: typescript error on clipboard 2021-07-29 18:13:17 -04:00
liyasthomas
82a5f56522 Merge branch 'main' into refactor/ui 2021-07-29 09:46:06 +05:30
liyasthomas
4f71e801d5 refactor(ui): minor improvements on buttons and actions 2021-07-28 22:23:43 +05:30
Andrew Bastin
d5cb9f135f fix: null reference when parsing error responses (fixes #1749) 2021-07-28 00:47:52 -04:00
liyasthomas
1a4d3dc91a feat: refactor modal component 2021-07-28 01:08:11 +05:30
liyasthomas
78fccc8583 feat: migrate all copy to clipboard actions to v-clipboard 2021-07-27 18:17:41 +05:30
liyasthomas
37ad8e08fc fix: build 2021-07-26 21:53:59 +05:30
liyasthomas
e60e8545a1 refactor(ui): better color schemes and empty states 2021-07-26 21:39:39 +05:30
liyasthomas
5258db345e refactor(ui): remaining realtime pages 2021-07-26 12:40:02 +05:30
liyasthomas
c3921bebf2 fix: proper padding and margins 2021-07-26 09:08:06 +05:30
liyasthomas
08d1f01e8e Merge branch 'main' into refactor/ui 2021-07-26 07:54:53 +05:30
liyasthomas
8bf9a1e821 chore(deps): bump 2021-07-26 07:52:15 +05:30
liyasthomas
8debb65d89 refactor(ui): better rendering with Inter font 2021-07-26 01:33:32 +05:30
liyasthomas
397cab9032 Merge branch 'main' into refactor/ui 2021-07-25 21:35:29 +05:30
liyasthomas
449c87802f chore(deps): bump 2021-07-25 18:41:26 +05:30
liyasthomas
3862a926ab fix: minor color scheme inconsistencies 2021-07-25 16:23:29 +05:30
liyasthomas
56c2e1094d refactor: wire remaining request actions 2021-07-25 11:15:53 +05:30
Andrew Bastin
4508e309c2 fix: fix typescript issues 2021-07-24 17:45:48 -04:00
liyasthomas
f0aaca2639 feat: slideover menus, minor ui fixes 2021-07-24 22:16:48 +05:30
liyasthomas
4c2a9c1229 refactor: types 2021-07-24 16:28:32 +05:30
liyasthomas
4de55c39dd refactor: graphql page to new ui 2021-07-24 14:10:28 +05:30
liyasthomas
84b94f3091 fix: minor input stylings 2021-07-24 11:23:10 +05:30
Liyas Thomas
2e94969a41 fix: uniform inputs 2021-07-23 19:12:31 +00:00
Liyas Thomas
09eabbdcea Merge branch 'main' into refactor/ui 2021-07-23 18:28:37 +00:00
Liyas Thomas
233214cb30 refactor: move actions from app header to app footer 2021-07-23 18:28:07 +00:00
liyasthomas
f694f1ad36 refactor: init new state for body 2021-07-23 00:07:39 +05:30
Andrew Bastin
dd004c921e fix: fix test script lint errors 2021-07-22 01:24:08 -04:00
Andrew Bastin
8597c04ff1 feat: test script and pre-request script wiring 2021-07-21 23:56:39 -04:00
Andrew Bastin
5f5f086dfc feat: fix loading state disappearing 2021-07-21 17:43:15 -04:00
liyasthomas
04cd5b0981 feat: zenmode + toggle left, right & header panes 2021-07-21 15:25:46 +05:30
liyasthomas
22772ac10f feat: migrate pre-request script, test script, settings to nuxt composition 2021-07-21 10:50:20 +05:30
liyasthomas
d4234f0837 fix: nullable analytic events 2021-07-21 10:15:29 +05:30
liyasthomas
982f467572 fix: remove unused deps 2021-07-21 09:02:37 +05:30
Andrew Bastin
f4ffb8e357 feat: move pre request script to new state system 2021-07-20 23:27:06 -04:00
Andrew Bastin
cd908ae1b2 feat: parse and run REST request params
* package-lock.json:
2021-07-20 19:12:04 -04:00
Andrew Bastin
1573ddad1b feat: initial attempt at restoring codegen 2021-07-20 19:12:04 -04:00
liyasthomas
2ace83bcaf fix: minor UI styling 2021-07-20 15:59:30 +05:30
liyasthomas
88ccda8fd1 feat: shortcuts indicator toggle 2021-07-19 22:12:56 +05:30
liyasthomas
ae8cf656a3 Merge branch 'refactor/codegen' into refactor/ui 2021-07-19 19:23:17 +05:30
liyasthomas
68c00433f5 refactor(ui): introduce landing page + minor fixes 2021-07-19 18:42:33 +05:30
liyasthomas
f1ad7b9ef5 chore(deps): bump 2021-07-18 20:41:51 +05:30
liyasthomas
27cf8660d8 Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-18 20:40:41 +05:30
liyasthomas
7105e7a86f chore(deps): bump 2021-07-18 20:37:06 +05:30
liyasthomas
e52ed7a5ce refactor(ui): minor inconsistency fixes 2021-07-18 18:53:51 +05:30
liyasthomas
393e6896ec refactor(ui): more pages 2021-07-18 13:17:58 +05:30
liyasthomas
6ebfb1f109 feat: init codegen state 2021-07-18 10:03:52 +05:30
liyasthomas
590c21209c refactor(ui): sort windicss classes 2021-07-17 23:10:28 +05:30
liyasthomas
e7b58b27e8 feat: init storybook 2021-07-16 20:35:15 +05:30
liyasthomas
a2a9bae0e3 refactor(ui): minor stylings 2021-07-16 20:34:35 +05:30
liyasthomas
3ef8e677c7 fix: wire response + init error handling 2021-07-15 09:40:45 +05:30
Andrew Bastin
86c9e09782 fix: theme flicker 2021-07-14 22:29:11 -04:00
liyasthomas
fa8662f17d Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-15 06:33:31 +05:30
Andrew Bastin
dcf34ea92c feat: pass headers to the ran request 2021-07-14 15:36:15 -04:00
Andrew Bastin
9ece8adda8 feat: response size and duration metrics 2021-07-14 14:54:53 -04:00
Liyas Thomas
c302f7e1a9 Merge pull request #1742 from s-r-x/fix/nil-response-time
fix: undefined duration
2021-07-14 12:51:09 +05:30
s-r-x
2907d69dfc fix: undefined duration 2021-07-14 10:55:57 +05:00
liyasthomas
eeddb6a97e fix: proper key for v-for loops 2021-07-14 05:19:08 +05:30
liyasthomas
7ec8539540 feat: new components and UI improvements 2021-07-13 22:07:01 +05:30
liyasthomas
5e740a6ed6 refactor(ui): minor stylings 2021-07-13 12:48:57 +05:30
liyasthomas
a4032836c3 feat: init new response state system 2021-07-13 11:07:29 +05:30
Andrew Bastin
ffc891f38e feat: add header session store fields and dispatchers 2021-07-12 20:17:13 -04:00
liyasthomas
93ea80a3e3 feat: init request state management 2021-07-12 09:11:55 +05:30
liyasthomas
68ff422a5f Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-12 07:05:29 +05:30
Andrew Bastin
54d21c4950 feat: url and params rewrite index.vue 2021-07-11 21:33:11 -04:00
Liyas Thomas
bfd9327e74 fix: raw <=> key-value toggle button 2021-07-12 01:21:40 +00:00
liyasthomas
498d0e18b9 Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-12 04:22:21 +05:30
liyasthomas
b5e524e513 refactor: remaining sections stylings 2021-07-12 04:20:00 +05:30
Liyas Thomas
c512c8d297 chore(deps): bump 2021-07-11 14:39:52 +00:00
liyasthomas
2e092d34a6 refactor: minor input stylings 2021-07-10 23:38:35 +05:30
liyasthomas
d94c8aec51 refactor: request section 2021-07-10 18:45:39 +05:30
liyasthomas
c7062ad613 refactor: modals 2021-07-09 22:49:45 +05:30
liyasthomas
08d0765cfb Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-09 13:11:12 +05:30
liyasthomas
1f0a3e97ae refactor: gql docs 2021-07-09 13:09:52 +05:30
Andrew Bastin
36745d79db feat: add page view to telemetry 2021-07-08 23:39:07 -04:00
liyasthomas
c6490818d0 feat: revamp graphql sidebar ui 2021-07-08 23:42:15 +05:30
liyasthomas
f1ef403c83 Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-08 14:03:41 +05:30
liyasthomas
cad7ecf760 feat: ask confirmation for telmetry 2021-07-08 14:00:18 +05:30
liyasthomas
8f7fcfa147 perf: even 2021-07-08 13:46:43 +05:30
liyasthomas
a3bde5797a Merge remote-tracking branch 'origin/main' into refactor/ui 2021-07-08 13:44:00 +05:30
liyasthomas
a070bed7c9 feat: revamp environments ui 2021-07-08 13:36:37 +05:30
liyasthomas
207dc2b6a6 feat: revamp collections ui 2021-07-08 13:00:41 +05:30
liyasthomas
fee0a8cec1 feat: ask confirmation for telmetry 2021-07-08 09:20:41 +05:30
Liyas Thomas
6635d449a5 feat: history section 2021-07-07 23:28:42 +00:00
Andrew Bastin
99b1699ade feat: disable telemetry calls if disabled 2021-07-07 16:40:31 -04:00
liyasthomas
20d38e247b feat: enable telemetry toggle button 2021-07-07 06:30:49 +05:30
Liyas Thomas
7c8ab6fd4a perf: even 2021-07-06 18:18:07 +00:00
Liyas Thomas
7bb570cdc7 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-07-06 18:13:49 +00:00
Liyas Thomas
fc5a5aad8d feat: init split layouts 2021-07-06 18:00:39 +00:00
Liyas Thomas
93d373c032 refactor(ui): popovers 2021-07-06 18:00:39 +00:00
Liyas Thomas
fde5b0717d fix: button icons 2021-07-06 18:00:39 +00:00
Liyas Thomas
069b26bdc4 feat: settings page 2021-07-06 18:00:39 +00:00
Liyas Thomas
8f3e4cfdba feat: refactor buttons 2021-07-06 18:00:39 +00:00
Liyas Thomas
ba7f5d3dc3 feat: tooltip and popover components 2021-07-06 18:00:39 +00:00
Liyas Thomas
42ce183510 feat: landing page + smart components 2021-07-06 18:00:39 +00:00
liyasthomas
977bad2156 refactor: init packages 2021-07-06 18:00:39 +00:00
Liyas Thomas
fd4f49cf8e refactor: settings page + ui components 2021-07-06 18:00:39 +00:00
Liyas Thomas
1b540c0e57 feat: refactor buttons 2021-07-06 18:00:39 +00:00
Liyas Thomas
0e443b3a43 feat: tooltip and popover components 2021-07-06 18:00:38 +00:00
Liyas Thomas
eaf0da3d00 feat: users section 2021-07-06 18:00:38 +00:00
Liyas Thomas
dd41ac3888 feat: landing page + smart components 2021-07-06 18:00:38 +00:00
liyasthomas
a0e26c6c4f refactor: init packages 2021-07-06 18:00:38 +00:00
liyasthomas
6ac7ce2c73 chore(deps): bump 2021-07-06 18:00:38 +00:00
Andrew Bastin
7b3dd697bb feat: pass theme data to analytics 2021-07-06 08:30:48 -04:00
Andrew Bastin
48e562dcee feat: theme syncing 2021-07-06 08:20:37 -04:00
Andrew Bastin
86bd4aa568 feat: add analytics logging while hoppscotch requests are fired 2021-07-05 21:47:48 -04:00
Liyas Thomas
ed91486d53 refactor(ui): popovers 2021-07-05 16:52:15 +00:00
Andrew Bastin
913b073ba4 feat: add initial analytics implementation 2021-07-05 12:45:10 -04:00
Andrew Bastin
b1418c081c feat: auth event subject 2021-07-05 12:44:43 -04:00
Andrew Bastin
6b373bee47 feat: update env with FB_MEASUREMENT_ID 2021-07-05 12:42:44 -04:00
Liyas Thomas
256d4b3e07 fix: button icons 2021-07-05 12:56:00 +00:00
Liyas Thomas
dc5a09bebc feat: settings page 2021-07-05 05:08:03 +00:00
Liyas Thomas
ababd79da2 Merge branch 'refactor/ui' of https://github.com/hoppscotch/hoppscotch into refactor/ui 2021-07-04 17:12:15 +00:00
Liyas Thomas
5e21210962 refactor: settings page + ui components 2021-07-04 17:00:30 +00:00
Liyas Thomas
3e3da2f27b feat: refactor buttons 2021-07-04 17:00:30 +00:00
Liyas Thomas
b55439ce44 feat: tooltip and popover components 2021-07-04 17:00:30 +00:00
Liyas Thomas
ff791098d8 feat: users section 2021-07-04 17:00:29 +00:00
Liyas Thomas
5abf837e95 feat: landing page + smart components 2021-07-04 17:00:29 +00:00
liyasthomas
6bcf1a3522 refactor: init packages 2021-07-04 17:00:29 +00:00
liyasthomas
b0f055567d chore(deps): bump 2021-07-04 22:27:18 +05:30
Liyas Thomas
1ee2fecbc2 feat: refactor buttons 2021-07-03 13:14:58 +00:00
Liyas Thomas
04b0cd2d3b feat: tooltip and popover components 2021-07-02 16:30:08 +00:00
Liyas Thomas
0439e6811b feat: users section 2021-07-02 08:55:03 +00:00
Liyas Thomas
a130cfcadb feat: landing page + smart components 2021-07-02 05:01:29 +00:00
Liyas Thomas
77fcc14043 Merge pull request #1737 from s-r-x/fix/duplicate-input-id
fix: duplicated input ids
2021-07-02 04:58:22 +05:30
liyasthomas
fb93db6ad4 refactor: init packages 2021-07-01 22:09:11 +05:30
s-r-x
47cf321eba fix: duplicated input ids 2021-07-01 15:10:51 +05:00
Liyas Thomas
b0ab1b048d refactor(ui): better GitHub buttons 2021-06-30 17:23:48 +00:00
liyasthomas
aaec87d7be docs: updated readme 2021-06-30 20:26:11 +05:30
liyasthomas
3198bc6b2c chore(deps): bump 2021-06-30 14:53:15 +05:30
liyasthomas
60be228c33 Merge branch 'refactor/sponsors' of https://github.com/hoppscotch/hoppscotch into refactor/sponsors 2021-06-30 14:27:38 +05:30
liyasthomas
22c3ffcc02 chore: removed sponsorship prompts 2021-06-30 14:21:16 +05:30
liyasthomas
b750ccd46f refactor: better implimentation for slots 2021-06-30 14:16:02 +05:30
liyasthomas
0dd0d262d6 Merge branch 'refactor/code' 2021-06-29 17:07:46 +05:30
liyasthomas
9a83938c75 refactor: better icon button states 2021-06-29 17:04:02 +05:30
liyasthomas
9b5b3cc202 ci: enforce commitlint + skip build on tests 2021-06-29 06:50:38 +05:30
liyasthomas
729f341164 fix: remove stale state file 2021-06-29 06:37:42 +05:30
liyasthomas
d5c5fb7435 refactor: better error prompts 2021-06-28 17:28:22 +05:30
liyasthomas
01b8001d4c chore: removed sponsorship prompts 2021-06-28 17:27:03 +05:30
liyasthomas
3992650fd6 fix: remove stale default environments state - fixed #1735 2021-06-28 08:48:07 +05:30
liyasthomas
a2354b5e9e feat: added commitlint, semantic pr 2021-06-28 00:24:16 +05:30
liyasthomas
43b7e94974 feat: setup firebase hosting for prod 2021-06-27 12:06:57 +05:30
Liyas Thomas
cdfce9e2b8 refactor: class names 2021-06-26 10:41:19 +00:00
Liyas Thomas
9bd86f0564 fix: minor stylings fixes 2021-06-26 00:19:42 +00:00
Liyas Thomas
1c0b5b25ed Merge pull request #1734 from hoppscotch/feat/windicss
feat: remove tailwindcss + introduce windicss
2021-06-26 05:21:13 +05:30
Liyas Thomas
6d33132705 feat: remove tailwindcss + introduce windicss 2021-06-25 23:44:27 +00:00
liyasthomas
3e5629e738 fix: typo 2021-06-21 16:39:51 +05:30
liyasthomas
41eb4f8395 refactor(ui): minor font tweaks 2021-06-21 16:31:40 +05:30
liyasthomas
6ddff58ba5 feat: better route determination - fixed #1732 2021-06-21 15:33:51 +05:30
liyasthomas
5bb9b1b675 chore: bump deps 2021-06-21 15:32:23 +05:30
Andrew Bastin
f4f29b8520 Fix localStorage usage 2021-06-21 00:27:45 -04:00
Andrew Bastin
257e2db651 Add no localstorage rule 2021-06-20 23:27:05 -04:00
liyasthomas
a853c13bcd Merge branch 'newstate/firebase' 2021-06-20 19:09:59 +05:30
liyasthomas
96c23200f7 chore: bump deps 2021-06-20 18:06:20 +05:30
Andrew Bastin
7c2becd3a4 Merge remote-tracking branch 'upstream/main' into newstate/firebase 2021-06-19 20:41:25 -04:00
Andrew Bastin
a85729b4cf Fix firebase reinitialization crash 2021-06-19 20:36:23 -04:00
Liyas Thomas
bd3cec18d8 Merge pull request #1727 from d4v3y0rk/patch-1 2021-06-20 05:47:23 +05:30
Dave York
7dcd96350a Cleaner Docker run command
added two flags to the docker run command to clean up the container after it has been run and also assign it a name to help manage it while it is running.
2021-06-19 12:09:03 -04:00
Ilya
2e1c0ae77a fix: janky sidebar animation (#1726) 2021-06-18 11:56:27 +05:30
liyasthomas
6a6754c7da feat: active toggle for web socket protocols 2021-06-18 10:45:48 +05:30
Andrew Bastin
1fb2c35984 Handle error.vue initializeFirebase 2021-06-17 08:22:59 -04:00
Andrew Bastin
02d3b45efc Added settings observable 2021-06-16 22:35:53 -04:00
Andrew Bastin
4ce7f0b487 Remove redudant applySettingFB 2021-06-16 22:33:17 -04:00
liyasthomas
3559d98df1 chore: lint 2021-06-16 19:13:07 +05:30
Liyas Thomas
0a4251825b feat: Sec-WebSocket-Protocol header on WebSocket connections - resolved #1620 2021-06-15 14:44:23 +00:00
Liyas Thomas
499cd9d81b Merge pull request #1723 from s-r-x/fix/broken-gql-col-req-edit 2021-06-15 18:24:52 +05:30
Liyas Thomas
10a6b96f13 Merge branch 'main' into fix/broken-gql-col-req-edit 2021-06-15 18:15:40 +05:30
Liyas Thomas
4e3d9187f7 Merge pull request #1721 from s-r-x/fix/modal-overlay-mouseup
fix: modal backdrop click
2021-06-15 18:13:02 +05:30
Andrew Bastin
0921cccb4c Reset save req selection when selected item is deleted 2021-06-15 08:26:01 -04:00
s-r-x
07a505c365 fix: broken gql collection request editor 2021-06-15 15:25:19 +05:00
s-r-x
c3411ba0cf fix: do not close modal if mousedown event was on the content but mouseup on the backdrop 2021-06-15 14:28:10 +05:00
Liyas Thomas
5246284e32 refactor(ci): minor optimizations 2021-06-15 08:40:03 +00:00
Ilya
5fe8fce89d refactor: modals (#1720)
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2021-06-15 13:48:38 +05:30
liyasthomas
0cedc9ed51 chore: remove unused code 2021-06-15 06:34:21 +05:30
Liyas Thomas
7cbb61bdf8 chore(deps): bump 2021-06-14 15:43:21 +00:00
Andrew Bastin
b357dc8e2f Fix history sync issues 2021-06-14 09:24:46 -04:00
Andrew Bastin
f745fef6c2 Fix enter.vue firebase not loaded 2021-06-14 08:40:39 -04:00
Andrew Bastin
dfe810fff4 Fix Sign In With Github 2021-06-14 08:35:53 -04:00
liyasthomas
111a947413 feat: minor ui tweaks 2021-06-14 09:55:27 +05:30
Andrew Bastin
85c6932f8f Initial Firebase refactor pass 2021-06-14 00:11:57 -04:00
liyasthomas
ced2f1b911 feat: introduce animations 2021-06-13 20:31:42 +05:30
liyasthomas
685f9d506d chore(deps): bump 2021-06-13 16:25:22 +05:30
liyasthomas
34cd604a91 refactor(ui): minor ux improvements 2021-06-13 16:24:29 +05:30
liyasthomas
2ffd0be03f refactor(ui): better color names 2021-06-12 22:16:17 +05:30
liyasthomas
58296505a8 feat: show and hide sidebar - fixed #1716 2021-06-12 16:40:12 +05:30
Andrew Bastin
779f5e9af4 Merge pull request #1710 from hoppscotch/feat/email-auth
Passwordless sign in with email address
2021-06-11 01:14:06 -04:00
Andrew Bastin
2351f64e6f Merge branch 'main' into feat/email-auth 2021-06-11 01:10:19 -04:00
liyasthomas
03987da05b refactor: better ui + ux for email sign in 2021-06-11 10:29:52 +05:30
Andrew Bastin
07e2cb5cd9 Email login toast improvements 2021-06-11 00:25:58 -04:00
Andrew Bastin
9b43f9a40c Close email modal on login complete 2021-06-10 23:57:29 -04:00
liyasthomas
43b0225fba fix: broken create github gist for collections 2021-06-11 09:05:00 +05:30
Liyas Thomas
da491a2967 Merge branch 'main' into feat/email-auth 2021-06-11 05:33:16 +05:30
liyasthomas
be67986123 feat: sign in with email 2021-06-11 05:31:29 +05:30
liyasthomas
af9c7e0aff feat: add FundOSS toast 2021-06-10 19:26:03 +05:30
liyasthomas
27e061c355 setup: GitHub actions for tests and remove Travis CI 2021-06-10 11:02:24 +05:30
Liyas Thomas
da94a94d71 Merge pull request #1709 from JoelJacobStephen/main
Made changes to Black Mode to make UI elements more visible.
2021-06-09 08:52:58 +05:30
Joel Jacob Stephen
970c2e56d8 Made changes to Black Mode to make UI elements more visible. 2021-06-08 18:28:34 +05:30
liyasthomas
766c31fa56 chore: bump deps + refactor: consistent import / export modal 2021-06-07 15:22:34 +05:30
Andrew Bastin
50fa1c8f0a Fix import export for environments 2021-06-07 00:13:28 -04:00
Andrew Bastin
e361d66c88 Merge branch 'newstate/environments' into main 2021-06-06 23:12:41 -04:00
Andrew Bastin
f1203efa62 Fix firebase sync issue 2021-06-06 20:35:28 -04:00
liyasthomas
45b9f2e1bf fix: replace auto complete with drop down for content-types - fixed #1704 2021-06-06 20:56:56 +05:30
liyasthomas
538600354d chore(deps): bump 2021-06-06 16:36:02 +05:30
liyasthomas
5c9093823b chore: lint + minor ui tweaks 2021-06-06 16:35:30 +05:30
liyasthomas
7b6c4f71a2 patch: set application/json as default content-type 2021-06-06 15:52:54 +05:30
nelsontky
7e9ae69f38 fix: prevent overwrite of content type (#1703)
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2021-06-06 03:12:50 -07:00
Andrew Bastin
ddbc9ca61b Inject globals env into pre-request scripts 2021-06-05 21:07:06 -04:00
Andrew Bastin
d9aa965069 Fix import of replaceEnvironments in fb.js 2021-06-05 20:55:51 -04:00
Andrew Bastin
6ea9d16f87 Add firebase sync code for new environment state system 2021-06-04 22:52:06 -04:00
Andrew Bastin
5bfeb541fc Initial environment state system refactor 2021-06-04 22:41:07 -04:00
liyasthomas
c3f713c0bd fix: break words on long texts - fixed #1699 2021-06-02 08:20:39 +05:30
Liyas Thomas
97979a6ab5 Merge pull request #1696 from JoelJacobStephen/main
Changing Hoppscotch Title from Hs to Hoppscotch for all sizes
2021-06-02 00:08:30 +05:30
Joel Jacob Stephen
055adf9fe0 Changing Hoppscotch Title from Hs to Hoppscotch for all sizes 2021-06-01 23:49:04 +05:30
Andrew Bastin
e94adc835d Merge pull request #1695 from JoelJacobStephen/main
Simplified the capitalization of Accent Color Names by using a function.
2021-06-01 13:24:32 -04:00
Joel Jacob Stephen
50bb8c4fdd Simplified the capitalization of Accent Color Names by using a function. 2021-06-01 22:44:22 +05:30
Andrew Bastin
aa0a340b95 Merge branch 'newstate/collections' into main 2021-06-01 00:12:40 -04:00
Andrew Bastin
41d21bc0ff Remove unwanted logs 2021-06-01 00:09:35 -04:00
liyasthomas
2de4b75b89 docs: add join beta form link 2021-06-01 07:11:05 +05:30
Andrew Bastin
b52cc9e2b4 Reimplement Body Param File input filtering for saving requests 2021-05-31 14:00:48 -04:00
liyasthomas
fea3843714 Merge branch 'newstate/collections' of https://github.com/AndrewBastin/hoppscotch into newstate/collections 2021-05-31 10:37:44 +05:30
Andrew Bastin
5df5d59f50 Drag and Drop for GraphQL requests in Collections pane 2021-05-30 23:30:28 -04:00
Andrew Bastin
062dd4f889 Linting 2021-05-30 23:30:28 -04:00
Andrew Bastin
948b027059 Remove GraphQL SaveRequest component 2021-05-30 23:30:28 -04:00
Andrew Bastin
4d057a39ed Migrate GraphQL to use SaveRequest modal instead of GQL one 2021-05-30 23:30:28 -04:00
Andrew Bastin
68c4efb1d3 fix: drag and drop on collections 2021-05-30 23:30:28 -04:00
Andrew Bastin
eda8c7da41 Initial Collection State System implementation
Co-authored-by: Liyas Thomas <hi@liyasthomas.com>
2021-05-30 23:30:28 -04:00
Liyas Thomas
ac1937f9be chore(deps): bump 2021-05-30 13:40:20 +00:00
liyasthomas
5f0f7693bb fix: import collections from file - removed store commit 2021-05-30 09:21:55 +05:30
Andrew Bastin
9ad22e2600 Linting 2021-05-29 22:43:05 -04:00
Andrew Bastin
fe8bbc6cc8 Remove GraphQL SaveRequest component 2021-05-29 22:38:18 -04:00
Andrew Bastin
795c5f8263 Migrate GraphQL to use SaveRequest modal instead of GQL one 2021-05-29 22:36:58 -04:00
Andrew Bastin
66bb9dc42b fix: drag and drop on collections 2021-05-28 00:23:11 -04:00
Andrew Bastin
70a350fdac Initial Collection State System implementation
Co-authored-by: Liyas Thomas <hi@liyasthomas.com>
2021-05-27 23:22:17 -04:00
660 changed files with 61376 additions and 98053 deletions

View File

@@ -1,34 +0,0 @@
{
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"contributors": [
{
"login": "liyasthomas",
"name": "Liyas Thomas",
"avatar_url": "https://avatars1.githubusercontent.com/u/10395817?v=4",
"profile": "https://liyasthomas.web.app",
"contributions": [
"code",
"design"
]
},
{
"login": "AndrewBastin",
"name": "Andrew Bastin",
"avatar_url": "https://avatars2.githubusercontent.com/u/9131943?v=4",
"profile": "https://github.com/AndrewBastin",
"contributions": [
"code"
]
},
],
"contributorsPerLine": 7,
"projectName": "hoppscotch",
"projectOwner": "hoppscotch",
"repoType": "github",
"repoHost": "https://github.com",
"skipCi": true
}

2
.github/FUNDING.yml vendored
View File

@@ -1,4 +1,2 @@
github: hoppscotch
open_collective: hoppscotch
patreon: liyasthomas
custom: https://www.paypal.me/liyascthomas

View File

@@ -6,5 +6,3 @@ labels: ''
assignees: ''
---

5
.github/semantic.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
# Always validate the PR title AND all the commits
titleAndCommits: true
# Allows use of Merge commits (eg on github: "Merge branch 'master' into feature/ride-unicorns")
# this is only relevant when using commitsOnly: true (or titleAndCommits: true)
allowMergeCommits: true

View File

@@ -1,71 +1,61 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
name: "Code Scanning - Action"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
- cron: '0 0 * * 6'
jobs:
analyze:
name: Analyze
CodeQL-Build:
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
permissions:
# required for all workflows
security-events: write
# only required for workflows in private repositories
actions: read
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
- name: Checkout repository
uses: actions/checkout@v2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below).
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# If the Autobuild fails above, remove it and uncomment the following
# three lines and modify them (or add more) to build your code if your
# project uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

18
.github/workflows/deploy-prod.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Deploy to Live Channel
on:
push:
branches:
- main
jobs:
deploy_live_website:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_POSTWOMAN_API }}'
channelId: live
projectId: postwoman-api

39
.github/workflows/publish-docker.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Publish Docker image
on:
push:
branches: [main]
release:
types: [published]
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v2
- name: Log in to Docker Hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: hoppscotch/hoppscotch
flavor: |
latest=true
prefix=
suffix=
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

32
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Cache .pnpm-store
uses: actions/cache@v1
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-node${{ matrix.node-version }}-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Install pnpm
run: curl -f https://get.pnpm.io/v6.14.js | node - add --global pnpm@6
- 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

4
.husky/commit-msg Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit ""

View File

@@ -8,7 +8,6 @@ module.exports = {
{
ignoreAtRules: [
"extends",
"tailwind",
"apply",
"variants",
"responsive",

View File

@@ -1,34 +0,0 @@
# == INSTRUCTIONS FOR SETTING UP TRAVIS ==
#
# 1. Find this repository in your Travis-CI dashboard.
# open settings and add an environment variable called
# GITHUB_ACCESS_TOKEN and set it to your personal access token.addons:
# See: https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line
#
# **DO NOT TURN ON 'Display value in build log'!!!!**
#
# 2. Push the code to the repository.
language: node_js
node_js:
- lts/*
os: linux
cache: npm
branches:
only:
- main
install:
- npm ci
before_script:
- npm run build # use nuxt build and start to run tests
script:
- npm test
notifications:
webhooks: https://www.travisbuddy.com

View File

@@ -1,4 +1,4 @@
FROM node:12.10.0-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
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,109 +0,0 @@
# **GitHub Externship @ Hoppscotch**
**We ❤️ open source**
We are super excited to be a Partner Organization of GitHub Externship 2021 and look forward to supporting all interested students to participate and contribute to our [open source projects](https://github.com/hoppscotch).
This document covers the process, expectations and guidelines for any interested student so that we can guide, mentor in the best possible manner and most importantly review your community engagement which is a critical factor along with your project idea to be selected from our organization.
**This post will be updated from time to time. So please keep an eye on it.**
Before, any of you jump in and start contributing, here are a few documents from the GitHub Externship Team which we advise every student to read through carefully and thoroughly:
- [GitHub Externship: Website](https://github-externships.github.io/externship/index.html)
- [GitHub Externship: Program Structure](https://github-externships.github.io/externship/structure.html)
Our awesome community members frequently request for features on our [Discord server](https://hoppscotch.io/discord), [Telegram group](https://hoppscotch.io/externship_telegram), [GitHub issues tab](https://github.com/hoppscotch/hoppscotch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) and we have a never ending list of awesome ideas. However, keeping in mind the 3 months time span, we have filtered through our stockpile and come up with the following ideas for [GitHub Externship](https://github-externships.github.io/externship/index.html) program.
## **Ideas**
If youre a student interested in working with Hoppscotch during GitHub Externship, weve assembled for you a list of 20 ideas under the following three categories:
### **1. Implement existing feature requests:**
- [gRPC-Web support](https://github.com/hoppscotch/hoppscotch/issues/402)
Like swagger, let users view message formats from `.proto` / `URL` and test the server methods by sending any messages from the Hoppscotch.
[**`Learn more →`**](https://github.com/hoppscotch/hoppscotch/issues/402)
- [Swagger / OpenAPI support](https://github.com/hoppscotch/hoppscotch/issues/470)
Like [Swagger Inspector](https://inspector.swagger.io/builder) / [Swagger Editor](https://editor.swagger.io). Let users import `swagger.json` and test the server methods by sending any messages from the Hoppscotch.
[**`Learn more →`**](https://github.com/hoppscotch/hoppscotch/issues/470)
- [Mock Server](https://github.com/hoppscotch/hoppscotch/issues/1598)
Mock server allows users to create mock endpoints that accepts request from the system-under-test or from a `json` file.
[**`Learn more →`**](https://github.com/hoppscotch/hoppscotch/issues/1598)
### **2. Implement new features:**
If you'd like to implement a totally new feature to help developers make API testing easy, feel free to come up with your own feature request or a port of feature from other API testing tools.
[**Create new feature request →**](https://github.com/hoppscotch/hoppscotch/issues/new?assignees=&labels=&template=feature_request.md&title=Feature%20[GitHub%20Externship]:)
### **3. Refactor existing features:**
If you'd like to refactor an already implemented feature / workflow - feel free to open a PR to do that. We appreciate using industry best pratices and latest technologies on all of our open source projects.
## **Built with**
- [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Tailwind CSS](https://tailwindcss.com)
- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- [TypeScript](https://www.typescriptlang.org)
- [Vue](https://vuejs.org)
- [Nuxt](https://nuxtjs.org)
## **Contributing**
Please contribute using [GitHub Flow](https://guides.github.com/introduction/flow). Create a branch, add commits, and [open a pull request](https://github.com/hoppscotch/hoppscotch/compare).
Please read [`CONTRIBUTING`](CONTRIBUTING.md) for details on our [`CODE OF CONDUCT`](CODE_OF_CONDUCT.md), and the process for submitting pull requests to us.
## **Quick links**
[**`Repository →`**](https://github.com/hoppscotch/hoppscotch)
[**`Web app →`**](https://hoppscotch.io)
[**`Discord server →`**](https://hoppscotch.io/discord)
[**`Telegram group →`**](https://hoppscotch.io/externship_telegram)
## **Discussions channel**
We use [GitHub Discussions](https://github.com/hoppscotch/hoppscotch/discussions) as the primary channel for anything and everything related to GitHub Externship, ranging from
- Queries on issues youre working or thinking about to take up.
- Mentor advice on your project ideas [Google Drive document once there is enough clarity for easier collaboration and feedback check project proposal ideas above]
- Helping out your friends to onboard and contribute
- Finally even selection updates etc.
Before asking a question please check this [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask)
## **Need help?**
Start a discussion [here](https://github.com/hoppscotch/hoppscotch/discussions) if youre unable to get a response from the [Telegram](https://hoppscotch.io/externship_telegram), [Discord](https://hoppscotch.io/discord) communities.
Start a new idea under [discussions](https://github.com/hoppscotch/hoppscotch/discussions) only once youve finalized your project proposal.
Send us an email at support@hoppscotch.io for any administrative or operational concerns regarding the program.
## **Submit your proposal on time**
You can find the complete GitHub Externship program timeline [here](https://github-externships.github.io/externship/structure.html). Students can begin registering and submitting project proposals to mentor organizations—including Hoppscotch—on April 22, 2021.
All proposals must be submitted by May 21, 2021.
We look forward to seeing your proposals for a happy summer of coding.
## **Mentors**
- [Liyas Thomas](https://github.com/liyasthomas)
- [Andrew Bastin](https://github.com/andrewbastin)
If you have any questions or queries please contact us via [Telegram](https://hoppscotch.io/externship_telegram), [Discord](https://hoppscotch.io/discord) or send an email to us at support@hoppscotch.io.

523
README.md
View File

@@ -1,58 +1,55 @@
<div align="center">
<a href="https://hoppscotch.io"><img src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/logo.png" alt="hoppscotch.io logo" height="128"></a>
<br>
<br>
<a href="https://hoppscotch.io">
<img
src="https://avatars.githubusercontent.com/u/56705483"
alt="Hoppscotch Logo"
height="64"
/>
</a>
<br />
<p>
<b>Hoppscotch - Open source API development ecosystem</b>
<h3>
<b>
Hoppscotch
</b>
</h3>
</p>
<p>
<i>Helps you create requests faster, saving precious time on development - <a href="https://eepurl.com/g6n_P5">Subscribe</a></i>
<b>
Open source API development ecosystem
</b>
</p>
<p>
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen?logo=github)](CODE_OF_CONDUCT.md) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fhoppscotch.io&logo=hoppscotch)](https://hoppscotch.io) [![Travis Build Status](https://img.shields.io/travis/com/hoppscotch/hoppscotch/main?logo=Travis)](https://travis-ci.com/hoppscotch/hoppscotch) [![Tweet](https://img.shields.io/twitter/url?url=https%3A%2F%2Fhoppscotch.io%2F)](https://twitter.com/share?text=%F0%9F%91%BD%20Hoppscotch%20%E2%80%A2%20Open%20source%20API%20development%20ecosystem%20-%20Helps%20you%20create%20requests%20faster,%20saving%20precious%20time%20on%20development.&url=https://hoppscotch.io&hashtags=hoppscotch&via=hoppscotch_io)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen?logo=github)](CODE_OF_CONDUCT.md) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fhoppscotch.io&logo=hoppscotch)](https://hoppscotch.io) [![Tests](https://github.com/hoppscotch/hoppscotch/actions/workflows/tests.yml/badge.svg)](https://github.com/hoppscotch/hoppscotch/actions) [![Tweet](https://img.shields.io/twitter/url?url=https%3A%2F%2Fhoppscotch.io%2F)](https://twitter.com/share?text=%F0%9F%91%BD%20Hoppscotch%20%E2%80%A2%20Open%20source%20API%20development%20ecosystem%20-%20Helps%20you%20create%20requests%20faster,%20saving%20precious%20time%20on%20development.&url=https://hoppscotch.io&hashtags=hoppscotch&via=hoppscotch_io)
</p>
<p>
<sub>Built with ❤︎ by
<a href="https://github.com/liyasthomas">liyasthomas</a> and
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors">contributors</a>
<sub>
Built with ❤︎ by
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors">
contributors
</a>
</sub>
</p>
<br />
<p>
<a href="https://hoppscotch.io">
<img
src="https://tiny.cc/hoppscotch_screenshot_1"
alt="Screenshot"
width="100%"
/>
</a>
</p>
</div>
<p align="center">
<b>Sponsored by</b>
<br>
<br>
<a href="https://appwrite.io/?utm_source=hoppscotch&utm_medium=banner&utm_campaign=hello" title="Appwrite" target="_blank">
<img height="60px" src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/assets/images/appwrite-banner.svg" title="Appwrite">
</a>
</p>
<div align="center">
<a href="https://hoppscotch.io"><img src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/images/screenshots/banner_dark.png" alt="Screenshot" width="100%"></a>
</div>
<p align="center">
<b>Powered by</b>
<br>
<br>
<a href="https://oss.capital/?ref=hoppscotch" title="OSS Capital" target="_blank">
<img height="100px" src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/assets/images/ossc-banner.svg" title="OSS Capital">
</a>
</p>
#### **Contact**
[![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)
#### **Support**
[![Sponsor on GitHub](https://img.shields.io/badge/sponsor-GitHub-181717?logo=github)](https://github.com/sponsors/hoppscotch) [![Contribute on Open Collective](https://img.shields.io/badge/contribute-Open%20Collective-7FADF2?logo=open-collective)](https://opencollective.com/hoppscotch) [![Join on Patreon](https://img.shields.io/badge/join-Patreon-F96854?logo=patreon)](https://www.patreon.com/liyasthomas) [![Donate on PayPal](https://img.shields.io/badge/donate-PayPal-00457C?logo=paypal)](https://www.paypal.me/liyascthomas)
[![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)
<details>
<summary><i>Table of contents</i></summary>
<details open>
<summary><b>Table of contents</b></summary>
---
@@ -61,21 +58,12 @@
- [Usage](#usage)
- [Built with](#built-with)
- [Developing](#developing)
- [Browser based development environment](#browser-based-development-environment)
- [Local development environment](#local-development-environment)
- [Docker compose](#docker-compose)
- [Docker](#docker)
- [Releasing](#releasing)
- [Contributing](#contributing)
- [Continuous Integration](#continuous-integration)
- [Changelog](#changelog)
- [Authors](#authors)
- [Lead Developers](#lead-developers)
- [Collaborators](#collaborators-)
- [Financial Contributors](#financial-contributors)
- [GitHub Sponsors](#github-sponsors)
- [Open Collective](#open-collective)
- [Code Contributors](#code-contributors)
- [License](#license)
---
@@ -88,84 +76,48 @@
⚡️ **Fast:** Send requests and get/copy responses in real-time.
<details>
<summary><i>HTTP Methods</i></summary>
---
**HTTP Methods**
- `GET` - Requests retrieve resource information
- `HEAD` - Retrieve response headers identical to those of a GET request, but without the response body.
- `POST` - The server creates a new entry in a database
- `PUT` - Updates an existing resource
- `PATCH` - Very similar to `PUT` but makes a partial update on a resource
- `DELETE` - Deletes resource or related component
- `HEAD` - Retrieve response headers identical to those of a GET request, but without the response body.
- `CONNECT` - Establishes a tunnel to the server identified by the target resource
- `OPTIONS` - Describe the communication options for the target resource
- `TRACE` - Performs a message loop-back test along the path to the target resource
- `PATCH` - Very similar to `PUT` but makes a partial update on a 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).
</details>
**Theming**
🌈 **Make it yours:** Customizable combinations for background, foreground and accent colors. [Customize now ✨](https://hoppscotch.io/settings)
- Choose theme: System (default), Light, Dark and Black
- Choose accent color: Green (default), Teal, Blue, Indigo, Purple, Yellow, Orange, Red and Pink
- Distraction free Zen mode
<details>
<summary><i>Theming</i></summary>
---
- Choose theme: System, Light, Dark (default) and Black
- Choose accent color: Blue, Green (default), Teal, Indigo, Purple, Orange, Pink, Red, and Yellow
- Toggle auto-scroll to response
<p>
<a href="https://hoppscotch.io"><img src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/images/screenshots/banner_light.png" alt="Screenshot" width="100%"></a>
</p>
---
</details>
_Customized themes are synced with local session storage_
_Customized themes are synced with cloud / local session_
🔥 **PWA:** Install as a [PWA](https://developers.google.com/web/progressive-web-apps) on your device.
<details>
<summary><i>Features</i></summary>
---
- Instant loading with Service Workers
- Offline support
- Low RAM/memory and CPU usage
- Add to Home Screen
- Desktop PWA
---
</details>
🚀 **Request:** Retrieve response from endpoint instantly.
- Choose `method`
- Enter `URL`
- Send
<details>
<summary><i>Features</i></summary>
---
1. Choose `method`
2. Enter `URL`
3. Send
- Copy/share public "Share URL"
- Generate/copy request code snippets for 10+ languages and frameworks
- Import `cURL`
- Label requests
---
</details>
🔌 **WebSocket:** Establish full-duplex communication channels over a single TCP connection.
📡 **Server Sent Events:** Receive a stream of updates from a server over a HTTP connection without resorting to polling.
@@ -176,27 +128,13 @@ _Customized themes are synced with local session storage_
🔮 **GraphQL:** GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.
<details>
<summary><i>Features</i></summary>
---
- Set endpoint and get schemas
- Set endpoint and get schema
- Multi-column docs
- Set custom request headers
- Query schema
- Get query response
---
</details>
🔐 **Authentication:** Allows to identify the end user.
<details>
<summary><i>Types</i></summary>
---
🔐 **Authorization:** Allows to identify the end user.
- None
- Basic
@@ -204,136 +142,62 @@ _Customized themes are synced with local session storage_
- OAuth 2.0
- OIDC Access Token/PKCE
---
</details>
📢 **Headers:** Describes the format the body of your request is being sent as.
📫 **Parameters:** Use request parameters to set varying parts in simulated requests.
📃 **Request Body:** Used to send and receive data via the REST API.
<details>
<summary><i>Options</i></summary>
---
- Set `Content Type`
- Add or remove Parameter list
- FormData, JSON and many more
- Toggle between key-value and RAW input parameter list
---
</details>
👋 **Response:** Contains the status line, headers and the message/response body.
<details>
<summary><i>Features</i></summary>
---
- Copy response to clipboard
- Download response as a file
- View response headers
- View raw and preview of HTML, image, JSON, XML responses
---
</details>
**History:** Request entries are synced with cloud / local session storage to restore with a single click.
📁 **Collections:** Keep your API requests organized with collections and folders. Reuse them with a single click.
<details>
<summary><i>Features</i></summary>
---
- Unlimited collections, folders and requests
- Nested folders
- Export as / import from GitHub gist
---
</details>
- Export and import as file or GitHub gist
_Collections are synced with cloud / local session storage_
🌐 **Proxy:** Enable Proxy Mode from Settings to access blocked APIs.
<details>
<summary><i>Features</i></summary>
---
- 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://`)
- Use custom Proxy URL
- Access APIs served in non-HTTPS (`http://`) endpoints
- Use your own Proxy URL
---
</details>
_Official proxy server is hosted by Hoppscotch - **[GitHub](https://github.com/hoppscotch/proxyscotch)** - **[Privacy Policy](https://github.com/hoppscotch/proxyscotch/wiki/Privacy-policy)**_
_Official proxy server is hosted by Hoppscotch - **[GitHub](https://github.com/hoppscotch/proxyscotch)** - **[Privacy Policy](https://docs.hoppscotch.io/privacy)**_
📜 **Pre-Request Scripts β:** Snippets of code associated with a request that are executed before the request is sent.
<details>
<summary><i>Use-cases</i></summary>
---
- Initialize environment variables
- Set environment variables
- Include timestamp in the request headers
- Send a random alphanumeric string in the URL parameters
---
</details>
- Any JavaScript functions
📄 **API Documentation:** Create and share dynamic API documentation easily, quickly.
<details>
<summary><i>Usage</i></summary>
---
1. Add your requests to Collections and Folders
2. Export Collections and easily share your APIs with the rest of your team
3. Import Collections and Generate Documentation on-the-go
---
</details>
⌨️ **Keyboard Shortcuts:** Optimized for efficiency.
> **[Shortcuts WIki](https://github.com/hoppscotch/hoppscotch/wiki/Shortcuts)**
> **[Read our documentation on Keyboard Shortcuts](https://docs.hoppscotch.io/features/shortcuts)**
🌎 **i18n:** Experience the app in your own language.
<details>
<summary><i>Usage</i></summary>
---
1. Scroll down to the footer
2. Click "Choose Language" icon button
3. Select your language from the menu
---
</details>
_Keep in mind: Translations aren't available for all source and target language combinations_
**To provide a localized experience for users around the world, you can add you own translations.**
_**All `i18n` contributions are welcome to `i18n` [branch](https://github.com/hoppscotch/hoppscotch/tree/i18n) only!**_
Help us to translate Hoppscotch. Please read [`TRANSLATIONS`](TRANSLATIONS.md) for details on our [`CODE OF CONDUCT`](CODE_OF_CONDUCT.md), and the process for submitting pull requests to us.
📦 **Add-ons:** Official add-ons for hoppscotch.
@@ -347,56 +211,36 @@ _**All `i18n` contributions are welcome to `i18n` [branch](https://github.com/ho
- **[Hopp-Doc-Gen](https://github.com/hoppscotch/hopp-doc-gen)** - An API doc generator CLI for Hoppscotch
_Add-ons are developed and maintained under **[Official Hoppscotch Organization](https://github.com/hoppscotch)**._
_Add-ons are developed and maintained under **[Hoppscotch Organization](https://github.com/hoppscotch)**._
☁️ **Auth + Sync:** Sign in and sync in real-time.
☁️ **Auth + Sync:** Sign in and sync your data in real-time.
**Sign in with**
- Google
- GitHub
- Google
- Email
**Sync**
**Synchronize your data**
- History
- Collections
- Environments
- Notes
- Settings
**Post-Request Tests β:** Write tests associated with a request that are executed after the request response.
<details>
<summary><i>Use-cases</i></summary>
---
- Check the status code as an integer
- Filter response headers
- Parse the response data
---
</details>
📝 **Notes** : Instantly jot down notes, tasks or whatever you feel like as they come to your mind.
_Notes are only available for signed-in users_
- Any JavaScript functions
🌱 **Environments** : Environment variables allow you to store and reuse values in your requests and scripts.
<details>
<summary><i>Features</i></summary>
---
- Unlimited environments and variables
- Initialize through pre-request script
- Export as / import from GitHub gist
---
</details>
<details>
<summary><i>Use-cases</i></summary>
@@ -412,20 +256,17 @@ _Notes are only available for signed-in users_
👨‍👩‍👧‍👦 **Teams β:** Helps you collaborate across your team to design, develop, and test APIs faster.
<details>
<summary><i>Features</i></summary>
---
- Unlimited team collections and shared requests
- Unlimited team members
- User roles
---
🚚 **Bulk Edit:** Edit key-value pairs in bulk.
</details>
- Entries are separated by newline
- Keys and values are separated by `:`
- Prepend `//` to any row you want to add but keep disabled
**To find out more, please check out [Hoppscotch Wiki](https://github.com/hoppscotch/hoppscotch/wiki).**
**For more features, please read our [documentation](https://docs.hoppscotch.io).**
## **Demo**
@@ -441,7 +282,7 @@ _Notes are only available for signed-in users_
## **Built with**
- [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Tailwind CSS](https://tailwindcss.com)
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Windi CSS](https://windicss.org)
- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- [TypeScript](https://www.typescriptlang.org)
- [Vue](https://vuejs.org)
@@ -449,22 +290,23 @@ _Notes are only available for signed-in users_
## **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/.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)._
#### Browser based development environment
### Browser based development environment
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/hoppscotch/hoppscotch)
- [GitHub codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace)
- [Gitpod](https://gitpod.io/#https://github.com/hoppscotch/hoppscotch)
#### Local development environment
### 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`.
2. Install dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
3. Start the development server with `pnpm run dev`.
4. Open development site by going to [`http://localhost:3000`](http://localhost:3000) in your browser.
#### Docker compose
### Docker compose
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
2. Run `docker-compose up`
@@ -475,44 +317,15 @@ _Sample keys only works with the [production build](https://hoppscotch.io)._
**Official container** &nbsp; [![hoppscotch/hoppscotch](https://img.shields.io/docker/pulls/hoppscotch/hoppscotch?style=social)](https://hub.docker.com/r/hoppscotch/hoppscotch)
```bash
#pull
docker pull hoppscotch/hoppscotch
#build
docker build -t hoppscotch/hoppscotch:latest .
#run
docker run -p 3000:3000 hoppscotch/hoppscotch:latest
docker run --rm --name hoppscotch -p 3000:3000 hoppscotch/hoppscotch:latest
```
**Legacy container** &nbsp; [![liyasthomas/postwoman](https://img.shields.io/docker/pulls/liyasthomas/postwoman?style=social)](https://hub.docker.com/r/liyasthomas/postwoman)
<details>
<summary><i>Legacy container</i></summary>
---
```bash
#pull
docker pull liyasthomas/postwoman
#build
docker build -t liyasthomas/postwoman:latest .
#run
docker run -p 3000:3000 liyasthomas/postwoman:latest
```
---
</details>
## **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 dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
3. Build the release files with `pnpm run generate`.
4. Find the built project in `packages/hoppscotch-app/dist`.
## **Contributing**
@@ -522,7 +335,7 @@ Please read [`CONTRIBUTING`](CONTRIBUTING.md) for details on our [`CODE OF CONDU
## **Continuous Integration**
We use [Travis CI](https://travis-ci.com) for continuous integration. Check out our [Travis CI Status](https://travis-ci.com/hoppscotch/hoppscotch).
We use [GitHub Actions](https://github.com/features/actions) for continuous integration. Check out our [build workflows](https://github.com/hoppscotch/hoppscotch/actions).
## **Changelog**
@@ -530,167 +343,15 @@ See the [`CHANGELOG`](CHANGELOG.md) file for details.
## **Authors**
### Lead Developers
This project exists thanks to all the people who contribute — [make a contribution](CONTRIBUTING.md).
- **[Liyas Thomas](https://github.com/liyasthomas)** - _Author_
- **[Andrew Bastin](https://github.com/andrewbastin)** - _Lead developer_
- **[Caneco](https://twitter.com/caneco)** - _Logo and banner designer_
### Collaborators <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://liyasthomas.web.app"><img src="https://avatars1.githubusercontent.com/u/10395817?v=4" width="100px;" alt=""/><br /><sub><b>Liyas Thomas</b></sub></a><br /><a href="https://github.com/liyasthomas/hoppscotch/commits?author=liyasthomas" title="Code">💻</a> <a href="#design-liyasthomas" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/AndrewBastin"><img src="https://avatars2.githubusercontent.com/u/9131943?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Bastin</b></sub></a><br /><a href="https://github.com/liyasthomas/hoppscotch/commits?author=AndrewBastin" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
See the list of [contributors](https://github.com/hoppscotch/hoppscotch/graphs/contributors) who participated in this project.
### Financial Contributors
Become a financial contributor and help us sustain our community [[Support](#support)].
#### GitHub Sponsors
<p align="center">
<a href="https://simplescraper.io/?utm_source=hs" target="_blank" rel="noopener">
<img
width="100"
src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/assets/images/Simplescraper.png"
alt="Simplescraper"
/>
</a>
</p>
<p align="center">
<a href="https://github.com/anmolm96" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/anmolm96.png?size=64"
alt="Anmol Maini"
/>
</a>
<a href="https://github.com/juzhiyuan" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/juzhiyuan.png?size=64"
alt="琚致远"
/>
</a>
<a href="https://github.com/eldadfux" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/eldadfux.png?size=64"
alt="Eldad A. Fux"
/>
</a>
<a href="https://github.com/aishwarydhare" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/aishwarydhare.png?size=64"
alt="Aishwary Dhare"
/>
</a>
<a href="https://github.com/rithish" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/rithish.png?size=64"
alt="Rithish"
/>
</a>
<a href="https://github.com/ankumar" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/ankumar.png?size=64"
alt="Anil Kumar"
/>
</a>
<a href="https://github.com/gpeal" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/gpeal.png?size=64"
alt="Gabriel Peal"
/>
</a>
<a href="https://github.com/donokuda" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/donokuda.png?size=64"
alt="Don Okuda"
/>
</a>
<a href="https://github.com/ebrescia" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/ebrescia.png?size=64"
alt="Erica Brescia"
/>
</a>
<a href="https://github.com/mlynch" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/mlynch.png?size=64"
alt="Max Lynch"
/>
</a>
<a href="https://github.com/brianshaler" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/brianshaler.png?size=64"
alt="Brian Shaler"
/>
</a>
<a href="https://github.com/mxstbr" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/mxstbr.png?size=64"
alt="Max Stoiber"
/>
</a>
<a href="https://github.com/jjcaine" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/jjcaine.png?size=64"
alt="John Caine"
/>
</a>
</p>
#### Open Collective
<p align="center">
<a href="https://pipedream.com/?ref=hoppscotch" target="_blank" rel="noopener">
<img
width="100"
src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/assets/images/pipedream.png"
alt="pipedream"
/>
</a>
<a href="https://paw.cloud/?utm_source=hoppscotch&utm_medium=github&utm_campaign=hoppscotch-sponsorship" target="_blank" rel="noopener">
<img
width="100"
src="https://raw.githubusercontent.com/hoppscotch/hoppscotch/main/assets/images/Paw-Logo-for-Hoppscotch.png"
alt="Paw"
/>
</a>
</p>
### Code Contributors
This project exists thanks to all the people who contribute [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors"><img src="https://opencollective.com/hoppscotch/contributors.svg?width=890&button=false" /></a>
<div align="center">
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors">
<img src="https://opencollective.com/hoppscotch/contributors.svg?width=840&button=false"
alt="Contributors"
width="100%" />
</a>
</div>
## **License**

View File

@@ -1,41 +1,23 @@
# Translations
Thanks for your interest in helping translating the software!
Thanks for showing your interest in helping us to translate the software.
## Starting a translation
## Creating a new translation
Before you start working on a translation, look through the [open pull requests](https://github.com/hoppscotch/hoppscotch/pulls) to see if anyone else is already working on one for your language.
Before you start working on a new language, please look through the [open pull requests](https://github.com/hoppscotch/hoppscotch/pulls) to see if anyone is already working on a translation. If you find one, please join the discussion and help us keep the existing translations up to date.
If there's not, then today is your day to lead this effort! Here's how to start:
if there is no existing translation, you can create a new one by following these steps:
1. [Fork this repository](https://github.com/hoppscotch/hoppscotch/fork)
2. Create a new branch for your translation work e.g. `es`.
3. Copy `lang/en-US.json` to your target language file e.g. `lang/es-ES.json` and translate all the strings.
4. Add your language entry to `nuxt.config.js`.
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.**
e.g.
```
i18n: {
locales: [
{
code: "en",
name: "English",
iso: "en-US",
file: "en-US.json",
},
{
code: 'es',
name: 'Español',
iso: 'es-ES',
file: 'es-ES.json'
}
]
}
```
5. Save & commit changes.
6. 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.)
_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._
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.

View File

@@ -1 +0,0 @@
export default {}

View File

@@ -1,259 +0,0 @@
/* fallback */
@font-face {
font-family: "Material Icons";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Material_Icons-400-fallback1.woff2") format("woff2");
}
/* devanagari */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Poppins-400-devanagari2.woff2") format("woff2");
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8,
U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Poppins-400-latin-ext3.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Poppins-400-latin4.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* devanagari */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("~assets/fonts/Poppins-500-devanagari5.woff2") format("woff2");
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8,
U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("~assets/fonts/Poppins-500-latin-ext6.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("~assets/fonts/Poppins-500-latin7.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* devanagari */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("~assets/fonts/Poppins-600-devanagari8.woff2") format("woff2");
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8,
U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("~assets/fonts/Poppins-600-latin-ext9.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("~assets/fonts/Poppins-600-latin10.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* devanagari */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("~assets/fonts/Poppins-700-devanagari11.woff2") format("woff2");
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8,
U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("~assets/fonts/Poppins-700-latin-ext12.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("~assets/fonts/Poppins-700-latin13.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* devanagari */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 800;
font-display: swap;
src: url("~assets/fonts/Poppins-800-devanagari14.woff2") format("woff2");
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8,
U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 800;
font-display: swap;
src: url("~assets/fonts/Poppins-800-latin-ext15.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 800;
font-display: swap;
src: url("~assets/fonts/Poppins-800-latin16.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-cyrillic-ext17.woff2") format("woff2");
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-cyrillic18.woff2") format("woff2");
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-greek19.woff2") format("woff2");
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-vietnamese20.woff2") format("woff2");
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-latin-ext21.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("~assets/fonts/Roboto_Mono-400-latin22.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD;
}
.material-icons {
font-family: "Material Icons"; /* stylelint-disable-line font-family-no-missing-generic-family-keyword */
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: "liga";
-webkit-font-smoothing: antialiased;
}

View File

@@ -1,6 +0,0 @@
/* purgecss start ignore */
@tailwind base;
@tailwind components;
/* purgecss end ignore */
@tailwind utilities;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.5 MiB

View File

@@ -1,8 +0,0 @@
<svg width="198" height="172" xmlns="http://www.w3.org/2000/svg">
<path fill="none" d="M-1-1h200v174H-1z"/>
<g>
<path fill="#f02e65" d="M197.289 88c0 35.899-29.101 65-65 65-16.675 0-31.883-6.279-43.389-16.601 18.433-8.298 31.266-26.827 31.266-48.353 0-21.553-12.865-40.101-31.335-48.384C100.346 29.304 115.581 23 132.289 23c35.899 0 65 29.101 65 65z"/>
<path fill="#f02e65" d="M106.306 36.116a65 65 0 10-78.307 103.769 65 65 0 1078.307-103.77v.001zm-7.229 9.578a53 53 0 01-63.85 84.612 53 53 0 0163.85-84.612z"/>
<path fill="#f02e65" d="M68.894 65.511c-.078.192-1.072 4.095-2.142 8.725-1.111 4.63-2.871 11.938-3.864 16.262-1.915 7.92-3.063 13.124-3.063 13.813 0 .19 1.187.345 2.64.345h2.641l1.185-5.282c.69-2.869 2.221-9.451 3.445-14.616 1.225-5.166 2.716-11.441 3.291-13.967.573-2.526 1.147-4.82 1.263-5.088.115-.344-.537-.458-2.526-.458-1.493 0-2.795.114-2.87.266zM48.345 82.079l-3.52 3.827 1.034 1.224c.572.688 2.143 2.411 3.482 3.827l2.449 2.601h6.964l-3.29-3.559c-1.8-1.911-3.292-3.749-3.292-3.978 0-.268 1.378-1.989 3.062-3.826 1.683-1.874 3.061-3.483 3.061-3.674 0-.153-1.454-.268-3.214-.268h-3.176l-3.56 3.826zm26.785-3.597c0 .116.651.842 1.453 1.646 2.987 2.984 5.091 5.511 4.976 6.007-.076.269-1.531 2.066-3.29 3.941l-3.175 3.482h3.557l3.559-.038 3.251-3.558c1.8-1.988 3.253-3.751 3.253-3.98 0-.19-1.53-1.989-3.444-4.016l-3.442-3.713h-3.331c-1.875 0-3.367.115-3.367.229z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -1,813 +0,0 @@
$responsiveWidth: 768px;
*,
*::before,
*::after {
backface-visibility: hidden;
}
:root {
@apply antialiased;
font-variant-ligatures: common-ligatures;
}
::selection {
@apply bg-acColor;
@apply text-actColor;
}
::-webkit-scrollbar {
@apply h-1;
@apply w-2;
&:hover {
@apply bg-bgDarkColor;
}
}
::-webkit-scrollbar-thumb {
@apply bg-fgLightColor;
&:hover {
@apply bg-fgColor;
}
}
::placeholder {
@apply text-fgLightColor;
@apply opacity-25;
}
html {
scroll-behavior: smooth;
}
body {
@apply bg-bgColor;
@apply text-fgColor;
@apply text-base;
@apply font-medium;
@apply select-none;
@apply transition;
@apply ease-in-out;
@apply duration-150;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
body.afterLoad {
@apply transition-colors;
@apply ease-in-out;
@apply duration-150;
}
body.sticky-footer footer {
@apply opacity-25;
}
.page-enter-active,
.page-leave-active,
.layout-enter-active,
.layout-leave-active {
@apply transition-opacity;
@apply duration-150;
}
.page-enter,
.page-leave-active,
.layout-enter,
.layout-leave-active {
@apply opacity-0;
}
a {
@apply inline-flex;
@apply text-current;
@apply no-underline;
@apply outline-none;
&.link {
@apply text-acColor;
}
}
header,
footer {
& > div {
@apply flex;
@apply py-2;
@apply px-2;
@apply w-full;
@apply items-center;
@apply justify-between;
}
}
.wrapper {
@apply min-h-screen;
@apply flex;
@apply flex-col;
@apply flex-nowrap;
}
.wrapper .page {
min-height: calc(100vh - 153px);
}
.header,
.content,
.columns,
.footer {
@apply flex;
@apply flex-1;
}
.nav-first,
.sticky-inner {
@apply flex;
@apply order-1;
@apply flex-col;
@apply sticky;
@apply top-0;
@apply items-start;
@apply items-stretch;
@apply h-full;
}
main {
@apply flex;
@apply flex-col;
@apply flex-1;
@apply order-2;
@apply relative;
@apply px-4;
}
h1,
h2,
h3,
h4 {
@apply flex;
@apply items-center;
@apply m-0;
@apply font-bold;
}
h3.title {
@apply m-2;
}
p {
@apply text-sm;
@apply transition;
@apply ease-in-out;
@apply duration-150;
}
hr {
@apply border-b;
@apply border-dashed;
@apply border-brdColor;
@apply my-4;
}
.tooltip {
@apply z-50;
@apply outline-none;
.tooltip-inner {
@apply rounded-lg;
@apply px-4;
@apply py-2;
@apply text-xs;
@apply font-medium;
@apply shadow-lg;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply bg-ttColor;
@apply text-fgColor;
}
.tooltip-arrow {
@apply h-0;
@apply w-0;
@apply border-solid;
@apply absolute;
@apply m-2;
@apply border-ttColor;
@apply z-30;
@apply transition;
@apply ease-in-out;
@apply duration-150;
}
&[x-placement^="top"] {
@apply mb-0;
.tooltip-arrow {
@apply mt-0;
@apply mb-0;
border-width: 5px 5px 0 5px;
border-left-color: transparent !important;
border-right-color: transparent !important;
border-bottom-color: transparent !important;
bottom: -5px;
left: calc(50% - 5px);
}
}
&[x-placement^="bottom"] {
@apply mt-0;
.tooltip-arrow {
@apply mt-0;
@apply mb-0;
border-width: 0 5px 5px 5px;
border-left-color: transparent !important;
border-right-color: transparent !important;
border-top-color: transparent !important;
top: -5px;
left: calc(50% - 5px);
}
}
&[x-placement^="right"] {
@apply ml-0;
.tooltip-arrow {
@apply ml-0;
@apply mr-0;
border-width: 5px 5px 5px 0;
border-left-color: transparent !important;
border-top-color: transparent !important;
border-bottom-color: transparent !important;
left: -5px;
top: calc(50% - 5px);
}
}
&[x-placement^="left"] {
@apply mr-0;
.tooltip-arrow {
@apply ml-0;
@apply mr-0;
border-width: 5px 0 5px 5px;
border-top-color: transparent !important;
border-right-color: transparent !important;
border-bottom-color: transparent !important;
right: -5px;
top: calc(50% - 5px);
}
}
&.popover {
.wrapper {
min-height: auto;
}
.popover-inner {
@apply bg-ttColor;
@apply text-fgColor;
@apply text-base;
@apply p-2;
@apply rounded-lg;
@apply overflow-auto;
@apply shadow-lg;
max-height: 256px;
min-width: 128px;
button {
@apply flex-1;
@apply m-0;
@apply p-2;
@apply justify-start;
@apply text-left;
}
div {
@apply flex;
@apply items-stretch;
@apply flex-col;
}
}
.popover-arrow {
@apply border-ttColor;
}
}
&[aria-hidden="true"] {
@apply invisible;
@apply opacity-0;
@apply transition-opacity;
@apply ease-in-out;
@apply duration-150;
}
&[aria-hidden="false"] {
@apply visible;
@apply opacity-100;
@apply transition-opacity;
@apply ease-in-out;
@apply duration-150;
}
}
.info:not(.toasted) {
@apply m-4;
@apply text-fgLightColor;
.material-icons {
@apply align-middle;
@apply mr-2;
}
}
button {
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply p-4;
@apply bg-acColor;
@apply text-actColor;
@apply font-bold;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply fill-current;
@apply cursor-pointer;
@apply outline-none;
@apply border-none;
span {
@apply inline-flex;
@apply ml-4;
@apply text-left;
}
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
@apply text-actColor;
@apply fill-current;
@apply outline-none;
box-shadow: inset 0 0 0 2px var(--fg-color);
}
&.icon {
@apply bg-transparent;
@apply text-fgLightColor;
@apply fill-current;
@apply outline-none;
@apply border-none;
@apply rounded-lg;
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
@apply text-fgColor;
@apply fill-current;
@apply shadow-none;
}
}
&.primary {
@apply text-acColor;
@apply px-6;
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
@apply bg-acColor;
@apply text-actColor;
}
}
}
@keyframes beat {
30% {
@apply transform;
@apply scale-90;
}
50% {
@apply transform;
@apply scale-110;
}
100% {
@apply transform;
@apply scale-100;
}
}
.material-icons {
&:active {
animation: beat 0.5s forwards 1;
}
}
fieldset:target,
section:target {
animation: highlight 2s ease;
}
@keyframes highlight {
50% {
box-shadow: 0 0 0 2px var(--ac-color);
}
}
input {
@apply truncate;
}
input[type="file"],
input[type="radio"],
#installPWA {
@apply hidden;
}
.show-on-large-screen {
@apply flex;
@apply flex-1;
}
.method,
.url-field,
kbd,
select,
input,
textarea,
pre,
code {
@apply flex;
@apply p-4;
@apply bg-bgDarkColor;
@apply text-fgColor;
@apply font-mono;
@apply font-normal;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply select-text;
@apply resize-y;
@apply outline-none;
@apply w-full;
&:not([readonly]):not(.ace_editor):hover,
&:not([readonly]):not(.ace_editor):active,
&:not([readonly]):not(.ace_editor):focus {
box-shadow: inset 0 0 0 2px var(--fg-light-color);
}
}
.method {
@apply cursor-pointer;
@apply uppercase;
@apply rounded-none;
min-width: 128px;
&:hover,
&:active,
&:focus {
box-shadow: inset 0 0 0 2px var(--fg-light-color);
}
}
pre {
@apply grid;
}
pre.ace_editor {
@apply font-mono;
@apply font-normal;
@apply z-0;
@apply resize-none;
}
kbd,
code,
pre {
@apply w-auto;
}
.select-wrapper {
@apply relative;
@apply w-full;
pre,
input {
@apply cursor-pointer;
}
.trigger {
@apply w-full;
}
&::after {
@apply inline-block;
@apply absolute;
@apply pointer-events-none;
@apply font-icon;
@apply text-fgLightColor;
content: "\e313";
top: 16px;
right: 16px;
}
}
select {
@apply cursor-pointer;
@apply appearance-none;
// height: 40px;
&::-ms-expand {
@apply hidden;
}
}
option {
@apply bg-bgColor;
}
input[type="checkbox"] {
@apply hidden;
&,
& + label {
@apply align-middle;
@apply cursor-pointer;
&::before {
@apply border;
@apply border-fgColor;
@apply rounded-lg;
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply text-transparent;
@apply transition;
@apply ease-in-out;
@apply duration-150;
content: "\2714";
height: 16px;
width: 16px;
margin: 8px 8px 8px 0;
}
}
&:checked + label::before {
@apply bg-acColor;
@apply border-acColor;
@apply text-actColor;
}
}
.error:not(input),
.disabled:not(input),
[disabled] {
@apply bg-errColor;
@apply text-fgLightColor;
@apply fill-current;
@apply cursor-not-allowed;
&.icon {
@apply text-errColor;
@apply fill-current;
}
}
label {
@apply p-4;
@apply text-fgLightColor;
@apply text-sm;
@apply transition;
@apply ease-in-out;
@apply duration-150;
}
ul,
ol {
@apply flex;
}
ul li,
ol li {
@apply inline-flex;
@apply flex-col;
@apply flex-nowrap;
@apply flex-1;
@apply justify-center;
&.shrink {
@apply flex-grow-0;
}
}
.row-wrapper {
@apply flex;
@apply items-center;
@apply justify-between;
@apply flex-1;
@apply flex-row;
span,
div {
@apply inline-flex;
@apply flex-nowrap;
@apply items-center;
@apply justify-center;
}
}
.info-response {
@apply text-yellow-400;
}
.success-response {
@apply text-green-400;
}
.redir-response {
@apply text-pink-400;
}
.cl-error-response {
@apply text-red-400;
}
.sv-error-response {
@apply text-red-600;
}
.missing-data-response {
@apply text-fgLightColor;
}
#response-details-wrapper {
@apply relative;
textarea {
@apply m-0;
@apply w-full;
line-height: 1;
}
.covers-response {
@apply absolute;
@apply inset-0;
@apply bg-white;
@apply h-full;
@apply w-full;
}
}
#send {
@apply whitespace-nowrap;
@apply outline-none;
@apply border-none;
&.show {
@apply flex;
@apply fixed;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply shadow-lg;
@apply rounded-lg;
bottom: 86px;
left: 50%;
z-index: 10001;
transform: translateX(-50%);
}
}
section {
@apply flex;
@apply rounded-lg;
@apply w-full;
}
.toasted-container .toasted {
justify-content: space-between !important;
}
.toasted.info {
background-color: var(--ac-color) !important;
color: var(--act-color) !important;
font-weight: 700 !important;
}
.toasted.bubble .action {
color: inherit !important;
}
.toasted .action {
margin-left: auto !important;
}
.page-columns {
@apply flex;
@apply flex-1;
@apply flex-col;
}
.inner-left {
@apply flex;
@apply order-1;
}
.inner-right {
@apply flex;
@apply order-2;
@apply ml-4;
width: 33%;
}
@media (max-width: $responsiveWidth) {
.content,
.columns {
@apply flex-col;
}
main {
padding: 0 8px 68px;
margin-bottom: env(safe-area-inset-bottom);
}
ul,
ol {
@apply flex-col;
@apply flex-nowrap;
}
ul li,
ol li {
@apply flex;
}
.hide-on-small-screen {
@apply hidden;
}
.sticky-inner {
@apply relative;
@apply w-full;
}
.inner-left {
order: 0;
}
.inner-right {
@apply ml-0;
}
.toasted-container {
margin-bottom: 68px;
}
}
.toasted-ad {
@apply bg-gray-50;
@apply text-gray-900;
@apply font-bold;
@apply text-sm;
@apply rounded-lg;
@apply shadow-lg;
padding: 16px !important;
.action {
@apply bg-gray-50;
@apply text-gray-900;
@apply rounded-lg;
@apply font-bold;
text-transform: none !important;
padding: 12px 16px !important;
font-size: 16px !important;
margin: 0 !important;
margin-left: 8px !important;
}
}
.virtual-list {
@apply overflow-auto;
}

View File

@@ -1,165 +0,0 @@
@mixin baseTheme {
--font-sans: "Poppins", "sans-serif";
--font-mono: "Roboto Mono", "monospace";
--font-icon: "Material Icons";
}
@mixin darkTheme {
// Background color
--bg-color: rgba(32, 33, 36, 1);
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.04);
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.2);
// Text color
--fg-color: rgba(255, 255, 255, 0.9);
// Light Text color
--fg-light-color: rgba(255, 255, 255, 0.5);
// Border color
--brd-color: rgba(255, 255, 255, 0.05);
// Error color
--err-color: rgba(255, 255, 255, 0.05);
// Tooltip color
--tt-color: rgba(48, 48, 48, 1);
// Editor theme
--editor-theme: "twilight";
// Active text color
--act-color: rgba(32, 33, 36, 1);
}
@mixin lightTheme {
// Background color
--bg-color: rgba(255, 255, 255, 1);
// Light Background color
--bg-light-color: rgba(0, 0, 0, 0.05);
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.02);
// Text color
--fg-color: rgba(0, 0, 0, 0.9);
// Light Text color
--fg-light-color: rgba(0, 0, 0, 0.6);
// Border color
--brd-color: rgba(0, 0, 0, 0.1);
// Error color
--err-color: rgba(0, 0, 0, 0.1);
// Tooltip color
--tt-color: rgba(255, 255, 255, 1);
// Editor theme
--editor-theme: "iplastic";
// Active text color
--act-color: rgba(255, 255, 255, 1);
}
@mixin blackTheme {
// Background color
--bg-color: rgba(0, 0, 0, 1);
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.02);
// Dark Background color
--bg-dark-color: rgba(255, 255, 255, 0.04);
// Text color
--fg-color: rgba(255, 255, 255, 0.9);
// Light Text color
--fg-light-color: rgba(255, 255, 255, 0.5);
// Border color
--brd-color: rgba(255, 255, 255, 0.05);
// Error color
--err-color: rgba(255, 255, 255, 0.05);
// Tooltip color
--tt-color: rgba(32, 32, 32, 1);
// Editor theme
--editor-theme: "vibrant_ink";
// Active text color
--act-color: rgba(0, 0, 0, 1);
}
@mixin blueTheme {
// Acent color
--ac-color: theme("colors.blue.400");
}
@mixin greenTheme {
// Acent color
--ac-color: theme("colors.green.400");
}
@mixin tealTheme {
// Acent color
--ac-color: theme("colors.teal.400");
}
@mixin indigoTheme {
// Acent color
--ac-color: theme("colors.indigo.400");
}
@mixin purpleTheme {
// Acent color
--ac-color: theme("colors.purple.400");
}
@mixin orangeTheme {
// Acent color
--ac-color: theme("colors.orange.400");
}
@mixin pinkTheme {
// Acent color
--ac-color: theme("colors.pink.400");
}
@mixin redTheme {
// Acent color
--ac-color: theme("colors.red.400");
}
@mixin yellowTheme {
// Acent color
--ac-color: theme("colors.yellow.400");
}
:root {
@include baseTheme;
@include darkTheme;
@include greenTheme;
}
:root.light {
@include lightTheme;
}
:root.dark {
@include darkTheme;
}
:root.black {
@include blackTheme;
}
:root[data-accent="blue"] {
@include blueTheme;
}
:root[data-accent="green"] {
@include greenTheme;
}
:root[data-accent="teal"] {
@include tealTheme;
}
:root[data-accent="indigo"] {
@include indigoTheme;
}
:root[data-accent="purple"] {
@include purpleTheme;
}
:root[data-accent="orange"] {
@include orangeTheme;
}
:root[data-accent="pink"] {
@include pinkTheme;
}
:root[data-accent="red"] {
@include redTheme;
}
:root[data-accent="yellow"] {
@include yellowTheme;
}

3
commitlint.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
}

View File

@@ -1,175 +0,0 @@
<template>
<div>
<p class="info">
{{ $t("donate_info1") }}
</p>
<p class="info">
{{ $t("donate_info2") }}
</p>
<div class="px-2 row-wrapper">
<span>
<a
v-tooltip.right="$t('recurring')"
href="https://github.com/sponsors/hoppscotch"
target="_blank"
rel="noopener"
>
<button class="icon">
<i class="material-icons">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
class="material-icons"
>
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
/>
</svg>
</i>
<span>GitHub Sponsors</span>
</button>
</a>
</span>
</div>
<div class="px-2 row-wrapper">
<span>
<a
v-tooltip.right="$t('one_time_recurring')"
href="https://opencollective.com/hoppscotch"
target="_blank"
rel="noopener"
>
<button class="icon">
<i class="material-icons">donut_large</i>
<span>{{ $t("open_collective") }}</span>
</button>
</a>
</span>
</div>
<div class="px-2 row-wrapper">
<span>
<a
v-tooltip.right="$t('recurring')"
href="https://www.patreon.com/liyasthomas"
target="_blank"
rel="noopener"
>
<button class="icon">
<i class="material-icons">local_parking</i>
<span>{{ $t("patreon") }}</span>
</button>
</a>
</span>
</div>
<div class="px-2 row-wrapper">
<span>
<a
v-tooltip.right="$t('one_time')"
href="https://www.paypal.me/liyascthomas"
target="_blank"
rel="noopener"
>
<button class="icon">
<i class="material-icons">payment</i>
<span>{{ $t("paypal") }}</span>
</button>
</a>
</span>
</div>
<hr />
<div class="p-2">
<h3 class="title">Financial Contributors</h3>
<div class="contributors">
<a
href="https://oss.capital/?ref=hoppscotch"
target="_blank"
rel="noopener"
>
<img
style="height: 100%; width: 300px"
src="~assets/images/ossc-banner.svg"
alt="OSS Capital"
/>
</a>
<a
href="https://appwrite.io/?utm_source=hoppscotch&utm_medium=banner&utm_campaign=hello"
target="_blank"
rel="noopener"
>
<img
style="height: 100%; width: 300px; background: #fff"
src="~assets/images/appwrite-banner.svg"
alt="Appwrite"
/>
</a>
<a
href="https://pipedream.com/?ref=hoppscotch"
target="_blank"
rel="noopener"
>
<img
style="max-width: 100px"
src="~assets/images/pipedream.png"
alt="pipedream"
/>
</a>
<a
href="https://paw.cloud/?utm_source=hoppscotch&utm_medium=website&utm_campaign=hoppscotch-sponsorship"
target="_blank"
rel="noopener"
>
<img
style="max-width: 100px"
src="~assets/images/Paw-Logo-for-Hoppscotch.png"
alt="Paw"
/>
</a>
<a
href="https://simplescraper.io/?utm_source=hs"
target="_blank"
rel="noopener"
>
<img
style="max-height: 50px"
src="~assets/images/Simplescraper_dark.png"
alt="Simplescraper"
/>
</a>
<a href="https://tyk.io?ref=hoppscotch" target="_blank" rel="noopener">
<img
style="max-width: 320px"
src="~assets/images/Tyk-side-project-logo-tagline-blk.png"
alt="Tyk Banner"
/>
</a>
</div>
</div>
<hr />
<p class="info">
This project exists thanks to all the
<a
target="_blank"
rel="noopener"
href="https://github.com/hoppscotch/hoppscotch/graphs/contributors"
class="link"
>
people who contribute
</a>
.
</p>
</div>
</template>
<style scoped lang="scss">
.contributors {
@apply flex;
@apply items-center;
@apply flex-wrap;
@apply overflow-auto;
@apply m-2;
@apply space-x-2;
@apply space-y-2;
}
</style>

View File

@@ -1,106 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("extensions") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<p class="info">
{{ $t("extensions_info1") }}
</p>
<div class="px-2">
<a
href="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
target="_blank"
rel="noopener"
>
<button class="icon">
<svg
class="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
>
<path
d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm8.003 8.657c-1.276-3.321-4.46-4.605-5.534-4.537 3.529 1.376 4.373 6.059 4.06 7.441-.307-1.621-1.286-3.017-1.872-3.385 3.417 8.005-4.835 10.465-7.353 7.687.649.168 1.931.085 2.891-.557.898-.602.983-.638 1.56-.683.686-.053-.041-1.406-1.539-1.177-.616.094-1.632.819-2.88.341-1.508-.576-1.46-2.634.096-2.015.337-.437.088-1.263.088-1.263.452-.414 1.022-.706 1.37-.911.228-.135.829-.507.795-1.23-.123-.096-.32-.219-.766-.193-1.736.11-1.852-.518-1.967-.808.078-.668.524-1.534 1.361-1.931-1.257-.193-2.28.397-2.789 1.154-.809-.174-1.305-.183-2.118-.031-.316-.24-.666-.67-.878-1.181C6.36 3.312 9.027 2 12 2c5.912 0 8.263 4.283 8.003 6.657z"
/>
</svg>
<span>Firefox</span>
<span
v-if="hasFirefoxExtInstalled"
v-tooltip="$t('installed')"
class="icon"
>
<i class="material-icons">done</i>
</span>
</button>
</a>
</div>
<div class="px-2">
<a
href="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
target="_blank"
rel="noopener"
>
<button class="icon">
<svg
class="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
>
<path
d="M2.897 4.181A11.87 11.87 0 0111.969 0c4.288 0 8.535 2.273 10.717 6.554h-9.293c-1.674.001-2.755-.037-3.926.579-1.376.724-2.415 2.067-2.777 3.644L2.897 4.181zM8.007 12c0 2.2 1.789 3.99 3.988 3.99s3.988-1.79 3.988-3.99-1.789-3.991-3.988-3.991S8.007 9.8 8.007 12zm5.536 5.223c-2.238.666-4.858-.073-6.293-2.549-1.095-1.891-3.989-6.933-5.305-9.225A11.856 11.856 0 000 11.956c0 5.448 3.726 10.65 9.673 11.818l3.87-6.551zm2.158-9.214a5.463 5.463 0 011.007 6.719 1815.43 1815.43 0 01-5.46 9.248C18.437 24.419 24 18.616 24 12.004c0-1.313-.22-2.66-.69-3.995h-7.609z"
/>
</svg>
<span>Chrome</span>
<span
v-if="hasChromeExtInstalled"
v-tooltip="$t('installed')"
class="icon"
>
<i class="material-icons">done</i>
</span>
</button>
</a>
</div>
</div>
<div slot="footer"></div>
</SmartModal>
</template>
<script>
import {
hasChromeExtensionInstalled,
hasFirefoxExtensionInstalled,
} from "~/helpers/strategies/ExtensionStrategy"
export default {
props: {
show: Boolean,
},
data() {
return {
hasChromeExtInstalled: hasChromeExtensionInstalled(),
hasFirefoxExtInstalled: hasFirefoxExtensionInstalled(),
}
},
watch: {
show() {
this.hasChromeExtInstalled = hasChromeExtensionInstalled()
this.hasFirefoxExtInstalled = hasFirefoxExtensionInstalled()
},
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,104 +0,0 @@
<template>
<footer class="footer">
<div class="row-wrapper">
<span
class="flex flex-col font-mono md:flex-row"
style="align-items: start"
>
<a
class="footer-link"
href="https://www.netlify.com"
target="_blank"
rel="noopener"
>
Powered by Netlify
</a>
<span>
<a
class="footer-link"
href="https://oss.capital/?ref=hoppscotch"
target="_blank"
rel="noopener"
>
OSS Capital
</a>
<a
class="footer-link"
href="https://paw.cloud/?utm_source=hoppscotch&utm_medium=website&utm_campaign=hoppscotch-sponsorship"
target="_blank"
rel="noopener"
>
Paw
</a>
<a
class="footer-link"
href="https://simplescraper.io/?utm_source=hs"
target="_blank"
rel="noopener"
>
Simplescraper
</a>
</span>
<iframe
src="https://ghbtns.com/github-btn.html?user=hoppscotch&type=sponsor"
frameborder="0"
scrolling="0"
width="150"
height="20"
title="GitHub"
class="footer-link"
loading="lazy"
></iframe>
</span>
<span
class="flex flex-col font-mono md:flex-row"
style="align-items: start"
>
<a href="mailto:support@hoppscotch.io" target="_blank" rel="noopener">
<button v-tooltip="$t('contact_us')" class="icon">
<i class="material-icons">email</i>
</button>
</a>
<v-popover>
<button v-tooltip="$t('choose_language')" class="icon">
<i class="material-icons">translate</i>
</button>
<template slot="popover">
<div v-for="locale in availableLocales" :key="locale.code">
<nuxt-link :to="switchLocalePath(locale.code)">
<button v-close-popover class="icon">
{{ locale.name }}
</button>
</nuxt-link>
</div>
</template>
</v-popover>
</span>
</div>
</footer>
</template>
<script>
export default {
computed: {
availableLocales() {
return this.$i18n.locales.filter(({ code }) => code !== this.$i18n.locale)
},
},
}
</script>
<style scoped lang="scss">
.footer-link {
@apply inline-flex;
@apply flex-shrink-0;
@apply my-2;
@apply mx-4;
@apply text-fgLightColor;
@apply text-sm;
&:hover {
@apply text-fgColor;
}
}
</style>

View File

@@ -1,342 +0,0 @@
<template>
<header class="header">
<div class="row-wrapper">
<span class="slide-in">
<nuxt-link :to="localePath('index')">
<h1 class="hide-on-small-screen logo">Hoppscotch</h1>
<h1 class="show-on-small-screen logo">Hs</h1>
</nuxt-link>
<iframe
src="https://ghbtns.com/github-btn.html?user=hoppscotch&repo=hoppscotch&type=star&count=true"
frameborder="0"
scrolling="0"
width="150"
height="20"
title="GitHub"
class="ml-8 hide-on-small-screen"
loading="lazy"
></iframe>
</span>
<span>
<a
href="https://appwrite.io/?utm_source=hoppscotch&utm_medium=banner&utm_campaign=hello"
target="_blank"
rel="noopener"
class="
inline-flex
items-center
px-4
py-2
mx-4
font-mono
text-sm
rounded-md
bg-bgDarkColor
hide-on-small-screen
"
>
Appwrite - Open-Source Backend as a Service
<img
class="w-8 ml-2"
src="~assets/images/appwrite-icon.svg"
alt="Appwrite"
/>
</a>
<button
id="installPWA"
v-tooltip="$t('install_pwa')"
class="icon"
@click.prevent="showInstallPrompt()"
>
<i class="material-icons">offline_bolt</i>
</button>
<a
href="https://github.com/hoppscotch/hoppscotch"
target="_blank"
aria-label="GitHub"
rel="noopener"
>
<button v-tooltip="'GitHub'" class="icon" aria-label="GitHub">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
class="material-icons"
>
<path
d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
/>
</svg>
</button>
</a>
<v-popover v-if="fb.currentUser === null">
<button v-tooltip="$t('login_with')" class="icon">
<i class="material-icons">login</i>
</button>
<template slot="popover">
<FirebaseLogin />
</template>
</v-popover>
<v-popover v-else>
<button
v-tooltip="
(fb.currentUser.displayName ||
'<label><i>Name not found</i></label>') +
'<br>' +
(fb.currentUser.email || '<label><i>Email not found</i></label>')
"
class="icon"
aria-label="Account"
>
<img
v-if="fb.currentUser.photoURL"
:src="fb.currentUser.photoURL"
class="w-6 h-6 rounded-full material-icons"
alt="Profile image"
/>
<i v-else class="material-icons">account_circle</i>
</button>
<template slot="popover">
<div>
<nuxt-link v-close-popover :to="localePath('settings')">
<button class="icon">
<i class="material-icons">settings</i>
<span>
{{ $t("settings") }}
</span>
</button>
</nuxt-link>
</div>
<div>
<FirebaseLogout />
</div>
</template>
</v-popover>
<v-popover>
<button v-tooltip="$t('more')" class="icon">
<i class="material-icons">drag_indicator</i>
</button>
<template slot="popover">
<button v-close-popover class="icon" @click="showExtensions = true">
<i class="material-icons">extension</i>
<span>{{ $t("extensions") }}</span>
</button>
<button v-close-popover class="icon" @click="showShortcuts = true">
<i class="material-icons">keyboard</i>
<span>{{ $t("shortcuts") }}</span>
</button>
<button v-close-popover class="icon" @click="showSupport = true">
<i class="material-icons">favorite</i>
<span>{{ $t("support_us") }}</span>
</button>
<button
v-close-popover
class="icon"
onClick="window.open('https://twitter.com/share?text=👽 Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.&url=https://hoppscotch.io&hashtags=hoppscotch&via=hoppscotch_io');"
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
<path
d="M24 4.557a9.83 9.83 0 01-2.828.775 4.932 4.932 0 002.165-2.724 9.864 9.864 0 01-3.127 1.195 4.916 4.916 0 00-3.594-1.555c-3.179 0-5.515 2.966-4.797 6.045A13.978 13.978 0 011.671 3.149a4.93 4.93 0 001.523 6.574 4.903 4.903 0 01-2.229-.616c-.054 2.281 1.581 4.415 3.949 4.89a4.935 4.935 0 01-2.224.084 4.928 4.928 0 004.6 3.419A9.9 9.9 0 010 19.54a13.94 13.94 0 007.548 2.212c9.142 0 14.307-7.721 13.995-14.646A10.025 10.025 0 0024 4.557z"
/>
</svg>
<span>Tweet</span>
</button>
<button
v-if="navigatorShare"
v-close-popover
v-tooltip="$t('more')"
class="icon"
@click="nativeShare"
>
<i class="material-icons">share</i>
<span>Share</span>
</button>
</template>
</v-popover>
</span>
</div>
<AppExtensions
:show="showExtensions"
@hide-modal="showExtensions = false"
/>
<AppShortcuts :show="showShortcuts" @hide-modal="showShortcuts = false" />
<AppSupport :show="showSupport" @hide-modal="showSupport = false" />
</header>
</template>
<script>
import intializePwa from "~/helpers/pwa"
import { fb } from "~/helpers/fb"
// import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
export default {
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,
showExtensions: false,
showShortcuts: false,
showSupport: false,
navigatorShare: navigator.share,
fb,
}
},
async mounted() {
this._keyListener = function (e) {
if (e.key === "Escape") {
e.preventDefault()
this.showExtensions = this.showShortcuts = this.showSupport = false
}
}
document.addEventListener("keydown", this._keyListener.bind(this))
// Initializes the PWA code - checks if the app is installed,
// etc.
this.showInstallPrompt = await intializePwa()
const cookiesAllowed = localStorage.getItem("cookiesAllowed") === "yes"
if (!cookiesAllowed) {
this.$toast.show(this.$t("we_use_cookies"), {
icon: "info",
duration: 5000,
theme: "toasted-primary",
action: [
{
text: this.$t("dismiss"),
onClick: (_, toastObject) => {
localStorage.setItem("cookiesAllowed", "yes")
toastObject.goAway(0)
},
},
],
})
}
// let showAd = localStorage.getItem("showAd") === "no"
// if (!showAd) {
// setTimeout(() => {
// this.$toast.clear()
// this.$toast.show(
// "<span><a href='https://github.com/sponsors/hoppscotch' target='_blank' rel='noopener'>Sponsor us to support Hoppscotch open source project 💖</a><br><sub>Whoosh this away to dismiss.</sub></span>",
// {
// icon: "",
// duration: 0,
// theme: "toasted-ad",
// action: [
// {
// text: "Sponsor",
// icon: "chevron_right",
// onClick: (_, toastObject) => {
// localStorage.setItem("showAd", "no")
// toastObject.goAway(0)
// window.open("https://github.com/sponsors/hoppscotch")
// },
// },
// ],
// onComplete() {
// localStorage.setItem("showAd", "no")
// },
// }
// )
// }, 8000)
// }
// let showExtensionsToast = localStorage.getItem("showExtensionsToast") === "yes"
// if (!showExtensionsToast) {
// setTimeout(() => {
// if (!hasExtensionInstalled()) {
// this.$toast.show(this.$t("extensions_info2"), {
// icon: "extension",
// duration: 5000,
// theme: "toasted-primary",
// action: [
// {
// text: this.$t("yes"),
// onClick: (_, toastObject) => {
// this.showExtensions = true
// localStorage.setItem("showExtensionsToast", "yes")
// toastObject.goAway(0)
// },
// },
// {
// text: this.$t("no"),
// onClick: (_, toastObject) => {
// this.$store.commit("setMiscState", {
// value: false,
// attribute: "showExtensionsToast",
// })
// localStorage.setItem("showExtensionsToast", "no")
// toastObject.goAway(0)
// },
// },
// ],
// })
// }
// }, 5000)
// }
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener)
},
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
}
},
},
}
</script>
<style scoped lang="scss">
$responsiveWidth: 768px;
.logo {
@apply text-xl;
@apply transition-colors;
@apply ease-in-out;
@apply duration-150;
&:hover {
@apply text-acColor;
}
}
@keyframes slideIn {
0% {
@apply opacity-0;
@apply -left-4;
}
100% {
@apply opacity-100;
@apply left-0;
}
}
.slide-in {
@apply relative;
animation: slideIn 0.2s forwards ease-in-out;
}
.show-on-small-screen {
@apply hidden;
}
@media (max-width: $responsiveWidth) {
.show-on-small-screen {
@apply inline-flex;
}
}
</style>

View File

@@ -1,22 +0,0 @@
<template>
<svg viewBox="0 0 612.001 612.001">
<path
:fill="color"
data-old_color="#202124"
class="active-path"
data-original="#202124"
d="M64.601 236.822C64.601 394.256 192.786 612 306.001 612 412.582 612 547.4 394.256 547.4 236.822S439.322 0 306 0 64.601 79.388 64.601 236.822zm304.12 116.415c29.475-29.475 70.598-40.195 108.552-32.173 8.021 37.954-2.698 79.077-32.173 108.552-29.475 29.476-70.598 40.196-108.552 32.174-8.022-37.955 2.698-79.078 32.173-108.552zm-233.994-32.174c37.954-8.02 79.077 2.698 108.552 32.173 29.475 29.475 40.195 70.598 32.173 108.552-37.954 8.021-79.077-2.698-108.552-32.173-29.475-29.476-40.194-70.598-32.173-108.552z"
/>
</svg>
</template>
<script>
export default {
props: {
color: {
type: String,
default: "",
},
},
}
</script>

View File

@@ -1,74 +0,0 @@
<template>
<fieldset :id="label.toLowerCase()">
<legend v-if="!noLegend" @click.prevent="collapse">
<span>{{ label }}</span>
<i class="ml-2 align-middle material-icons">
{{ isCollapsed(label) ? "expand_more" : "expand_less" }}
</i>
</legend>
<div
class="collapsible"
:class="{ hidden: isCollapsed(label.toLowerCase()) }"
>
<slot></slot>
</div>
</fieldset>
</template>
<script lang="ts">
import Vue from "vue"
export default Vue.extend({
props: {
label: {
type: String,
default: "Section",
},
noLegend: {
type: Boolean,
default: false,
},
},
computed: {
sectionString(): string {
return `${this.$route.path.replace(/\/+$/, "")}/${this.label}`
},
},
methods: {
collapse() {
// Save collapsed section into the collapsedSections array
this.$store.commit("setCollapsedSection", this.sectionString)
},
isCollapsed(_label: string) {
return (
this.$store.state.theme.collapsedSections.includes(
this.sectionString
) || false
)
},
},
})
</script>
<style scoped lang="scss">
fieldset {
@apply my-4;
@apply rounded-lg;
@apply bg-bgDarkColor;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply w-full;
legend {
@apply px-4;
@apply text-fgColor;
@apply font-bold;
@apply cursor-pointer;
@apply transition;
@apply ease-in-out;
@apply duration-150;
}
}
</style>

View File

@@ -1,102 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("shortcuts") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<div class="p-2">
<div>
<kbd>{{ getSpecialKey() }}</kbd>
+
<kbd>G</kbd>
<label>{{ $t("send_request") }}</label>
</div>
<div>
<kbd>{{ getSpecialKey() }}</kbd
>+<kbd>S</kbd>
<label>{{ $t("save_to_collections") }}</label>
</div>
<div>
<kbd>{{ getSpecialKey() }}</kbd
>+<kbd>K</kbd>
<label>{{ $t("copy_request_link") }}</label>
</div>
<div>
<kbd>{{ getSpecialKey() }}</kbd
>+<kbd>I</kbd>
<label>{{ $t("reset_request") }}</label>
</div>
</div>
<hr />
<div class="p-2">
<div>
<kbd>Alt</kbd>+<kbd></kbd>
<label>{{ $t("select_next_method") }}</label>
</div>
<div>
<kbd>Alt</kbd>+<kbd></kbd>
<label>{{ $t("select_previous_method") }}</label>
</div>
</div>
<hr />
<div class="p-2">
<div>
<kbd>Alt</kbd>+<kbd>G</kbd>
<label>{{ $t("select_get_method") }}</label>
</div>
<div>
<kbd>Alt</kbd>+<kbd>H</kbd>
<label>{{ $t("select_head_method") }}</label>
</div>
<div>
<kbd>Alt</kbd>+<kbd>P</kbd>
<label>{{ $t("select_post_method") }}</label>
</div>
<div>
<kbd>Alt</kbd>+<kbd>U</kbd>
<label>{{ $t("select_put_method") }}</label>
</div>
<div>
<kbd>Alt</kbd>+<kbd>X</kbd>
<label>{{ $t("select_delete_method") }}</label>
</div>
</div>
</div>
<div slot="footer"></div>
</SmartModal>
</template>
<script>
import { getPlatformSpecialKey } from "~/helpers/platformutils"
export default {
props: {
show: Boolean,
},
methods: {
getSpecialKey: getPlatformSpecialKey,
hideModal() {
this.$emit("hide-modal")
},
},
}
</script>
<style scoped lang="scss">
kbd {
@apply inline-flex;
@apply resize-none;
@apply m-2;
@apply rounded-lg;
@apply py-2;
@apply px-4;
@apply text-sm;
}
</style>

View File

@@ -1,307 +0,0 @@
<template>
<aside class="nav-first">
<nav class="primary-nav">
<!--
We're using manual checks for linkActive because the query string
seems to mess up the nuxt-link active class.
-->
<nuxt-link
v-tooltip.right="$t('home')"
:to="localePath('index')"
:class="linkActive('/')"
:aria-label="$t('home')"
>
<AppLogo alt class="material-icons" style="height: 24px" />
</nuxt-link>
<nuxt-link
v-tooltip.right="$t('realtime')"
:to="localePath('realtime')"
:class="linkActive('/realtime')"
>
<i class="material-icons">language</i>
</nuxt-link>
<nuxt-link
v-tooltip.right="$t('graphql')"
:to="localePath('graphql')"
:class="linkActive('/graphql')"
:aria-label="$t('graphql')"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
width="24"
viewBox="0 0 29.999 30"
>
<path d="M4.08 22.864l-1.1-.636L15.248.98l1.1.636z" />
<path d="M2.727 20.53h24.538v1.272H2.727z" />
<path
d="M15.486 28.332L3.213 21.246l.636-1.1 12.273 7.086zm10.662-18.47L13.874 2.777l.636-1.1 12.273 7.086z"
/>
<path d="M3.852 9.858l-.636-1.1L15.5 1.67l.636 1.1z" />
<path
d="M25.922 22.864l-12.27-21.25 1.1-.636 12.27 21.25zM3.7 7.914h1.272v14.172H3.7zm21.328 0H26.3v14.172h-1.272z"
/>
<path d="M15.27 27.793l-.555-.962 10.675-6.163.555.962z" />
<path
d="M27.985 22.5a2.68 2.68 0 01-3.654.981 2.68 2.68 0 01-.981-3.654 2.68 2.68 0 013.654-.981 2.665 2.665 0 01.98 3.654M6.642 10.174a2.68 2.68 0 01-3.654.981A2.68 2.68 0 012.007 7.5a2.68 2.68 0 013.654-.981 2.68 2.68 0 01.981 3.654M2.015 22.5a2.68 2.68 0 01.981-3.654 2.68 2.68 0 013.654.981 2.68 2.68 0 01-.981 3.654c-1.287.735-2.92.3-3.654-.98m21.343-12.326a2.68 2.68 0 01.981-3.654 2.68 2.68 0 013.654.981 2.68 2.68 0 01-.981 3.654 2.68 2.68 0 01-3.654-.981M15 30a2.674 2.674 0 112.674-2.673A2.68 2.68 0 0115 30m0-24.652a2.67 2.67 0 01-2.674-2.674 2.67 2.67 0 115.347 0A2.67 2.67 0 0115 5.347"
/>
</svg>
</nuxt-link>
<nuxt-link
v-tooltip.right="$t('documentation')"
:to="localePath('doc')"
:class="linkActive('/doc')"
:aria-label="$t('documentation')"
>
<i class="material-icons">topic</i>
</nuxt-link>
<nuxt-link
v-tooltip.right="$t('settings')"
:to="localePath('settings')"
:class="linkActive('/settings')"
:aria-label="$t('settings')"
>
<i class="material-icons">settings</i>
</nuxt-link>
</nav>
<nav v-if="$route.path == '/'" class="secondary-nav">
<a v-tooltip.right="$t('request')" href="#request">
<i class="material-icons">cloud_upload</i>
</a>
<a v-tooltip.right="$t('options')" href="#options">
<i class="material-icons">toc</i>
</a>
<a v-tooltip.right="$t('response')" href="#response">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/realtime')" class="secondary-nav">
<a v-tooltip.right="$t('request')" href="#request">
<i class="material-icons">cloud_upload</i>
</a>
<a v-tooltip.right="$t('communication')" href="#response">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/graphql')" class="secondary-nav">
<a v-tooltip.right="$t('endpoint')" href="#endpoint">
<i class="material-icons">cloud</i>
</a>
<a v-tooltip.right="$t('schema')" href="#schema">
<i class="material-icons">assignment_returned</i>
</a>
<a v-tooltip.right="$t('query')" href="#query">
<i class="material-icons">cloud_upload</i>
</a>
<a v-tooltip.right="$t('response')" href="#response">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/doc')" class="secondary-nav">
<a v-tooltip.right="$t('import')" href="#import">
<i class="material-icons">folder</i>
</a>
<a v-tooltip.right="$t('documentation')" href="#documentation">
<i class="material-icons">insert_drive_file</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/settings')" class="secondary-nav">
<a v-tooltip.right="$t('account')" href="#account">
<i class="material-icons">person</i>
</a>
<a v-tooltip.right="$t('theme')" href="#theme">
<i class="material-icons">brush</i>
</a>
<a v-tooltip.right="$t('extensions')" href="#extensions">
<i class="material-icons">extension</i>
</a>
<a v-tooltip.right="$t('proxy')" href="#proxy">
<i class="material-icons">public</i>
</a>
</nav>
</aside>
</template>
<script>
export default {
mounted() {
window.addEventListener("scroll", () => {
const mainNavLinks = document.querySelectorAll("nav.secondary-nav a")
const fromTop = window.scrollY
mainNavLinks.forEach(({ hash, classList }) => {
const section = document.querySelector(hash)
if (
section &&
section.offsetTop <= fromTop &&
section.offsetTop + section.offsetHeight > fromTop
) {
classList.add("current")
} else {
classList.remove("current")
}
})
})
},
methods: {
linkActive(path) {
return {
"nuxt-link-exact-active": this.$route.path === path,
"nuxt-link-active": this.$route.path === path,
}
},
},
}
</script>
<style scoped lang="scss">
$responsiveWidth: 768px;
.nav-first {
@apply z-10;
@apply h-screen;
@apply p-2;
@apply bg-bgDarkColor;
@apply transition;
@apply ease-in-out;
@apply duration-150;
@apply space-y-2;
}
nav.primary-nav {
@apply flex;
@apply flex-col;
@apply flex-nowrap;
@apply items-center;
@apply justify-center;
@apply space-y-2;
@apply w-full;
svg {
@apply fill-current;
}
a {
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply flex-shrink-0;
@apply p-4;
@apply rounded-full;
@apply bg-bgLightColor;
@apply text-fgLightColor;
@apply fill-current;
@apply outline-none;
@apply transition;
@apply ease-in-out;
@apply duration-150;
&:hover {
@apply text-fgColor;
@apply fill-current;
svg {
@apply fill-current;
}
}
&.nuxt-link-exact-active {
@apply bg-acColor;
@apply text-actColor;
@apply fill-current;
border-radius: 16px;
svg {
@apply fill-current;
}
}
}
}
nav.primary-nav::-webkit-scrollbar,
.nav-first::-webkit-scrollbar {
@apply hidden;
}
nav.secondary-nav {
@apply flex;
@apply flex-col;
@apply flex-nowrap;
@apply items-center;
@apply justify-center;
@apply border-t-2;
@apply border-dashed;
@apply border-brdColor;
@apply pt-2;
@apply space-y-2;
a {
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply flex-shrink-0;
@apply p-4;
@apply rounded-full;
@apply bg-bgDarkColor;
@apply text-fgLightColor;
@apply fill-current;
@apply outline-none;
@apply transition;
@apply ease-in-out;
@apply duration-150;
&:hover {
@apply text-fgColor;
@apply fill-current;
}
&.current {
@apply text-acColor;
@apply fill-current;
}
}
}
@media (max-width: $responsiveWidth) {
.nav-first {
@apply fixed;
@apply top-auto;
@apply bottom-0;
@apply h-auto;
@apply p-0;
@apply w-full;
@apply bg-bgColor;
@apply shadow-2xl;
}
nav.primary-nav {
@apply flex-row;
@apply flex-nowrap;
@apply overflow-auto;
@apply bg-bgDarkColor;
@apply space-y-0;
padding-bottom: env(safe-area-inset-bottom);
a {
@apply bg-transparent;
@apply my-2;
@apply flex-1;
&.nuxt-link-exact-active {
@apply bg-transparent;
@apply text-acColor;
@apply fill-current;
svg {
@apply fill-current;
}
}
}
}
nav.secondary-nav {
@apply hidden;
}
}
</style>

View File

@@ -1,31 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("support_us") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<AppContributors />
</div>
<div slot="footer"></div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,60 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("new_collection") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="$t('my_new_collection')"
@keyup.enter="addNewCollection"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addNewCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
},
data() {
return {
name: null,
}
},
methods: {
addNewCollection() {
this.$emit("submit", this.name)
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,67 +0,0 @@
<template>
<SmartModal v-if="show" @close="$emit('hide-modal')">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("new_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="$t('my_new_folder')"
@keyup.enter="addFolder"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
folder: { type: Object, default: () => {} },
folderPath: { type: String, default: null },
collectionIndex: { type: Number, default: null },
},
data() {
return {
name: null,
}
},
methods: {
addFolder() {
this.$emit("add-folder", {
name: this.name,
folder: this.folder,
path: this.folderPath || `${this.collectionIndex}`,
})
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,105 +0,0 @@
<template>
<div v-if="show">
<SmartTabs
:id="'collections_tab'"
styles="m-4"
@tab-changed="updateCollectionsType"
>
<SmartTab
:id="'my-collections'"
:label="'My Collections'"
:selected="true"
/>
<SmartTab
v-if="currentUser && currentUser.eaInvited && !doc"
:id="'team-collections'"
:label="'Team Collections'"
>
<ul>
<li>
<span class="select-wrapper">
<SmartIntersection @intersecting="onTeamSelectIntersect">
<select
id="team"
type="text"
class="team"
autofocus
@change="updateSelectedTeam(myTeams[$event.target.value])"
>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>
Select team
</option>
<option
v-for="(team, index) in myTeams"
:key="index"
:value="index"
>
{{ team.name }}
</option>
</select>
</SmartIntersection>
</span>
</li>
</ul>
</SmartTab>
</SmartTabs>
</div>
</template>
<script>
import gql from "graphql-tag"
import { currentUserInfo$ } from "~/helpers/teams/BackendUserInfo"
export default {
props: {
doc: Boolean,
show: Boolean,
},
data() {
return {
skipTeamsFetching: true,
}
},
subscriptions() {
return {
currentUser: currentUserInfo$,
}
},
apollo: {
myTeams: {
query: gql`
query GetMyTeams {
myTeams {
id
name
myRole
}
}
`,
pollInterval: 10000,
skip() {
return this.skipTeamsFetching
},
},
},
methods: {
onTeamSelectIntersect() {
// Load team data as soon as intersection
this.$apollo.queries.myTeams.refetch()
this.skipTeamsFetching = false
},
updateCollectionsType(tabID) {
this.$emit("update-collection-type", tabID)
},
updateSelectedTeam(team) {
this.$emit("update-selected-team", team)
},
},
}
</script>

View File

@@ -1,61 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_collection") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="placeholderCollName"
@keyup.enter="saveCollection"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
placeholderCollName: { type: String, default: null },
},
data() {
return {
name: null,
}
},
methods: {
saveCollection() {
this.$emit("submit", this.name)
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,59 +0,0 @@
<template>
<SmartModal v-if="show" @close="$emit('hide-modal')">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
@keyup.enter="editFolder"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="editFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
},
data() {
return {
name: null,
}
},
methods: {
editFolder() {
this.$emit("submit", this.name)
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,63 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_request") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="requestUpdateData.name"
type="text"
:placeholder="placeholderReqName"
@keyup.enter="saveRequest"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveRequest">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
placeholderReqName: { type: String, default: null },
},
data() {
return {
requestUpdateData: {
name: null,
},
}
},
methods: {
saveRequest() {
this.$emit("submit", this.requestUpdateData)
this.hideModal()
},
hideModal() {
this.requestUpdateData = { name: null }
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,262 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("save_request_as") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("token_req_name") }}</label>
<input
id="selectLabel"
v-model="requestData.name"
type="text"
@keyup.enter="saveRequestAs"
/>
<label for="selectLabel">Select location</label>
<!-- <input readonly :value="path" /> -->
<Collections
:picked="picked"
:save-request="true"
@select="onSelect"
@update-collection="collectionsType.type = $event"
@update-coll-type="onUpdateCollType"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveRequestAs">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import * as teamUtils from "~/helpers/teams/utils"
export default {
props: {
show: Boolean,
editingRequest: { type: Object, default: () => {} },
},
data() {
return {
defaultRequestName: "Untitled Request",
path: "Path will appear here",
requestData: {
name: undefined,
collectionIndex: undefined,
folderName: undefined,
requestIndex: undefined,
},
collectionsType: {
type: "my-collections",
selectedTeam: undefined,
},
picked: null,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
computed: {
folders() {
const collections = this.$store.state.postwoman.collections
const collectionIndex = this.$data.requestData.collectionIndex
const userSelectedAnyCollection = collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
const noCollectionAvailable = collections[collectionIndex] !== undefined
if (!noCollectionAvailable) return []
return getFolderNames(collections[collectionIndex].folders, [])
},
requests() {
const collections = this.$store.state.postwoman.collections
const collectionIndex = this.$data.requestData.collectionIndex
const folderName = this.$data.requestData.folderName
const userSelectedAnyCollection = collectionIndex !== undefined
if (!userSelectedAnyCollection) {
return []
}
const userSelectedAnyFolder =
folderName !== undefined && folderName !== ""
if (userSelectedAnyFolder) {
const collection = collections[collectionIndex]
const folder = findFolder(folderName, collection)
return folder.requests
} else {
const collection = collections[collectionIndex]
const noCollectionAvailable = collection !== undefined
if (!noCollectionAvailable) {
return []
}
return collection.requests
}
},
},
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
},
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
saveRequestAs() {
if (this.picked == null) {
this.$toast.error(this.$t("select_collection"), {
icon: "error",
})
return
}
if (this.$data.requestData.name.length === 0) {
this.$toast.error(this.$t("empty_req_name"), {
icon: "error",
})
return
}
const requestUpdated = {
...this.$props.editingRequest,
name: this.$data.requestData.name,
collection: this.$data.requestData.collectionIndex,
}
if (this.picked.pickedType === "my-request") {
this.$store.commit("postwoman/saveRequestAs", {
request: requestUpdated,
collectionIndex: this.picked.collectionIndex,
folderName: this.picked.folderName,
requestIndex: this.picked.requestIndex,
flag: "rest",
})
this.syncCollections()
} else if (this.picked.pickedType === "my-folder") {
this.$store.commit("postwoman/saveRequestAs", {
request: requestUpdated,
collectionIndex: this.picked.collectionIndex,
folderName: this.picked.folderName,
flag: "rest",
})
this.syncCollections()
} else if (this.picked.pickedType === "my-collection") {
this.$store.commit("postwoman/saveRequestAs", {
request: requestUpdated,
collectionIndex: this.picked.collectionIndex,
flag: "rest",
})
this.syncCollections()
} else if (this.picked.pickedType === "teams-request") {
teamUtils.overwriteRequestTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.picked.requestID
)
} else if (this.picked.pickedType === "teams-folder") {
teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.folderID
)
} else if (this.picked.pickedType === "teams-collection") {
teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.collectionID
)
}
this.$toast.success("Requested added", {
icon: "done",
})
this.hideModal()
},
hideModal() {
this.$emit("hide-modal")
},
},
}
function getFolderNames(folders, namesList, folderName = "") {
if (folders.length) {
folders.forEach((folder) => {
namesList.push(folderName + folder.name)
if (folder.folders && folder.folders.length) {
getFolderNames(folder.folders, namesList, folder.name + "/")
}
})
}
return namesList
}
function findFolder(folderName, currentFolder) {
let selectedFolder
let result
if (folderName === currentFolder.name) {
return currentFolder
}
for (let i = 0; i < currentFolder.folders.length; i++) {
selectedFolder = currentFolder.folders[i]
result = findFolder(folderName, selectedFolder)
if (result !== false) {
return result
}
}
return false
}
</script>

View File

@@ -1,82 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("new_collection") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="$t('my_new_collection')"
@keyup.enter="addNewCollection"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addNewCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
},
data() {
return {
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
addNewCollection() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_collection_name"))
return
}
this.$store.commit("postwoman/addNewCollection", {
name: this.$data.name,
flag: "graphql",
})
this.syncCollections()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,82 +0,0 @@
<template>
<SmartModal v-if="show" @close="$emit('hide-modal')">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("new_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="$t('my_new_folder')"
@keyup.enter="addFolder"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
folder: { type: Object, default: () => {} },
folderPath: { type: String, default: null },
collectionIndex: { type: Number, default: null },
},
data() {
return {
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
addFolder() {
this.$emit("add-folder", {
name: this.name,
folder: this.folder,
path: this.folderPath || `${this.collectionIndex}`,
})
this.syncCollections()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,203 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
@dragover.prevent
@drop.prevent="dropEvent"
@dragover="dragging = true"
@drop="dragging = false"
@dragleave="dragging = false"
@dragend="dragging = false"
>
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i class="material-icons">folder</i>
<span>{{ collection.name }}</span>
</button>
<div>
<button
v-if="doc"
v-tooltip.left="$t('import')"
class="icon"
@click="$emit('select-collection')"
>
<i class="material-icons">topic</i>
</button>
<v-popover>
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="
$emit('add-folder', {
folder: collection,
path: `${collectionIndex}`,
})
"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="$emit('edit-collection')"
>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="confirmRemove = true"
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(folder, index) in collection.folders"
:key="folder.name"
class="ml-8 border-l border-brdColor"
>
<CollectionsGraphqlFolder
:folder="folder"
:folder-index="index"
:folder-path="`${collectionIndex}/${index}`"
:collection-index="collectionIndex"
:doc="doc"
:is-filtered="isFiltered"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in collection.requests"
:key="index"
class="ml-8 border-l border-brdColor"
>
<CollectionsGraphqlRequest
:request="request"
:collection-index="collectionIndex"
:folder-index="-1"
:folder-name="collection.name"
:request-index="index"
:doc="doc"
@edit-request="$emit('edit-request', $event)"
/>
</li>
</ul>
<ul>
<li
v-if="
collection.folders.length === 0 && collection.requests.length === 0
"
class="flex ml-8 border-l border-brdColor"
>
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("collection_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_collection')"
@hide-modal="confirmRemove = false"
@resolve="removeCollection"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
collectionIndex: { type: Number, default: null },
collection: { type: Object, default: () => {} },
doc: Boolean,
isFiltered: Boolean,
},
data() {
return {
showChildren: false,
dragging: false,
selectedFolder: {},
confirmRemove: false,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
toggleShowChildren() {
this.showChildren = !this.showChildren
},
removeCollection() {
this.$store.commit("postwoman/removeCollection", {
collectionIndex: this.collectionIndex,
flag: "graphql",
})
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
this.syncCollections()
},
dropEvent({ dataTransfer }) {
this.dragging = !this.dragging
const oldCollectionIndex = dataTransfer.getData("oldCollectionIndex")
const oldFolderIndex = dataTransfer.getData("oldFolderIndex")
const oldFolderName = dataTransfer.getData("oldFolderName")
const requestIndex = dataTransfer.getData("requestIndex")
const flag = "graphql"
this.$store.commit("postwoman/moveRequest", {
oldCollectionIndex,
newCollectionIndex: this.$props.collectionIndex,
newFolderIndex: -1,
newFolderName: this.$props.collection.name,
oldFolderIndex,
oldFolderName,
requestIndex,
flag,
})
this.syncCollections()
},
},
}
</script>

View File

@@ -1,89 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_collection") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="editingCollection.name"
@keyup.enter="saveCollection"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
editingCollection: { type: Object, default: () => {} },
editingCollectionIndex: { type: Number, default: null },
},
data() {
return {
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
saveCollection() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_collection_name"))
return
}
const collectionUpdated = {
...this.$props.editingCollection,
name: this.$data.name,
}
this.$store.commit("postwoman/editCollection", {
collection: collectionUpdated,
collectionIndex: this.$props.editingCollectionIndex,
flag: "graphql",
})
this.syncCollections()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,84 +0,0 @@
<template>
<SmartModal v-if="show" @close="$emit('hide-modal')">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="folder.name"
@keyup.enter="editFolder"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="editFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
collectionIndex: { type: Number, default: null },
folder: { type: Object, default: () => {} },
folderIndex: { type: Number, default: null },
},
data() {
return {
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
editFolder() {
this.$store.commit("postwoman/editFolder", {
collectionIndex: this.$props.collectionIndex,
folder: { ...this.$props.folder, name: this.$data.name },
folderIndex: this.$props.folderIndex,
folderName: this.$props.folder.name,
flag: "graphql",
})
this.syncCollections()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,94 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_request") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="requestUpdateData.name"
type="text"
:placeholder="request.name"
@keyup.enter="saveRequest"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveRequest">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
collectionIndex: { type: Number, default: null },
folderIndex: { type: Number, default: null },
folderName: { type: String, default: null },
request: { type: Object, default: () => {} },
requestIndex: { type: Number, default: null },
},
data() {
return {
requestUpdateData: {
name: null,
},
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
saveRequest() {
const requestUpdated = {
...this.$props.request,
name: this.$data.requestUpdateData.name || this.$props.request.name,
}
this.$store.commit("postwoman/editRequest", {
requestCollectionIndex: this.$props.collectionIndex,
requestFolderName: this.$props.folderName,
requestFolderIndex: this.$props.folderIndex,
requestNew: requestUpdated,
requestIndex: this.$props.requestIndex,
flag: "graphql",
})
this.syncCollections()
this.hideModal()
},
hideModal() {
this.requestUpdateData = { name: null }
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,195 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
@dragover.prevent
@drop.prevent="dropEvent"
@dragover="dragging = true"
@drop="dragging = false"
@dragleave="dragging = false"
@dragend="dragging = false"
>
<div>
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i class="material-icons">folder_open</i>
<span>{{ folder.name }}</span>
</button>
</div>
<v-popover>
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="$emit('add-folder', { folder, path: folderPath })"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="
$emit('edit-folder', { folder, folderIndex, collectionIndex })
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(subFolder, subFolderIndex) in folder.folders"
:key="subFolder.name"
class="ml-8 border-l border-brdColor"
>
<CollectionsGraphqlFolder
:folder="subFolder"
:folder-index="subFolderIndex"
:folder-path="`${folderPath}/${subFolderIndex}`"
:collection-index="collectionIndex"
:doc="doc"
:is-filtered="isFiltered"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in folder.requests"
:key="index"
class="flex ml-8 border-l border-brdColor"
>
<CollectionsGraphqlRequest
:request="request"
:collection-index="collectionIndex"
:folder-index="folderIndex"
:folder-name="folder.name"
:request-index="index"
:doc="doc"
@edit-request="$emit('edit-request', $event)"
/>
</li>
</ul>
<ul
v-if="
folder.folders &&
folder.folders.length === 0 &&
folder.requests &&
folder.requests.length === 0
"
>
<li class="flex ml-8 border-l border-brdColor">
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("folder_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_folder')"
@hide-modal="confirmRemove = false"
@resolve="removeFolder"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
name: "Folder",
props: {
folder: { type: Object, default: () => {} },
folderIndex: { type: Number, default: null },
collectionIndex: { type: Number, default: null },
folderPath: { type: String, default: null },
doc: Boolean,
isFiltered: Boolean,
},
data() {
return {
showChildren: false,
dragging: false,
confirmRemove: false,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
toggleShowChildren() {
this.showChildren = !this.showChildren
},
removeFolder() {
this.$store.commit("postwoman/removeFolder", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folder.name,
folderIndex: this.$props.folderIndex,
flag: "graphql",
})
this.syncCollections()
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
},
dropEvent({ dataTransfer }) {
this.dragging = !this.dragging
const oldCollectionIndex = dataTransfer.getData("oldCollectionIndex")
const oldFolderIndex = dataTransfer.getData("oldFolderIndex")
const oldFolderName = dataTransfer.getData("oldFolderName")
const requestIndex = dataTransfer.getData("requestIndex")
const flag = "graphql"
this.$store.commit("postwoman/moveRequest", {
oldCollectionIndex,
newCollectionIndex: this.$props.collectionIndex,
newFolderIndex: this.$props.folderIndex,
newFolderName: this.$props.folder.name,
oldFolderIndex,
oldFolderName,
requestIndex,
flag,
})
this.syncCollections()
},
},
}
</script>

View File

@@ -1,123 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
draggable="true"
@dragstart="dragStart"
@dragover.stop
@dragleave="dragging = false"
@dragend="dragging = false"
>
<div>
<button
v-tooltip="!doc ? $t('use_request') : ''"
class="icon"
@click="!doc ? selectRequest() : {}"
>
<i class="material-icons">description</i>
<span>{{ request.name }}</span>
</button>
</div>
<v-popover>
<button v-tooltip="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="
$emit('edit-request', {
collectionIndex,
folderIndex,
folderName,
request,
requestIndex,
})
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_request')"
@hide-modal="confirmRemove = false"
@resolve="removeRequest"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
request: { type: Object, default: () => {} },
collectionIndex: { type: Number, default: null },
folderIndex: { type: Number, default: null },
folderName: { type: String, default: null },
requestIndex: { type: Number, default: null },
doc: Boolean,
},
data() {
return {
dragging: false,
confirmRemove: false,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
selectRequest() {
this.$store.commit("postwoman/selectGraphqlRequest", {
request: this.request,
})
},
dragStart({ dataTransfer }) {
this.dragging = !this.dragging
dataTransfer.setData("oldCollectionIndex", this.$props.collectionIndex)
dataTransfer.setData("oldFolderIndex", this.$props.folderIndex)
dataTransfer.setData("oldFolderName", this.$props.folderName)
dataTransfer.setData("requestIndex", this.$props.requestIndex)
},
removeRequest() {
this.$store.commit("postwoman/removeRequest", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folderName,
requestIndex: this.$props.requestIndex,
flag: "graphql",
})
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
this.confirmRemove = false
this.syncCollections()
},
},
}
</script>

View File

@@ -1,253 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("save_request_as") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("token_req_name") }}</label>
<input
id="selectLabel"
v-model="requestData.name"
type="text"
@keyup.enter="saveRequestAs"
/>
<ul>
<li>
<label for="selectCollection">{{ $t("collection") }}</label>
<span class="select-wrapper">
<select
id="selectCollection"
v-model="requestData.collectionIndex"
type="text"
>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>
{{ $t("select_collection") }}
</option>
<option
v-for="(collection, index) in $store.state.postwoman
.collectionsGraphql"
:key="index"
:value="index"
>
{{ collection.name }}
</option>
</select>
</span>
</li>
</ul>
<label>{{ $t("folder") }}</label>
<SmartAutoComplete
v-model="requestData.folderName"
:placeholder="$t('search')"
:source="folders"
:spellcheck="false"
/>
<ul>
<li>
<label for="selectRequest">{{ $t("request") }}</label>
<span class="select-wrapper">
<select
id="selectRequest"
v-model="requestData.requestIndex"
type="text"
>
<option :key="undefined" :value="undefined">/</option>
<option
v-for="(folder, index) in requests"
:key="index"
:value="index"
>
{{ folder.name }}
</option>
</select>
</span>
</li>
</ul>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveRequestAs">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
props: {
show: Boolean,
editingRequest: { type: Object, default: () => {} },
},
data() {
return {
defaultRequestName: "Untitled Request",
requestData: {
name: undefined,
collectionIndex: undefined,
folderName: undefined,
requestIndex: undefined,
},
}
},
computed: {
folders() {
const collections = this.$store.state.postwoman.collectionsGraphql
const collectionIndex = this.$data.requestData.collectionIndex
const userSelectedAnyCollection = collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
const noCollectionAvailable = collections[collectionIndex] !== undefined
if (!noCollectionAvailable) return []
return getFolderNames(collections[collectionIndex].folders, [])
},
requests() {
const collections = this.$store.state.postwoman.collectionsGraphql
const collectionIndex = this.$data.requestData.collectionIndex
const folderName = this.$data.requestData.folderName
const userSelectedAnyCollection = collectionIndex !== undefined
if (!userSelectedAnyCollection) {
return []
}
const userSelectedAnyFolder =
folderName !== undefined && folderName !== ""
if (userSelectedAnyFolder) {
const collection = collections[collectionIndex]
const folder = findFolder(folderName, collection)
return folder.requests
} else {
const collection = collections[collectionIndex]
const noCollectionAvailable = collection !== undefined
if (!noCollectionAvailable) {
return []
}
return collection.requests
}
},
},
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: {
syncCollections() {
if (fb.currentUser !== null && fb.currentSettings[0]) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(
JSON.stringify(this.$store.state.postwoman.collectionsGraphql)
),
"collectionsGraphql"
)
}
}
},
saveRequestAs() {
const userDidntSpecifyCollection =
this.$data.requestData.collectionIndex === undefined
if (userDidntSpecifyCollection) {
this.$toast.error(this.$t("select_collection"), {
icon: "error",
})
return
}
if (this.$data.requestData.name.length === 0) {
this.$toast.error(this.$t("empty_req_name"), {
icon: "error",
})
return
}
const requestUpdated = {
...this.$props.editingRequest,
name: this.$data.requestData.name,
collection: this.$data.requestData.collectionIndex,
}
this.$store.commit("postwoman/saveRequestAs", {
request: requestUpdated,
collectionIndex: this.$data.requestData.collectionIndex,
folderName: this.$data.requestData.folderName,
requestIndex: this.$data.requestData.requestIndex,
flag: "graphql",
})
this.hideModal()
this.syncCollections()
},
hideModal() {
this.$emit("hide-modal")
},
},
}
function getFolderNames(folders, namesList) {
if (folders.length) {
folders.forEach((folder) => {
namesList.push(folder.name)
if (folder.folders && folder.folders.length) {
getFolderNames(folder.folders, namesList)
}
})
}
return namesList
}
function findFolder(folderName, currentFolder) {
let selectedFolder
let result
if (folderName === currentFolder.name) {
return currentFolder
}
for (let i = 0; i < currentFolder.folders.length; i++) {
selectedFolder = currentFolder.folders[i]
result = findFolder(folderName, selectedFolder)
if (result !== false) {
return result
}
}
return false
}
</script>

View File

@@ -1,265 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
@dragover.prevent
@drop.prevent="dropEvent"
@dragover="dragging = true"
@drop="dragging = false"
@dragleave="dragging = false"
@dragend="dragging = false"
>
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i v-if="isSelected" class="text-green-400 material-icons"
>check_circle</i
>
<i v-else class="material-icons">folder</i>
<span>{{ collection.name }}</span>
</button>
<div>
<button
v-if="doc && !selected"
v-tooltip.left="$t('import')"
class="icon"
@click="$emit('select-collection')"
>
<i class="material-icons">check_box_outline_blank</i>
</button>
<button
v-if="doc && selected"
v-tooltip.left="$t('delete')"
class="icon"
@click="$emit('unselect-collection')"
>
<i class="material-icons">check_box</i>
</button>
<v-popover v-if="!saveRequest">
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="
$emit('add-folder', {
folder: collection,
path: `${collectionIndex}`,
})
"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="$emit('edit-collection')"
>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="confirmRemove = true"
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(folder, index) in collection.folders"
:key="index"
class="ml-8 border-l border-brdColor"
>
<CollectionsMyFolder
:folder="folder"
:folder-index="index"
:folder-path="`${collectionIndex}/${index}`"
:collection-index="collectionIndex"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:is-filtered="isFiltered"
:picked="picked"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in collection.requests"
:key="index"
class="ml-8 border-l border-brdColor"
>
<CollectionsMyRequest
:request="request"
:collection-index="collectionIndex"
:folder-index="-1"
:folder-name="collection.name"
:folder-path="collectionIndex.toString()"
:request-index="index"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:picked="picked"
@edit-request="editRequest($event)"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul>
<li
v-if="
(collection.folders == undefined ||
collection.folders.length === 0) &&
(collection.requests == undefined ||
collection.requests.length === 0)
"
class="flex ml-8 border-l border-brdColor"
>
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("collection_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_collection')"
@hide-modal="confirmRemove = false"
@resolve="removeCollection"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
collectionIndex: { type: Number, default: null },
collection: { type: Object, default: () => {} },
doc: Boolean,
isFiltered: Boolean,
selected: Boolean,
saveRequest: Boolean,
collectionsType: { type: Object, default: () => {} },
picked: { type: Object, default: () => {} },
},
data() {
return {
showChildren: false,
dragging: false,
selectedFolder: {},
confirmRemove: false,
prevCursor: "",
cursor: "",
pageNo: 0,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "my-collection" &&
this.picked.collectionIndex === this.collectionIndex
)
},
},
methods: {
editRequest(event) {
this.$emit("edit-request", event)
},
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
toggleShowChildren() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "my-collection",
collectionIndex: this.collectionIndex,
},
})
this.$emit("expand-collection", this.collection.id)
this.showChildren = !this.showChildren
},
removeCollection() {
this.$emit("remove-collection", {
collectionsType: this.collectionsType,
collectionIndex: this.collectionIndex,
collectionID: this.collection.id,
})
this.confirmRemove = false
},
dropEvent({ dataTransfer }) {
this.dragging = !this.dragging
const oldCollectionIndex = dataTransfer.getData("oldCollectionIndex")
const oldFolderIndex = dataTransfer.getData("oldFolderIndex")
const oldFolderName = dataTransfer.getData("oldFolderName")
const requestIndex = dataTransfer.getData("requestIndex")
const flag = "rest"
this.$store.commit("postwoman/moveRequest", {
oldCollectionIndex,
newCollectionIndex: this.$props.collectionIndex,
newFolderIndex: -1,
newFolderName: this.$props.collection.name,
oldFolderIndex,
oldFolderName,
requestIndex,
flag,
})
this.syncCollections()
},
removeRequest({ collectionIndex, folderName, requestIndex }) {
this.$emit("remove-request", {
collectionIndex,
folderName,
requestIndex,
})
},
},
}
</script>

View File

@@ -1,241 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
@dragover.prevent
@drop.prevent="dropEvent"
@dragover="dragging = true"
@drop="dragging = false"
@dragleave="dragging = false"
@dragend="dragging = false"
>
<div>
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i v-if="isSelected" class="text-green-400 material-icons"
>check_circle</i
>
<i v-else class="material-icons">folder_open</i>
<span>{{ folder.name ? folder.name : folder.title }}</span>
</button>
</div>
<v-popover v-if="!saveRequest">
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="$emit('add-folder', { folder, path: folderPath })"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-close-popover
class="icon"
@click="
$emit('edit-folder', { folder, folderIndex, collectionIndex })
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(subFolder, subFolderIndex) in folder.folders"
:key="subFolder.name"
class="ml-8 border-l border-brdColor"
>
<CollectionsMyFolder
:folder="subFolder"
:folder-index="subFolderIndex"
:collection-index="collectionIndex"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:folder-path="`${folderPath}/${subFolderIndex}`"
:picked="picked"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
@update-team-collections="$emit('update-team-collections')"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in folder.requests"
:key="index"
class="flex ml-8 border-l border-brdColor"
>
<CollectionsMyRequest
:request="request"
:collection-index="collectionIndex"
:folder-index="folderIndex"
:folder-name="folder.name"
:request-index="index"
:folder-path="folderPath"
:doc="doc"
:picked="picked"
:save-request="saveRequest"
:collections-type="collectionsType"
@edit-request="$emit('edit-request', $event)"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul
v-if="
folder.folders &&
folder.folders.length === 0 &&
folder.requests &&
folder.requests.length === 0
"
>
<li class="flex ml-8 border-l border-brdColor">
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("folder_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_folder')"
@hide-modal="confirmRemove = false"
@resolve="removeFolder"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
name: "Folder",
props: {
folder: { type: Object, default: () => {} },
folderIndex: { type: Number, default: null },
collectionIndex: { type: Number, default: null },
folderPath: { type: String, default: null },
doc: Boolean,
saveRequest: Boolean,
isFiltered: Boolean,
collectionsType: { type: Object, default: () => {} },
picked: { type: Object, default: () => {} },
},
data() {
return {
showChildren: false,
dragging: false,
confirmRemove: false,
prevCursor: "",
cursor: "",
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "my-folder" &&
this.picked.folderPath === this.folderPath
)
},
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
toggleShowChildren() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "my-folder",
collectionIndex: this.collectionIndex,
folderName: this.folder.name,
folderPath: this.folderPath,
},
})
this.showChildren = !this.showChildren
},
removeFolder() {
this.$store.commit("postwoman/removeFolder", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folder.name,
folderIndex: this.$props.folderIndex,
flag: "rest",
})
this.syncCollections()
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
},
dropEvent({ dataTransfer }) {
this.dragging = !this.dragging
const oldCollectionIndex = dataTransfer.getData("oldCollectionIndex")
const oldFolderIndex = dataTransfer.getData("oldFolderIndex")
const oldFolderName = dataTransfer.getData("oldFolderName")
const requestIndex = dataTransfer.getData("requestIndex")
const flag = "rest"
this.$store.commit("postwoman/moveRequest", {
oldCollectionIndex,
newCollectionIndex: this.$props.collectionIndex,
newFolderIndex: this.$props.folderIndex,
newFolderName: this.$props.folder.name,
oldFolderIndex,
oldFolderName,
requestIndex,
flag,
})
this.syncCollections()
},
removeRequest({ collectionIndex, folderName, requestIndex }) {
this.$emit("remove-request", {
collectionIndex,
folderName,
requestIndex,
})
},
},
}
</script>

View File

@@ -1,146 +0,0 @@
<template>
<div>
<div
:class="[
'row-wrapper transition duration-150 ease-in-out',
{ 'bg-bgDarkColor': dragging },
]"
draggable="true"
@dragstart="dragStart"
@dragover.stop
@dragleave="dragging = false"
@dragend="dragging = false"
>
<div>
<button
v-tooltip="!doc ? $t('use_request') : ''"
class="icon"
@click="!doc ? selectRequest() : {}"
>
<i v-if="isSelected" class="mx-3 text-green-400 material-icons"
>check_circle</i
>
<span v-else :class="getRequestLabelColor(request.method)">{{
request.method
}}</span>
<span>{{ request.name }}</span>
</button>
</div>
<v-popover v-if="!saveRequest">
<button v-tooltip="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="
$emit('edit-request', {
collectionIndex,
folderIndex,
folderName,
request,
requestIndex,
})
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_request')"
@hide-modal="confirmRemove = false"
@resolve="removeRequest"
/>
</div>
</template>
<script>
export default {
props: {
request: { type: Object, default: () => {} },
collectionIndex: { type: Number, default: null },
folderIndex: { type: Number, default: null },
folderName: { type: String, default: null },
// eslint-disable-next-line vue/require-default-prop
requestIndex: [Number, String],
doc: Boolean,
saveRequest: Boolean,
collectionsType: { type: Object, default: () => {} },
folderPath: { type: String, default: null },
picked: { type: Object, default: () => {} },
},
data() {
return {
dragging: false,
requestMethodLabels: {
get: "text-green-400",
post: "text-yellow-400",
put: "text-blue-400",
delete: "text-red-400",
default: "text-gray-400",
},
confirmRemove: false,
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "my-request" &&
this.picked.folderPath === this.folderPath &&
this.picked.requestIndex === this.requestIndex
)
},
},
methods: {
selectRequest() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "my-request",
collectionIndex: this.collectionIndex,
folderPath: this.folderPath,
folderName: this.folderName,
requestIndex: this.requestIndex,
},
})
else
this.$store.commit("postwoman/selectRequest", { request: this.request })
},
dragStart({ dataTransfer }) {
this.dragging = !this.dragging
dataTransfer.setData("oldCollectionIndex", this.$props.collectionIndex)
dataTransfer.setData("oldFolderIndex", this.$props.folderIndex)
dataTransfer.setData("oldFolderName", this.$props.folderName)
dataTransfer.setData("requestIndex", this.$props.requestIndex)
},
removeRequest() {
this.$emit("remove-request", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folderName,
requestIndex: this.$props.requestIndex,
})
},
getRequestLabelColor(method) {
return (
this.requestMethodLabels[method.toLowerCase()] ||
this.requestMethodLabels.default
)
},
},
}
</script>

View File

@@ -1,236 +0,0 @@
<template>
<div>
<div class="transition duration-150 ease-in-out row-wrapper">
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i v-if="isSelected" class="text-green-400 material-icons"
>check_circle</i
>
<i v-else class="material-icons">folder</i>
<span>{{ collection.title }}</span>
</button>
<div>
<button
v-if="doc && !selected"
v-tooltip.left="$t('import')"
class="icon"
@click="$emit('select-collection')"
>
<i class="material-icons">check_box_outline_blank</i>
</button>
<button
v-if="doc && selected"
v-tooltip.left="$t('delete')"
class="icon"
@click="$emit('unselect-collection')"
>
<i class="material-icons">check_box</i>
</button>
<v-popover v-if="!saveRequest">
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-tooltip.left="$t('more')"
class="tooltip-target icon"
>
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="
$emit('add-folder', {
folder: collection,
path: `${collectionIndex}`,
})
"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="$emit('edit-collection')"
>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="confirmRemove = true"
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(folder, index) in collection.children"
:key="folder.title"
class="ml-8 border-l border-brdColor"
>
<CollectionsTeamsFolder
:folder="folder"
:folder-index="index"
:folder-path="`${collectionIndex}/${index}`"
:collection-index="collectionIndex"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:is-filtered="isFiltered"
:picked="picked"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
@select="$emit('select', $event)"
@expand-collection="expandCollection"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in collection.requests"
:key="index"
class="ml-8 border-l border-brdColor"
>
<CollectionsTeamsRequest
:request="request.request"
:collection-index="collectionIndex"
:folder-index="-1"
:folder-name="collection.name"
:request-index="request.id"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:picked="picked"
@edit-request="editRequest($event)"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul>
<li
v-if="
(collection.children == undefined ||
collection.children.length === 0) &&
(collection.requests == undefined ||
collection.requests.length === 0)
"
class="flex ml-8 border-l border-brdColor"
>
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("collection_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_collection')"
@hide-modal="confirmRemove = false"
@resolve="removeCollection"
/>
</div>
</template>
<script>
export default {
props: {
collectionIndex: { type: Number, default: null },
collection: { type: Object, default: () => {} },
doc: Boolean,
isFiltered: Boolean,
selected: Boolean,
saveRequest: Boolean,
collectionsType: { type: Object, default: () => {} },
picked: { type: Object, default: () => {} },
},
data() {
return {
showChildren: false,
dragging: false,
selectedFolder: {},
confirmRemove: false,
prevCursor: "",
cursor: "",
pageNo: 0,
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "teams-collection" &&
this.picked.collectionID === this.collection.id
)
},
},
methods: {
editRequest(event) {
this.$emit("edit-request", event)
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "teams-collection",
collectionID: this.collection.id,
},
})
},
toggleShowChildren() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "teams-collection",
collectionID: this.collection.id,
},
})
this.$emit("expand-collection", this.collection.id)
this.showChildren = !this.showChildren
},
removeCollection() {
this.$emit("remove-collection", {
collectionsType: this.collectionsType,
collectionIndex: this.collectionIndex,
collectionID: this.collection.id,
})
this.confirmRemove = false
},
expandCollection(collectionID) {
this.$emit("expand-collection", collectionID)
},
removeRequest({ collectionIndex, folderName, requestIndex }) {
this.$emit("remove-request", {
collectionIndex,
folderName,
requestIndex,
})
},
},
}
</script>

View File

@@ -1,219 +0,0 @@
<template>
<div>
<div class="transition duration-150 ease-in-out row-wrapper">
<div>
<button class="icon" @click="toggleShowChildren">
<i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i
>
<i v-show="showChildren || isFiltered" class="material-icons"
>arrow_drop_down</i
>
<i v-if="isSelected" class="text-green-400 material-icons"
>check_circle</i
>
<i v-else class="material-icons">folder_open</i>
<span>{{ folder.name ? folder.name : folder.title }}</span>
</button>
</div>
<v-popover v-if="!saveRequest">
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-tooltip.left="$t('more')"
class="tooltip-target icon"
>
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="$emit('add-folder', { folder, path: folderPath })"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="
$emit('edit-folder', { folder, folderIndex, collectionIndex })
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-close-popover
class="icon"
@click="confirmRemove = true"
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren || isFiltered">
<ul class="flex-col">
<li
v-for="(subFolder, subFolderIndex) in folder.children"
:key="subFolder.name"
class="ml-8 border-l border-brdColor"
>
<CollectionsTeamsFolder
:folder="subFolder"
:folder-index="subFolderIndex"
:collection-index="collectionIndex"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:folder-path="`${folderPath}/${subFolderIndex}`"
:picked="picked"
@add-folder="$emit('add-folder', $event)"
@edit-folder="$emit('edit-folder', $event)"
@edit-request="$emit('edit-request', $event)"
@update-team-collections="$emit('update-team-collections')"
@select="$emit('select', $event)"
@expand-collection="expandCollection"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul class="flex-col">
<li
v-for="(request, index) in folder.requests"
:key="index"
class="flex ml-8 border-l border-brdColor"
>
<CollectionsTeamsRequest
:request="request.request"
:collection-index="collectionIndex"
:folder-index="folderIndex"
:folder-name="folder.name"
:request-index="request.id"
:doc="doc"
:save-request="saveRequest"
:collections-type="collectionsType"
:picked="picked"
@edit-request="$emit('edit-request', $event)"
@select="$emit('select', $event)"
@remove-request="removeRequest"
/>
</li>
</ul>
<ul
v-if="
(folder.children == undefined || folder.children.length === 0) &&
(folder.requests == undefined || folder.requests.length === 0)
"
>
<li class="flex ml-8 border-l border-brdColor">
<p class="info">
<i class="material-icons">not_interested</i>
{{ $t("folder_empty") }}
</p>
</li>
</ul>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_folder')"
@hide-modal="confirmRemove = false"
@resolve="removeFolder"
/>
</div>
</template>
<script>
import * as teamUtils from "~/helpers/teams/utils"
export default {
name: "Folder",
props: {
folder: { type: Object, default: () => {} },
folderIndex: { type: Number, default: null },
collectionIndex: { type: Number, default: null },
folderPath: { type: String, default: null },
doc: Boolean,
saveRequest: Boolean,
isFiltered: Boolean,
collectionsType: { type: Object, default: () => {} },
picked: { type: Object, default: () => {} },
},
data() {
return {
showChildren: false,
confirmRemove: false,
prevCursor: "",
cursor: "",
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "teams-folder" &&
this.picked.folderID === this.folder.id
)
},
},
methods: {
toggleShowChildren() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "teams-folder",
folderID: this.folder.id,
},
})
this.$emit("expand-collection", this.$props.folder.id)
this.showChildren = !this.showChildren
},
removeFolder() {
if (this.collectionsType.selectedTeam.myRole !== "VIEWER") {
teamUtils
.deleteCollection(this.$apollo, this.folder.id)
.then(() => {
// Result
this.$toast.success(this.$t("deleted"), {
icon: "delete",
})
this.$emit("update-team-collections")
this.confirmRemove = false
})
.catch((error) => {
// Error
this.$toast.error(this.$t("error_occurred"), {
icon: "done",
})
console.error(error)
})
this.$emit("update-team-collections")
}
},
expandCollection(collectionID) {
this.$emit("expand-collection", collectionID)
},
removeRequest({ collectionIndex, folderName, requestIndex }) {
this.$emit("remove-request", {
collectionIndex,
folderName,
requestIndex,
})
},
},
}
</script>

View File

@@ -1,128 +0,0 @@
<template>
<div>
<div class="transition duration-150 ease-in-out row-wrapper">
<div>
<button
v-tooltip="!doc ? $t('use_request') : ''"
class="icon"
@click="!doc ? selectRequest() : {}"
>
<i v-if="isSelected" class="mx-3 text-green-400 material-icons"
>check_circle</i
>
<span v-else :class="getRequestLabelColor(request.method)">{{
request.method
}}</span>
<span>{{ request.name }}</span>
</button>
</div>
<v-popover v-if="!saveRequest">
<button
v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
v-tooltip="$t('more')"
class="tooltip-target icon"
>
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="
$emit('edit-request', {
collectionIndex,
folderIndex,
folderName,
request,
requestIndex,
})
"
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_request')"
@hide-modal="confirmRemove = false"
@resolve="removeRequest"
/>
</div>
</template>
<script>
export default {
props: {
request: { type: Object, default: () => {} },
collectionIndex: { type: Number, default: null },
folderIndex: { type: Number, default: null },
folderName: { type: String, default: null },
// eslint-disable-next-line vue/require-default-prop
requestIndex: [Number, String],
doc: Boolean,
saveRequest: Boolean,
collectionsType: { type: Object, default: () => {} },
picked: { type: Object, default: () => {} },
},
data() {
return {
dragging: false,
requestMethodLabels: {
get: "text-green-400",
post: "text-yellow-400",
put: "text-blue-400",
delete: "text-red-400",
default: "text-gray-400",
},
confirmRemove: false,
}
},
computed: {
isSelected() {
return (
this.picked &&
this.picked.pickedType === "teams-request" &&
this.picked.requestID === this.requestIndex
)
},
},
methods: {
selectRequest() {
if (this.$props.saveRequest)
this.$emit("select", {
picked: {
pickedType: "teams-request",
requestID: this.requestIndex,
},
})
else
this.$store.commit("postwoman/selectRequest", { request: this.request })
},
removeRequest() {
this.$emit("remove-request", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folderName,
requestIndex: this.$props.requestIndex,
})
},
getRequestLabelColor(method) {
return (
this.requestMethodLabels[method.toLowerCase()] ||
this.requestMethodLabels.default
)
},
},
}
</script>

View File

@@ -1,39 +0,0 @@
<template>
<div class="folder">
<h3>
<i class="material-icons">folder_open</i>
{{ folder.name || $t("none") }}
</h3>
<div v-for="(subFolder, index) in folder.folders" :key="index">
<DocsFolder :folder="subFolder" />
</div>
<div v-for="(request, index) in folder.requests" :key="index">
<DocsRequest :request="request" />
</div>
</div>
</template>
<script>
export default {
props: {
folder: { type: Object, default: () => {} },
},
}
</script>
<style lang="scss" scoped>
.folder {
@apply flex;
@apply flex-col;
@apply justify-center;
@apply flex-1;
@apply p-4;
@apply border-l;
@apply border-brdColor;
@apply mt-4;
.material-icons {
@apply mr-4;
}
}
</style>

View File

@@ -1,153 +0,0 @@
<template>
<div class="request">
<h4>
<i class="material-icons">insert_drive_file</i>
{{ request.name || $t("none") }}
</h4>
<p v-if="request.url" class="doc-desc">
<span>
{{ $t("url") }}: <code>{{ request.url || $t("none") }}</code>
</span>
</p>
<p v-if="request.path" class="doc-desc">
<span>
{{ $t("path") }}:
<code>{{ request.path || $t("none") }}</code>
</span>
</p>
<p v-if="request.method" class="doc-desc">
<span>
{{ $t("method") }}:
<code>{{ request.method || $t("none") }}</code>
</span>
</p>
<p v-if="request.auth" class="doc-desc">
<span>
{{ $t("authentication") }}:
<code>{{ request.auth || $t("none") }}</code>
</span>
</p>
<p v-if="request.httpUser" class="doc-desc">
<span>
{{ $t("username") }}:
<code>{{ request.httpUser || $t("none") }}</code>
</span>
</p>
<p v-if="request.httpPassword" class="doc-desc">
<span>
{{ $t("password") }}:
<code>{{ request.httpPassword || $t("none") }}</code>
</span>
</p>
<p v-if="request.bearerToken" class="doc-desc">
<span>
{{ $t("token") }}:
<code>{{ request.bearerToken || $t("none") }}</code>
</span>
</p>
<h4 v-if="request.headers">{{ $t("headers") }}</h4>
<span v-if="request.headers">
<p v-for="header in request.headers" :key="header.key" class="doc-desc">
<span>
{{ header.key || $t("none") }}:
<code>{{ header.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.params">{{ $t("parameters") }}</h4>
<span v-if="request.params">
<p
v-for="parameter in request.params"
:key="parameter.key"
class="doc-desc"
>
<span>
{{ parameter.key || $t("none") }}:
<code>{{ parameter.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.bodyParams">{{ $t("payload") }}</h4>
<span v-if="request.bodyParams">
<p
v-for="payload in request.bodyParams"
:key="payload.key"
class="doc-desc"
>
<span>
{{ payload.key || $t("none") }}:
<code>{{ payload.value || $t("none") }}</code>
</span>
</p>
</span>
<p v-if="request.rawParams" class="doc-desc">
<span>
{{ $t("parameters") }}:
<code>{{ request.rawParams || $t("none") }}</code>
</span>
</p>
<p v-if="request.contentType" class="doc-desc">
<span>
{{ $t("content_type") }}:
<code>{{ request.contentType || $t("none") }}</code>
</span>
</p>
<p v-if="request.requestType" class="doc-desc">
<span>
{{ $t("request_type") }}:
<code>{{ request.requestType || $t("none") }}</code>
</span>
</p>
</div>
</template>
<script>
export default {
props: {
request: { type: Object, default: () => {} },
},
}
</script>
<style scoped lang="scss">
.request {
@apply flex;
@apply flex-col;
@apply justify-center;
@apply flex-1;
@apply p-4;
@apply border;
@apply border-brdColor;
@apply rounded-lg;
@apply mt-4;
h4 {
@apply mt-4;
}
.material-icons {
@apply mr-4;
}
}
.doc-desc {
@apply flex;
@apply flex-col;
@apply justify-center;
@apply flex-1;
@apply p-4;
@apply text-fgLightColor;
@apply border-b;
@apply border-dashed;
@apply border-brdColor;
@apply m-0;
&:last-child {
@apply border-b-0;
}
.material-icons {
@apply mr-4;
}
}
</style>

View File

@@ -1,89 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("new_environment") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="$t('my_new_environment')"
@keyup.enter="addNewEnvironment"
/>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addNewEnvironment">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
show: Boolean,
},
data() {
return {
name: null,
}
},
subscriptions() {
return {
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
}
},
methods: {
syncEnvironments() {
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
)
}
},
addNewEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"))
return
}
const newEnvironment = [
{
name: this.$data.name,
variables: [],
},
]
this.$store.commit("postwoman/importAddEnvironments", {
environments: newEnvironment,
confirmation: "Environment added",
})
this.syncEnvironments()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,224 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("edit_environment") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
id="selectLabel"
v-model="name"
type="text"
:placeholder="editingEnvironment.name"
@keyup.enter="saveEnvironment"
/>
<div class="row-wrapper">
<label for="variableList">{{ $t("env_variable_list") }}</label>
<div>
<button
v-tooltip.bottom="$t('clear')"
class="icon"
@click="clearContent($event)"
>
<i class="material-icons">clear_all</i>
</button>
</div>
</div>
<ul
v-for="(variable, index) in editingEnvCopy.variables"
:key="index"
class="
border-b border-dashed
divide-y
md:divide-x
border-brdColor
divide-dashed divide-brdColor
md:divide-y-0
"
:class="{ 'border-t': index == 0 }"
>
<li>
<input
:placeholder="$t('variable_count', { count: index + 1 })"
:name="'param' + index"
:value="variable.key"
autofocus
@change="
$store.commit('postwoman/setVariableKey', {
index,
value: $event.target.value,
})
"
/>
</li>
<li>
<input
:placeholder="$t('value_count', { count: index + 1 })"
:name="'value' + index"
:value="
typeof variable.value === 'string'
? variable.value
: JSON.stringify(variable.value)
"
@change="
$store.commit('postwoman/setVariableValue', {
index,
value: $event.target.value,
})
"
/>
</li>
<div>
<li>
<button
id="variable"
v-tooltip.bottom="$t('delete')"
class="icon"
@click="removeEnvironmentVariable(index)"
>
<i class="material-icons">delete</i>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button class="icon" @click="addEnvironmentVariable">
<i class="material-icons">add</i>
<span>{{ $t("add_new") }}</span>
</button>
</li>
</ul>
</div>
<div slot="footer">
<div class="row-wrapper">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveEnvironment">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
show: Boolean,
editingEnvironment: { type: Object, default: () => {} },
editingEnvironmentIndex: { type: Number, default: null },
},
data() {
return {
name: null,
doneButton: '<i class="material-icons">done</i>',
}
},
subscriptions() {
return {
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
}
},
computed: {
editingEnvCopy() {
return this.$store.state.postwoman.editingEnvironment
},
variableString() {
const result = this.editingEnvCopy.variables
return result === "" ? "" : JSON.stringify(result)
},
},
watch: {
editingEnvironment() {
this.name =
this.$props.editingEnvironment && this.$props.editingEnvironment.name
? this.$props.editingEnvironment.name
: undefined
this.$store.commit(
"postwoman/setEditingEnvironment",
this.$props.editingEnvironment
)
},
},
methods: {
syncEnvironments() {
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
)
}
},
clearContent({ target }) {
this.$store.commit("postwoman/removeVariables", [])
target.innerHTML = this.doneButton
this.$toast.info(this.$t("cleared"), {
icon: "clear_all",
})
setTimeout(
() => (target.innerHTML = '<i class="material-icons">clear_all</i>'),
1000
)
},
addEnvironmentVariable() {
const value = { key: "", value: "" }
this.$store.commit("postwoman/addVariable", value)
this.syncEnvironments()
},
removeEnvironmentVariable(index) {
const variableIndex = index
const oldVariables = this.editingEnvCopy.variables.slice()
const newVariables = this.editingEnvCopy.variables.filter(
(_, index) => variableIndex !== index
)
this.$store.commit("postwoman/removeVariable", newVariables)
this.$toast.error(this.$t("deleted"), {
icon: "delete",
action: {
text: this.$t("undo"),
onClick: (_, toastObject) => {
this.$store.commit("postwoman/removeVariable", oldVariables)
toastObject.remove()
},
},
})
this.syncEnvironments()
},
saveEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"))
return
}
const environmentUpdated = {
...this.editingEnvCopy,
name: this.$data.name,
}
this.$store.commit("postwoman/saveEnvironment", {
environment: environmentUpdated,
environmentIndex: this.$props.editingEnvironmentIndex,
})
this.syncEnvironments()
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,79 +0,0 @@
<template>
<div>
<div class="row-wrapper">
<div>
<button class="icon" @click="$emit('edit-environment')">
<i class="material-icons">layers</i>
<span>{{ environment.name }}</span>
</button>
</div>
<v-popover>
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="$emit('edit-environment')"
>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="confirmRemove = true">
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_environment')"
@hide-modal="confirmRemove = false"
@resolve="removeEnvironment"
/>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
environment: { type: Object, default: () => {} },
environmentIndex: { type: Number, default: null },
},
data() {
return {
confirmRemove: false,
}
},
subscriptions() {
return {
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
}
},
methods: {
syncEnvironments() {
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
)
}
},
removeEnvironment() {
this.$store.commit("postwoman/removeEnvironment", this.environmentIndex)
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
this.syncEnvironments()
},
},
}
</script>

View File

@@ -1,303 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">
{{ $t("import_export") }} {{ $t("environments") }}
</h3>
<div>
<v-popover>
<button v-tooltip.left="$t('more')" class="tooltip-target icon">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
class="icon"
@click="readEnvironmentGist"
>
<i class="material-icons">assignment_returned</i>
<span>{{ $t("import_from_gist") }}</span>
</button>
</div>
<div
v-tooltip.bottom="{
content: !fb.currentUser
? $t('login_with_github_to') + $t('create_secret_gist')
: fb.currentUser.provider !== 'github.com'
? $t('login_with_github_to') + $t('create_secret_gist')
: null,
}"
>
<button
v-close-popover
:disabled="
!fb.currentUser
? true
: fb.currentUser.provider !== 'github.com'
? true
: false
"
class="icon"
@click="createEnvironmentGist"
>
<i class="material-icons">assignment_turned_in</i>
<span>{{ $t("create_secret_gist") }}</span>
</button>
</div>
</template>
</v-popover>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
<div slot="body" class="flex flex-col">
<div class="flex flex-col items-start p-2">
<span
v-tooltip="{
content: !fb.currentUser
? $t('login_first')
: $t('replace_current'),
}"
>
<button
:disabled="!fb.currentUser"
class="icon"
@click="syncEnvironments"
>
<i class="material-icons">folder_shared</i>
<span>{{ $t("import_from_sync") }}</span>
</button>
</span>
<button
v-tooltip="$t('replace_current')"
class="icon"
@click="openDialogChooseFileToReplaceWith"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("replace_json") }}</span>
<input
ref="inputChooseFileToReplaceWith"
type="file"
style="display: none"
accept="application/json"
@change="replaceWithJSON"
/>
</button>
<button
v-tooltip="$t('preserve_current')"
class="icon"
@click="openDialogChooseFileToImportFrom"
>
<i class="material-icons">folder_special</i>
<span>{{ $t("import_json") }}</span>
<input
ref="inputChooseFileToImportFrom"
type="file"
style="display: none"
accept="application/json"
@change="importFromJSON"
/>
</button>
</div>
<div v-if="showJsonCode" class="row-wrapper">
<textarea v-model="environmentJson" rows="8" readonly></textarea>
</div>
</div>
<div slot="footer">
<div class="row-wrapper">
<span>
<SmartToggle :on="showJsonCode" @change="showJsonCode = $event">
{{ $t("show_code") }}
</SmartToggle>
</span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button
v-tooltip="$t('download_file')"
class="icon primary"
@click="exportJSON"
>
{{ $t("export") }}
</button>
</span>
</div>
</div>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
show: Boolean,
},
data() {
return {
fb,
showJsonCode: false,
}
},
subscriptions() {
return {
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
}
},
computed: {
environmentJson() {
return JSON.stringify(this.$store.state.postwoman.environments, null, 2)
},
},
methods: {
async createEnvironmentGist() {
await this.$axios
.$post(
"https://api.github.com/gists",
{
files: {
"hoppscotch-environments.json": {
content: this.environmentJson,
},
},
},
{
headers: {
Authorization: `token ${fb.currentUser.accessToken}`,
Accept: "application/vnd.github.v3+json",
},
}
)
.then((res) => {
this.$toast.success(this.$t("gist_created"), {
icon: "done",
})
window.open(res.html_url)
})
.catch((error) => {
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error",
})
console.log(error)
})
},
async readEnvironmentGist() {
const gist = prompt(this.$t("enter_gist_url"))
if (!gist) return
await this.$axios
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
headers: {
Accept: "application/vnd.github.v3+json",
},
})
.then(({ files }) => {
const environments = JSON.parse(Object.values(files)[0].content)
this.$store.commit("postwoman/replaceEnvironments", environments)
this.fileImported()
this.syncToFBEnvironments()
})
.catch((error) => {
this.failedImport()
console.log(error)
})
},
hideModal() {
this.$emit("hide-modal")
},
openDialogChooseFileToReplaceWith() {
this.$refs.inputChooseFileToReplaceWith.click()
},
openDialogChooseFileToImportFrom() {
this.$refs.inputChooseFileToImportFrom.click()
},
replaceWithJSON() {
const reader = new FileReader()
reader.onload = ({ target }) => {
const content = target.result
const environments = JSON.parse(content)
this.$store.commit("postwoman/replaceEnvironments", environments)
}
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0])
this.fileImported()
this.syncToFBEnvironments()
this.$refs.inputChooseFileToReplaceWith.value = ""
},
importFromJSON() {
const reader = new FileReader()
reader.onload = ({ target }) => {
const content = target.result
const importFileObj = JSON.parse(content)
if (
importFileObj._postman_variable_scope === "environment" ||
importFileObj._postman_variable_scope === "globals"
) {
this.importFromPostman(importFileObj)
} else {
this.importFromPostwoman(importFileObj)
}
}
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0])
this.syncToFBEnvironments()
this.$refs.inputChooseFileToImportFrom.value = ""
},
importFromPostwoman(environments) {
const confirmation = this.$t("file_imported")
this.$store.commit("postwoman/importAddEnvironments", {
environments,
confirmation,
})
},
importFromPostman({ name, values }) {
const environment = { name, variables: [] }
values.forEach(({ key, value }) =>
environment.variables.push({ key, value })
)
const environments = [environment]
this.importFromPostwoman(environments)
},
exportJSON() {
let text = this.environmentJson
text = text.replace(/\n/g, "\r\n")
const blob = new Blob([text], {
type: "text/json",
})
const anchor = document.createElement("a")
anchor.download = "hoppscotch-environment.json"
anchor.href = window.URL.createObjectURL(blob)
anchor.target = "_blank"
anchor.style.display = "none"
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
this.$toast.success(this.$t("download_started"), {
icon: "done",
})
},
syncEnvironments() {
this.$store.commit(
"postwoman/replaceEnvironments",
fb.currentEnvironments
)
this.fileImported()
},
syncToFBEnvironments() {
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
)
}
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
icon: "folder_shared",
})
},
},
}
</script>

View File

@@ -1,190 +0,0 @@
<template>
<AppSection
ref="environments"
icon="history"
:label="$t('environments')"
no-legend
>
<div class="show-on-large-screen">
<span class="select-wrapper">
<select
v-model="selectedEnvironmentIndex"
:disabled="environments.length == 0"
class="rounded-t-lg"
>
<option :value="-1">No environment</option>
<option v-if="environments.length === 0" value="0">
{{ $t("create_new_environment") }}
</option>
<option
v-for="(environment, index) in environments"
:key="index"
:value="index"
>
{{ environment.name }}
</option>
</select>
</span>
</div>
<EnvironmentsAdd
:show="showModalAdd"
@hide-modal="displayModalAdd(false)"
/>
<EnvironmentsEdit
:show="showModalEdit"
:editing-environment="editingEnvironment"
:editing-environment-index="editingEnvironmentIndex"
@hide-modal="displayModalEdit(false)"
/>
<EnvironmentsImportExport
:show="showModalImportExport"
@hide-modal="displayModalImportExport(false)"
/>
<div class="border-b row-wrapper border-brdColor">
<div>
<button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i>
<span>{{ $t("new") }}</span>
</button>
</div>
<div>
<button class="icon" @click="displayModalImportExport(true)">
{{ $t("import_export") }}
</button>
</div>
</div>
<p v-if="environments.length === 0" class="info">
<i class="material-icons">help_outline</i>
{{ $t("create_new_environment") }}
</p>
<div class="virtual-list">
<ul class="flex-col">
<li
v-for="(environment, index) in environments"
:key="environment.name"
>
<EnvironmentsEnvironment
:environment-index="index"
:environment="environment"
@edit-environment="editEnvironment(environment, index)"
/>
</li>
</ul>
</div>
</AppSection>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
export default {
data() {
return {
showModalImportExport: false,
showModalAdd: false,
showModalEdit: false,
editingEnvironment: undefined,
editingEnvironmentIndex: undefined,
selectedEnvironmentIndex: -1,
defaultEnvironment: {
name: "My Environment Variables",
variables: [],
},
}
},
subscriptions() {
return {
SYNC_ENVIRONMENTS: getSettingSubject("syncEnvironments"),
}
},
computed: {
environments() {
return fb.currentUser !== null
? fb.currentEnvironments
: this.$store.state.postwoman.environments
},
},
watch: {
selectedEnvironmentIndex(val) {
if (val === -1)
this.$emit("use-environment", {
environment: this.defaultEnvironment,
environments: this.environments,
})
else
this.$emit("use-environment", {
environment: this.environments[val],
environments: this.environments,
})
},
environments: {
handler({ length }) {
if (length === 0) {
this.selectedEnvironmentIndex = -1
this.$emit("use-environment", {
environment: this.defaultEnvironment,
environments: this.environments,
})
} else if (this.environments[this.selectedEnvironmentIndex])
this.$emit("use-environment", {
environment: this.environments[this.selectedEnvironmentIndex],
environments: this.environments,
})
else this.selectedEnvironmentIndex = -1
},
},
},
mounted() {
this._keyListener = function (e) {
if (e.key === "Escape") {
e.preventDefault()
this.showModalImportExport =
this.showModalAdd =
this.showModalEdit =
false
}
}
document.addEventListener("keydown", this._keyListener.bind(this))
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener)
},
methods: {
displayModalAdd(shouldDisplay) {
this.showModalAdd = shouldDisplay
},
displayModalEdit(shouldDisplay) {
this.showModalEdit = shouldDisplay
if (!shouldDisplay) this.resetSelectedData()
},
displayModalImportExport(shouldDisplay) {
this.showModalImportExport = shouldDisplay
},
editEnvironment(environment, environmentIndex) {
this.$data.editingEnvironment = environment
this.$data.editingEnvironmentIndex = environmentIndex
this.displayModalEdit(true)
this.syncEnvironments()
},
resetSelectedData() {
this.$data.editingEnvironment = undefined
this.$data.editingEnvironmentIndex = undefined
},
syncEnvironments() {
if (fb.currentUser !== null && this.SYNC_ENVIRONMENTS) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
)
}
},
},
}
</script>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 270px);
}
</style>

View File

@@ -1,62 +0,0 @@
<template>
<div
v-if="fb.currentFeeds.length !== 0"
class="divide-y virtual-list divide-dashed divide-brdColor"
>
<ul v-for="feed in fb.currentFeeds" :key="feed.id" class="flex-col">
<div data-test="list-item" class="show-on-large-screen">
<li class="info">
<label data-test="list-label">
{{ feed.label || $t("no_label") }}
</label>
</li>
<button class="icon" @click="deleteFeed(feed)">
<i class="material-icons">delete</i>
</button>
</div>
<div class="show-on-large-screen">
<li data-test="list-message" class="info clamb-3">
<label>{{ feed.message || $t("empty") }}</label>
</li>
</div>
</ul>
</div>
<ul v-else class="flex-col">
<li>
<p class="info">{{ $t("empty") }}</p>
</li>
</ul>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
data() {
return {
fb,
}
},
methods: {
async deleteFeed({ id }) {
await fb.deleteFeed(id)
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
},
},
}
</script>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 270px);
}
.clamb-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
@apply overflow-hidden;
}
</style>

View File

@@ -1,57 +0,0 @@
<template>
<div class="flex-col">
<div class="show-on-large-screen">
<input
v-model="message"
:aria-label="$t('label')"
type="text"
autofocus
:placeholder="$t('paste_a_note')"
class="rounded-t-lg"
@keyup.enter="formPost"
/>
</div>
<div class="border-b show-on-large-screen border-brdColor">
<input
v-model="label"
:aria-label="$t('label')"
type="text"
autofocus
:placeholder="$t('label')"
@keyup.enter="formPost"
/>
<button
class="icon"
:disabled="!(message || label)"
value="Save"
@click="formPost"
>
<i class="material-icons">add</i>
<span>Add</span>
</button>
</div>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
data() {
return {
message: null,
label: null,
}
},
methods: {
formPost() {
if (!(this.message || this.label)) {
return
}
fb.writeFeeds(this.message, this.label)
this.message = null
this.label = null
},
},
}
</script>

View File

@@ -1,198 +0,0 @@
<template>
<div>
<div>
<button v-close-popover class="icon" @click="signInWithGoogle">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
class="material-icons"
>
<path
d="M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z"
/>
</svg>
<span>Google</span>
</button>
</div>
<div>
<button v-close-popover class="icon" @click="signInWithGithub">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
class="material-icons"
>
<path
d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"
/>
</svg>
<span>GitHub</span>
</button>
</div>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
data() {
return {
fb,
}
},
methods: {
showLoginSuccess() {
this.$toast.info(this.$t("login_success"), {
icon: "vpn_key",
})
},
async signInWithGoogle() {
try {
const { additionalUserInfo } = await fb.signInUserWithGoogle()
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (_, toastObject) => {
fb.writeSettings("syncHistory", true)
fb.writeSettings("syncCollections", true)
fb.writeSettings("syncEnvironments", true)
this.$router.push({ path: "/settings" })
toastObject.remove()
},
},
})
}
this.showLoginSuccess()
} catch (err) {
console.log(err)
// An error happened.
if (err.code === "auth/account-exists-with-different-credential") {
// Step 2.
// User's email already exists.
// The pending Google credential.
const pendingCred = err.credential
// The provider account's email address.
const email = err.email
// Get sign-in methods for this email.
const methods = await fb.getSignInMethodsForEmail(email)
// Step 3.
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (methods[0] === "password") {
// Asks the user their password.
// In real scenario, you should handle this asynchronously.
const password = promptUserForPassword() // TODO: implement promptUserForPassword.
const user = await fb.signInWithEmailAndPassword(email, password)
await user.linkWithCredential(pendingCred)
this.showLoginSuccess()
return
}
this.$toast.info(`${this.$t("account_exists")}`, {
icon: "vpn_key",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: async (_, toastObject) => {
const { user } = await fb.signInWithGithub()
await user.linkAndRetrieveDataWithCredential(pendingCred)
this.showLoginSuccess()
toastObject.remove()
},
},
})
}
}
},
async signInWithGithub() {
try {
const { credential, additionalUserInfo } =
await fb.signInUserWithGithub()
fb.setProviderInfo(credential.providerId, credential.accessToken)
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (_, toastObject) => {
fb.writeSettings("syncHistory", true)
fb.writeSettings("syncCollections", true)
fb.writeSettings("syncEnvironments", true)
this.$router.push({ path: "/settings" })
toastObject.remove()
},
},
})
}
this.showLoginSuccess()
} catch (err) {
console.log(err)
// An error happened.
if (err.code === "auth/account-exists-with-different-credential") {
// Step 2.
// User's email already exists.
// The pending Google credential.
const pendingCred = err.credential
// The provider account's email address.
const email = err.email
// Get sign-in methods for this email.
const methods = await fb.getSignInMethodsForEmail(email)
// Step 3.
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (methods[0] === "password") {
// Asks the user their password.
// In real scenario, you should handle this asynchronously.
const password = promptUserForPassword() // TODO: implement promptUserForPassword.
const user = await fb.signInWithEmailAndPassword(email, password)
await user.linkWithCredential(pendingCred)
this.showLoginSuccess()
return
}
this.$toast.info(`${this.$t("account_exists")}`, {
icon: "vpn_key",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: async (_, toastObject) => {
const { user } = await fb.signInUserWithGoogle()
await user.linkAndRetrieveDataWithCredential(pendingCred)
this.showLoginSuccess()
toastObject.remove()
},
},
})
}
}
},
},
}
</script>

View File

@@ -1,35 +0,0 @@
<template>
<div>
<button v-close-popover class="icon" @click="logout">
<i class="material-icons">exit_to_app</i>
<span>{{ $t("logout") }}</span>
</button>
</div>
</template>
<script>
import { fb } from "~/helpers/fb"
export default {
data() {
return {
fb,
}
},
methods: {
async logout() {
try {
await fb.signOutUser()
this.$toast.info(this.$t("logged_out"), {
icon: "vpn_key",
})
} catch (err) {
this.$toast.show(err.message || err, {
icon: "error",
})
}
},
},
}
</script>

View File

@@ -1,132 +0,0 @@
import { shallowMount } from "@vue/test-utils"
import feeds from "../Feeds"
import { fb } from "~/helpers/fb"
jest.mock("~/helpers/fb", () => ({
__esModule: true,
fb: {
currentFeeds: [
{
id: "test1",
label: "First",
message: "First Message",
},
{
id: "test2",
label: "Second",
},
{
id: "test3",
message: "Third Message",
},
{
id: "test4",
},
],
deleteFeed: jest.fn(() => Promise.resolve()),
},
}))
const factory = () =>
shallowMount(feeds, {
mocks: {
$t: (text) => text,
$toast: {
error: jest.fn(),
},
},
})
beforeEach(() => {
fb.deleteFeed.mockClear()
})
describe("feeds", () => {
test("mounts properly when proper components are given", () => {
const wrapper = factory()
expect(wrapper).toBeTruthy()
})
test("renders all the current feeds", () => {
const wrapper = factory()
expect(wrapper.findAll("div[data-test='list-item']").wrappers).toHaveLength(
4
)
})
test("feeds with no label displays the 'no_label' message", () => {
const wrapper = factory()
expect(
wrapper
.findAll("label[data-test='list-label']")
.wrappers.map((e) => e.text())
.filter((text) => text === "no_label")
).toHaveLength(2)
})
test("feeds with no message displays the 'empty' message", () => {
const wrapper = factory()
expect(
wrapper
.findAll("li[data-test='list-message']")
.wrappers.map((e) => e.text())
.filter((text) => text === "empty")
).toHaveLength(2)
})
test("labels in the list are proper", () => {
const wrapper = factory()
expect(
wrapper
.findAll("label[data-test='list-label']")
.wrappers.map((e) => e.text())
).toEqual(["First", "Second", "no_label", "no_label"])
})
test("messages in the list are proper", () => {
const wrapper = factory()
expect(
wrapper
.findAll("li[data-test='list-message']")
.wrappers.map((e) => e.text())
).toEqual(["First Message", "empty", "Third Message", "empty"])
})
test("clicking on the delete button deletes the feed", async () => {
const wrapper = factory()
const deleteButton = wrapper.find("button")
await deleteButton.trigger("click")
expect(fb.deleteFeed).toHaveBeenCalledTimes(1)
})
test("correct feed is passed to from the list for deletion", async () => {
const wrapper = factory()
const deleteButton = wrapper.find("button")
await deleteButton.trigger("click")
expect(fb.deleteFeed).toHaveBeenCalledWith("test1")
})
test("renders the 'empty' label if no elements in the current feeds", () => {
jest.spyOn(fb, "currentFeeds", "get").mockReturnValueOnce([])
const wrapper = factory()
expect(wrapper.findAll("li").wrappers).toHaveLength(1)
expect(wrapper.find("li").text()).toEqual("empty")
})
})

View File

@@ -1,92 +0,0 @@
import { shallowMount } from "@vue/test-utils"
import inputform from "../Inputform"
import { fb } from "~/helpers/fb"
jest.mock("~/helpers/fb", () => ({
__esModule: true,
fb: {
writeFeeds: jest.fn(() => Promise.resolve()),
},
}))
const factory = () =>
shallowMount(inputform, {
mocks: {
$t: (text) => text,
},
})
beforeEach(() => {
fb.writeFeeds.mockClear()
})
describe("inputform", () => {
test("mounts properly", () => {
const wrapper = factory()
expect(wrapper).toBeTruthy()
})
test("calls writeFeeds when submitted properly", async () => {
const wrapper = factory()
const addButton = wrapper.find("button")
const [messageInput, labelInput] = wrapper.findAll("input").wrappers
await messageInput.setValue("test message")
await labelInput.setValue("test label")
await addButton.trigger("click")
expect(fb.writeFeeds).toHaveBeenCalledTimes(1)
})
test("doesn't call writeFeeds when submitted without a data", async () => {
const wrapper = factory()
const addButton = wrapper.find("button")
await addButton.trigger("click")
expect(fb.writeFeeds).not.toHaveBeenCalled()
})
test("doesn't call writeFeeds when message or label is null", async () => {
const wrapper = factory()
const addButton = wrapper.find("button")
const [messageInput, labelInput] = wrapper.findAll("input").wrappers
await messageInput.setValue(null)
await labelInput.setValue(null)
await addButton.trigger("click")
expect(fb.writeFeeds).not.toHaveBeenCalled()
})
test("doesn't call writeFeeds when message or label is empty", async () => {
const wrapper = factory()
const addButton = wrapper.find("button")
const [messageInput, labelInput] = wrapper.findAll("input").wrappers
await messageInput.setValue("")
await labelInput.setValue("")
await addButton.trigger("click")
expect(fb.writeFeeds).not.toHaveBeenCalled()
})
test("calls writeFeeds with correct values", async () => {
const wrapper = factory()
const addButton = wrapper.find("button")
const [messageInput, labelInput] = wrapper.findAll("input").wrappers
await messageInput.setValue("test message")
await labelInput.setValue("test label")
await addButton.trigger("click")
expect(fb.writeFeeds).toHaveBeenCalledWith("test message", "test label")
})
})

View File

@@ -1,67 +0,0 @@
import { shallowMount, createLocalVue } from "@vue/test-utils"
import logout from "../Logout"
import { fb } from "~/helpers/fb"
jest.mock("~/helpers/fb", () => ({
__esModule: true,
fb: {
signOutUser: jest.fn(() => Promise.resolve()),
},
}))
const $toast = {
info: jest.fn(),
show: jest.fn(),
}
const localVue = createLocalVue()
localVue.directive("close-popover", {})
const factory = () =>
shallowMount(logout, {
mocks: {
$t: (text) => text,
$toast,
},
localVue,
})
beforeEach(() => {
fb.signOutUser.mockClear()
$toast.info.mockClear()
$toast.show.mockClear()
})
describe("logout", () => {
test("mounts properly", () => {
const wrapper = factory()
expect(wrapper).toBeTruthy()
})
test("clicking the logout button fires the logout firebase function", async () => {
const wrapper = factory()
const button = wrapper.find("button")
await button.trigger("click")
expect(fb.signOutUser).toHaveBeenCalledTimes(1)
})
test("failed signout request fires a error toast", async () => {
fb.signOutUser.mockImplementationOnce(() =>
Promise.reject(new Error("test reject"))
)
const wrapper = factory()
const button = wrapper.find("button")
await button.trigger("click")
expect($toast.show).toHaveBeenCalledTimes(1)
expect($toast.show).toHaveBeenCalledWith("test reject", expect.anything())
})
})

View File

@@ -1,244 +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 { defineGQLLanguageMode } from "~/helpers/syntax/gqlQueryLangMode"
import debounce from "~/helpers/utils/debounce"
export default {
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,
}
},
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
})
})
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("gql_prettify_invalid_query")}`, {
icon: "error",
})
}
},
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,62 +0,0 @@
import { mount } from "@vue/test-utils"
import RestCard from "../rest/Card"
const factory = (props) => {
return mount(RestCard, {
propsData: props,
stubs: {
"v-popover": {
template: "<div><slot /><slot name='popover' :is-open=true /></div>",
},
},
mocks: {
$t: (text) => text,
},
directives: {
tooltip() {
/* stub */
},
closePopover() {
/* stub */
},
},
})
}
const url = "https://dummydata.com/get"
const entry = {
type: "rest",
url,
method: "GET",
status: 200,
star: false,
}
describe("RestCard", () => {
test("Mounts properly if props are given", () => {
const wrapper = factory({ entry })
expect(wrapper).toBeTruthy()
})
test("toggle-star emitted on clicking on star button", () => {
const wrapper = factory({ entry })
wrapper.find("button[data-testid='star_button']").trigger("click")
expect(wrapper.emitted("toggle-star")).toBeTruthy()
})
test("use-entry emit on clicking the restore button", async () => {
const wrapper = factory({ entry })
await wrapper
.find("button[data-testid='restore_history_entry']")
.trigger("click")
expect(wrapper.emitted("use-entry")).toBeTruthy()
})
test("delete-entry emit on clicking the delete button", async () => {
const wrapper = factory({ entry })
await wrapper
.find("button[data-testid=delete_history_entry]")
.trigger("click")
expect(wrapper.emitted("delete-entry")).toBeTruthy()
})
})

View File

@@ -1,159 +0,0 @@
<template>
<div>
<div class="show-on-large-screen">
<li>
<input
data-testid="'url'"
:aria-label="$t('url')"
type="text"
readonly
:value="entry.url"
:placeholder="$t('empty_req_name')"
class="bg-transparent"
/>
</li>
<button
v-tooltip="{
content: !entry.star ? $t('add_star') : $t('remove_star'),
}"
data-testid="star_button"
class="icon"
:class="{ stared: entry.star }"
@click="$emit('toggle-star')"
>
<i class="material-icons">
{{ entry.star ? "star" : "star_border" }}
</i>
</button>
<button
v-tooltip="{
content: expand ? $t('hide_more') : $t('show_more'),
}"
data-testid="query_expand"
class="icon"
@click="expand = !expand"
>
<i class="material-icons">
{{ expand ? "unfold_less" : "unfold_more" }}
</i>
</button>
<v-popover>
<button
v-tooltip="$t('options')"
data-testid="options"
class="tooltip-target icon"
>
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
v-close-popover
data-testid="restore_history_entry"
class="icon"
:aria-label="$t('restore')"
@click="$emit('use-entry')"
>
<i class="material-icons">restore</i>
<span>{{ $t("restore") }}</span>
</button>
</div>
<div>
<button
v-close-popover
data-testid="delete_history_entry"
class="icon"
:aria-label="$t('delete')"
@click="$emit('delete-entry')"
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div class="show-on-large-screen">
<li data-testid="'query'">
<input
v-for="(line, index) in query"
:key="`line-${index}`"
:aria-label="$t('query')"
type="text"
readonly
:value="`${line}`"
class="pt-0 mt-0 text-sm bg-transparent text-fgLightColor"
/>
</li>
</div>
<transition name="fade">
<div v-if="showMore" class="show-on-large-screen">
<li>
<input
v-tooltip="entry.date"
:aria-label="$t('time')"
type="text"
readonly
:value="entry.time"
class="pt-0 mt-0 text-sm bg-transparent text-fgLightColor"
/>
</li>
<li>
<input
:aria-label="$t('duration')"
type="text"
readonly
:value="`Duration: ${entry.duration}ms`"
:placeholder="$t('no_duration')"
class="pt-0 mt-0 text-sm bg-transparent text-fgLightColor"
/>
</li>
<!-- <li>
<input
:aria-label="$t('prerequest_script')"
type="text"
readonly
:value="entry.preRequestScript"
:placeholder="$t('no_prerequest_script')"
class="pt-0 mt-0 text-sm bg-transparent text-fgLightColor"
/>
</li> -->
</div>
</transition>
</div>
</template>
<script>
export default {
props: {
entry: { type: Object, default: () => {} },
showMore: Boolean,
},
data() {
return {
expand: false,
}
},
computed: {
query() {
return this.expand
? this.entry.query.split("\n")
: this.entry.query.split("\n").slice(0, 2).concat(["..."])
},
},
}
</script>
<style scoped lang="scss">
.stared {
color: #f8e81c !important;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>

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