Compare commits

...

555 Commits

Author SHA1 Message Date
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
Liyas Thomas
a795fc4310 release: v1.12.0 2021-05-27 15:11:01 +00:00
Liyas Thomas
790b743e42 fix: copy .env to root - fixed #1671 2021-05-27 14:08:21 +00:00
Andrew Bastin
21aeded2ea Update DispatchingStore to provide better typing for dispatch function parameters 2021-05-25 18:27:50 -04:00
liyasthomas
baf6d6bd29 refactor: lint options 2021-05-25 21:43:13 +05:30
Andrew Bastin
2e213a8692 Remove History test spec 2021-05-24 23:37:48 -04:00
Andrew Bastin
455cccebb5 Fix issue with clear history confirmation persisting after clearing 2021-05-24 23:37:48 -04:00
Andrew Bastin
9e602394cf Remove dependency on history component to add history entry 2021-05-24 23:37:48 -04:00
Andrew Bastin
46ebd49936 Refactor history entry limits 2021-05-24 23:37:48 -04:00
Andrew Bastin
fcac750ad7 Migrate code to new history store 2021-05-24 23:37:48 -04:00
Andrew Bastin
8cd3acd205 Introduce History store 2021-05-24 23:37:48 -04:00
liyasthomas
bc95a028ce chore(deps): bump 2021-05-23 18:48:48 +05:30
Andrew Bastin
5fb457d331 Fix Settings Sync issues 2021-05-22 21:48:15 -04:00
liyasthomas
454c11a12c chore: lint 2021-05-22 20:50:23 +05:30
Andrew Bastin
3ac9a418e6 Defer ChooseType teams list query until component visible 2021-05-20 22:21:12 -04:00
liyasthomas
c98de5988e fix: clean input value in modals - fixed #1662 2021-05-20 14:24:14 +05:30
Andrew Bastin
ca5df588b7 Fix UrlField tests 2021-05-19 22:41:16 -04:00
Andrew Bastin
08a41691af Revamp URLField 2021-05-19 22:25:00 -04:00
Andrew Bastin
665f272a0e Stylelint updates 2021-05-19 22:24:31 -04:00
Andrew Bastin
2591e3ab67 Add node-interval-tree as dep 2021-05-19 22:23:47 -04:00
liyasthomas
44df9b3be8 refactor: lint 2021-05-19 10:24:57 +05:30
liyasthomas
40ddfa8def refactor: lint 2021-05-18 21:39:55 +05:30
liyasthomas
cc27c552af refactor: lint 2021-05-18 14:57:29 +05:30
liyasthomas
7f248da0b3 refactor: lint 2021-05-18 11:56:59 +05:30
Andrew Bastin
79a0002594 Load through server side pagination for team members list 2021-05-17 12:27:36 -04:00
Andrew Bastin
a6c015bcc5 Make ESLint happy with fb.js 2021-05-17 12:26:57 -04:00
Andrew Bastin
692d98cb55 Make ESLint a bit more forgiving 2021-05-17 12:26:25 -04:00
liyasthomas
d9ddc184cb refactor: lint 2021-05-17 19:17:57 +05:30
liyasthomas
e424d06026 refactor: lint 2021-05-17 17:11:58 +05:30
liyasthomas
f9821e5f80 feat: eslint for typescript 2021-05-17 15:17:23 +05:30
Liyas Thomas
5bd53dc093 feat: eslint + stylelint 2021-05-17 05:55:50 +00:00
Liyas Thomas
204834872e refector: remove unused components 2021-05-17 03:19:53 +00:00
liyasthomas
a24049aa17 fix: dotenv 2021-05-16 14:10:39 +05:30
liyasthomas
9cb9e9e7b6 fix: dotenv 2021-05-16 12:53:40 +05:30
liyasthomas
3e7a766d12 Merge branch 'main' of https://github.com/hoppscotch/hoppscotch 2021-05-16 12:23:45 +05:30
liyasthomas
02debdc28b fix: use .env values - fixed #1639 2021-05-16 12:23:29 +05:30
liyasthomas
e104fe3021 chore(deps): bump 2021-05-16 12:21:28 +05:30
Andrew Bastin
dda40537cc Don't update BackendUserInfo if not authenticated 2021-05-15 21:52:31 -04:00
liyasthomas
217269467c docs: updated sponsors list 2021-05-16 04:08:56 +05:30
Liyas Thomas
5f193680c9 fix: minor UI stylings 2021-05-15 21:19:23 +00:00
Liyas Thomas
c0ef713c0b i18n: add Hindi and Norwegian (Bokmål) language (#1642)
Co-authored-by: Sindre van der Linden <sindre@allvis.io>
Co-authored-by: Deven Rathod <devenrathod2001@gmail.com>
2021-05-15 06:23:12 -07:00
Liyas Thomas
3533aa391a chore: lint 2021-05-15 12:43:31 +00:00
Liyas Thomas
ec90365427 Merge pull request #1641 from hoppscotch/teams 2021-05-15 14:08:03 +05:30
Liyas Thomas
78f7a9ba06 chore(deps): lock file 2021-05-15 08:26:22 +00:00
Liyas Thomas
7793dd8b3e Merge branch 'main' into teams 2021-05-15 08:11:03 +00:00
Liyas Thomas
76866f78f0 cleanup: remove logs 2021-05-15 06:47:13 +00:00
Liyas Thomas
8e3ecb4c25 fix: save location picker indicator 2021-05-15 05:45:05 +00:00
Andrew Bastin
1b9b2ac4c9 Fix SaveRequest modal selection 2021-05-15 00:02:55 -04:00
Andrew Bastin
489f14b88f Fixed issue in TeamCollectionAdapter with request updates 2021-05-14 01:59:08 -04:00
Liyas Thomas
8f09c82763 fixes and refactor 2021-05-14 05:50:17 +00:00
Andrew Bastin
2b8cda40a2 Introduce TeamMemberAdapter 2021-05-14 00:08:52 -04:00
Liyas Thomas
4656d67fcf fix: teams edit modal + race conditions on currentUser 2021-05-14 03:40:53 +00:00
Andrew Bastin
e7dd67deaa Update race condition with Apollo getting ID Token and BackendUserInfo 2021-05-13 22:42:04 -04:00
Andrew Bastin
b9c3219094 Hide "Team Collections" tab if user has no access 2021-05-13 20:16:41 -04:00
Andrew Bastin
f55a995c0a Introducing BackendUserInfo 2021-05-13 20:16:29 -04:00
Andrew Bastin
ee378a128c Introduce observable function for team member list 2021-05-13 02:28:35 -04:00
Liyas Thomas
c1f083d19f fix: indicate selected location on save request 2021-05-13 04:26:33 +00:00
Liyas Thomas
2ff0f97295 refactor: request actions + fix: timeout bug 2021-05-12 05:33:15 +00:00
Andrew Bastin
dd3b51d0b7 Use Intersection component to fetch team list on visibility 2021-05-11 23:39:23 -04:00
Andrew Bastin
853acfda2c Introduce Intersection component 2021-05-11 23:38:47 -04:00
Liyas Thomas
c756be54a1 refactor: separate request components for team & my collections 2021-05-11 13:10:36 +00:00
Liyas Thomas
3bbf334f99 refactor: separate folders for team and personal collections 2021-05-11 05:49:36 +00:00
Liyas Thomas
c6c8b7da6a chore(deps): bump 2021-05-09 14:59:24 +00:00
Liyas Thomas
8a30d3ed42 refactor: separated my collections and tam collections 2021-05-09 07:48:52 +00:00
Andrew Bastin
a5a6b864a5 Fix issue with child collection not rerendering 2021-05-09 02:08:48 -04:00
Liyas Thomas
97b7320939 move collections actions to parent 2021-05-09 05:30:31 +00:00
Andrew Bastin
5c11bcb2c6 Update TeamCollectionAdapter with more docs 2021-05-06 21:22:17 -04:00
Andrew Bastin
3888584b58 Initial refactor of the collections list and friends 2021-05-06 20:46:29 -04:00
Andrew Bastin
531a9c0bc8 Update team_utils imports 2021-05-06 12:21:53 -04:00
Andrew Bastin
84f8048e0a Initial introduction of TeamCollectionAdapter based collection render 2021-05-06 12:06:19 -04:00
Andrew Bastin
fdf96b0b63 Fixed build time issue with TeamCollectionAdapter 2021-05-06 12:05:45 -04:00
Andrew Bastin
86ddfe2c9f Introduce TeamCollectionAdapter 2021-05-05 10:44:17 -04:00
Andrew Bastin
115ae93073 Merge pull request #1625 from iamtabrezkhan/issue-1507
FEAT: add syntax highlighting in Code Generator Modal
2021-05-04 22:57:45 -04:00
Andrew Bastin
aa65cada6f Merge branch 'main' into issue-1507 2021-05-04 22:44:11 -04:00
Andrew Bastin
ad9cdf3fa8 Update team/utils code style 2021-05-04 22:18:46 -04:00
Liyas Thomas
5c0035f4c3 chore(deps): bump 2021-05-04 19:36:50 +00:00
Liyas Thomas
37b4c67ead docs: updated sponsors list 2021-05-04 19:36:23 +00:00
Liyas Thomas
63998f4a23 minor UI styling 2021-05-04 14:02:19 +05:30
Liyas Thomas
efeec13794 set default export language as cURL 2021-05-03 19:14:26 -07:00
Liyas Thomas
6c49e5c86a fix: race condition where no language is selected 2021-05-03 19:12:13 -07:00
Andrew Bastin
ec57392424 Fixed subscriptions authorization 2021-05-03 09:57:58 -04:00
Andrew Bastin
8713aa7fd3 Remove @nuxtjs/apollo and added vue-apollo as dep 2021-05-03 09:22:39 -04:00
Andrew Bastin
627811f28d Refactor Apollo Client handling 2021-05-03 09:18:24 -04:00
Tabrez Khan
3f743b4f61 FEAT: add syntax highlighting in Code Generator Modal
USE: SmartAceEditor componenent
2021-05-03 14:46:41 +05:30
Liyas Thomas
d676b5a68d chore(deps): bump rxjs 2021-05-03 05:08:39 +00:00
Liyas Thomas
a6dfab5fbf chore(deps): bump 2021-05-02 15:21:27 +00:00
Liyas Thomas
b8bc110d33 check existance of teamCollectionAdded.parent
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-05-02 03:49:00 +00:00
Andrew Bastin
597fd2c6d1 Fix duplication on teams folder creation 2021-04-29 23:50:50 -04:00
Liyas Thomas
ab0bc3e927 fix: permissions for collections and folders 2021-04-30 01:04:41 +00:00
liyasthomas
e28373dae1 fixes
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2021-04-29 14:03:39 +05:30
Liyas Thomas
1bc57f159c merge feat/teams-new-ui
Co-authored-by: Isha Gupta <40794215+IshaGupta18@users.noreply.github.com>
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
Co-authored-by: Osheen Sachdev <45964755+oshhh@users.noreply.github.com>
Co-authored-by: Rohan Rajpal <rohan46000@gmail.com>
Co-authored-by: Raghav Gupta <raghav.gupta0307@gmail.com>
2021-04-26 09:37:18 +00:00
Liyas Thomas
6a8019c7a0 chore(deps): bump 2021-04-25 16:38:09 +00:00
Liyas Thomas
9b0dc5a849 Merge pull request #1615 from hoppscotch/feat/links 2021-04-23 04:46:54 -07:00
Liyas Thomas
283e1b0790 chore(deps): bump 2021-04-23 11:39:20 +00:00
Liyas Thomas
fc05a4bb78 docs: better copy 2021-04-23 11:38:56 +00:00
Liyas Thomas
88b32e317a docs: update links 2021-04-23 11:38:17 +00:00
Liyas Thomas
6c61a70d58 docs: updated built with stack, ideas for externship 2021-04-22 01:01:39 +00:00
Osheen Sachdev
5df3ebae22 Documentation generation (#1610)
Co-authored-by: Isha Gupta <40794215+IshaGupta18@users.noreply.github.com>
Co-authored-by: IshaGupta18 <ishagupta1828@gmail.com>
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2021-04-21 10:17:31 -07:00
Liyas Thomas
ad252476ce docs: update GitHub Externship guidelines 2021-04-20 11:20:01 +00:00
Liyas Thomas
8e5f6a3a96 GitHub Externship @ Hoppscotch 2021-04-20 10:37:46 +00:00
Liyas Thomas
9ff209bd32 Merge pull request #1608 from hoppscotch/dependabot/npm_and_yarn/ssri-6.0.2
chore(deps): bump ssri from 6.0.1 to 6.0.2
2021-04-19 09:27:15 -07:00
dependabot[bot]
505e61475d chore(deps): bump ssri from 6.0.1 to 6.0.2
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-19 16:22:02 +00:00
Liyas Thomas
2c137a0eec chore(deps): bump 2021-04-18 15:09:32 +00:00
Liyas Thomas
b65ae89be6 fix: respect environment variable in inline query parameters - fixed #1603 2021-04-15 10:04:23 +00:00
Liyas Thomas
432884a2af Select multiple collections (#1604) (#1605) 2021-04-15 01:01:15 -07:00
Osheen Sachdev
6878498b2e Fix folder nesting in document generation (#1602) 2021-04-14 17:54:55 -07:00
Jainal Gosaliya
4d5332fef7 fixes empty url bug during importing postman json (#1593)
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2021-04-13 21:44:50 -07:00
Andrew Bastin
50a149b662 Bump graphql-language-service-interface and fix build issues 2021-04-12 11:50:25 -04:00
Liyas Thomas
930838d676 chore(deps): bump 2021-04-12 08:14:19 +00:00
445 changed files with 90434 additions and 29554 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
}

View File

@@ -30,7 +30,7 @@ coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)

View File

@@ -1,4 +1,5 @@
# editorconfig.org
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
@@ -8,6 +9,3 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@@ -1,15 +1,18 @@
# Google Analytics
GA_ID=UA-XXXXXXXX-X
# Google Analytics ID
GA_ID=UA-61422507-4
# Google Tag Manager
GTM_ID=GTM-XXXXXXX
# Google Tag Manager ID
GTM_ID=GTM-NMKVBMV
# Firebase
API_KEY=api-key
AUTH_DOMAIN=project-id.firebaseapp.com
DATABASE_URL=https://project-id.firebaseio.com
PROJECT_ID=project-id
STORAGE_BUCKET=project-id.appspot.com
MESSAGING_SENDER_ID=sender-id
APP_ID=app-id
MEASUREMENT_ID=G-measurement-id
# Firebase config
API_KEY=AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM
AUTH_DOMAIN=postwoman-api.firebaseapp.com
DATABASE_URL=https://postwoman-api.firebaseio.com
PROJECT_ID=postwoman-api
STORAGE_BUCKET=postwoman-api.appspot.com
MESSAGING_SENDER_ID=421993993223
APP_ID=1:421993993223:web:ec0baa8ee8c02ffa1fc6a2
MEASUREMENT_ID=G-BBJ3R80PJT
# Base URL
BASE_URL=https://hoppscotch.io

67
.eslintrc.js Normal file
View File

@@ -0,0 +1,67 @@
module.exports = {
root: true,
env: {
browser: true,
node: true,
jest: true,
},
parserOptions: {
sourceType: "module",
requireConfigFile: false,
},
extends: [
"@nuxtjs",
"@nuxtjs/eslint-config-typescript",
"prettier/prettier",
"eslint:recommended",
"plugin:vue/recommended",
"plugin:prettier/recommended",
"plugin:nuxt/recommended",
],
plugins: ["vue", "prettier"],
// add your custom rules here
rules: {
semi: [2, "never"],
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
"vue/max-attributes-per-line": "off",
"vue/component-name-in-template-casing": ["error", "PascalCase"],
"vue/html-self-closing": [
"error",
{
html: {
normal: "never",
void: "always",
},
},
],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline": "off",
"vue/require-default-prop": "warn",
"vue/require-prop-types": "warn",
"prettier/prettier": ["warn", { semi: false }],
"import/no-named-as-default": "off",
"no-undef": "off",
// localStorage block
"no-restricted-globals": [
"error",
{
name: "localStorage",
message:
"Do not use 'localStorage' directly. Please use localpersistence.ts functions or stores",
},
],
// window.localStorage block
"no-restricted-syntax": [
"error",
{
selector: "CallExpression[callee.object.property.name='localStorage']",
message:
"Do not use 'localStorage' directly. Please use localpersistence.ts functions or stores",
},
],
},
globals: {
$nuxt: true,
},
}

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

@@ -31,15 +31,6 @@ jobs:
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
# 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
@@ -47,7 +38,7 @@ jobs:
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.
# 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

View File

@@ -0,0 +1,19 @@
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools
name: Deploy to Firebase Hosting on merge
'on':
push:
branches:
- main
jobs:
build_and_deploy:
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

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

@@ -0,0 +1,25 @@
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@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test

2
.gitignore vendored
View File

@@ -26,7 +26,7 @@ coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)

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

@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname $0)/_/husky.sh"
. "$(dirname "$0")/_/husky.sh"
npm run pretty-quick
npm run pre-commit

View File

@@ -4,4 +4,5 @@
.hoppscotch
.vscode
package-lock.json
node_modules
node_modules
dist

3
.prettierrc.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
semi: false
}

23
.stylelintrc.js Normal file
View File

@@ -0,0 +1,23 @@
module.exports = {
extends: ["stylelint-config-standard", "stylelint-config-prettier"],
// add your custom config here
// https://stylelint.io/user-guide/configuration
rules: {
"at-rule-no-unknown": [
true,
{
ignoreAtRules: [
"extends",
"apply",
"variants",
"responsive",
"screen",
"mixin",
"include",
],
},
],
"declaration-block-trailing-semicolon": null,
"no-descending-specificity": null,
},
}

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,5 +1,13 @@
# Changelog
## [v1.12.0](https://github.com/hoppscotch/hoppscotch/tree/v1.12.0) (2020-05-27)
[Full Changelog](https://github.com/hoppscotch/hoppscotch/compare/v1.10.0...v1.12.0)
## [v1.10.0](https://github.com/hoppscotch/hoppscotch/tree/v1.10.0) (2020-04-10)
[Full Changelog](https://github.com/hoppscotch/hoppscotch/compare/v1.9.9...v1.10.0)
## [v1.9.9](https://github.com/liyasthomas/postwoman/tree/v1.9.9) (2020-07-30)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/v1.9.7...v1.9.9)

View File

@@ -2,75 +2,131 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
Examples of behavior that contributes to a positive environment for our
community include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior by participants include:
Examples of unacceptable behavior include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
## Enforcement Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior. Maintainers are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned with our Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at liyascthomas@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
All complaints will be reviewed and investigated promptly and fairly.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][mozilla coc].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][faq]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[mozilla coc]: https://github.com/mozilla/diversity
[faq]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -12,81 +12,6 @@ Please note we have a code of conduct, please follow it in all your interactions
2. Update the README.md with details of changes to the interface, this includes new environment
variables, exposed ports, useful file locations and container parameters.
3. Increase the version numbers in any examples files and the README.md to the new version that this
Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
Pull Request would represent. The versioning scheme we use is [SemVer](https://semver.org).
4. You may merge the Pull Request once you have the sign-off of two other developers, or if you
do not have permission to do that, you may request the second reviewer merge it for you.
## Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior. Maintainers are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned with our Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at liyascthomas@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -1,6 +1,6 @@
FROM node:12.10.0-alpine
FROM node:12-alpine
LABEL maintainer="Liyas Thomas (liyascthomas@gmail.com)"
LABEL maintainer="Hoppscotch (support@hoppscotch.io)"
# Add git as the prebuild target requires it to parse version information
RUN apk add --update --no-cache \
@@ -17,9 +17,9 @@ ADD . /app/
COPY . .
RUN npm run generate
ENV HOST 0.0.0.0
EXPOSE 3000
RUN mv .env.example .env
CMD ["npm", "run", "dev"]

488
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://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/logo.png"
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="http://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/intent/tweet?url=https%3A%2F%2Fhoppscotch.io&text=%F0%9F%91%BD%20Hoppscotch%20%E2%80%A2%20API%20request%20builder%20-%20Helps%20you%20create%20requests%20faster%2C%20saving%20precious%20time%20on%20development&original_referer=https%3A%2F%2Ftwitter.com%2Fshare%3Ftext%3D%25F0%259F%2591%25BD%2520Hoppscotch%2520%25E2%2580%25A2%2520API%2520request%2520builder%2520-%2520Helps%2520you%2520create%2520requests%2520faster%2C%2520saving%2520precious%2520time%2520on%2520development%26url%3Dhttps%3A%2F%2Fhoppscotch.io%26hashtags%3Dhoppscotch%26via%3Dliyasthomas&via=liyasthomas&hashtags=hoppscotch)
[![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://raw.githubusercontent.com/hoppscotch/hoppscotch/main/static/images/screenshots/light_rest.png"
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://t.me/hoppscotch) [![Chat on Discord](https://img.shields.io/badge/chat-Discord-7289DA?logo=discord)](https://discord.gg/GAMWxmR)
#### **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,137 +142,61 @@ _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!**_
📦 **Add-ons:** Official add-ons for hoppscotch.
- **[Proxy](https://github.com/hoppscotch/proxyscotch)** - A simple proxy server created for Hoppscotch
@@ -347,56 +209,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>
@@ -410,7 +252,13 @@ _Notes are only available for signed-in users_
</details>
**To find out more, please check out [Hoppscotch Wiki](https://github.com/hoppscotch/hoppscotch/wiki).**
👨‍👩‍👧‍👦 **Teams β:** Helps you collaborate across your team to design, develop, and test APIs faster.
- Unlimited team collections and shared requests
- Unlimited team members
- User roles
**For more features, please read our [documentation](https://docs.hoppscotch.io).**
## **Demo**
@@ -426,8 +274,9 @@ _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)
- [Nuxt](https://nuxtjs.org)
@@ -437,18 +286,19 @@ _Notes are only available for signed-in users_
_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`.
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`
@@ -459,38 +309,9 @@ _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.
@@ -506,7 +327,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**
@@ -514,148 +335,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://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="http://tom.preston-werner.com" target="_blank" rel="noopener">
<img
width="64"
src="https://github.com/mojombo.png?size=64"
alt="Tom Preston-Werner"
/>
</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://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>
<p align="center">
<a href="https://opencollective.com/hoppscotch/organization/0/website"><img src="https://opencollective.com/hoppscotch/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/hoppscotch/organization/1/website"><img src="https://opencollective.com/hoppscotch/organization/1/avatar.svg"></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,213 +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';
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,5 +0,0 @@
/* purgecss start ignore */
@tailwind base;
@tailwind components;
/* purgecss end ignore */
@tailwind utilities;

1
assets/icons/chrome.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient x1="49.998%" y1=".706%" x2="49.998%" y2="96.99%" id="IconifyId-17b2bfeca9d-d6badc-3320"><stop stop-color="#86BBE5" offset="0%"></stop><stop stop-color="#1072BA" offset="100%"></stop></linearGradient></defs><path d="M127.789.035s75.32-3.38 115.253 72.328H121.38s-22.96-.74-42.573 27.114c-5.634 11.691-11.69 23.734-4.894 47.468c-9.79-16.586-51.975-90.04-51.975-90.04S51.693 3.028 127.788.035z" fill="#EF3F36"></path><path d="M239.133 192.229s-34.756 66.94-120.253 63.63c10.564-18.276 60.848-105.358 60.848-105.358s12.149-19.508-2.183-50.425c-7.29-10.74-14.72-21.973-38.664-27.96c19.262-.175 103.95 0 103.95 0s31.726 52.715-3.698 120.113z" fill="#FCD900"></path><path d="M16.973 192.757s-40.601-63.56 5.035-135.958c10.529 18.276 60.813 105.358 60.813 105.358s10.846 20.283 44.756 23.31c12.924-.95 26.375-1.76 43.56-19.472C161.663 182.757 119.16 256 119.16 256s-61.552 1.127-102.188-63.243z" fill="#61BC5B"></path><path d="M118.845 256.493l17.113-71.412s18.804-1.48 34.58-18.769c-9.79 17.22-51.693 90.181-51.693 90.181z" fill="#5AB055"></path><path d="M70.462 129.056c0-31.48 25.53-57.01 57.01-57.01c31.48 0 57.01 25.53 57.01 57.01c0 31.481-25.53 57.01-57.01 57.01c-31.48-.035-57.01-25.529-57.01-57.01z" fill="#FFF"></path><path d="M80.004 129.056c0-26.198 21.234-47.467 47.468-47.467c26.198 0 47.467 21.234 47.467 47.467c0 26.199-21.233 47.468-47.467 47.468c-26.199 0-47.468-21.269-47.468-47.468z" fill="url(#IconifyId-17b2bfeca9d-d6badc-3320)"></path><path d="M242.795 72.152l-70.462 20.67s-10.634-15.6-33.487-20.67c19.825-.106 103.949 0 103.949 0z" fill="#EACA05"></path><path d="M72.54 144.339c-9.896-17.149-50.602-87.434-50.602-87.434l52.186 51.622s-5.353 11.022-3.345 26.797l1.76 9.015z" fill="#DF3A32"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

1
assets/icons/discord.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="41.17" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 199"><path d="M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046c-19.692-2.961-39.203-2.961-58.533 0c-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632a108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237a136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848c21.142-6.58 42.646-16.637 64.815-33.213c5.316-56.288-9.08-105.09-38.056-148.36zM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2c.02 14.375-10.148 26.18-23.015 26.18zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2c0 14.375-10.148 26.18-23.015 26.18z" fill="#5865F2"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
assets/icons/email.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--simple-icons" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M15.61 12c0 1.99-1.62 3.61-3.61 3.61c-1.99 0-3.61-1.62-3.61-3.61c0-1.99 1.62-3.61 3.61-3.61c1.99 0 3.61 1.62 3.61 3.61M12 0C5.383 0 0 5.383 0 12s5.383 12 12 12c2.424 0 4.761-.722 6.76-2.087l.034-.024l-1.617-1.879l-.027.017A9.494 9.494 0 0 1 12 21.54c-5.26 0-9.54-4.28-9.54-9.54c0-5.26 4.28-9.54 9.54-9.54c5.26 0 9.54 4.28 9.54 9.54a9.63 9.63 0 0 1-.225 2.05c-.301 1.239-1.169 1.618-1.82 1.568c-.654-.053-1.42-.52-1.426-1.661V12A6.076 6.076 0 0 0 12 5.93A6.076 6.076 0 0 0 5.93 12A6.076 6.076 0 0 0 12 18.07a6.02 6.02 0 0 0 4.3-1.792a3.9 3.9 0 0 0 3.32 1.805c.874 0 1.74-.292 2.437-.821c.719-.547 1.256-1.336 1.553-2.285c.047-.154.135-.504.135-.507l.002-.013c.175-.76.253-1.52.253-2.457c0-6.617-5.383-12-12-12" fill="currentColor"></path></svg>

After

Width:  |  Height:  |  Size: 982 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M241.871 256.001c7.802 0 14.129-6.326 14.129-14.129V14.129C256 6.325 249.673 0 241.871 0H14.129C6.324 0 0 6.325 0 14.129v227.743c0 7.803 6.324 14.129 14.129 14.129h227.742" fill="#395185"></path><path d="M176.635 256.001v-99.137h33.277l4.982-38.635h-38.259V93.561c0-11.186 3.107-18.809 19.148-18.809l20.459-.009V40.188c-3.54-.471-15.684-1.523-29.812-1.523c-29.498 0-49.692 18.005-49.692 51.071v28.493h-33.362v38.635h33.362v99.137h39.897" fill="#FFF"></path></svg>

After

Width:  |  Height:  |  Size: 697 B

1
assets/icons/firefox.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

1
assets/icons/github.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="2500" height="2432" viewBox="0 0 256 249" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><g fill="currentColor"><path d="M127.505 0C57.095 0 0 57.085 0 127.505c0 56.336 36.534 104.13 87.196 120.99 6.372 1.18 8.712-2.766 8.712-6.134 0-3.04-.119-13.085-.173-23.739-35.473 7.713-42.958-15.044-42.958-15.044-5.8-14.738-14.157-18.656-14.157-18.656-11.568-7.914.872-7.752.872-7.752 12.804.9 19.546 13.14 19.546 13.14 11.372 19.493 29.828 13.857 37.104 10.6 1.144-8.242 4.449-13.866 8.095-17.05-28.32-3.225-58.092-14.158-58.092-63.014 0-13.92 4.981-25.295 13.138-34.224-1.324-3.212-5.688-16.18 1.235-33.743 0 0 10.707-3.427 35.073 13.07 10.17-2.826 21.078-4.242 31.914-4.29 10.836.048 21.752 1.464 31.942 4.29 24.337-16.497 35.029-13.07 35.029-13.07 6.94 17.563 2.574 30.531 1.25 33.743 8.175 8.929 13.122 20.303 13.122 34.224 0 48.972-29.828 59.756-58.22 62.912 4.573 3.957 8.648 11.717 8.648 23.612 0 17.06-.148 30.791-.148 34.991 0 3.393 2.295 7.369 8.759 6.117 50.634-16.879 87.122-64.656 87.122-120.973C255.009 57.085 197.922 0 127.505 0"/><path d="M47.755 181.634c-.28.633-1.278.823-2.185.389-.925-.416-1.445-1.28-1.145-1.916.275-.652 1.273-.834 2.196-.396.927.415 1.455 1.287 1.134 1.923M54.027 187.23c-.608.564-1.797.302-2.604-.589-.834-.889-.99-2.077-.373-2.65.627-.563 1.78-.3 2.616.59.834.899.996 2.08.36 2.65M58.33 194.39c-.782.543-2.06.034-2.849-1.1-.781-1.133-.781-2.493.017-3.038.792-.545 2.05-.055 2.85 1.07.78 1.153.78 2.513-.019 3.069M65.606 202.683c-.699.77-2.187.564-3.277-.488-1.114-1.028-1.425-2.487-.724-3.258.707-.772 2.204-.555 3.302.488 1.107 1.026 1.445 2.496.7 3.258M75.01 205.483c-.307.998-1.741 1.452-3.185 1.028-1.442-.437-2.386-1.607-2.095-2.616.3-1.005 1.74-1.478 3.195-1.024 1.44.435 2.386 1.596 2.086 2.612M85.714 206.67c.036 1.052-1.189 1.924-2.705 1.943-1.525.033-2.758-.818-2.774-1.852 0-1.062 1.197-1.926 2.721-1.951 1.516-.03 2.758.815 2.758 1.86M96.228 206.267c.182 1.026-.872 2.08-2.377 2.36-1.48.27-2.85-.363-3.039-1.38-.184-1.052.89-2.105 2.367-2.378 1.508-.262 2.857.355 3.049 1.398"/></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

1
assets/icons/google.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M118.2 208.3c19.9-60.3 76.5-103.6 143.7-103.6 36.1 0 68.6 12.8 94.3 33.7L430.5 64C385.2 24.4 327 0 261.8 0 160.9 0 74 57.6 32.3 141.9l85.9 66.4z" fill="currentColor"/><path d="M348 384.3c-23.3 15-52.8 23-86.2 23-66.9 0-123.3-43-143.4-102.9l-86.2 65.4C73.9 454.3 160.8 512 261.8 512c62.6 0 122.4-22.2 167.1-64L348 384.3z" fill="currentColor"/><path d="M428.9 448c46.8-43.7 77.2-108.7 77.2-192 0-15.1-2.3-31.4-5.8-46.5H261.8v98.9h137.3c-6.8 33.3-25 59-51.1 75.9l80.9 63.7z" fill="currentColor"/><path d="M118.4 304.4c-5.1-15.2-7.9-31.4-7.9-48.4 0-16.7 2.7-32.7 7.6-47.7l-85.9-66.4C15.1 176.2 5.8 214.9 5.8 256c0 40.9 9.5 79.6 26.4 113.8l86.2-65.4z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 746 B

1
assets/icons/graphql.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--fontisto" width="28" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 21 24"><path d="M12.731 2.751L17.666 5.6a2.138 2.138 0 1 1 2.07 3.548l-.015.003v5.7a2.14 2.14 0 1 1-2.098 3.502l-.002-.002l-4.905 2.832a2.14 2.14 0 1 1-4.079.054l-.004.015l-4.941-2.844a2.14 2.14 0 1 1-2.067-3.556l.015-.003V9.15a2.14 2.14 0 1 1 1.58-3.926l-.01-.005c.184.106.342.231.479.376l.001.001l4.938-2.85a2.14 2.14 0 1 1 4.096.021l.004-.015zm-.515.877a.766.766 0 0 1-.057.057l-.001.001l6.461 11.19c.026-.009.056-.016.082-.023V9.146a2.14 2.14 0 0 1-1.555-2.603l-.003.015l.019-.072zm-3.015.059l-.06-.06l-4.946 2.852A2.137 2.137 0 0 1 2.749 9.12l-.015.004l-.076.021v5.708l.084.023l6.461-11.19zm2.076.507a2.164 2.164 0 0 1-1.207-.004l.015.004l-6.46 11.189c.286.276.496.629.597 1.026l.003.015h12.911c.102-.413.313-.768.599-1.043l.001-.001L11.28 4.194zm.986 16.227l4.917-2.838a1.748 1.748 0 0 1-.038-.142H4.222l-.021.083l4.939 2.852c.39-.403.936-.653 1.54-.653c.626 0 1.189.268 1.581.696l.001.002z" fill="currentColor"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M218.123 218.127h-37.931v-59.403c0-14.165-.253-32.4-19.728-32.4c-19.756 0-22.779 15.434-22.779 31.369v60.43h-37.93V95.967h36.413v16.694h.51a39.907 39.907 0 0 1 35.928-19.733c38.445 0 45.533 25.288 45.533 58.186l-.016 67.013zM56.955 79.27c-12.157.002-22.014-9.852-22.016-22.009c-.002-12.157 9.851-22.014 22.008-22.016c12.157-.003 22.014 9.851 22.016 22.008A22.013 22.013 0 0 1 56.955 79.27m18.966 138.858H37.95V95.967h37.97v122.16zM237.033.018H18.89C8.58-.098.125 8.161-.001 18.471v219.053c.122 10.315 8.576 18.582 18.89 18.474h218.144c10.336.128 18.823-8.139 18.966-18.474V18.454c-.147-10.33-8.635-18.588-18.966-18.453" fill="#0A66C2"></path></svg>

After

Width:  |  Height:  |  Size: 882 B

1
assets/icons/reddit.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><circle fill="#FF4500" cx="128" cy="128" r="128"></circle><path d="M213.15 129.22c0-10.376-8.391-18.617-18.617-18.617a18.74 18.74 0 0 0-12.97 5.189c-12.818-9.157-30.368-15.107-49.9-15.87l8.544-39.981l27.773 5.95c.307 7.02 6.104 12.667 13.278 12.667c7.324 0 13.275-5.95 13.275-13.278c0-7.324-5.95-13.275-13.275-13.275c-5.188 0-9.768 3.052-11.904 7.478l-30.976-6.562c-.916-.154-1.832 0-2.443.458c-.763.458-1.22 1.22-1.371 2.136l-9.464 44.558c-19.837.612-37.692 6.562-50.662 15.872a18.74 18.74 0 0 0-12.971-5.188c-10.377 0-18.617 8.391-18.617 18.617c0 7.629 4.577 14.037 10.988 16.939a33.598 33.598 0 0 0-.458 5.646c0 28.686 33.42 52.036 74.621 52.036c41.202 0 74.622-23.196 74.622-52.036a35.29 35.29 0 0 0-.458-5.646c6.408-2.902 10.985-9.464 10.985-17.093zM85.272 142.495c0-7.324 5.95-13.275 13.278-13.275c7.324 0 13.275 5.95 13.275 13.275s-5.95 13.278-13.275 13.278c-7.327.15-13.278-5.953-13.278-13.278zm74.317 35.251c-9.156 9.157-26.553 9.768-31.588 9.768c-5.188 0-22.584-.765-31.59-9.768c-1.371-1.373-1.371-3.51 0-4.883c1.374-1.371 3.51-1.371 4.884 0c5.8 5.8 18.008 7.782 26.706 7.782c8.699 0 21.058-1.983 26.704-7.782c1.374-1.371 3.51-1.371 4.884 0c1.22 1.373 1.22 3.51 0 4.883zm-2.443-21.822c-7.325 0-13.275-5.95-13.275-13.275s5.95-13.275 13.275-13.275c7.327 0 13.277 5.95 13.277 13.275c0 7.17-5.95 13.275-13.277 13.275z" fill="#FFF"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
assets/icons/twitter.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="39.2" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 209"><path d="M256 25.45c-9.42 4.177-19.542 7-30.166 8.27c10.845-6.5 19.172-16.793 23.093-29.057a105.183 105.183 0 0 1-33.351 12.745C205.995 7.201 192.346.822 177.239.822c-29.006 0-52.523 23.516-52.523 52.52c0 4.117.465 8.125 1.36 11.97c-43.65-2.191-82.35-23.1-108.255-54.876c-4.52 7.757-7.11 16.78-7.11 26.404c0 18.222 9.273 34.297 23.365 43.716a52.312 52.312 0 0 1-23.79-6.57c-.003.22-.003.44-.003.661c0 25.447 18.104 46.675 42.13 51.5a52.592 52.592 0 0 1-23.718.9c6.683 20.866 26.08 36.05 49.062 36.475c-17.975 14.086-40.622 22.483-65.228 22.483c-4.24 0-8.42-.249-12.529-.734c23.243 14.902 50.85 23.597 80.51 23.597c96.607 0 149.434-80.031 149.434-149.435c0-2.278-.05-4.543-.152-6.795A106.748 106.748 0 0 0 256 25.45" fill="#55acee"></path></svg>

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 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

18
assets/js/getLinkTag.js Normal file
View File

@@ -0,0 +1,18 @@
const DEFAULT_TAG = "button"
const ANCHOR_TAG = "a"
const FRAMEWORK_LINK = "NuxtLink" // or "router-link", "g-link"...
const getLinkTag = ({ to, blank }) => {
if (!to) {
return DEFAULT_TAG
} else if (blank) {
return ANCHOR_TAG
} else if (/^\/(?!\/).*$/.test(to)) {
// regex101.com/r/LU1iFL/1
return FRAMEWORK_LINK
} else {
return ANCHOR_TAG
}
}
export { getLinkTag as default, ANCHOR_TAG, FRAMEWORK_LINK }

View File

@@ -17,7 +17,10 @@ const regex = { ws, sse, socketio }
// type = ws/sse/socketio
async function validator(type, url) {
console.time(`validator ${url}`)
const [res1, res2] = await Promise.all([regex[type][0].test(url), regex[type][1].test(url)])
const [res1, res2] = await Promise.all([
regex[type][0].test(url),
regex[type][1].test(url),
])
console.timeEnd(`validator ${url}`)
return res1 || res2
}

View File

@@ -1,218 +1,12 @@
**Table of Contents**
{{#collections}}
{{>folderContents}}
{{/collections}}
{{#collections}}
# {{name}}
## {{#folders}}
## Folder: {{name}}
{{#requests}}
### {{name}}
**Method**: {{method}}
**Request URL**: `{{{url}}}{{{path}}}`
{{#isHeaders}}
**Headers**:
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{{#headers}}
<tr>
<td>{{{key}}}</td>
<td>`{{{value}}}`</td>
</tr>
{{/headers}}
</table>
{{/isHeaders}}
{{#isParams}}
**Parameters**:
<table>
<tr>
<th>type</th>
<th>Key</th>
<th>Value</th>
</tr>
{{#params}}
<tr>
<td>{{type}}</td>
<td>{{{key}}}</td>
<td>{{{value}}}</td>
</tr>
{{/params}}
</table>
{{/isParams}}
{{#isAuth}}
**Authentication Type**: {{{auth}}}
{{/isAuth}}
{{#bearerToken}}
**Bearer Token**: `{{{.}}}`
{{/bearerToken}}
{{#isAuthBasic}}
Username: `{{{httpUser}}}`
Password: `{{{httpPassword}}}`
{{/isAuthBasic}}
{{#isRawParams}}
**RawParams**:
```json
{{{rawParams}}}
```
{{/isRawParams}}
{{#contentType}}
**ContentType**: `{{{contentType}}}`
{{/contentType}}
{{#preRequestScript}}
**Pre Request Script**:
```js
{
{
{
preRequestScript
}
}
}
```
{{/preRequestScript}}
{{#testScript}}
**Test Script**:
```js
{
{
{
testScript
}
}
}
```
{{/testScript}}
{{/requests}}
---
{{/folders}}
{{#requests}}
## {{name}}
**Method**: {{method}}
**Request URL**: `{{{url}}}{{{path}}}`
{{#isHeaders}}
**Headers**:
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{{#headers}}
<tr>
<td>{{{key}}}</td>
<td>`{{{value}}}`</td>
</tr>
{{/headers}}
</table>
{{/isHeaders}}
{{#isParams}}
**Parameters**:
<table>
<tr>
<th>type</th>
<th>Key</th>
<th>Value</th>
</tr>
{{#params}}
<tr>
<td>{{type}}</td>
<td>{{{key}}}</td>
<td>{{{value}}}</td>
</tr>
{{/params}}
</table>
{{/isParams}}
{{#isAuth}}
**Authentication Type**: {{{auth}}}
{{/isAuth}}
{{#bearerToken}}
**Bearer Token**: `{{{.}}}`
{{/bearerToken}}
{{#isAuthBasic}}
Username: `{{{httpUser}}}`
Password: `{{{httpPassword}}}`
{{/isAuthBasic}}
{{#isRawParams}}
**Raw Parameters**:
```json
{{{rawParams}}}
```
{{/isRawParams}}
{{#contentType}}
**Content Type**: `{{{contentType}}}`
{{/contentType}}
{{#preRequestScript}}
**Pre Request Script**:
```js
{
{
{
preRequestScript
}
}
}
```
{{/preRequestScript}}
{{#testScript}}
**Test Script**:
```js
{
{
{
testScript
}
}
}
```
{{/testScript}}
{{/requests}}
{{>folderBody}}
{{/collections}}

113
assets/md/folderBody.md Normal file
View File

@@ -0,0 +1,113 @@
{{nestingLevel}} {{name}}
{{#requests}}
{{nestingLevel}} Request: {{name}}
**Method**: {{method}}
**Request URL**:
```
{{{url}}}{{{path}}}
```
{{#isHeaders}}
**Headers**:
<table>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{{#headers}}
<tr>
<td>{{{key}}}</td>
<td>`{{{value}}}`</td>
</tr>
{{/headers}}
</table>
{{/isHeaders}}
{{#isParams}}
**Parameters**:
<table>
<tr>
<th>type</th>
<th>Key</th>
<th>Value</th>
</tr>
{{#params}}
<tr>
<td>{{type}}</td>
<td>{{{key}}}</td>
<td>{{{value}}}</td>
</tr>
{{/params}}
</table>
{{/isParams}}
{{#isAuth}}
**Authentication Type**: {{{auth}}}
{{/isAuth}}
{{#bearerToken}}
**Bearer Token**: `{{{.}}}`
{{/bearerToken}}
{{#isAuthBasic}}
Username: `{{{httpUser}}}`
Password: `{{{httpPassword}}}`
{{/isAuthBasic}}
{{#isRawParams}}
**Raw Parameters**:
```json
{{{rawParams}}}
```
{{/isRawParams}}
{{#contentType}}
**Content Type**: `{{{contentType}}}`
{{/contentType}}
{{#isPreRequestScript}}
**Pre Request Script**:
```js
{
{
{
preRequestScript
}
}
}
```
{{/isPreRequestScript}}
{{#isTestScript}}
**Test Script**:
```js
{
{
{
testScript
}
}
}
```
{{/isTestScript}}
{{/requests}}
{{#folders}}
{{> folderBody }}
{{/folders}}

View File

@@ -0,0 +1,4 @@
{{{id}}} <a href="#{{ref}}"> {{name}} </a> <br>
{{#folders}}
{{> folderContents}}
{{/folders}}

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +1,247 @@
@mixin baseTheme {
--font-sans: "Poppins", "sans-serif";
--font-mono: "Roboto Mono", "monospace";
--font-sans: "Inter", sans-serif;
--font-mono: "Roboto Mono", monospace;
--font-icon: "Material Icons";
}
@mixin darkTheme {
// Background color
--bg-color: rgba(32, 33, 36, 1);
--primary-color: theme("colors.true-gray.900");
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.04);
--primary-light-color: theme("colors.dark.600");
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.2);
--primary-dark-color: theme("colors.true-gray.800");
// Text color
--fg-color: rgba(255, 255, 255, 0.9);
--secondary-color: theme("colors.true-gray.400");
// Light Text color
--fg-light-color: rgba(255, 255, 255, 0.5);
--secondary-light-color: theme("colors.true-gray.500");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.100");
// Border color
--brd-color: rgba(255, 255, 255, 0.05);
--divider-color: theme("colors.true-gray.800");
// Light Border color
--divider-light-color: theme("colors.dark.500");
// Dark Border color
--divider-dark-color: theme("colors.dark.300");
// Error color
--err-color: rgba(255, 255, 255, 0.05);
--error-color: theme("colors.warm-gray.800");
// Tooltip color
--tt-color: rgba(48, 48, 48, 1);
--tooltip-color: theme("colors.true-gray.100");
// Popover color
--popover-color: theme("colors.dark.700");
// Editor theme
--editor-theme: "twilight";
// Active text color
--act-color: rgba(32, 33, 36, 1);
--editor-theme: "merbivore_soft";
}
@mixin lightTheme {
// Background color
--bg-color: rgba(255, 255, 255, 1);
--primary-color: theme("colors.white");
// Light Background color
--bg-light-color: rgba(0, 0, 0, 0.05);
--primary-light-color: theme("colors.true-gray.50");
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.02);
--primary-dark-color: theme("colors.true-gray.100");
// Text color
--fg-color: rgba(0, 0, 0, 0.9);
--secondary-color: theme("colors.true-gray.500");
// Light Text color
--fg-light-color: rgba(0, 0, 0, 0.6);
--secondary-light-color: theme("colors.true-gray.400");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.900");
// Border color
--brd-color: rgba(0, 0, 0, 0.1);
--divider-color: theme("colors.true-gray.200");
// Light Border color
--divider-light-color: theme("colors.true-gray.100");
// Dark Border color
--divider-dark-color: theme("colors.true-gray.300");
// Error color
--err-color: rgba(0, 0, 0, 0.1);
--error-color: theme("colors.yellow.100");
// Tooltip color
--tt-color: rgba(255, 255, 255, 1);
--tooltip-color: theme("colors.true-gray.800");
// Popover color
--popover-color: theme("colors.white");
// Editor theme
--editor-theme: "iplastic";
// Active text color
--act-color: rgba(255, 255, 255, 1);
--editor-theme: "textmate";
}
@mixin blackTheme {
// Background color
--bg-color: rgba(0, 0, 0, 1);
--primary-color: theme("colors.dark.900");
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.02);
--primary-light-color: theme("colors.true-gray.900");
// Dark Background color
--bg-dark-color: rgba(255, 255, 255, 0.04);
--primary-dark-color: theme("colors.dark.800");
// Text color
--fg-color: rgba(255, 255, 255, 0.9);
--secondary-color: theme("colors.true-gray.400");
// Light Text color
--fg-light-color: rgba(255, 255, 255, 0.5);
--secondary-light-color: theme("colors.true-gray.500");
// Dark Text color
--secondary-dark-color: theme("colors.true-gray.100");
// Border color
--brd-color: rgba(255, 255, 255, 0.05);
--divider-color: theme("colors.true-gray.800");
// Light Border color
--divider-light-color: theme("colors.dark.700");
// Dark Border color
--divider-dark-color: theme("colors.dark.300");
// Error color
--err-color: rgba(255, 255, 255, 0.05);
--error-color: theme("colors.warm-gray.900");
// Tooltip color
--tt-color: rgba(32, 32, 32, 1);
--tooltip-color: theme("colors.true-gray.100");
// Popover color
--popover-color: theme("colors.dark.700");
// 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");
--editor-theme: "twilight";
}
@mixin greenTheme {
// Acent color
--ac-color: theme("colors.green.400");
// Accent color
--accent-color: theme("colors.green.500");
// Light Accent color
--accent-light-color: theme("colors.green.400");
// Dark Accent color
--accent-dark-color: theme("colors.green.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.green.200");
// Gradient via
--gradient-via-color: theme("colors.green.400");
// Gradient to
--gradient-to-color: theme("colors.green.600");
}
@mixin tealTheme {
// Acent color
--ac-color: theme("colors.teal.400");
// Accent color
--accent-color: theme("colors.teal.500");
// Light Accent color
--accent-light-color: theme("colors.teal.400");
// Dark Accent color
--accent-dark-color: theme("colors.teal.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.teal.200");
// Gradient via
--gradient-via-color: theme("colors.teal.400");
// Gradient to
--gradient-to-color: theme("colors.teal.600");
}
@mixin blueTheme {
// Accent color
--accent-color: theme("colors.blue.500");
// Light Accent color
--accent-light-color: theme("colors.blue.400");
// Dark Accent color
--accent-dark-color: theme("colors.blue.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.blue.200");
// Gradient via
--gradient-via-color: theme("colors.blue.400");
// Gradient to
--gradient-to-color: theme("colors.blue.600");
}
@mixin indigoTheme {
// Acent color
--ac-color: theme("colors.indigo.400");
// Accent color
--accent-color: theme("colors.indigo.500");
// Light Accent color
--accent-light-color: theme("colors.indigo.400");
// Dark Accent color
--accent-dark-color: theme("colors.indigo.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.indigo.200");
// Gradient via
--gradient-via-color: theme("colors.indigo.400");
// Gradient to
--gradient-to-color: theme("colors.indigo.600");
}
@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");
// Accent color
--accent-color: theme("colors.purple.500");
// Light Accent color
--accent-light-color: theme("colors.purple.400");
// Dark Accent color
--accent-dark-color: theme("colors.purple.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.purple.200");
// Gradient via
--gradient-via-color: theme("colors.purple.400");
// Gradient to
--gradient-to-color: theme("colors.purple.600");
}
@mixin yellowTheme {
// Acent color
--ac-color: theme("colors.yellow.400");
// Accent color
--accent-color: theme("colors.yellow.500");
// Light Accent color
--accent-light-color: theme("colors.yellow.400");
// Dark Accent color
--accent-dark-color: theme("colors.yellow.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.yellow.200");
// Gradient via
--gradient-via-color: theme("colors.yellow.400");
// Gradient to
--gradient-to-color: theme("colors.yellow.600");
}
@mixin orangeTheme {
// Accent color
--accent-color: theme("colors.orange.500");
// Light Accent color
--accent-light-color: theme("colors.orange.400");
// Dark Accent color
--accent-dark-color: theme("colors.orange.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.orange.200");
// Gradient via
--gradient-via-color: theme("colors.orange.400");
// Gradient to
--gradient-to-color: theme("colors.orange.600");
}
@mixin redTheme {
// Accent color
--accent-color: theme("colors.red.500");
// Light Accent color
--accent-light-color: theme("colors.red.400");
// Dark Accent color
--accent-dark-color: theme("colors.red.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.red.200");
// Gradient via
--gradient-via-color: theme("colors.red.400");
// Gradient to
--gradient-to-color: theme("colors.red.600");
}
@mixin pinkTheme {
// Accent color
--accent-color: theme("colors.pink.500");
// Light Accent color
--accent-light-color: theme("colors.pink.400");
// Dark Accent color
--accent-dark-color: theme("colors.pink.600");
// Light Contrast color
--accent-contrast-color: theme("colors.white");
// Gradient from
--gradient-from-color: theme("colors.pink.200");
// Gradient via
--gradient-via-color: theme("colors.pink.400");
// Gradient to
--gradient-to-color: theme("colors.pink.600");
}
:root {
@@ -139,27 +265,110 @@
: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;
}
@mixin fontSmall {
// Font size
--body-font-size: 0.75rem;
// Line height
--body-line-height: 1rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.125rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 6.125rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 8.188rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 5rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 4rem;
}
@mixin fontMedium {
// Font size
--body-font-size: 0.875rem;
// Line height
--body-line-height: 1.25rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.375rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 6.625rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 8.813rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3.25rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 5.5rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2.25rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 4.5rem;
}
@mixin fontLarge {
// Font size
--body-font-size: 1rem;
// Line height
--body-line-height: 1.5rem;
// Upper primary sticky fold
--upper-primary-sticky-fold: 4.625rem;
// Upper secondary sticky fold
--upper-secondary-sticky-fold: 7.125rem;
// Upper tertiary sticky fold
--upper-tertiary-sticky-fold: 9.5rem;
// Lower primary sticky fold
--lower-primary-sticky-fold: 3.5rem;
// Lower secondary sticky fold
--lower-secondary-sticky-fold: 6rem;
// Sidebar primary sticky fold
--sidebar-primary-sticky-fold: 2.5rem;
// Sidebar secondary sticky fold
--sidebar-secondary-sticky-fold: 5rem;
}
:root[data-font-size="small"] {
@include fontSmall;
}
:root[data-font-size="medium"] {
@include fontMedium;
}
:root[data-font-size="large"] {
@include fontLarge;
}

View File

@@ -5,7 +5,11 @@ function isBabelLoader(caller) {
module.exports = function (api) {
if (api.env("test") && !api.caller(isBabelLoader)) {
return {
plugins: ["@babel/plugin-proposal-class-properties"],
plugins: [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
],
presets: [
[
"@babel/preset-env",

3
commitlint.config.js Normal file
View File

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

View File

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

View File

@@ -1,169 +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
href="https://github.com/sponsors/hoppscotch"
target="_blank"
rel="noopener"
v-tooltip.right="$t('recurring')"
>
<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
href="https://opencollective.com/hoppscotch"
target="_blank"
rel="noopener"
v-tooltip.right="$t('one_time_recurring')"
>
<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
href="https://www.patreon.com/liyasthomas"
target="_blank"
rel="noopener"
v-tooltip.right="$t('recurring')"
>
<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
href="https://www.paypal.me/liyascthomas"
target="_blank"
rel="noopener"
v-tooltip.right="$t('one_time')"
>
<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>
</div>
<div class="contributors">
<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>
</div>
<div class="contributors">
<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>
</div>
<div class="contributors">
<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 class="contributors">
<a
target="_blank"
rel="noopener"
href="https://opencollective.com/hoppscotch/organization/0/website"
>
<img src="https://opencollective.com/hoppscotch/organization/0/avatar.svg" />
</a>
<a
target="_blank"
rel="noopener"
href="https://opencollective.com/hoppscotch/organization/1/website"
>
<img src="https://opencollective.com/hoppscotch/organization/1/avatar.svg" />
</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-nowrap;
@apply overflow-auto;
@apply m-2;
}
</style>

View File

@@ -1,88 +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 class="icon" v-if="hasFirefoxExtInstalled" v-tooltip="$t('installed')">
<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 class="icon" v-if="hasChromeExtInstalled" v-tooltip="$t('installed')">
<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,
},
watch: {
show() {
this.hasChromeExtInstalled = hasChromeExtensionInstalled()
this.hasFirefoxExtInstalled = hasFirefoxExtensionInstalled()
},
},
data() {
return {
hasChromeExtInstalled: hasChromeExtensionInstalled(),
hasFirefoxExtInstalled: hasFirefoxExtensionInstalled(),
}
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,88 +1,164 @@
<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 class="footer-link"> Sponsored by </span>
<div>
<div class="flex justify-between">
<div class="flex">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="LEFT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
icon="menu_open"
:class="{ 'transform -rotate-180': !LEFT_SIDEBAR }"
@click.native="LEFT_SIDEBAR = !LEFT_SIDEBAR"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="`${
ZEN_MODE ? $t('action.turn_off') : $t('action.turn_on')
} ${$t('layout.zen_mode')}`"
:icon="ZEN_MODE ? 'fullscreen_exit' : 'fullscreen'"
:class="{
'!text-accent !focus-visible:text-accentDark !hover:text-accentDark':
ZEN_MODE,
}"
@click.native="ZEN_MODE = !ZEN_MODE"
/>
</div>
<div class="flex">
<span>
<a
class="footer-link"
href="https://oss.capital/?ref=hoppscotch"
target="_blank"
rel="noopener"
<tippy
ref="options"
interactive
trigger="click"
theme="popover"
arrow
>
OSS Capital
</a>
</span>
<span class="footer-link"> & </span>
<span>
<a
class="footer-link"
href="https://paw.cloud/?utm_source=hoppscotch&utm_medium=website&utm_campaign=hoppscotch-sponsorship"
target="_blank"
rel="noopener"
>
Paw
</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:liyascthomas@gmail.com" target="_blank" rel="noopener">
<button class="icon" v-tooltip="$t('contact_us')">
<i class="material-icons">email</i>
</button>
</a>
<v-popover>
<button class="icon" v-tooltip="$t('choose_language')">
<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 class="icon" v-close-popover>
{{ locale.name }}
</button>
</nuxt-link>
<template #trigger>
<ButtonSecondary
icon="help_center"
class="rounded-none"
:label="$t('app.help')"
/>
</template>
<div class="flex flex-col">
<SmartItem
:label="$t('app.documentation')"
to="https://docs.hoppscotch.io"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
:label="$t('app.keyboard_shortcuts')"
@click.native="
showShortcuts = true
$refs.options.tippy().hide()
"
/>
<SmartItem
:label="$t('app.whats_new')"
to="https://docs.hoppscotch.io/changelog"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
:label="$t('app.chat_with_us')"
@click.native="
chatWithUs()
$refs.options.tippy().hide()
"
/>
<hr />
<SmartItem
:label="$t('app.twitter')"
to="https://twitter.com/hoppscotch_io"
blank
@click.native="$refs.options.tippy().hide()"
/>
<SmartItem
:label="$t('app.terms_and_privacy')"
to="https://docs.hoppscotch.io/privacy"
blank
@click.native="$refs.options.tippy().hide()"
/>
<!-- <SmartItem :label="$t('app.status')" /> -->
<div class="flex opacity-50 py-2 px-4">
{{ `${$t("app.name")} ${$t("app.version")}` }}
</div>
</div>
</template>
</v-popover>
</span>
</tippy>
</span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
icon="keyboard"
:title="$t('app.shortcuts')"
@click.native="showShortcuts = true"
/>
<ButtonSecondary
v-if="navigatorShare"
v-tippy="{ theme: 'tooltip' }"
icon="share"
:title="$t('request.share')"
@click.native="nativeShare()"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="RIGHT_SIDEBAR ? $t('hide.sidebar') : $t('show.sidebar')"
icon="menu_open"
class="transform rotate-180"
:class="{ 'rotate-360': !RIGHT_SIDEBAR }"
@click.native="RIGHT_SIDEBAR = !RIGHT_SIDEBAR"
/>
</div>
</div>
</footer>
<AppShortcuts :show="showShortcuts" @close="showShortcuts = false" />
</div>
</template>
<style scoped lang="scss">
.footer-link {
@apply inline-flex;
@apply flex-shrink-0;
@apply my-2;
@apply mx-4;
@apply text-fgLightColor;
<script lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api"
import { defineActionHandler } from "~/helpers/actions"
import { showChat } from "~/helpers/support"
import { useSetting } from "~/newstore/settings"
&:hover {
@apply text-fgColor;
}
}
</style>
export default defineComponent({
setup() {
const showShortcuts = ref(false)
<script>
export default {
computed: {
availableLocales() {
return this.$i18n.locales.filter(({ code }) => code !== this.$i18n.locale)
defineActionHandler("flyouts.keybinds.toggle", () => {
showShortcuts.value = !showShortcuts.value
})
return {
LEFT_SIDEBAR: useSetting("LEFT_SIDEBAR"),
RIGHT_SIDEBAR: useSetting("RIGHT_SIDEBAR"),
ZEN_MODE: useSetting("ZEN_MODE"),
navigatorShare: !!navigator.share,
showShortcuts,
}
},
watch: {
ZEN_MODE() {
this.LEFT_SIDEBAR = !this.ZEN_MODE
},
},
}
methods: {
nativeShare() {
if (navigator.share) {
navigator
.share({
title: "Hoppscotch",
text: "Hoppscotch • Open source API development ecosystem - Helps you create requests faster, saving precious time on development.",
url: "https://hoppscotch.io",
})
.then(() => {})
.catch(console.error)
} else {
// fallback
}
},
chatWithUs() {
showChat()
},
},
})
</script>

View File

@@ -0,0 +1,36 @@
<template>
<transition name="fade" appear>
<GithubButton
title="Star Hoppscotch"
href="https://github.com/hoppscotch/hoppscotch"
:data-color-scheme="
$colorMode.value != 'light'
? $colorMode.value == 'black'
? 'dark'
: 'dark_dimmed'
: 'light'
"
:data-show-count="true"
data-text="Star"
aria-label="Star Hoppscotch on GitHub"
:data-size="size"
/>
</transition>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import GithubButton from "vue-github-button"
export default defineComponent({
components: {
GithubButton,
},
props: {
size: {
type: String,
default: undefined,
},
},
})
</script>

View File

@@ -1,319 +1,137 @@
<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
class="icon"
<div>
<header
class="flex space-x-2 flex-1 py-2 px-2 items-center justify-between"
>
<div class="space-x-2 inline-flex items-center">
<ButtonSecondary
class="tracking-wide !font-bold !text-secondaryDark"
label="HOPPSCOTCH"
to="/"
/>
<AppGitHubStarButton class="mt-1.5 transition" />
</div>
<div class="space-x-2 inline-flex items-center">
<ButtonSecondary
id="installPWA"
@click.prevent="showInstallPrompt()"
v-tooltip="$t('install_pwa')"
>
<i class="material-icons">offline_bolt</i>
</button>
<a
href="https://github.com/hoppscotch/hoppscotch"
target="_blank"
aria-label="GitHub"
rel="noopener"
>
<button class="icon" aria-label="GitHub" v-tooltip="'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"
v-tippy="{ theme: 'tooltip' }"
:title="$t('header.install_pwa')"
icon="download_for_offline"
class="rounded"
@click.native="showInstallPrompt()"
/>
<ButtonSecondary
v-if="currentUser === null"
icon="filter_drama"
:label="$t('header.save_workspace')"
filled
class="hidden !font-semibold md:flex"
@click.native="showLogin = true"
/>
<ButtonPrimary
v-if="currentUser === null"
:label="$t('header.login')"
@click.native="showLogin = true"
/>
<span v-else class="pr-2">
<tippy ref="user" interactive trigger="click" theme="popover" arrow>
<template #trigger>
<ProfilePicture
v-if="currentUser.photoURL"
v-tippy="{
theme: 'tooltip',
}"
:url="currentUser.photoURL"
:alt="currentUser.displayName"
:title="currentUser.displayName"
indicator
:indicator-styles="isOnLine ? 'bg-green-500' : 'bg-red-500'"
/>
</svg>
</button>
</a>
<v-popover v-if="fb.currentUser === null">
<button class="icon" v-tooltip="$t('login_with')">
<i class="material-icons">login</i>
</button>
<template slot="popover">
<FirebaseLogin />
</template>
</v-popover>
<v-popover v-else>
<button
class="icon"
v-tooltip="
(fb.currentUser.displayName || '<label><i>Name not found</i></label>') +
'<br>' +
(fb.currentUser.email || '<label><i>Email not found</i></label>')
"
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"
<ButtonSecondary
v-else
v-tippy="{ theme: 'tooltip' }"
:title="$t('header.account')"
class="rounded"
icon="account_circle"
/>
</template>
<SmartItem
to="/settings"
icon="settings"
:label="$t('navigation.settings')"
@click.native="$refs.user.tippy().hide()"
/>
<i v-else class="material-icons">account_circle</i>
</button>
<template slot="popover">
<div>
<nuxt-link :to="localePath('settings')" v-close-popover>
<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 class="icon" v-tooltip="$t('more')">
<i class="material-icons">drag_indicator</i>
</button>
<template slot="popover">
<button class="icon" @click="showExtensions = true" v-close-popover>
<i class="material-icons">extension</i>
<span>{{ $t("extensions") }}</span>
</button>
<button class="icon" @click="showShortcuts = true" v-close-popover>
<i class="material-icons">keyboard</i>
<span>{{ $t("shortcuts") }}</span>
</button>
<button class="icon" @click="showSupport = true" v-close-popover>
<i class="material-icons">favorite</i>
<span>{{ $t("support_us") }}</span>
</button>
<button
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=liyasthomas');"
v-close-popover
>
<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"
class="icon"
@click="nativeShare"
v-close-popover
v-tooltip="$t('more')"
>
<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>
<FirebaseLogout @confirm-logout="$refs.user.tippy().hide()" />
</tippy>
</span>
</div>
</header>
<AppAnnouncement v-if="!isOnLine" />
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
</div>
</template>
<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>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import intializePwa from "~/helpers/pwa"
import { fb } from "~/helpers/fb"
// import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
import { currentUser$ } from "~/helpers/fb/auth"
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
import { useReadonlyStream } from "~/helpers/utils/composables"
export default {
export default defineComponent({
setup() {
return {
currentUser: useReadonlyStream(currentUser$, null),
}
},
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,
showLogin: false,
isOnLine: navigator.onLine,
}
},
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))
window.addEventListener("online", () => {
this.isOnLine = true
})
window.addEventListener("offline", () => {
this.isOnLine = false
})
// Initializes the PWA code - checks if the app is installed,
// etc.
this.showInstallPrompt = await intializePwa()
let cookiesAllowed = localStorage.getItem("cookiesAllowed") === "yes"
const cookiesAllowed = getLocalConfig("cookiesAllowed") === "yes"
if (!cookiesAllowed) {
this.$toast.show(this.$t("we_use_cookies"), {
icon: "info",
duration: 5000,
theme: "toasted-primary",
this.$toast.show(this.$t("app.we_use_cookies").toString(), {
icon: "cookie",
duration: 0,
action: [
{
text: this.$t("dismiss"),
onClick: (e, toastObject) => {
localStorage.setItem("cookiesAllowed", "yes")
text: this.$t("action.learn_more").toString(),
onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0)
window
.open("https://docs.hoppscotch.io/privacy", "_blank")
.focus()
},
},
{
text: this.$t("action.dismiss").toString(),
onClick: (_, toastObject) => {
setLocalConfig("cookiesAllowed", "yes")
toastObject.goAway(0)
},
},
],
})
}
// 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: (e, 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: (e, toastObject) => {
// this.showExtensions = true
// localStorage.setItem("showExtensionsToast", "yes")
// toastObject.goAway(0)
// },
// },
// {
// text: this.$t("no"),
// onClick: (e, toastObject) => {
// this.$store.commit("setMiscState", {
// value: false,
// attribute: "showExtensionsToast",
// })
// localStorage.setItem("showExtensionsToast", "no")
// toastObject.goAway(0)
// },
// },
// ],
// })
// }
// }, 5000)
// }
},
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
}
},
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener)
},
}
})
</script>

View File

@@ -1,21 +1,33 @@
<template>
<svg viewBox="0 0 612.001 612.001">
<svg
class="logo"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<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"
d="M17 10.54C16.78 7.44 14.63 5 12 5s-4.78 2.44-5 5.54C4 11.23 2 12.5 2 14c0 2.21 4.5 4 10 4s10-1.79 10-4c0-1.5-2-2.77-5-3.46m-2.07 1.3c-1.9.21-3.96.21-5.86 0c-.04-.28-.07-.56-.07-.84c0-2.2 1.35-4 3-4s3 1.8 3 4c0 .28 0 .56-.07.84z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
props: {
color: {
type: String,
},
},
<style scoped lang="scss">
.logo {
animation: 200ms appear;
}
</script>
@keyframes appear {
0% {
@apply opacity-0;
}
100% {
@apply opacity-100;
}
}
</style>

123
components/app/Search.vue Normal file
View File

@@ -0,0 +1,123 @@
<template>
<SmartModal v-if="show" @close="$emit('hide-modal')">
<template #body>
<input
id="command"
v-model="search"
v-focus
type="text"
name="command"
:placeholder="$t('app.type_a_command_search')"
class="
bg-transparent
border-b border-dividerLight
text-secondaryDark text-base
leading-normal
px-4
pt-2
pb-6
"
/>
<div
class="
divide-y divide-dividerLight
flex flex-col
space-y-4
flex-1
overflow-auto
hide-scrollbar
"
>
<div
v-for="(map, mapIndex) in filteredMappings"
:key="`map-${mapIndex}`"
>
<h5 class="my-2 text-secondaryLight py-2 px-4">
{{ $t(map.section) }}
</h5>
<div
v-for="(shortcut, shortcutIndex) in map.shortcuts"
:key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
class="
rounded
cursor-pointer
flex
py-2
px-4
transition
items-center
group
hover:bg-primaryLight
"
@click="
runAction(shortcut.action)
hideModal()
"
>
<i class="mr-4 opacity-75 material-icons group-hover:opacity-100">
{{ shortcut.icon }}
</i>
<span class="flex flex-1 mr-4 group-hover:text-secondaryDark">
{{ $t(shortcut.label) }}
</span>
<span
v-for="(key, keyIndex) in shortcut.keys"
:key="`map-${mapIndex}-shortcut-${shortcutIndex}-key-${keyIndex}`"
class="shortcut-key"
>
{{ key }}
</span>
</div>
</div>
</div>
</template>
</SmartModal>
</template>
<script>
import { defineComponent } from "@nuxtjs/composition-api"
import { invokeAction } from "~/helpers/actions"
import { spotlight } from "~/helpers/shortcuts"
export default defineComponent({
props: {
show: Boolean,
},
data() {
return {
search: "",
mappings: spotlight,
}
},
computed: {
filteredMappings() {
return this.mappings.filter((mapping) =>
mapping.shortcuts.some((shortcut) =>
shortcut.keywords.some((keyword) =>
keyword.toLowerCase().includes(this.search.toLowerCase())
)
)
)
},
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
runAction(command) {
invokeAction(command, "path_from_invokeAction")
},
},
})
</script>
<style lang="scss" scoped>
.shortcut-key {
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply py-1;
@apply px-2;
@apply inline-flex;
}
</style>

View File

@@ -1,67 +1,18 @@
<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 />
</div>
</fieldset>
<section :id="label.toLowerCase()" class="flex flex-col flex-1 relative">
<slot></slot>
</section>
</template>
<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>
<script lang="ts">
import Vue from "vue"
import { defineComponent } from "@nuxtjs/composition-api"
export default Vue.extend({
computed: {
sectionString(): string {
return `${this.$route.path.replace(/\/+$/, "")}/${this.label}`
},
},
export default defineComponent({
props: {
label: {
type: String,
default: "Section",
},
noLegend: {
type: Boolean,
default: false,
},
},
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>

125
components/app/Share.vue Normal file
View File

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

View File

@@ -1,102 +1,120 @@
<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>
<AppSlideOver :show="show" @close="close()">
<template #content>
<div
class="
bg-primary
border-b border-dividerLight
flex
p-2
top-0
z-10
items-center
sticky
justify-between
"
>
<h3 class="ml-4 heading">{{ $t("app.shortcuts") }}</h3>
<div class="flex">
<ButtonSecondary
icon="close"
class="rounded"
@click.native="close()"
/>
</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 class="bg-primary border-b border-dividerLight">
<div class="flex flex-col my-4 mx-6 search-wrapper">
<input
v-model="filterText"
type="search"
class="
bg-primaryLight
border border-dividerLight
rounded
flex
w-full
py-2
pr-2
pl-8
focus-visible:border-divider
"
:placeholder="$t('action.search')"
/>
</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
class="
divide-y divide-dividerLight
flex flex-col flex-1
overflow-auto
hide-scrollbar
"
>
<div
v-for="(map, mapIndex) in mappings"
:key="`map-${mapIndex}`"
class="space-y-4 py-4 px-6"
>
<h1 class="font-semibold text-secondaryDark">
{{ $t(map.section) }}
</h1>
<div
v-for="(shortcut, shortcutIndex) in map.shortcuts"
:key="`map-${mapIndex}-shortcut-${shortcutIndex}`"
class="flex items-center"
>
<span class="flex flex-1 mr-4">
{{ $t(shortcut.label) }}
</span>
<span
v-for="(key, keyIndex) in shortcut.keys"
:key="`map-${mapIndex}-shortcut-${shortcutIndex}-key-${keyIndex}`"
class="shortcut-key"
>
{{ key }}
</span>
</div>
</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>
</AppSlideOver>
</template>
<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>
<script>
import { getPlatformSpecialKey } from "~/helpers/platformutils"
import { defineComponent } from "@nuxtjs/composition-api"
import shortcuts from "~/helpers/shortcuts"
export default {
export default defineComponent({
props: {
show: Boolean,
},
methods: {
getSpecialKey: getPlatformSpecialKey,
hideModal() {
this.$emit("hide-modal")
data() {
return {
filterText: "",
mappings: shortcuts,
}
},
watch: {
$route() {
this.$emit("close")
},
},
}
methods: {
close() {
this.$emit("close")
},
},
})
</script>
<style lang="scss" scoped>
.shortcut-key {
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply py-1;
@apply px-2;
@apply inline-flex;
}
</style>

View File

@@ -1,307 +1,178 @@
<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
:to="localePath('index')"
:class="linkActive('/')"
v-tooltip.right="$t('home')"
:aria-label="$t('home')"
<aside class="flex h-full justify-between md:flex-col">
<nav class="flex flex-nowrap md:flex-col">
<NuxtLink
v-for="(navigation, index) in primaryNavigation"
:key="`navigation-${index}`"
:to="localePath(navigation.target)"
class="nav-link"
tabindex="0"
>
<AppLogo alt class="material-icons" style="height: 24px" />
</nuxt-link>
<nuxt-link
:to="localePath('realtime')"
:class="linkActive('/realtime')"
v-tooltip.right="$t('realtime')"
>
<i class="material-icons">language</i>
</nuxt-link>
<nuxt-link
:to="localePath('graphql')"
:class="linkActive('/graphql')"
v-tooltip.right="$t('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
:to="localePath('doc')"
:class="linkActive('/doc')"
v-tooltip.right="$t('documentation')"
:aria-label="$t('documentation')"
>
<i class="material-icons">topic</i>
</nuxt-link>
<nuxt-link
:to="localePath('settings')"
:class="linkActive('/settings')"
v-tooltip.right="$t('settings')"
:aria-label="$t('settings')"
>
<i class="material-icons">settings</i>
</nuxt-link>
</nav>
<nav v-if="$route.path == '/'" class="secondary-nav">
<a href="#request" v-tooltip.right="$t('request')">
<i class="material-icons">cloud_upload</i>
</a>
<a href="#options" v-tooltip.right="$t('options')">
<i class="material-icons">toc</i>
</a>
<a href="#response" v-tooltip.right="$t('response')">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/realtime')" class="secondary-nav">
<a href="#request" v-tooltip.right="$t('request')">
<i class="material-icons">cloud_upload</i>
</a>
<a href="#response" v-tooltip.right="$t('communication')">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/graphql')" class="secondary-nav">
<a href="#endpoint" v-tooltip.right="$t('endpoint')">
<i class="material-icons">cloud</i>
</a>
<a href="#schema" v-tooltip.right="$t('schema')">
<i class="material-icons">assignment_returned</i>
</a>
<a href="#query" v-tooltip.right="$t('query')">
<i class="material-icons">cloud_upload</i>
</a>
<a href="#response" v-tooltip.right="$t('response')">
<i class="material-icons">cloud_download</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/doc')" class="secondary-nav">
<a href="#import" v-tooltip.right="$t('import')">
<i class="material-icons">folder</i>
</a>
<a href="#documentation" v-tooltip.right="$t('documentation')">
<i class="material-icons">insert_drive_file</i>
</a>
</nav>
<nav v-else-if="$route.path.includes('/settings')" class="secondary-nav">
<a href="#account" v-tooltip.right="$t('account')">
<i class="material-icons">person</i>
</a>
<a href="#theme" v-tooltip.right="$t('theme')">
<i class="material-icons">brush</i>
</a>
<a href="#extensions" v-tooltip.right="$t('extensions')">
<i class="material-icons">extension</i>
</a>
<a href="#proxy" v-tooltip.right="$t('proxy')">
<i class="material-icons">public</i>
</a>
<i v-if="navigation.icon" class="material-icons">
{{ navigation.icon }}
</i>
<div v-if="navigation.svg" class="h-4 w-4">
<SmartIcon :name="navigation.svg" class="svg-icons" />
</div>
<span v-if="LEFT_SIDEBAR">{{ navigation.title }}</span>
</NuxtLink>
</nav>
<!-- <nav
class="
flex flex-nowrap
p-4
items-center
justify-center
md:(flex-col
space-x-0 space-y-2)
"
>
<ButtonSecondary
v-tippy="{ theme: 'tooltip', placement: 'top' }"
:title="`${$t('app.search')} <kbd>/</kbd>`"
icon="search"
class="rounded"
@click.native="showSearch = true"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip', placement: 'top' }"
:title="$t('app.invite')"
icon="person_add_alt"
class="rounded"
@click.native="showShare = true"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip', placement: 'top' }"
:title="`${$t('support.title')} <kbd>?</kbd>`"
icon="support"
class="rounded"
@click.native="showSupport = true"
/>
</nav> -->
<!-- <AppSearch :show="showSearch" @hide-modal="showSearch = false" />
<AppSupport :show="showSupport" @hide-modal="showSupport = false" />
<AppShare :show="showShare" @hide-modal="showShare = false" /> -->
</aside>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { useSetting } from "~/newstore/settings"
// import { defineActionHandler } from "~/helpers/actions"
export default defineComponent({
setup() {
// const showSearch = ref(false)
// const showSupport = ref(false)
// const showShare = ref(false)
// defineActionHandler("modals.search.toggle", () => {
// showSearch.value = !showSearch.value
// })
// defineActionHandler("modals.support.toggle", () => {
// showSupport.value = !showSupport.value
// })
// defineActionHandler("modals.share.toggle", () => {
// showShare.value = !showShare.value
// })
return {
// showSearch,
// showSupport,
// showShare,
LEFT_SIDEBAR: useSetting("LEFT_SIDEBAR"),
}
},
data() {
return {
primaryNavigation: [
{
target: "index",
icon: "settings_ethernet",
title: this.$t("navigation.rest"),
},
{
target: "graphql",
svg: "graphql",
title: this.$t("navigation.graphql"),
},
{
target: "realtime",
icon: "language",
title: this.$t("navigation.realtime"),
},
{
target: "documentation",
icon: "book",
title: this.$t("navigation.doc"),
},
{
target: "settings",
icon: "settings",
title: this.$t("navigation.settings"),
},
],
}
},
})
</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;
.nav-link {
@apply relative;
@apply p-4;
@apply flex flex-col flex-1;
@apply items-center;
@apply justify-center;
@apply space-y-2;
@apply w-full;
@apply hover:(bg-primaryDark text-secondaryDark);
@apply focus-visible:text-secondaryDark;
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;
&::after {
@apply absolute;
@apply inset-x-0;
@apply md:inset-x-auto;
@apply md:inset-y-0;
@apply bottom-0;
@apply h-auto;
@apply p-0;
@apply md:bottom-auto;
@apply md:left-0;
@apply z-2;
@apply h-0.5;
@apply md:h-full;
@apply w-full;
@apply bg-bgColor;
@apply shadow-2xl;
@apply md:w-0.5;
content: "";
}
nav.primary-nav {
@apply flex-row;
@apply flex-nowrap;
@apply overflow-auto;
@apply bg-bgDarkColor;
@apply space-y-0;
&:focus::after {
@apply bg-divider;
}
padding-bottom: env(safe-area-inset-bottom);
.material-icons,
.svg-icons {
@apply opacity-75;
}
a {
@apply bg-transparent;
@apply my-2;
@apply flex-1;
span {
@apply mt-2;
@apply font-font-medium;
}
&.nuxt-link-exact-active {
@apply bg-transparent;
@apply text-acColor;
@apply fill-current;
&.exact-active-link {
@apply text-secondaryDark;
@apply bg-primaryLight;
@apply hover:text-secondaryDark;
svg {
@apply fill-current;
}
}
.material-icons,
.svg-icons {
@apply opacity-100;
}
}
nav.secondary-nav {
@apply hidden;
&::after {
@apply bg-accent;
}
}
}
</style>
<script>
export default {
methods: {
linkActive(path) {
return {
"nuxt-link-exact-active": this.$route.path === path,
"nuxt-link-active": this.$route.path === path,
}
},
},
mounted() {
window.addEventListener("scroll", (event) => {
let mainNavLinks = document.querySelectorAll("nav ul li a")
let fromTop = window.scrollY
mainNavLinks.forEach(({ hash, classList }) => {
let section = document.querySelector(hash)
if (
section &&
section.offsetTop <= fromTop &&
section.offsetTop + section.offsetHeight > fromTop
) {
classList.add("current")
} else {
classList.remove("current")
}
})
})
},
// watch: {
// $route() {
// // this.$toast.clear();
// },
// },
}
</script>

View File

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

View File

@@ -1,31 +1,97 @@
<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>
<SmartModal
v-if="show"
:title="$t('support.title')"
@close="$emit('hide-modal')"
>
<template #body>
<div class="flex flex-col space-y-2">
<SmartItem
icon="menu_book"
:label="$t('app.documentation')"
to="https://docs.hoppscotch.io"
:description="$t('support.documentation')"
info-icon="chevron_right"
active
blank
@click.native="hideModal()"
/>
<SmartItem
icon="keyboard"
:label="$t('app.keyboard_shortcuts')"
:description="$t('support.shortcuts')"
info-icon="chevron_right"
active
@click.native="
showShortcuts()
hideModal()
"
/>
<SmartItem
icon="auto_awesome"
:label="$t('app.whats_new')"
to="https://docs.hoppscotch.io/changelog"
:description="$t('support.changelog')"
info-icon="chevron_right"
active
blank
@click.native="hideModal()"
/>
<SmartItem
icon="contact_support"
:label="$t('app.chat_with_us')"
:description="$t('support.chat')"
info-icon="chevron_right"
active
@click.native="
chatWithUs()
hideModal()
"
/>
<SmartItem
svg="discord"
:label="$t('app.join_discord_community')"
to="https://hoppscotch.io/discord"
blank
:description="$t('support.community')"
info-icon="chevron_right"
active
@click.native="hideModal()"
/>
<SmartItem
svg="twitter"
:label="$t('app.twitter')"
to="https://twitter.com/hoppscotch_io"
blank
:description="$t('support.twitter')"
info-icon="chevron_right"
active
@click.native="hideModal()"
/>
</div>
</div>
<div slot="body" class="flex flex-col">
<AppContributors />
</div>
<div slot="footer"></div>
</template>
</SmartModal>
</template>
<script>
export default {
import { defineComponent } from "@nuxtjs/composition-api"
import { invokeAction } from "~/helpers/actions"
import { showChat } from "~/helpers/support"
export default defineComponent({
props: {
show: Boolean,
},
methods: {
chatWithUs() {
showChat()
},
showShortcuts() {
invokeAction("flyouts.keybinds.toggle")
},
hideModal() {
this.$emit("hide-modal")
},
},
}
})
</script>

View File

@@ -0,0 +1,147 @@
<template>
<SmartLink
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
:exact="exact"
:blank="blank"
class="
font-bold
py-2
inline-flex
items-center
justify-center
focus:outline-none
focus-visible:bg-accentDark
"
:class="[
color
? `text-${color}-800 bg-${color}-200 hover:(text-${color}-900 bg-${color}-300) focus-visible:(text-${color}-900 bg-${color}-300)`
: `text-accentContrast bg-accent hover:bg-accentDark focus-visible:bg-accentDark`,
label ? 'px-4' : 'px-2',
rounded ? 'rounded-full' : 'rounded',
{ 'opacity-75 cursor-not-allowed': disabled },
{ 'pointer-events-none': loading },
{ 'px-6 py-4 text-lg': large },
{ 'shadow-lg hover:shadow-xl': shadow },
{
'text-white bg-gradient-to-tr from-gradientFrom via-gradientVia to-gradientTo':
gradient,
},
{
'border border-accent hover:border-accentDark focus-visible:border-accentDark':
outline,
},
]"
:disabled="disabled"
:tabindex="loading ? '-1' : '0'"
>
<span
v-if="!loading"
class="inline-flex items-center justify-center whitespace-nowrap"
:class="{ 'flex-row-reverse': reverse }"
>
<i
v-if="icon"
class="material-icons"
:class="[
{ '!text-2xl': large },
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
>
{{ icon }}
</i>
<SmartIcon
v-if="svg"
:name="svg"
class="svg-icons"
:class="[
{ '!h-6 !w-6': large },
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
/>
{{ label }}
<div v-if="shortcut.length" class="ml-2">
<kbd
v-for="(key, index) in shortcut"
:key="`key-${index}`"
class="bg-accentLight rounded ml-1 px-1 inline-flex"
>
{{ key }}
</kbd>
</div>
</span>
<SmartSpinner v-else />
</SmartLink>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
export default defineComponent({
props: {
to: {
type: String,
default: "",
},
exact: {
type: Boolean,
default: true,
},
blank: {
type: Boolean,
default: false,
},
label: {
type: String,
default: "",
},
icon: {
type: String,
default: "",
},
svg: {
type: String,
default: "",
},
color: {
type: String,
default: "",
},
disabled: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
large: {
type: Boolean,
default: false,
},
shadow: {
type: Boolean,
default: false,
},
reverse: {
type: Boolean,
default: false,
},
rounded: {
type: Boolean,
default: false,
},
gradient: {
type: Boolean,
default: false,
},
outline: {
type: Boolean,
default: false,
},
shortcut: {
type: Array,
default: () => [],
},
},
})
</script>

View File

@@ -0,0 +1,137 @@
<template>
<SmartLink
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
:exact="exact"
:blank="blank"
class="
font-medium
py-2
inline-flex
items-center
justify-center
whitespace-nowrap
hover:bg-primaryDark
focus:outline-none
focus-visible:bg-primaryDark
"
:class="[
color
? `text-${color}-500 hover:(text-${color}-600 text-${color}-600)`
: 'text-secondary hover:text-secondaryDark focus-visible:text-secondaryDark',
label ? 'rounded px-4' : 'px-2',
{ 'rounded-full': rounded },
{ 'opacity-75 cursor-not-allowed': disabled },
{ 'flex-row-reverse': reverse },
{ 'px-6 py-4 text-lg': large },
{
'border border-divider hover:border-dividerDark focus-visible:border-dividerDark':
outline,
},
{ 'bg-primaryDark': filled },
]"
:disabled="disabled"
tabindex="0"
>
<i
v-if="icon"
class="material-icons"
:class="[
{ '!text-2xl': large },
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
>
{{ icon }}
</i>
<SmartIcon
v-if="svg"
:name="svg"
class="svg-icons"
:class="[
{ '!h-6 !w-6': large },
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
/>
{{ label }}
<div v-if="shortcut.length" class="ml-2">
<kbd
v-for="(key, index) in shortcut"
:key="`key-${index}`"
class="
bg-dividerLight
rounded
text-secondaryLight
ml-1
px-1
inline-flex
"
>
{{ key }}
</kbd>
</div>
</SmartLink>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
export default defineComponent({
props: {
to: {
type: String,
default: "",
},
exact: {
type: Boolean,
default: true,
},
blank: {
type: Boolean,
default: false,
},
label: {
type: String,
default: "",
},
icon: {
type: String,
default: "",
},
svg: {
type: String,
default: "",
},
color: {
type: String,
default: "",
},
disabled: {
type: Boolean,
default: false,
},
reverse: {
type: Boolean,
default: false,
},
rounded: {
type: Boolean,
default: false,
},
large: {
type: Boolean,
default: false,
},
outline: {
type: Boolean,
default: false,
},
shortcut: {
type: Array,
default: () => [],
},
filled: {
type: Boolean,
default: false,
},
},
})
</script>

View File

@@ -1,84 +1,63 @@
<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>
<SmartModal v-if="show" :title="$t('collection.new')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<input
id="selectLabelAdd"
v-model="name"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="addNewCollection"
/>
<label for="selectLabelAdd">
{{ $t("action.label") }}
</label>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="name"
: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>
</template>
<template #footer>
<span>
<ButtonPrimary
:label="$t('action.save')"
@click.native="addNewCollection"
/>
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
export default {
export default defineComponent({
props: {
show: Boolean,
},
data() {
return {
name: undefined,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
addNewCollection() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_collection_name"))
if (!this.name) {
this.$toast.error(this.$t("collection.invalid_name"), {
icon: "error_outline",
})
return
}
this.$store.commit("postwoman/addNewCollection", {
name: this.$data.name,
flag: "rest",
})
this.$emit("hide-modal")
this.syncCollections()
this.$emit("submit", this.name)
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
this.$data.name = undefined
},
},
}
})
</script>

View File

@@ -1,65 +1,71 @@
<template>
<SmartModal v-if="show" @close="show = false">
<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>
<SmartModal
v-if="show"
:title="$t('folder.new')"
@close="$emit('hide-modal')"
>
<template #body>
<div class="flex flex-col px-2">
<input
id="selectLabelAddFolder"
v-model="name"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="addFolder"
/>
<label for="selectLabelAddFolder">
{{ $t("action.label") }}
</label>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="name"
: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>
</template>
<template #footer>
<span>
<ButtonPrimary :label="$t('action.save')" @click.native="addFolder" />
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
export default {
import { defineComponent } from "@nuxtjs/composition-api"
export default defineComponent({
props: {
show: Boolean,
folder: Object,
folderPath: String,
collectionIndex: Number,
folder: { type: Object, default: () => {} },
folderPath: { type: String, default: null },
collectionIndex: { type: Number, default: null },
},
data() {
return {
name: undefined,
name: null,
}
},
methods: {
addFolder() {
if (!this.name) {
this.$toast.error(this.$t("folder.invalid_name"), {
icon: "error_outline",
})
return
}
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

@@ -0,0 +1,110 @@
<template>
<div v-if="show">
<SmartTabs :id="'collections_tab'" @tab-changed="updateCollectionsType">
<SmartTab
:id="'my-collections'"
:label="$t('collection.my_collections')"
:selected="true"
/>
<SmartTab
v-if="currentUser && currentUser.eaInvited && !doc"
:id="'team-collections'"
:label="$t('collection.team_collections')"
>
<SmartIntersection @intersecting="onTeamSelectIntersect">
<div class="select-wrapper">
<select
id="team"
type="text"
autofocus
class="
bg-transparent
border-b border-transparent
cursor-pointer
flex
font-medium
w-full
py-2
px-4
appearance-none
hover:bg-primaryDark
"
@change="updateSelectedTeam(myTeams[$event.target.value])"
>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>
{{ $t("collection.select_team") }}
</option>
<option
v-for="(team, index) in myTeams"
:key="`team-${index}`"
:value="index"
>
{{ team.name }}
</option>
</select>
</div>
</SmartIntersection>
</SmartTab>
</SmartTabs>
</div>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import gql from "graphql-tag"
import { currentUserInfo$ } from "~/helpers/teams/BackendUserInfo"
import { useReadonlyStream } from "~/helpers/utils/composables"
export default defineComponent({
props: {
doc: Boolean,
show: Boolean,
},
setup() {
return {
currentUser: useReadonlyStream(currentUserInfo$, null),
}
},
data() {
return {
skipTeamsFetching: true,
}
},
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: string) {
this.$emit("update-collection-type", tabID)
},
updateSelectedTeam(team: any) {
this.$emit("update-selected-team", team)
},
},
})
</script>

View File

@@ -1,182 +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 class="material-icons" v-show="!showChildren && !isFiltered">arrow_right</i>
<i class="material-icons" v-show="showChildren || isFiltered">arrow_drop_down</i>
<i class="material-icons">folder</i>
<span>{{ collection.name }}</span>
</button>
<div>
<button
v-if="doc"
class="icon"
@click="$emit('select-collection')"
v-tooltip.left="$t('import')"
>
<i class="material-icons">topic</i>
</button>
<v-popover>
<button class="tooltip-target icon" v-tooltip.left="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="$emit('add-folder', { folder: collection, path: `${collectionIndex}` })"
v-close-popover
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button class="icon" @click="$emit('edit-collection')" v-close-popover>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="confirmRemove = true" v-close-popover>
<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"
>
<CollectionsFolder
:folder="folder"
:folder-index="index"
:folder-path="`${collectionIndex}/${index}`"
:collection-index="collectionIndex"
:doc="doc"
:isFiltered="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"
>
<CollectionsRequest
: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"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
collectionIndex: Number,
collection: Object,
doc: Boolean,
isFiltered: Boolean,
},
data() {
return {
showChildren: false,
dragging: false,
selectedFolder: {},
confirmRemove: false,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
toggleShowChildren() {
this.showChildren = !this.showChildren
},
removeCollection() {
this.$store.commit("postwoman/removeCollection", {
collectionIndex: this.collectionIndex,
flag: "rest",
})
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 = "rest"
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,90 +1,64 @@
<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>
<SmartModal v-if="show" :title="$t('collection.edit')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<input
id="selectLabelEdit"
v-model="name"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="saveCollection"
/>
<label for="selectLabelEdit">
{{ $t("action.label") }}
</label>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="name"
: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>
</template>
<template #footer>
<span>
<ButtonPrimary
:label="$t('action.save')"
@click.native="saveCollection"
/>
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
export default {
export default defineComponent({
props: {
show: Boolean,
editingCollection: Object,
editingCollectionIndex: Number,
placeholderCollName: { type: String, default: null },
},
data() {
return {
name: undefined,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
saveCollection() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_collection_name"))
if (!this.name) {
this.$toast.error(this.$t("collection.invalid_name"), {
icon: "error_outline",
})
return
}
const collectionUpdated = {
...this.$props.editingCollection,
name: this.$data.name,
}
this.$store.commit("postwoman/editCollection", {
collection: collectionUpdated,
collectionIndex: this.$props.editingCollectionIndex,
flag: "rest",
})
this.$emit("hide-modal")
this.syncCollections()
this.$emit("submit", this.name)
this.hideModal()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
})
</script>

View File

@@ -1,85 +1,64 @@
<template>
<SmartModal v-if="show" @close="show = false">
<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>
<SmartModal
v-if="show"
:title="$t('folder.edit')"
@close="$emit('hide-modal')"
>
<template #body>
<div class="flex flex-col px-2">
<input
id="selectLabelEditFolder"
v-model="name"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="editFolder"
/>
<label for="selectLabelEditFolder">
{{ $t("action.label") }}
</label>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="name"
: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>
</template>
<template #footer>
<span>
<ButtonPrimary :label="$t('action.save')" @click.native="editFolder" />
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
export default {
export default defineComponent({
props: {
show: Boolean,
collectionIndex: Number,
folder: Object,
folderIndex: Number,
},
data() {
return {
name: undefined,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
name: null,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
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: "rest",
})
if (!this.name) {
this.$toast.error(this.$t("folder.invalid_name"), {
icon: "error_outline",
})
return
}
this.$emit("submit", this.name)
this.hideModal()
this.syncCollections()
},
hideModal() {
this.name = null
this.$emit("hide-modal")
},
},
}
})
</script>

View File

@@ -1,96 +1,63 @@
<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>
<SmartModal v-if="show" :title="$t('modal.edit_request')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<input
id="selectLabelEditReq"
v-model="requestUpdateData.name"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="saveRequest"
/>
<label for="selectLabelEditReq">
{{ $t("action.label") }}
</label>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="requestUpdateData.name"
@keyup.enter="saveRequest"
:placeholder="request.name"
/>
</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>
</template>
<template #footer>
<span>
<ButtonPrimary :label="$t('action.save')" @click.native="saveRequest" />
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
export default {
export default defineComponent({
props: {
show: Boolean,
collectionIndex: Number,
folderIndex: Number,
folderName: String,
request: Object,
requestIndex: Number,
placeholderReqName: { type: String, default: null },
},
data() {
return {
requestUpdateData: {
name: undefined,
name: null,
},
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
saveRequest() {
const requestUpdated = {
...this.$props.request,
name: this.$data.requestUpdateData.name || this.$props.request.name,
if (!this.requestUpdateData.name) {
this.$toast.error(this.$t("request.invalid_name"), {
icon: "error_outline",
})
return
}
this.$store.commit("postwoman/editRequest", {
requestCollectionIndex: this.$props.collectionIndex,
requestFolderName: this.$props.folderName,
requestFolderIndex: this.$props.folderIndex,
requestNew: requestUpdated,
requestIndex: this.$props.requestIndex,
flag: "rest",
})
this.$emit("submit", this.requestUpdateData)
this.hideModal()
this.syncCollections()
},
hideModal() {
this.requestUpdateData = { name: null }
this.$emit("hide-modal")
},
},
}
})
</script>

View File

@@ -1,184 +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 class="material-icons" v-show="!showChildren && !isFiltered">arrow_right</i>
<i class="material-icons" v-show="showChildren || isFiltered">arrow_drop_down</i>
<i class="material-icons">folder_open</i>
<span>{{ folder.name }}</span>
</button>
</div>
<v-popover>
<button class="tooltip-target icon" v-tooltip.left="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="$emit('add-folder', { folder, path: folderPath })"
v-close-popover
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="$emit('edit-folder', { folder, folderIndex, collectionIndex })"
v-close-popover
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="confirmRemove = true" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren || isFiltered">
<ul v-if="folder.folders && folder.folders.length" class="flex-col">
<li
v-for="(subFolder, subFolderIndex) in folder.folders"
:key="subFolder.name"
class="ml-8 border-l border-brdColor"
>
<CollectionsFolder
:folder="subFolder"
:folder-index="subFolderIndex"
:collection-index="collectionIndex"
:doc="doc"
:folder-path="`${folderPath}/${subFolderIndex}`"
@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"
>
<CollectionsRequest
: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"
import { getSettingSubject } from "~/newstore/settings"
export default {
name: "folder",
props: {
folder: Object,
folderIndex: Number,
collectionIndex: Number,
folderPath: String,
doc: Boolean,
isFiltered: Boolean,
},
data() {
return {
showChildren: false,
dragging: false,
confirmRemove: false,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
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: "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()
},
},
}
</script>

View File

@@ -1,140 +1,208 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<div slot="header">
<div class="row-wrapper">
<h3 class="title">{{ $t("import_export") }} {{ $t("collections") }}</h3>
<div>
<v-popover>
<button class="tooltip-target icon" v-tooltip.left="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button class="icon" @click="readCollectionGist" v-close-popover>
<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
:disabled="
!fb.currentUser ? true : fb.currentUser.provider !== 'github.com' ? true : false
"
class="icon"
@click="createCollectionGist"
v-close-popover
>
<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>
<SmartModal
v-if="show"
:title="`${$t('modal.import_export')} ${$t('modal.collections')}`"
@close="hideModal"
>
<template #actions>
<ButtonSecondary
v-if="mode == 'import_from_my_collections'"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.go_back')"
class="rounded"
icon="arrow_back"
@click.native="
mode = 'import_export'
mySelectedCollectionID = undefined
"
/>
<span>
<tippy
v-if="
mode == 'import_export' && collectionsType.type == 'my-collections'
"
ref="options"
interactive
trigger="click"
theme="popover"
arrow
>
<template #trigger>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.more')"
class="rounded"
icon="more_vert"
/>
</template>
<SmartItem
icon="assignment_returned"
:label="$t('import.from_gist')"
@click.native="
readCollectionGist
$refs.options.tippy().hide()
"
/>
<span
v-tippy="{ theme: 'tooltip' }"
:title="
!currentUser
? $t('export.require_github')
: currentUser.provider !== 'github.com'
? $t('export.require_github')
: null
"
>
<SmartItem
:disabled="
!currentUser
? true
: currentUser.provider !== 'github.com'
? true
: false
"
icon="assignment_turned_in"
:label="$t('export.create_secret_gist')"
@click.native="
createCollectionGist()
$refs.options.tippy().hide()
"
/>
</span>
</tippy>
</span>
</template>
<template #body>
<div v-if="mode == 'import_export'" class="flex flex-col space-y-2">
<SmartItem
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.replace_current')"
icon="folder_special"
:label="$t('action.replace_json')"
@click.native="openDialogChooseFileToReplaceWith"
/>
<input
ref="inputChooseFileToReplaceWith"
class="input"
type="file"
style="display: none"
accept="application/json"
@change="replaceWithJSON"
/>
<SmartItem
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.preserve_current')"
icon="create_new_folder"
:label="$t('import.json')"
@click.native="openDialogChooseFileToImportFrom"
/>
<input
ref="inputChooseFileToImportFrom"
class="input"
type="file"
style="display: none"
accept="application/json"
@change="importFromJSON"
/>
<SmartItem
v-if="collectionsType.type == 'team-collections'"
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.preserve_current')"
icon="folder_shared"
:label="$t('import.from_my_collections')"
@click.native="mode = 'import_from_my_collections'"
/>
<SmartItem
v-tippy="{ theme: 'tooltip' }"
:title="$t('action.download_file')"
icon="drive_file_move"
:label="$t('export.as_json')"
@click.native="exportJSON"
/>
</div>
<div
v-if="mode == 'import_from_my_collections'"
class="flex flex-col px-2"
>
<div class="select-wrapper">
<select
type="text"
class="select"
autofocus
@change="
($event) => {
mySelectedCollectionID = $event.target.value
}
"
>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>
Select Collection
</option>
<option
v-for="(collection, index) in myCollections"
:key="`collection-${index}`"
:value="index"
>
{{ collection.name }}
</option>
</select>
</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="syncCollections">
<i class="material-icons">folder_shared</i>
<span>{{ $t("import_from_sync") }}</span>
</button>
</span>
<button
class="icon"
@click="openDialogChooseFileToReplaceWith"
v-tooltip="$t('replace_current')"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("replace_json") }}</span>
<input
type="file"
@change="replaceWithJSON"
style="display: none"
ref="inputChooseFileToReplaceWith"
accept="application/json"
/>
</button>
<button
class="icon"
@click="openDialogChooseFileToImportFrom"
v-tooltip="$t('preserve_current')"
>
<i class="material-icons">folder_special</i>
<span>{{ $t("import_json") }}</span>
<input
type="file"
@change="importFromJSON"
style="display: none"
ref="inputChooseFileToImportFrom"
accept="application/json"
/>
</button>
</div>
<div v-if="showJsonCode" class="row-wrapper">
<textarea v-model="collectionJson" rows="8" readonly></textarea>
</div>
</div>
<div slot="footer">
<div class="row-wrapper">
</template>
<template #footer>
<div v-if="mode == 'import_from_my_collections'">
<span>
<SmartToggle :on="showJsonCode" @change="showJsonCode = $event">
{{ $t("show_code") }}
</SmartToggle>
</span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="exportJSON" v-tooltip="$t('download_file')">
{{ $t("export") }}
</button>
<ButtonPrimary
:disabled="mySelectedCollectionID == undefined"
icon="create_new_folder"
:label="$t('import.title')"
@click.native="importFromMyCollections"
/>
</span>
</div>
</div>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
import { currentUser$ } from "~/helpers/fb/auth"
import * as teamUtils from "~/helpers/teams/utils"
import { useReadonlyStream } from "~/helpers/utils/composables"
import {
restCollections$,
setRESTCollections,
appendRESTCollections,
} from "~/newstore/collections"
export default {
data() {
return {
fb,
showJsonCode: false,
}
},
subscriptions() {
SYNC_COLLECTIONS: getSettingSubject("syncCollections")
},
export default defineComponent({
props: {
show: Boolean,
collectionsType: { type: Object, default: () => {} },
},
computed: {
collectionJson() {
return JSON.stringify(this.$store.state.postwoman.collections, null, 2)
},
setup() {
return {
myCollections: useReadonlyStream(restCollections$, []),
currentUser: useReadonlyStream(currentUser$, null),
}
},
data() {
return {
showJsonCode: false,
mode: "import_export",
mySelectedCollectionID: undefined,
collectionJson: "",
}
},
methods: {
async createCollectionGist() {
this.getJSONCollection()
await this.$axios
.$post(
"https://api.github.com/gists",
@@ -147,26 +215,26 @@ export default {
},
{
headers: {
Authorization: `token ${fb.currentUser.accessToken}`,
Authorization: `token ${this.currentUser.accessToken}`,
Accept: "application/vnd.github.v3+json",
},
}
)
.then(({ html_url }) => {
this.$toast.success(this.$t("gist_created"), {
.then((res) => {
this.$toast.success(this.$t("export.gist_created"), {
icon: "done",
})
window.open(html_url)
window.open(res.html_url)
})
.catch((error) => {
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error",
.catch((e) => {
this.$toast.error(this.$t("error.something_went_wrong"), {
icon: "error_outline",
})
console.log(error)
console.error(e)
})
},
async readCollectionGist() {
let gist = prompt(this.$t("enter_gist_url"))
const gist = prompt(this.$t("import.gist_url"))
if (!gist) return
await this.$axios
.$get(`https://api.github.com/gists/${gist.split("/").pop()}`, {
@@ -175,17 +243,18 @@ export default {
},
})
.then(({ files }) => {
let collections = JSON.parse(Object.values(files)[0].content)
this.$store.commit("postwoman/replaceCollections", { data: collections, flag: "rest" })
const collections = JSON.parse(Object.values(files)[0].content)
setRESTCollections(collections)
this.fileImported()
this.syncToFBCollections()
})
.catch((error) => {
.catch((e) => {
this.failedImport()
console.log(error)
console.error(e)
})
},
hideModal() {
this.mode = "import_export"
this.mySelectedCollectionID = undefined
this.$emit("hide-modal")
},
openDialogChooseFileToReplaceWith() {
@@ -195,126 +264,210 @@ export default {
this.$refs.inputChooseFileToImportFrom.click()
},
replaceWithJSON() {
let reader = new FileReader()
const reader = new FileReader()
reader.onload = ({ target }) => {
let content = target.result
const content = target.result
let collections = JSON.parse(content)
if (collections[0]) {
let [name, folders, requests] = Object.keys(collections[0])
if (name === "name" && folders === "folders" && requests === "requests") {
const [name, folders, requests] = Object.keys(collections[0])
if (
name === "name" &&
folders === "folders" &&
requests === "requests"
) {
// Do nothing
}
} else if (collections.info && collections.info.schema.includes("v2.1.0")) {
} else if (
collections.info &&
collections.info.schema.includes("v2.1.0")
) {
collections = [this.parsePostmanCollection(collections)]
} else {
this.failedImport()
return
}
this.$store.commit("postwoman/replaceCollections", { data: collections, flag: "rest" })
this.fileImported()
this.syncToFBCollections()
if (this.collectionsType.type === "team-collections") {
teamUtils
.replaceWithJSON(
this.$apollo,
collections,
this.collectionsType.selectedTeam.id
)
.then((status) => {
if (status) {
this.fileImported()
} else {
this.failedImport()
}
})
.catch((e) => {
console.error(e)
this.failedImport()
})
} else {
setRESTCollections(collections)
this.fileImported()
}
}
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0])
this.$refs.inputChooseFileToReplaceWith.value = ""
},
importFromJSON() {
let reader = new FileReader()
const reader = new FileReader()
reader.onload = ({ target }) => {
let content = target.result
const content = target.result
let collections = JSON.parse(content)
if (collections[0]) {
let [name, folders, requests] = Object.keys(collections[0])
if (name === "name" && folders === "folders" && requests === "requests") {
const [name, folders, requests] = Object.keys(collections[0])
if (
name === "name" &&
folders === "folders" &&
requests === "requests"
) {
// Do nothing
}
} else if (collections.info && collections.info.schema.includes("v2.1.0")) {
//replace the variables, postman uses {{var}}, Hoppscotch uses <<var>>
collections = JSON.parse(content.replaceAll(/{{([a-z]+)}}/gi, "<<$1>>"))
} else if (
collections.info &&
collections.info.schema.includes("v2.1.0")
) {
// replace the variables, postman uses {{var}}, Hoppscotch uses <<var>>
collections = JSON.parse(
content.replaceAll(/{{([a-z]+)}}/gi, "<<$1>>")
)
collections = [this.parsePostmanCollection(collections)]
} else {
this.failedImport()
return
}
this.$store.commit("postwoman/importCollections", { data: collections, flag: "rest" })
this.fileImported()
this.syncToFBCollections()
if (this.collectionsType.type === "team-collections") {
teamUtils
.importFromJSON(
this.$apollo,
collections,
this.collectionsType.selectedTeam.id
)
.then((status) => {
if (status) {
this.$emit("update-team-collections")
this.fileImported()
} else {
this.failedImport()
}
})
.catch((e) => {
console.error(e)
this.failedImport()
})
} else {
appendRESTCollections(collections)
this.fileImported()
}
}
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0])
this.$refs.inputChooseFileToImportFrom.value = ""
},
exportJSON() {
let text = this.collectionJson
text = text.replace(/\n/g, "\r\n")
let blob = new Blob([text], {
type: "text/json",
})
let anchor = document.createElement("a")
anchor.download = "hoppscotch-collection.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",
})
importFromMyCollections() {
teamUtils
.importFromMyCollections(
this.$apollo,
this.mySelectedCollectionID,
this.collectionsType.selectedTeam.id
)
.then((success) => {
if (success) {
this.fileImported()
this.$emit("update-team-collections")
} else {
this.failedImport()
}
})
.catch((e) => {
console.error(e)
this.failedImport()
})
},
syncCollections() {
this.$store.commit("postwoman/replaceCollections", {
data: fb.currentCollections,
flag: "rest",
})
this.fileImported()
},
syncToFBCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
async getJSONCollection() {
if (this.collectionsType.type === "my-collections") {
this.collectionJson = JSON.stringify(this.myCollections, null, 2)
} else {
this.collectionJson = await teamUtils.exportAsJSON(
this.$apollo,
this.collectionsType.selectedTeam.id
)
}
return this.collectionJson
},
exportJSON() {
this.getJSONCollection()
const dataToWrite = this.collectionJson
const file = new Blob([dataToWrite], { type: "application/json" })
const a = document.createElement("a")
const url = URL.createObjectURL(file)
a.href = url
// TODO get uri from meta
a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
document.body.appendChild(a)
a.click()
this.$toast.success(this.$t("state.download_started"), {
icon: "downloading",
})
setTimeout(() => {
document.body.removeChild(a)
URL.revokeObjectURL(url)
}, 1000)
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
this.$toast.success(this.$t("state.file_imported"), {
icon: "folder_shared",
})
},
failedImport() {
this.$toast.error(this.$t("import_failed"), {
icon: "error",
this.$toast.error(this.$t("import.failed"), {
icon: "error_outline",
})
},
parsePostmanCollection({ info, name, item }) {
let postwomanCollection = {
const hoppscotchCollection = {
name: "",
folders: [],
requests: [],
}
postwomanCollection.name = info ? info.name : name
hoppscotchCollection.name = info ? info.name : name
if (item && item.length > 0) {
for (let collectionItem of item) {
for (const collectionItem of item) {
if (collectionItem.request) {
if (postwomanCollection.hasOwnProperty("folders")) {
postwomanCollection.name = info ? info.name : name
postwomanCollection.requests.push(this.parsePostmanRequest(collectionItem))
if (
Object.prototype.hasOwnProperty.call(
hoppscotchCollection,
"folders"
)
) {
hoppscotchCollection.name = info ? info.name : name
hoppscotchCollection.requests.push(
this.parsePostmanRequest(collectionItem)
)
} else {
postwomanCollection.name = name ? name : ""
postwomanCollection.requests.push(this.parsePostmanRequest(collectionItem))
hoppscotchCollection.name = name || ""
hoppscotchCollection.requests.push(
this.parsePostmanRequest(collectionItem)
)
}
} else if (this.hasFolder(collectionItem)) {
postwomanCollection.folders.push(this.parsePostmanCollection(collectionItem))
hoppscotchCollection.folders.push(
this.parsePostmanCollection(collectionItem)
)
} else {
postwomanCollection.requests.push(this.parsePostmanRequest(collectionItem))
hoppscotchCollection.requests.push(
this.parsePostmanRequest(collectionItem)
)
}
}
}
return postwomanCollection
return hoppscotchCollection
},
parsePostmanRequest({ name, request }) {
let pwRequest = {
const pwRequest = {
url: "",
path: "",
method: "",
@@ -334,20 +487,28 @@ export default {
}
pwRequest.name = name
let requestObjectUrl = request.url.raw.match(/^(.+:\/\/[^\/]+|{[^\/]+})(\/[^\?]+|).*$/)
if (requestObjectUrl) {
pwRequest.url = requestObjectUrl[1]
pwRequest.path = requestObjectUrl[2] ? requestObjectUrl[2] : ""
if (request.url) {
const requestObjectUrl = request.url.raw.match(
/^(.+:\/\/[^/]+|{[^/]+})(\/[^?]+|).*$/
)
if (requestObjectUrl) {
pwRequest.url = requestObjectUrl[1]
pwRequest.path = requestObjectUrl[2] ? requestObjectUrl[2] : ""
}
}
pwRequest.method = request.method
let itemAuth = request.auth ? request.auth : ""
let authType = itemAuth ? itemAuth.type : ""
const itemAuth = request.auth ? request.auth : ""
const authType = itemAuth ? itemAuth.type : ""
if (authType === "basic") {
pwRequest.auth = "Basic Auth"
pwRequest.httpUser =
itemAuth.basic[0].key === "username" ? itemAuth.basic[0].value : itemAuth.basic[1].value
itemAuth.basic[0].key === "username"
? itemAuth.basic[0].value
: itemAuth.basic[1].value
pwRequest.httpPassword =
itemAuth.basic[0].key === "password" ? itemAuth.basic[0].value : itemAuth.basic[1].value
itemAuth.basic[0].key === "password"
? itemAuth.basic[0].value
: itemAuth.basic[1].value
} else if (authType === "oauth2") {
pwRequest.auth = "OAuth 2.0"
pwRequest.bearerToken =
@@ -358,26 +519,28 @@ export default {
pwRequest.auth = "Bearer Token"
pwRequest.bearerToken = itemAuth.bearer[0].value
}
let requestObjectHeaders = request.header
const requestObjectHeaders = request.header
if (requestObjectHeaders) {
pwRequest.headers = requestObjectHeaders
for (let header of pwRequest.headers) {
for (const header of pwRequest.headers) {
delete header.name
delete header.type
}
}
let requestObjectParams = request.url.query
if (requestObjectParams) {
pwRequest.params = requestObjectParams
for (let param of pwRequest.params) {
delete param.disabled
if (request.url) {
const requestObjectParams = request.url.query
if (requestObjectParams) {
pwRequest.params = requestObjectParams
for (const param of pwRequest.params) {
delete param.disabled
}
}
}
if (request.body) {
if (request.body.mode === "urlencoded") {
let params = request.body.urlencoded
pwRequest.bodyParams = params ? params : []
for (let param of pwRequest.bodyParams) {
const params = request.body.urlencoded
pwRequest.bodyParams = params || []
for (const param of pwRequest.bodyParams) {
delete param.type
}
} else if (request.body.mode === "raw") {
@@ -388,8 +551,8 @@ export default {
return pwRequest
},
hasFolder(item) {
return item.hasOwnProperty("item")
return Object.prototype.hasOwnProperty.call(item, "item")
},
},
}
})
</script>

View File

@@ -1,130 +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
class="icon"
@click="!doc ? selectRequest() : {}"
v-tooltip="!doc ? $t('use_request') : ''"
>
<span :class="getRequestLabelColor(request.method)">{{ request.method }}</span>
<span>{{ request.name }}</span>
</button>
</div>
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="
$emit('edit-request', {
collectionIndex,
folderIndex,
folderName,
request,
requestIndex,
})
"
v-close-popover
>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="confirmRemove = true" v-close-popover>
<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"
import { getSettingSubject } from "~/newstore/settings"
export default {
props: {
request: Object,
collectionIndex: Number,
folderIndex: Number,
folderName: String,
requestIndex: Number,
doc: Boolean,
},
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,
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
)
}
},
selectRequest() {
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.$store.commit("postwoman/removeRequest", {
collectionIndex: this.$props.collectionIndex,
folderName: this.$props.folderName,
requestIndex: this.$props.requestIndex,
flag: "rest",
})
this.$toast.error(this.$t("deleted"), {
icon: "delete",
})
this.confirmRemove = false
this.syncCollections()
},
getRequestLabelColor(method) {
return this.requestMethodLabels[method.toLowerCase()] || this.requestMethodLabels.default
},
},
}
</script>

View File

@@ -1,97 +1,98 @@
<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>
<SmartModal v-if="show" :title="$t('collection.save_as')" @close="hideModal">
<template #body>
<div class="flex flex-col px-2">
<div class="flex relative">
<input
id="selectLabelSaveReq"
v-model="requestName"
v-focus
class="input floating-input"
placeholder=" "
type="text"
@keyup.enter="saveRequestAs"
/>
<label for="selectLabelSaveReq">
{{ $t("request.name") }}
</label>
</div>
<label class="px-4 pt-4 pb-4">
{{ $t("collection.select_location") }}
</label>
<CollectionsGraphql
v-if="mode === 'graphql'"
:doc="false"
:show-coll-actions="false"
:picked="picked"
:saving-mode="true"
@select="onSelect"
/>
<Collections
v-else
:picked="picked"
:save-request="true"
@select="onSelect"
@update-collection="collectionsType.type = $event"
@update-coll-type="onUpdateCollType"
/>
</div>
</div>
<div slot="body" class="flex flex-col">
<label for="selectLabel">{{ $t("token_req_name") }}</label>
<input type="text" id="selectLabel" v-model="requestData.name" @keyup.enter="saveRequestAs" />
<ul>
<li>
<label for="selectCollection">{{ $t("collection") }}</label>
<span class="select-wrapper">
<select type="text" id="selectCollection" v-model="requestData.collectionIndex">
<option :key="undefined" :value="undefined" hidden disabled selected>
{{ $t("select_collection") }}
</option>
<option
v-for="(collection, index) in $store.state.postwoman.collections"
:key="index"
:value="index"
>
{{ collection.name }}
</option>
</select>
</span>
</li>
</ul>
<label>{{ $t("folder") }}</label>
<SmartAutoComplete
:placeholder="$t('search')"
:source="folders"
:spellcheck="false"
v-model="requestData.folderName"
/>
<ul>
<li>
<label for="selectRequest">{{ $t("request") }}</label>
<span class="select-wrapper">
<select type="text" id="selectRequest" v-model="requestData.requestIndex">
<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>
</template>
<template #footer>
<span>
<ButtonPrimary
:label="$t('action.save')"
@click.native="saveRequestAs"
/>
<ButtonSecondary
:label="$t('action.cancel')"
@click.native="hideModal"
/>
</span>
</template>
</SmartModal>
</template>
<script>
import { fb } from "~/helpers/fb"
import { getSettingSubject } from "~/newstore/settings"
import { defineComponent } from "@nuxtjs/composition-api"
import * as teamUtils from "~/helpers/teams/utils"
import {
saveRESTRequestAs,
editRESTRequest,
editGraphqlRequest,
saveGraphqlRequestAs,
} from "~/newstore/collections"
import { getGQLSession, useGQLRequestName } from "~/newstore/GQLSession"
import {
getRESTRequest,
useRESTRequestName,
setRESTSaveContext,
} from "~/newstore/RESTSession"
export default {
export default defineComponent({
props: {
// mode can be either "graphql" or "rest"
mode: { type: String, default: "rest" },
show: Boolean,
editingRequest: Object,
},
setup(props) {
return {
requestName:
props.mode === "rest" ? useRESTRequestName() : useGQLRequestName(),
}
},
data() {
return {
defaultRequestName: "Untitled Request",
requestData: {
name: undefined,
name: this.requestName,
collectionIndex: undefined,
folderName: undefined,
requestIndex: undefined,
},
}
},
subscriptions() {
return {
SYNC_COLLECTIONS: getSettingSubject("syncCollections"),
collectionsType: {
type: "my-collections",
selectedTeam: undefined,
},
picked: null,
}
},
watch: {
@@ -108,122 +109,134 @@ export default {
this.$data.requestData.name = name || this.$data.defaultRequestName
},
},
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
}
},
},
methods: {
syncCollections() {
if (fb.currentUser !== null && this.SYNC_COLLECTIONS) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)),
"collections"
onUpdateCollType(newCollType) {
this.collectionsType = newCollType
},
onSelect({ picked }) {
this.picked = picked
},
async saveRequestAs() {
if (!this.requestName) {
this.$toast.error(this.$t("error.empty_req_name"), {
icon: "error_outline",
})
return
}
if (this.picked == null) {
this.$toast.error(this.$t("collection.select"), {
icon: "error_outline",
})
return
}
const requestUpdated =
this.mode === "rest" ? getRESTRequest() : getGQLSession()
// Filter out all REST file inputs
if (this.mode === "rest" && requestUpdated.bodyParams) {
requestUpdated.bodyParams = requestUpdated.bodyParams.map((param) =>
param?.value?.[0] instanceof File ? { ...param, value: "" } : param
)
}
},
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,
}
if (this.picked.pickedType === "my-request") {
editRESTRequest(
this.picked.folderPath,
this.picked.requestIndex,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: this.picked.folderPath,
requestIndex: this.picked.requestIndex,
})
} else if (this.picked.pickedType === "my-folder") {
const insertionIndex = saveRESTRequestAs(
this.picked.folderPath,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: this.picked.folderPath,
requestIndex: insertionIndex,
})
} else if (this.picked.pickedType === "my-collection") {
const insertionIndex = saveRESTRequestAs(
`${this.picked.collectionIndex}`,
requestUpdated
)
setRESTSaveContext({
originLocation: "user-collection",
folderPath: `${this.picked.collectionIndex}`,
requestIndex: insertionIndex,
})
} else if (this.picked.pickedType === "teams-request") {
teamUtils.overwriteRequestTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.picked.requestID
)
setRESTSaveContext({
originLocation: "team-collection",
requestID: this.picked.requestID,
})
} else if (this.picked.pickedType === "teams-folder") {
const req = await teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.folderID
)
this.$store.commit("postwoman/saveRequestAs", {
request: requestUpdated,
collectionIndex: this.$data.requestData.collectionIndex,
folderName: this.$data.requestData.folderName,
requestIndex: this.$data.requestData.requestIndex,
flag: "rest",
if (req && req.id) {
setRESTSaveContext({
originLocation: "team-collection",
requestID: req.id,
teamID: this.collectionsType.selectedTeam.id,
collectionID: this.picked.folderID,
})
}
} else if (this.picked.pickedType === "teams-collection") {
const req = await teamUtils.saveRequestAsTeams(
this.$apollo,
JSON.stringify(requestUpdated),
requestUpdated.name,
this.collectionsType.selectedTeam.id,
this.picked.collectionID
)
if (req && req.id) {
setRESTSaveContext({
originLocation: "team-collection",
requestID: req.id,
teamID: this.collectionsType.selectedTeam.id,
collectionID: this.picked.collectionID,
})
}
} else if (this.picked.pickedType === "gql-my-request") {
editGraphqlRequest(
this.picked.folderPath,
this.picked.requestIndex,
requestUpdated
)
} else if (this.picked.pickedType === "gql-my-folder") {
saveGraphqlRequestAs(this.picked.folderPath, requestUpdated)
} else if (this.picked.pickedType === "gql-my-collection") {
saveGraphqlRequestAs(`${this.picked.collectionIndex}`, requestUpdated)
}
this.$toast.success(this.$t("request.added"), {
icon: "post_add",
})
this.hideModal()
this.syncCollections()
},
hideModal() {
this.picked = null
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>

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