Compare commits

...

823 Commits

Author SHA1 Message Date
Liyas Thomas
08bb47da1d 🔖 v1.9.0 2020-02-24 18:43:14 +05:30
Liyas Thomas
4fad3808a2 🔖 v1.9.0 2020-02-24 18:36:14 +05:30
Liyas Thomas
f05a875a05 Merge pull request #591 from liyasthomas/feature/env-manager
Environment Mangement
2020-02-24 14:14:18 +05:30
Liyas Thomas
4f7f2ba361 Merge branch 'master' into feature/env-manager 2020-02-24 13:52:30 +05:30
Liyas Thomas
0cfe87e65c Updated contributors list 2020-02-24 12:21:00 +05:30
Andrew Bastin
5ec9944f2a Merge pull request #594 from AndrewBastin/feat/post-raw-type-handle
POST request body editor reacts to the content type
2020-02-24 00:44:16 -05:00
Andrew Bastin
fa339a5183 Updated POST request body to react to the Content Type 2020-02-23 23:24:23 -05:00
Andrew Bastin
5936a06ad1 Added editorutils file with a utility function to convert mimetype to editor modes 2020-02-23 23:23:18 -05:00
Jacob Anavisca
c21bbf1022 Merge branch 'master' into feature/env-manager 2020-02-23 22:21:55 -05:00
Jacob Anavisca
00fa17b31f Review Updates 2020-02-23 22:21:10 -05:00
John Harker
6e03c8d236 Merge pull request #593 from dmitryyankowski/patch-1
Fix variablesJSONString store default for GraphQL page
2020-02-24 01:06:15 +00:00
Dmitry Yankowski
7022ef5f7e Fix variables JSON string
I don't have any variables set, and when running a mutation; I get the following error:

```
Error SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at VueComponent._callee$ (graphql.vue?f047:505)
    at tryCatch (runtime.js?96cf:45)
    at Generator.invoke [as _invoke] (runtime.js?96cf:271)
    at Generator.prototype.<computed> [as next] (runtime.js?96cf:97)
    at asyncGeneratorStep (asyncToGenerator.js?1da1:3)
    at _next (asyncToGenerator.js?1da1:25)
    at eval (asyncToGenerator.js?1da1:32)
    at new Promise (<anonymous>)
    at VueComponent.eval (asyncToGenerator.js?1da1:21)
```

Setting the `variablesJSONString` variable to the correct default (`{}`) fixes this issue :)
2020-02-23 19:42:59 -05:00
Liyas Thomas
54d590765f Typo 2020-02-24 00:48:39 +05:30
Liyas Thomas
d24c572d7f Firebase sync 2020-02-24 00:30:22 +05:30
Liyas Thomas
010be95ed5 Lint + few best practices 2020-02-23 22:43:12 +05:30
Jacob Anavisca
59ca8cb2c6 Merge branch 'master' into feature/env-manager 2020-02-23 11:39:44 -05:00
Jacob Anavisca
15dc0ad9ac Env management 2020-02-23 11:38:15 -05:00
Andrew Bastin
f690ea01c4 Merge pull request #590 from AndrewBastin/feat/gql-hints
GraphQL Query Autocompletion
2020-02-22 22:04:08 -05:00
Liyas Thomas
9c09a8128a Lint 2020-02-23 06:58:13 +05:30
Andrew Bastin
16779d496e Updated GQL Query Editor code to show autocompletion 2020-02-22 19:25:34 -05:00
Andrew Bastin
3ab7318b25 Added graphql-language-service-interface as dependency 2020-02-22 19:24:59 -05:00
Liyas Thomas
a2b7e039d5 Merge pull request #589 from liyasthomas/refactor/lint
Refactor/lint
2020-02-22 23:49:12 +05:30
Liyas Thomas
a68e88826f Merge branch 'refactor/lint' of https://github.com/liyasthomas/postwoman into refactor/lint 2020-02-22 23:14:32 +05:30
Liyas Thomas
7c8545c21b Merge pull request #588 from liyasthomas/master
Even
2020-02-22 23:13:53 +05:30
Liyas Thomas
d17c3b4aa3 Merge branch 'refactor/lint' of https://github.com/liyasthomas/postwoman into refactor/lint 2020-02-22 23:09:13 +05:30
Liyas Thomas
a0529b1cdd 💫 Butter smooth animations and transitions 2020-02-22 23:06:32 +05:30
Liyas Thomas
1f0c77c3bf Merge pull request #587 from liyasthomas/dependabot/npm_and_yarn/firebase-7.9.1
chore(deps): bump firebase from 7.9.0 to 7.9.1
2020-02-22 06:21:12 +05:30
dependabot-preview[bot]
56acfab2b2 chore(deps): bump firebase from 7.9.0 to 7.9.1
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 7.9.0 to 7.9.1.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@7.9.0...firebase@7.9.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-22 00:14:02 +00:00
Liyas Thomas
256cef9047 Merge pull request #585 from liyasthomas/dependabot/npm_and_yarn/firebase-7.9.0
chore(deps): bump firebase from 7.8.2 to 7.9.0
2020-02-21 13:18:41 +05:30
dependabot-preview[bot]
7d3750e54c chore(deps): bump firebase from 7.8.2 to 7.9.0
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 7.8.2 to 7.9.0.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@7.8.2...firebase@7.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-21 07:17:25 +00:00
Liyas Thomas
f021d080af Merge pull request #584 from liyasthomas/dependabot/npm_and_yarn/vue-virtual-scroll-list-1.4.6
chore(deps): bump vue-virtual-scroll-list from 1.4.5 to 1.4.6
2020-02-21 12:45:04 +05:30
Liyas Thomas
293400fd76 Merge pull request #586 from liyasthomas/master
Even
2020-02-21 12:16:41 +05:30
dependabot-preview[bot]
c495ca5256 chore(deps): bump vue-virtual-scroll-list from 1.4.5 to 1.4.6
Bumps [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list) from 1.4.5 to 1.4.6.
- [Release notes](https://github.com/tangbc/vue-virtual-scroll-list/releases)
- [Commits](https://github.com/tangbc/vue-virtual-scroll-list/compare/v1.4.5...v1.4.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-21 06:25:12 +00:00
Liyas Thomas
956c7bf93a Merge pull request #582 from levrik/patch-1
Update link to extension repo in README
2020-02-21 08:13:30 +05:30
Andrew Bastin
219d88851e Merge branch 'master' into patch-1 2020-02-20 19:30:29 -05:00
Andrew Bastin
9b9fb62596 Merge pull request #583 from levrik/extension-check
Adapt extension check to new extensions
2020-02-20 19:29:16 -05:00
Levin Rickert
f636e7dbd4 Adapt extension check to new extensions 2020-02-20 19:36:30 +01:00
Levin Rickert
33f2341f7f Update link to extension repo in README 2020-02-20 19:22:10 +01:00
Liyas Thomas
f5bbcb2777 Merge pull request #578 from liyasthomas/refactor/lint
Refactor/lint
2020-02-20 10:12:53 +05:30
jamesgeorge007
5a56081a29 fix: remove unused code snippet 2020-02-20 09:46:07 +05:30
jamesgeorge007
d2b73a8942 refactor: nested destructuring 2020-02-20 09:45:19 +05:30
Liyas Thomas
09a35cf10a 🚨 Lint 2020-02-20 08:52:42 +05:30
Liyas Thomas
eb7ac7bfc4 Merge pull request #579 from liyasthomas/master
Even
2020-02-20 08:45:15 +05:30
Liyas Thomas
a98636ed39 Merge pull request #573 from levrik/unify-extensions
Unify Chrome and Firefox extensions
2020-02-20 08:06:33 +05:30
Liyas Thomas
73a2a0a127 Updated color codes, minor UI tweaks 2020-02-20 08:01:22 +05:30
Andrew Bastin
494dc72eb9 Merge branch 'master' into unify-extensions 2020-02-19 21:14:57 -05:00
Liyas Thomas
4665dbc372 🚨 Lint 2020-02-19 09:29:49 +05:30
Liyas Thomas
0b6671d538 🎨 Improving structure / format of the code 2020-02-18 23:56:22 +05:30
Liyas Thomas
392c97f35f Even 2020-02-18 22:13:07 +05:30
Liyas Thomas
8629eda6d4 📱 Working on responsive design 2020-02-18 22:10:53 +05:30
Liyas Thomas
8507f11175 Merge pull request #576 from liyasthomas/dependabot/npm_and_yarn/vue-virtual-scroll-list-1.4.5
chore(deps): bump vue-virtual-scroll-list from 1.4.4 to 1.4.5
2020-02-18 07:20:20 +05:30
dependabot-preview[bot]
ae6d33febd chore(deps): bump vue-virtual-scroll-list from 1.4.4 to 1.4.5
Bumps [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list) from 1.4.4 to 1.4.5.
- [Release notes](https://github.com/tangbc/vue-virtual-scroll-list/releases)
- [Commits](https://github.com/tangbc/vue-virtual-scroll-list/compare/v1.4.4...v1.4.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-18 01:05:27 +00:00
Liyas Thomas
54e11170fb Merge pull request #574 from liyasthomas/feature/postmanParsing
Postman collection parsing
2020-02-17 14:26:12 +05:30
Levin Rickert
66eecf5e37 Unify Chrome and Firefox extensions 2020-02-16 15:48:10 +01:00
Jacob Anavisca
f7b1e876ad Merge branch 'master' into feature/postmanParsing 2020-02-15 17:39:28 -05:00
Jacob Anavisca
ccff68ad18 Postman collection parsing 2020-02-15 17:36:38 -05:00
James George
112c140ce7 Merge pull request #572 from liyasthomas/hotfix/share
fix: drop the toast which doesn't show up
2020-02-15 13:40:48 +05:30
jamesgeorge007
c2cd9f0865 fix: drop toast 2020-02-15 12:00:45 +05:30
Liyas Thomas
749e89e362 Merge pull request #571 from liyasthomas/feature/native-share
 Native share + updated meta description
2020-02-15 11:42:18 +05:30
jamesgeorge007
7241bbbb6d feat: show toast info if Web Share API is not supported 2020-02-15 11:19:38 +05:30
jamesgeorge007
edb7bef5a3 fix: use Vue.js on-click directive 2020-02-15 11:17:43 +05:30
Liyas Thomas
436de528e9 Native share + updated meta description 2020-02-15 09:53:26 +05:30
Liyas Thomas
7f0f932aca Merge pull request #570 from liyasthomas/dependabot/npm_and_yarn/firebase-7.8.2
chore(deps): bump firebase from 7.8.1 to 7.8.2
2020-02-15 07:12:59 +05:30
dependabot-preview[bot]
73d2d58da9 chore(deps): bump firebase from 7.8.1 to 7.8.2
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 7.8.1 to 7.8.2.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@7.8.1...firebase@7.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-15 01:24:58 +00:00
Liyas Thomas
777b201c1f Merge pull request #569 from liyasthomas/dependabot/npm_and_yarn/cypress-4.0.2
chore(deps-dev): bump cypress from 4.0.1 to 4.0.2
2020-02-15 06:52:32 +05:30
dependabot-preview[bot]
11ff85c56c chore(deps-dev): bump cypress from 4.0.1 to 4.0.2
Bumps [cypress](https://github.com/cypress-io/cypress) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v4.0.1...v4.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-15 00:14:39 +00:00
Liyas Thomas
a9ed1c0fe8 🔧 Minor under the hood changes according to HTML specs 2020-02-13 17:13:11 +05:30
Liyas Thomas
9a06b19288 Merge pull request #568 from liyasthomas/fix/collection-sync
Added create collection and save request syncs
2020-02-13 15:28:31 +05:30
Liyas Thomas
516610a820 Better Collections Sync 2020-02-13 15:12:17 +05:30
Jacob Anavisca
8b989924a4 Added create collection and save request syncs 2020-02-13 00:00:19 -05:00
Liyas Thomas
bd3e1b7592 Merge pull request #566 from AndrewBastin/refactor/headers
Moved common headers to a separate file
2020-02-11 17:46:05 +05:30
James George
af18b95ffa Merge branch 'master' into refactor/headers 2020-02-11 15:52:54 +05:30
jamesgeorge007
9ecec8ce17 refactor: object shorthand 2020-02-11 15:14:03 +05:30
jamesgeorge007
f2f097bb7e refactor: use relative imports 2020-02-11 15:09:07 +05:30
jamesgeorge007
27da1c8e49 refactor: use relative imports 2020-02-11 15:07:43 +05:30
Liyas Thomas
015fd24e03 Minor UI tweaks 2020-02-11 08:51:34 +05:30
Liyas Thomas
1306b78f63 Merge branch 'master' into refactor/headers 2020-02-11 07:02:32 +05:30
Liyas Thomas
ad0b342d89 Merge pull request #565 from liyasthomas/dependabot/npm_and_yarn/cypress-4.0.1
chore(deps-dev): bump cypress from 4.0.0 to 4.0.1
2020-02-11 07:00:51 +05:30
Andrew Bastin
6d463dcfef Updated commonHeaders definition to use the imported ones 2020-02-10 18:12:31 -05:00
Andrew Bastin
965923116d Added Common Headers to a separate file 2020-02-10 18:12:21 -05:00
dependabot-preview[bot]
3281adce65 chore(deps-dev): bump cypress from 4.0.0 to 4.0.1
Bumps [cypress](https://github.com/cypress-io/cypress) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v4.0.0...v4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 22:49:31 +00:00
Liyas Thomas
74f6be6123 Merge pull request #564 from liyasthomas/dependabot/npm_and_yarn/yargs-parser-17.0.0
chore(deps): bump yargs-parser from 16.1.0 to 17.0.0
2020-02-11 04:17:27 +05:30
dependabot-preview[bot]
74b997ba49 chore(deps): bump yargs-parser from 16.1.0 to 17.0.0
Bumps [yargs-parser](https://github.com/yargs/yargs-parser) from 16.1.0 to 17.0.0.
- [Release notes](https://github.com/yargs/yargs-parser/releases)
- [Changelog](https://github.com/yargs/yargs-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/yargs-parser/compare/v16.1.0...v17.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 22:30:43 +00:00
Liyas Thomas
b7c6f3e2bb Merge pull request #561 from liyasthomas/dependabot/npm_and_yarn/firebase-7.8.1
chore(deps): bump firebase from 7.8.0 to 7.8.1
2020-02-08 06:17:47 +05:30
dependabot-preview[bot]
8506275f90 chore(deps): bump firebase from 7.8.0 to 7.8.1
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 7.8.0 to 7.8.1.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@7.8.0...firebase@7.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 00:32:17 +00:00
Liyas Thomas
64c3a82189 Merge pull request #562 from liyasthomas/dependabot/npm_and_yarn/cypress-4.0.0
chore(deps-dev): bump cypress from 3.8.3 to 4.0.0
2020-02-08 06:00:08 +05:30
dependabot-preview[bot]
23b1d94808 chore(deps-dev): bump cypress from 3.8.3 to 4.0.0
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.8.3 to 4.0.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.8.3...v4.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 00:14:37 +00:00
James George
0a9712d227 Merge pull request #559 from liyasthomas/tweaks
chore: use typeof as an operator and make use of localizable strings
2020-02-07 15:28:31 +05:30
jamesgeorge007
6575d03f45 refactor: use localizable string 2020-02-07 14:58:03 +05:30
jamesgeorge007
6037daedcd refactor: use localizable string 2020-02-07 14:57:57 +05:30
jamesgeorge007
a351abd5d9 refactor: use typeof as an operator 2020-02-07 14:44:14 +05:30
jamesgeorge007
8b00bb59de refactor: use typeof as an operator 2020-02-07 14:43:13 +05:30
Liyas Thomas
910c20bd00 📱 Working on responsive design 2020-02-07 09:06:52 +05:30
Liyas Thomas
885318623f Merge pull request #556 from AndrewBastin/master
Fixed typo in translation file for Auto theme
2020-02-07 07:02:06 +05:30
Andrew Bastin
e1df6105ed Fixed typo in translation file for Auto theme 2020-02-06 12:48:54 -05:00
Andrew Bastin
c4879d598b Merge pull request #551 from AndrewBastin/feat/extension-toggle
Added toggle to decide whether extensions should be used
2020-02-05 13:34:20 -05:00
Andrew Bastin
cc9cfa53fa Merge branch 'master' into feat/extension-toggle 2020-02-05 13:17:30 -05:00
Liyas Thomas
996bb206c6 Merge pull request #554 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/pwa-3.0.0-beta.20
chore(deps): bump @nuxtjs/pwa from 3.0.0-beta.19 to 3.0.0-beta.20
2020-02-05 23:42:27 +05:30
Liyas Thomas
df0ac3b7c8 Merge pull request #555 from liyasthomas/formdata
Support for Formdata
2020-02-05 23:29:56 +05:30
dependabot-preview[bot]
df68f9ac25 chore(deps): bump @nuxtjs/pwa from 3.0.0-beta.19 to 3.0.0-beta.20
Bumps [@nuxtjs/pwa](https://github.com/nuxt-community/pwa-module) from 3.0.0-beta.19 to 3.0.0-beta.20.
- [Release notes](https://github.com/nuxt-community/pwa-module/releases)
- [Changelog](https://github.com/nuxt-community/pwa-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/pwa-module/compare/v3.0.0-beta.19...v3.0.0-beta.20)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 17:46:08 +00:00
Liyas Thomas
a639ee63dd Merge pull request #553 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/axios-5.9.5
chore(deps): bump @nuxtjs/axios from 5.9.4 to 5.9.5
2020-02-05 23:14:01 +05:30
Liyas Thomas
04feb3cdbe Support for Formdata 2020-02-05 23:04:46 +05:30
dependabot-preview[bot]
f77f0a59ec chore(deps): bump @nuxtjs/axios from 5.9.4 to 5.9.5
Bumps [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) from 5.9.4 to 5.9.5.
- [Release notes](https://github.com/nuxt-community/axios-module/releases)
- [Changelog](https://github.com/nuxt-community/axios-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/axios-module/compare/v5.9.4...v5.9.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-05 17:21:32 +00:00
Liyas Thomas
fdc5695fb4 🎨 Fixes 2020-02-05 19:22:03 +05:30
Liyas Thomas
f24477e7b4 🎉 Initial formdata support and UI tweaks 2020-02-05 09:20:04 +05:30
Andrew Bastin
0e561e7bc2 Removed logging 2020-02-04 19:01:26 +00:00
Andrew Bastin
257cb5141b Merge branch 'master' into feat/extension-toggle 2020-02-04 13:17:46 -05:00
Andrew Bastin
89312347d1 Updated strategy identification to consider extensions toggle 2020-02-04 13:13:20 -05:00
Andrew Bastin
f1e752892d Added toggle for using extensions to send requests 2020-02-04 13:09:29 -05:00
Liyas Thomas
6a13b8c3c5 🎨 Better drop-down for method field 2020-02-04 20:52:52 +05:30
Liyas Thomas
c43a864480 Merge branch 'master' of https://github.com/liyasthomas/postwoman 2020-02-04 07:06:41 +05:30
Liyas Thomas
06d58547c8 Custom methods support (follow up of #398) 2020-02-04 07:05:37 +05:30
Andrew Bastin
173e3a3fc0 Merge pull request #549 from AndrewBastin/feat/proper-key-def
Show Ctrl instead of Command for shortcuts non-Apple platforms
2020-02-03 18:38:12 -05:00
Andrew Bastin
d0cf780ea2 Show Ctrl instead of Command for shortcuts non-Apple platforms 2020-02-03 17:47:48 -05:00
James George
493538ae70 Merge pull request #548 from liyasthomas/hotfix/validate-collection
fix(chore): Take letter casing into account while checking for duplicate collection
2020-02-03 18:47:41 +05:30
jamesgeorge007
955bb5c99d fix: account for letter casing while creating editing a collection 2020-02-03 17:38:38 +05:30
jamesgeorge007
88fc45975f fix: account for letter casing while creating new collection 2020-02-03 17:38:07 +05:30
Liyas Thomas
09a88b4a97 💄 Updating the UI and style files 2020-02-03 08:38:40 +05:30
Liyas Thomas
67e98ef46b Merge pull request #546 from yubathom/fix/start-server-and-test
update e2e tests
2020-02-02 11:07:16 +05:30
yubathom
85c5f16e93 tests(fix): update start-server-and-test, update e2e tests, change build test command at ci 2020-02-02 02:01:21 -03:00
Liyas Thomas
7cf5345c5a ️ Sync Collection -> Notes 2020-02-02 08:31:06 +05:30
James George
4c62baa577 Merge pull request #543 from liyasthomas/refactor
Refactor
2020-02-01 23:44:54 +05:30
jamesgeorge007
0f55b8ee8a refactor: minor tweak 2020-02-01 22:56:29 +05:30
jamesgeorge007
ad041a5cf1 refactor: tweaks 2020-02-01 22:49:09 +05:30
jamesgeorge007
3bd22f6b78 refactor: let to const 2020-02-01 22:48:06 +05:30
jamesgeorge007
fa15457ce4 refactor: let to const 2020-02-01 22:44:24 +05:30
jamesgeorge007
ef434ca804 refactor: destructuring assignment 2020-02-01 22:30:35 +05:30
jamesgeorge007
2b165a065c refactor: stick with the enforced style 2020-02-01 22:26:31 +05:30
James George
12b7e22c31 Merge branch 'master' into refactor 2020-02-01 20:23:30 +05:30
jamesgeorge007
d77e3745bb refactor: stylistic update 2020-01-31 19:50:24 +05:30
jamesgeorge007
5429e493ea refactor: stylistic update 2020-01-31 19:47:19 +05:30
jamesgeorge007
b05cd2e6e4 refactor: stick with Es6 semantics 2020-01-31 19:45:52 +05:30
jamesgeorge007
a9564086b0 refactor: destructuring assignment and other tweaks 2020-01-31 19:44:49 +05:30
Liyas Thomas
c32c6e0363 ♻️ Refactor 2020-01-31 18:25:55 +05:30
Liyas Thomas
f9008df1c6 chore(deps): bump @nuxtjs/axios from 5.9.3 to 5.9.4 (#545)
chore(deps): bump @nuxtjs/axios from 5.9.3 to 5.9.4
2020-01-31 07:07:41 +05:30
dependabot-preview[bot]
9a2fa9e2c7 chore(deps): bump @nuxtjs/axios from 5.9.3 to 5.9.4
Bumps [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) from 5.9.3 to 5.9.4.
- [Release notes](https://github.com/nuxt-community/axios-module/releases)
- [Changelog](https://github.com/nuxt-community/axios-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/axios-module/compare/v5.9.3...v5.9.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-31 01:25:41 +00:00
Liyas Thomas
dd8f7d078b chore(deps): bump graphql from 14.5.8 to 14.6.0 (#541)
chore(deps): bump graphql from 14.5.8 to 14.6.0
2020-01-31 06:53:37 +05:30
dependabot-preview[bot]
b40d5a75f2 chore(deps): bump graphql from 14.5.8 to 14.6.0
Bumps [graphql](https://github.com/graphql/graphql-js) from 14.5.8 to 14.6.0.
- [Release notes](https://github.com/graphql/graphql-js/releases)
- [Commits](https://github.com/graphql/graphql-js/compare/v14.5.8...v14.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-31 01:07:32 +00:00
Liyas Thomas
01e41ba1b2 chore(deps): bump firebase from 7.7.0 to 7.8.0 (#542)
chore(deps): bump firebase from 7.7.0 to 7.8.0
2020-01-31 06:35:34 +05:30
dependabot-preview[bot]
1ed28a717c chore(deps): bump firebase from 7.7.0 to 7.8.0
Bumps [firebase](https://github.com/firebase/firebase-js-sdk) from 7.7.0 to 7.8.0.
- [Release notes](https://github.com/firebase/firebase-js-sdk/releases)
- [Commits](https://github.com/firebase/firebase-js-sdk/compare/firebase@7.7.0...firebase@7.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-31 00:50:57 +00:00
Liyas Thomas
1d6d8af748 ♻️ Refactor 2020-01-31 00:18:20 +05:30
Liyas Thomas
f80c5d6a46 ♻️ Refactor 2020-01-30 23:45:38 +05:30
Liyas Thomas
6c7643a4c3 Press Escape to close modal, Enter to return. Fixes #539 2020-01-30 20:35:22 +05:30
Liyas Thomas
563ac1d2fb Merge pull request #538 from liyasthomas/i18n
i18n
2020-01-30 10:24:17 +05:30
Andrew Bastin
91511c09f3 Merge pull request #534 from AndrewBastin/feat/gql-variable-update
Updated GraphQL Query Variable Editor
2020-01-29 22:17:45 -05:00
Liyas Thomas
82180a54f1 Modification of French translations (#537)
Modification of French translations
2020-01-30 08:33:45 +05:30
Thomas Bnt
aee2863caf Modification of French language 2020-01-30 03:03:16 +01:00
Liyas Thomas
ac705a6900 Merge pull request #535 from liyasthomas/master
Even
2020-01-30 07:30:40 +05:30
Andrew Bastin
5b4f3f5b67 Merge branch 'master' into feat/gql-variable-update 2020-01-29 20:49:05 -05:00
Andrew Bastin
94c2440832 Hooked the new variable editor to the persistent store 2020-01-29 20:35:54 -05:00
Andrew Bastin
5d2ba22988 Removed mutations for GraphQL variables 2020-01-29 20:21:23 -05:00
Andrew Bastin
cf9fe0c02c Removed old variable store mechanisms 2020-01-29 20:05:59 -05:00
Liyas Thomas
4c57139cdc Improving Lighthouse score 2020-01-28 20:03:31 +05:30
Liyas Thomas
2c0b8b5f8e Improving Lighthouse score 2020-01-28 20:02:07 +05:30
Liyas Thomas
2634eb10be 🔖 v1.8.0 2020-01-28 07:37:14 +05:30
Liyas Thomas
101d7807ff Updated feature list 2020-01-28 07:19:08 +05:30
Liyas Thomas
d707ba3bad Merge pull request #531 from liyasthomas/enhancements
Enhancements
2020-01-28 06:11:47 +05:30
Andrew Bastin
d35d3061e5 Added variable editor and removed the old variable system 2020-01-27 18:42:38 -05:00
Liyas Thomas
f93fc4cf62 🎨 Minor UI styling 2020-01-27 23:28:07 +05:30
jamesgeorge007
870484d06a refactor: let to const 2020-01-27 22:50:02 +05:30
jamesgeorge007
f816ad0841 fix: typo 2020-01-27 22:49:12 +05:30
jamesgeorge007
a55eb11f5b fix: status code info 2020-01-27 18:19:27 +05:30
jamesgeorge007
dacf479838 fix: comment spacing 2020-01-27 18:17:01 +05:30
jamesgeorge007
568fd873e4 fix: typo 2020-01-27 18:16:40 +05:30
Liyas Thomas
d2bf0b7749 Merge pull request #530 from liyasthomas/feature/post-request-tests
Updating the UI and style files
2020-01-27 12:12:45 +05:30
Liyas Thomas
e68bfc0557 Merge branch 'master' into feature/post-request-tests 2020-01-27 11:19:14 +05:30
Liyas Thomas
60c82fa144 💄 Updating the UI and style files 2020-01-27 11:16:49 +05:30
Liyas Thomas
aca53be909 Updating spanish translation (#529)
Updating spanish translation
2020-01-27 05:44:51 +05:30
Liyas Thomas
aefe0abede Feature/post request tests (#518)
Feature/post request tests
2020-01-27 05:43:58 +05:30
Liyas Thomas
e3221aedaa even merge (#528)
even merge
2020-01-27 05:36:22 +05:30
Liyas Thomas
505268c037 Merge branch 'i18n' into master 2020-01-27 05:20:44 +05:30
Alfredo Finol
363902a588 Updating spanish translation 2020-01-26 17:00:55 -03:00
Andrew Bastin
dc236c6bf1 Fixed function name typo for runScriptWithVariables 2020-01-26 13:51:19 -05:00
Andrew Bastin
f16e6148b4 Fixed import resolution issue in pages/index.vue 2020-01-26 13:46:27 -05:00
Nick Palenchar
9e615c91cb Merge branch 'master' into feature/post-request-tests 2020-01-25 10:16:01 -05:00
Liyas Thomas
16491d36de ✏️ Updated feature list 2020-01-25 16:37:00 +05:30
Liyas Thomas
3e126cdfa4 🐛 Fixed a bug with Collection sync 2020-01-25 12:21:47 +05:30
Liyas Thomas
51fcec3369 Merge pull request #521 from liyasthomas/dependabot/npm_and_yarn/v-tooltip-2.0.3
chore(deps): bump v-tooltip from 2.0.2 to 2.0.3
2020-01-25 08:48:23 +05:30
dependabot-preview[bot]
2077dc2eee chore(deps): bump v-tooltip from 2.0.2 to 2.0.3
Bumps [v-tooltip](https://github.com/Akryum/vue-tooltip) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/Akryum/vue-tooltip/releases)
- [Commits](https://github.com/Akryum/vue-tooltip/compare/v2.0.2...v2.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-25 03:05:07 +00:00
Liyas Thomas
4487d90fec chore(deps): bump nuxt-i18n from 6.4.1 to 6.5.0 (#522)
chore(deps): bump nuxt-i18n from 6.4.1 to 6.5.0
2020-01-25 08:32:03 +05:30
Liyas Thomas
f088894ee1 Merge branch 'master' into dependabot/npm_and_yarn/nuxt-i18n-6.5.0 2020-01-25 08:06:18 +05:30
Liyas Thomas
8c9cf86d91 chore(deps-dev): bump cypress from 3.8.2 to 3.8.3 (#520)
chore(deps-dev): bump cypress from 3.8.2 to 3.8.3
2020-01-25 07:47:45 +05:30
Liyas Thomas
f41d8ca868 Merge branch 'master' into dependabot/npm_and_yarn/nuxt-i18n-6.5.0 2020-01-25 07:34:30 +05:30
Liyas Thomas
048776b53a Merge branch 'master' into dependabot/npm_and_yarn/cypress-3.8.3 2020-01-25 07:33:41 +05:30
Liyas Thomas
ac634708cc Refactor (#523)
Refactor
2020-01-25 07:16:25 +05:30
Liyas Thomas
54e4dbc4ac 💚 Fixing CI Build 2020-01-25 07:00:07 +05:30
dependabot-preview[bot]
254b500f03 chore(deps): bump nuxt-i18n from 6.4.1 to 6.5.0
Bumps [nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n) from 6.4.1 to 6.5.0.
- [Release notes](https://github.com/nuxt-community/nuxt-i18n/releases)
- [Changelog](https://github.com/nuxt-community/nuxt-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/nuxt-i18n/compare/v6.4.1...v6.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-25 00:16:15 +00:00
dependabot-preview[bot]
c057c7ea24 chore(deps-dev): bump cypress from 3.8.2 to 3.8.3
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.8.2 to 3.8.3.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.8.2...v3.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-25 00:14:47 +00:00
Liyas Thomas
3e27157eaa Refactor 2020-01-25 01:00:45 +05:30
Nicholas Palenchar
0da1f3a406 remove unnesscessary values 2020-01-24 13:34:24 -05:00
Nicholas Palenchar
113939c273 fix link typo 2020-01-24 12:22:00 -05:00
Nicholas Palenchar
708043dd6b very basic testing implementation 2020-01-24 12:18:55 -05:00
Nicholas Palenchar
bc4c59694c adding test report ui 2020-01-24 11:51:40 -05:00
Nicholas Palenchar
63b7035e74 re-add testing functions 2020-01-24 10:10:50 -05:00
Nicholas Palenchar
d8d5707f33 resolve merge conflicts 2020-01-24 09:18:11 -05:00
Nicholas Palenchar
24584cdadd remove console logs 2020-01-24 09:01:59 -05:00
Liyas Thomas
bbaa48c1ec 🚨 Removing linter warnings 2020-01-24 17:50:30 +05:30
Liyas Thomas
92d8878c38 🐛 Fixed Staring history not updating on synced DB 2020-01-24 08:49:36 +05:30
Liyas Thomas
282f3c47ed Auth (#513)
Auth
2020-01-23 19:58:42 +05:30
Liyas Thomas
65e9e7a73b Added History sync 2020-01-23 19:07:36 +05:30
Liyas Thomas
ab336de732 Merged master branch 2020-01-23 17:07:19 +05:30
Liyas Thomas
2efc549aca Merge branch 'auth' of https://github.com/liyasthomas/postwoman into auth 2020-01-23 16:48:30 +05:30
Liyas Thomas
7275e8075b 🔥 Firestore rules 2020-01-23 16:44:49 +05:30
Liyas Thomas
118a7aa258 ♻️ Rewrote all DB structure 2020-01-23 16:44:48 +05:30
Liyas Thomas
6bcd532767 🐛 Fixed error on Download feed 2020-01-23 16:44:48 +05:30
Liyas Thomas
6eb9ae8ad5 🐛 Fixed broken responsiveness UI in Feeds 2020-01-23 16:44:47 +05:30
Liyas Thomas
b450cd7ee4 🐛 Fixed sync toast prompt 2020-01-23 16:44:46 +05:30
Liyas Thomas
c8568ae15a Updated Firestore data rules 2020-01-23 16:44:45 +05:30
Liyas Thomas
65e1221298 🎉 Completed MVP 2020-01-23 16:44:44 +05:30
Liyas Thomas
b4a7c45b61 ✏️ Typo 2020-01-23 16:44:41 +05:30
Liyas Thomas
211dfa24fa Account setting on setting page 2020-01-23 16:44:40 +05:30
Liyas Thomas
1fdde89d49 ♻️ Refactor 2020-01-23 16:44:35 +05:30
Liyas Thomas
94d0bf59b2 Show logged in user image 2020-01-23 16:43:04 +05:30
Liyas Thomas
05fe9dcccf Delete data 2020-01-23 16:43:03 +05:30
Liyas Thomas
f89f27698e 🎨 Minor UI stylings 2020-01-23 16:43:03 +05:30
Liyas Thomas
4931804056 Moved inputform and feed to index 2020-01-23 16:43:02 +05:30
Liyas Thomas
67bcf91073 ♻️ Lint 2020-01-23 16:42:31 +05:30
Liyas Thomas
87be0b3d3d 🎉 Initial Auth 2020-01-23 16:41:23 +05:30
James George
27585d5c93 Merge pull request #516 from liyasthomas/hotfix/validate-collections
Validations for edit and create collections activity
2020-01-23 15:10:47 +05:30
jamesgeorge007
7d003cefd7 chore: rephrase warning message 2020-01-23 14:59:21 +05:30
jamesgeorge007
f132de8dbb chore: validate edit collection activity for duplicate collection 2020-01-23 14:57:44 +05:30
jamesgeorge007
b0c22a2b2d chore: validate edit collection activity for empty names 2020-01-23 14:52:52 +05:30
jamesgeorge007
9b8936f53c feat: switch to toast 2020-01-23 14:12:04 +05:30
jamesgeorge007
c3ecf98b62 feat: show warning alert 2020-01-23 14:11:04 +05:30
jamesgeorge007
5481c28e4b refactor: use shorthand version 2020-01-23 14:10:26 +05:30
jamesgeorge007
4ad4bad295 fix: validation for empty collection names 2020-01-23 14:09:36 +05:30
Liyas Thomas
5119505475 Support for Google Chrome Extension (#512)
Support for Google Chrome Extension
2020-01-23 11:42:57 +05:30
Liyas Thomas
8b7fd238d0 Detech whether extension is already installed or not, if not, shoe install prompt toast 2020-01-23 11:03:22 +05:30
Liyas Thomas
df21deddba ✏️ Updated extensions link 2020-01-23 09:15:59 +05:30
Liyas Thomas
91b29b893b Merge branch 'master' into auth 2020-01-23 08:53:03 +05:30
Liyas Thomas
32c7ece2ef 🔥 Firestore rules 2020-01-23 08:02:34 +05:30
Liyas Thomas
dbbf310e83 ♻️ Rewrote all DB structure 2020-01-23 07:51:23 +05:30
Andrew Bastin
52fe6474e2 Merge branch 'master' into feat/chrome-extension 2020-01-22 12:38:39 -05:00
Andrew Bastin
81654c35da Use relative imports
Co-Authored-By: James George <jamesgeorge998001@gmail.com>
2020-01-22 12:38:17 -05:00
Liyas Thomas
32d57814a9 🎉 Powered by Netlify 2020-01-22 19:29:11 +05:30
Liyas Thomas
860993663f 🐛 Fixed error on Download feed 2020-01-22 12:47:09 +05:30
Liyas Thomas
ea7feee840 🐛 Fixed broken responsiveness UI in Feeds 2020-01-22 10:28:37 +05:30
Liyas Thomas
a556e6d0c2 🐛 Fixed sync toast prompt 2020-01-22 10:10:29 +05:30
Liyas Thomas
bf686736f8 Updated Firestore data rules 2020-01-22 09:48:52 +05:30
Andrew Bastin
56c7ec3750 Merge branch 'master' into feat/chrome-extension 2020-01-21 21:09:15 -05:00
Liyas Thomas
a7cd6395b7 🎉 Completed MVP 2020-01-22 07:27:38 +05:30
Andrew Bastin
2d6d1b2d34 Added Chrome Strategy as a valid network strategy 2020-01-21 20:01:22 -05:00
Andrew Bastin
a235d38240 Added ChromeStrategy to interact with the Postwoman Chrome Extension 2020-01-21 20:00:29 -05:00
Liyas Thomas
43d95a2271 ✏️ Typo 2020-01-21 22:46:29 +05:30
Liyas Thomas
40e05a0461 Account setting on setting page 2020-01-21 22:27:52 +05:30
James George
b60bc1ee39 Merge pull request #510 from liyasthomas/hotfix/validate-collections
Validate duplicate collections
2020-01-21 20:10:15 +05:30
jamesgeorge007
bb973ee449 fix: prevent creation of duplicate collection 2020-01-21 19:46:33 +05:30
jamesgeorge007
e16019dcbf chore: make use of toast 2020-01-21 19:45:52 +05:30
Liyas Thomas
01a890bce9 ♻️ Refactor 2020-01-21 17:55:35 +05:30
jamesgeorge007
fcdf93c5e5 fix: prefer destructuring approach 2020-01-21 16:38:34 +05:30
jamesgeorge007
a34acfd0c5 fix: return for duplicate collection 2020-01-21 16:38:09 +05:30
jamesgeorge007
2853a4bbef fix: validation for duplicate collections 2020-01-21 16:37:04 +05:30
Liyas Thomas
8bc1df9b8e Show logged in user image 2020-01-21 12:04:03 +05:30
Liyas Thomas
29e96ddd12 Delete data 2020-01-21 08:32:43 +05:30
Liyas Thomas
a852432c9f 🎨 Minor UI stylings 2020-01-21 01:10:04 +05:30
Liyas Thomas
c7e5fc47ba Moved inputform and feed to index 2020-01-21 00:52:45 +05:30
Liyas Thomas
19a2323880 ♻️ Lint 2020-01-20 23:01:31 +05:30
Liyas Thomas
fb4554abe3 🎉 Initial Auth 2020-01-20 22:25:48 +05:30
Andrew Bastin
cd2680135d Merge pull request #508 from AndrewBastin/feat/gql-query-schema-val
GraphQL query validation based on schema
2020-01-19 19:53:53 -05:00
Andrew Bastin
8ae5dbc375 Fixed proxying through the firefox extension 2020-01-19 15:24:17 -05:00
Andrew Bastin
744d647704 GQL Query Editor doesn't give errors for empty queries 2020-01-19 14:38:46 -05:00
Andrew Bastin
77e51f3301 GraphQL page now notifies the query editor about the schema for validation 2020-01-19 14:22:56 -05:00
Andrew Bastin
f0cfee56f2 Added ability to query editor to validate based on schema 2020-01-19 14:21:31 -05:00
Nicholas Palenchar
61bf735315 response data into testing and error handling 2020-01-19 11:28:23 -05:00
Nicholas Palenchar
b2be9dce6f pw.test working 2020-01-19 10:46:04 -05:00
Liyas Thomas
8b970ed9a0 Merge pull request #506 from liyasthomas/refactor
Lint and refactor
2020-01-19 14:04:38 +05:30
Liyas Thomas
5458debe35 ♻️ Refactor 2020-01-19 12:37:19 +05:30
Nicholas Palenchar
dd970af6b1 inline expects returning testResults correctly 2020-01-18 13:26:07 -05:00
Andrew Bastin
d9feffa630 Merge pull request #505 from AndrewBastin/feat/gql-query-errors
Syntax Error marking in GraphQL query editor
2020-01-18 12:18:00 -05:00
Andrew Bastin
efe21d450e Merge branch 'master' into feat/gql-query-errors 2020-01-18 12:07:42 -05:00
Andrew Bastin
7728231cad Merge pull request #500 from AndrewBastin/refactor/strategy-proxy-handling
Refactoring proxy handling to be done in strategies
2020-01-18 12:07:26 -05:00
Nicholas Palenchar
3ecf62857c 💄 add tests section to UI 2020-01-18 12:06:45 -05:00
Nicholas Palenchar
b8beac37c3 Merge branch 'master' into feature/post-request-tests 2020-01-18 10:51:01 -05:00
jamesgeorge007
aa056ff1c1 refactor: remove extraneous else 2020-01-18 15:22:59 +05:30
Andrew Bastin
23199979e6 Merge branch 'master' into feat/gql-query-errors 2020-01-18 04:50:09 -05:00
Andrew Bastin
b3dd2ebf31 Removed GQL parse log 2020-01-18 04:43:58 -05:00
Andrew Bastin
0cec1b977a QueryEditor parses query on mount 2020-01-18 04:42:50 -05:00
Andrew Bastin
3b96f85c55 Make James happy by doing proper code refactors 2020-01-18 04:30:24 -05:00
Andrew Bastin
8e86e4c8e8 Update functions/strategies/AxiosStrategy.js
Co-Authored-By: James George <jamesgeorge998001@gmail.com>
2020-01-18 04:22:30 -05:00
Andrew Bastin
a1568a98d4 Update functions/strategies/FirefoxStrategy.js
Co-Authored-By: James George <jamesgeorge998001@gmail.com>
2020-01-18 04:22:21 -05:00
Andrew Bastin
c61d825c37 Merge branch 'refactor/strategy-proxy-handling' of https://github.com/AndrewBastin/postwoman into refactor/strategy-proxy-handling 2020-01-18 04:17:21 -05:00
Andrew Bastin
730018b45f Improve strategy code redability 2020-01-18 04:16:51 -05:00
Andrew Bastin
d8af767dc4 Updated graphql page to use QueryEditor for query field 2020-01-18 04:15:28 -05:00
Andrew Bastin
82756a9c55 Added GQL Query Editor component 2020-01-18 04:14:30 -05:00
Andrew Bastin
fe81a7dba9 Added debounce util function 2020-01-18 04:14:10 -05:00
Andrew Bastin
9d085e301d Merge branch 'master' into refactor/strategy-proxy-handling 2020-01-18 04:03:24 -05:00
Liyas Thomas
5206aeead0 Don't show Extension toast if user opt-out of it once or have already installed it. 2020-01-18 10:07:30 +05:30
Liyas Thomas
6a93e56747 Merge pull request #504 from liyasthomas/dependabot/npm_and_yarn/node-sass-4.13.1
chore(deps-dev): bump node-sass from 4.13.0 to 4.13.1
2020-01-18 08:03:14 +05:30
dependabot-preview[bot]
15e5edb1a3 chore(deps-dev): bump node-sass from 4.13.0 to 4.13.1
Bumps [node-sass](https://github.com/sass/node-sass) from 4.13.0 to 4.13.1.
- [Release notes](https://github.com/sass/node-sass/releases)
- [Changelog](https://github.com/sass/node-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/node-sass/compare/v4.13.0...v4.13.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-18 02:05:59 +00:00
Liyas Thomas
2b17b9b218 Merge pull request #503 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/axios-5.9.3
chore(deps): bump @nuxtjs/axios from 5.9.2 to 5.9.3
2020-01-18 07:34:04 +05:30
dependabot-preview[bot]
808e4545ae chore(deps): bump @nuxtjs/axios from 5.9.2 to 5.9.3
Bumps [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) from 5.9.2 to 5.9.3.
- [Release notes](https://github.com/nuxt-community/axios-module/releases)
- [Changelog](https://github.com/nuxt-community/axios-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/axios-module/compare/v5.9.2...v5.9.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-18 01:51:14 +00:00
Liyas Thomas
2da4c385ba Merge pull request #502 from liyasthomas/dependabot/npm_and_yarn/sass-loader-8.0.2
chore(deps-dev): bump sass-loader from 8.0.1 to 8.0.2
2020-01-18 07:19:18 +05:30
dependabot-preview[bot]
b6e5f7f337 chore(deps-dev): bump sass-loader from 8.0.1 to 8.0.2
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v8.0.1...v8.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-18 01:24:42 +00:00
Liyas Thomas
8b39da6043 Merge pull request #501 from liyasthomas/dependabot/npm_and_yarn/ace-builds-1.4.8
chore(deps): bump ace-builds from 1.4.7 to 1.4.8
2020-01-18 06:52:47 +05:30
dependabot-preview[bot]
9e43bbcce2 chore(deps): bump ace-builds from 1.4.7 to 1.4.8
Bumps [ace-builds](https://github.com/ajaxorg/ace-builds) from 1.4.7 to 1.4.8.
- [Release notes](https://github.com/ajaxorg/ace-builds/releases)
- [Changelog](https://github.com/ajaxorg/ace-builds/blob/master/ChangeLog.txt)
- [Commits](https://github.com/ajaxorg/ace-builds/compare/v1.4.7...v1.4.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-18 00:13:19 +00:00
Andrew Bastin
a9224b94b1 Merge branch 'master' into refactor/strategy-proxy-handling 2020-01-17 13:40:21 -05:00
Andrew Bastin
951266e529 Added proxy support to FirefoxStrategy 2020-01-17 13:28:04 -05:00
Andrew Bastin
2a51ec6d9f Moved proxy code to be handled in each strategy 2020-01-17 13:27:37 -05:00
Andrew Bastin
cc5966e90c Merge pull request #499 from pushrbx/bugfix/gql-vars-str-null
💚 Fixed #497
2020-01-17 13:18:22 -05:00
pushrbx
76d2ca3e37 removed unneeded console.log 2020-01-17 17:58:09 +00:00
pushrbx
c4c2f1cbee 💚 Fixed #497 2020-01-17 11:58:13 +00:00
Liyas Thomas
f7a67ec30f Indicate installed extensions 2020-01-17 09:46:23 +05:30
Liyas Thomas
60676addef ✏️ Typo 2020-01-17 01:31:30 +05:30
Liyas Thomas
c4a48f1037 Feat/firefox strategy (#496)
Feat/firefox strategy
2020-01-17 01:16:35 +05:30
Liyas Thomas
217cdad775 Merge branch 'master' into feat/firefox-strategy 2020-01-17 01:05:26 +05:30
Liyas Thomas
3dac917cc1 Merge branch 'feat/firefox-strategy' of https://github.com/AndrewBastin/postwoman into feat/firefox-strategy 2020-01-17 00:55:37 +05:30
Liyas Thomas
93acb03297 Toast for extensions 2020-01-17 00:55:31 +05:30
Andrew Bastin
7c530550f9 Merge pull request #494 from AndrewBastin/feat/firefox-strategy
Firefox Extension compatibility
2020-01-16 13:00:37 -05:00
Liyas Thomas
aafb4dc901 Merge branch 'master' into feat/firefox-strategy 2020-01-16 23:02:33 +05:30
Liyas Thomas
497a4dfde6 🐛 Fix #495 2020-01-16 22:57:35 +05:30
Andrew Bastin
5070d9fe95 Added FirefoxStrategy to interact with the Firefox extension for Postwoman 2020-01-16 01:26:25 -05:00
Andrew Bastin
4b48d8a8c8 Refactor to bring the nuxt loading bar code out of the strategies 2020-01-16 01:25:43 -05:00
Liyas Thomas
ebb17489b7 i18n Japanese: Added new translations (#492)
i18n Japanese: Added new translations
2020-01-15 10:51:28 +05:30
Abdul Rifqi Al Abqary
1e2797a681 Added new translations 2020-01-15 14:10:27 +09:00
Liyas Thomas
2faf675c0a 🚨 Removing linter warnings 2020-01-15 09:10:14 +05:30
Andrew Bastin
c8878aba57 Merge pull request #487 from AndrewBastin/refactor/network-strategy
Network Strategies
2020-01-14 20:22:42 -05:00
Liyas Thomas
061f86fbfa 🐛 Fixed Nuxt loader won't finish after response 2020-01-15 06:33:04 +05:30
Liyas Thomas
1b783fdfa0 Merge branch 'master' into refactor/network-strategy 2020-01-14 22:36:09 +05:30
Liyas Thomas
e7a15c9242 Merge pull request #491 from liyasthomas/i18n
i18n
2020-01-14 22:34:59 +05:30
Liyas Thomas
36c984d152 Replaced hard-coded strings with localizable strings (#490)
Replaced hard-coded strings with localizable strings
2020-01-14 22:20:32 +05:30
Andrew Bastin
bd008f42dd Refactor network and ProxyStrategy code 2020-01-14 11:49:43 -05:00
Alec Ananian
8690d18695 Replaced hard-coded strings with localizable strings
Added en locale as localization fallback
2020-01-14 07:43:41 -08:00
Andrew Bastin
3a8b4337f0 Refactor graphql page to use Network Strategies 2020-01-13 23:55:03 -05:00
Andrew Bastin
5ef1b5b75c Refactor index.vue to use Network Strategies 2020-01-13 23:48:20 -05:00
Andrew Bastin
3726f0a376 Added sendNetworkRequest to detect appropriate strategy and use it 2020-01-13 23:47:28 -05:00
Andrew Bastin
61d7dcf61b Added AxiosStrategy and ProxyStrategy Network Strategies 2020-01-13 23:46:31 -05:00
Nicholas Palenchar
dce58bdb2f wip - basic test scaffolding 2020-01-11 13:01:42 -05:00
Nicholas Palenchar
311d87b223 Expectation class 2020-01-11 12:18:29 -05:00
Nicholas Palenchar
2214645a96 Merge branch 'master' into feature/post-request-tests 2020-01-11 11:18:46 -05:00
James George
119eb321ec Merge pull request #486 from liyasthomas/refactor
chore(oauth): Added method signatures as per JSDoc conventions
2020-01-11 21:27:43 +05:30
jamesgeorge007
5fffc5d29e fix: lint 2020-01-11 16:38:54 +05:30
jamesgeorge007
9838a68ff7 fix: remove redundant declaration 2020-01-11 16:37:58 +05:30
jamesgeorge007
64222327c9 refactor: prefer reduce 2020-01-11 16:36:41 +05:30
jamesgeorge007
e1423033a6 chore: method signatures for oauthRedirect method 2020-01-11 13:31:49 +05:30
jamesgeorge007
dcd148e43b fix: minor tweak 2020-01-11 13:30:03 +05:30
jamesgeorge007
daf214275b chore: method signatures for tokenRequest method 2020-01-11 13:29:57 +05:30
jamesgeorge007
a4b89a2152 chore: method signatures for pkceChallengeFromVerifier method 2020-01-11 13:26:56 +05:30
jamesgeorge007
9e5a162d74 fix: minor tweak 2020-01-11 13:25:01 +05:30
jamesgeorge007
3ba279c81b chore: method signatures for base64urlencode method 2020-01-11 13:24:04 +05:30
jamesgeorge007
836bd9ab3c chore: method signatures for sha256 method 2020-01-11 13:19:31 +05:30
jamesgeorge007
12ef2f4465 fix: minor tweak 2020-01-11 13:17:24 +05:30
jamesgeorge007
4ce673acfd chore: method signatures for getRandomString method 2020-01-11 13:16:57 +05:30
jamesgeorge007
80f7d3120a fix: minor tweak 2020-01-11 13:15:41 +05:30
jamesgeorge007
1a04d79fb9 chore: method signatures for getTokenConfiguration method 2020-01-11 13:15:09 +05:30
jamesgeorge007
ee49f8d26c fix: minor tweak 2020-01-11 13:13:53 +05:30
jamesgeorge007
bbb559ad2c chore: change var name 2020-01-11 13:13:12 +05:30
jamesgeorge007
5dab781fbe fix: minor tweak 2020-01-11 13:11:02 +05:30
jamesgeorge007
2f3c3aeba9 chore: method signatures for parseQueryString method 2020-01-11 13:10:11 +05:30
jamesgeorge007
7f8b49dd1d fix: minor tweak 2020-01-11 13:08:05 +05:30
jamesgeorge007
14f03e61ef fix: minor tweak 2020-01-11 13:07:53 +05:30
jamesgeorge007
bf08883f15 chore: method signatures for sendPostRequest method 2020-01-11 13:07:26 +05:30
Liyas Thomas
f1b22e7122 chore: Minor tweaks (#485)
chore: Minor tweaks
2020-01-11 11:51:41 +05:30
jamesgeorge007
caf33ba87e refactor: use const 2020-01-11 10:48:12 +05:30
jamesgeorge007
46d5ffc05b fix: typo 2020-01-11 10:47:57 +05:30
jamesgeorge007
086b2de505 refactor: use const 2020-01-11 10:44:07 +05:30
jamesgeorge007
908d672cf2 refactor: use const 2020-01-11 10:42:08 +05:30
Liyas Thomas
d13e6f1897 ⬆️ Bump cypress from 3.8.1 to 3.8.2 (#483)
⬆️ Bump cypress from 3.8.1 to 3.8.2

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-01-11 06:28:55 +05:30
dependabot-preview[bot]
de480c457a ⬆️ Bump cypress from 3.8.1 to 3.8.2
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.8.1 to 3.8.2.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.8.1...v3.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-11 00:48:14 +00:00
Liyas Thomas
493b6cd576 ⬆️ Bump sass-loader from 8.0.0 to 8.0.1 (#482)
⬆️ Bump sass-loader from 8.0.0 to 8.0.1

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-01-11 06:16:17 +05:30
dependabot-preview[bot]
7296873562 ⬆️ Bump sass-loader from 8.0.0 to 8.0.1
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-11 00:32:24 +00:00
Liyas Thomas
85fd5cf0dc ⬆️ Bump @nuxtjs/google-analytics from 2.2.2 to 2.2.3 (#481)
⬆️ Bump @nuxtjs/google-analytics from 2.2.2 to 2.2.3

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-01-11 06:00:28 +05:30
dependabot-preview[bot]
bb9db3b1ca ⬆️ Bump @nuxtjs/google-analytics from 2.2.2 to 2.2.3
Bumps [@nuxtjs/google-analytics](https://github.com/nuxt-community/analytics-module) from 2.2.2 to 2.2.3.
- [Release notes](https://github.com/nuxt-community/analytics-module/releases)
- [Changelog](https://github.com/nuxt-community/analytics-module/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/analytics-module/compare/v2.2.2...v2.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-11 00:12:49 +00:00
Liyas Thomas
35a0d50918 🐛 Fixed a broken function 2020-01-10 09:06:08 +05:30
Liyas Thomas
57f7621567 ♻️ Refactoring code 2020-01-10 06:27:48 +05:30
Liyas Thomas
bf1a143f03 🎨 Minor stylings 2020-01-10 05:30:38 +05:30
Liyas Thomas
355688abf8 Merge pull request #479 from AndrewBastin/feat/graphql_highlight
GraphQL Type Highlight and Links
2020-01-10 04:29:39 +05:30
Andrew Bastin
f5efb425cd Merge branch 'upstream/master' into feat/graphql_highlight 2020-01-09 13:33:33 -05:00
Andrew Bastin
cc396aecd3 Updated field, type and graphql page to use the new argument and typelink components 2020-01-09 13:32:38 -05:00
Andrew Bastin
faa420753f Added argument and typelink components for GraphQL 2020-01-09 13:31:30 -05:00
Nicholas Palenchar
dbba0cf847 wip 2020-01-08 20:40:50 -05:00
Liyas Thomas
725fa31e77 🎨 Improved structure and format of the code 2020-01-09 06:01:31 +05:30
Liyas Thomas
bb924dc250 Merge pull request #476 from reefqi037/feature/oauth-support
OAuth 2.0/OIDC Access Token Retrieval Support
2020-01-08 03:42:35 +05:30
Liyas Thomas
b0346aa340 Merge branch 'master' into feature/oauth-support 2020-01-07 22:55:10 +05:30
Liyas Thomas
671fca0736 🐛 Fixed broken cURL import. Fix #477 2020-01-07 22:41:05 +05:30
Liyas Thomas
322945ec99 Merge branch 'master' into feature/oauth-support 2020-01-07 21:04:01 +05:30
Liyas Thomas
1c6f87784b Better URL parsing 2020-01-07 20:47:11 +05:30
RifqiAlAbqary
9d56af4160 Merge branch 'master' into feature/oauth-support 2020-01-07 23:24:55 +09:00
Liyas Thomas
fdedb1f231 Set credentials to true. Fix #443 2020-01-07 19:49:14 +05:30
Abdul Rifqi Al Abqary
161c0b7b88 added token request management 2020-01-07 18:46:16 +09:00
Abdul Rifqi Al Abqary
f847cbe122 Added token management 2020-01-07 11:50:56 +09:00
Abdul Rifqi Al Abqary
df48e85de5 added token managements 2020-01-06 18:17:50 +09:00
Abdul Rifqi Al Abqary
2a818dc81d comment correction 2020-01-06 16:50:20 +09:00
Abdul Rifqi Al Abqary
83a20bd7de implement oidc discovery 2020-01-06 16:44:50 +09:00
Abdul Rifqi Al Abqary
2e7e40c4cc display error & disable input based on user input 2020-01-06 16:15:58 +09:00
Abdul Rifqi Al Abqary
b98d9074bb fix token placement 2020-01-06 15:55:14 +09:00
Abdul Rifqi Al Abqary
5377c69b40 add oauth handler 2020-01-06 15:06:50 +09:00
Abdul Rifqi Al Abqary
d24b917c17 added oauth token ui 2020-01-06 14:51:47 +09:00
Liyas Thomas
d99ede8c05 ⬆️ Bumped version to 1.5.0 2020-01-04 07:18:06 +05:30
Liyas Thomas
3f727d6f71 Merge branch 'master' of https://github.com/liyasthomas/postwoman 2020-01-04 06:57:53 +05:30
Liyas Thomas
99acc4921c ⬆️ Bumped version to 1.5.0 2020-01-04 06:55:44 +05:30
Liyas Thomas
db7dcba1b9 Merge pull request #472 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/axios-5.9.2
⬆️ Bump @nuxtjs/axios from 5.9.0 to 5.9.2
2020-01-04 06:02:34 +05:30
dependabot-preview[bot]
8f76d3fa58 ⬆️ Bump @nuxtjs/axios from 5.9.0 to 5.9.2
Bumps [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) from 5.9.0 to 5.9.2.
- [Release notes](https://github.com/nuxt-community/axios-module/releases)
- [Changelog](https://github.com/nuxt-community/axios-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/axios-module/compare/v5.9.0...v5.9.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-04 00:13:01 +00:00
Liyas Thomas
0930b1ada8 🐛 Better URL validation, Fixed #471 2020-01-03 21:07:41 +05:30
Liyas Thomas
35df7c6429 💚 Fixing CI Build 2020-01-01 13:51:28 +05:30
Liyas Thomas
e679e8c5f4 Added OAuth 2.0 authentication. Fixed #358 2020-01-01 13:36:55 +05:30
Liyas Thomas
d43a655116 💲 Updated Open Collective link 2020-01-01 10:29:51 +05:30
Liyas Thomas
56a4ca0e21 🐛 Fixed clear button on variables list 2019-12-31 19:38:26 +05:30
Liyas Thomas
f17b126dd4 Merge pull request #464 from pushrbx/feature/graphql-vars
Added variables to graphql page.
2019-12-31 19:03:40 +05:30
pushrbx
1ac144e3a7 🎉 Added variables to graphql page (w/ lame type validation). 2019-12-31 13:09:26 +00:00
Liyas Thomas
13402a5aa5 Added Gitpod dev env 2019-12-31 08:50:35 +05:30
Liyas Thomas
92a0cc245f i18n (#463)
i18n

Co-authored-by: Tanbir Hasan <tanbir2025@gmail.com>
Co-authored-by: Gabriel Schneider <57860382+gabschne@users.noreply.github.com>
2019-12-31 08:46:40 +05:30
Liyas Thomas
8b9a2c5f7e Merge branch 'master' into i18n 2019-12-31 08:38:05 +05:30
Liyas Thomas
bc10e4304f Added Gitpod dev env, removed two stale translations 2019-12-31 08:35:27 +05:30
Liyas Thomas
d40de785b7 Lint and minor UI improvements 2019-12-29 06:17:00 +05:30
Liyas Thomas
9ff02eefb8 🔥 Hid empty fields 2019-12-29 05:08:55 +05:30
Liyas Thomas
e8837e69a0 Merge pull request #460 from liyasthomas/dependabot/npm_and_yarn/cypress-3.8.1
⬆️ Bump cypress from 3.8.0 to 3.8.1
2019-12-28 07:47:16 +05:30
dependabot-preview[bot]
9d02f2687d ⬆️ Bump cypress from 3.8.0 to 3.8.1
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.8.0...v3.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-28 00:13:41 +00:00
Liyas Thomas
9f2ecd619f ✏️ Typo on CLI repo link 2019-12-26 13:31:01 +05:30
Liyas Thomas
6b899b2ce0 Merge pull request #459 from gabschne/i18n
i18n(de-DE): improve some translations
2019-12-26 08:32:55 +05:30
gabschne
d5cb66079b i18n(de-DE): improve some translations 2019-12-26 01:56:24 +01:00
gabschne
5690599241 i18n(de-DE): improve some translations 2019-12-26 01:01:23 +01:00
Liyas Thomas
3ee2bae78d 🐛 Fixes #456 2019-12-23 13:15:30 +05:30
Liyas Thomas
21041fc6da Merge pull request #451 from liyasthomas/doc
API documentation page
2019-12-23 08:24:53 +05:30
Liyas Thomas
2b40db285e Introducing API Documentation 2019-12-23 08:16:45 +05:30
Liyas Thomas
c3a6cc133f Introducing API Documentation 2019-12-22 23:28:36 +05:30
Liyas Thomas
10f6bb9cc6 🐛 Added error handler 2019-12-22 15:49:26 +05:30
Liyas Thomas
5589c61423 🎉 Display actual Documentation 2019-12-22 15:26:13 +05:30
Liyas Thomas
158c34d091 Initial iteration on Collection 2019-12-22 09:20:38 +05:30
Liyas Thomas
99f182599a Merge pull request #455 from hmtanbir/i18n
bn-BD i18n
2019-12-21 21:23:02 +05:30
hmtanbir
216bd4e7b4 add bangla i18n 2019-12-21 10:30:04 +06:00
Liyas Thomas
ecfc7c84c3 Merge branch 'doc' of https://github.com/liyasthomas/postwoman into doc 2019-12-21 08:44:52 +05:30
Liyas Thomas
d4819bcd0a 🎉 Added navigation link to Documentation page in default layour 2019-12-21 08:44:10 +05:30
Liyas Thomas
b067a4723b Merge branch 'master' into doc 2019-12-21 08:14:58 +05:30
Liyas Thomas
9217ebf75e Merge pull request #450 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/axios-5.9.0
⬆️ Bump @nuxtjs/axios from 5.8.0 to 5.9.0
2019-12-21 06:28:34 +05:30
dependabot-preview[bot]
305a8f74b0 ⬆️ Bump @nuxtjs/axios from 5.8.0 to 5.9.0
Bumps [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) from 5.8.0 to 5.9.0.
- [Release notes](https://github.com/nuxt-community/axios-module/releases)
- [Changelog](https://github.com/nuxt-community/axios-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/axios-module/compare/v5.8.0...v5.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-21 00:33:16 +00:00
Liyas Thomas
a3666b3d44 ⬆️ Bump nuxt from 2.10.2 to 2.11.0 (#449)
⬆️ Bump nuxt from 2.10.2 to 2.11.0

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2019-12-21 06:01:18 +05:30
dependabot-preview[bot]
182bca9361 ⬆️ Bump nuxt from 2.10.2 to 2.11.0
Bumps [nuxt](https://github.com/nuxt/nuxt.js) from 2.10.2 to 2.11.0.
- [Release notes](https://github.com/nuxt/nuxt.js/releases)
- [Changelog](https://github.com/nuxt/nuxt.js/blob/dev/RELEASE_PLAN.md)
- [Commits](https://github.com/nuxt/nuxt.js/compare/v2.10.2...v2.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-21 00:13:26 +00:00
Liyas Thomas
f0868f383b 🎉 API documentation page 2019-12-20 14:40:16 +05:30
Liyas Thomas
001c4818a0 ✏️ Added badge name 2019-12-20 10:05:59 +05:30
Liyas Thomas
0d47a1a1c2 ✏️ Fixed table width 2019-12-20 09:54:13 +05:30
Liyas Thomas
75f4d8e09c ✏️ Put badges inside table 2019-12-20 09:50:48 +05:30
Liyas Thomas
2e5d8b330b ✏️ Updated wwith organization and add-ons links 2019-12-20 09:08:39 +05:30
Liyas Thomas
42e0200956 🐛 Fixed #446 and crash on closing file picker for raw request body without selecting a file 2019-12-20 08:19:14 +05:30
Liyas Thomas
780bc55a96 Various UI tweaks (#439)
Various UI tweaks

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-12-18 00:54:02 +05:30
Liyas Thomas
bc6ea34f14 🎨 Various UI tweaks 2019-12-18 00:43:15 +05:30
Liyas Thomas
ae237f1ad3 🐛 Fixes #435 2019-12-17 06:45:24 +05:30
Liyas Thomas
7451a0bcc4 Merge pull request #438 from liyasthomas/i18n
i18n
2019-12-17 06:03:31 +05:30
Liyas Thomas
ffed1dbc90 Merge branch 'master' into i18n 2019-12-17 05:50:19 +05:30
Liyas Thomas
3ffe5559e7 🌐 Added more internationalization vocabulary 2019-12-16 23:26:46 +05:30
Liyas Thomas
2c93e2f783 🌐 Added more internationalization vocabulary 2019-12-16 23:21:32 +05:30
Liyas Thomas
7ef5919ba1 Burmese translation added (#437)
Burmese translation added
2019-12-16 21:12:54 +05:30
Zayar Tun
4c19a7d598 Burmese translation added 2019-12-16 21:46:00 +06:30
Liyas Thomas
feb782270b 🎨 Toast button now align to end 2019-12-15 21:46:55 +05:30
Liyas Thomas
29c6109ea3 Merge pull request #432 from liyasthomas/refactor/enhancements
chore: stick to Vue.js best practices
2019-12-15 19:44:20 +05:30
jamesgeorge007
ffe4796f2c refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:23:53 +05:30
jamesgeorge007
5762cea9bd refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:23:09 +05:30
jamesgeorge007
7b0a1c4266 refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:22:37 +05:30
jamesgeorge007
d2086b1661 refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:21:25 +05:30
jamesgeorge007
c50cbc9750 refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:20:31 +05:30
jamesgeorge007
24ee395b73 refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:14:44 +05:30
jamesgeorge007
48bd772171 refactor: make use of v-bind directive shorthand
vue.js best practices
2019-12-15 19:13:53 +05:30
jamesgeorge007
928ace5ba6 refactor: use property shorthand for consistency 2019-12-15 19:03:39 +05:30
jamesgeorge007
0791d196d4 refactor: use property shorthand for consistency 2019-12-15 19:03:18 +05:30
jamesgeorge007
9223044967 refactor: use property shorthand for consistency 2019-12-15 19:02:37 +05:30
jamesgeorge007
998a925fd1 refactor: make request component self closing 2019-12-15 19:02:03 +05:30
jamesgeorge007
f49bfb4d74 refactor: use property shorthand for consistency 2019-12-15 19:01:31 +05:30
jamesgeorge007
b20cb040b0 refactor: make collection component self closing 2019-12-15 19:00:31 +05:30
jamesgeorge007
82096f3a1e refactor: use property shorthand for consistency 2019-12-15 18:59:45 +05:30
jamesgeorge007
fcc6f5aa76 refactor: make history component self closing 2019-12-15 18:55:29 +05:30
jamesgeorge007
4c82ef89fb refactor: make component tag self closing 2019-12-15 18:52:34 +05:30
Liyas Thomas
9b7141b1f4 Styled select input (#431)
Styled select input

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-12-15 05:50:47 +05:30
Liyas Thomas
965133d6e2 🎨 Styled select input 2019-12-15 05:29:03 +05:30
Liyas Thomas
498b3f80bf Bumped dependencies and Improved UI contrast (#430)
Bumped dependencies and Improved UI contrast

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-12-14 15:44:50 +05:30
Liyas Thomas
6cf9044db6 🎨 Updated hex to rgba 2019-12-14 15:33:50 +05:30
Liyas Thomas
acc80cff74 ⬆️ Bumped dependencies
🎨 Improved UI contrast
2019-12-14 15:23:10 +05:30
Liyas Thomas
9e2407b7f1 Merge pull request #429 from liyasthomas/dependabot/npm_and_yarn/cypress-3.8.0
⬆️ Bump cypress from 3.7.0 to 3.8.0
2019-12-14 07:40:42 +05:30
dependabot-preview[bot]
6da9beb273 ⬆️ Bump cypress from 3.7.0 to 3.8.0
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.7.0...v3.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-14 00:14:17 +00:00
Liyas Thomas
1104f22f19 Merge pull request #428 from liyasthomas/i18n
I18n
2019-12-13 13:52:15 +05:30
Liyas Thomas
cd272ab0c8 Merge pull request #427 from reefqi037/I18n-Japanese-Translation
I18n Japanese translation added
2019-12-13 13:09:48 +05:30
Abdul Rifqi Al Abqary
34dbec4a5c add newline 2019-12-13 15:38:09 +09:00
Abdul Rifqi Al Abqary
3f0608fd9c I18n Japanese translation added 2019-12-13 15:34:59 +09:00
Liyas Thomas
17a6b03d00 Even (#424)
Even

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
Co-authored-by: Alexandre Reis <alex.cst.reis@gmail.com>
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
2019-12-13 04:56:15 +05:30
Liyas Thomas
5efb921a6b I18n (#423)
I18n

Co-authored-by: William Surya Permana <zarambie_game@yahoo.com>
Co-authored-by: N Jannasch <NJannasch@users.noreply.github.com>
2019-12-13 04:48:26 +05:30
Liyas Thomas
01d4443a4f I18n German translation added (#422)
I18n German translation added
2019-12-13 04:38:15 +05:30
N Jannasch
1591205f46 Create de-DE.js 2019-12-12 17:35:59 -05:00
N Jannasch
ad005d99d2 Create de-DE.js 2019-12-12 17:34:37 -05:00
Andrew Bastin
27e1541a6d Merge pull request #421 from AndrewBastin/feat/header_completion
Header key autocompletion
2019-12-11 18:55:13 -05:00
Andrew Bastin
9fb966f705 GraphQL header keys now offer completion 2019-12-11 18:34:46 -05:00
Andrew Bastin
096b981247 Updated default Autocomplete Component placeholder 2019-12-11 17:46:13 -05:00
Andrew Bastin
cea9ac3965 Header Key values now display suggestions for common headers 2019-12-11 17:29:53 -05:00
Andrew Bastin
f446c9acc1 Generalized AutoComplete Component code 2019-12-11 17:28:32 -05:00
Liyas Thomas
870521c004 Merge pull request #410 from adevr/bug/save-request
Fixing bug on request saving
2019-12-11 09:07:36 +05:30
Liyas Thomas
05114b6dfc Even 2019-12-11 08:58:54 +05:30
Liyas Thomas
945a83625d 🐛 Fixed broken i18n route on toggle 2019-12-11 08:38:26 +05:30
Liyas Thomas
e2d7c0225e 🐛 Fixes #417 2019-12-11 07:07:31 +05:30
Liyas Thomas
55e5444a71 Merge pull request #416 from williamsp/patch-1
Update id-ID.js
2019-12-10 22:15:45 +05:30
William Surya Permana
a3e8a4a41f Update id-ID.js
Fix untranslated "proxy"
2019-12-10 23:41:41 +07:00
Liyas Thomas
b91798e8b8 Merge pull request #414 from williamsp/patch-1
Improving translation for id-ID
2019-12-10 22:03:43 +05:30
Liyas Thomas
d284002803 Zap 2019-12-10 21:58:08 +05:30
William Surya Permana
74e6bf50b1 Improving translation for id-ID
Fix word choice, and use capitalization case from en-US (no longer Capitalized Each Word)
2019-12-10 23:25:41 +07:00
Liyas Thomas
60ba539104 🐛 Fixed opaque select element, curved modals, better disabled color scheme 2019-12-09 09:40:47 +05:30
Liyas Thomas
979909ad57 🎨 Updated color schemes 2019-12-09 09:05:03 +05:30
adevr
c4bd471516 Fixing bug on request saving
This bug appeared when saving a request with no collections available
2019-12-08 23:21:53 +00:00
Liyas Thomas
cd8b4d0dd1 💫 Updating animations and transitions 2019-12-08 22:38:32 +05:30
Liyas Thomas
d018ebda7e 🐛 Fixed abnormal toast margin on mobile devices 2019-12-08 16:10:26 +05:30
Liyas Thomas
5b9aeb70d9 🐛 Fixed #409 2019-12-08 16:05:20 +05:30
Liyas Thomas
35d551f05e 🐛 Fixed toast poition on mobile devices 2019-12-08 10:01:33 +05:30
Liyas Thomas
a32eb24f8c Bottom navbar on mobile device, minor UI revamp 2019-12-08 09:20:19 +05:30
Liyas Thomas
5c7f3c282b Bottom navbar on mobile device, minor UI revamp 2019-12-08 09:20:09 +05:30
Liyas Thomas
c19c399508 🎉 Added icon button animation 2019-12-08 01:08:49 +05:30
Liyas Thomas
4d24d49a0b ✏️ Updated features list 2019-12-07 10:30:28 +05:30
Liyas Thomas
cbe214113c Merge pull request #406 from liyasthomas/dependabot/npm_and_yarn/vue-virtual-scroll-list-1.4.4
⬆️ Bump vue-virtual-scroll-list from 1.4.3 to 1.4.4
2019-12-07 07:16:16 +05:30
Liyas Thomas
fdc2d2cb17 Merge branch 'master' into dependabot/npm_and_yarn/vue-virtual-scroll-list-1.4.4 2019-12-07 06:43:49 +05:30
Liyas Thomas
eae1d22a2f Merge pull request #405 from liyasthomas/dependabot/npm_and_yarn/nuxt-i18n-6.4.1
⬆️ Bump nuxt-i18n from 6.4.0 to 6.4.1
2019-12-07 06:42:40 +05:30
dependabot-preview[bot]
3d66a7deb9 ⬆️ Bump nuxt-i18n from 6.4.0 to 6.4.1
Bumps [nuxt-i18n](https://github.com/nuxt-community/nuxt-i18n) from 6.4.0 to 6.4.1.
- [Release notes](https://github.com/nuxt-community/nuxt-i18n/releases)
- [Changelog](https://github.com/nuxt-community/nuxt-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/nuxt-i18n/compare/v6.4.0...v6.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-07 01:02:36 +00:00
dependabot-preview[bot]
a4022dc70c ⬆️ Bump vue-virtual-scroll-list from 1.4.3 to 1.4.4
Bumps [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/tangbc/vue-virtual-scroll-list/releases)
- [Commits](https://github.com/tangbc/vue-virtual-scroll-list/compare/v1.4.3...v1.4.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-07 01:02:35 +00:00
Liyas Thomas
f82c0cdb4f Merge pull request #407 from liyasthomas/dependabot/npm_and_yarn/nuxtjs/google-analytics-2.2.2
⬆️ Bump @nuxtjs/google-analytics from 2.2.1 to 2.2.2
2019-12-07 06:30:42 +05:30
dependabot-preview[bot]
6e208c3766 ⬆️ Bump @nuxtjs/google-analytics from 2.2.1 to 2.2.2
Bumps [@nuxtjs/google-analytics](https://github.com/nuxt-community/analytics-module) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/nuxt-community/analytics-module/releases)
- [Changelog](https://github.com/nuxt-community/analytics-module/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/analytics-module/compare/v2.2.1...v2.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-12-07 00:15:10 +00:00
Liyas Thomas
777fe9b42a Merge pull request #404 from liyasthomas/i18n
I18n
2019-12-07 02:31:13 +05:30
yubathom
afbf21c47f Fix buttons translations 2019-12-06 16:44:20 -03:00
Gustavo Bezerra
461c30580f Fixing messages in pt-BR 2019-12-06 16:17:38 -03:00
Gustavo Bezerra
82cdcc1cce Improved lang pt-BR. Fixing translate 2019-12-06 16:17:38 -03:00
Gustavo Bezerra
3efcaf4921 Improved lang pt-BR 2019-12-06 16:17:37 -03:00
Liyas Thomas
2be4b672d5 🎨 Text selection color now matches theme (accent color) 2019-12-06 08:59:15 +05:30
Liyas Thomas
2b4d743d79 💄 Scoped styles 2019-12-06 07:11:38 +05:30
Liyas Thomas
c80634b026 Added preload to scripts, sttyles and fonts. Moved font assets to static folder 2019-12-05 06:17:41 +05:30
Liyas Thomas
0028d03e1b 🎨 Minor UI update 2019-12-05 05:51:43 +05:30
Liyas Thomas
d687c9f36d Custom methods support (#400)
Custom methods support

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-12-04 21:51:59 +05:30
Liyas Thomas
5fbf4879ae 🐛 Fixes #399 2019-12-04 21:43:16 +05:30
Liyas Thomas
a719dff1f7 Updating tests 2019-12-04 21:41:58 +05:30
Liyas Thomas
d99170f0d9 Merge branch 'master' into methods 2019-12-04 20:34:19 +05:30
Liyas Thomas
7d5a8499c3 🎉 Custom methods support 2019-12-04 20:19:47 +05:30
Liyas Thomas
1cfaf0bd57 Merge pull request #391 from liyasthomas/app-ui
App UI
2019-12-02 23:00:45 +05:30
Liyas Thomas
bc3c608277 🐛 Fixed connect icon 2019-12-02 22:52:11 +05:30
Liyas Thomas
2f09995306 🎨 Hid sidebar toggle button 2019-12-02 22:29:10 +05:30
Liyas Thomas
72acdeaab9 Improved icon toggle 2019-12-02 20:50:20 +05:30
Liyas Thomas
0bfc0256a6 Optimized UI components 2019-12-02 18:05:10 +05:30
Liyas Thomas
c1a733af53 💄 Minor stylings 2019-12-02 17:12:30 +05:30
Liyas Thomas
c3544076ba 🎉 Toggle sidebar 2019-12-02 13:49:52 +05:30
Liyas Thomas
ae528f6302 🎨 Redesigned color swatches 2019-12-01 06:20:37 +05:30
Liyas Thomas
6a63325f10 Merge pull request #383 from liyasthomas/i18n
i18n
2019-12-01 04:23:24 +05:30
Liyas Thomas
395d244e04 Merge branch 'master' into i18n 2019-12-01 03:29:29 +05:30
Liyas Thomas
d9f0e61375 Added Turkish Language Support (#382)
Added Turkish Language Support
2019-12-01 03:27:14 +05:30
Ali Anıl Koçak
b3751ec4bf nuxt.config.js edited for Turkish Language support 2019-11-30 21:39:58 +00:00
Ali Anıl Koçak
a11a24bfe2 Create tr-TR.js 2019-11-30 21:38:49 +00:00
Liyas Thomas
b31de72ccc Translated new words to Farsi lang (#380)
Translated new words to Farsi lang
2019-11-30 18:56:00 +05:30
Hossein Nedaee
fa4c08dcc5 Translated new words to Farsi lang 2019-11-30 16:44:02 +03:30
Liyas Thomas
d0aa75c792 Two Way Data Binding (v-model) to Ace Editor component (#379)
Two Way Data Binding (v-model) to Ace Editor component
2019-11-30 13:56:40 +05:30
Andrew Bastin
492a5bd5e9 Merge branch 'master' into feat/two_way_ace 2019-11-30 02:42:35 -05:00
Liyas Thomas
772fdd5e87 Merge pull request #378 from peterpeterparker/twitter-card-img
fix: twitter summary card image url
2019-11-30 13:10:33 +05:30
Andrew Bastin
c4116d6819 Added placeholder pre-request script value 2019-11-30 02:26:00 -05:00
Andrew Bastin
050a53af0d Changed pre request script field to use the ace-editor 2019-11-30 02:24:31 -05:00
peterpeterparker
a42136c419 fix: twitter summary card image url 2019-11-30 08:22:54 +01:00
Andrew Bastin
c5d5c15b11 Changed the GQL query entry to use ace-editor 2019-11-30 02:09:34 -05:00
Andrew Bastin
2360803e44 Added v-model support to ace-editor 2019-11-30 02:08:09 -05:00
Liyas Thomas
3f5752247b Added nav shortcuts to GraphQL query and response, updated Graph… (#377)
Added nav shortcuts to GraphQL query and response, updated GraphQL shortcut icons
2019-11-30 08:40:59 +05:30
Andrew Bastin
1e85a649db Added shortcuts to query and response, updated shortcut icons 2019-11-29 21:56:58 -05:00
Liyas Thomas
84eed2aab2 Bump cypress from 3.6.1 to 3.7.0 (#376)
Bump cypress from 3.6.1 to 3.7.0

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2019-11-30 06:22:24 +05:30
Liyas Thomas
32f5e784e8 Merge branch 'master' into dependabot/npm_and_yarn/cypress-3.7.0 2019-11-30 06:10:29 +05:30
Liyas Thomas
53e391982f Bump vuex-persist from 2.1.1 to 2.2.0 (#375)
Bump vuex-persist from 2.1.1 to 2.2.0

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
2019-11-30 06:05:48 +05:30
Liyas Thomas
0f8adf13ae Merge branch 'master' into dependabot/npm_and_yarn/cypress-3.7.0 2019-11-30 05:59:25 +05:30
Liyas Thomas
a91e265097 Merge branch 'master' into dependabot/npm_and_yarn/vuex-persist-2.2.0 2019-11-30 05:58:07 +05:30
Liyas Thomas
b7fc72004f ⚗️ Page animation 2019-11-30 05:54:47 +05:30
dependabot-preview[bot]
9927239ec9 Bump cypress from 3.6.1 to 3.7.0
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.6.1 to 3.7.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.6.1...v3.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-30 00:14:41 +00:00
dependabot-preview[bot]
cff94a1672 Bump vuex-persist from 2.1.1 to 2.2.0
Bumps [vuex-persist](https://github.com/championswimmer/vuex-persist) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/championswimmer/vuex-persist/releases)
- [Changelog](https://github.com/championswimmer/vuex-persist/blob/master/CHANGELOG.md)
- [Commits](https://github.com/championswimmer/vuex-persist/compare/v2.1.1...v2.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-30 00:13:42 +00:00
Liyas Thomas
a0191bafe7 🐛 Fixed browser default shortcut mapping fixes #374 2019-11-29 14:53:44 +05:30
Liyas Thomas
f2262c0e19 📸 Updated screenshots 2019-11-29 12:19:17 +05:30
Liyas Thomas
068d251b64 Lint 2019-11-29 11:25:13 +05:30
Liyas Thomas
1872dacb5e Use GraphQL logo for GraphQL tab (#371)
Use GraphQL logo for GraphQL tab
2019-11-29 08:42:01 +05:30
Liyas Thomas
ef162dd963 Merge pull request #372 from EdikWang/i18n
I18n
2019-11-29 07:39:44 +05:30
Edik
2a19285d3c Added font assets 2019-11-29 09:58:10 +08:00
NBTX
38a9a75b2d Use GraphQL logo for GraphQL tab 2019-11-28 19:48:49 -06:00
Liyas Thomas
6959a4510e I18n (#366)
I18n

Co-authored-by: wahid <wahid@gamatechno.com>
Co-authored-by: LaurentBrieu <laurent.brieu@mediapart.fr>
Co-authored-by: Abdul R. Wahid <wahid.dulrohman@gmail.com>
Co-authored-by: adlpaf <adlpaf@angels>
2019-11-29 04:45:43 +05:30
Liyas Thomas
fe383d32a7 optimized font assets 2019-11-29 04:38:01 +05:30
Liyas Thomas
560bdb139a Added font assets 2019-11-29 04:24:36 +05:30
Liyas Thomas
fe14286bc8 Merge pull request #369 from wahwahid/i18n
Update i18n keywords for Bahasa Indonesia
2019-11-28 22:51:06 +05:30
Liyas Thomas
7584b489ac Merge pull request #368 from adlpaf/i18n
Intent to translate to Spanish on I18n
2019-11-28 22:43:16 +05:30
wahwahid
84461ffa35 Fix Capitalize in Bahasa Indonesia Support Lang 2019-11-29 00:02:07 +07:00
adlpaf
d89c652622 Translated to Spanish 2019-11-28 13:56:56 -03:00
adlpaf
9d19d26d8e Translated to Spanish 2019-11-28 13:43:34 -03:00
wahwahid
e307d51f24 Update keywords i18n for Bahasa Indonesia 2019-11-28 23:15:32 +07:00
Edik
4632e281a6 Merge pull request #3 from liyasthomas/i18n
I18n
2019-11-28 23:57:23 +08:00
Liyas Thomas
ab4f961795 Merge branch 'master' into i18n 2019-11-28 21:20:19 +05:30
Abdul R. Wahid
9859a34e90 Merge pull request #1 from liyasthomas/i18n
I18n
2019-11-28 22:35:41 +07:00
Liyas Thomas
b10a209daf Improving performance 2019-11-28 20:41:52 +05:30
Liyas Thomas
2a81c2611b Merge pull request #364 from LaurentBrieu/add-translations-for-fr-en-catalogues
Add translations for FR/EN catalogues
2019-11-28 18:07:22 +05:30
Edik
8d98c8ad16 Merge pull request #1 from liyasthomas/i18n
I18n
2019-11-28 20:31:10 +08:00
LaurentBrieu
1c12c66b31 Add translations for FR/EN catalogues 2019-11-28 13:27:52 +01:00
Liyas Thomas
cb79567942 Merge pull request #362 from wahwahid/i18n-id
Added Bahasa Indonesia language support
2019-11-28 08:31:24 +05:30
wahid
c35a9c64f6 Added Bahasa Indonesia language support 2019-11-28 09:51:42 +07:00
Liyas Thomas
95832eb657 Merge pull request #361 from liyasthomas/i18n
i18n
2019-11-28 08:14:30 +05:30
Liyas Thomas
ee53c12c35 Merge branch 'master' into i18n 2019-11-28 08:07:01 +05:30
Liyas Thomas
c3d2d928b3 Add Simplified Chinese language (#360)
Add Simplified Chinese language
2019-11-28 08:01:53 +05:30
Liyas Thomas
87e598b5f0 Merge branch 'i18n' into i18n 2019-11-28 07:48:39 +05:30
Liyas Thomas
f61cbba8cb 🐛 Fixed i18n routing 2019-11-28 07:45:35 +05:30
Edik
a4089efe85 Add Simplified Chinese language 2019-11-28 09:38:31 +08:00
Liyas Thomas
781d8e3b68 Merge pull request #359 from tetri/patch-1
Added Brazilian Portuguese language support
2019-11-28 04:49:14 +05:30
Tetri Mesquita
cf81a970cc Added Brazilian Portuguese language support 2019-11-27 20:01:34 -03:00
Liyas Thomas
367d73ef23 i18n 2019-11-28 00:38:23 +05:30
Tetri Mesquita
314084d092 Added Brazilian Portuguese language support 2019-11-27 15:59:09 -03:00
Liyas Thomas
e4441d129c Merge pull request #357 from hosseinnedaee/i18n
Added Farsi language support
2019-11-27 23:28:57 +05:30
Hossein Nedaee
292550f6b5 Added Farsi language support 2019-11-27 21:03:02 +03:30
Liyas Thomas
93364afc98 Merge pull request #355 from thomasbnt/i18n
Adding french language basic
2019-11-27 21:34:37 +05:30
Thomas Bnt
558b961afa Forgotten space 2019-11-27 16:55:15 +01:00
Thomas Bnt
d99b5cf525 Added French language (basic config) 2019-11-27 16:49:59 +01:00
Liyas Thomas
c75e4a52eb Updated test 2019-11-27 20:22:32 +05:30
Liyas Thomas
0ac01fe8e5 Updated test 2019-11-27 20:15:47 +05:30
Liyas Thomas
13615e06e9 🐛 Fixes #353 2019-11-27 19:52:03 +05:30
Liyas Thomas
623b177eb0 Basic i18n support (#351)
Basic i18n support
2019-11-27 17:40:32 +05:30
Liyas Thomas
a74522c465 Merge branch 'master' into i18n 2019-11-27 17:33:16 +05:30
Liyas Thomas
4f5788fe31 Merge pull request #344 from athul/athul-patch
♻️ Refactor Functions
2019-11-27 17:22:30 +05:30
Liyas Thomas
d739af3d4b Merge branch 'master' into athul-patch 2019-11-27 17:14:50 +05:30
Liyas Thomas
3a2284cf99 ES6 2019-11-27 17:04:43 +05:30
Liyas Thomas
9019babf6d Merge branch 'master' into i18n 2019-11-27 15:44:02 +05:30
Liyas Thomas
5382cd8d5f 🐛 Fixed SSE connection closing issues. Fixes #349 2019-11-27 15:35:39 +05:30
Liyas Thomas
37c41086d2 Undo header/param/body param deletion (#350)
Undo header/param/body param deletion
2019-11-27 15:09:56 +05:30
Liyas Thomas
2697cce6dd 🎉 Basic i18n support 2019-11-27 14:15:11 +05:30
Andrew Bastin
294b26787b Added undo functionality to the index page 2019-11-26 23:01:03 -05:00
Andrew Bastin
b67de81616 Added undo button for undoing removing headers 2019-11-26 22:46:33 -05:00
Liyas Thomas
36568d5720 🐛 Fixed build + refactored all js files 2019-11-27 06:54:32 +05:30
Liyas Thomas
dcf1966719 Merge branch 'master' into athul-patch 2019-11-27 05:57:53 +05:30
Liyas Thomas
33cbc9b525 Added ability to run GraphQL queries (#346)
Added ability to run GraphQL queries
2019-11-27 04:52:56 +05:30
Andrew Bastin
d2115ab004 Added ability to copy GQL response 2019-11-26 16:55:43 -05:00
Andrew Bastin
9cbd6ea7b7 Added ability to copy GQL query 2019-11-26 16:48:13 -05:00
Andrew Bastin
ded69f979e Entered GQL query is persisted 2019-11-26 15:44:15 -05:00
Andrew Bastin
7fab6f4732 Added query field to the GQL state 2019-11-26 15:43:06 -05:00
Andrew Bastin
9ad822577b Added ability to do GraphQL queries 2019-11-26 15:37:41 -05:00
Athul Cyriac Ajay
bdaac40435 Deleting Comments
Co-Authored-By: James George <jamesgeorge998001@gmail.com>
2019-11-26 21:03:53 +05:30
James George
19b43e152a Merge branch 'master' into athul-patch 2019-11-26 20:57:23 +05:30
Liyas Thomas
c4c320da83 🚨 Lint 2019-11-26 20:01:48 +05:30
athul
43cd6504b6 Edited as per @jamesgeorge007 's said 2019-11-26 19:08:28 +05:30
athul
cb8734bba7 Revert "Resolves @jamegeorge007 's Review"
This reverts commit 57860c17d9.
2019-11-26 19:03:06 +05:30
athul
57860c17d9 Resolves @jamegeorge007 's Review 2019-11-26 18:59:19 +05:30
Athul Cyriac Ajay
c56c162045 Update assets/js/curlparser.js
Co-Authored-By: James George <jamesgeorge998001@gmail.com>
2019-11-26 18:50:42 +05:30
Liyas Thomas
249407403d Merge branch 'master' into athul-patch 2019-11-26 18:44:31 +05:30
Liyas Thomas
1aa5ec6aa4 Merge pull request #345 from NBTX/master
Add Proxy URL option
2019-11-26 18:34:47 +05:30
athul
f129ead9a0 Merge branch 'athul-patch' of github.com:athul/postwoman into athul-patch 2019-11-26 18:32:03 +05:30
athul
321a45615a Formatted 2019-11-26 18:31:55 +05:30
NBTX
dd280732d1 Add Proxy URL option 2019-11-26 06:53:12 -06:00
Athul Cyriac Ajay
8966e6fd55 Delete yarn.lock 2019-11-26 18:22:41 +05:30
athul
3523b5f2c7 ♻️ Refactor Functions 2019-11-26 18:19:51 +05:30
Liyas Thomas
2f727b1a1e refactor: minor improvements (#343)
refactor: minor improvements
2019-11-26 17:44:11 +05:30
jamesgeorge007
6e537eed58 fix: make headers property writable 2019-11-26 15:41:53 +05:30
jamesgeorge007
ffb8fd0172 refactor(index): use directive shorthand notation
for consistency
2019-11-26 14:37:32 +05:30
jamesgeorge007
ba1410c7f4 refactor(index): self closing components 2019-11-26 14:34:40 +05:30
jamesgeorge007
61f8e36383 refactor(folder): self closing component 2019-11-26 14:32:18 +05:30
jamesgeorge007
20a7094d33 refactor(index): us Array.includes 2019-11-26 14:27:51 +05:30
jamesgeorge007
06d7534462 refactor(realtime): replace instances of var with const 2019-11-26 14:25:40 +05:30
jamesgeorge007
b3680224cc refactor(index): replace instances of var with const 2019-11-26 14:24:27 +05:30
jamesgeorge007
113bf14718 refactor(graphql): replace instances of var with const 2019-11-26 14:20:57 +05:30
Andrew Bastin
937df4486e Merge pull request #341 from AndrewBastin/feat/gql_req_header
GraphQL Request Headers
2019-11-26 00:06:59 -05:00
Andrew Bastin
5f79ca2872 Fixed header inclusion mistake 2019-11-25 23:42:41 -05:00
Andrew Bastin
e999d7428a Merge remote-tracking branch 'upstream/master' into feat/gql_req_header 2019-11-25 22:52:23 -05:00
Andrew Bastin
146df237f2 Added Headers for GraphQL requests 2019-11-25 22:48:36 -05:00
Liyas Thomas
d802945ec7 Separate dockerfile layers and add volume (#340)
Separate dockerfile layers and add volume
2019-11-26 08:56:52 +05:30
Andrew Bastin Kalloor Biju
122782f244 Added headers field to state and added mutations to handle header list updates 2019-11-25 22:25:22 -05:00
Vítor Xoteslem
ff006a254a Separate dockerfile layers and add volume 2019-11-26 00:03:55 -03:00
Liyas Thomas
c1d11e7489 🐛 Fixed incorrect badge label 2019-11-26 07:41:03 +05:30
Liyas Thomas
7d78d34de0 🐛 Fixed incorrect badge label 2019-11-25 21:57:15 +05:30
Liyas Thomas
5f97f49f28 ✏️ Writing docs 2019-11-25 20:45:13 +05:30
Liyas Thomas
f63bb11cc3 🍭 Updated funding links 2019-11-25 09:36:43 +05:30
Liyas Thomas
b23f0a9c16 Refactoring code (#332)
Refactoring code

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-25 06:09:58 +05:30
Liyas Thomas
e609300533 Merge branch 'master' into refactor 2019-11-25 06:03:39 +05:30
Liyas Thomas
f623b31220 ♻️ Refactoring code 2019-11-25 05:51:48 +05:30
Liyas Thomas
a17239ca31 ♻️ Refactoring code 2019-11-25 05:44:44 +05:30
Liyas Thomas
f2a35a7716 SSE (#330)
SSE

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-25 05:20:41 +05:30
Liyas Thomas
0383403cce Adds Server Sent Events debug support 2019-11-25 05:13:35 +05:30
Liyas Thomas
57b71ce4ea Merge branch 'sse' of https://github.com/liyasthomas/postwoman into sse 2019-11-24 18:46:01 +05:30
Liyas Thomas
f6752e9743 SSE mvp 2019-11-24 18:45:26 +05:30
Liyas Thomas
45fa84d5ae Merge branch 'master' into sse 2019-11-24 17:39:32 +05:30
Liyas Thomas
873b97b052 🎉 Initial SSE MVP 2019-11-24 08:48:50 +05:30
Liyas Thomas
7a25f4c13c 💫 Updated Support us section 2019-11-23 18:15:15 +05:30
Liyas Thomas
48e9171153 Improving accessibility 2019-11-23 15:25:30 +05:30
Liyas Thomas
1dbea4d39a Initial SSE MVP 2019-11-23 14:31:15 +05:30
Liyas Thomas
edba562a99 Added download & expand button for GraphQL schema response 2019-11-23 10:31:53 +05:30
Liyas Thomas
60368341ed ⬆️ Bump vue-virtual-scroll-list from 1.4.2 to 1.4.3 (#328)
⬆️ Bump vue-virtual-scroll-list from 1.4.2 to 1.4.3

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2019-11-23 08:34:52 +05:30
dependabot-preview[bot]
ab24faaa55 ⬆️ Bump vue-virtual-scroll-list from 1.4.2 to 1.4.3
Bumps [vue-virtual-scroll-list](https://github.com/tangbc/vue-virtual-scroll-list) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/tangbc/vue-virtual-scroll-list/releases)
- [Commits](https://github.com/tangbc/vue-virtual-scroll-list/compare/v1.4.2...v1.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-23 00:13:30 +00:00
Liyas Thomas
e79b113907 Merge pull request #322 from AndrewBastin/feat/gql_proxy
GraphQL introspection requests now support and respect proxying
2019-11-21 23:31:20 +05:30
Liyas Thomas
fb69fcee3c Merge branch 'master' into feat/gql_proxy 2019-11-21 22:11:36 +05:30
Andrew Bastin
41ff83821b GraphQL introspection requests now support and respect Proxying 2019-11-21 11:31:58 -05:00
Liyas Thomas
463ef82255 Added Expand/Collapse response button. Fixes #320 2019-11-21 20:28:06 +05:30
Liyas Thomas
5d011b09ae GraphQL endpoint field is now persisted (#319)
GraphQL endpoint field is now persisted
2019-11-21 10:49:04 +05:30
Andrew Bastin
638f3f1a05 GraphQL endpoint URL is now persisted 2019-11-21 00:02:30 -05:00
Andrew Bastin
879fc58d9c Added mutation for working with the GQL store 2019-11-21 00:01:12 -05:00
Andrew Bastin
2c139c2a65 Added GQL object to global store 2019-11-21 00:00:15 -05:00
Liyas Thomas
4c9c9a2240 🚨 Lint 2019-11-21 09:11:50 +05:30
Liyas Thomas
354ad3983f 🎨 Updated GraphQL docs section styles 2019-11-21 07:09:17 +05:30
Liyas Thomas
8d99d4aa99 :liptick: Minor UI update 2019-11-21 06:55:37 +05:30
Liyas Thomas
1ab2de9c69 Merge pull request #318 from AndrewBastin/feat/gql_copy_schema
Added button to copy GraphQL schema
2019-11-21 02:49:08 +05:30
Andrew Bastin
6a938cdcca Added copy schema button to copy schema string to clipboard 2019-11-20 17:49:42 +00:00
Liyas Thomas
0c705bfa6d ✏️ Added GraphQL support to feature list 2019-11-20 20:29:23 +05:30
Liyas Thomas
6169f1c150 chore(refactor): switch to async/await approach (#317)
chore(refactor): switch to async/await approach
2019-11-20 19:43:22 +05:30
jamesgeorge007
3639ed8f70 fix: add async nature 2019-11-20 18:11:07 +05:30
jamesgeorge007
2083e02698 fix: typo 2019-11-20 18:08:30 +05:30
jamesgeorge007
a7d483ea1b fix: lint 2019-11-20 18:07:52 +05:30
jamesgeorge007
a0dd02ec07 fix: lint 2019-11-20 18:07:33 +05:30
jamesgeorge007
929d955237 fix: minor tweak 2019-11-20 18:06:19 +05:30
jamesgeorge007
f61eeebc8f fix: lint 2019-11-20 18:05:46 +05:30
jamesgeorge007
f8c3d1e6db refactor: use async await approach 2019-11-20 18:00:17 +05:30
Liyas Thomas
38513d3eed GraphQL Support (#311)
GraphQL Support

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-20 12:04:19 +05:30
Andrew Bastin
051259419c Merge branch 'master' into master 2019-11-20 01:09:36 -05:00
Liyas Thomas
fad28ee40b Compact UI. fixe #314 2019-11-20 06:16:02 +05:30
Liyas Thomas
1d9778226c feat: use alpine for Dockerfile (#316)
feat: use alpine for Dockerfile
2019-11-20 05:45:21 +05:30
Colin Nelson
f1dab84571 Merge branch 'master' into dockerfile-alpine 2019-11-19 15:58:46 -08:00
Liyas Thomas
c413317970 📸 Updated screenshots 2019-11-20 05:27:00 +05:30
Andrew Bastin
631c8b625b Removed debug console logs 2019-11-19 15:42:28 -05:00
Colin Nelson
2dd9683eb1 feat: use alpine for Dockerfile
Reduces resultant image size to ~942MB (was 1.55GB).
2019-11-19 10:54:16 -08:00
Andrew Bastin
f7faac1afc Added deprecated label for deprecated GQL fields 2019-11-19 12:06:47 -05:00
Liyas Thomas
91d0422f53 Minor UI stylings 2019-11-19 20:29:18 +05:30
Liyas Thomas
a22090e3df Added scroll for overflowing Docs section 2019-11-19 20:13:46 +05:30
Liyas Thomas
62f52a0be1 🐛 Fixed gqlType 2019-11-19 09:53:02 +05:30
Liyas Thomas
eca1dc8e66 Moved Cocs section to right sidebar (will fix overflow issue later today) + Basic lint 2019-11-19 08:55:57 +05:30
Andrew Bastin
8e3542863a Filtered unwanted type entries 2019-11-18 21:53:13 -05:00
Andrew Bastin
34be6ce795 Added GraphQL types section in docs 2019-11-18 15:17:33 -05:00
Andrew Bastin
2d995b87b1 Added GraphQL type component 2019-11-18 15:17:07 -05:00
Andrew Bastin
edbb81d089 Added a null guard for args field 2019-11-18 15:14:26 -05:00
Andrew Bastin
6c4fbb501c Fixed margin mistake in field-desc 2019-11-18 14:58:37 -05:00
Andrew Bastin
5f3ca632cb Added docs section with query,mutation and subscription lists 2019-11-18 14:34:31 -05:00
Andrew Bastin
3db28e4f22 Added GraphQL field component 2019-11-18 14:34:00 -05:00
Liyas Thomas
79a7b3c985 🌱 Error handlers 2019-11-18 22:20:18 +05:30
Liyas Thomas
109d57b4b4 Merge branch 'master' into master 2019-11-18 19:58:51 +05:30
Liyas Thomas
71779d560a Added loader, changed webSocket icon 2019-11-18 19:55:54 +05:30
Liyas Thomas
967bf49db0 Lint 2019-11-18 18:02:44 +05:30
Liyas Thomas
3cedd48503 Merge branch 'master' into master 2019-11-18 07:12:59 +05:30
Liyas Thomas
0c303b63bd Merge pull request #310 from liyasthomas/app-ui
 Minor UI updates
2019-11-18 07:11:01 +05:30
Liyas Thomas
ef070dbad7 Merge branch 'master' into app-ui 2019-11-18 07:04:07 +05:30
liyasthomas
d88e777f80 Minor UI updates 2019-11-18 06:32:30 +05:30
Andrew Bastin
cffdd56522 Added GraphQL page to the sidebar 2019-11-17 19:48:53 -05:00
Andrew Bastin
d44b821a04 Added GraphQL page 2019-11-17 19:48:29 -05:00
Andrew Bastin
0c6a59282e Added graphql as dependency 2019-11-17 18:00:01 -05:00
Liyas Thomas
3ba2aa922f App ui (#309)
App ui
2019-11-17 15:13:48 +05:30
liyasthomas
ce8e2c6684 Right secondary sidebar 2019-11-17 15:04:06 +05:30
liyasthomas
d3aa8e03a2 Moved sidebar to left 2019-11-17 11:58:40 +05:30
liyasthomas
3ae9c49029 Moved History and Collection sections to right side bar 2019-11-17 08:25:07 +05:30
liyasthomas
bac0db10a6 UI optimizations 2019-11-17 05:03:57 +05:30
liyasthomas
a40d67138b 🎨 Moved History & Collection section to sticky right nav (initial upload). 2019-11-17 03:26:26 +05:30
Liyas Thomas
a8f6df16a8 🐛 Fixed entry animation on few modals 2019-11-16 14:14:53 +05:30
Liyas Thomas
63f23118b6 Merge branch 'master' of https://github.com/liyasthomas/postwoman 2019-11-16 11:21:26 +05:30
Liyas Thomas
71de9cfec5 🐛 Fixed Edit foldernot working, added critical render for Collection component 2019-11-16 11:20:36 +05:30
Liyas Thomas
5f8729536c 💩 Removed unused parameters 2019-11-16 11:20:35 +05:30
dependabot-preview[bot]
461dd21806 ⬆️ Bump @nuxtjs/sitemap from 2.0.0 to 2.0.1
Bumps [@nuxtjs/sitemap](https://github.com/nuxt-community/sitemap-module) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/nuxt-community/sitemap-module/releases)
- [Changelog](https://github.com/nuxt-community/sitemap-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/sitemap-module/compare/v2.0.0...v2.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-16 11:20:34 +05:30
Liyas Thomas
d5a44fdec4 ⬆️ Bump @nuxtjs/sitemap from 2.0.0 to 2.0.1 (#307)
⬆️ Bump @nuxtjs/sitemap from 2.0.0 to 2.0.1

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2019-11-16 08:56:32 +05:30
dependabot-preview[bot]
0fd96aa92e ⬆️ Bump @nuxtjs/sitemap from 2.0.0 to 2.0.1
Bumps [@nuxtjs/sitemap](https://github.com/nuxt-community/sitemap-module) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/nuxt-community/sitemap-module/releases)
- [Changelog](https://github.com/nuxt-community/sitemap-module/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/nuxt-community/sitemap-module/compare/v2.0.0...v2.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-16 00:13:43 +00:00
Liyas Thomas
3ba6de6f34 Lazy (#306)
Lazy

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-16 01:03:44 +05:30
Liyas Thomas
d214be027d 🐛 Fixed critical render for essential components 2019-11-16 00:51:16 +05:30
Liyas Thomas
af7273e7eb Lazy components 2019-11-16 00:32:27 +05:30
Liyas Thomas
69971198af ⚗ Lazy component import 2019-11-16 00:25:05 +05:30
Liyas Thomas
23a681f214 Merge pull request #305 from liyasthomas/shortcuts
 Added "Keyboard shortcuts" to features list
2019-11-15 05:08:40 +05:30
Liyas Thomas
7516524d38 Added "Keyboard shortcuts" to features list 2019-11-15 00:05:51 +05:30
Liyas Thomas
474711431e More shortcuts (#304)
 More shortcuts

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-14 23:41:30 +05:30
Liyas Thomas
3cea9de8fe More shortcuts 2019-11-14 23:18:44 +05:30
Liyas Thomas
9235b0ffb6 Keyboard shortcuts (#303)
Keyboard shortcuts

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-14 19:09:40 +05:30
Liyas Thomas
a159275dba Polished Shortcuts modal 2019-11-14 19:02:44 +05:30
Liyas Thomas
105005aa07 Merge branch 'shortcuts' of https://github.com/liyasthomas/postwoman into shortcuts 2019-11-14 18:28:40 +05:30
Liyas Thomas
40a8d45ab0 More shortcuts 2019-11-14 17:43:45 +05:30
Liyas Thomas
009eae83a6 Keyboard shortcuts 2019-11-14 16:28:17 +05:30
Liyas Thomas
c146879fd3 Lint (#301)
 Lint
2019-11-14 10:18:58 +05:30
Liyas Thomas
00c6e22861 Lint 2019-11-14 10:10:02 +05:30
Liyas Thomas
939a74b7be 💄 Minor UI improvements (#300)
💄 Minor UI improvements

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-14 05:30:47 +05:30
Liyas Thomas
a53db858e3 Merge branch 'app-ui' of https://github.com/liyasthomas/postwoman into app-ui 2019-11-14 05:26:58 +05:30
Liyas Thomas
38da938ec1 🔎 Improving Lighthouse score 2019-11-14 05:25:12 +05:30
Liyas Thomas
8cf1a37633 Merge branch 'master' into app-ui 2019-11-14 05:07:16 +05:30
Liyas Thomas
9de8c4cf04 💄 Minor UI improvements 2019-11-14 05:00:44 +05:30
Liyas Thomas
40be148c9b 📱 Popovers on mobile devices (#297)
📱 Popovers on mobile devices

Co-authored-by: Liyas Thomas <liyasthomas@gmail.com>
2019-11-13 21:16:55 +05:30
Liyas Thomas
dfbb563b6f Added payload upload feature. Fixes #298 2019-11-13 21:04:49 +05:30
Liyas Thomas
ab76afb322 Merge branch 'app-ui' of https://github.com/liyasthomas/postwoman into app-ui 2019-11-13 19:20:26 +05:30
Liyas Thomas
4b3593d081 🐛 Fixed huge padding in auto-complete 2019-11-13 19:18:34 +05:30
Liyas Thomas
210e182d7e ✏️ Typo 2019-11-13 16:56:14 +05:30
Liyas Thomas
6f1154a1f8 Merge branch 'app-ui' of https://github.com/liyasthomas/postwoman into app-ui 2019-11-13 09:30:23 +05:30
Liyas Thomas
d935ff4b3e ✏️ Initial docs upload 2019-11-13 09:29:42 +05:30
Liyas Thomas
cd92d87c5d Merge branch 'master' into app-ui 2019-11-13 07:06:41 +05:30
Liyas Thomas
e8ac8ac0ab 📱 Popovers 2019-11-13 06:57:09 +05:30
Liyas Thomas
7ae7bdd670 Merge pull request #296 from liyasthomas/app-ui
Moved "Generate code" section to modal
2019-11-13 04:50:10 +05:30
Liyas Thomas
1dbb89df34 ⚗️ Popover 2019-11-12 22:35:46 +05:30
Liyas Thomas
b9908f68f9 Fixed abnormal popover position 2019-11-12 22:27:14 +05:30
Liyas Thomas
b839e8183f Moved Generate code section to modal 2019-11-12 16:05:33 +05:30
Liyas Thomas
51b370efa6 Minor UI changes (#295)
Minor UI changes
2019-11-12 10:57:56 +05:30
Liyas Thomas
f65e67d86a 🐛 Fixed invisible Install PWA button 2019-11-12 10:44:52 +05:30
Liyas Thomas
653e42c2b9 🚨 Lint 2019-11-12 10:22:50 +05:30
Liyas Thomas
3b6c8247c5 Minor UI changes 2019-11-12 09:48:57 +05:30
Hossein Nedaee
f457cc5107 Merge pull request #292 from hosseinnedaee/implement-ace-instead-highlightjs
Replace highlight.js with ace editor.
2019-11-12 06:58:51 +03:30
Liyas Thomas
f9e62f3237 Merge branch 'master' into implement-ace-instead-highlightjs 2019-11-12 07:24:47 +05:30
Hossein Nedaee
4ca78a2fe5 Make lang prop dynamic. 2019-11-11 21:44:29 +03:30
Hossein Nedaee
179010ddbf Change ace-editor theme by PW theme changing. 2019-11-11 20:44:24 +03:30
Liyas Thomas
4cca931d9d 🔍 SEO optimizations 2019-11-11 19:23:35 +05:30
Liyas Thomas
3c2743510b 🔍 SEO optimizations 2019-11-11 19:01:49 +05:30
Hossein Nedaee
716434d59e Reduce response body font size 2019-11-10 21:08:57 +03:30
Hossein Nedaee
4accbda497 Change ace editor font-family 2019-11-10 21:03:20 +03:30
Liyas Thomas
9f0512e81e 📱 Responsive History section for mobile devices 2019-11-10 21:49:26 +05:30
Liyas Thomas
10b699a6f7 Favorite (star) History entries 2019-11-10 12:08:10 +05:30
Hossein Nedaee
1a9b4cdbf5 Replace highlight.js with ace editor. 2019-11-09 22:58:05 +03:30
Liyas Thomas
ee8f133ebb ⚗️ Hid commiit hash and variant from footer 2019-11-09 21:31:20 +05:30
Liyas Thomas
b193625fb6 🎨 Version and hash on footer 2019-11-09 21:10:00 +05:30
Liyas Thomas
ca3abed605 🔥 Better boolean conditions 2019-11-09 20:43:48 +05:30
liyasthomas
3b2fd26bd9 Merge branch 'master' of https://github.com/liyasthomas/postwoman 2019-11-09 14:31:54 +05:30
liyasthomas
1b21187397 Better History section 2019-11-09 14:31:07 +05:30
liyasthomas
c2519bdb7d Added pw.env.set() for storing environment variables 2019-11-09 12:17:50 +05:30
Liyas Thomas
797edc50f4 Checking if seciton exist before accessing its properties (#288)
Checking if seciton exist before accessing its properties
2019-11-09 07:50:09 +05:30
liyasthomas
6ffbd88d92 ✏️ Updated meta 2019-11-09 07:44:22 +05:30
liyasthomas
377cd2ba1f Merge branch 'master' of https://github.com/liyasthomas/postwoman 2019-11-09 07:19:51 +05:30
liyasthomas
14a67fa698 🐛 Fixed #275 2019-11-09 07:18:53 +05:30
Liyas Thomas
efe1c7ba45 ⬆️ Bump cypress from 3.6.0 to 3.6.1 (#290)
⬆️ Bump cypress from 3.6.0 to 3.6.1

Co-authored-by: null <27856297+dependabot-preview[bot]@users.noreply.github.com>
2019-11-09 05:52:27 +05:30
dependabot-preview[bot]
96cf5f43d2 ⬆️ Bump cypress from 3.6.0 to 3.6.1
Bumps [cypress](https://github.com/cypress-io/cypress) from 3.6.0 to 3.6.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Commits](https://github.com/cypress-io/cypress/compare/v3.6.0...v3.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-09 00:14:29 +00:00
liyasthomas
4ed461bc69 ✏️ Updated link 2019-11-09 00:45:58 +05:30
liyasthomas
78fd2d5399 🐛 Fixed overflow on WebSocket response box 2019-11-08 23:56:49 +05:30
liyasthomas
cf1d07e7a6 🐛 Fixed #289 2019-11-08 23:41:30 +05:30
liyasthomas
f71b940197 Adds expandable columns to History component for showing request duration and pre-request scripts if any. Fixes #233 #225 2019-11-08 23:22:48 +05:30
liyasthomas
aae182a9f8 Added preRequestScript and request duration to history entry 2019-11-08 22:26:43 +05:30
rafi993
2162f52e00 Checking if seciton is valid 2019-11-08 16:36:55 +05:30
Liyas Thomas
7a88d2d08c Fixes #281 (accessibility issues) 2019-11-08 09:08:35 +05:30
Liyas Thomas
896c4e7561 🐛 Fixed broken syntax highlighting 2019-11-08 00:52:45 +05:30
Liyas Thomas
c537477d3a 🐛 Better error prompt. Fixes #283 2019-11-08 00:28:58 +05:30
Liyas Thomas
2a9adfd180 Improving accessibility 2019-11-08 00:01:35 +05:30
Liyas Thomas
7a60cc25e9 :wheel_chair: Improving accessibility 2019-11-07 23:11:41 +05:30
Liyas Thomas
73255c9c75 Enhancement: make saving of collections, requests, folder more c… (#282)
Enhancement: make saving of collections, requests, folder more convenient
2019-11-07 16:19:33 +00:00
Markus Reisenhofer
840af00d6d Added event for new request as well 2019-11-07 16:26:19 +01:00
Markus Reisenhofer
c3a58eec8d Added enter key event for convenience reasons 2019-11-07 16:09:31 +01:00
Liyas Thomas
e18b8f6bb6 Improving accessibility, fixes #277 2019-11-07 09:29:08 +05:30
Liyas Thomas
48d4e69fc8 Improving accessibility, fixes #279 2019-11-07 09:19:37 +05:30
Liyas Thomas
c388eddc67 Added response URL, Path, Method and timestamp to downloaded response file 2019-11-07 08:59:04 +05:30
Liyas Thomas
dcf5c2a0d6 Merge pull request #280 from Daniellunsc/add-download-button
Add download button
2019-11-07 08:00:53 +05:30
Daniel Luna
7d070810d5 Updated README 2019-11-06 23:21:38 -03:00
Daniel Luna
5923c88a94 Added download button 2019-11-06 23:19:27 -03:00
Liyas Thomas
a45770119c Fix #271 Duplicated query string (#273)
Fix #271 Duplicated query string
2019-11-06 14:43:05 +05:30
RifqiAlAbqary
d3d3cda758 Fix #271 Duplicated query string 2019-11-06 18:05:13 +09:00
Liyas Thomas
8ae157a272 Fix #269 Incorrect code generation (#270)
Fix #269 Incorrect code generation
2019-11-06 13:20:00 +05:30
RifqiAlAbqary
8398db90ef Merge remote-tracking branch 'upstream/master' into fix-code-generation 2019-11-06 16:17:36 +09:00
RifqiAlAbqary
177585c998 Fix #269 Incorrect code generation 2019-11-06 16:17:03 +09:00
Liyas Thomas
7ac9c34820 ✏️ Added Wiki links to sections 2019-11-06 12:23:30 +05:30
Liyas Thomas
5e424bb64d 🐛 Fixed a critical bug, clear cookies to take effect 2019-11-06 09:25:55 +05:30
Liyas Thomas
d290b25f8a 🐛 Fixed a critical bug, clear cookies to take effect 2019-11-06 08:35:56 +05:30
Liyas Thomas
90c3ca47b9 🐛 Fixed light theme issues on highlightjs 2019-11-05 19:03:09 +05:30
Liyas Thomas
924a931568 📜 v1.0.0 changelog 2019-11-04 17:47:31 +05:30
114 changed files with 15159 additions and 4758 deletions

View File

@@ -52,15 +52,6 @@
"code"
]
},
{
"login": "terranblake",
"name": "Terran Blake",
"avatar_url": "https://avatars3.githubusercontent.com/u/8795767?v=4",
"profile": "https://www.lumahealth.io/",
"contributions": [
"code"
]
},
{
"login": "AndrewBastin",
"name": "Andrew Bastin",

3
.github/FUNDING.yml vendored
View File

@@ -1,4 +1,3 @@
ko_fi: liyasthomas
open_collective: liyasthomas
open_collective: postwoman
patreon: liyasthomas
custom: https://www.paypal.me/liyascthomas

6
.gitignore vendored
View File

@@ -98,3 +98,9 @@ sw.*
# File explorer
.directory
# Tests screenshots
tests/*/screenshots
# Tests videos
tests/*/videos

View File

@@ -15,6 +15,8 @@ language: node_js
node_js:
- "12"
os: linux
addons:
apt:
packages:
@@ -38,6 +40,7 @@ install:
- "npm install"
before_script:
- "npm run build" # use nuxt build and start to run tests
- "npm run test"
script:

View File

@@ -1,3 +1,457 @@
# Changelog
* [v0.1.0](https://github.com/liyasthomas/postwoman/releases/tag/v0.1.0) - Initial 🎉 Initial public release
## [v1.9.0](https://github.com/liyasthomas/postwoman/tree/v1.9.0) (2020-02-24)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/v1.8.0...v1.9.0)
**Implemented enhancements:**
- Disable SSL cert for websockets [\#557](https://github.com/liyasthomas/postwoman/issues/557)
- Feature request: Keyboard shortcuts for folder creation [\#539](https://github.com/liyasthomas/postwoman/issues/539)
- Friendly minded GraphQL [\#468](https://github.com/liyasthomas/postwoman/issues/468)
- multipart/form-data support [\#434](https://github.com/liyasthomas/postwoman/issues/434)
- Implement pre-request and post-request scripts \(and request chaining\) [\#218](https://github.com/liyasthomas/postwoman/issues/218)
- Environment management and configuration [\#147](https://github.com/liyasthomas/postwoman/issues/147)
- POST request body editor reacts to the content type [\#594](https://github.com/liyasthomas/postwoman/pull/594) ([AndrewBastin](https://github.com/AndrewBastin))
- Environment Mangement [\#591](https://github.com/liyasthomas/postwoman/pull/591) ([JacobAnavisca](https://github.com/JacobAnavisca))
- GraphQL Query Autocompletion [\#590](https://github.com/liyasthomas/postwoman/pull/590) ([AndrewBastin](https://github.com/AndrewBastin))
- Postman collection parsing [\#574](https://github.com/liyasthomas/postwoman/pull/574) ([JacobAnavisca](https://github.com/JacobAnavisca))
- Added toggle to decide whether extensions should be used [\#551](https://github.com/liyasthomas/postwoman/pull/551) ([AndrewBastin](https://github.com/AndrewBastin))
- Show Ctrl instead of Command for shortcuts non-Apple platforms [\#549](https://github.com/liyasthomas/postwoman/pull/549) ([AndrewBastin](https://github.com/AndrewBastin))
- Updated GraphQL Query Variable Editor [\#534](https://github.com/liyasthomas/postwoman/pull/534) ([AndrewBastin](https://github.com/AndrewBastin))
**Fixed bugs:**
- Auto Theme Selection is kinda difficult to see [\#563](https://github.com/liyasthomas/postwoman/issues/563)
- Can't send request to localhost via Chrome extention [\#560](https://github.com/liyasthomas/postwoman/issues/560)
- Validation for duplicate collection ignores letter case [\#547](https://github.com/liyasthomas/postwoman/issues/547)
- Build failed [\#327](https://github.com/liyasthomas/postwoman/issues/327)
- Fixed typo in translation file for Auto theme [\#556](https://github.com/liyasthomas/postwoman/pull/556) ([AndrewBastin](https://github.com/AndrewBastin))
**Closed issues:**
- don't run [\#577](https://github.com/liyasthomas/postwoman/issues/577)
- Get correct response data but occurs with error "Cannot read property 'value' of undefined" [\#575](https://github.com/liyasthomas/postwoman/issues/575)
- firebase\_app\_\_WEBPACK\_IMPORTED\_MODULE\_2\_\_\_default.a.firestore is not a function [\#558](https://github.com/liyasthomas/postwoman/issues/558)
- relative module not found during start [\#552](https://github.com/liyasthomas/postwoman/issues/552)
- Feature Request: Subfolders [\#540](https://github.com/liyasthomas/postwoman/issues/540)
- Add max-height and overflow: auto to "parameter list" textarea [\#532](https://github.com/liyasthomas/postwoman/issues/532)
- IE Support [\#386](https://github.com/liyasthomas/postwoman/issues/386)
- ⏬ Import a Postman's Collection [\#333](https://github.com/liyasthomas/postwoman/issues/333)
**Merged pull requests:**
- Fix variablesJSONString store default for GraphQL page [\#593](https://github.com/liyasthomas/postwoman/pull/593) ([dmitryyankowski](https://github.com/dmitryyankowski))
- Refactor/lint [\#589](https://github.com/liyasthomas/postwoman/pull/589) ([liyasthomas](https://github.com/liyasthomas))
- Even [\#588](https://github.com/liyasthomas/postwoman/pull/588) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump firebase from 7.9.0 to 7.9.1 [\#587](https://github.com/liyasthomas/postwoman/pull/587) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Even [\#586](https://github.com/liyasthomas/postwoman/pull/586) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump firebase from 7.8.2 to 7.9.0 [\#585](https://github.com/liyasthomas/postwoman/pull/585) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump vue-virtual-scroll-list from 1.4.5 to 1.4.6 [\#584](https://github.com/liyasthomas/postwoman/pull/584) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Adapt extension check to new extensions [\#583](https://github.com/liyasthomas/postwoman/pull/583) ([levrik](https://github.com/levrik))
- Update link to extension repo in README [\#582](https://github.com/liyasthomas/postwoman/pull/582) ([levrik](https://github.com/levrik))
- Even [\#579](https://github.com/liyasthomas/postwoman/pull/579) ([liyasthomas](https://github.com/liyasthomas))
- Refactor/lint [\#578](https://github.com/liyasthomas/postwoman/pull/578) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump vue-virtual-scroll-list from 1.4.4 to 1.4.5 [\#576](https://github.com/liyasthomas/postwoman/pull/576) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Unify Chrome and Firefox extensions [\#573](https://github.com/liyasthomas/postwoman/pull/573) ([levrik](https://github.com/levrik))
- fix: drop the toast which doesn't show up [\#572](https://github.com/liyasthomas/postwoman/pull/572) ([jamesgeorge007](https://github.com/jamesgeorge007))
- :sparkles: Native share + updated meta description [\#571](https://github.com/liyasthomas/postwoman/pull/571) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump firebase from 7.8.1 to 7.8.2 [\#570](https://github.com/liyasthomas/postwoman/pull/570) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps-dev\): bump cypress from 4.0.1 to 4.0.2 [\#569](https://github.com/liyasthomas/postwoman/pull/569) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Added create collection and save request syncs [\#568](https://github.com/liyasthomas/postwoman/pull/568) ([JacobAnavisca](https://github.com/JacobAnavisca))
- Moved common headers to a separate file [\#566](https://github.com/liyasthomas/postwoman/pull/566) ([AndrewBastin](https://github.com/AndrewBastin))
- chore\(deps-dev\): bump cypress from 4.0.0 to 4.0.1 [\#565](https://github.com/liyasthomas/postwoman/pull/565) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump yargs-parser from 16.1.0 to 17.0.0 [\#564](https://github.com/liyasthomas/postwoman/pull/564) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps-dev\): bump cypress from 3.8.3 to 4.0.0 [\#562](https://github.com/liyasthomas/postwoman/pull/562) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump firebase from 7.8.0 to 7.8.1 [\#561](https://github.com/liyasthomas/postwoman/pull/561) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore: use typeof as an operator and make use of localizable strings [\#559](https://github.com/liyasthomas/postwoman/pull/559) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Support for Formdata [\#555](https://github.com/liyasthomas/postwoman/pull/555) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump @nuxtjs/pwa from 3.0.0-beta.19 to 3.0.0-beta.20 [\#554](https://github.com/liyasthomas/postwoman/pull/554) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump @nuxtjs/axios from 5.9.4 to 5.9.5 [\#553](https://github.com/liyasthomas/postwoman/pull/553) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- fix\(chore\): Take letter casing into account while checking for duplicate collection [\#548](https://github.com/liyasthomas/postwoman/pull/548) ([jamesgeorge007](https://github.com/jamesgeorge007))
- update e2e tests [\#546](https://github.com/liyasthomas/postwoman/pull/546) ([yubathom](https://github.com/yubathom))
- chore\(deps\): bump @nuxtjs/axios from 5.9.3 to 5.9.4 [\#545](https://github.com/liyasthomas/postwoman/pull/545) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Refactor [\#543](https://github.com/liyasthomas/postwoman/pull/543) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump firebase from 7.7.0 to 7.8.0 [\#542](https://github.com/liyasthomas/postwoman/pull/542) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump graphql from 14.5.8 to 14.6.0 [\#541](https://github.com/liyasthomas/postwoman/pull/541) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- i18n [\#538](https://github.com/liyasthomas/postwoman/pull/538) ([liyasthomas](https://github.com/liyasthomas))
- Modification of French translations [\#537](https://github.com/liyasthomas/postwoman/pull/537) ([thomasbnt](https://github.com/thomasbnt))
- Even [\#535](https://github.com/liyasthomas/postwoman/pull/535) ([liyasthomas](https://github.com/liyasthomas))
- Updating spanish translation [\#529](https://github.com/liyasthomas/postwoman/pull/529) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump nuxt-i18n from 6.4.1 to 6.5.0 [\#522](https://github.com/liyasthomas/postwoman/pull/522) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
## [v1.8.0](https://github.com/liyasthomas/postwoman/tree/v1.8.0) (2020-01-28)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/v1.5.0...v1.8.0)
**Implemented enhancements:**
- Sync collection with a cloud storage \(e.g: Google drive\) [\#507](https://github.com/liyasthomas/postwoman/issues/507)
- Application contains many hard-coded strings that aren't translatable [\#488](https://github.com/liyasthomas/postwoman/issues/488)
- ULR parsing and var auto creation [\#469](https://github.com/liyasthomas/postwoman/issues/469)
- What about additional loaders: + Pug, TypeScript, SASS, material-vue ? [\#467](https://github.com/liyasthomas/postwoman/issues/467)
- \[suggestion\] - Tests tab [\#465](https://github.com/liyasthomas/postwoman/issues/465)
- cookie not found support [\#443](https://github.com/liyasthomas/postwoman/issues/443)
- Feature Request: Consumer Driven Contract Testing [\#420](https://github.com/liyasthomas/postwoman/issues/420)
- Feature Request: Support OAuth2/OIDC [\#337](https://github.com/liyasthomas/postwoman/issues/337)
- Add DB cache [\#26](https://github.com/liyasthomas/postwoman/issues/26)
- Update asset/\*. js to asset/\*. ts. [\#517](https://github.com/liyasthomas/postwoman/pull/517) ([Sn005](https://github.com/Sn005))
- Auth [\#513](https://github.com/liyasthomas/postwoman/pull/513) ([liyasthomas](https://github.com/liyasthomas))
- Support for Google Chrome Extension [\#512](https://github.com/liyasthomas/postwoman/pull/512) ([AndrewBastin](https://github.com/AndrewBastin))
- GraphQL query validation based on schema [\#508](https://github.com/liyasthomas/postwoman/pull/508) ([AndrewBastin](https://github.com/AndrewBastin))
- Syntax Error marking in GraphQL query editor [\#505](https://github.com/liyasthomas/postwoman/pull/505) ([AndrewBastin](https://github.com/AndrewBastin))
- Refactoring proxy handling to be done in strategies [\#500](https://github.com/liyasthomas/postwoman/pull/500) ([AndrewBastin](https://github.com/AndrewBastin))
- Firefox Extension compatibility [\#494](https://github.com/liyasthomas/postwoman/pull/494) ([AndrewBastin](https://github.com/AndrewBastin))
- Network Strategies [\#487](https://github.com/liyasthomas/postwoman/pull/487) ([AndrewBastin](https://github.com/AndrewBastin))
- chore\(oauth\): Added method signatures as per JSDoc conventions [\#486](https://github.com/liyasthomas/postwoman/pull/486) ([jamesgeorge007](https://github.com/jamesgeorge007))
- GraphQL Type Highlight and Links [\#479](https://github.com/liyasthomas/postwoman/pull/479) ([AndrewBastin](https://github.com/AndrewBastin))
**Fixed bugs:**
- Warn the user if name field was left blank while creating a new collection [\#515](https://github.com/liyasthomas/postwoman/issues/515)
- Multiple collections with the same name shouldn't exist [\#509](https://github.com/liyasthomas/postwoman/issues/509)
- GraphQL String variables are null [\#497](https://github.com/liyasthomas/postwoman/issues/497)
- Post request body is empty [\#473](https://github.com/liyasthomas/postwoman/issues/473)
**Closed issues:**
- Allow importing Postman collections [\#524](https://github.com/liyasthomas/postwoman/issues/524)
- Request descriptions [\#511](https://github.com/liyasthomas/postwoman/issues/511)
- Ability to run all requests of a folder/collection [\#498](https://github.com/liyasthomas/postwoman/issues/498)
- Change import/export collection on requests page icon [\#495](https://github.com/liyasthomas/postwoman/issues/495)
- import cURL error [\#477](https://github.com/liyasthomas/postwoman/issues/477)
- move to postwoman org [\#475](https://github.com/liyasthomas/postwoman/issues/475)
- Create standalone vue components of the request builder. [\#474](https://github.com/liyasthomas/postwoman/issues/474)
- Enable running proxy as a backend for Request Capture [\#325](https://github.com/liyasthomas/postwoman/issues/325)
- Label doesn't change when switching between collection requests [\#291](https://github.com/liyasthomas/postwoman/issues/291)
**Merged pull requests:**
- Enhancements [\#531](https://github.com/liyasthomas/postwoman/pull/531) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Merge pull request \#530 from liyasthomas/feature/post-request-tests [\#530](https://github.com/liyasthomas/postwoman/pull/530) ([liyasthomas](https://github.com/liyasthomas))
- even merge [\#528](https://github.com/liyasthomas/postwoman/pull/528) ([liyasthomas](https://github.com/liyasthomas))
- Refactor [\#523](https://github.com/liyasthomas/postwoman/pull/523) ([liyasthomas](https://github.com/liyasthomas))
- chore\(deps\): bump v-tooltip from 2.0.2 to 2.0.3 [\#521](https://github.com/liyasthomas/postwoman/pull/521) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps-dev\): bump cypress from 3.8.2 to 3.8.3 [\#520](https://github.com/liyasthomas/postwoman/pull/520) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Feature/post request tests [\#518](https://github.com/liyasthomas/postwoman/pull/518) ([nickpalenchar](https://github.com/nickpalenchar))
- Validations for edit and create collections activity [\#516](https://github.com/liyasthomas/postwoman/pull/516) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Validate duplicate collections [\#510](https://github.com/liyasthomas/postwoman/pull/510) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Lint and refactor [\#506](https://github.com/liyasthomas/postwoman/pull/506) ([liyasthomas](https://github.com/liyasthomas))
- Merge pull request \#504 from liyasthomas/dependabot/npm\_and\_yarn/node-sass-4.13.1 [\#504](https://github.com/liyasthomas/postwoman/pull/504) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump @nuxtjs/axios from 5.9.2 to 5.9.3 [\#503](https://github.com/liyasthomas/postwoman/pull/503) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps-dev\): bump sass-loader from 8.0.1 to 8.0.2 [\#502](https://github.com/liyasthomas/postwoman/pull/502) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- chore\(deps\): bump ace-builds from 1.4.7 to 1.4.8 [\#501](https://github.com/liyasthomas/postwoman/pull/501) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- 💚 Fixed \#497 [\#499](https://github.com/liyasthomas/postwoman/pull/499) ([pushrbx](https://github.com/pushrbx))
- Feat/firefox strategy [\#496](https://github.com/liyasthomas/postwoman/pull/496) ([liyasthomas](https://github.com/liyasthomas))
- i18n Japanese: Added new translations [\#492](https://github.com/liyasthomas/postwoman/pull/492) ([reefqi037](https://github.com/reefqi037))
- Merge pull request \#491 from liyasthomas/i18n [\#491](https://github.com/liyasthomas/postwoman/pull/491) ([liyasthomas](https://github.com/liyasthomas))
- Replaced hard-coded strings with localizable strings [\#490](https://github.com/liyasthomas/postwoman/pull/490) ([liyasthomas](https://github.com/liyasthomas))
- chore: Minor tweaks [\#485](https://github.com/liyasthomas/postwoman/pull/485) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Porting \(most of\) code to typescript [\#484](https://github.com/liyasthomas/postwoman/pull/484) ([AndrewBastin](https://github.com/AndrewBastin))
- ⬆️ Bump cypress from 3.8.1 to 3.8.2 [\#483](https://github.com/liyasthomas/postwoman/pull/483) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump sass-loader from 8.0.0 to 8.0.1 [\#482](https://github.com/liyasthomas/postwoman/pull/482) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump @nuxtjs/google-analytics from 2.2.2 to 2.2.3 [\#481](https://github.com/liyasthomas/postwoman/pull/481) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- OAuth 2.0/OIDC Access Token Retrieval Support [\#476](https://github.com/liyasthomas/postwoman/pull/476) ([reefqi037](https://github.com/reefqi037))
## [v1.5.0](https://github.com/liyasthomas/postwoman/tree/v1.5.0) (2020-01-04)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/v1.0.0...v1.5.0)
**Implemented enhancements:**
- Can WSDL be implemented, similar to SoapUI? [\#461](https://github.com/liyasthomas/postwoman/issues/461)
- Raw Request Body should be supported to format the JSON string [\#446](https://github.com/liyasthomas/postwoman/issues/446)
- Ability to send Binary data using Postwoman [\#415](https://github.com/liyasthomas/postwoman/issues/415)
- Custom request method [\#398](https://github.com/liyasthomas/postwoman/issues/398)
- \[request\]: CLI possibilities [\#363](https://github.com/liyasthomas/postwoman/issues/363)
- Feature request: OAuth header support/integration [\#358](https://github.com/liyasthomas/postwoman/issues/358)
- i18n support [\#348](https://github.com/liyasthomas/postwoman/issues/348)
- Separate layers in dockerfile to improve image build [\#339](https://github.com/liyasthomas/postwoman/issues/339)
- Internal server environment usage requirements [\#336](https://github.com/liyasthomas/postwoman/issues/336)
- Server Sent Events [\#329](https://github.com/liyasthomas/postwoman/issues/329)
- Generate API documentation [\#326](https://github.com/liyasthomas/postwoman/issues/326)
- Auth info on WebSocket connections [\#321](https://github.com/liyasthomas/postwoman/issues/321)
- Set response panel to fullscreen [\#320](https://github.com/liyasthomas/postwoman/issues/320)
- Graphql support [\#312](https://github.com/liyasthomas/postwoman/issues/312)
- Keyboard shortcuts [\#302](https://github.com/liyasthomas/postwoman/issues/302)
- File/binary request body support [\#298](https://github.com/liyasthomas/postwoman/issues/298)
- It's possible to tab into read only and non-form elements [\#287](https://github.com/liyasthomas/postwoman/issues/287)
- Change cursor to disabled on disabled inputs [\#286](https://github.com/liyasthomas/postwoman/issues/286)
- Hover Styling on Inputs [\#285](https://github.com/liyasthomas/postwoman/issues/285)
- Focus Styles on Buttons [\#284](https://github.com/liyasthomas/postwoman/issues/284)
- Missing Focus on Inputs [\#279](https://github.com/liyasthomas/postwoman/issues/279)
- Download the request result into a file. [\#278](https://github.com/liyasthomas/postwoman/issues/278)
- Improve UI Contrast [\#277](https://github.com/liyasthomas/postwoman/issues/277)
- \[UI\] \[UX\] Allow app to take width of browser [\#236](https://github.com/liyasthomas/postwoman/issues/236)
- Extend syntax highlighting with ACE for pre-request script textarea [\#235](https://github.com/liyasthomas/postwoman/issues/235)
- Store pre-request scripts in history [\#233](https://github.com/liyasthomas/postwoman/issues/233)
- Store the time spent on fetching a response [\#225](https://github.com/liyasthomas/postwoman/issues/225)
- Cache view [\#188](https://github.com/liyasthomas/postwoman/issues/188)
- chore: stick to Vue.js best practices [\#432](https://github.com/liyasthomas/postwoman/pull/432) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Header key autocompletion [\#421](https://github.com/liyasthomas/postwoman/pull/421) ([AndrewBastin](https://github.com/AndrewBastin))
- Custom methods support [\#400](https://github.com/liyasthomas/postwoman/pull/400) ([liyasthomas](https://github.com/liyasthomas))
- Two Way Data Binding \(v-model\) to Ace Editor component [\#379](https://github.com/liyasthomas/postwoman/pull/379) ([AndrewBastin](https://github.com/AndrewBastin))
- Basic i18n support [\#351](https://github.com/liyasthomas/postwoman/pull/351) ([liyasthomas](https://github.com/liyasthomas))
- Undo header/param/body param deletion [\#350](https://github.com/liyasthomas/postwoman/pull/350) ([AndrewBastin](https://github.com/AndrewBastin))
- refactor: minor improvements [\#343](https://github.com/liyasthomas/postwoman/pull/343) ([jamesgeorge007](https://github.com/jamesgeorge007))
**Fixed bugs:**
- WebSocket page freezes when pasting long URL [\#471](https://github.com/liyasthomas/postwoman/issues/471)
- API Documentation won't be generated [\#456](https://github.com/liyasthomas/postwoman/issues/456)
- Sharing Requests via link is not working [\#435](https://github.com/liyasthomas/postwoman/issues/435)
- URL input text is so stutters [\#412](https://github.com/liyasthomas/postwoman/issues/412)
- Save to collections after deleting all the collections causes an error page [\#390](https://github.com/liyasthomas/postwoman/issues/390)
- Bearer token doesnt work with CORS when only authorization header is allowed [\#353](https://github.com/liyasthomas/postwoman/issues/353)
- Make the UI more compact [\#314](https://github.com/liyasthomas/postwoman/issues/314)
- Allow reserved characters on websocket URI [\#289](https://github.com/liyasthomas/postwoman/issues/289)
- Unable to edit or delete row in history table [\#281](https://github.com/liyasthomas/postwoman/issues/281)
- Allow url request with `/` at eol [\#275](https://github.com/liyasthomas/postwoman/issues/275)
- \[request\] localhost support [\#274](https://github.com/liyasthomas/postwoman/issues/274)
- Code generation for Fetch request type of some methods \(POST, PUT, PATCH\) won't be shown [\#268](https://github.com/liyasthomas/postwoman/issues/268)
- \[BUG\] \[UI\] \[Mobile\] Get results not scrollable. [\#266](https://github.com/liyasthomas/postwoman/issues/266)
- POSTing large raw JSON packets [\#265](https://github.com/liyasthomas/postwoman/issues/265)
**Closed issues:**
- Module not found: Error: Can't resolve '../.postwoman/version.json' [\#457](https://github.com/liyasthomas/postwoman/issues/457)
- \* ../.postwoman/version.json in ./node\_modules/babel-loader/lib??ref--2-0!./node\_modules/vue-loader/lib??vue-loader-options!./layouts/default.vue?vue&type=script&lang=js& friendly-errors 11:12:37 [\#448](https://github.com/liyasthomas/postwoman/issues/448)
- npm run dev module was not found: ../.postwoman/version.json [\#442](https://github.com/liyasthomas/postwoman/issues/442)
- graphql and websocket work, but http and https do not [\#441](https://github.com/liyasthomas/postwoman/issues/441)
- Can I test localhost? [\#433](https://github.com/liyasthomas/postwoman/issues/433)
- No 'Access-Control-Allow-Origin' [\#426](https://github.com/liyasthomas/postwoman/issues/426)
- When uninstall the PWA the "install PWA" link in postwoman.io isn't appear anymore [\#419](https://github.com/liyasthomas/postwoman/issues/419)
- Toggling options will reset the UI to English [\#417](https://github.com/liyasthomas/postwoman/issues/417)
- Oh my dear god why don't we just wrap it in electron [\#413](https://github.com/liyasthomas/postwoman/issues/413)
- UI improvement suggestion for request method drop down [\#409](https://github.com/liyasthomas/postwoman/issues/409)
- Can I share a request with my team? [\#408](https://github.com/liyasthomas/postwoman/issues/408)
- Does it not support the post method? [\#403](https://github.com/liyasthomas/postwoman/issues/403)
- Post can't send request [\#401](https://github.com/liyasthomas/postwoman/issues/401)
- \[Bug\] fix header icons overlap [\#399](https://github.com/liyasthomas/postwoman/issues/399)
- Improve translate for pt-BR \(i18n\) [\#395](https://github.com/liyasthomas/postwoman/issues/395)
- Raw input disabled is not working properly [\#394](https://github.com/liyasthomas/postwoman/issues/394)
- Input area is not clearly to identify for users because the dark mode [\#393](https://github.com/liyasthomas/postwoman/issues/393)
- \[UX\] Setting to make sidebar buttons small [\#389](https://github.com/liyasthomas/postwoman/issues/389)
- \[UX\] Improve responsive breaking points [\#388](https://github.com/liyasthomas/postwoman/issues/388)
- \[UX\] Hide history/collections [\#387](https://github.com/liyasthomas/postwoman/issues/387)
- Clearing shortcut overrides browser default [\#374](https://github.com/liyasthomas/postwoman/issues/374)
- Proxy server default configuration [\#373](https://github.com/liyasthomas/postwoman/issues/373)
- Intent to translate [\#367](https://github.com/liyasthomas/postwoman/issues/367)
- Static builds on releases [\#352](https://github.com/liyasthomas/postwoman/issues/352)
- fix:SSE onclose handle [\#349](https://github.com/liyasthomas/postwoman/issues/349)
- \[Request\] Use responses for next request? [\#324](https://github.com/liyasthomas/postwoman/issues/324)
- Make response body area expandable [\#294](https://github.com/liyasthomas/postwoman/issues/294)
- Mobile can't see console for request errors [\#283](https://github.com/liyasthomas/postwoman/issues/283)
- Duplicated query string in generated code [\#272](https://github.com/liyasthomas/postwoman/issues/272)
- Query parameters are duplicated [\#271](https://github.com/liyasthomas/postwoman/issues/271)
- Generated code is incorrect [\#269](https://github.com/liyasthomas/postwoman/issues/269)
- Lacking documentation and wiki [\#232](https://github.com/liyasthomas/postwoman/issues/232)
- I can't send POST method [\#210](https://github.com/liyasthomas/postwoman/issues/210)
- Handling request failures when build number is obtained from GitHub [\#122](https://github.com/liyasthomas/postwoman/issues/122)
**Merged pull requests:**
- ⬆️ Bump @nuxtjs/axios from 5.9.0 to 5.9.2 [\#472](https://github.com/liyasthomas/postwoman/pull/472) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Added variables to graphql page. [\#464](https://github.com/liyasthomas/postwoman/pull/464) ([pushrbx](https://github.com/pushrbx))
- i18n [\#463](https://github.com/liyasthomas/postwoman/pull/463) ([liyasthomas](https://github.com/liyasthomas))
- ⬆️ Bump cypress from 3.8.0 to 3.8.1 [\#460](https://github.com/liyasthomas/postwoman/pull/460) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- i18n\(de-DE\): improve some translations [\#459](https://github.com/liyasthomas/postwoman/pull/459) ([gabschne](https://github.com/gabschne))
- bn-BD i18n [\#455](https://github.com/liyasthomas/postwoman/pull/455) ([hmtanbir](https://github.com/hmtanbir))
- API documentation page [\#451](https://github.com/liyasthomas/postwoman/pull/451) ([liyasthomas](https://github.com/liyasthomas))
- ⬆️ Bump @nuxtjs/axios from 5.8.0 to 5.9.0 [\#450](https://github.com/liyasthomas/postwoman/pull/450) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump nuxt from 2.10.2 to 2.11.0 [\#449](https://github.com/liyasthomas/postwoman/pull/449) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Various UI tweaks [\#439](https://github.com/liyasthomas/postwoman/pull/439) ([liyasthomas](https://github.com/liyasthomas))
- i18n [\#438](https://github.com/liyasthomas/postwoman/pull/438) ([liyasthomas](https://github.com/liyasthomas))
- Burmese translation added [\#437](https://github.com/liyasthomas/postwoman/pull/437) ([ZattWine](https://github.com/ZattWine))
- Styled select input [\#431](https://github.com/liyasthomas/postwoman/pull/431) ([liyasthomas](https://github.com/liyasthomas))
- Bumped dependencies and Improved UI contrast [\#430](https://github.com/liyasthomas/postwoman/pull/430) ([liyasthomas](https://github.com/liyasthomas))
- ⬆️ Bump cypress from 3.7.0 to 3.8.0 [\#429](https://github.com/liyasthomas/postwoman/pull/429) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- I18n [\#428](https://github.com/liyasthomas/postwoman/pull/428) ([liyasthomas](https://github.com/liyasthomas))
- I18n Japanese translation added [\#427](https://github.com/liyasthomas/postwoman/pull/427) ([reefqi037](https://github.com/reefqi037))
- Even [\#424](https://github.com/liyasthomas/postwoman/pull/424) ([liyasthomas](https://github.com/liyasthomas))
- I18n [\#423](https://github.com/liyasthomas/postwoman/pull/423) ([liyasthomas](https://github.com/liyasthomas))
- I18n German translation added [\#422](https://github.com/liyasthomas/postwoman/pull/422) ([NJannasch](https://github.com/NJannasch))
- Update id-ID.js [\#416](https://github.com/liyasthomas/postwoman/pull/416) ([williamsp](https://github.com/williamsp))
- Improving translation for id-ID [\#414](https://github.com/liyasthomas/postwoman/pull/414) ([williamsp](https://github.com/williamsp))
- Fixing bug on request saving [\#410](https://github.com/liyasthomas/postwoman/pull/410) ([adevr](https://github.com/adevr))
- ⬆️ Bump @nuxtjs/google-analytics from 2.2.1 to 2.2.2 [\#407](https://github.com/liyasthomas/postwoman/pull/407) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump vue-virtual-scroll-list from 1.4.3 to 1.4.4 [\#406](https://github.com/liyasthomas/postwoman/pull/406) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump nuxt-i18n from 6.4.0 to 6.4.1 [\#405](https://github.com/liyasthomas/postwoman/pull/405) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- I18n [\#404](https://github.com/liyasthomas/postwoman/pull/404) ([yubathom](https://github.com/yubathom))
- App UI [\#391](https://github.com/liyasthomas/postwoman/pull/391) ([liyasthomas](https://github.com/liyasthomas))
- i18n [\#383](https://github.com/liyasthomas/postwoman/pull/383) ([liyasthomas](https://github.com/liyasthomas))
- Added Turkish Language Support [\#382](https://github.com/liyasthomas/postwoman/pull/382) ([AliAnilKocak](https://github.com/AliAnilKocak))
- Translated new words to Farsi lang [\#380](https://github.com/liyasthomas/postwoman/pull/380) ([hosseinnedaee](https://github.com/hosseinnedaee))
- fix: twitter summary card image url [\#378](https://github.com/liyasthomas/postwoman/pull/378) ([peterpeterparker](https://github.com/peterpeterparker))
- Added nav shortcuts to GraphQL query and response, updated GraphQL shortcut icons [\#377](https://github.com/liyasthomas/postwoman/pull/377) ([AndrewBastin](https://github.com/AndrewBastin))
- Bump cypress from 3.6.1 to 3.7.0 [\#376](https://github.com/liyasthomas/postwoman/pull/376) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump vuex-persist from 2.1.1 to 2.2.0 [\#375](https://github.com/liyasthomas/postwoman/pull/375) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- I18n [\#372](https://github.com/liyasthomas/postwoman/pull/372) ([EdikWang](https://github.com/EdikWang))
- Use GraphQL logo for GraphQL tab [\#371](https://github.com/liyasthomas/postwoman/pull/371) ([NBTX](https://github.com/NBTX))
- Update i18n keywords for Bahasa Indonesia [\#369](https://github.com/liyasthomas/postwoman/pull/369) ([wahwahid](https://github.com/wahwahid))
- Intent to translate to Spanish on I18n [\#368](https://github.com/liyasthomas/postwoman/pull/368) ([adlpaf](https://github.com/adlpaf))
- I18n [\#366](https://github.com/liyasthomas/postwoman/pull/366) ([liyasthomas](https://github.com/liyasthomas))
- Add translations for FR/EN catalogues [\#364](https://github.com/liyasthomas/postwoman/pull/364) ([LaurentBrieu](https://github.com/LaurentBrieu))
- Added Bahasa Indonesia language support [\#362](https://github.com/liyasthomas/postwoman/pull/362) ([wahwahid](https://github.com/wahwahid))
- i18n [\#361](https://github.com/liyasthomas/postwoman/pull/361) ([liyasthomas](https://github.com/liyasthomas))
- Add Simplified Chinese language [\#360](https://github.com/liyasthomas/postwoman/pull/360) ([EdikWang](https://github.com/EdikWang))
- Added Brazilian Portuguese language support [\#359](https://github.com/liyasthomas/postwoman/pull/359) ([tetri](https://github.com/tetri))
- Added Farsi language support [\#357](https://github.com/liyasthomas/postwoman/pull/357) ([hosseinnedaee](https://github.com/hosseinnedaee))
- Adding french language basic [\#355](https://github.com/liyasthomas/postwoman/pull/355) ([thomasbnt](https://github.com/thomasbnt))
- Add Proxy URL option [\#345](https://github.com/liyasthomas/postwoman/pull/345) ([NBTX](https://github.com/NBTX))
## [v1.0.0](https://github.com/liyasthomas/postwoman/tree/v1.0.0) (2019-11-04)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/v0.1.0...v1.0.0)
**Implemented enhancements:**
- Chain requests. Execute a bunch of requests one by one and produce results [\#196](https://github.com/liyasthomas/postwoman/issues/196)
- Allow User to Choose Whether to Include Authentication in Permalink [\#178](https://github.com/liyasthomas/postwoman/issues/178)
- Allow HTTP \(not HTTPS\) on postwoman.io [\#175](https://github.com/liyasthomas/postwoman/issues/175)
- Docker-compose in development [\#168](https://github.com/liyasthomas/postwoman/issues/168)
- Add Docker [\#164](https://github.com/liyasthomas/postwoman/issues/164)
- Clear Input [\#155](https://github.com/liyasthomas/postwoman/issues/155)
- introduce some script language to parse the response and pass environment variable as request parameter [\#139](https://github.com/liyasthomas/postwoman/issues/139)
- Add links to the footer version and commit sha [\#134](https://github.com/liyasthomas/postwoman/issues/134)
- Please add a label for each request. It will be helpful. [\#133](https://github.com/liyasthomas/postwoman/issues/133)
- Use 'icon buttons' instead of 'text buttons' [\#130](https://github.com/liyasthomas/postwoman/issues/130)
- Change .editorconfig [\#115](https://github.com/liyasthomas/postwoman/issues/115)
- \[UX\] Provide Focus State for Buttons, etc. [\#112](https://github.com/liyasthomas/postwoman/issues/112)
- Add linter semistandard [\#98](https://github.com/liyasthomas/postwoman/issues/98)
- Show "Send" button all over the page or enable hotkeys [\#94](https://github.com/liyasthomas/postwoman/issues/94)
- Import request from cURL [\#93](https://github.com/liyasthomas/postwoman/issues/93)
- Search on History [\#92](https://github.com/liyasthomas/postwoman/issues/92)
- Add support for "application/hal+json" Content-Type [\#88](https://github.com/liyasthomas/postwoman/issues/88)
- The query string is built incorrectly when the path contains a parameter [\#87](https://github.com/liyasthomas/postwoman/issues/87)
- Option to Copy request as Fetch or XHR Or CURL [\#76](https://github.com/liyasthomas/postwoman/issues/76)
- Add Tests [\#65](https://github.com/liyasthomas/postwoman/issues/65)
- Request Headers [\#57](https://github.com/liyasthomas/postwoman/issues/57)
- Colored response codes based on status code [\#46](https://github.com/liyasthomas/postwoman/issues/46)
- Improve SEO [\#45](https://github.com/liyasthomas/postwoman/issues/45)
- Add html preview to response section [\#41](https://github.com/liyasthomas/postwoman/issues/41)
- websocket support [\#40](https://github.com/liyasthomas/postwoman/issues/40)
- Raw request body for POST requests and Authorization key/value in Header [\#36](https://github.com/liyasthomas/postwoman/issues/36)
- Code highlight on response body [\#33](https://github.com/liyasthomas/postwoman/issues/33)
- Template selector [\#32](https://github.com/liyasthomas/postwoman/issues/32)
- Vue template [\#31](https://github.com/liyasthomas/postwoman/issues/31)
- Add copy response to clipboard button [\#30](https://github.com/liyasthomas/postwoman/issues/30)
- Ability to store/share/create collections [\#29](https://github.com/liyasthomas/postwoman/issues/29)
- Send request on Enter Key press [\#17](https://github.com/liyasthomas/postwoman/issues/17)
- Readable [\#5](https://github.com/liyasthomas/postwoman/issues/5)
- Serialize a request into JSON? [\#4](https://github.com/liyasthomas/postwoman/issues/4)
- Add brand new logo to the project [\#244](https://github.com/liyasthomas/postwoman/pull/244) ([caneco](https://github.com/caneco))
- Feature/pre request script [\#231](https://github.com/liyasthomas/postwoman/pull/231) ([nickpalenchar](https://github.com/nickpalenchar))
- Add the ApolloTV proxy server [\#217](https://github.com/liyasthomas/postwoman/pull/217) ([NBTX](https://github.com/NBTX))
- bug: keeping information on page change [\#211](https://github.com/liyasthomas/postwoman/pull/211) ([breno-pereira](https://github.com/breno-pereira))
- Work in Progress: feature/allow-collections-importing [\#209](https://github.com/liyasthomas/postwoman/pull/209) ([vlad0337187](https://github.com/vlad0337187))
- Feature/log errors [\#207](https://github.com/liyasthomas/postwoman/pull/207) ([nickpalenchar](https://github.com/nickpalenchar))
- Use returned value from toggle component on change event [\#205](https://github.com/liyasthomas/postwoman/pull/205) ([hosseinnedaee](https://github.com/hosseinnedaee))
- Fix CORS and mixed content issue [\#199](https://github.com/liyasthomas/postwoman/pull/199) ([hosseinnedaee](https://github.com/hosseinnedaee))
- Added Tooltips [\#197](https://github.com/liyasthomas/postwoman/pull/197) ([AndrewBastin](https://github.com/AndrewBastin))
- Added auto theme [\#185](https://github.com/liyasthomas/postwoman/pull/185) ([AndrewBastin](https://github.com/AndrewBastin))
- Add Request name label for every requests [\#184](https://github.com/liyasthomas/postwoman/pull/184) ([sharath2106](https://github.com/sharath2106))
- Collections [\#176](https://github.com/liyasthomas/postwoman/pull/176) ([TheHollidayInn](https://github.com/TheHollidayInn))
**Fixed bugs:**
- Bearer Token value still left even after being cleared [\#212](https://github.com/liyasthomas/postwoman/issues/212)
- All changes in input fields lost when you switch to another page [\#203](https://github.com/liyasthomas/postwoman/issues/203)
- POST request json bodies aren't sent [\#180](https://github.com/liyasthomas/postwoman/issues/180)
- Headers turn into 0 : \[Object object\] [\#166](https://github.com/liyasthomas/postwoman/issues/166)
- Send Again Button Constantly Flickering [\#157](https://github.com/liyasthomas/postwoman/issues/157)
- There are cross-domain problems [\#128](https://github.com/liyasthomas/postwoman/issues/128)
- Raw requests are not being sent [\#124](https://github.com/liyasthomas/postwoman/issues/124)
- Request Body Is Not Sent [\#113](https://github.com/liyasthomas/postwoman/issues/113)
- default menu option - 'Http' is not highlighted when launched from installed pwa app \(UI bug\) [\#100](https://github.com/liyasthomas/postwoman/issues/100)
- App is broken with old history in localStorage [\#74](https://github.com/liyasthomas/postwoman/issues/74)
- Last added history entry is removed automatically after refresh [\#66](https://github.com/liyasthomas/postwoman/issues/66)
- Cannot use localhost as base url [\#56](https://github.com/liyasthomas/postwoman/issues/56)
- \[CORS\] No 'Access-Control-Allow-Origin' header is present on the requested resource [\#2](https://github.com/liyasthomas/postwoman/issues/2)
**Closed issues:**
- Section labels don't display properly in Firefox [\#237](https://github.com/liyasthomas/postwoman/issues/237)
- Unsupported URLs \[BUG\]? [\#229](https://github.com/liyasthomas/postwoman/issues/229)
- Credentials are still being included in Permalink even when "Include in URL" is turned off [\#227](https://github.com/liyasthomas/postwoman/issues/227)
- Display sendRequest runtime errors in the console [\#206](https://github.com/liyasthomas/postwoman/issues/206)
- Missing "Landing/start page" [\#162](https://github.com/liyasthomas/postwoman/issues/162)
- Response with content-type "application/hal+json" shows as \[Object object\] [\#158](https://github.com/liyasthomas/postwoman/issues/158)
- A place to discuss [\#149](https://github.com/liyasthomas/postwoman/issues/149)
- Inconsistent version name [\#141](https://github.com/liyasthomas/postwoman/issues/141)
- Autoresize the textarea [\#102](https://github.com/liyasthomas/postwoman/issues/102)
- Content-Type revamping [\#99](https://github.com/liyasthomas/postwoman/issues/99)
- Add version number in footer [\#97](https://github.com/liyasthomas/postwoman/issues/97)
- The history doesn't show a date with the timestamp. [\#81](https://github.com/liyasthomas/postwoman/issues/81)
- Not working on Brave Browser anymore [\#71](https://github.com/liyasthomas/postwoman/issues/71)
- Why da fuq is your name plastered all over the README? [\#70](https://github.com/liyasthomas/postwoman/issues/70)
- Comparison with Postman is missing [\#69](https://github.com/liyasthomas/postwoman/issues/69)
- HTTP request with different library [\#61](https://github.com/liyasthomas/postwoman/issues/61)
- Editorconfig file [\#60](https://github.com/liyasthomas/postwoman/issues/60)
- 500 this.isValidURL is not a function [\#58](https://github.com/liyasthomas/postwoman/issues/58)
- Styling with Tailwindcss [\#38](https://github.com/liyasthomas/postwoman/issues/38)
- Not Working in IE 11 [\#37](https://github.com/liyasthomas/postwoman/issues/37)
- PWA not installable [\#19](https://github.com/liyasthomas/postwoman/issues/19)
- Simple Misspelling [\#8](https://github.com/liyasthomas/postwoman/issues/8)
**Merged pull requests:**
- docs: add liyasthomas as a contributor [\#264](https://github.com/liyasthomas/postwoman/pull/264) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add jamesgeorge007 as a contributor [\#263](https://github.com/liyasthomas/postwoman/pull/263) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add NBTX as a contributor [\#262](https://github.com/liyasthomas/postwoman/pull/262) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- Fix .all-contributorsrc badge template. [\#260](https://github.com/liyasthomas/postwoman/pull/260) ([NBTX](https://github.com/NBTX))
- docs: add hosseinnedaee as a contributor [\#259](https://github.com/liyasthomas/postwoman/pull/259) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add nityanandagohain as a contributor [\#257](https://github.com/liyasthomas/postwoman/pull/257) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add JacobAnavisca as a contributor [\#256](https://github.com/liyasthomas/postwoman/pull/256) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add izerozlu as a contributor [\#255](https://github.com/liyasthomas/postwoman/pull/255) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add vlad0337187 as a contributor [\#254](https://github.com/liyasthomas/postwoman/pull/254) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add AndrewBastin as a contributor [\#253](https://github.com/liyasthomas/postwoman/pull/253) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add terranblake as a contributor [\#252](https://github.com/liyasthomas/postwoman/pull/252) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add nickpalenchar as a contributor [\#251](https://github.com/liyasthomas/postwoman/pull/251) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add yubathom as a contributor [\#250](https://github.com/liyasthomas/postwoman/pull/250) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add larouxn as a contributor [\#249](https://github.com/liyasthomas/postwoman/pull/249) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add NBTX as a contributor [\#248](https://github.com/liyasthomas/postwoman/pull/248) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- docs: add liyasthomas as a contributor [\#247](https://github.com/liyasthomas/postwoman/pull/247) ([allcontributors[bot]](https://github.com/apps/allcontributors))
- Make page changes more fluid [\#246](https://github.com/liyasthomas/postwoman/pull/246) ([NBTX](https://github.com/NBTX))
- Minor tweaks [\#245](https://github.com/liyasthomas/postwoman/pull/245) ([liyasthomas](https://github.com/liyasthomas))
- ⬆️ Bump @nuxtjs/google-tag-manager from 2.3.0 to 2.3.1 [\#243](https://github.com/liyasthomas/postwoman/pull/243) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump yargs-parser from 15.0.0 to 16.1.0 [\#242](https://github.com/liyasthomas/postwoman/pull/242) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump @nuxtjs/toast from 3.2.1 to 3.3.0 [\#241](https://github.com/liyasthomas/postwoman/pull/241) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump highlight.js from 9.15.10 to 9.16.2 [\#240](https://github.com/liyasthomas/postwoman/pull/240) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump cypress from 3.5.0 to 3.6.0 [\#239](https://github.com/liyasthomas/postwoman/pull/239) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Fix legend labels in Firefox, fix colored labels slider [\#238](https://github.com/liyasthomas/postwoman/pull/238) ([NBTX](https://github.com/NBTX))
- Documentation Cleanup [\#230](https://github.com/liyasthomas/postwoman/pull/230) ([amitdash291](https://github.com/amitdash291))
- Fix \#227 Exclude credentials from permalink [\#228](https://github.com/liyasthomas/postwoman/pull/228) ([reefqi037](https://github.com/reefqi037))
- ⬆️ Bump cypress from 3.4.1 to 3.5.0 [\#224](https://github.com/liyasthomas/postwoman/pull/224) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump @nuxtjs/axios from 5.6.0 to 5.8.0 [\#223](https://github.com/liyasthomas/postwoman/pull/223) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump node-sass from 4.12.0 to 4.13.0 [\#222](https://github.com/liyasthomas/postwoman/pull/222) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump nuxt from 2.10.1 to 2.10.2 [\#221](https://github.com/liyasthomas/postwoman/pull/221) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump @nuxtjs/google-analytics from 2.2.0 to 2.2.1 [\#220](https://github.com/liyasthomas/postwoman/pull/220) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump vuex-persist from 2.1.0 to 2.1.1 [\#219](https://github.com/liyasthomas/postwoman/pull/219) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Fixed frame colors toggle [\#216](https://github.com/liyasthomas/postwoman/pull/216) ([mateusppereira](https://github.com/mateusppereira))
- Re-order sections and add toggle for including authentication in URL [\#215](https://github.com/liyasthomas/postwoman/pull/215) ([NBTX](https://github.com/NBTX))
- chore: minor code refactor [\#214](https://github.com/liyasthomas/postwoman/pull/214) ([jamesgeorge007](https://github.com/jamesgeorge007))
- Fix \#212 Clear bearer token value [\#213](https://github.com/liyasthomas/postwoman/pull/213) ([reefqi037](https://github.com/reefqi037))
- fix: don't display 'Collection is empty' label if collection has any … [\#208](https://github.com/liyasthomas/postwoman/pull/208) ([vlad0337187](https://github.com/vlad0337187))
- Fix proxy URL [\#201](https://github.com/liyasthomas/postwoman/pull/201) ([NBTX](https://github.com/NBTX))
- Fix CORS and Mixed-Content issue & Bug Fixes [\#200](https://github.com/liyasthomas/postwoman/pull/200) ([NBTX](https://github.com/NBTX))
- ⬆️ Bump start-server-and-test from 1.10.5 to 1.10.6 [\#198](https://github.com/liyasthomas/postwoman/pull/198) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump start-server-and-test from 1.10.3 to 1.10.5 [\#194](https://github.com/liyasthomas/postwoman/pull/194) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump @nuxtjs/google-tag-manager from 2.2.1 to 2.3.0 [\#193](https://github.com/liyasthomas/postwoman/pull/193) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump nuxt from 2.10.0 to 2.10.1 [\#192](https://github.com/liyasthomas/postwoman/pull/192) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- ⬆️ Bump yargs-parser from 14.0.0 to 15.0.0 [\#191](https://github.com/liyasthomas/postwoman/pull/191) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add quotation marks for generated code [\#187](https://github.com/liyasthomas/postwoman/pull/187) ([johnhenry](https://github.com/johnhenry))
- updated threshold and rootMargin for IntersectionObserver [\#182](https://github.com/liyasthomas/postwoman/pull/182) ([edisonaugusthy](https://github.com/edisonaugusthy))
- Add basic e2e tests [\#181](https://github.com/liyasthomas/postwoman/pull/181) ([yubathom](https://github.com/yubathom))
- ⬆️ Bump nuxt from 2.9.2 to 2.10.0 [\#179](https://github.com/liyasthomas/postwoman/pull/179) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- 🐛 Fixed sitemap configuration [\#177](https://github.com/liyasthomas/postwoman/pull/177) ([NicoPennec](https://github.com/NicoPennec))
- Code Refactoring [\#173](https://github.com/liyasthomas/postwoman/pull/173) ([edisonaugusthy](https://github.com/edisonaugusthy))
- Added Black Theme [\#172](https://github.com/liyasthomas/postwoman/pull/172) ([AndrewBastin](https://github.com/AndrewBastin))
## [v0.1.0](https://github.com/liyasthomas/postwoman/tree/v0.1.0) (2019-08-22)
[Full Changelog](https://github.com/liyasthomas/postwoman/compare/91c08a5e6305cc95a0df46a33fdd0013bf7339b4...v0.1.0)
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*

View File

@@ -34,12 +34,12 @@ Examples of unacceptable behavior by participants include:
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
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 to this Code of Conduct, or to ban temporarily or
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.

View File

@@ -13,8 +13,8 @@ Please note we have a code of conduct, please follow it in all your interactions
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/).
4. You may merge the Pull Request in 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 to merge it for you.
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
@@ -52,12 +52,12 @@ advances
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
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 to this Code of Conduct, or to ban temporarily or
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.

View File

@@ -1,12 +1,19 @@
FROM node:12.10.0-buster
FROM node:12.10.0-alpine
LABEL maintainer="Liyas Thomas (liyascthomas@gmail.com)"
# Add git as the prebuild target requires it to parse version information
RUN apk add --update --no-cache \
git
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000

212
README.md
View File

@@ -3,14 +3,14 @@
<br>
<br>
<p>
API request builder - A free, fast, and beautiful alternative to Postman
<b>A free, fast and beautiful API request builder</b>
</p>
<p>
Helps you create your requests faster, saving you precious time on your development - <a href="https://postwoman.launchaco.com">Subscribe</a>
<i>Web alternative to Postman - Helps you create requests faster, saving precious time on development - <a href="https://postwoman.launchaco.com">Subscribe</a></i>
</p>
<p>
[![Travis Build Status](https://img.shields.io/travis/com/liyasthomas/postwoman?logo=Travis)](https://travis-ci.com/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all?logo=GitHub)](https://github.com/liyasthomas/postwoman/releases/latest) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io)](https://postwoman.io) [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen?style=flat)](CONTRIBUTING.md) [![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors) [![Financial Contributors on Open Collective](https://img.shields.io/opencollective/all/postwoman?logo=Open-Collective&label=financial+contributors)](https://opencollective.com/postwoman) [![Donate on PayPal](https://img.shields.io/badge/support-PayPal-blue?logo=PayPal)](https://www.paypal.me/liyascthomas) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-blueviolet?logo=Telegram)](https://t.me/postwoman_app) [![Chat on Discord](https://img.shields.io/badge/chat-Discord-violet?logo=discord)](https://discord.gg/GAMWxmR) [![Tweet](https://img.shields.io/twitter/url?url=https%3A%2F%2Fpostwoman.io%2F)](https://twitter.com/intent/tweet?url=https%3A%2F%2Fpostwoman.io&text=%F0%9F%91%BD%20Postwoman%20%E2%80%A2%20API%20request%20builder%20-%20Helps%20you%20create%20your%20requests%20faster%2C%20saving%20you%20precious%20time%20on%20your%20development&original_referer=https%3A%2F%2Ftwitter.com%2Fshare%3Ftext%3D%25F0%259F%2591%25BD%2520Postwoman%2520%25E2%2580%25A2%2520API%2520request%2520builder%2520-%2520Helps%2520you%2520create%2520your%2520requests%2520faster%2C%2520saving%2520you%2520precious%2520time%2520on%2520your%2520development%26url%3Dhttps%3A%2F%2Fpostwoman.io%26hashtags%3Dpostwoman%26via%3Dliyasthomas&via=liyasthomas&hashtags=postwoman)
[![Travis Build Status](https://img.shields.io/travis/com/liyasthomas/postwoman?logo=Travis)](https://travis-ci.com/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all?logo=GitHub)](https://github.com/liyasthomas/postwoman/releases/latest) [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io&logo=Postwoman)](https://postwoman.io) [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen)](CONTRIBUTING.md) [![Financial Contributors on Open Collective](https://img.shields.io/opencollective/all/postwoman?logo=Open-Collective&label=financial+contributors)](https://opencollective.com/postwoman) [![Donate on PayPal](https://img.shields.io/badge/support-PayPal-blue?logo=PayPal)](https://www.paypal.me/liyascthomas) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-blueviolet?logo=Telegram)](https://t.me/postwoman_app) [![Chat on Discord](https://img.shields.io/badge/chat-Discord-violet?logo=discord)](https://discord.gg/GAMWxmR) [![Tweet](https://img.shields.io/twitter/url?url=https%3A%2F%2Fpostwoman.io%2F)](https://twitter.com/intent/tweet?url=https%3A%2F%2Fpostwoman.io&text=%F0%9F%91%BD%20Postwoman%20%E2%80%A2%20API%20request%20builder%20-%20Helps%20you%20create%20your%20requests%20faster%2C%20saving%20you%20precious%20time%20on%20your%20development&original_referer=https%3A%2F%2Ftwitter.com%2Fshare%3Ftext%3D%25F0%259F%2591%25BD%2520Postwoman%2520%25E2%2580%25A2%2520API%2520request%2520builder%2520-%2520Helps%2520you%2520create%2520your%2520requests%2520faster%2C%2520saving%2520you%2520precious%2520time%2520on%2520your%2520development%26url%3Dhttps%3A%2F%2Fpostwoman.io%26hashtags%3Dpostwoman%26via%3Dliyasthomas&via=liyasthomas&hashtags=postwoman)
</p>
<p>
@@ -23,26 +23,23 @@
---
**Start here: _[Story behind Postwoman](https://dev.to/liyasthomas/i-created-postwoman-an-online-open-source-api-request-builder-41md)_**
**Read: _[Story behind Postwoman](https://dev.to/liyasthomas/i-created-postwoman-an-online-open-source-api-request-builder-41md), [Postwoman v1.0](https://dev.to/liyasthomas/postwoman-v1-0-a-free-fast-beautiful-alternative-to-postman-mn0)_**
**Chat here: _[Telegram](https://t.me/postwoman_app), [Discord](https://discord.gg/GAMWxmR)_**
**Chat: _[Telegram](https://t.me/postwoman_app), [Discord](https://discord.gg/GAMWxmR)_**
**Donate here: _[PayPal](https://www.paypal.me/liyascthomas), [Open Collective](https://opencollective.com/postwoman), [Patreon](https://www.patreon.com/liyasthomas)_**
**Donate: _[PayPal](https://www.paypal.me/liyascthomas), [Open Collective](https://opencollective.com/postwoman), [Patreon](https://www.patreon.com/liyasthomas)_**
<div align="center">
<br>
<img src="static/images/screenshot1.png" alt="Screenshot1" width="100%">
<img src="static/images/screenshot2.png" alt="Screenshot2" width="100%">
<br>
</div>
### Features ✨
❤️ **Lightweight**: Crafted with minimalistic UI design. Simple design is the best design.
❤️ **Lightweight**: Crafted with minimalistic UI design - simple design is the best design.
- Faster, lighter, cleaner, minimal & responsive
⚡️ **Fast**: Send requests and get/copy responses in real-time! Fast software is the best software.
⚡️ **Fast**: Send requests and get/copy responses in real-time - fast software is the best software.
**Methods:**
- `GET` - Retrieve information about the REST API resource
@@ -50,19 +47,20 @@
- `POST` - Create a REST API resource
- `PUT` - Update a REST API resource
- `DELETE` - Delete a REST API resource or related component
- `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` - Apply partial modifications to a REST API resource
- `<custom>` - Some APIs use custom request methods such as `LIST`. Type in your custom methods.
_History entries are synced with local session storage_
🌈 **Make it yours**: Customizable combinations for background, foreground and accent colors: because customization === freedom. [Customize now ✨](https://postwoman.io/settings).
🌈 **Make it yours**: Customizable combinations for background, foreground and accent colors: because customization is freedom. [Customize now ✨](https://postwoman.io/settings).
**Customizations:**
- Choose theme: Kinda Dark (default), Clearly White, Just Black and System theme
- Choose accent color: Green (default), Yellow, Pink, Red, Purple, Orange, Cyan and Blue
- Toggle multi-colored frames
- Toggle multi-colored headings
_Customized themes are also synced with local session storage_
_Customized themes are synced with local session storage_
🔥 **PWA**: Install as a [PWA](https://developers.google.com/web/progressive-web-apps) on your device.
@@ -70,33 +68,46 @@ _Customized themes are also synced with local session storage_
- Instant loading with [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers)
- Offline support
- Low RAM/memory and CPU usage
- [Add to Home Screen](https://developers.google.com/web/fundamentals/app-install-banners) (button in footer)
- [Desktop PWA](https://developers.google.com/web/progressive-web-apps/desktop) support (button in footer)
- Add to Home Screen
- Desktop PWA
- ([full features](https://developers.google.com/web/progressive-web-apps))
🚀 **Request**: Retrieve data from a URL without having to do a full page refresh.
🚀 **Request**: Retrieve response from endpoint instantly.
- Choose `method`
- Enter `URL`
- Enter `Path`
- Enter `URL` and `Path`
- Send
**Features:**
- Copy/share public "Share URL"
- Generate request code for JavaScript XHR, Fetch and cURL
- Generate request code for `JavaScript XHR`, `Fetch` and `cURL`
- Copy generated request code to clipboard
- Import cURL
- Import `cURL`
- Label requests
🔌 **WebSocket**: Establish full-duplex communication channels over a single TCP connection.
- Send and receive data
- Basic and Bearer Token authentication
🔐 **Authentication**: Allows to identity the end user.
📡 **Server Sent Events**: Receive a stream of updates from a server over a HTTP connection without resorting to polling.
🔮 **GraphQL**: GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.
- Set endpoint and get schemas
- Multi-column docs
- Set custom request headers
- Query schema
- Get query response
🔐 **Authentication**: Allows to identify the end user.
**Types:**
- None
- Basic authentication using username and password
- Token based authentication
- Basic
- Bearer Token
- OAuth 2.0
- OIDC Access Token/PKCE (Proof Key for Code Exchange)
📢 **Headers**: Describes the format the body of your request is being sent as.
@@ -107,30 +118,32 @@ _Customized themes are also synced with local session storage_
📃 **Request Body**: Used to send and receive data via the REST API.
**Options:**
- Set Content Type
- Set `Content Type`
- Add or remove Parameter list
- Toggle between key-value and RAW input Parameter list
👋 **Responses**: Contains the status line, headers and the message/response body.
- Copy response to clipboard
- View preview for HTML responses
_HTML responses have "Preview HTML" feature_
- Download response to as a file
- View preview of HTML responses
**History**: Request entries are synced with local session storage to reuse with a single click.
**Fields:**
- Star
- Label
- Timestamp
- Method
- Status code
- URL
- Path
- Timestamp
- Duration
- Pre-request script
_History entries can be sorted by any fields_
_Histories can deleted one-by-one or all together_
_Histories can be deleted one-by-one or all together_
📁 **Collections**: Keep your API requests organized with collections and folders. Reuse them with a single click.
@@ -138,8 +151,6 @@ _Histories can deleted one-by-one or all together_
- Create infinite collections, folders and requests
- Edit, delete, move, export, import and replace
_Export, import and replace collections with JSON files_
_Collections are synced with local session storage_
🌐 **Proxy**: Enable Proxy Mode from Settings to access blocked APIs.
@@ -147,33 +158,91 @@ _Collections are synced with local session storage_
**Features:**
- 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://`, `localhost`, etc.)
- Access APIs served in non-HTTPS (`http://`)
- Use custom Proxy URL
_Proxy is hosted by ApolloTV - [Privacy policy](https://apollotv.xyz/legal)_
_Official Postwoman Proxy is hosted by ApolloTV - **[Privacy policy](https://apollotv.xyz/legal)**_
📜 **Pre-Request Scripts β**: Snippets of code associated with a request that are executed before the request is sent.
**Use-cases:**
- Including the timestamp in the request headers
- Sending a random alphanumeric string in the URL parameters
_Pre-Request Scripts is an experimental feature and is in Public Beta testing_
- Include timestamp in the request headers
- Send a random alphanumeric string in the URL parameters
_Requests with Pre-Request Scripts are indicated in History entries_
📄 **API Documentation**: Create and share dynamic API documentation easily, quickly.
**Usage:**
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
⌨️ **Keyboard Shortcuts**: Optimized for efficiency.
**Shortcuts:**
- Send Request <kbd>Ctrl</kbd> + <kbd>G</kbd>
- Save to Collections <kbd>Ctrl</kbd> + <kbd>S</kbd>
- Copy Request Link <kbd>Ctrl</kbd> + <kbd>K</kbd>
- Reset Request <kbd>Ctrl</kbd> + <kbd>L</kbd>
🌎 **i18n β**: Experience the app in your own language.
1. Scroll down to the footer
2. Click "Choose Language" icon button
3. Select your language from the menu
_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/liyasthomas/postwoman/tree/i18n) only!**_
📦 **Add-ons**: Official add-ons for Postwoman.
- **[Proxy β](https://github.com/postwoman-io/postwoman-proxy)** - A simple proxy server created for Postwoman
- **[CLI β](https://github.com/postwoman-io/postwoman-cli)** - A CLI solution for Postwoman
- **Browser Extensions** - Browser extensions that simplifies access to Postwoman
[![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_16x16.png) **Firefox**](https://addons.mozilla.org/en-US/firefox/addon/postwoman) &nbsp;|&nbsp; [![Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_16x16.png) **Chrome**](https://chrome.google.com/webstore/detail/postwoman-extension-for-c/amknoiejhlmhancpahfcfcfhllgkpbld) ([GitHub](https://github.com/AndrewBastin/postwoman-extension))
>**Extensions fixes `CORS` issues.**
_Add-ons are developed and maintained under **[Official Postwoman Organization](https://github.com/postwoman-io)**._
☁️ **Auth + Sync**: Sign in and sync in real-time.
**Sign in with:**
- Google
- GitHub
**Sync:**
- History
- Collections
**Post-Request Tests β**: Write tests associated with a request that are executed after the request response.
**Use-cases:**
- Check the status code as an integer
- Filter response headers
- Parse the response data
**To find out more, please check out [Postwoman Wiki](https://github.com/liyasthomas/postwoman/wiki).**
## Demo 🚀 [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io)](https://postwoman.io)
## Demo 🚀 [![Website](https://img.shields.io/website?url=https%3A%2F%2Fpostwoman.io&logo=Postwoman)](https://postwoman.io)
[https://postwoman.io](https://postwoman.io)
[postwoman.io](https://postwoman.io)
<a href="https://www.netlify.com">
<img src="https://www.netlify.com/img/global/badges/netlify-light.svg"/>
</a>
## Usage 💡
1. Specify your request method
2. Type in your API URL
3. Add API path
4. Send request
5. Get response!
1. Specify your request `method`
2. Type in your API `URL` and `path`
3. Send request
4. Get response
You're done!
@@ -188,6 +257,12 @@ You're done!
## Developing 👷
#### Use a browser based development environment:
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/liyasthomas/postwoman)
#### Or, with 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 `postwoman`).
3. Start the development server with `npm run dev`.
@@ -240,7 +315,10 @@ See the [CHANGELOG](CHANGELOG.md) file for details.
### Lead Developers
* **[Liyas Thomas](https://github.com/liyasthomas)** - *Author*
* **[Caneco](https://twitter.com/caneco)** - *Designer*
* **[John Harker](https://github.com/NBTX)** - *Lead developer*
* **[Andrew Bastin](https://github.com/andrewbastin)** - *Lead developer*
* **[James George](https://github.com/jamesgeorge007)** - *Lead maintainer*
* **[Caneco](https://twitter.com/caneco)** - *Logo and banner designer*
### Testing and Debugging
@@ -258,11 +336,10 @@ See the [CHANGELOG](CHANGELOG.md) file for details.
<td align="center"><a href="https://nicholaslaroux.com"><img src="https://avatars0.githubusercontent.com/u/1557529?v=4" width="100px;" alt="Nicholas La Roux"/><br /><sub><b>Nicholas La Roux</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=larouxn" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/yubathom"><img src="https://avatars3.githubusercontent.com/u/4117768?v=4" width="100px;" alt="Thomas Yuba"/><br /><sub><b>Thomas Yuba</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=yubathom" title="Code">💻</a></td>
<td align="center"><a href="http://www.linkedin.com/in/nickpalenchar"><img src="https://avatars1.githubusercontent.com/u/7539781?v=4" width="100px;" alt="Nick Palenchar"/><br /><sub><b>Nick Palenchar</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=nickpalenchar" title="Code">💻</a></td>
<td align="center"><a href="https://www.lumahealth.io/"><img src="https://avatars3.githubusercontent.com/u/8795767?v=4" width="100px;" alt="Terran Blake"/><br /><sub><b>Terran Blake</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=terranblake" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/AndrewBastin"><img src="https://avatars2.githubusercontent.com/u/9131943?v=4" width="100px;" alt="Andrew Bastin"/><br /><sub><b>Andrew Bastin</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=AndrewBastin" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/vlad0337187"><img src="https://avatars1.githubusercontent.com/u/12682937?v=4" width="100px;" alt="Vladislav"/><br /><sub><b>Vladislav</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=vlad0337187" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/vlad0337187"><img src="https://avatars1.githubusercontent.com/u/12682937?v=4" width="100px;" alt="Vladislav"/><br /><sub><b>Vladislav</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=vlad0337187" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/izerozlu"><img src="https://avatars3.githubusercontent.com/u/17386157?v=4" width="100px;" alt="izerozlu"/><br /><sub><b>izerozlu</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=izerozlu" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JacobAnavisca"><img src="https://avatars2.githubusercontent.com/u/21232366?v=4" width="100px;" alt="Jacob Anavisca"/><br /><sub><b>Jacob Anavisca</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=JacobAnavisca" title="Code">💻</a></td>
<td align="center"><a href="http://nityanandagohain.github.io"><img src="https://avatars3.githubusercontent.com/u/26831659?v=4" width="100px;" alt="Nityananda Gohain"/><br /><sub><b>Nityananda Gohain</b></sub></a><br /><a href="https://github.com/liyasthomas/postwoman/commits?author=nityanandagohain" title="Code">💻</a></td>
@@ -320,13 +397,34 @@ This project is licensed under the [MIT License](https://opensource.org/licenses
## Badges
| Status | Preview | Markdown Code (copy & paste into `readme.md`) |
| ----------- | ----------- | ----------- |
| **Default** | [![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-50fa7b)](https://postwoman.io) | `[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-50fa7b)](https://postwoman.io)` |
| **Success** | [![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-success)](https://postwoman.io) | `[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-success)](https://postwoman.io)` |
| **Critical** | [![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-critical)](https://postwoman.io) | `[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-critical)](https://postwoman.io)` |
| **Custom** | [![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-blueviolet)](https://postwoman.io) | `[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-blueviolet)](https://postwoman.io)` |
| Make your own badge! | [![Postwoman](https://img.shields.io/badge/your_text-Postwoman-hex_color_code)](https://postwoman.io) | `[![Postwoman](https://img.shields.io/badge/your_text-Postwoman-hex_color_code)](https://postwoman.io)` |
<table>
<tr>
<th>Preview</th>
<th>Markdown code</th>
</tr>
<tbody>
<tr>
<td align="center" width="200px"><a href="https://postwoman.io"><br/><img src="https://img.shields.io/badge/Tested_on-Postwoman-202124?logo=Postwoman"/></a><br/><sub>Default<sub></td>
<td><code>[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-202124?logo=Postwoman)](https://postwoman.io)</code></td>
</tr>
<tr>
<td align="center" width="200px"><a href="https://postwoman.io"><br/><img src="https://img.shields.io/badge/Tested_on-Postwoman-success?logo=Postwoman"/></a><br/><sub>Success<sub></td>
<td><code>[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-success?logo=Postwoman)](https://postwoman.io)</code></td>
</tr>
<tr>
<td align="center" width="200px"><a href="https://postwoman.io"><br/><img src="https://img.shields.io/badge/Tested_on-Postwoman-critical?logo=Postwoman"/></a><br/><sub>Critical<sub></td>
<td><code>[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-critical?logo=Postwoman)](https://postwoman.io)</code></td>
</tr>
<tr>
<td align="center" width="200px"><a href="https://postwoman.io"><br/><img src="https://img.shields.io/badge/Tested_on-Postwoman-blueviolet?logo=Postwoman"/></a><br/><sub>Custom<sub></td>
<td><code>[![Postwoman](https://img.shields.io/badge/Tested_on-Postwoman-blueviolet?logo=Postwoman)](https://postwoman.io)</code></td>
</tr>
<tr>
<td align="center" width="200px"><a href="https://postwoman.io"><br/><img src="https://img.shields.io/badge/your_text-Postwoman-hex_color_code?logo=Postwoman"/></a><br/><sub>Customize<sub></td>
<td><code>[![Postwoman](https://img.shields.io/badge/your_text-Postwoman-hex_color_code?logo=Postwoman)](https://postwoman.io)</code></td>
</tr>
</tbody>
</table>
<div align="center">
<br>

View File

@@ -1,16 +1,21 @@
// @import url("https://fonts.googleapis.com/css?family=Poppins:500,700|Roboto+Mono:400&display=swap");
// @import url("https://fonts.googleapis.com/icon?family=Material+Icons&display=swap");
/* Material Design Icons */
@font-face {
font-family: "Material Icons";
font-display: swap;
font-style: normal;
font-weight: 400;
src: url(~@/assets/fonts/material-icons-v48.woff2) format("woff2");
font-display: swap;
src: url("~static/fonts/material-icons-v48.woff2") format("woff2");
}
.material-icons {
font-family: "Material Icons";
font-weight: normal;
font-style: normal;
height: 24px;
width: 24px;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
@@ -21,43 +26,45 @@
direction: ltr;
-webkit-font-feature-settings: "liga";
-webkit-font-smoothing: antialiased;
font-feature-settings: "liga";
border-radius: 50%;
}
/* Roboto Mono 400 */
@font-face {
font-family: "Roboto Mono";
font-display: swap;
font-style: normal;
font-weight: 400;
src: local("Roboto Mono"), local("RobotoMono-Regular"),
url("~@/assets/fonts/roboto-mono-v7-latin-regular.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("~@/assets/fonts/roboto-mono-v7-latin-regular.woff") format("woff");
/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* Poppins 500 */
/* poppins-500 - latin */
@font-face {
font-family: "Poppins";
font-display: swap;
font-style: normal;
font-weight: 500;
font-display: swap;
src: local("Poppins Medium"), local("Poppins-Medium"),
url("~@/assets/fonts/poppins-v9-latin-500.woff2") format("woff2"),
url("~static/fonts/poppins-v9-latin-500.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("~@/assets/fonts/poppins-v9-latin-500.woff") format("woff");
url("~static/fonts/poppins-v9-latin-500.woff") format("woff");
/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* poppins-700 - latin */
@font-face {
font-family: "Poppins";
font-display: swap;
font-style: normal;
font-weight: 700;
font-display: swap;
src: local("Poppins Bold"), local("Poppins-Bold"),
url("~@/assets/fonts/poppins-v9-latin-700.woff2") format("woff2"),
url("~static/fonts/poppins-v9-latin-700.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("~@/assets/fonts/poppins-v9-latin-700.woff") format("woff");
url("~static/fonts/poppins-v9-latin-700.woff") format("woff");
/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* roboto-mono-regular - latin */
@font-face {
font-family: "Roboto Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: local("Roboto Mono"), local("RobotoMono-Regular"),
url("~static/fonts/roboto-mono-v7-latin-regular.woff2") format("woff2"),
/* Chrome 26+, Opera 23+, Firefox 39+ */
url("~static/fonts/roboto-mono-v7-latin-regular.woff") format("woff");
/* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

View File

@@ -1,28 +1,37 @@
$responsiveWidth: 720px;
html {
scroll-behavior: smooth;
.page-enter-active,
.page-leave-active,
.layout-enter-active,
.layout-leave-active {
transition: opacity 0.2s;
}
.page-enter,
.page-leave-active,
.layout-enter,
.layout-leave-active {
opacity: 0;
}
$responsiveWidth: 768px;
::selection {
background-color: var(--ac-sel-color);
background-color: var(--ac-color);
color: var(--act-color);
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
width: 4px;
height: 4px;
background-color: var(--bg-dark-color);
}
::-webkit-scrollbar-thumb {
background-color: var(--fg-light-color);
border-radius: 8px;
border: 2px solid var(--bg-color);
}
::-webkit-scrollbar-thumb:hover {
&:hover {
background-color: var(--fg-color);
}
}
::placeholder {
color: var(--fg-light-color);
@@ -35,11 +44,12 @@ html {
border: 0;
}
html,
body {
background-color: var(--bg-color);
color: var(--fg-color);
font-weight: 500;
font-size: 16px;
font-size: 14px;
font-family: "Poppins", "Roboto", "Noto", sans-serif;
line-height: 1.5;
-webkit-tap-highlight-color: transparent;
@@ -47,15 +57,12 @@ body {
user-select: none;
padding: 0;
margin: 0;
scroll-behavior: smooth;
transition: all 0.2s ease-in-out;
}
// Make theme transition smoother.
body.afterLoad {
&,
& * {
transition: background-color 0.2s ease-in-out, border 0.2s ease-in-out;
}
transition: background-color 0.2s ease-in-out;
}
body.sticky-footer footer {
@@ -66,14 +73,18 @@ a {
display: inline-flex;
color: inherit;
text-decoration: none;
font-weight: 700;
transition: all 0.2s ease-in-out;
&.link {
color: var(--ac-color);
}
}
header,
footer {
& > div {
display: flex;
padding: 16px;
padding: 16px 8px;
width: 100%;
align-items: center;
justify-content: space-between;
@@ -83,11 +94,11 @@ footer {
.wrapper {
min-height: 100vh;
display: flex;
flex-direction: column;
flex-flow: column nowrap;
}
.wrapper .content {
min-height: 100vh;
.wrapper .page {
min-height: calc(100vh - 153px);
}
.header,
@@ -117,45 +128,55 @@ footer {
.logo {
font-size: 22px;
&:hover {
color: var(--ac-color);
}
.tagline {
font-size: 18px;
}
.nav-first {
.nav-first,
.sticky-inner {
display: flex;
order: 1;
flex-flow: column;
position: sticky;
top: 0;
align-self: flex-start;
}
.nav-first {
z-index: 1;
height: 100vh;
padding: 0 8px;
background-color: var(--bg-dark-color);
transition: all 0.2s ease-in-out;
}
.main {
display: flex;
flex-flow: column;
flex: 1;
order: 2;
position: relative;
padding: 0 16px;
height: 100%;
}
.nav-second {
display: flex;
width: 10%;
order: 3;
// comment this to display
// comment below this to display
display: none;
}
nav.primary-nav {
display: flex;
flex-flow: column nowrap;
border-bottom: 1px solid var(--brd-color);
svg {
fill: var(--fg-light-color);
transition: all 0.2s ease-in-out;
}
a {
@@ -163,15 +184,16 @@ nav.primary-nav {
align-items: center;
justify-content: center;
flex-shrink: 0;
padding: 16px;
padding: 14px;
border-radius: 50%;
background-color: var(--brd-color);
background-color: var(--bg-light-color);
color: var(--fg-light-color);
margin: 8px;
transition: all 0.2s ease-in-out;
fill: var(--fg-light-color);
margin: 8px 0;
&:hover {
color: var(--fg-color);
fill: var(--fg-color);
svg {
fill: var(--fg-color);
@@ -181,6 +203,7 @@ nav.primary-nav {
&.nuxt-link-exact-active {
background-color: var(--ac-color);
color: var(--act-color);
fill: var(--act-color);
border-radius: 16px;
svg {
@@ -192,6 +215,7 @@ nav.primary-nav {
nav.secondary-nav {
display: flex;
border-top: 1px dashed var(--brd-color);
ul {
display: flex;
@@ -205,11 +229,11 @@ nav.secondary-nav {
align-items: center;
justify-content: center;
flex-shrink: 0;
padding: 16px;
padding: 14px;
border-radius: 50%;
background-color: var(--bg-dark-color);
color: var(--fg-light-color);
margin: 8px;
margin: 8px 0;
&:hover {
color: var(--fg-color);
@@ -225,51 +249,42 @@ nav.secondary-nav {
}
.footer {
flex-direction: column;
}
$responsiveWidth: 720px;
@media (max-width: $responsiveWidth) {
.columns {
flex-flow: column;
}
.nav-first {
width: 100%;
background-color: var(--bg-color);
}
nav.primary-nav {
flex-flow: row;
}
nav.secondary-nav {
display: none;
}
.main {
padding: 0 8px;
}
flex-flow: column nowrap;
}
h1,
h2,
h3 {
h3,
h4 {
display: flex;
align-items: center;
margin: 0;
font-weight: 700;
}
hr {
border-bottom: 1px dashed var(--brd-color);
}
p {
transition: all 0.2s ease-in-out;
}
.tooltip {
$bgcolor: var(--tt-color);
$fgcolor: var(--fg-color);
display: block !important;
z-index: 10000;
transition: all 0.2s ease-in-out;
.tooltip-inner {
background: black;
color: white;
background: $bgcolor;
color: $fgcolor;
border-radius: 8px;
padding: 8px 16px;
font-size: 14px;
font-size: 12px;
font-weight: 500;
box-shadow: 0 4px 24px rgba(black, 0.1);
}
.tooltip-arrow {
@@ -278,7 +293,7 @@ h3 {
border-style: solid;
position: absolute;
margin: 5px;
border-color: black;
border-color: $bgcolor;
z-index: 1;
}
@@ -343,18 +358,22 @@ h3 {
}
&.popover {
$color: #f9f9f9;
.wrapper {
min-height: auto;
}
.popover-inner {
background: $color;
color: black;
padding: 24px;
border-radius: 5px;
background: $bgcolor;
color: $fgcolor;
padding: 4px;
border-radius: 8px;
box-shadow: 0 5px 30px rgba(black, 0.1);
max-height: 256px;
overflow: auto;
}
.popover-arrow {
border-color: $color;
border-color: $bgcolor;
}
}
@@ -375,21 +394,29 @@ h3.title {
margin: 4px;
}
.info {
margin-left: 4px;
color: var(--fg-light-color);
}
.bg-color {
background-color: transparent;
}
button {
display: inline-flex;
align-items: center;
justify-content: center;
margin: 4px;
padding: 0 16px;
padding: 6px 16px;
border-radius: 20px;
background-color: var(--ac-color);
color: var(--act-color);
font-weight: 700;
font-size: 16px;
font-family: "Poppins", "Roboto", "Noto", sans-serif;
font-weight: 700;
transition: all 0.2s ease-in-out;
fill: var(--act-color);
height: 40px;
cursor: pointer;
span {
@@ -397,28 +424,73 @@ button {
margin-left: 8px;
}
&.icon {
background-color: var(--bg-color);
color: var(--fg-light-color);
fill: var(--fg-light-color);
&:not([disabled]):hover {
color: var(--fg-color);
fill: var(--fg-color);
}
}
&:not([disabled]):hover {
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
color: var(--act-color);
fill: var(--act-color);
box-shadow: inset 0 0 0 2px var(--fg-color);
}
&.icon {
background-color: transparent;
color: var(--fg-light-color);
fill: var(--fg-light-color);
border-radius: 8px;
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
color: var(--fg-color);
fill: var(--fg-color);
box-shadow: none;
}
}
&.primary {
color: var(--ac-color);
&:not([disabled]):hover,
&:not([disabled]):active,
&:not([disabled]):focus {
background-color: var(--ac-color);
color: var(--act-color);
}
}
}
@keyframes beat {
30% {
transform: scale(1.1);
}
50% {
transform: scale(0.9);
}
100% {
transform: scale(1);
}
}
.material-icons:active {
animation: beat 0.5s forwards 1;
}
fieldset {
margin: 16px 0;
border: 1px solid var(--brd-color);
border-radius: 8px;
background-color: var(--bg-color);
border-radius: 16px;
background-color: var(--bg-dark-color);
transition: all 0.2s ease-in-out;
}
fieldset:target,
section:target {
animation: highlight 2s ease;
}
@keyframes highlight {
50% {
box-shadow: 0 0 0 2px var(--ac-color);
}
}
legend {
@@ -428,6 +500,7 @@ legend {
color: var(--fg-color);
font-weight: 700;
cursor: pointer;
transition: all 0.2s ease-in-out;
* {
vertical-align: middle;
@@ -474,31 +547,52 @@ fieldset.yellow legend {
color: #f1fa8c;
}
input[type="file"],
input[type="radio"],
.tab,
.hide-on-large-screen,
#installPWA,
.hidden {
display: none;
}
.method,
kbd,
select,
input,
option,
textarea,
pre {
pre,
code {
display: inline-flex;
margin: 4px;
padding: 8px;
border-radius: 8px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
font-size: 16px;
font-family: 'Roboto Mono', monospace;
font-family: "Roboto Mono", monospace;
font-weight: 400;
line-height: 1;
transition: all 0.2s ease-in-out;
user-select: text;
width: calc(100% - 8px);
min-height: 40px;
resize: vertical;
text-overflow: ellipsis;
&:not([readonly]):hover {
background-color: var(--bg-dark-color);
&:not([readonly]):not(.ace_editor):hover,
&:not([readonly]):not(.ace_editor):active,
&:not([readonly]):not(.ace_editor):focus {
box-shadow: inset 0 0 0 2px var(--fg-light-color);
}
}
.method {
cursor: pointer;
&:hover,
&:active,
&:focus {
box-shadow: inset 0 0 0 2px var(--fg-light-color);
}
}
@@ -506,22 +600,54 @@ pre {
display: grid;
}
code {
height: 336px;
border-radius: 8px;
pre.ace_editor {
font-family: "Roboto Mono", monospace;
font-weight: 400;
z-index: 0;
}
.hljs,
.hljs-subst {
background-color: var(--bg-dark-color) !important;
color: var(--fg-color) !important;
font-family: 'Roboto Mono', monospace;
kbd,
code,
pre {
width: auto;
}
.select-wrapper {
position: relative;
input {
text-transform: uppercase;
}
.trigger {
width: 100%;
}
&:after {
display: inline-block;
position: absolute;
pointer-events: none;
content: "\e313";
font-family: "Material Icons";
top: 14px;
right: 14px;
}
}
select {
height: 37px;
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
&::-ms-expand {
display: none;
}
}
select,
input,
option {
height: 40px;
background-color: var(--bg-color);
}
input[type="checkbox"] {
@@ -554,23 +680,24 @@ input[type="checkbox"] {
}
}
.error,
.disabled,
.error:not(input),
.disabled:not(input),
[disabled] {
background-color: var(--err-color);
color: var(--fg-light-color);
fill: var(--fg-light-color);
cursor: default;
cursor: not-allowed;
&.icon {
color: var(--bg-color);
fill: var(--bg-color);
color: var(--err-color);
fill: var(--err-color);
}
}
label {
padding: 4px;
color: var(--fg-light-color);
transition: all 0.2s ease-in-out;
}
ul,
@@ -579,48 +706,43 @@ ol {
margin: 4px 0 4px;
padding: 0;
list-style-type: none;
ul,
ol {
margin: 0;
}
}
ul li,
ol li {
display: inline-flex;
flex-direction: column;
flex-flow: column nowrap;
flex-grow: 1;
justify-content: center;
}
.flex-wrap {
display: flex;
align-items: center;
justify-content: space-between;
}
flex-grow: 1;
flex-direction: row;
.show-on-small-screen {
display: flex;
}
@media (max-width: $responsiveWidth) {
ul,
ol {
flex-direction: column;
}
ul li,
ol li {
display: flex;
}
.hide-on-small-screen {
display: none;
}
.show-on-small-screen {
* {
display: inline-flex;
flex-flow: row wrap;
align-items: center;
justify-content: center;
}
}
#installPWA {
display: none;
.show-on-small-screen {
display: flex;
}
.show-on-large-screen {
display: inline-flex;
flex: 1;
}
.info-response {
@@ -647,23 +769,6 @@ ol li {
background-color: var(--err-color);
}
.virtual-list::-webkit-scrollbar {
width: 0;
}
fieldset#history {
.method-list-item {
position: relative;
span {
position: absolute;
top: 12px;
right: 12px;
font-family: 'Roboto Mono', monospace;
}
}
}
.align-left {
text-align: left;
}
@@ -676,6 +781,11 @@ fieldset#history {
text-align: right;
}
.mono {
font-family: "Roboto Mono", monospace;
font-weight: 400;
}
#response-details-wrapper {
position: relative;
overflow: hidden;
@@ -684,6 +794,7 @@ fieldset#history {
textarea {
margin: 0;
width: 100%;
line-height: 1;
}
.covers-response {
@@ -699,67 +810,165 @@ fieldset#history {
}
#send {
#hidden-message {
display: none;
}
&.show {
display: flex;
position: fixed;
top: 12px;
right: 12px;
z-index: 1;
#hidden-message {
display: block;
margin-left: 4px;
}
z-index: 2;
}
}
section {
display: flex;
flex-wrap: wrap;
border-radius: 16px;
}
div.tab {
.tab {
width: 100%;
order: 1;
}
input[type="radio"],
div.tab {
display: none;
}
input[type="radio"] + label {
padding: 8px 16px;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: all 0.2s ease-in-out;
&:hover {
&:hover,
&:active,
&:focus {
border-color: var(--brd-color);
}
}
input[type="radio"]:checked + label {
border-color: var(--fg-color);
color: var(--fg-color);
}
input[type="radio"]:checked + label + div.tab {
input[type="radio"]:checked + label + .tab {
display: block;
}
.toasted-container .toasted {
justify-content: start !important;
justify-content: flex-start !important;
}
.toasted.info {
background-color: var(--ac-color) !important;
color: var(--act-color) !important;
font-weight: 700 !important;
}
.toasted.bubble .action {
color: inherit !important;
}
.toasted .action {
margin-left: auto !important;
}
.page-columns {
display: flex;
flex: 1;
flex-flow: column;
}
.inner-left {
display: flex;
order: 1;
}
.inner-right {
display: flex;
width: 30%;
order: 2;
margin-left: 16px;
}
@media (max-width: $responsiveWidth) {
.content,
.columns {
flex-flow: column;
}
.nav-first {
position: fixed;
top: auto;
bottom: 0;
height: auto;
padding: 0;
width: 100%;
background-color: var(--bg-color);
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.45);
}
nav.primary-nav {
flex-flow: row nowrap;
overflow: auto;
justify-content: space-between;
background-color: var(--bg-dark-color);
a {
background-color: transparent;
margin: 8px;
flex: 1;
&.nuxt-link-exact-active {
background-color: transparent;
color: var(--ac-color);
fill: var(--ac-color);
svg {
fill: var(--ac-color);
}
}
}
}
nav.secondary-nav {
display: none;
}
.main {
padding: 0 8px 68px;
}
ul,
ol {
flex-flow: column nowrap;
}
ul li,
ol li {
display: flex;
}
.hide-on-small-screen {
display: none;
}
.hide-on-large-screen,
.show-on-small-screen {
display: inline-flex;
}
.sticky-inner {
position: relative;
width: 100%;
}
.inner-left {
order: 0;
}
.inner-right {
margin-left: 0;
}
.toasted-container {
margin-bottom: 68px;
}
}

View File

@@ -8,91 +8,100 @@
// Dark is the default theme variant.
@mixin darkTheme {
// Dark Background color
--bg-dark-color: rgb(41, 42, 45);
// Background color
--bg-color: rgb(37, 38, 40);
// Auto-complete color
--atc-color: rgb(49, 49, 55);
--bg-color: rgba(32, 33, 36, 1);
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.02);
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.1);
// Text color
--fg-color: rgb(247, 248, 248);
--fg-color: rgba(255, 255, 255, 0.9);
// Light Text color
--fg-light-color: rgb(150, 155, 160);
--fg-light-color: rgba(255, 255, 255, 0.5);
// Border color
--brd-color: rgb(48, 47, 55);
--brd-color: rgba(255, 255, 255, 0.05);
// Error color
--err-color: rgb(41, 42, 45);
--err-color: rgba(255, 255, 255, 0.05);
// Acent color
--ac-color: #50fa7b;
--ac-sel-color: rgb(80, 250, 123, 0.8);
--ac-color: rgba(80, 250, 123, 1);
// Active text color
--act-color: rgb(37, 38, 40);
--act-color: rgba(32, 33, 36, 1);
// Auto-complete color
--atc-color: rgba(32, 33, 36, 1);
// Tooltip color
--tt-color: rgba(53, 53, 53, 1);
}
@mixin lightTheme {
// Background color
--bg-color: rgba(255, 255, 255, 1);
// Light Background color
--bg-light-color: rgba(0, 0, 0, 0.02);
// Dark Background color
--bg-dark-color: rgba(0, 0, 0, 0.02);
// Text color
--fg-color: rgba(0, 0, 0, 0.9);
// Light Text color
--fg-light-color: rgba(0, 0, 0, 0.6);
// Border color
--brd-color: rgba(0, 0, 0, 0.1);
// Error color
--err-color: rgba(0, 0, 0, 0.1);
// Acent color
--ac-color: rgba(80, 250, 123, 1);
// Active text color
--act-color: rgba(255, 255, 255, 1);
// Auto-complete color
--atc-color: rgba(255, 255, 255, 1);
// Tooltip color
--tt-color: rgba(220, 220, 220, 1);
}
@mixin blackTheme {
// Background color
--bg-color: rgba(0, 0, 0, 1);
// Light Background color
--bg-light-color: rgba(255, 255, 255, 0.02);
// Dark Background color
--bg-dark-color: rgba(255, 255, 255, 0.02);
// Text color
--fg-color: rgba(255, 255, 255, 0.9);
// Light Text color
--fg-light-color: rgba(255, 255, 255, 0.5);
// Border color
--brd-color: rgba(255, 255, 255, 0.05);
// Error color
--err-color: rgba(255, 255, 255, 0.05);
// Acent color
--ac-color: rgba(80, 250, 123, 1);
// Active text color
--act-color: rgba(0, 0, 0, 1);
// Auto-complete color
--atc-color: rgba(0, 0, 0, 1);
// Tooltip color
--tt-color: rgba(18, 18, 18, 1);
}
:root {
@include darkTheme;
}
:root.light {
@include lightTheme;
}
:root.black {
@include blackTheme;
}
@media (prefers-color-scheme: dark) {
:root.auto {
@include darkTheme;
}
}
@mixin lightTheme {
// Dark Background color
--bg-dark-color: #f6f6f6;
// Background color
--bg-color: #ffffff;
// Auto-complete color
--atc-color: #ebebeb;
// Text color
--fg-color: #525252;
// Light Text color
--fg-light-color: rgb(150, 155, 160);
// Border color
--brd-color: #eeeeed;
// Error color
--err-color: #f6f6f6;
// Acent color
--ac-color: #57b5f9;
--ac-sel-color: #57b5f9;
// Active text color
--act-color: #ffffff;
}
:root.light {
@include lightTheme;
}
@media (prefers-color-scheme: light) {
:root.auto {
@include lightTheme;
}
}
@mixin blackTheme {
// Dark Background color
--bg-dark-color: rgb(8, 8, 8);
// Background color
--bg-color: #000000;
// Auto-complete color
--atc-color: rgb(18, 18, 18);
// Text color
--fg-color: rgb(250, 250, 250);
// Light Text color
--fg-light-color: rgb(100, 100, 100);
// Border color
--brd-color: rgb(16, 16, 16);
// Error color
--err-color: rgb(8, 8, 8);
// Acent color
--ac-color: #50fa7b;
--ac-sel-color: rgb(80, 250, 123, 0.8);
// Active text color
--act-color: #000000;
}
:root.black {
@include blackTheme;
}

View File

@@ -7,23 +7,23 @@ import * as querystring from "querystring";
* output this: 'msg1=value1&msg2=value2'
* @param dataArguments
*/
function joinDataArguments(dataArguments) {
const joinDataArguments = dataArguments => {
let data = "";
dataArguments.forEach(function (argument, i) {
dataArguments.forEach((argument, i) => {
if (i === 0) {
data += argument;
} else {
data += "&" + argument;
data += `&${argument}`;
}
});
return data;
}
};
function parseCurlCommand(curlCommand) {
const parseCurlCommand = curlCommand => {
let newlineFound = /\r|\n/.exec(curlCommand);
if (newlineFound) {
// remove newlines
curlCommand = curlCommand.replace(/\\\r|\\\n/g, "");
curlCommand = curlCommand.replace(/\r|\n/g, "");
}
// yargs parses -XPOST as separate arguments. just prescreen for it.
curlCommand = curlCommand.replace(/ -XPOST/, " -X POST");
@@ -47,7 +47,7 @@ function parseCurlCommand(curlCommand) {
}
let headers;
let parseHeaders = function (headerFieldName) {
const parseHeaders = headerFieldName => {
if (parsedArguments[headerFieldName]) {
if (!headers) {
headers = {};
@@ -55,7 +55,7 @@ function parseCurlCommand(curlCommand) {
if (!Array.isArray(parsedArguments[headerFieldName])) {
parsedArguments[headerFieldName] = [parsedArguments[headerFieldName]];
}
parsedArguments[headerFieldName].forEach(function (header) {
parsedArguments[headerFieldName].forEach(header => {
if (header.includes("Cookie")) {
// stupid javascript tricks: closure
cookieString = header;
@@ -95,17 +95,15 @@ function parseCurlCommand(curlCommand) {
if (!Array.isArray(parsedArguments.F)) {
parsedArguments.F = [parsedArguments.F];
}
parsedArguments.F.forEach(function (multipartArgument) {
parsedArguments.F.forEach(multipartArgument => {
// input looks like key=value. value could be json or a file path prepended with an @
const [key, value] = multipartArgument.split("=", 2);
multipartUploads[key] = value;
});
}
if (cookieString) {
let cookieParseOptions = {
decode: function (s) {
return s;
}
const cookieParseOptions = {
decode: s => s
};
// separate out cookie headers into separate data structure
// note: cookie is case insensitive
@@ -174,8 +172,8 @@ function parseCurlCommand(curlCommand) {
});
urlObject.search = null; // Clean out the search/query portion.
let request = {
url: url,
const request = {
url,
urlWithoutQuery: URL.format(urlObject)
};
if (compressed) {
@@ -223,6 +221,6 @@ function parseCurlCommand(curlCommand) {
request.insecure = true;
}
return request;
}
};
export default parseCurlCommand;

238
assets/js/oauth.js Normal file
View File

@@ -0,0 +1,238 @@
const redirectUri = `${window.location.origin}/`;
// GENERAL HELPER FUNCTIONS
/**
* Makes a POST request and parse the response as JSON
*
* @param {String} url - The resource
* @param {Object} params - Configuration options
* @returns {Object}
*/
const sendPostRequest = async (url, params) => {
const body = Object.keys(params)
.map(key => `${key}=${params[key]}`)
.join("&");
const options = {
method: "post",
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body
};
try {
const response = await fetch(url, options);
const data = await response.json();
return data;
} catch (err) {
console.error("Request failed", err);
throw err;
}
};
/**
* Parse a query string into an object
*
* @param {String} searchQuery - The search query params
* @returns {Object}
*/
const parseQueryString = searchQuery => {
if (searchQuery === "") {
return {};
}
const segments = searchQuery.split("&").map(s => s.split("="));
const queryString = segments.reduce(
(obj, el) => ({ ...obj, [el[0]]: el[1] }),
{}
);
return queryString;
};
/**
* Get OAuth configuration from OpenID Discovery endpoint
*
* @returns {Object}
*/
const getTokenConfiguration = async endpoint => {
const options = {
method: "GET",
headers: {
"Content-type": "application/json"
}
};
try {
const response = await fetch(endpoint, options);
const config = await response.json();
return config;
} catch (err) {
console.error("Request failed", err);
throw err;
}
};
// PKCE HELPER FUNCTIONS
/**
* Generates a secure random string using the browser crypto functions
*
* @returns {Object}
*/
const generateRandomString = () => {
const array = new Uint32Array(28);
window.crypto.getRandomValues(array);
return Array.from(array, dec => `0${dec.toString(16)}`.substr(-2)).join("");
};
/**
* Calculate the SHA256 hash of the input text
*
* @returns {Promise<ArrayBuffer>}
*/
const sha256 = plain => {
const encoder = new TextEncoder();
const data = encoder.encode(plain);
return window.crypto.subtle.digest("SHA-256", data);
};
/**
* Encodes the input string into Base64 format
*
* @param {String} str - The string to be converted
* @returns {Promise<ArrayBuffer>}
*/
const base64urlencode = (
str // Converts the ArrayBuffer to string using Uint8 array to convert to what btoa accepts.
) =>
// btoa accepts chars only within ascii 0-255 and base64 encodes them.
// Then convert the base64 encoded to base64url encoded
// (replace + with -, replace / with _, trim trailing =)
btoa(String.fromCharCode.apply(null, new Uint8Array(str)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
/**
* Return the base64-urlencoded sha256 hash for the PKCE challenge
*
* @param {String} v - The randomly generated string
* @returns {String}
*/
const pkceChallengeFromVerifier = async v => {
const hashed = await sha256(v);
return base64urlencode(hashed);
};
// OAUTH REQUEST
/**
* Initiates PKCE Auth Code flow when requested
*
* @param {Object} - The necessary params
* @returns {Void}
*/
const tokenRequest = async ({
oidcDiscoveryUrl,
grantType,
authUrl,
accessTokenUrl,
clientId,
scope
}) => {
// Check oauth configuration
if (oidcDiscoveryUrl !== "") {
const {
authorization_endpoint,
token_endpoint
} = await getTokenConfiguration(oidcDiscoveryUrl);
authUrl = authorization_endpoint;
accessTokenUrl = token_endpoint;
}
// Store oauth information
localStorage.setItem("token_endpoint", accessTokenUrl);
localStorage.setItem("client_id", clientId);
// Create and store a random state value
const state = generateRandomString();
localStorage.setItem("pkce_state", state);
// Create and store a new PKCE code_verifier (the plaintext random secret)
const code_verifier = generateRandomString();
localStorage.setItem("pkce_code_verifier", code_verifier);
// Hash and base64-urlencode the secret to use as the challenge
const code_challenge = await pkceChallengeFromVerifier(code_verifier);
// Build the authorization URL
const buildUrl = () =>
`${authUrl + `?response_type=${grantType}`}&client_id=${encodeURIComponent(
clientId
)}&state=${encodeURIComponent(state)}&scope=${encodeURIComponent(
scope
)}&redirect_uri=${encodeURIComponent(
redirectUri
)}&code_challenge=${encodeURIComponent(
code_challenge
)}&code_challenge_method=S256`;
// Redirect to the authorization server
window.location = buildUrl();
};
// OAUTH REDIRECT HANDLING
/**
* Handle the redirect back from the authorization server and
* get an access token from the token endpoint
*
* @returns {Object}
*/
const oauthRedirect = async () => {
let tokenResponse = "";
let q = parseQueryString(window.location.search.substring(1));
// Check if the server returned an error string
if (q.error) {
alert(`Error returned from authorization server: ${q.error}`);
}
// If the server returned an authorization code, attempt to exchange it for an access token
if (q.code) {
// Verify state matches what we set at the beginning
if (localStorage.getItem("pkce_state") != q.state) {
alert("Invalid state");
} else {
try {
// Exchange the authorization code for an access token
tokenResponse = await sendPostRequest(
localStorage.getItem("token_endpoint"),
{
grant_type: "authorization_code",
code: q.code,
client_id: localStorage.getItem("client_id"),
redirect_uri: redirectUri,
code_verifier: localStorage.getItem("pkce_code_verifier")
}
);
} catch (err) {
console.log(`${error.error}\n\n${error.error_description}`);
}
}
// Clean these up since we don't need them anymore
localStorage.removeItem("pkce_state");
localStorage.removeItem("pkce_code_verifier");
localStorage.removeItem("token_endpoint");
localStorage.removeItem("client_id");
return tokenResponse;
}
return tokenResponse;
};
export { tokenRequest, oauthRedirect };

View File

@@ -2,36 +2,39 @@ export default () => {
//*** Determine whether or not the PWA has been installed. ***//
// Step 1: Check local storage
let pwaInstalled = localStorage.getItem('pwaInstalled') === 'yes';
let pwaInstalled = localStorage.getItem("pwaInstalled") === "yes";
// Step 2: Check if the display-mode is standalone. (Only permitted for PWAs.)
if (!pwaInstalled && window.matchMedia('(display-mode: standalone)').matches) {
localStorage.setItem('pwaInstalled', 'yes');
if (
!pwaInstalled &&
window.matchMedia("(display-mode: standalone)").matches
) {
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
}
// Step 3: Check if the navigator is in standalone mode. (Again, only permitted for PWAs.)
if (!pwaInstalled && window.navigator.standalone === true) {
localStorage.setItem('pwaInstalled', 'yes');
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
}
//*** If the PWA has not been installed, show the install PWA prompt.. ***//
let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (event) => {
window.addEventListener("beforeinstallprompt", event => {
deferredPrompt = event;
// Show the install button if the prompt appeared.
if (!pwaInstalled) {
document.querySelector('#installPWA').style.display = 'inline-flex';
document.querySelector("#installPWA").style.display = "inline-flex";
}
});
// When the app is installed, remove install prompts.
window.addEventListener('appinstalled', (event) => {
localStorage.setItem('pwaInstalled', 'yes');
window.addEventListener("appinstalled", event => {
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
document.getElementById('installPWA').style.display = 'none';
document.getElementById("installPWA").style.display = "none";
});
// When the app is uninstalled, add the prompts back
@@ -40,13 +43,14 @@ export default () => {
deferredPrompt.prompt();
let outcome = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
console.log('Postwoman was installed successfully.')
if (outcome === "accepted") {
console.log("Postwoman was installed successfully.");
} else {
console.log('Postwoman could not be installed. (Installation rejected by user.)')
console.log(
"Postwoman could not be installed. (Installation rejected by user.)"
);
}
deferredPrompt = null;
}
};
};

View File

@@ -1,8 +1,6 @@
const axios = require("axios");
const fs = require("fs");
const {
spawnSync
} = require("child_process");
const { spawnSync } = require("child_process");
const runCommand = (command, args) =>
spawnSync(command, args)
.stdout.toString()
@@ -21,18 +19,24 @@ try {
let version = {};
// Get the current version name as the tag from Git.
version.name = process.env.TRAVIS_TAG || runCommand("git", ["tag"]);
version.name =
process.env.TRAVIS_TAG ||
runCommand("git", ["tag --sort=committerdate | tail -1"]);
// FALLBACK: If version.name was unset, let's grab it from GitHub.
if (!version.name) {
version.name = (await axios
version.name = (
await axios
.get("https://api.github.com/repos/liyasthomas/postwoman/releases")
// If we can't get it from GitHub, we'll resort to getting it from package.json
.catch(ex => ({
data: [{
data: [
{
tag_name: require("./package.json").version
}]
}))).data[0]["tag_name"];
}
]
}))
).data[0]["tag_name"];
}
// Get the current version hash as the short hash from Git.
@@ -43,12 +47,13 @@ try {
runCommand("git", ["branch"])
.split("* ")[1]
.split(" ")[0] + (IS_DEV_MODE ? " - DEV MODE" : "");
if (["", "master"].includes(version.variant))
if (["", "master"].includes(version.variant)) {
delete version.variant;
}
// Write version data into a file
fs.writeFileSync(
PW_BUILD_DATA_DIR + "/version.json",
`${PW_BUILD_DATA_DIR}/version.json`,
JSON.stringify(version)
);
})();

91
components/ace-editor.vue Normal file
View File

@@ -0,0 +1,91 @@
<template>
<pre ref="editor"></pre>
</template>
<script>
const DEFAULT_THEME = "twilight";
import ace from "ace-builds";
import "ace-builds/webpack-resolver";
export default {
props: {
value: {
type: String,
default: ""
},
theme: {
type: String,
required: false
},
lang: {
type: String,
default: "json"
},
options: {
type: Object,
default: {}
}
},
data() {
return {
editor: null,
cacheValue: ""
};
},
watch: {
value(value) {
if (value !== this.cacheValue) {
this.editor.session.setValue(value, 1);
this.cacheValue = value;
}
},
theme() {
this.editor.setTheme("ace/theme/" + this.defineTheme());
},
lang(value) {
this.editor.getSession().setMode("ace/mode/" + value);
},
options(value) {
this.editor.setOptions(value);
}
},
mounted() {
const editor = ace.edit(this.$refs.editor, {
theme: `ace/theme/${this.defineTheme()}`,
mode: `ace/mode/${this.lang}`,
...this.options
});
if (this.value) editor.setValue(this.value, 1);
this.editor = editor;
this.cacheValue = this.value;
editor.on("change", () => {
const content = editor.getValue();
this.$emit("input", content);
this.cacheValue = content;
});
},
methods: {
defineTheme() {
if (this.theme) {
return this.theme;
}
return (
this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
);
}
},
beforeDestroy() {
this.editor.destroy();
this.editor.container.remove();
}
};
</script>

View File

@@ -3,7 +3,7 @@
<input
type="text"
:placeholder="placeholder"
v-model="value"
v-model="text"
@input="updateSuggestions"
@keyup="updateSuggestions"
@click="updateSuggestions"
@@ -23,12 +23,14 @@
@click.prevent="forceSuggestion(suggestion)"
:class="{ active: currentSuggestionIndex === index }"
:key="index"
>{{ suggestion }}</li>
>
{{ suggestion }}
</li>
</ul>
</div>
</template>
<style lang="scss" scoped>
<style scoped lang="scss">
.autocomplete-wrapper {
position: relative;
@@ -45,20 +47,21 @@
margin: 0 4px;
left: 0;
padding: 0;
border-radius: 0 0 4px 4px;
border-radius: 0 0 8px 8px;
z-index: 9999;
transition: transform 200ms ease-out;
transition: transform 0.2s ease-out;
box-shadow: 0 5px 30px rgba(black, 0.1);
li {
width: 100%;
display: block;
padding: 8px 16px;
font-size: 18px;
font-size: 16px;
font-family: "Roboto Mono", monospace;
white-space: pre-wrap;
font-weight: 400;
&:last-child {
border-radius: 0 0 4px 4px;
border-radius: 0 0 8px 8px;
}
&:hover,
@@ -89,25 +92,31 @@ export default {
placeholder: {
type: String,
default: "Start typing...",
default: "",
required: false
},
source: {
type: Array,
required: true
},
value: {
type: String,
default: "",
required: false
}
},
watch: {
value() {
this.$emit("input", this.value);
text() {
this.$emit("input", this.text);
}
},
data() {
return {
value: "application/json",
text: this.value,
selectionStart: 0,
suggestionsOffsetLeft: 0,
currentSuggestionIndex: -1,
@@ -133,10 +142,10 @@ export default {
},
forceSuggestion(text) {
let input = this.value.substring(0, this.selectionStart);
this.value = input + text;
let input = this.text.substring(0, this.selectionStart);
this.text = input + text;
this.selectionStart = this.value.length;
this.selectionStart = this.text.length;
this.suggestionsVisible = true;
this.currentSuggestionIndex = -1;
},
@@ -165,8 +174,8 @@ export default {
this.currentSuggestionIndex >= 0 ? this.currentSuggestionIndex : 0
];
if (activeSuggestion) {
let input = this.value.substring(0, this.selectionStart);
this.value = input + activeSuggestion;
let input = this.text.substring(0, this.selectionStart);
this.text = input + activeSuggestion;
}
break;
@@ -183,7 +192,7 @@ export default {
* @returns {default.props.source|{type, required}}
*/
suggestions() {
let input = this.value.substring(0, this.selectionStart);
let input = this.text.substring(0, this.selectionStart);
return (
this.source
@@ -195,8 +204,8 @@ export default {
})
// Cut off the part that's already been typed.
.map(entry => entry.substring(this.selectionStart))
// We only want the top 3 suggestions.
.slice(0, 3)
// We only want the top 6 suggestions.
.slice(0, 6)
);
}
},

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">New Collection</h3>
<h3 class="title">{{ $t("new_collection") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,32 +17,40 @@
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" placeholder="My New Collection" />
<input
type="text"
v-model="name"
:placeholder="$t('my_new_collection')"
@keyup.enter="addNewCollection"
/>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="addNewCollection">
<i class="material-icons">add</i>
<span>Create</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="addNewCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
import { fb } from "../../functions/fb";
export default {
props: {
show: Boolean
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {
@@ -50,11 +58,25 @@ export default {
};
},
methods: {
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
}
}
},
addNewCollection() {
if (!this.$data.name) {
this.$toast.info($t("invalid_collection_name"));
return;
}
this.$store.commit("postwoman/addNewCollection", {
name: this.$data.name
});
this.$emit("hide-modal");
this.syncCollections();
},
hideModal() {
this.$emit("hide-modal");

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">New Folder</h3>
<h3 class="title">{{ $t("new_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,26 +17,32 @@
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" placeholder="My New Folder" />
<input
type="text"
v-model="name"
:placeholder="$t('my_new_folder')"
@keyup.enter="addNewFolder"
/>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="addNewFolder">
<i class="material-icons">add</i>
<span>Create</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="addNewFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show: Boolean,
@@ -44,7 +50,7 @@ export default {
collectionIndex: Number
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {

View File

@@ -9,50 +9,79 @@
<span>{{ collection.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="removeCollection" v-tooltip="'Delete collection'">
<i class="material-icons">delete</i>
</button>
<button class="icon" @click="$emit('edit-collection')" v-tooltip="'Edit collection'">
<i class="material-icons">create</i>
</button>
<button class="icon" @click="$emit('add-folder')" v-tooltip="'New Folder'">
<button class="icon" @click="$emit('add-folder')" 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="removeCollection" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren">
<ul>
<li v-for="(folder, index) in collection.folders" :key="folder.name">
<folder
v-bind:folder="folder"
v-bind:folderIndex="index"
v-bind:collection-index="collectionIndex"
v-on:edit-folder="editFolder(collectionIndex, folder, index)"
v-on:edit-request="$emit('edit-request', $event)"
:folder="folder"
:folderIndex="index"
:collection-index="collectionIndex"
@edit-folder="editFolder(collectionIndex, folder, index)"
@edit-request="$emit('edit-request', $event)"
/>
</li>
<li v-if="(collection.folders.length === 0) && (collection.requests.length === 0)">
<label>Collection is empty</label>
<li
v-if="
collection.folders.length === 0 && collection.requests.length === 0
"
>
<label>{{ $t("collection_empty") }}</label>
</li>
</ul>
<ul>
<li v-for="(request, index) in collection.requests" :key="index">
<request
v-bind:request="request"
v-bind:collection-index="collectionIndex"
v-bind:folder-index="-1"
v-bind:request-index="index"
v-on:edit-request="$emit('edit-request', { request, collectionIndex, folderIndex: undefined, requestIndex: index })"
></request>
:request="request"
:collection-index="collectionIndex"
:folder-index="-1"
:request-index="index"
@edit-request="
$emit('edit-request', {
request,
collectionIndex,
folderIndex: undefined,
requestIndex: index
})
"
/>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
<style scoped lang="scss">
ul {
display: flex;
flex-direction: column;
@@ -66,13 +95,10 @@ ul li {
</style>
<script>
import folder from "./folder";
import request from "./request";
export default {
components: {
folder,
request
folder: () => import("./folder"),
request: () => import("./request")
},
props: {
collectionIndex: Number,
@@ -89,7 +115,7 @@ export default {
this.showChildren = !this.showChildren;
},
removeCollection() {
if (!confirm("Are you sure you want to remove this collection?")) return;
if (!confirm("Are you sure you want to remove this Collection?")) return;
this.$store.commit("postwoman/removeCollection", {
collectionIndex: this.collectionIndex
});

View File

@@ -1,12 +1,12 @@
<template>
<modal v-if="show" @close="hideModel">
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Collection</h3>
<h3 class="title">{{ $t("edit_collection") }}</h3>
<div>
<button class="icon" @click="hideModel">
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
@@ -17,26 +17,32 @@
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" v-bind:placeholder="editingCollection.name" />
<input
type="text"
v-model="name"
:placeholder="editingCollection.name"
@keyup.enter="saveCollection"
/>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveCollection">
<i class="material-icons">save</i>
<span>Save</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="saveCollection">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show: Boolean,
@@ -44,7 +50,7 @@ export default {
editingCollectionIndex: Number
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {
@@ -53,6 +59,10 @@ export default {
},
methods: {
saveCollection() {
if (!this.$data.name) {
this.$toast.info($t("invalid_collection_name"));
return;
}
const collectionUpdated = {
...this.$props.editingCollection,
name: this.$data.name
@@ -63,7 +73,7 @@ export default {
});
this.$emit("hide-modal");
},
hideModel() {
hideModal() {
this.$emit("hide-modal");
}
}

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Folder</h3>
<h3 class="title">{{ $t("edit_folder") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,26 +17,32 @@
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" v-bind:placeholder="folder.name" />
<input
type="text"
v-model="name"
:placeholder="folder.name"
@keyup.enter="editFolder"
/>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="editFolder">
<i class="material-icons">add</i>
<span>Save</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="editFolder">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show: Boolean,
@@ -46,7 +52,7 @@ export default {
folderIndex: Number
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Request</h3>
<h3 class="title">{{ $t("edit_request") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,41 +17,76 @@
<div slot="body">
<ul>
<li>
<label for="selectLabel">Label</label>
<input type="text" id="selectLabel" v-model="requestUpdateData.name" :placeholder="request.name" />
<label for="selectCollection">Collection</label>
<select type="text" id="selectCollection" v-model="requestUpdateData.collectionIndex">
<option :key="undefined" :value="undefined" hidden disabled selected>Current Collection</option>
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="requestUpdateData.name"
@keyup.enter="saveRequest"
:placeholder="request.name"
/>
<label for="selectCollection">{{ $t("collection") }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectCollection"
v-model="requestUpdateData.collectionIndex"
>
<option
v-for="(collection, index) in $store.state.postwoman.collections"
:key="undefined"
:value="undefined"
hidden
disabled
selected
>{{ $t("current_collection") }}</option
>
<option
v-for="(collection, index) in $store.state.postwoman
.collections"
:key="index"
:value="index"
>{{ collection.name }}</option>
>
{{ collection.name }}
</option>
</select>
<label for="selectFolder">Folder</label>
<select type="text" id="selectFolder" v-model="requestUpdateData.folderIndex">
</span>
<label for="selectFolder">{{ $t("folder") }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectFolder"
v-model="requestUpdateData.folderIndex"
>
<option :key="undefined" :value="undefined">/</option>
<option v-for="(folder, index) in folders" :key="index" :value="index">{{ folder.name }}</option>
<option
v-for="(folder, index) in folders"
:key="index"
:value="index"
>
{{ folder.name }}
</option>
</select>
</span>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveRequest">
<i class="material-icons">save</i>
<span>Save</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="saveRequest">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show: Boolean,
@@ -61,7 +96,7 @@ export default {
requestIndex: Number
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {
@@ -107,7 +142,6 @@ export default {
// pass data separately to don't depend on request's collection, folder fields
// probably, they should be deprecated because they don't describe request itself
this.$store.commit("postwoman/editRequest", {
requestOld: this.$props.request,
requestOldCollectionIndex: this.$props.collectionIndex,
requestOldFolderIndex: this.$props.folderIndex,
requestOldIndex: this.$props.requestIndex,

View File

@@ -9,36 +9,54 @@
<span>{{ folder.name }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeFolder" v-tooltip="'Delete folder'">
<i class="material-icons">delete</i>
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<button class="icon" @click="editFolder" v-tooltip="'Edit folder'">
<template slot="popover">
<div>
<button class="icon" @click="editFolder" v-close-popover>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeFolder" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div v-show="showChildren">
<ul>
<li v-for="(request, index) in folder.requests" :key="index">
<request
v-bind:request="request"
v-bind:collection-index="collectionIndex"
v-bind:folder-index="folderIndex"
v-bind:request-index="index"
v-on:edit-request="$emit('edit-request', { request, collectionIndex, folderIndex, requestIndex: index })"
></request>
:request="request"
:collection-index="collectionIndex"
:folder-index="folderIndex"
:request-index="index"
@edit-request="
$emit('edit-request', {
request,
collectionIndex,
folderIndex,
requestIndex: index
})
"
/>
</li>
<li v-if="folder.requests.length === 0">
<label>Folder is empty</label>
<label>{{ $t("folder_empty") }}</label>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
<style scoped lang="scss">
ul {
display: flex;
flex-direction: column;
@@ -52,8 +70,6 @@ ul li {
</style>
<script>
import request from "./request";
export default {
props: {
folder: Object,
@@ -61,7 +77,7 @@ export default {
folderIndex: Number
},
components: {
request
request: () => import("./request")
},
data() {
return {

View File

@@ -1,16 +1,64 @@
<template>
<modal v-if="show" @close="hideModel">
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Import / Export Collections</h3>
<div>
<button class="icon" @click="hideModel">
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
<div class="flex-wrap">
<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>
</li>
</ul>
</div>
@@ -18,59 +66,39 @@
<textarea v-model="collectionJson" rows="8"></textarea>
</div>
<div slot="footer">
<ul>
<li>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button
class="icon"
@click="openDialogChooseFileToReplaceWith"
v-tooltip="'Replace current'"
class="icon primary"
@click="exportJSON"
v-tooltip="$t('download_file')"
>
<i class="material-icons">create_new_folder</i>
<span>Replace with JSON</span>
<input
type="file"
@change="replaceWithJSON"
style="display: none;"
ref="inputChooseFileToReplaceWith"
/>
{{ $t("export") }}
</button>
</li>
<li>
<button
class="icon"
@click="openDialogChooseFileToImportFrom"
v-tooltip="'Preserve current'"
>
<i class="material-icons">folder_shared</i>
<span>Import from JSON</span>
<input
type="file"
@change="importFromJSON"
style="display: none;"
ref="inputChooseFileToImportFrom"
/>
</button>
</li>
<li>
<button class="icon" @click="exportJSON" v-tooltip="'Download file'">
<i class="material-icons">get_app</i>
<span>Export to JSON</span>
</button>
</li>
</ul>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
import { fb } from "../../functions/fb";
export default {
data() {
return {
fb
};
},
props: {
show: Boolean
},
components: {
modal
modal: () => import("../../components/modal")
},
computed: {
collectionJson() {
@@ -78,7 +106,7 @@ export default {
}
},
methods: {
hideModel() {
hideModal() {
this.$emit("hide-modal");
},
openDialogChooseFileToReplaceWith() {
@@ -92,7 +120,25 @@ export default {
reader.onload = event => {
let content = event.target.result;
let collections = JSON.parse(content);
this.$store.commit("postwoman/replaceCollections", collections);
if (collections[0]) {
let [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")
) {
collections = this.parsePostmanCollection(collections);
} else {
return this.failedImport();
}
this.$store.commit("postwoman/importCollections", collections);
this.fileImported();
};
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0]);
},
@@ -101,7 +147,25 @@ export default {
reader.onload = event => {
let content = event.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"
) {
// Do nothing
}
} else if (
collections.info &&
collections.info.schema.includes("v2.1.0")
) {
collections = this.parsePostmanCollection(collections);
} else {
return this.failedImport();
}
this.$store.commit("postwoman/importCollections", collections);
this.fileImported();
};
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0]);
},
@@ -119,6 +183,141 @@ export default {
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
},
syncCollections() {
this.$store.commit("postwoman/replaceCollections", fb.currentCollections);
this.fileImported();
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
icon: "folder_shared"
});
},
failedImport() {
this.$toast.error(this.$t("import_failed"), {
icon: "error"
});
},
parsePostmanCollection(collection, folders = true) {
let postwomanCollection = folders
? [
{
name: "",
folders: [],
requests: []
}
]
: {
name: "",
requests: []
};
for (let collectionItem of collection.item) {
if (collectionItem.request) {
if (postwomanCollection[0]) {
postwomanCollection[0].name = collection.info
? collection.info.name
: "";
postwomanCollection[0].requests.push(
this.parsePostmanRequest(collectionItem)
);
} else {
postwomanCollection.name = collection.name ? collection.name : "";
postwomanCollection.requests.push(
this.parsePostmanRequest(collectionItem)
);
}
} else if (collectionItem.item) {
if (collectionItem.item[0]) {
postwomanCollection[0].folders.push(
this.parsePostmanCollection(collectionItem, false)
);
}
}
}
return postwomanCollection;
},
parsePostmanRequest(requestObject) {
let pwRequest = {
url: "",
path: "",
method: "",
auth: "",
httpUser: "",
httpPassword: "",
passwordFieldType: "password",
bearerToken: "",
headers: [],
params: [],
bodyParams: [],
rawParams: "",
rawInput: false,
contentType: "",
requestType: "",
name: ""
};
pwRequest.name = requestObject.name;
let requestObjectUrl = requestObject.request.url.raw.match(
/^(.+:\/\/[^\/]+|{[^\/]+})(\/[^\?]+|).*$/
);
pwRequest.url = requestObjectUrl[1];
pwRequest.path = requestObjectUrl[2] ? requestObjectUrl[2] : "";
pwRequest.method = requestObject.request.method;
let itemAuth = requestObject.request.auth
? requestObject.request.auth
: "";
let 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;
pwRequest.httpPassword =
itemAuth.basic[0].key === "password"
? itemAuth.basic[0].value
: itemAuth.basic[1].value;
} else if (authType === "oauth2") {
pwRequest.auth = "OAuth 2.0";
pwRequest.bearerToken =
itemAuth.oauth2[0].key === "accessToken"
? itemAuth.oauth2[0].value
: itemAuth.oauth2[1].value;
} else if (authType === "bearer") {
pwRequest.auth = "Bearer Token";
pwRequest.bearerToken = itemAuth.bearer[0].value;
}
let requestObjectHeaders = requestObject.request.header;
if (requestObjectHeaders) {
pwRequest.headers = requestObjectHeaders;
for (let header of pwRequest.headers) {
delete header.name;
delete header.type;
}
}
let requestObjectParams = requestObject.request.url.query;
if (requestObjectParams) {
pwRequest.params = requestObjectParams;
for (let param of pwRequest.params) {
delete param.disabled;
}
}
if (requestObject.request.body) {
if (requestObject.request.body.mode === "urlencoded") {
let params = requestObject.request.body.urlencoded;
pwRequest.bodyParams = params ? params : [];
for (let param of pwRequest.bodyParams) {
delete param.type;
}
} else if (requestObject.request.body.mode === "raw") {
pwRequest.rawInput = true;
pwRequest.rawParams = requestObject.request.body.raw;
}
}
return pwRequest;
}
}
};

View File

@@ -4,75 +4,102 @@ TODO:
-->
<template>
<div class="collections-wrapper">
<addCollection v-bind:show="showModalAdd" v-on:hide-modal="displayModalAdd(false)"></addCollection>
<pw-section class="yellow" :label="$t('collections')" ref="collections">
<addCollection :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
<editCollection
v-bind:show="showModalEdit"
v-bind:editingCollection="editingCollection"
v-bind:editingCollectionIndex="editingCollectionIndex"
v-on:hide-modal="displayModalEdit(false)"
></editCollection>
:show="showModalEdit"
:editingCollection="editingCollection"
:editingCollectionIndex="editingCollectionIndex"
@hide-modal="displayModalEdit(false)"
/>
<addFolder
v-bind:show="showModalAddFolder"
v-bind:collection="editingCollection"
v-bind:collectionIndex="editingCollectionIndex"
v-on:hide-modal="displayModalAddFolder(false)"
></addFolder>
:show="showModalAddFolder"
:collection="editingCollection"
:collectionIndex="editingCollectionIndex"
@hide-modal="displayModalAddFolder(false)"
/>
<editFolder
v-bind:show="showModalEditFolder"
v-bind:collection="editingCollection"
v-bind:collectionIndex="editingCollectionIndex"
v-bind:folder="editingFolder"
v-bind:folderIndex="editingFolderIndex"
v-on:hide-modal="displayModalEditFolder(false)"
></editFolder>
:show="showModalEditFolder"
:collection="editingCollection"
:collectionIndex="editingCollectionIndex"
:folder="editingFolder"
:folderIndex="editingFolderIndex"
@hide-modal="displayModalEditFolder(false)"
/>
<editRequest
v-bind:show="showModalEditRequest"
v-bind:collectionIndex="editingCollectionIndex"
v-bind:folderIndex="editingFolderIndex"
v-bind:request="editingRequest"
v-bind:requestIndex="editingRequestIndex"
v-on:hide-modal="displayModalEditRequest(false)"
></editRequest>
:show="showModalEditRequest"
:collectionIndex="editingCollectionIndex"
:folderIndex="editingFolderIndex"
:request="editingRequest"
:requestIndex="editingRequestIndex"
@hide-modal="displayModalEditRequest(false)"
/>
<importExportCollections
v-bind:show="showModalImportExport"
v-on:hide-modal="displayModalImportExport(false)"
></importExportCollections>
:show="showModalImportExport"
@hide-modal="displayModalImportExport(false)"
/>
<div class="flex-wrap">
<div>
<button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i>
<span>New</span>
<span>{{ $t("new") }}</span>
</button>
</div>
<div>
<button class="icon" @click="displayModalImportExport(true)">
<i class="material-icons">import_export</i>
<span>Import / Export</span>
{{ $t("import_export") }}
</button>
<!-- <a
href="https://github.com/liyasthomas/postwoman/wiki/Collections"
target="_blank"
rel="noopener"
>
<button class="icon" v-tooltip="'Wiki'">
<i class="material-icons">help</i>
</button>
</a> -->
</div>
</div>
<p v-if="collections.length === 0" class="info">
Create new collection
</p>
<virtual-list
class="virtual-list"
:class="{ filled: collections.length }"
:size="152"
:remain="Math.min(5, collections.length)"
>
<ul>
<li v-for="(collection, index) in collections" :key="collection.name">
<collection
v-bind:collection-index="index"
v-bind:collection="collection"
v-on:edit-collection="editCollection(collection, index)"
v-on:add-folder="addFolder(collection, index)"
v-on:edit-folder="editFolder($event)"
v-on:edit-request="editRequest($event)"
></collection>
:collection-index="index"
:collection="collection"
@edit-collection="editCollection(collection, index)"
@add-folder="addFolder(collection, index)"
@edit-folder="editFolder($event)"
@edit-request="editRequest($event)"
/>
</li>
<li v-if="collections.length === 0">
<label>Collections are empty</label>
</li>
</ul>
</div>
</virtual-list>
<nuxt-link :to="localePath('doc')" :aria-label="$t('documentation')">
<button class="icon">
<i class="material-icons">books</i>
<span>{{ $t("generate_docs") }}</span>
</button>
</nuxt-link>
</pw-section>
</template>
<style lang="scss" scoped>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 276px);
}
ul {
display: flex;
flex-direction: column;
@@ -80,23 +107,20 @@ ul {
</style>
<script>
import addCollection from "./addCollection";
import addFolder from "./addFolder";
import collection from "./collection";
import editCollection from "./editCollection";
import editFolder from "./editFolder";
import editRequest from "./editRequest";
import importExportCollections from "./importExportCollections";
import { fb } from "../../functions/fb";
export default {
components: {
addCollection,
addFolder,
collection,
editCollection,
editFolder,
editRequest,
importExportCollections
"pw-section": () => import("../section"),
addCollection: () => import("./addCollection"),
addFolder: () => import("./addFolder"),
editCollection: () => import("./editCollection"),
editFolder: () => import("./editFolder"),
editRequest: () => import("./editRequest"),
importExportCollections: () => import("./importExportCollections"),
VirtualList: () => import("vue-virtual-scroll-list")
},
data() {
return {
@@ -119,6 +143,15 @@ export default {
return this.$store.state.postwoman.collections;
}
},
async mounted() {
this._keyListener = function(e) {
if (e.key === "Escape") {
e.preventDefault();
this.showModalAdd = this.showModalEdit = this.showModalImportExport = this.showModalAddFolder = this.showModalEditFolder = this.showModalEditRequest = false;
}
};
document.addEventListener("keydown", this._keyListener.bind(this));
},
methods: {
displayModalAdd(shouldDisplay) {
this.showModalAdd = shouldDisplay;
@@ -150,11 +183,13 @@ export default {
this.$data.editingCollection = collection;
this.$data.editingCollectionIndex = collectionIndex;
this.displayModalEdit(true);
this.syncCollections();
},
addFolder(collection, collectionIndex) {
this.$data.editingCollection = collection;
this.$data.editingCollectionIndex = collectionIndex;
this.displayModalAddFolder(true);
this.syncCollections();
},
editFolder(payload) {
const { collectionIndex, folder, folderIndex } = payload;
@@ -163,6 +198,7 @@ export default {
this.$data.editingFolder = folder;
this.$data.editingFolderIndex = folderIndex;
this.displayModalEditFolder(true);
this.syncCollections();
},
editRequest(payload) {
const { request, collectionIndex, folderIndex, requestIndex } = payload;
@@ -171,6 +207,7 @@ export default {
this.$data.editingRequest = request;
this.$data.editingRequestIndex = requestIndex;
this.displayModalEditRequest(true);
this.syncCollections();
},
resetSelectedData() {
this.$data.editingCollection = undefined;
@@ -179,7 +216,19 @@ export default {
this.$data.editingFolderIndex = undefined;
this.$data.editingRequest = undefined;
this.$data.editingRequestIndex = undefined;
},
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
}
}
}
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
</script>

View File

@@ -1,23 +1,38 @@
<template>
<div class="flex-wrap">
<div>
<button class="icon" @click="selectRequest()" v-tooltip="'Use request'">
<button
class="icon"
@click="selectRequest()"
v-tooltip="$t('use_request')"
>
<i class="material-icons">insert_drive_file</i>
<span>{{ request.name }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeRequest" v-tooltip="'Delete request'">
<i class="material-icons">delete</i>
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<button class="icon" @click="$emit('edit-request')" v-tooltip="'Edit request'">
<template slot="popover">
<div>
<button class="icon" @click="$emit('edit-request')" v-close-popover>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeRequest" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
</template>
<style scoped>
<style scoped lang="scss">
ul {
display: flex;
flex-direction: column;

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Save Request As</h3>
<h3 class="title">{{ $t("save_request_as") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,54 +17,94 @@
<div slot="body">
<ul>
<li>
<label for="selectLabel">Label</label>
<label for="selectLabel">{{ $t("label") }}</label>
<input
type="text"
id="selectLabel"
v-model="requestData.name"
v-bind:placeholder="defaultRequestName"
:placeholder="defaultRequestName"
@keyup.enter="saveRequestAs"
/>
<label for="selectCollection">Collection</label>
<select type="text" id="selectCollection" v-model="requestData.collectionIndex">
<option :key="undefined" :value="undefined" hidden disabled selected>Select a Collection</option>
<label for="selectCollection">{{ $t("collection") }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectCollection"
v-model="requestData.collectionIndex"
>
<option
v-for="(collection, index) in $store.state.postwoman.collections"
: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>
>
{{ collection.name }}
</option>
</select>
<label for="selectFolder">Folder</label>
<select type="text" id="selectFolder" v-model="requestData.folderIndex">
</span>
<label for="selectFolder">{{ $t("folder") }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectFolder"
v-model="requestData.folderIndex"
>
<option :key="undefined" :value="undefined">/</option>
<option v-for="(folder, index) in folders" :key="index" :value="index">{{ folder.name }}</option>
<option
v-for="(folder, index) in folders"
:key="index"
:value="index"
>
{{ folder.name }}
</option>
</select>
<label for="selectRequest">Request</label>
<select type="text" id="selectRequest" v-model="requestData.requestIndex">
</span>
<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>
>
{{ folder.name }}
</option>
</select>
</span>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveRequestAs">
<i class="material-icons">save</i>
<span>Save</span>
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
</li>
</ul>
<button class="icon primary" @click="saveRequestAs">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
import { fb } from "../../functions/fb";
export default {
props: {
@@ -72,11 +112,11 @@ export default {
editingRequest: Object
},
components: {
modal
modal: () => import("../../components/modal")
},
data() {
return {
defaultRequestName: "My New Request",
defaultRequestName: "My Request",
requestData: {
name: undefined,
collectionIndex: undefined,
@@ -102,6 +142,12 @@ export default {
this.$data.requestData.collectionIndex !== undefined;
if (!userSelectedAnyCollection) return [];
const noCollectionAvailable =
this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
] !== undefined;
if (!noCollectionAvailable) return [];
return this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
].folders;
@@ -124,17 +170,32 @@ export default {
const collection = this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
];
const noCollectionAvailable =
this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
] !== undefined;
if (!noCollectionAvailable) return [];
const requests = collection.requests;
return requests;
}
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
}
}
},
saveRequestAs() {
const userDidntSpecifyCollection =
this.$data.requestData.collectionIndex === undefined;
if (userDidntSpecifyCollection) {
this.$toast.error("Select a Collection", {
this.$toast.error(this.$t("select_collection"), {
icon: "error"
});
return;
@@ -154,6 +215,7 @@ export default {
});
this.hideModal();
this.syncCollections();
},
hideModal() {
this.$emit("hide-modal");

View File

@@ -0,0 +1,94 @@
<template>
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("new_environment") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input
type="text"
v-model="name"
:placeholder="$t('my_new_environment')"
@keyup.enter="addNewEnvironment"
/>
</li>
</ul>
</div>
<div slot="footer">
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="addNewEnvironment">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import { fb } from "../../functions/fb";
export default {
props: {
show: Boolean
},
components: {
modal: () => import("../../components/modal")
},
data() {
return {
name: undefined
};
},
methods: {
syncEnvironments() {
if (fb.currentUser !== null) {
if (fb.currentSettings[1].value) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
);
}
}
},
addNewEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"));
return;
}
let newEnvironment = [
{
name: this.$data.name,
variables: []
}
];
this.$store.commit("postwoman/importAddEnvironments", {
environments: newEnvironment,
confirmation: "Environment added"
});
this.$emit("hide-modal");
this.syncEnvironments();
},
hideModal() {
this.$data.name = undefined;
this.$emit("hide-modal");
}
}
};
</script>

View File

@@ -0,0 +1,221 @@
<template>
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("edit_environment") }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input
type="text"
v-model="name"
:placeholder="editingEnvironment.name"
@keyup.enter="saveEnvironment"
/>
</li>
</ul>
<ul>
<li>
<div class="flex-wrap">
<label for="variableList">{{ $t("env_variable_list") }}</label>
<div>
<button
class="icon"
@click="clearContent($event)"
v-tooltip.bottom="$t('clear')"
>
<i class="material-icons">clear_all</i>
</button>
</div>
</div>
<textarea
id="variableList"
readonly
v-textarea-auto-height="variableString"
v-model="variableString"
:placeholder="$t('add_one_variable')"
rows="1"
></textarea>
</li>
</ul>
<ul
v-for="(variable, index) in this.editingEnvCopy.variables"
:key="index"
>
<li>
<input
:placeholder="$t('parameter_count', { count: index + 1 })"
:name="'param' + index"
:value="variable.key"
@change="
$store.commit('postwoman/setVariableKey', {
index,
value: $event.target.value
})
"
autofocus
/>
</li>
<li>
<input
:placeholder="$t('value_count', { count: index + 1 })"
:name="'value' + index"
:value="
typeof variable.value === 'string'
? variable.value
: JSON.stringify(variable.value)
"
@change="
$store.commit('postwoman/setVariableValue', {
index,
value: $event.target.value
})
"
/>
</li>
<div>
<li>
<button
class="icon"
@click="removeEnvironmentVariable(index)"
v-tooltip.bottom="$t('delete')"
id="variable"
>
<i class="material-icons">delete</i>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button class="icon" @click="addEnvironmentVariable">
<i class="material-icons">add</i>
<span>{{ $t("add_new") }}</span>
</button>
</li>
</ul>
</div>
<div slot="footer">
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button class="icon primary" @click="saveEnvironment">
{{ $t("save") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import textareaAutoHeight from "../../directives/textareaAutoHeight";
export default {
directives: {
textareaAutoHeight
},
props: {
show: Boolean,
editingEnvironment: Object,
editingEnvironmentIndex: Number
},
components: {
modal: () => import("../../components/modal")
},
data() {
return {
name: undefined
};
},
watch: {
editingEnvironment: function(update) {
this.name = this.$props.editingEnvironment && this.$props.editingEnvironment.name
? this.$props.editingEnvironment.name
: undefined
this.$store.commit(
"postwoman/setEditingEnvironment",
this.$props.editingEnvironment
);
}
},
computed: {
editingEnvCopy() {
return this.$store.state.postwoman.editingEnvironment;
},
variableString() {
const result = this.editingEnvCopy.variables;
return result === "" ? "" : JSON.stringify(result);
}
},
methods: {
clearContent(e) {
this.$store.commit("postwoman/removeVariables", []);
e.target.innerHTML = this.doneButton;
this.$toast.info(this.$t("cleared"), {
icon: "clear_all"
});
setTimeout(
() => (e.target.innerHTML = '<i class="material-icons">clear_all</i>'),
1000
);
},
addEnvironmentVariable() {
let value = { key: "", value: "" };
this.$store.commit("postwoman/addVariable", value);
},
removeEnvironmentVariable(index) {
let variableIndex = index;
const oldVariables = this.editingEnvCopy.variables.slice();
const newVariables = this.editingEnvCopy.variables.filter(
(variable, index) => variableIndex !== index
);
this.$store.commit("postwoman/removeVariable", newVariables);
this.$toast.error(this.$t("deleted"), {
icon: "delete",
action: {
text: this.$t("undo"),
onClick: (e, toastObject) => {
this.$store.commit("postwoman/removeVariable", oldVariables);
toastObject.remove();
}
}
});
},
saveEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"));
return;
}
const environmentUpdated = {
...this.editingEnvCopy,
name: this.$data.name
};
this.$store.commit("postwoman/saveEnvironment", {
environment: environmentUpdated,
environmentIndex: this.$props.editingEnvironmentIndex
});
this.$emit("hide-modal");
},
hideModal() {
this.$data.name = undefined;
this.$emit("hide-modal");
}
}
};
</script>

View File

@@ -0,0 +1,65 @@
<template>
<div class="flex-wrap">
<div>
<button
class="icon"
@click="$emit('select-environment')"
v-tooltip="$t('use_environment')"
>
<i class="material-icons">insert_drive_file</i>
<span>{{ environment.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-environment')"
v-close-popover
>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeEnvironment" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
</template>
<style scoped lang="scss">
ul {
display: flex;
flex-direction: column;
}
ul li {
display: flex;
padding-left: 16px;
border-left: 1px solid var(--brd-color);
}
</style>
<script>
export default {
props: {
environment: Object,
environmentIndex: Number
},
methods: {
removeEnvironment() {
if (!confirm("Are you sure you want to remove this environment?")) return;
this.$store.commit("postwoman/removeEnvironment", this.environmentIndex);
}
}
};
</script>

View File

@@ -0,0 +1,173 @@
<template>
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Import / Export Environment</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
<div class="flex-wrap">
<span
v-tooltip="{
content: !fb.currentUser
? $t('login_first')
: $t('replace_current')
}"
>
<button
:disabled="!fb.currentUser"
class="icon"
@click="syncEnvironments"
>
<i class="material-icons">folder_shared</i>
<span>{{ $t("import_from_sync") }}</span>
</button>
</span>
<button
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>
</li>
</ul>
</div>
<div slot="body">
<textarea v-model="environmentJson" rows="8"></textarea>
</div>
<div slot="footer">
<div class="flex-wrap">
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
</button>
<button
class="icon primary"
@click="exportJSON"
v-tooltip="$t('download_file')"
>
{{ $t("export") }}
</button>
</span>
</div>
</div>
</modal>
</template>
<script>
import { fb } from "../../functions/fb";
export default {
data() {
return {
fb
};
},
props: {
show: Boolean
},
components: {
modal: () => import("../../components/modal")
},
computed: {
environmentJson() {
return JSON.stringify(this.$store.state.postwoman.environments, null, 2);
}
},
methods: {
hideModal() {
this.$emit("hide-modal");
},
openDialogChooseFileToReplaceWith() {
this.$refs.inputChooseFileToReplaceWith.click();
},
openDialogChooseFileToImportFrom() {
this.$refs.inputChooseFileToImportFrom.click();
},
replaceWithJSON() {
let reader = new FileReader();
reader.onload = event => {
let content = event.target.result;
let environments = JSON.parse(content);
this.$store.commit("postwoman/replaceEnvironments", environments);
};
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0]);
this.fileImported();
},
importFromJSON() {
let reader = new FileReader();
reader.onload = event => {
let content = event.target.result;
let environments = JSON.parse(content);
let confirmation = this.$t("file_imported")
this.$store.commit("postwoman/importAddEnvironments", {
environments,
confirmation
});
};
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0]);
},
exportJSON() {
let text = this.environmentJson;
text = text.replace(/\n/g, "\r\n");
let blob = new Blob([text], {
type: "text/json"
});
let anchor = document.createElement("a");
anchor.download = "postwoman-environment.json";
anchor.href = window.URL.createObjectURL(blob);
anchor.target = "_blank";
anchor.style.display = "none";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
},
syncEnvironments() {
this.$store.commit(
"postwoman/replaceEnvironments",
fb.currentEnvironments
);
this.fileImported();
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
icon: "folder_shared"
});
}
}
};
</script>

View File

@@ -0,0 +1,147 @@
<template>
<pw-section
class="green"
icon="history"
:label="$t('environment')"
ref="environment"
>
<addEnvironment :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
<editEnvironment
:show="showModalEdit"
:editingEnvironment="editingEnvironment"
:editingEnvironmentIndex="editingEnvironmentIndex"
@hide-modal="displayModalEdit(false)"
/>
<importExportEnvironment
:show="showModalImportExport"
@hide-modal="displayModalImportExport(false)"
/>
<div class="flex-wrap">
<div>
<button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i>
<span>{{ $t("new") }}</span>
</button>
</div>
<div>
<button class="icon" @click="displayModalImportExport(true)">
{{ $t("import_export") }}
</button>
</div>
</div>
<p v-if="environments.length === 0" class="info">
Create new environment
</p>
<virtual-list
class="virtual-list"
:class="{ filled: environments.length }"
:size="152"
:remain="Math.min(5, environments.length)"
>
<ul>
<li
v-for="(environment, index) in environments"
:key="environment.name"
>
<environment
:environmentIndex="index"
:environment="environment"
@edit-environment="editEnvironment(environment, index)"
@select-environment="$emit('use-environment', environment)"
/>
</li>
<li v-if="environments.length === 0">
<label>Environments are empty</label>
</li>
</ul>
</virtual-list>
</pw-section>
</template>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 276px);
}
ul {
display: flex;
flex-direction: column;
}
</style>
<script>
import environment from "./environment";
import { fb } from "../../functions/fb";
const updateOnLocalStorage = (propertyName, property) =>
window.localStorage.setItem(propertyName, JSON.stringify(property));
export default {
components: {
environment,
"pw-section": () => import("../section"),
addEnvironment: () => import("./addEnvironment"),
editEnvironment: () => import("./editEnvironment"),
importExportEnvironment: () => import("./importExportEnvironment"),
VirtualList: () => import("vue-virtual-scroll-list")
},
data() {
return {
showModalImportExport: false,
showModalAdd: false,
showModalEdit: false,
editingEnvironment: undefined,
editingEnvironmentIndex: undefined
};
},
computed: {
environments() {
return this.$store.state.postwoman.environments;
}
},
async mounted() {
this._keyListener = function(e) {
if (e.key === "Escape") {
e.preventDefault();
this.showModalImportExport = false;
}
};
document.addEventListener("keydown", this._keyListener.bind(this));
},
methods: {
displayModalAdd(shouldDisplay) {
this.showModalAdd = shouldDisplay;
},
displayModalEdit(shouldDisplay) {
this.showModalEdit = shouldDisplay;
if (!shouldDisplay) this.resetSelectedData();
},
displayModalImportExport(shouldDisplay) {
this.showModalImportExport = shouldDisplay;
},
editEnvironment(environment, environmentIndex) {
this.$data.editingEnvironment = environment;
this.$data.editingEnvironmentIndex = environmentIndex;
this.displayModalEdit(true);
this.syncEnvironments;
},
resetSelectedData() {
this.$data.editingEnvironment = undefined;
this.$data.editingEnvironmentIndex = undefined;
},
syncEnvironments() {
if (fb.currentUser !== null) {
if (fb.currentSettings[1].value) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
);
}
}
}
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
</script>

View File

@@ -0,0 +1,78 @@
<template>
<virtual-list
v-if="fb.currentFeeds.length !== 0"
class="virtual-list"
:class="{ filled: fb.currentFeeds.length }"
:size="90"
:remain="Math.min(5, fb.currentFeeds.length)"
>
<ul v-for="feed in fb.currentFeeds" :key="feed.id" class="entry">
<div class="show-on-large-screen">
<li class="info">
<label>
{{ feed.label || $t("no_label") }}
</label>
</li>
<button class="icon" @click="deleteFeed(feed)">
<i class="material-icons">delete</i>
</button>
</div>
<div class="show-on-large-screen">
<li class="info clamb-3">
<label>{{ feed.message || $t("empty") }}</label>
</li>
</div>
</ul>
</virtual-list>
<ul v-else>
<li>
<label class="info">{{ $t("empty") }}</label>
</li>
</ul>
</template>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 288px);
}
ul,
ol {
flex-direction: column;
}
.entry {
border-bottom: 1px dashed var(--brd-color);
padding: 0 0 8px;
}
.clamb-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>
<script>
import { fb } from "../../functions/fb";
export default {
components: {
VirtualList: () => import("vue-virtual-scroll-list")
},
data() {
return {
fb
};
},
methods: {
deleteFeed(feed) {
fb.deleteFeed(feed.id);
this.$toast.error(this.$t("deleted"), {
icon: "delete"
});
}
}
};
</script>

View File

@@ -0,0 +1,69 @@
<template>
<div>
<ul>
<div class="show-on-large-screen">
<li>
<input
:aria-label="$t('label')"
type="text"
autofocus
v-model="message"
:placeholder="$t('paste_a_note')"
@keyup.enter="formPost"
/>
</li>
</div>
<div class="show-on-large-screen">
<li>
<input
:aria-label="$t('label')"
type="text"
autofocus
v-model="label"
:placeholder="$t('label')"
@keyup.enter="formPost"
/>
</li>
<button
class="icon"
:disabled="!(this.message || this.label)"
value="Save"
@click="formPost"
>
<i class="material-icons">add</i>
<span>Add</span>
</button>
</div>
</ul>
</div>
</template>
<style scoped lang="scss">
ul,
ol {
flex-direction: column;
}
</style>
<script>
import { fb } from "../../functions/fb";
export default {
data() {
return {
message: null,
label: null
};
},
methods: {
formPost() {
if (!(this.message || this.label)) {
return;
}
fb.writeFeeds(this.message, this.label);
this.message = null;
this.label = null;
}
}
};
</script>

View File

@@ -0,0 +1,115 @@
<template>
<v-popover>
<button class="icon" v-tooltip="$t('login_with')">
<i class="material-icons">vpn_key</i>
</button>
<template slot="popover">
<div>
<button class="icon" @click="signInWithGoogle" v-close-popover>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
class="material-icons"
>
<path
d="M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z"
/>
</svg>
<span>Google</span>
</button>
</div>
<div>
<button class="icon" @click="signInWithGithub" v-close-popover>
<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>
<span>GitHub</span>
</button>
</div>
</template>
</v-popover>
</template>
<script>
import firebase from "firebase/app";
import { fb } from "../../functions/fb";
export default {
data() {
return {
fb
};
},
methods: {
signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", false);
fb.writeSettings("syncCollections", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
},
signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider();
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", false);
fb.writeSettings("syncCollections", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
}
}
};
</script>

View File

@@ -0,0 +1,38 @@
<template>
<span>
<span class="argumentName">
{{ argName }}
</span>
:
<typelink :type="argType" :jumpTypeCallback="jumpCallback" />
</span>
</template>
<style scoped lang="scss"></style>
<script>
import typelink from "./typelink";
export default {
components: {
typelink: typelink
},
props: {
gqlArg: Object
},
computed: {
argName() {
return this.gqlArg.name;
},
argType() {
return this.gqlArg.type;
}
},
methods: {
jumpCallback(typeName) {}
}
};
</script>

View File

@@ -0,0 +1,93 @@
<template>
<div class="field-box">
<div class="field-title">
{{ fieldName }}
<span v-if="fieldArgs.length > 0">
(
<span v-for="(field, index) in fieldArgs" :key="index">
{{ field.name }}:
<typelink
:gqlType="field.type"
:jumpTypeCallback="jumpTypeCallback"
/>
<span v-if="index !== fieldArgs.length - 1">
,
</span>
</span>
) </span
>:
<typelink :gqlType="gqlField.type" :jumpTypeCallback="jumpTypeCallback" />
</div>
<div class="field-desc" v-if="gqlField.description">
{{ gqlField.description }}
</div>
<div class="field-deprecated" v-if="gqlField.isDeprecated">
{{ $t("deprecated") }}
</div>
</div>
</template>
<style scoped lang="scss">
.field-box {
padding: 16px;
margin: 4px;
border-bottom: 1px dashed var(--brd-color);
}
.field-deprecated {
background-color: yellow;
color: black;
display: inline-block;
padding: 4px 8px;
margin: 4px 0;
border-radius: 4px;
font-size: 14px;
font-weight: 700;
}
.field-desc {
color: var(--fg-light-color);
margin-top: 4px;
}
</style>
<script>
import typelink from "./typelink";
export default {
components: {
typelink: typelink
},
props: {
gqlField: Object,
jumpTypeCallback: Function
},
computed: {
fieldString() {
const args = (this.gqlField.args || []).reduce((acc, arg, index) => {
return (
acc +
`${arg.name}: ${arg.type.toString()}${
index !== this.gqlField.args.length - 1 ? ", " : ""
}`
);
}, "");
const argsString = args.length > 0 ? `(${args})` : "";
return `${
this.gqlField.name
}${argsString}: ${this.gqlField.type.toString()}`;
},
fieldName() {
return this.gqlField.name;
},
fieldArgs() {
return this.gqlField.args || [];
}
}
};
</script>

View File

@@ -0,0 +1,173 @@
<template>
<pre ref="editor"></pre>
</template>
<script>
const DEFAULT_THEME = "twilight";
import ace from "ace-builds";
import * as gql from "graphql";
import { getAutocompleteSuggestions } from "graphql-language-service-interface";
import "ace-builds/webpack-resolver";
import "ace-builds/src-noconflict/ext-language_tools";
import debounce from "../../functions/utils/debounce";
export default {
props: {
value: {
type: String,
default: ""
},
theme: {
type: String,
required: false
},
lang: {
type: String,
default: "json"
},
options: {
type: Object,
default: {}
}
},
data() {
return {
editor: null,
cacheValue: "",
validationSchema: null
};
},
watch: {
value(value) {
if (value !== this.cacheValue) {
this.editor.session.setValue(value, 1);
this.cacheValue = value;
}
},
theme() {
this.editor.setTheme(`ace/theme/${this.defineTheme()}`);
},
lang(value) {
this.editor.getSession().setMode(`ace/mode/${value}`);
},
options(value) {
this.editor.setOptions(value);
}
},
mounted() {
let langTools = ace.require("ace/ext/language_tools");
const editor = ace.edit(this.$refs.editor, {
theme: `ace/theme/${this.defineTheme()}`,
mode: `ace/mode/${this.lang}`,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
...this.options
});
const completer = {
getCompletions: (
editor,
_session,
{ row, column },
_prefix,
callback
) => {
if (this.validationSchema) {
const completions = getAutocompleteSuggestions(
this.validationSchema,
editor.getValue(),
{ line: row, character: column }
);
callback(
null,
completions.map(({ label, detail }) => ({
name: label,
value: label,
score: 1.0,
meta: detail
}))
);
} else {
callback(null, []);
}
}
};
langTools.setCompleters([completer]);
if (this.value) editor.setValue(this.value, 1);
this.editor = editor;
this.cacheValue = this.value;
editor.on("change", () => {
const content = editor.getValue();
this.$emit("input", content);
this.parseContents(content);
this.cacheValue = content;
});
this.parseContents(this.value);
},
methods: {
defineTheme() {
if (this.theme) {
return this.theme;
} else {
return (
this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
);
}
},
setValidationSchema(schema) {
this.validationSchema = schema;
this.parseContents(this.cacheValue);
},
parseContents: debounce(function(content) {
if (content !== "") {
try {
const doc = gql.parse(content);
if (this.validationSchema) {
this.editor.session.setAnnotations(
gql
.validate(this.validationSchema, doc)
.map(({ locations, message }) => ({
row: locations[0].line - 1,
column: locations[0].column - 1,
text: message,
type: "error"
}))
);
}
} catch (e) {
this.editor.session.setAnnotations([
{
row: e.locations[0].line - 1,
column: e.locations[0].column - 1,
text: e.message,
type: "error"
}
]);
}
} else {
this.editor.session.setAnnotations([]);
}
}, 2000)
},
beforeDestroy() {
this.editor.destroy();
this.editor.container.remove();
}
};
</script>

View File

@@ -0,0 +1,44 @@
<template>
<div class="type-box">
<div class="type-title">{{ gqlType.name }}</div>
<div class="type-desc" v-if="gqlType.description">
{{ gqlType.description }}
</div>
<div v-if="gqlType.getFields">
<h5>{{ $t("fields") }}</h5>
<div v-for="field in gqlType.getFields()" :key="field.name">
<gql-field :gqlField="field" :jumpTypeCallback="jumpTypeCallback" />
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.type-box {
padding: 16px;
margin: 4px 0;
}
.type-desc {
color: var(--fg-light-color);
margin-top: 4px;
}
.type-title {
font-weight: 700;
}
</style>
<script>
export default {
components: {
"gql-field": () => import("./field")
},
props: {
gqlType: {},
jumpTypeCallback: Function
}
};
</script>

View File

@@ -0,0 +1,34 @@
<template>
<span class="typelink" @click="jumpToType">{{ typeString }}</span>
</template>
<style scoped lang="scss">
.typelink {
color: var(--ac-color);
font-family: "Roboto Mono", monospace;
font-weight: 400;
cursor: pointer;
}
</style>
<script>
export default {
props: {
gqlType: null,
// (typeName: string) => void
jumpTypeCallback: Function
},
computed: {
typeString() {
return this.gqlType.toString();
}
},
methods: {
jumpToType() {
this.jumpTypeCallback(this.gqlType);
}
}
};
</script>

View File

@@ -1,81 +1,100 @@
<template>
<pw-section class="green" icon="history" label="History" ref="history">
<pw-section class="green" icon="history" :label="$t('history')" ref="history">
<ul>
<div class="show-on-large-screen">
<li id="filter-history">
<input
aria-label="Search"
type="text"
placeholder="search history"
:readonly="history.length === 0"
type="search"
:placeholder="$t('search')"
v-model="filterText"
/>
</li>
</ul>
<ul>
<li></li>
<li @click="sort_by_label()">
<label>
Label
</label>
</li>
<li @click="sort_by_time()">
<label>
Time
</label>
</li>
<li @click="sort_by_status_code()">
<label>
Status
</label>
</li>
<li @click="sort_by_url()">
<label>
URL
</label>
</li>
<li @click="sort_by_path()">
<label>
Path
</label>
</li>
<li></li>
<button class="icon">
<i class="material-icons">search</i>
</button>
</div>
</ul>
<virtual-list
class="virtual-list"
:class="{ filled: filteredHistory.length }"
:size="54"
:size="185"
:remain="Math.min(5, filteredHistory.length)"
>
<ul v-for="(entry, index) in filteredHistory" :key="index" class="entry">
<li>
<button v-if="entry.usesScripts"
v-tooltip="'This entry used pre-request scripts'"
<div class="show-on-large-screen">
<button
class="icon"
:class="{ stared: entry.star }"
@click="toggleStar(entry)"
v-tooltip="{
content: !entry.star ? $t('add_star') : $t('remove_star')
}"
>
<i class="material-icons">code</i>
<i class="material-icons">
{{ entry.star ? "star" : "star_border" }}
</i>
</button>
<button v-else
v-tooltip="'No pre-request scripts'"
class="icon"
>
<i class="material-icons">http</i>
</button>
</li>
<li>
<input
aria-label="Label"
:aria-label="$t('label')"
type="text"
readonly
:value="entry.label"
placeholder="No label"
:placeholder="$t('no_label')"
class="bg-color"
/>
</li>
<li>
<input aria-label="Time" type="text" readonly :value="entry.time" v-tooltip="entry.date" />
</li>
<!-- <li>
<button
class="icon"
v-tooltip="{
content: !entry.usesScripts
? 'No pre-request script'
: 'Used pre-request script'
}"
>
<i class="material-icons">
{{ !entry.usesScripts ? "http" : "code" }}
</i>
</button>
</li> -->
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('options')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
class="icon"
:id="'use-button#' + index"
@click="useHistory(entry)"
:aria-label="$t('edit')"
v-close-popover
>
<i class="material-icons">restore</i>
<span>{{ $t("restore") }}</span>
</button>
</div>
<div>
<button
class="icon"
:id="'delete-button#' + index"
@click="deleteHistory(entry)"
:aria-label="$t('delete')"
v-close-popover
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div class="show-on-large-screen">
<li class="method-list-item">
<input
aria-label="Method"
:aria-label="$t('method')"
type="text"
readonly
:value="entry.method"
@@ -86,52 +105,75 @@
class="entry-status-code"
:class="findEntryStatus(entry).className"
:style="{ '--status-code': entry.status }"
>{{entry.status}}</span>
</li>
<li>
<input aria-label="URL" type="text" readonly :value="entry.url" />
</li>
<li>
<input aria-label="Path" type="text" readonly :value="entry.path" placeholder="No path" />
</li>
<div class="show-on-small-screen">
<li>
<button
v-tooltip="'Delete entry'"
class="icon"
:id="'delete-button#'+index"
@click="deleteHistory(entry)"
aria-label="Delete"
>{{ entry.status }}</span
>
<i class="material-icons">delete</i>
</button>
</li>
<li>
<button
v-tooltip="'Edit entry'"
class="icon"
:id="'use-button#'+index"
@click="useHistory(entry)"
aria-label="Edit"
>
<i class="material-icons">edit</i>
</button>
</li>
</div>
<div class="show-on-large-screen">
<li>
<input
:aria-label="$t('url')"
type="text"
readonly
:value="entry.url"
:placeholder="$t('no_url')"
/>
</li>
<li>
<input
:aria-label="$t('path')"
type="text"
readonly
:value="entry.path"
:placeholder="$t('no_path')"
/>
</li>
</div>
<transition name="fade">
<div v-if="showMore" class="show-on-large-screen">
<li>
<input
:aria-label="$t('time')"
type="text"
readonly
:value="entry.time"
v-tooltip="entry.date"
/>
</li>
<li>
<input
:aria-label="$t('duration')"
type="text"
readonly
:value="entry.duration"
:placeholder="$t('no_duration')"
/>
</li>
<li>
<input
:aria-label="$t('prerequest_script')"
type="text"
readonly
:value="entry.preRequestScript"
:placeholder="$t('no_prerequest_script')"
/>
</li>
</div>
</transition>
</ul>
</virtual-list>
<ul :class="{hidden: filteredHistory.length != 0 || history.length === 0 }">
<ul
:class="{ hidden: filteredHistory.length != 0 || history.length === 0 }"
>
<li>
<label>Nothing found "{{filterText}}"</label>
<label>{{ $t("nothing_found") }} "{{ filterText }}"</label>
</li>
</ul>
<ul v-if="history.length === 0">
<li>
<label>History is empty</label>
</li>
</ul>
<ul v-if="history.length !== 0">
<li v-if="!isClearingHistory">
<p v-if="history.length === 0" class="info">
{{ $t("history_empty") }}
</p>
<div v-if="history.length !== 0">
<div class="flex-wrap" v-if="!isClearingHistory">
<button
class="icon"
id="clear-history-button"
@@ -139,62 +181,168 @@
@click="enableHistoryClearing"
>
<i class="material-icons">clear_all</i>
<span>Clear All</span>
<span>{{ $t("clear_all") }}</span>
</button>
</li>
<li v-else>
<div class="flex-wrap">
<label for="clear-history-button">Are you sure?</label>
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('sort')">
<i class="material-icons">sort</i>
</button>
<template slot="popover">
<div>
<button class="icon" id="confirm-clear-history-button" @click="clearHistory">Yes</button>
<button class="icon" id="reject-clear-history-button" @click="disableHistoryClearing">No</button>
<button class="icon" @click="sort_by_label()" v-close-popover>
<i class="material-icons">sort_by_alpha</i>
<span>{{ $t("label") }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_time()" v-close-popover>
<i class="material-icons">access_time</i>
<span>{{ $t("time") }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="sort_by_status_code()"
v-close-popover
>
<i class="material-icons">assistant</i>
<span>{{ $t("status") }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_url()" v-close-popover>
<i class="material-icons">language</i>
<span>{{ $t("url") }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_path()" v-close-popover>
<i class="material-icons">timeline</i>
<span>{{ $t("path") }}</span>
</button>
</div>
<div v-if="showMore">
<button class="icon" @click="sort_by_duration()" v-close-popover>
<i class="material-icons">timer</i>
<span>{{ $t("duration") }}</span>
</button>
</div>
<div>
<button class="icon" @click="toggleCollapse()">
<i class="material-icons">
{{ !showMore ? "first_page" : "last_page" }}
</i>
<span>{{ !showMore ? $t("show_more") : $t("hide_more") }}</span>
</button>
</div>
</template>
</v-popover>
</div>
<div class="flex-wrap" v-else>
<label for="clear-history-button" class="info">
{{ $t("are_you_sure") }}
</label>
<div>
<button
class="icon"
id="confirm-clear-history-button"
@click="clearHistory"
v-tooltip="$t('yes')"
>
<i class="material-icons">done</i>
</button>
<button
class="icon"
id="reject-clear-history-button"
@click="disableHistoryClearing"
v-tooltip="$t('no')"
>
<i class="material-icons">close</i>
</button>
</div>
</div>
</div>
</li>
</ul>
</pw-section>
</template>
<style scoped lang="scss">
.virtual-list {
max-height: calc(100vh - 284px);
[readonly] {
cursor: default;
}
}
label {
&:hover {
cursor: pointer;
color: var(--fg-color);
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.stared {
color: #f8e81c !important;
}
ul,
ol {
flex-direction: column;
}
.method-list-item {
position: relative;
span {
position: absolute;
top: 10px;
right: 10px;
font-family: "Roboto Mono", monospace;
font-weight: 400;
background-color: transparent;
padding: 2px 6px;
border-radius: 8px;
}
}
.entry {
border-bottom: 1px dashed var(--brd-color);
padding: 0 0 8px;
}
@media (max-width: 720px) {
.virtual-list.filled {
min-height: 200px;
min-height: 320px;
}
.labels {
display: none;
}
}
</style>
<script>
import VirtualList from "vue-virtual-scroll-list";
import section from "./section";
import { findStatusGroup } from "../pages/index";
import { fb } from "../functions/fb";
const updateOnLocalStorage = (propertyName, property) =>
window.localStorage.setItem(propertyName, JSON.stringify(property));
export default {
components: {
"pw-section": section,
VirtualList
"pw-section": () => import("./section"),
VirtualList: () => import("vue-virtual-scroll-list")
},
data() {
const localStorageHistory = JSON.parse(
window.localStorage.getItem("history")
);
return {
history: localStorageHistory || [],
history:
fb.currentUser !== null
? fb.currentHistory
: JSON.parse(window.localStorage.getItem("history")) || [],
filterText: "",
showFilter: false,
isClearingHistory: false,
@@ -202,11 +350,16 @@
reverse_sort_time: false,
reverse_sort_status_code: false,
reverse_sort_url: false,
reverse_sort_path: false
reverse_sort_path: false,
showMore: false
};
},
computed: {
filteredHistory() {
this.history =
fb.currentUser !== null
? fb.currentHistory
: JSON.parse(window.localStorage.getItem("history")) || [];
return this.history.filter(entry => {
const filterText = this.filterText.toLowerCase();
return Object.keys(entry).some(key => {
@@ -219,11 +372,14 @@
},
methods: {
clearHistory() {
if (fb.currentUser !== null) {
fb.clearHistory();
}
this.history = [];
this.filterText = "";
this.disableHistoryClearing();
updateOnLocalStorage("history", this.history);
this.$toast.error("History Deleted", {
this.$toast.error(this.$t("history_deleted"), {
icon: "delete"
});
},
@@ -239,12 +395,15 @@
);
},
deleteHistory(entry) {
if (fb.currentUser !== null) {
fb.deleteHistory(entry);
}
this.history.splice(this.history.indexOf(entry), 1);
if (this.history.length === 0) {
this.filterText = "";
}
updateOnLocalStorage("history", this.history);
this.$toast.error("Deleted", {
this.$toast.error(this.$t("deleted"), {
icon: "delete"
});
},
@@ -301,8 +460,8 @@
let byUrl = this.history.slice(0);
byUrl.sort((a, b) => {
if (this.reverse_sort_url)
return a.url == b.url ? 0 : +(a.url < b.url) || -1;
else return a.url == b.url ? 0 : +(a.url > b.url) || -1;
return a.url === b.url ? 0 : +(a.url < b.url) || -1;
else return a.url === b.url ? 0 : +(a.url > b.url) || -1;
});
this.history = byUrl;
this.reverse_sort_url = !this.reverse_sort_url;
@@ -311,8 +470,8 @@
let byLabel = this.history.slice(0);
byLabel.sort((a, b) => {
if (this.reverse_sort_label)
return a.label == b.label ? 0 : +(a.label < b.label) || -1;
else return a.label == b.label ? 0 : +(a.label > b.label) || -1;
return a.label === b.label ? 0 : +(a.label < b.label) || -1;
else return a.label === b.label ? 0 : +(a.label > b.label) || -1;
});
this.history = byLabel;
this.reverse_sort_label = !this.reverse_sort_label;
@@ -321,11 +480,36 @@
let byPath = this.history.slice(0);
byPath.sort((a, b) => {
if (this.reverse_sort_path)
return a.path == b.path ? 0 : +(a.path < b.path) || -1;
else return a.path == b.path ? 0 : +(a.path > b.path) || -1;
return a.path === b.path ? 0 : +(a.path < b.path) || -1;
else return a.path === b.path ? 0 : +(a.path > b.path) || -1;
});
this.history = byPath;
this.reverse_sort_path = !this.reverse_sort_path;
},
sort_by_duration() {
let byDuration = this.history.slice(0);
byDuration.sort((a, b) => {
if (this.reverse_sort_duration)
return a.duration === b.duration
? 0
: +(a.duration < b.duration) || -1;
else
return a.duration === b.duration
? 0
: +(a.duration > b.duration) || -1;
});
this.history = byDuration;
this.reverse_sort_duration = !this.reverse_sort_duration;
},
toggleCollapse() {
this.showMore = !this.showMore;
},
toggleStar(entry) {
if (fb.currentUser !== null) {
fb.toggleStar(entry, !entry.star);
}
entry.star = !entry.star;
updateOnLocalStorage("history", this.history);
}
}
};

View File

@@ -24,9 +24,9 @@
<path
:fill="color"
id="path3816"
data-old_color="#121212"
data-old_color="#202124"
class="active-path"
data-original="#121212"
data-original="#202124"
d="M 64.601,236.822 C 64.601,394.256 192.786,612 306.001,612 412.582,612 547.4,394.256 547.4,236.822 547.4,79.388 439.322,0 306,0 172.678,0 64.601,79.388 64.601,236.822 Z m 304.12,116.415 c 29.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.475 -70.598,40.195 -108.552,32.173 -8.022,-37.955 2.698,-79.078 32.173,-108.552 z M 134.727,321.063 c 37.954,-8.021 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.552 z"
/>
</g>
@@ -35,7 +35,7 @@
</svg>
</template>
<style>
<style scoped lang="scss">
#circle3814 {
/* fill: var(--fg-color); */
fill: transparent;

View File

@@ -1,5 +1,5 @@
<template>
<transition name="modal-fade">
<transition name="modal" appear>
<div class="modal-backdrop">
<div class="modal-wrapper">
<div class="modal-container">
@@ -17,7 +17,7 @@
</div>
</transition>
</template>
<style scoped>
<style scoped lang="scss">
.modal-backdrop {
position: fixed;
z-index: 998;
@@ -25,7 +25,7 @@
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.32);
display: flex;
align-items: center;
justify-content: center;
@@ -37,19 +37,24 @@
align-items: center;
justify-content: center;
flex-grow: 1;
max-width: 800px;
max-width: 720px;
}
.modal-container {
display: flex;
flex-grow: 1;
flex-direction: column;
margin: 8px;
padding: 12px;
margin: 16px;
padding: 16px;
transition: all 0.2s ease;
background-color: var(--bg-color);
border-radius: 8px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 16px 70px;
border-radius: 16px;
box-shadow: 0px 16px 70px rgba(0, 0, 0, 0.5);
max-height: calc(100vh - 32px);
}
.modal-body {
overflow: auto;
}
/*
@@ -61,13 +66,13 @@
* these styles.
*/
.modal-fade-enter,
.modal-fade-leave-active {
.modal-enter,
.modal-leave-active {
opacity: 0;
}
.modal-fade-enter .modal-container,
.modal-fade-leave-active .modal-container {
.modal-enter .modal-container,
.modal-leave-active .modal-container {
transform: scale(0.8);
transition: all 0.2s ease-in-out;
}

View File

@@ -1,9 +1,13 @@
<template>
<fieldset :id="label.toLowerCase()" :class="{ 'no-colored-frames': !frameColorsEnabled }">
<fieldset
:id="label.toLowerCase()"
:class="{ 'no-colored-frames': !frameColorsEnabled }"
>
<legend @click.prevent="collapse">
<span>{{ label }}</span>
<i class="material-icons" v-if="isCollapsed">expand_more</i>
<i class="material-icons" v-if="!isCollapsed">expand_less</i>
<i class="material-icons">
{{ isCollapsed ? "expand_more" : "expand_less" }}
</i>
</legend>
<div class="collapsible" :class="{ hidden: collapsed }">
<slot />
@@ -11,7 +15,7 @@
</fieldset>
</template>
<style>
<style scoped lang="scss">
fieldset.no-colored-frames legend {
color: var(--fg-color);
}

View File

@@ -1,50 +1,41 @@
<template>
<div class="color" :data-color="color">
<span :style="{backgroundColor: color}" class="preview">
<div
class="color"
:data-color="color"
:class="{ active: active }"
v-tooltip="{ content: name || color }"
:style="{ backgroundColor: color }"
>
<i v-if="active" class="material-icons activeTick">done</i>
</span>
{{ name || color }}
</div>
</template>
<style lang="scss">
<style scoped lang="scss">
.color {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0 16px 0 4px;
margin: 4px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
border-radius: 20px;
margin: 8px;
padding: 16px;
border-radius: 100%;
border: 3px solid var(--bg-dark-color);
cursor: pointer;
height: 40px;
transition: all 0.2s ease-in-out;
&.active {
background-color: var(--bg-dark-color);
&.fg {
color: var(--act-color);
}
.preview {
vertical-align: middle;
display: inline-block;
border-radius: 100%;
margin-right: 8px;
padding: 16px;
position: relative;
&.active {
border: 3px solid var(--ac-color);
}
&.fg.active {
border: 3px solid var(--fg-color);
}
.activeTick {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #ffffff;
}
}
}
.color.vibrant {
.preview .activeTick {
color: var(--act-color);
}
}
</style>

View File

@@ -9,7 +9,7 @@
</div>
</template>
<style lang="scss" scoped>
<style scoped lang="scss">
$useBorder: false;
$borderColor: var(--fg-light-color);
$activeColor: var(--ac-color);

View File

@@ -1,5 +1,4 @@
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": false,
".write": false

View File

@@ -1,8 +1,8 @@
export default {
name: "textareaAutoHeight",
update(element) {
if (element.scrollHeight !== element.clientHeight) {
element.style.minHeight = `${element.scrollHeight}px`;
}
update({ scrollHeight, clientHeight, style }) {
if (scrollHeight !== clientHeight) {
style.minHeight = `${scrollHeight}px`;
}
}
};

View File

@@ -14,6 +14,7 @@ services:
- "./plugins:/app/plugins"
- "./static:/app/static"
- "./store:/app/store"
- "./components:/app/components"
ports:
- "3000:3000"
command: "npm run dev"

15
docs/index.html Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Postwoman</title>
<meta http-equiv="refresh" content="0; url=https://postwoman.io" />
<link rel="canonical" href="https://postwoman.io" />
</head>
<body>
Redirecting to postwoman.io
</body>
</html>

View File

@@ -1,7 +1,14 @@
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
allow read, write: if request.auth.uid != null;
}
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}

11
functions/editorutils.js Normal file
View File

@@ -0,0 +1,11 @@
const mimeToMode = {
"text/plain": "plain_text",
"text/html": "html",
"application/xml": "xml",
"application/hal+json": "json",
"application/json": "json"
}
export function getEditorLangForMimeType(mimeType) {
return mimeToMode[mimeType] || "plain_text";
}

221
functions/fb.js Normal file
View File

@@ -0,0 +1,221 @@
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
// Initialize Firebase, copied from cloud console
const firebaseConfig = {
apiKey: "AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM",
authDomain: "postwoman-api.firebaseapp.com",
databaseURL: "https://postwoman-api.firebaseio.com",
projectId: "postwoman-api",
storageBucket: "postwoman-api.appspot.com",
messagingSenderId: "421993993223",
appId: "1:421993993223:web:ec0baa8ee8c02ffa1fc6a2",
measurementId: "G-ERJ6025CEB"
};
firebase.initializeApp(firebaseConfig);
// a reference to the users collection
const usersCollection = firebase.firestore().collection("users");
// the shared state object that any vue component
// can get access to
export const fb = {
currentUser: {},
currentFeeds: [],
currentSettings: [],
currentHistory: [],
currentCollections: [],
currentEnvironments: [],
writeFeeds: async (message, label) => {
const dt = {
createdOn: new Date(),
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
message,
label
};
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.add(dt)
.catch(e => console.error("error inserting", dt, e));
},
deleteFeed: id => {
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.doc(id)
.delete()
.catch(e => console.error("error deleting", id, e));
},
writeSettings: async (setting, value) => {
const st = {
updatedOn: new Date(),
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
name: setting,
value
};
usersCollection
.doc(fb.currentUser.uid)
.collection("settings")
.doc(setting)
.set(st)
.catch(e => console.error("error updating", st, e));
},
writeHistory: async entry => {
const hs = entry;
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.add(hs)
.catch(e => console.error("error inserting", hs, e));
},
deleteHistory: entry => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.doc(entry.id)
.delete()
.catch(e => console.error("error deleting", entry, e));
},
clearHistory: () => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.get()
.then(({ docs }) => {
docs.forEach(e => fb.deleteHistory(e));
});
},
toggleStar: (entry, value) => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.doc(entry.id)
.update({ star: value })
.catch(e => console.error("error deleting", entry, e));
},
writeCollections: async collection => {
const cl = {
updatedOn: new Date(),
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
collection: collection
};
usersCollection
.doc(fb.currentUser.uid)
.collection("collections")
.doc("sync")
.set(cl)
.catch(e => console.error("error updating", cl, e));
},
writeEnvironments: async environment => {
const ev = {
updatedOn: new Date(),
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
environment: environment
};
usersCollection
.doc(fb.currentUser.uid)
.collection("environments")
.doc("sync")
.set(ev)
.catch(e => console.error("error updating", ev, e));
}
};
// When a user logs in or out, save that in the store
firebase.auth().onAuthStateChanged(user => {
if (user) {
fb.currentUser = user;
fb.currentUser.providerData.forEach(profile => {
let us = {
updatedOn: new Date(),
provider: profile.providerId,
name: profile.displayName,
email: profile.email,
photoUrl: profile.photoURL,
uid: profile.uid
};
usersCollection
.doc(fb.currentUser.uid)
.set(us)
.catch(e => console.error("error updating", us, e));
});
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.orderBy("createdOn", "desc")
.onSnapshot(feedsRef => {
const feeds = [];
feedsRef.forEach(doc => {
const feed = doc.data();
feed.id = doc.id;
feeds.push(feed);
});
fb.currentFeeds = feeds;
});
usersCollection
.doc(fb.currentUser.uid)
.collection("settings")
.onSnapshot(settingsRef => {
const settings = [];
settingsRef.forEach(doc => {
const setting = doc.data();
setting.id = doc.id;
settings.push(setting);
});
fb.currentSettings = settings;
});
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.onSnapshot(historyRef => {
const history = [];
historyRef.forEach(doc => {
const entry = doc.data();
entry.id = doc.id;
history.push(entry);
});
fb.currentHistory = history;
});
usersCollection
.doc(fb.currentUser.uid)
.collection("collections")
.onSnapshot(collectionsRef => {
const collections = [];
collectionsRef.forEach(doc => {
const collection = doc.data();
collection.id = doc.id;
collections.push(collection);
});
fb.currentCollections = collections[0].collection;
});
usersCollection
.doc(fb.currentUser.uid)
.collection("environments")
.onSnapshot(environmentsRef => {
const environments = [];
environmentsRef.forEach(doc => {
const environment = doc.data();
environment.id = doc.id;
environments.push(environment);
});
fb.currentEnvironments = environments[0].environment;
});
} else {
fb.currentUser = null;
}
});

124
functions/headers.js Normal file
View File

@@ -0,0 +1,124 @@
export const commonHeaders = [
"WWW-Authenticate",
"Authorization",
"Proxy-Authenticate",
"Proxy-Authorization",
"Age",
"Cache-Control",
"Clear-Site-Data",
"Expires",
"Pragma",
"Warning",
"Accept-CH",
"Accept-CH-Lifetime",
"Early-Data",
"Content-DPR",
"DPR",
"Device-Memory",
"Save-Data",
"Viewport-Width",
"Width",
"Last-Modified",
"ETag",
"If-Match",
"If-None-Match",
"If-Modified-Since",
"If-Unmodified-Since",
"Vary",
"Connection",
"Keep-Alive",
"Accept",
"Accept-Charset",
"Accept-Encoding",
"Accept-Language",
"Expect",
"Max-Forwards",
"Cookie",
"Set-Cookie",
"Cookie2",
"Set-Cookie2",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials",
"Access-Control-Allow-Headers",
"Access-Control-Allow-Methods",
"Access-Control-Expose-Headers",
"Access-Control-Max-Age",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Origin",
"Service-Worker-Allowed",
"Timing-Allow-Origin",
"X-Permitted-Cross-Domain-Policies",
"DNT",
"Tk",
"Content-Disposition",
"Content-Length",
"Content-Type",
"Content-Encoding",
"Content-Language",
"Content-Location",
"Forwarded",
"X-Forwarded-For",
"X-Forwarded-Host",
"X-Forwarded-Proto",
"Via",
"Location",
"From",
"Host",
"Referer",
"Referrer-Policy",
"User-Agent",
"Allow",
"Server",
"Accept-Ranges",
"Range",
"If-Range",
"Content-Range",
"Cross-Origin-Opener-Policy",
"Cross-Origin-Resource-Policy",
"Content-Security-Policy",
"Content-Security-Policy-Report-Only",
"Expect-CT",
"Feature-Policy",
"Public-Key-Pins",
"Public-Key-Pins-Report-Only",
"Strict-Transport-Security",
"Upgrade-Insecure-Requests",
"X-Content-Type-Options",
"X-Download-Options",
"X-Frame-Options",
"X-Powered-By",
"X-XSS-Protection",
"Last-Event-ID",
"NEL",
"Ping-From",
"Ping-To",
"Report-To",
"Transfer-Encoding",
"TE",
"Trailer",
"Sec-WebSocket-Key",
"Sec-WebSocket-Extensions",
"Sec-WebSocket-Accept",
"Sec-WebSocket-Protocol",
"Sec-WebSocket-Version",
"Accept-Push-Policy",
"Accept-Signature",
"Alt-Svc",
"Date",
"Large-Allocation",
"Link",
"Push-Policy",
"Retry-After",
"Signature",
"Signed-Headers",
"Server-Timing",
"SourceMap",
"Upgrade",
"X-DNS-Prefetch-Control",
"X-Firefox-Spdy",
"X-Pingback",
"X-Requested-With",
"X-Robots-Tag",
"X-UA-Compatible"
];

View File

@@ -1,4 +1,4 @@
const functions = require('firebase-functions');
// const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions

42
functions/network.js Normal file
View File

@@ -0,0 +1,42 @@
import AxiosStrategy from "./strategies/AxiosStrategy";
import ExtensionStrategy, {
hasExtensionInstalled
} from "./strategies/ExtensionStrategy";
import FirefoxStrategy from "./strategies/FirefoxStrategy";
import ChromeStrategy, {
hasChromeExtensionInstalled
} from "./strategies/ChromeStrategy";
const isExtensionsAllowed = ({ state }) =>
typeof state.postwoman.settings.EXTENSIONS_ENABLED === "undefined" ||
state.postwoman.settings.EXTENSIONS_ENABLED;
const runAppropriateStrategy = (req, store) => {
if (isExtensionsAllowed(store)) {
if (hasExtensionInstalled()) {
return ExtensionStrategy(req, store);
}
// The following strategies are deprecated and kept to support older version of the extensions
// Chrome Provides a chrome object for scripts to access
// Check its availability to say whether you are in Google Chrome
if (window.chrome && hasChromeExtensionInstalled()) {
return ChromeStrategy(req, store);
}
// The firefox plugin injects a function to send requests through it
// If that is available, then we can use the FirefoxStrategy
if (window.firefoxExtSendRequest) {
return FirefoxStrategy(req, store);
}
}
return AxiosStrategy(req, store);
};
const sendNetworkRequest = (req, store) =>
runAppropriateStrategy(req, store).finally(() =>
window.$nuxt.$loading.finish()
);
export { sendNetworkRequest };

View File

@@ -0,0 +1,175 @@
const PASS = "PASS";
const FAIL = "FAIL";
const ERROR = "ERROR";
const styles = {
[PASS]: { icon: "check", class: "success-response" },
[FAIL]: { icon: "close", class: "cl-error-response" },
[ERROR]: { icon: "close", class: "cl-error-response" },
none: { icon: "", class: "" }
};
// TODO: probably have to use a more global state for `test`
export default function runTestScriptWithVariables(script, variables) {
let pw = {
_errors: [],
_testReports: [],
_report: "",
expect(value) {
try {
return expect(value, this._testReports);
} catch (e) {
pw._testReports.push({ result: ERROR, message: e });
}
},
test: (descriptor, func) => test(descriptor, func, pw._testReports)
// globals that the script is allowed to have access to.
};
Object.assign(pw, variables);
// run pre-request script within this function so that it has access to the pw object.
new Function("pw", script)(pw);
//
const testReports = pw._testReports.map(item => {
if (item.result) {
item.styles = styles[item.result];
} else {
item.styles = styles.none;
}
return item;
});
return { report: pw._report, errors: pw._errors, testResults: testReports };
}
function test(descriptor, func, _testReports) {
_testReports.push({ startBlock: descriptor });
try {
func();
} catch (e) {
_testReports.push({ result: ERROR, message: e });
}
_testReports.push({ endBlock: true });
// TODO: Organize and generate text report of each {descriptor: true} section in testReports.
// add checkmark or x depending on if each testReport is pass=true or pass=false
}
function expect(expectValue, _testReports) {
return new Expectation(expectValue, null, _testReports);
}
class Expectation {
constructor(expectValue, _not, _testReports) {
this.expectValue = expectValue;
this.not = _not || new Expectation(this.expectValue, true, _testReports);
this._testReports = _testReports; // this values is used within Test.it, which wraps Expectation and passes _testReports value.
this._satisfies = function(expectValue, targetValue) {
// Used for testing if two values match the expectation, which could be === OR !==, depending on if not
// was used. Expectation#_satisfies prevents the need to have an if(this.not) branch in every test method.
// Signature is _satisfies([expectValue,] targetValue): if only one argument is given, it is assumed the targetValue, and expectValue is set to this.expectValue
if (!targetValue) {
targetValue = expectValue;
expectValue = this.expectValue;
}
if (this.not === true) {
// test the inverse. this.not is always truthly, but an Expectation that is inverted will always be strictly `true`
return expectValue !== targetValue;
} else {
return expectValue === targetValue;
}
};
}
_fmtNot(message) {
// given a string with "(not)" in it, replaces with "not" or "", depending if the expectation is expecting the positive or inverse (this._not)
if (this.not === true) {
return message.replace("(not)", "not ");
} else {
return message.replace("(not)", "");
}
}
_fail(message) {
this._testReports.push({ result: FAIL, message });
}
_pass(message) {
this._testReports.push({ result: PASS });
}
// TEST METHODS DEFINED BELOW
// these are the usual methods that would follow expect(...)
toBe(value) {
return this._satisfies(value)
? this._pass()
: this._fail(
this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`)
);
}
toHaveProperty(value) {
return this._satisfies(this.expectValue.hasOwnProperty(value), true)
? this._pass()
: this._fail(
this._fmtNot(
`Expected object ${this.expectValue} to (not)have property ${value}`
)
);
}
toBeLevel2xx() {
const code = parseInt(this.expectValue);
if (Number.isNaN(code)) {
return this._fail(
`Expected 200-level status but could not parse value ${this.expectValue}`
);
}
return this._satisfies(code >= 200 && code < 300)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 200-level status`
)
);
}
toBeLevel3xx() {
const code = parseInt(this.expectValue);
if (Number.isNaN(code)) {
return this._fail(
`Expected 300-level status but could not parse value ${this.expectValue}`
);
}
return this._satisfies(code >= 300 && code < 400)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 300-level status`
)
);
}
toBeLevel4xx() {
const code = parseInt(this.expectValue);
if (Number.isNaN(code)) {
return this._fail(
`Expected 400-level status but could not parse value ${this.expectValue}`
);
}
return this._satisfies(code >= 400 && code < 500)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 400-level status`
)
);
}
toBeLevel5xx() {
const code = parseInt(this.expectValue);
if (Number.isNaN(code)) {
return this._fail(
`Expected 500-level status but could not parse value ${this.expectValue}`
);
}
return this._satisfies(code >= 500 && code < 600)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 500-level status`
)
);
}
}

View File

@@ -5,13 +5,16 @@ export default function getEnvironmentVariablesFromScript(script) {
// for security and control purposes, this is the only way a pre-request script should modify variables.
let pw = {
environment: {
set: (key, value) => _variables[key] = value,
set: (key, value) => (_variables[key] = value)
},
env: {
set: (key, value) => (_variables[key] = value)
}
// globals that the script is allowed to have access to.
};
// run pre-request script within this function so that it has access to the pw object.
(new Function('pw', script))(pw);
new Function("pw", script)(pw);
return _variables;
}

View File

@@ -0,0 +1,23 @@
import axios from "axios";
const axiosWithProxy = async (req, { state }) => {
const { data } = await axios.post(
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
req
);
return data;
};
const axiosWithoutProxy = async (req, _store) => {
const res = await axios(req);
return res;
};
const axiosStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return axiosWithProxy(req, store);
}
return axiosWithoutProxy(req, store);
};
export default axiosStrategy;

View File

@@ -0,0 +1,63 @@
const EXTENSION_ID = "amknoiejhlmhancpahfcfcfhllgkpbld";
// Check if the Chrome Extension is present
// The Chrome extension injects an empty span to help detection.
// Also check for the presence of window.chrome object to confirm smooth operations
export const hasChromeExtensionInstalled = () =>
document.getElementById("chromePWExtensionDetect") !== null;
const chromeWithoutProxy = (req, _store) =>
new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
EXTENSION_ID,
{
messageType: "send-req",
data: {
config: req
}
},
({ data }) => {
if (data.error) {
reject(data.error);
} else {
resolve(data.response);
}
}
);
});
const chromeWithProxy = (req, { state }) =>
new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
EXTENSION_ID,
{
messageType: "send-req",
data: {
config: {
method: "post",
url:
state.postwoman.settings.PROXY_URL ||
"https://postwoman.apollotv.xyz/",
data: req
}
}
},
({ data }) => {
if (data.error) {
reject(error);
} else {
resolve(data.response.data);
}
}
);
});
const chromeStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return chromeWithProxy(req, store);
} else {
return chromeWithoutProxy(req, store);
}
};
export default chromeStrategy;

View File

@@ -0,0 +1,26 @@
export const hasExtensionInstalled = () =>
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== "undefined";
const extensionWithProxy = async (req, { state }) => {
const { data } = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
method: "post",
url:
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
data: req
});
return data;
};
const extensionWithoutProxy = async (req, _store) => {
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest(req);
return res;
};
const extensionStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return extensionWithProxy(req, store);
}
return extensionWithoutProxy(req, store);
};
export default extensionStrategy;

View File

@@ -0,0 +1,50 @@
const firefoxWithProxy = (req, { state }) =>
new Promise((resolve, reject) => {
const eventListener = event => {
window.removeEventListener("firefoxExtSendRequestComplete", event);
if (event.detail.error) {
reject(JSON.parse(event.detail.error));
} else {
resolve(JSON.parse(event.detail.response).data);
}
};
window.addEventListener("firefoxExtSendRequestComplete", eventListener);
window.firefoxExtSendRequest({
method: "post",
url:
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
data: req
});
});
const firefoxWithoutProxy = (req, _store) =>
new Promise((resolve, reject) => {
const eventListener = ({ detail }) => {
window.removeEventListener(
"firefoxExtSendRequestComplete",
eventListener
);
if (detail.error) {
reject(JSON.parse(detail.error));
} else {
resolve(JSON.parse(detail.response));
}
};
window.addEventListener("firefoxExtSendRequestComplete", eventListener);
window.firefoxExtSendRequest(req);
});
const firefoxStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return firefoxWithProxy(req, store);
}
return firefoxWithoutProxy(req, store);
};
export default firefoxStrategy;

View File

@@ -3,5 +3,5 @@ export default function parseTemplateString(string, variables) {
return string;
}
const searchTerm = /<<([^>]*)>>/g; // "<<myVariable>>"
return string.replace(searchTerm, (match, p1) => variables[p1] || '');
return string.replace(searchTerm, (match, p1) => variables[p1] || "");
}

View File

@@ -0,0 +1,15 @@
// Debounce is a higher order function which makes its enclosed function be executed
// only if the function wasn't called again till 'delay' time has passed, this helps reduce impact of heavy working
// functions which might be called frequently
// NOTE : Don't use lambda functions as this doesn't get bound properly in them, use the 'function (args) {}' format
const debounce = (func, delay) => {
let inDebounce;
return function() {
const context = this;
const args = arguments;
clearTimeout(inDebounce);
inDebounce = setTimeout(() => func.apply(context, args), delay);
};
};
export default debounce;

90
lang/de-DE.js Normal file
View File

@@ -0,0 +1,90 @@
export default {
home: "Startseite",
realtime: "Echtzeit",
graphql: "GraphQL",
settings: "Einstellungen",
request: "Anfrage",
install_pwa: "PWA installieren",
support_us: "Unterstütze uns",
tweet: "Twittern",
options: "Optionen",
communication: "Kommunikation",
endpoint: "Endpunkt",
schema: "Schema",
theme: "Design",
subscribe: "Abonnieren",
choose_language: "Sprache auswählen",
shortcuts: "Tastenkombinationen",
send_request: "Anfrage senden",
save_to_collections: "In Sammlungen speichern",
copy_request_link: "Anfragelink kopieren",
reset_request: "Anfrage zurücksetzen",
support_us_on: "Unterstütze uns auf",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript-Code",
method: "Methode",
path: "Pfad",
label: "Beschriftung",
again: "Wiederholen",
content_type: "Content-Typ",
raw_input: "Rohdaten-Eingabe",
parameter_list: "Parameterliste",
raw_request_body: "Rohdaten der Anfrage",
show_code: "Code zeigen",
hide_code: "Code ausblenden",
show_prerequest_script: "Preanfrageskript anzeigen",
hide_prerequest_script: "Preanfrageskript ausblenden",
authentication: "Authentifizierung",
authentication_type: "Authentifizierungs-Typ",
include_in_url: "In URL einfügen",
parameters: "Parameter",
expand_response: "Antwort ausklappen",
collapse_response: "Antwort einklappen",
hide_preview: "Vorschau verstecken",
preview_html: "HTML-Vorschau",
history: "Verlauf",
collections: "Kollektionen",
import_curl: "cURL importieren",
import: "Importieren",
generate_code: "Code generieren",
request_type: "Anfrage-Typ",
generated_code: "Generierter Code",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(warte auf Verbindung)",
message: "Nachricht",
sse: "SSE",
server: "Server",
events: "Ereignisse",
url: "URL",
get_schema: "Schema abrufen",
header_list: "Headerliste",
add_new: "Neu hinzufügen",
response: "Antwort",
query: "Abfrage",
queries: "Abfragen",
query_variables: "Variablen",
mutations: "Mutationen",
subscriptions: "Abonnements",
types: "Typen",
send: "Senden",
background: "Hintergrund",
color: "Farbe",
labels: "Bezeichner",
multi_color: "Mehrfarbig",
enabled: "Aktiviert",
disabled: "Deaktiviert",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Postwomans offizieller Proxy wird durch ApolloTV bereitgestellt.",
read_the: "Lies die",
apollotv_privacy_policy: "ApolloTV Datenschutzerklärung",
contact_us: "Kontaktiere uns",
connect: "Verbinden",
disconnect: "Trennen",
start: "Start",
stop: "Stopp"
};

277
lang/en-US.js Normal file
View File

@@ -0,0 +1,277 @@
export default {
home: "Home",
realtime: "Realtime",
graphql: "GraphQL",
settings: "Settings",
request: "Request",
install_pwa: "Install PWA",
support_us: "Support us",
tweet: "Tweet",
options: "Options",
communication: "Communication",
endpoint: "Endpoint",
schema: "Schema",
theme: "Theme",
subscribe: "Subscribe",
choose_language: "Choose Language",
shortcuts: "Shortcuts",
send_request: "Send Request",
save_to_collections: "Save to Collections",
copy_request_link: "Copy Request Link",
reset_request: "Reset Request",
support_us_on: "Support us on",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript Code",
method: "Method",
path: "Path",
label: "Label",
content_type: "Content Type",
raw_input: "Raw input",
parameter_list: "Parameter List",
raw_request_body: "Raw Request Body",
show_code: "Show Code",
hide_code: "Hide Code",
show_prerequest_script: "Show Pre-Request Script",
hide_prerequest_script: "Hide Pre-Request Script",
authentication: "Authentication",
authentication_type: "Authentication type",
include_in_url: "Include in URL",
parameters: "Parameters",
expand_response: "Expand response",
collapse_response: "Collapse response",
hide_preview: "Hide Preview",
preview_html: "Preview HTML",
history: "History",
collections: "Collections",
environment: "Environment",
new_environment: "New Environment",
my_new_environment: "My New Environment",
edit_environment: "Edit Environment",
env_variable_list: "Variable List",
invalid_environment_name: "Please provide a valid name for the environment",
use_environment: "Use Environment",
add_one_variable: "(add at least one variable)",
import_curl: "Import cURL",
import: "Import",
generate_code: "Generate code",
request_type: "Request type",
generated_code: "Generated code",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(waiting for connection)",
message: "Message",
sse: "SSE",
server: "Server",
events: "Events",
url: "URL",
get_schema: "Get schema",
header_list: "Header list",
add_new: "Add new",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Subscriptions",
types: "Types",
send: "Send",
background: "Background",
color: "Color",
labels: "Labels",
multi_color: "Multi-color",
enabled: "Enabled",
disabled: "Disabled",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Postwoman's Official Proxy is hosted by ApolloTV.",
read_the: "Read the",
apollotv_privacy_policy: "ApolloTV privacy policy",
contact_us: "Contact us",
connect: "Connect",
disconnect: "Disconnect",
start: "Start",
stop: "Stop",
access_token: "Access Token",
token_list: "Token List",
get_token: "Get New Token",
manage_token: "Manage Access Token",
save_token: "Save Access Token",
use_token: "Use Saved Token",
request_token: "Request Token",
save_token_req: "Save Token Request",
manage_token_req: "Manage Token Request",
use_token_req: "Use Token Request",
token_req_name: "Request Name",
token_req_details: "Request Details",
token_name: "Token Name",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "Auth URL",
access_token_url: "Access Token URL",
client_id: "Client ID",
scope: "Scope",
state: "State",
token_req_list: "Token Request List",
no_path: "No path",
no_label: "No label",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "No pre-request script",
search: "Search",
history_empty: "History is empty",
history_deleted: "History Deleted",
clear: "Clear",
clear_all: "Clear All",
cleared: "Cleared",
close: "Close",
sort: "Sort",
time: "Time",
duration: "Duration",
no_duration: "No duration",
show_more: "Show more",
hide_more: "Hide more",
collection: "Collection",
current_collection: "Current Collection",
select_collection: "Select a Collection",
create_collection: "Create a Collection",
new: "New",
import_export: "Import / Export",
more: "More",
folder: "Folder",
new_folder: "New Folder",
my_new_folder: "My New Folder",
folder_empty: "Folder is empty",
edit_folder: "Edit Folder",
edit: "Edit",
delete: "Delete",
deleted: "Deleted",
undo: "Undo",
collection_empty: "Collection is empty",
invalid_collection_name: "Please provide a valid name for the collection",
new_collection: "New Collection",
my_new_collection: "My New Collection",
edit_collection: "Edit Collection",
edit_request: "Edit Request",
save_request_as: "Save Request As",
export: "Export",
connecting_to: "Connecting to {name}...",
connected: "Connected",
connected_to: "Connected to {name}",
disconnected: "Disconnected",
disconnected_from: "Disconnected from {name}",
something_went_wrong: "Something went wrong!",
error_occurred: "An error has occurred.",
browser_support_sse:
"This browser doesn't seems to have Server Sent Events support.",
log: "Log",
no_url: "No URL",
run_query: "Run Query",
copy_query: "Copy Query",
kinda_dark: "Kinda Dark",
clearly_white: "Clearly White",
just_black: "Just Black",
auto_system: "Auto (system)",
green: "Green",
yellow: "Yellow",
pink: "Pink",
red: "Red",
purple: "Purple",
orange: "Orange",
cyan: "Cyan",
blue: "Blue",
loading: "Loading...",
fetching: "Fetching...",
waiting_send_req: "(waiting to send request)",
cancel: "Cancel",
save: "Save",
dismiss: "Dismiss",
are_you_sure: "Are you sure?",
yes: "Yes",
no: "No",
restore: "Restore",
add_star: "Add star",
remove_star: "Remove star",
nothing_found: "Nothing found",
replace_current: "Replace current",
replace_json: "Replace with JSON",
preserve_current: "Preserve current",
import_json: "Import from JSON",
download_file: "Download file",
upload_file: "Upload file",
copy_response: "Copy response",
copy_code: "Copy code",
copy_schema: "Copy Schema",
use_request: "Use request",
documentation: "Documentation",
docs: "Docs",
reset_default: "Reset to default",
fields: "FIELDS",
deprecated: "DEPRECATED",
add_one_header: "(add at least one header)",
add_one_parameter: "(add at least one parameter)",
header_count: "header {count}",
parameter_count: "parameter {count}",
variable_count: "variable {count}",
value_count: "value {count}",
send_request_first: "Send a request first",
generate_docs: "Generate Documentation",
generate_docs_message:
"Import any Postwoman Collection to Generate Documentation on-the-go.",
generate_docs_first: "Generate documentation first",
docs_generated: "Documentation generated",
import_collections: "Import collections",
optional: "(optional)",
json: "JSON",
none: "None",
username: "Username",
password: "Password",
token: "Token",
payload: "Payload",
choose_file: "Choose a file",
file_imported: "File imported",
import_failed: "Import failed",
f12_details: "(F12 for details)",
we_use_cookies: "We use cookies",
copied_to_clipboard: "Copied to clipboard",
finished_in: "Finished in {duration}ms",
check_console_details: "Check console for details.",
download_started: "Download started",
url_invalid_format: "URL is not formatted properly",
curl_invalid_format: "cURL is not formatted properly",
enable_proxy: "Try enabling Proxy",
complete_config_urls: "Please complete configuration urls.",
token_request_saved: "Token request saved",
donate_info1:
"If you have enjoyed the productivity of using Postwoman, consider donating as a sign of appreciation.",
donate_info2:
"You can support Postwoman development via the following methods:",
one_time_recurring: "One-time or recurring",
one_time: "One-time",
recurring: "Recurring",
wiki: "Wiki",
error: "Error",
go_home: "Go Home",
reload: "Reload",
enter_curl: "Enter cURL",
empty: "Empty",
extensions: "Extensions",
extensions_use_toggle:
"Use the browser extension to send requests (if present)",
extensions_info1: "Browser extension that simplifies access to Postwoman",
extensions_info2: "Get Postwoman browser extension!",
installed: "Installed",
login_with: "Login with",
logged_out: "Logged out",
logout: "Logout",
account: "Account",
sync: "Sync",
syncHistory: "History",
syncCollections: "Collections",
syncEnvironments: "Environments",
turn_on: "Turn on",
login_first: "Login first",
paste_a_note: "Paste a note",
import_from_sync: "Import from Sync",
notes: "Notes"
};

264
lang/es-ES.js Normal file
View File

@@ -0,0 +1,264 @@
export default {
home: "Inicio",
realtime: "Tiempo real",
graphql: "GraphQL",
settings: "Ajustes",
request: "Petición",
install_pwa: "Instalar PWA",
support_us: "Ayúdanos",
tweet: "Tweet",
options: "Opciones",
communication: "Comunicación",
endpoint: "Endpoint",
schema: "Esquema",
theme: "Tema",
subscribe: "Subscribirse",
choose_language: "Seleccione un idioma",
shortcuts: "Atajos",
send_request: "Enviar petición",
save_to_collections: "Guardar en las Colecciones",
copy_request_link: "Copiar enlace de la petición",
reset_request: "Reiniciar Petición",
support_us_on: "Ayúdanos en",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "Código JavaScript",
method: "Método",
path: "Ruta",
label: "Etiqueta",
again: "De nuevo",
content_type: "Tipo de Contenido",
raw_input: "Datos sin Procesar",
parameter_list: "Lista de Parámetros",
raw_request_body: "Cuerpo de la Solicitud sin Procesar",
show_code: "Mostrar el código",
hide_code: "Ocultar el código",
show_prerequest_script: "Mostrar Script pre solicitud",
hide_prerequest_script: "Ocultar Script pre solicitud",
authentication: "Autenticación",
authentication_type: "Tipo de autenticación",
include_in_url: "Incluir en el URL",
parameters: "Parámetros",
expand_response: "Ampliar Respuesta",
collapse_response: "Contraer Respuesta",
hide_preview: "Ocultar la vista previa",
preview_html: "Vista Previa del HTML",
history: "Historial",
collections: "Colecciones",
import_curl: "Importar cURL",
import: "Importar",
generate_code: "Generar código",
request_type: "Tipo de Petición",
generated_code: "Código Generado",
status: "Estado",
headers: "Cabeceras",
websocket: "WebSocket",
waiting_for_connection: "(esperando por conexión)",
message: "Mensaje",
sse: "SSE",
server: "Servidor",
events: "Eventos",
url: "URL",
get_schema: "Obtener esquema",
header_list: "Lista de Cabeceras",
add_new: "Agregar nuevo",
response: "Respuesta",
query: "Consulta",
queries: "Consultas",
query_variables: "Variables",
mutations: "Mutaciones",
subscriptions: "Subscripciones",
types: "Tipos",
send: "Enviar",
background: "Fondo",
color: "Color",
labels: "Etiquetas",
multi_color: "Multicolor",
enabled: "Habilitado",
disabled: "Deshabilitado",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
read_the: "Leer la",
apollotv_privacy_policy: "Política de Privacidad de ApolloTV",
contact_us: "Contáctenos",
connect: "Conectar",
disconnect: "Desconectar",
start: "Comienzo",
stop: "Detener",
access_token: "Token de acceso",
token_list: "Lista de token",
get_token: "Obtener un nuevo token",
manage_token: "Gestionar el token de acceso",
save_token: "Guardar el token de acceso",
use_token: "Usar token guardado",
request_token: "Petición del token",
save_token_req: "Guardar la petición del token",
manage_token_req: "Gestionar la petición del token",
use_token_req: "Usar el token de la petición",
token_req_name: "Nombre de la petición",
token_req_details: "Petición de detalles",
token_name: "Nombre del token",
oidc_discovery_url: "URL de descubrimiento de OIDC",
auth_url: "URL de autenticación",
access_token_url: "URL de token de acceso",
client_id: "ID del cliente",
scope: "Alcance",
state: "Estado",
token_req_list: "Lista de solicitud de token",
no_path: "Sin ruta",
no_label: "Sin etiqueta",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "Script sin pre-requisito",
search: "buscar historial",
history_empty: "Historial vacío",
history_deleted: "Historial borrado",
clear: "Limpiar",
clear_all: "Limpiar todo",
cleared: "Limpiado",
close: "Cerrar",
sort: "Ordenar",
time: "Tiempo",
duration: "Duración",
no_duration: "Sin duración",
show_more: "Mostrar más",
hide_more: "Ocultar más",
collection: "Colección",
current_collection: "Actual colección",
select_collection: "Seleccionar una colección",
create_collection: "Crear una colección",
new: "Nuevo",
import_export: "Importar / Exportar",
more: "Más",
folder: "Directorio",
new_folder: "Nuevo directorio",
my_new_folder: "Mi nuevo directorio",
folder_empty: "Directorio vacío",
edit_folder: "Editar directorio",
edit: "Editar",
delete: "Borrar",
deleted: "Borrado",
undo: "Deshacer",
collection_empty: "Colección vacía",
new_collection: "Nueva colección",
my_new_collection: "Mi nueva colección",
edit_collection: "Editar colección",
edit_request: "Editar petición",
save_request_as: "Guardar petición como",
export: "Exportar",
connecting_to: "Conectando a {name}...",
connected: "Conectado",
connected_to: "Conectado a {name}",
disconnected: "Desconectado",
disconnected_from: "Desconectado desde {name}",
something_went_wrong: "Algo ha salido mal!",
error_occurred: "Ha ocurrido un error.",
browser_support_sse:
"Este navegador parace no tener soporte a los eventos enviados desde el servidor.",
log: "Bitácora",
no_url: "Sin URL",
run_query: "Ejecutar consulta",
copy_query: "Copiar consulta",
kinda_dark: "Un poco oscúro",
clearly_white: "Claramento blanco",
just_black: "Solo Negro",
auto_system: "Autenticación (sistema)",
green: "Verde",
yellow: "Amarillo",
pink: "Rosado",
red: "Rojo",
purple: "Púrpura",
orange: "Anaranjado",
cyan: "Cian",
blue: "Azul",
loading: "Cargando...",
fetching: "Recuperando...",
waiting_send_req: "(esperando para enviar la petición)",
cancel: "Cancelar",
save: "Guardar",
dismiss: "Descartar",
are_you_sure: "Está seguro?",
yes: "Sí",
no: "No",
restore: "Restaurar",
add_star: "Agregar estrella",
remove_star: "Eliminar estrella",
nothing_found: "No se encontró nada",
replace_current: "Reemplaza el actual",
replace_json: "Reemplazar con JSON",
preserve_current: "Preservar el actual",
import_json: "Importar desde JSON",
download_file: "Descargar archivo",
upload_file: "Cargar archivo",
copy_response: "Copiar respuesta",
copy_code: "Copiar codigo",
copy_schema: "Copiar Esquema",
use_request: "Usar la petición",
documentation: "Documentación",
docs: "Documentos",
reset_default: "Reiniciar valores por defecto",
fields: "CAMPOS",
deprecated: "OBSOLETO",
add_one_header: "(agregar al menos una cabecera)",
add_one_parameter: "(agregar al menos un parámetro)",
header_count: "cabecera {count}",
parameter_count: "parámetro {count}",
variable_count: "variable {count}",
value_count: "valor {count}",
send_request_first: "Enviar primero la petición",
generate_docs: "Generar la Documentación",
generate_docs_message:
"Importar cualquier Colección de Postwoman para Generar la Documentación sobre la marcha.",
generate_docs_first: "Generar primero la documentación",
docs_generated: "Documentación generada",
import_collections: "Importar colecciones",
optional: "(opcional)",
json: "JSON",
none: "Nada",
username: "Nombre de usuario",
password: "Contrasaeña",
token: "Token",
payload: "Carga",
choose_file: "Seleccione un archivo",
file_imported: "Archivo imporado",
f12_details: "(F12 para ver detalles)",
we_use_cookies: "Usamos las cookies",
copied_to_clipboard: "Copiado al portapapeles",
finished_in: "Terminado en {duration}ms",
check_console_details: "Verifique la consola para más detalles.",
download_started: "Inició la descarga",
url_invalid_format: "La URL no está formateado apropiadamente",
curl_invalid_format: "El cURL no está formateado apropiadamente",
enable_proxy: "Pruebe habilitando el Proxy",
complete_config_urls: "Por favor, termine la configuración de las urls.",
token_request_saved: "La petición de tToken ha sido guardada",
donate_info1:
"Si le ha gustado su productividad usando Postwoman, considere hacer una donación como un signo de su apreciación.",
donate_info2:
"Puede ayudar al desarrollo de Postwoman mediante los siguientes métodos:",
one_time_recurring: "Una vez o recurrente",
one_time: "Una vez",
recurring: "Recurrente",
wiki: "Wiki",
error: "Error",
go_home: "Ir al inicio",
reload: "Recargar",
enter_curl: "Intruduzca cURL",
empty: "Vacío",
extensions: "Extensiones",
extensions_info1: "Extensión del navegador que simplifica el acceso a Postwoman",
extensions_info2: "Obtener la extensión del navegador de Postwoman!",
installed: "Instalado",
login_with: "Iniciar sesión con",
logged_out: "Sesión cerreda",
logout: "Cerrar sesión",
account: "Cuenta",
sync: "Sync",
syncHistory: "Historial",
syncCollections: "Colecciones",
turn_on: "Encender",
login_first: "Inicie sesión primero",
paste_a_collection: "Pegar una Colección",
import_from_sync: "Importar desde Sync"
};

90
lang/fa-IR.js Normal file
View File

@@ -0,0 +1,90 @@
export default {
home: "خانه",
realtime: "بلادرنگ",
graphql: "GraphQL",
settings: "تنظیمات",
request: "درخواست",
install_pwa: "نصب PWA",
support_us: "از ما حمایت کنید",
tweet: "Tweet",
options: "گزینه‌ها",
communication: "ارتباط",
endpoint: "Endpoint",
schema: "Schema",
theme: "پوسته",
subscribe: "اشتراک",
choose_language: "تغییر زبان",
shortcuts: "میانبرها",
send_request: "ارسال درخواست",
save_to_collections: "ذخیره در کلکسیون",
copy_request_link: "کپی لینک درخواست",
reset_request: "بازنشانی درخواست",
support_us_on: "حمایت از ما از طریق",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "کد JavaScript",
method: "متد",
path: "مسیر",
label: "برچسب",
again: "دوباره",
content_type: "Content Type",
raw_input: "ورودی raw",
parameter_list: "لیست پارامترها",
raw_request_body: "Raw Request Body",
show_code: "نمایش کد",
hide_code: "عدم نمایش کد",
show_prerequest_script: "Show Pre-Request Script",
hide_prerequest_script: "Hide Pre-Request Script",
authentication: "Authentication",
authentication_type: "Authentication type",
include_in_url: "در URL گنجانده شود",
parameters: "پارامترها",
expand_response: "نمایش کامل پاسخ",
collapse_response: "نمایش مختصر پاسخ",
hide_preview: "مخفی کردن نمایش",
preview_html: "نمایش HTML",
history: "تاریخچه",
collections: "کلکسیون",
import_curl: "وارد کردن cURL",
import: "وارد کردن",
generate_code: "تولید کد",
request_type: "Request type",
generated_code: "کد تولید شده",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(منتظر برقراری اتصال)",
message: "پیام",
sse: "SSE",
server: "سرور",
events: "رویداد",
url: "URL",
get_schema: "دریافت Schema",
header_list: "لیست Header",
add_new: "افزودن",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Subscriptions",
types: "Types",
send: "ارسال",
background: "پس زمینه",
color: "رنگ",
labels: "برچسب‌ها",
multi_color: "چند رنگی",
enabled: "فعال",
disabled: "غیر فعال",
proxy: "پراکسی",
postwoman_official_proxy_hosting:
"پراکسی Postwoman برروی هاست ApolloTV قرار دارد.",
read_the: "بخوانید",
apollotv_privacy_policy: "خط مشی رازداری ApolloTV",
contact_us: "Contact us",
connect: "Connect",
disconnect: "Disconnect",
start: "Start",
stop: "Stop"
};

264
lang/fr-FR.js Normal file
View File

@@ -0,0 +1,264 @@
export default {
home: "Accueil",
realtime: "Temps réel",
graphql: "GraphQL",
settings: "Paramètres",
request: "Request",
install_pwa: "Installer la PWA",
support_us: "Nous supporter",
tweet: "Tweeter",
options: "Options",
communication: "Communication",
endpoint: "Endpoint",
schema: "Schéma",
theme: "Thème",
subscribe: "S'inscrire",
choose_language: "Sélectionner une langue",
shortcuts: "Raccourcis",
send_request: "Envoyer la requête",
save_to_collections: "Sauvegarder dans les collections",
copy_request_link: "Copier le lien de la requête",
reset_request: "Réinitialiser la requête",
support_us_on: "Supportez-nous sur",
open_collective: "Ouvrir Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "Code JavaScript",
method: "Méthode",
path: "Chemin d'accès",
label: "Libellé",
again: "Réessayer",
content_type: "Type de contenu",
raw_input: "Texte brut",
parameter_list: "Liste des paramètres",
raw_request_body: "Corps de la requête en texte brut",
show_code: "Afficher le code",
hide_code: "Masquer le code",
show_prerequest_script: "Afficher le script de pré-requête",
hide_prerequest_script: "Masquer le script de pré-requête",
authentication: "Authentification",
authentication_type: "Type d'authentification",
include_in_url: "Inclure dans l'URL",
parameters: "Paramètres",
expand_response: "Agrandir la réponse",
collapse_response: "Réduire la réponse",
hide_preview: "Masquer la prévisualisation",
preview_html: "Prévisualiser le HTML",
history: "Historique",
collections: "Collections",
import_curl: "Importer en cURL",
importer: "Importer",
generate_code: "Générer le code",
request_type: "Type de requête",
generated_code: "Code généré",
status: "Statut",
headers: "En-têtes",
websocket: "WebSocket",
waiting_for_connection: "(en attente de connexion)",
message: "Message",
sse: "SSE",
server: "Serveur",
events: "Évènements",
url: "URL",
get_schema: "Récuperer le schéma",
header_list: "Liste d'en-têtes",
add_new: "Ajouter",
response: "Réponse",
query: "Requête",
queries: "Requêtes",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Abonnements",
types: "Types",
send: "Envoyer",
background: "Arrière-plan",
color: "Couleur",
labels: "Libellés",
multi_color: "Multi-couleurs",
enabled: "Activé",
disabled: "Désactivé",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Le proxy officiel de Postwoman est hébergé par ApolloTV.",
read_the: "Lire la",
apollotv_privacy_policy: "politique de confidentialité ApolloTV",
contact_us: "Contactez nous",
connect: "Relier",
disconnect: "Déconnecter",
start: "Début",
stop: "Arrêtez",
access_token: "Token d'accès",
token_list: "Liste des Tokens",
get_token: "Obtenir un nouveau Token",
manage_token: "Gérer le Token",
save_token: "Sauvegarder le Token",
use_token: "Utiliser un Token",
request_token: "Demander un Token",
save_token_req: "Sauvegarder la requête ",
manage_token_req: "Gérer la requête avec Token",
use_token_req: "Utiliser la requête avec Token",
token_req_name: "Nom de la requête",
token_req_details: "Détails de la requête",
token_name: "Nom du Token",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "Auth URL",
access_token_url: "URL du Token d'accès",
client_id: "Client ID",
scope: "Scope",
state: "État",
token_req_list: "Liste des requêtes avec Token",
no_path: "Aucun chemin",
no_label: "Aucun label",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "No pre-request script",
search: "Historique de la recherche",
history_empty: "L'historique est vide",
history_deleted: "Historique supprimé",
clear: "Nettoyer",
clear_all: "Tout nettoyer",
cleared: "Nettoyé",
close: "Fermer",
sort: "Trier",
time: "Temps",
duration: "Durée",
no_duration: "Aucune durée",
show_more: "Plus d'informations",
hide_more: "Moins d'informations",
collection: "Collection",
current_collection: "Collection Actuelle",
select_collection: "Selectionner une Collection",
create_collection: "Créer une Collection",
new: "Nouveau",
import_export: "Importer / Exporter",
more: "Plus",
folder: "Dossier",
new_folder: "Nouveau Dossier",
my_new_folder: "Mon Nouveau Dossier",
folder_empty: "Ce Dossier est vide",
edit_folder: "Éditer le Dossier",
edit: "Éditer",
delete: "Supprimer",
deleted: "Supprimé",
undo: "Annuler",
collection_empty: "Cette Collection est vide",
new_collection: "Nouvelle Collection",
my_new_collection: "Ma Nouvelle Collection",
edit_collection: "Éditer la Collection",
edit_request: "Éditer ma requête",
save_request_as: "Sauvegarder ma requête sous",
export: "Exporter",
connecting_to: "Connexion à {name}...",
connected: "Connecté",
connected_to: "Connecté à {name}",
disconnected: "Déconnecté",
disconnected_from: "Déconnecté sur {name}",
something_went_wrong: "Quelque chose n'a pas marché!",
error_occurred: "Une erreur s'est produite.",
browser_support_sse:
"Ce navigateur ne semble pas prendre en charge les événements envoyés par le serveur.",
log: "Log",
no_url: "Aucune URL",
run_query: "Lancer une recherche",
copy_query: "Copier la recherche",
kinda_dark: "Plutôt Sombre",
clearly_white: "Clairement Blanc",
just_black: "Seulement Noir",
auto_system: "Auth (système)",
green: "Vert",
yellow: "Jaune",
pink: "Rose",
red: "Rouge",
purple: "Violet",
orange: "Orange",
cyan: "Cyan",
blue: "Bleue",
loading: "Chargement...",
fetching: "Récupération...",
waiting_send_req: "(en attente de l'envoi de la demande)",
cancel: "Annuler",
save: "Sauvarder",
dismiss: "Dismiss",
are_you_sure: "Êtes-vous sûr?",
yes: "Oui",
no: "Non",
restore: "Restaurer",
add_star: "Ajouter une étoile",
remove_star: "Supprimer une étoile",
nothing_found: "Rien n'a été trouvé",
replace_current: "Remplacer l'actuel",
replace_json: "Replacer avec du JSON",
preserve_current: "Conserver l'actuel",
import_json: "Importer depuis un JSON",
download_file: "Télécharger un fichier",
upload_file: "Charger un fichier",
copy_response: "Copier la réponse",
copy_code: "Copier le code",
copy_schema: "Copier le Schéma",
use_request: "Utiliser cette requête",
documentation: "Documentation",
docs: "Docs",
reset_default: "Rétablir la valeur par défaut",
fields: "CHAMPS",
deprecated: "DÉPRÉCIÉ",
add_one_header: "(ajouter au moins un en-tête)",
add_one_parameter: "(ajouter au moins un paramètre)",
header_count: "{count} en-tête",
parameter_count: "{count} paramètre",
variable_count: "{count} variable",
value_count: "{count} valeur",
send_request_first: "Envoyez d'abord une requête",
generate_docs: "Genérer une Documentation",
generate_docs_message:
"Importer n'importe quelle collection de Postwoman pour générer de la documentation en déplacement.",
generate_docs_first: "Générer la documentation d'abord",
docs_generated: "Documentation générée",
import_collections: "Importer les collections",
optional: "(optionnel)",
json: "JSON",
none: "Aucun",
username: "Username",
password: "Password",
token: "Token",
payload: "Payload",
choose_file: "Choisir un fichier",
file_imported: "Fichier importé",
f12_details: "(F12 pour voir les détails)",
we_use_cookies: "Nous utilisons des cookies",
copied_to_clipboard: "Copié dans le presse-papier",
finished_in: "Fini en {duration}ms",
check_console_details: "Consultez la console pour plus de détails.",
download_started: "Téléchargement démarré",
url_invalid_format: "L'URL n'est pas formatée correctement",
curl_invalid_format: "cURL n'est pas formaté correctement",
enable_proxy: "Essayez en activant le Proxy",
complete_config_urls: "Veuillez compléter les urls de configuration.",
token_request_saved: "Requête de Token sauvegardé",
donate_info1:
"Si vous avez apprécié la productivité de l'utilisation de Postwoman, considérez le don comme un signe d'appréciation.",
donate_info2:
"Vous pouvez soutenir le développement de Postwoman par les méthodes suivantes :",
one_time_recurring: "Ponctuel ou récurrent",
one_time: "Une fois",
recurring: "Récurrent",
wiki: "Wiki",
error: "Erreur",
go_home: "Aller à l'accueil",
reload: "Recharger",
enter_curl: "Entrer cURL",
empty: "Vide",
extensions: "Extensions",
extensions_info1: "Extension pour navigateur qui simplifie l'accès à Postwoman",
extensions_info2: "Obtenez l'extension Postwoman pour navigateur !",
installed: "Installé",
login_with: "Se connecter avec",
logged_out: "Se déconnecter",
logout: "Déconnexion",
account: "Compte",
sync: "Synchroniser",
syncHistory: "Historique",
syncCollections: "Collections",
turn_on: "Activer",
login_first: "Se connecter d'abord",
paste_a_collection: "Coller une collection",
import_from_sync: "Importer depuis la synchronisation"
};

90
lang/id-ID.js Normal file
View File

@@ -0,0 +1,90 @@
export default {
home: "Beranda",
realtime: "Waktu Nyata",
graphql: "GraphQL",
settings: "Pengaturan",
request: "Permintaan",
install_pwa: "Pasang PWA",
support_us: "Dukung kami",
tweet: "Cuitkan",
options: "Opsi",
communication: "Komunikasi",
endpoint: "Titik Akhir",
schema: "Skema",
theme: "Tema",
subscribe: "Berlangganan",
choose_language: "Pilih Bahasa",
shortcuts: "Pintasan",
send_request: "Kirim Permintaan",
save_to_collections: "Simpan ke Koleksi",
copy_request_link: "Salin Tautan Permintaan",
reset_request: "Atur Ulang Permintaan",
support_us_on: "Dukung kami di",
open_collective: "Open Collective",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "Kode Javascript",
method: "Metode",
path: "Lintasan",
label: "Label",
again: "Lagi",
content_type: "Jenis Konten",
raw_input: "Masukan mentah",
parameter_list: "Daftar parameter",
raw_request_body: "Badan Permintaan Mentah",
show_code: "Tampilkan Kode",
hide_code: "Sembunyikan Kode",
show_prerequest_script: "Tampilkan Skrip Pra-Permintaan",
hide_prerequest_script: "Sembunyikan Skrip Pra-Permintaan",
authentication: "Autentikasi",
authentication_type: "Jenis Autentikasi",
include_in_url: "Sertakan di URL",
parameters: "Parameter",
expand_response: "Bentangkan Balasan",
collapse_response: "Ciutkan Balasan",
hide_preview: "Sembunyikan Pratinjau",
preview_html: "Pratinjau HTML",
history: "Riwayat",
collections: "Koleksi",
import_curl: "Impor cURL",
import: "Impor",
generate_code: "Hasilkan kode",
request_type: "Jenis permintaan",
generated_code: "Kode yang dihasilkan",
status: "Status",
headers: "Header",
websocket: "WebSocket",
waiting_for_connection: "(Menunggu sambungan)",
message: "Pesan",
sse: "SSE",
server: "Peladen",
events: "Kejadian",
url: "URL",
get_schema: "Ambil skema",
header_list: "Daftar header",
add_new: "Tambah baru",
response: "Balasan",
query: "Kueri",
queries: "Kueri",
query_variables: "Variables",
mutations: "Mutasi",
subscriptions: "Langganan",
types: "Jenis",
send: "Kirim",
background: "Latar belakang",
color: "Warna",
labels: "Label",
multi_color: "Warna beragam",
enabled: "diaktifkan",
disabled: "dinonaktifkan",
proxy: "Proksi",
postwoman_official_proxy_hosting:
"Proksi Resmi Postwoman dalam penginangan ApolloTV.",
read_the: "Bacalah",
apollotv_privacy_policy: "kebijakan privasi ApolloTV",
contact_us: "Hubungi kami",
connect: "Menghubungkan",
disconnect: "Memutuskan",
start: "Mulai",
stop: "Berhenti"
};

245
lang/ja-JP.js Normal file
View File

@@ -0,0 +1,245 @@
export default {
home: "ホーム",
realtime: "リアルタイム",
graphql: "GraphQL",
settings: "設定",
request: "リクエスト",
install_pwa: "PWAをインストール",
support_us: "寄付",
tweet: "ツイート",
options: "オプション",
communication: "通信",
endpoint: "エンドポイント",
schema: "スキーマ",
theme: "テーマ",
subscribe: "登録",
choose_language: "言語の選択",
shortcuts: "ショートカット",
send_request: "リクエストを送信",
save_to_collections: "コレクションに保存",
copy_request_link: "リクエストURLをコピー",
reset_request: "リクエストをリセット",
support_us_on: "以下より寄付",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScriptコード",
method: "メソッド",
path: "パス",
label: "ラベル",
again: "",
content_type: "Content Type",
raw_input: "Raw入力",
parameter_list: "パラメータリスト",
raw_request_body: "Rawリクエストボディー",
show_code: "コードを表示",
hide_code: "コードを非表示",
show_prerequest_script: "プレリクエストスクリプトを表示",
hide_prerequest_script: "プレリクエストスクリプトを非表示",
authentication: "認証",
authentication_type: "認証タイプ",
include_in_url: "URLに含む",
parameters: "パラメータ",
expand_response: "レスポンスを広げる",
collapse_response: "レスポンスを狭める",
hide_preview: "プレビューしない",
preview_html: "HTMLプレビュー表示",
history: "履歴",
collections: "コレクション",
import_curl: "cURLをインポート",
import: "インポート",
generate_code: "コード生成",
request_type: "リクエストタイプ",
generated_code: "生成されたコード",
status: "ステータス",
headers: "ヘッダー",
websocket: "ウェブソケット",
waiting_for_connection: "(接続待ち)",
message: "メッセージ",
sse: "SSE",
server: "サーバ",
events: "イベント",
url: "URL",
get_schema: "スキーマを取得",
header_list: "ヘッダーリスト",
add_new: "追加",
response: "レスポンス",
query: "クエリ",
queries: "クエリ",
query_variables: "変数",
mutations: "ミューテーション",
subscriptions: "サブスクリプション",
types: "タイプ",
send: "送信",
background: "背景",
color: "色",
labels: "ラベル",
multi_color: "マルチカラー",
enabled: "有効",
disabled: "無効",
proxy: "プロキシ",
postwoman_official_proxy_hosting:
"Postwomanの公式プロキシは、Apollo TVがホストしています。",
read_the: "プライバシーポリシー",
apollotv_privacy_policy: "を読む",
contact_us: "お問い合わせ",
connect: "接続",
disconnect: "切断",
start: "開始",
stop: "停止",
access_token: "アクセストークン",
token_list: "トークンリスト",
get_token: "新しいトークンを取得",
manage_token: "アクセストークンを管理",
save_token: "アクセストークンを保存",
use_token: "アクセストークンを使用",
request_token: "トークンをリクエスト",
save_token_req: "トークンリクエストを保存",
manage_token_req: "トークンリクエストを管理",
use_token_req: "トークンリクエストを使用",
token_req_name: "リクエスト名",
token_req_details: "リクエスト詳細",
token_name: "トークン名",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "認証URL",
access_token_url: "アクセストークンURL",
client_id: "クライアントID",
scope: "スコープ",
state: "ステート",
token_req_list: "トークンリクエストリスト",
no_path: "パス無し",
no_label: "ラベル無し",
prerequest_script: "プレリクエストスクリプト",
no_prerequest_script: "プレリクエストスクリプト無し",
search: "検索履歴",
history_empty: "履歴が空です",
history_deleted: "履歴が削除された",
clear: "クリア",
clear_all: "全てクリア",
cleared: "クリアされた",
close: "閉じる",
sort: "ソート",
time: "時間",
duration: "期間",
no_duration: "期間なし",
show_more: "もっと表示する",
hide_more: "隠す",
collection: "コレクション",
current_collection: "現在のコレクション",
select_collection: "コレクションを選択",
create_collection: "コレクションを作成",
new: "新規",
import_export: "インポート・エクスポート",
more: "More",
folder: "フォルダ",
new_folder: "新しいフォルダー",
my_new_folder: "私の新しいフォルダー",
folder_empty: "フォルダーが空です",
edit_folder: "フォルダーを編集",
edit: "編集",
delete: "削除",
deleted: "削除された",
undo: "元に戻す",
collection_empty: "コレクションが空です",
new_collection: "新しいコレクション",
my_new_collection: "私の新しいコレクション",
edit_collection: "コレクションを編集",
edit_request: "リクエストを編集",
save_request_as: "名前を付けてリクエストを保存",
export: "エクスポート",
connecting_to: "{name}に接続中...",
connected: "接続した",
connected_to: "{name}に接続した",
disconnected: "切断された",
disconnected_from: "{name}から切断された",
something_went_wrong: "何かの問題が起きた",
error_occurred: "エラーが発生した",
browser_support_sse: "このブラウザはサーバー送信イベントのサポートがないようです。",
log: "ログ",
no_url: "URL無し",
run_query: "クエリを実行",
copy_query: "クエリをコピー",
kinda_dark: "ちょっと暗い",
clearly_white: "明らかに白",
just_black: "ただの黒",
auto_system: "オート(システム)",
green: "緑",
yellow: "黄",
pink: "ピンク",
red: "赤",
purple: "紫",
orange: "オレンジ",
cyan: "シヤン",
blue: "青",
loading: "ロード中...",
fetching: "フェッチ中...",
waiting_send_req: "(リクエスト送信待ち)",
cancel: "キャンセル",
save: "保存",
dismiss: "Dismiss",
are_you_sure: "よろしいですか?",
yes: "はい",
no: "いいえ",
restore: "リストア",
add_star: "星を付ける",
remove_star: "星を外す",
nothing_found: "何も見つからない",
replace_current: "置換",
replace_json: "JSONに置換",
preserve_current: "保持",
import_json: "JSONをインポート",
download_file: "ファイルをダウンロード",
upload_file: "ファイルをアップロード",
copy_response: "レスポンスをコピー",
copy_code: "コードをコピー",
copy_schema: "スキーマをコピー",
use_request: "リクエストを使用",
documentation: "ドキュメンテーション",
docs: "ドキュメント",
reset_default: "デフォルトにリセット",
fields: "FIELDS",
deprecated: "DEPRECATED",
add_one_header: "ヘッダーを少なくとも1つ追加してください",
add_one_parameter: "パラメータを少なくとも1つ追加してください",
header_count: "ヘッダー {count}",
parameter_count: "パラメータ {count}",
variable_count: "変数 {count}",
value_count: "値 {count}",
send_request_first: "リクエストを先に送信してください",
generate_docs: "ドキュメンテーションを生成",
generate_docs_message: "Postwomanのコレクションをインポートし、直ちにドキュメンテーションを生成",
generate_docs_first: "ドキュメントを先に生成してください",
docs_generated: "ドキュメンテーションを生成した",
import_collections: "コレクションをインポート",
optional: "(オプション)",
json: "JSON",
none: "なし",
username: "ユーザー名",
password: "パスワード",
token: "トークン",
payload: "ペイロード",
choose_file: "ファイルを選択",
file_imported: "ファイルをインポートした",
f12_details: "F12を押して詳細を確認してください",
we_use_cookies: "クッキーを使用します。",
copied_to_clipboard: "クリップボードにコピーした",
finished_in: "{duration}msで終了した",
check_console_details: "コンソールより詳細を確認してください",
download_started: "ダウンロードを開始した",
url_invalid_format: "URLが正しくフォーマットされていない",
curl_invalid_format: "cURLが正しくフォーマットされていない",
enable_proxy: "プロキシを有効にしてみてください",
complete_config_urls: "設定URLsを入力してください",
token_request_saved: "トークンリクエストを保存した",
donate_info1: "Postwomanを非常に役に立つと思われる場合、感謝の印として寄付のご検討をお願いします。",
donate_info2: "以下の方法でPostwomanの開発をサポートできます",
one_time_recurring: "一度又は定期的",
one_time: "一度",
recurring: "定期的",
wiki: "Wiki",
error: "エラー",
go_home: "ホームに戻る",
reload: "リロード",
enter_curl: "cURLを入力",
empty: "空"
};

89
lang/pt-BR.js Normal file
View File

@@ -0,0 +1,89 @@
export default {
home: "Home",
realtime: "Tempo real",
graphql: "GraphQL",
settings: "Configurações",
request: "Request",
install_pwa: "Instalar PWA",
support_us: "Nos ajude",
tweet: "Tweet",
options: "Opções",
communication: "Comunicação",
endpoint: "Endpoint",
schema: "Schema",
theme: "Tema",
subscribe: "Subscribe",
choose_language: "Escolher idioma",
shortcuts: "Atalhos",
send_request: "Enviar request",
save_to_collections: "Salvar nas coleções",
copy_request_link: "Copiar link da request",
reset_request: "Reiniciar request",
support_us_on: "Nos ajude no",
open_collective: "Abrir coletivamente",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "Codigo JavaScript",
method: "Método",
path: "Caminho",
label: "Label",
again: "Novamente",
content_type: "Content Type",
raw_input: "Raw input",
parameter_list: "Lista de parâmetros",
raw_request_body: "Raw request body",
show_code: "Mostrar código",
hide_code: "Esconder código",
show_prerequest_script: "Mostrar script de pré-request",
hide_prerequest_script: "Esconder script de pré-request",
authentication: "Autenticação",
authentication_type: "Tipo de autenticação",
include_in_url: "Incluir na url",
parameters: "Parâmetros",
expand_response: "Expandir response",
collapse_response: "Esconder response",
hide_preview: "Esconder preview",
preview_html: "Preview html",
history: "Histórico",
collections: "Coleções",
import_curl: "Importar curl",
import: "Importar",
generate_code: "Gerar código",
request_type: "Tipo de request",
generated_code: "Código gerado",
status: "Status",
headers: "Headers",
websocket: "Websocket",
waiting_for_connection: "(aguardando conexão)",
message: "Mensagem",
sse: "SSE",
server: "Servidor",
events: "Eventos",
url: "URL",
get_schema: "Get schema",
header_list: "Lista de headers",
add_new: "Adicionar novo",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variáveis",
mutations: "Mutações",
subscriptions: "Assinaturas",
types: "Tipos",
send: "Enviar",
background: "Fundo",
color: "Cor",
labels: "Labels",
multi_color: "Multi cor",
enabled: "Ativado",
disabled: "Desativado",
proxy: "Proxy",
postwoman_official_proxy_hosting: "Postwoman's alojamento proxy oficial",
read_the: "Leia o",
apollotv_privacy_policy: "ApolloTV Política de Privacidade",
contact_us: "Contate-Nos",
connect: "Conectar",
disconnect: "Desconectar",
start: "Começar",
stop: "Pare"
};

90
lang/tr-TR.js Normal file
View File

@@ -0,0 +1,90 @@
export default {
home: "Ana Sayfa",
realtime: "Realtime",
graphql: "GraphQL",
settings: "Ayarlar",
request: "İstek",
install_pwa: "PWA yükle",
support_us: "Bize destek ol",
tweet: "Tweet",
options: "Options",
communication: "İletişim",
endpoint: "Endpoint",
schema: "Taslak",
theme: "Tema",
subscribe: "Abonelik",
choose_language: "Dil seç",
shortcuts: "Kısayollar",
send_request: "İstek gönder",
save_to_collections: "Koleksiyonları kaydet",
copy_request_link: "İstek adresini kopyala",
reset_request: "İstekleri resetle",
support_us_on: "Bizi destekle",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript code",
method: "Metot",
path: "Yol",
label: "Etiket",
again: "Yeniden",
content_type: "İçerik tipi",
raw_input: "Raw giriş",
parameter_list: "Parametre listesi",
raw_request_body: "Raw istek içeriği",
show_code: "Kodu göster",
hide_code: "Kodu gizle",
show_prerequest_script: "Pre-Request scriptini göster",
hide_prerequest_script: "Pre-Request scriptini gizle",
authentication: "Authentication",
authentication_type: "Authentication tipi",
include_in_url: "URL'den içeri aktar",
parameters: "Parametre",
expand_response: "Cevabı genişlet",
collapse_response: "Cevap daralt",
hide_preview: "Görüntülemeyi gizle",
preview_html: "HTML formatında görüntüle",
history: "Geçmiş",
collections: "Koleksiyonlar",
import_curl: "cURL içeri aktar",
import: "İçeri Aktar",
generate_code: "Kod Üret",
request_type: "Request tipi",
generated_code: "Üretilen Kod",
status: "Durum",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(esperando por conexión)",
message: "Mesaj",
sse: "SSE",
server: "Server",
events: "Events",
url: "URL",
get_schema: "Taslak",
header_list: "Header listesi",
add_new: "Yeni Ekle",
response: "Cevap",
query: "Sorgu",
queries: "Sorgular",
query_variables: "Değişkenler",
mutations: "Değişimler",
subscriptions: "Aboneler",
types: "Tipler",
send: "Gönder",
background: "Arka Plan",
color: "Renk",
labels: "Etiketler",
multi_color: "Çoklu renk",
enabled: "Aktif",
disabled: "Aktif değil",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
read_the: "Leer la",
apollotv_privacy_policy: "ApolloTV gizlilik politikaları",
contact_us: "Bizimle iletişime geçin",
connect: "Bağlan",
disconnect: "Kesmek",
start: "Başla",
stop: "Durdurmak"
};

89
lang/zh-CN.js Normal file
View File

@@ -0,0 +1,89 @@
export default {
home: "主页",
realtime: "长连接",
graphql: "GraphQL",
settings: "设置",
request: "请求",
install_pwa: "安装PWA应用",
support_us: "支持我们",
tweet: "推特",
options: "选项",
communication: "联系我们",
endpoint: "服务端点",
schema: "模式",
theme: "主题",
subscribe: "订阅",
choose_language: "选择语言",
shortcuts: "快捷键",
send_request: "发送请求",
save_to_collections: "保存到收藏夹",
copy_request_link: "复制请求链接",
reset_request: "重置请求",
support_us_on: "支持我们",
open_collective: "Open Collective",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "JavaScript代码",
method: "方法",
path: "路径",
label: "标签",
again: "重试",
content_type: "内容类型",
raw_input: "raw数据",
parameter_list: "参数列表",
raw_request_body: "raw请求主体",
show_code: "显示代码",
hide_code: "隐藏代码",
show_prerequest_script: "显示预请求脚本",
hide_prerequest_script: "隐藏预请求脚本",
authentication: "认证方式",
authentication_type: "认证类型",
include_in_url: "包含在URL中",
parameters: "参数",
expand_response: "展开显示响应内容",
collapse_response: "折叠显示响应内容",
hide_preview: "隐藏预览",
preview_html: "预览HTML",
history: "历史记录",
collections: "收藏夹",
import_curl: "批量导入",
import: "导入",
generate_code: "生成代码",
request_type: "请求类型",
generated_code: "生成的代码",
status: "状态码",
headers: "请求头",
websocket: "Websocket",
waiting_for_connection: "(等待连接)",
message: "消息内容",
sse: "SSE",
server: "Server",
events: "事件",
url: "地址",
get_schema: "获取模式",
header_list: "请求头列表",
add_new: "添加",
response: "响应",
query: "查询",
queries: "查询",
query_variables: "变数",
mutations: "Mutations",
subscriptions: "订阅",
types: "种类",
send: "发送",
background: "背景",
color: "颜色",
labels: "标签",
multi_color: "彩色",
enabled: "已启用",
disabled: "已禁用",
proxy: "代理",
postwoman_official_proxy_hosting: "Postwoman的官方代理由ApolloTV托管",
read_the: "阅读",
apollotv_privacy_policy: "ApolloTV隐私政策",
contact_us: "联系我们",
connect: "连接",
disconnect: "断开",
start: "开始",
stop: "停止"
};

View File

@@ -1,21 +1,5 @@
<template>
<div class="wrapper">
<header class="header">
<div>
<div class="slide-in">
<nuxt-link to="/">
<h1 class="logo">Postwoman</h1>
</nuxt-link>
<h3 class="tagline">API request builder</h3>
</div>
<a href="https://github.com/liyasthomas/postwoman" target="_blank" rel="noopener">
<button class="icon">
<img id="imgGitHub" src="~static/icons/github.svg" alt="GitHub" :style="logoStyle()" />
<span>GitHub</span>
</button>
</a>
</div>
</header>
<div class="content">
<div class="columns">
<aside class="nav-first">
@@ -24,82 +8,252 @@
We're using manual checks for linkActive because the query string
seems to mess up the nuxt-link active class.
-->
<nuxt-link to="/" :class="linkActive('/')" v-tooltip.right="'Home'" aria-label="Home">
<logo alt style="height: 24px;"></logo>
</nuxt-link>
<nuxt-link
to="/websocket"
:class="linkActive('/websocket')"
v-tooltip.right="'WebSocket'"
:to="localePath('index')"
:class="linkActive('/')"
v-tooltip.right="$t('home')"
:aria-label="$t('home')"
>
<i class="material-icons">cloud</i>
<logo alt class="material-icons" style="height: 24px;"></logo>
</nuxt-link>
<nuxt-link
to="/settings"
:to="localePath('realtime')"
:class="linkActive('/realtime')"
v-tooltip.right="$t('realtime')"
>
<i class="material-icons">settings_input_hdmi</i>
</nuxt-link>
<nuxt-link
:to="localePath('graphql')"
:class="linkActive('/graphql')"
v-tooltip.right="$t('graphql')"
:aria-label="$t('graphql')"
>
<svg
class="material-icons"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
viewBox="0 0 400 400"
>
<g>
<g>
<g>
<rect
x="122"
y="-0.4"
transform="matrix(-0.866 -0.5 0.5 -0.866 163.3196 363.3136)"
width="16.6"
height="320.3"
/>
</g>
</g>
<g>
<g>
<rect x="39.8" y="272.2" width="320.3" height="16.6" />
</g>
</g>
<g>
<g>
<rect
x="37.9"
y="312.2"
transform="matrix(-0.866 -0.5 0.5 -0.866 83.0693 663.3409)"
width="185"
height="16.6"
/>
</g>
</g>
<g>
<g>
<rect
x="177.1"
y="71.1"
transform="matrix(-0.866 -0.5 0.5 -0.866 463.3409 283.0693)"
width="185"
height="16.6"
/>
</g>
</g>
<g>
<g>
<rect
x="122.1"
y="-13"
transform="matrix(-0.5 -0.866 0.866 -0.5 126.7903 232.1221)"
width="16.6"
height="185"
/>
</g>
</g>
<g>
<g>
<rect
x="109.6"
y="151.6"
transform="matrix(-0.5 -0.866 0.866 -0.5 266.0828 473.3766)"
width="320.3"
height="16.6"
/>
</g>
</g>
<g>
<g><rect x="52.5" y="107.5" width="16.6" height="185" /></g>
</g>
<g>
<g>
<rect x="330.9" y="107.5" width="16.6" height="185" />
</g>
</g>
<g>
<g>
<rect
x="262.4"
y="240.1"
transform="matrix(-0.5 -0.866 0.866 -0.5 126.7953 714.2875)"
width="14.5"
height="160.9"
/>
</g>
</g>
<path
d="M369.5,297.9c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8C373.5,259.9,379.2,281.2,369.5,297.9"
/>
<path
d="M90.9,137c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8C94.8,99,100.5,120.3,90.9,137"
/>
<path
d="M30.5,297.9c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6,16.7,3.9,38-12.8,47.7C61.4,320.3,40.1,314.6,30.5,297.9"
/>
<path
d="M309.1,137c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6,16.7,3.9,38-12.8,47.7C340.1,159.4,318.7,153.7,309.1,137"
/>
<path
d="M200,395.8c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9C234.9,380.1,219.3,395.8,200,395.8"
/>
<path
d="M200,74c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9C234.9,58.4,219.3,74,200,74"
/>
</g>
</svg>
</nuxt-link>
<nuxt-link
:to="localePath('doc')"
:class="linkActive('/doc')"
v-tooltip.right="$t('documentation')"
:aria-label="$t('documentation')"
>
<i class="material-icons">books</i>
</nuxt-link>
<nuxt-link
:to="localePath('settings')"
:class="linkActive('/settings')"
v-tooltip.right="'Settings'"
aria-label="Settings"
v-tooltip.right="$t('settings')"
:aria-label="$t('settings')"
>
<i class="material-icons">settings</i>
</nuxt-link>
</nav>
<div v-if="['/'].includes($route.path)">
<div v-if="$route.path === '/'">
<nav class="secondary-nav">
<ul>
<li>
<a href="#request" v-tooltip.right="'Request'">
<a href="#request" v-tooltip.right="$t('request')">
<i class="material-icons">cloud_upload</i>
</a>
</li>
<li>
<a href="#options" v-tooltip.right="'Options'">
<a href="#options" v-tooltip.right="$t('options')">
<i class="material-icons">toc</i>
</a>
</li>
<li>
<a href="#response" v-tooltip.right="'Response'">
<a href="#response" v-tooltip.right="$t('response')">
<i class="material-icons">cloud_download</i>
</a>
</li>
<li>
<a href="#collections" v-tooltip.right="'Collections'">
<i class="material-icons">folder_special</i>
</a>
</li>
<li>
<a href="#history" v-tooltip.right="'History'">
<i class="material-icons">watch_later</i>
</a>
</li>
</ul>
</nav>
</div>
<div v-else-if="['/websocket'].includes($route.path)">
<div v-else-if="$route.path === '/realtime'">
<nav class="secondary-nav">
<ul>
<li>
<a href="#request" v-tooltip.right="'Request'">
<a href="#request" v-tooltip.right="$t('request')">
<i class="material-icons">cloud_upload</i>
</a>
</li>
<li>
<a href="#response" v-tooltip.right="'Response'">
<a href="#response" v-tooltip.right="$t('communication')">
<i class="material-icons">cloud_download</i>
</a>
</li>
</ul>
</nav>
</div>
<div v-else-if="['/settings'].includes($route.path)">
<div v-else-if="$route.path === '/graphql'">
<nav class="secondary-nav">
<ul>
<li>
<a href="#theme" v-tooltip.right="'Theme'">
<a href="#endpoint" v-tooltip.right="$t('endpoint')">
<i class="material-icons">cloud</i>
</a>
</li>
<li>
<a href="#schema" v-tooltip.right="$t('schema')">
<i class="material-icons">assignment_returned</i>
</a>
</li>
<li>
<a href="#query" v-tooltip.right="$t('query')">
<i class="material-icons">cloud_upload</i>
</a>
</li>
<li>
<a href="#response" v-tooltip.right="$t('response')">
<i class="material-icons">cloud_download</i>
</a>
</li>
</ul>
</nav>
</div>
<div v-else-if="$route.path === '/doc'">
<nav class="secondary-nav">
<ul>
<li>
<a href="#collections" v-tooltip.right="$t('collections')">
<i class="material-icons">folder</i>
</a>
</li>
<li>
<a href="#documentation" v-tooltip.right="'Documentation'">
<i class="material-icons">insert_drive_file</i>
</a>
</li>
</ul>
</nav>
</div>
<div v-else-if="$route.path === '/settings'">
<nav class="secondary-nav">
<ul>
<li>
<a href="#account" v-tooltip.right="$t('account')">
<i class="material-icons">person</i>
</a>
</li>
<li>
<a href="#theme" v-tooltip.right="$t('theme')">
<i class="material-icons">brush</i>
</a>
</li>
<li>
<a href="#proxy" v-tooltip.right="'Proxy'">
<a href="#extensions" v-tooltip.right="$t('extensions')">
<i class="material-icons">extensions</i>
</a>
</li>
<li>
<a href="#proxy" v-tooltip.right="$t('proxy')">
<i class="material-icons">public</i>
</a>
</li>
@@ -107,74 +261,467 @@
</nav>
</div>
</aside>
<nuxt id="main" class="main" />
<aside class="nav-second"></aside>
</div>
</div>
<footer class="footer">
<!-- Top section of footer: GitHub/install links -->
<div class="main" id="main">
<header class="header">
<div class="flex-wrap">
<button class="icon" id="installPWA" @click.prevent="showInstallPrompt()">
<i class="material-icons">add_to_home_screen</i>
<span>Install PWA</span>
<span class="slide-in">
<nuxt-link :to="localePath('index')">
<h1 class="logo">Postwoman</h1>
</nuxt-link>
</span>
<span>
<a
href="https://github.com/liyasthomas/postwoman"
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"
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>
</button>
</a>
<button
class="icon"
onClick="window.open('https://twitter.com/share?text=👽 Postwoman • API request builder - Helps you create your requests faster, saving you precious time on your development&url=https://postwoman.io&hashtags=postwoman&via=liyasthomas');"
id="installPWA"
@click.prevent="showInstallPrompt()"
v-tooltip="$t('install_pwa')"
>
<i class="material-icons">offline_bolt</i>
</button>
<login v-if="!fb.currentUser" />
<span v-if="fb.currentUser">
<v-popover>
<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="material-icons"
alt="Profile image"
/>
<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>
<button class="icon" @click="logout" v-close-popover>
<i class="material-icons">exit_to_app</i>
<span>{{ $t("logout") }}</span>
</button>
</div>
</template>
</v-popover>
</span>
<v-popover>
<button class="icon" v-tooltip="$t('more')">
<i class="material-icons">more_vert</i>
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="showExtensions = true"
v-close-popover
>
<i class="material-icons">extension</i>
<span>{{ $t("extensions") }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="showShortcuts = true"
v-close-popover
>
<i class="material-icons">keyboard</i>
<span>{{ $t("shortcuts") }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="showSupport = true"
v-close-popover
>
<i class="material-icons">favorite</i>
<span>{{ $t("support_us") }}</span>
</button>
</div>
<div>
<button
class="icon"
onClick="window.open('https://twitter.com/share?text=👽 Postwoman • A free, fast and beautiful API request builder - Web alternative to Postman - Helps you create requests faster, saving precious time on development.&url=https://postwoman.io&hashtags=postwoman&via=liyasthomas');"
v-close-popover
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path
d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"
/>
</svg>
<span>Tweet</span>
<span>{{ $t("tweet") }}</span>
</button>
<button
v-if="navigatorShare"
class="icon"
@click="nativeShare"
v-close-popover
v-tooltip="$t('more')"
>
<i class="material-icons">share</i>
</button>
</div>
<!-- Bottom section of footer: version/author information -->
<p class="align-center">
<span v-if="version.name">
</template>
</v-popover>
</span>
</div>
</header>
<nuxt />
<footer class="footer">
<div class="flex-wrap">
<span v-if="version.name" class="mono">
<a
v-bind:href="'https://github.com/liyasthomas/postwoman/releases/tag/' + version.name"
class="footer-link"
:href="
'https://github.com/liyasthomas/postwoman/releases/tag/' +
version.name
"
target="_blank"
rel="noopener"
>{{version.name}}</a>
<span v-if="version.hash">
v-tooltip="'GitHub'"
>
{{ version.name }}
</a>
<a
class="footer-link hide-on-small-screen"
href="https://www.netlify.com"
target="_blank"
rel="noopener"
>
Powered by Netlify
</a>
<!-- <span v-if="version.hash">
-
<a
v-bind:href="'https://github.com/liyasthomas/postwoman/commit/' + version.hash"
:href="'https://github.com/liyasthomas/postwoman/commit/' + version.hash"
target="_blank"
rel="noopener"
>{{version.hash}}</a>
</span> -->
<!-- <span v-if="version.variant">({{version.variant}})</span> -->
</span>
<span v-if="version.variant">({{version.variant}})</span>
&#x2022;
</span> by
<a href="https://liyasthomas.web.app" target="_blank" rel="noopener">Liyas Thomas 🦄</a> &#x2022;
<a href="https://postwoman.launchaco.com" target="_blank" rel="noopener">Subscribe</a>
</p>
<span>
<a
href="https://liyasthomas.web.app"
target="_blank"
rel="noopener"
>
<button class="icon" v-tooltip="'Liyas Thomas'">
🦄
</button>
</a>
<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>
</div>
</template>
</v-popover>
</span>
</div>
</footer>
</div>
<aside class="nav-second"></aside>
</div>
</div>
<modal v-if="showExtensions" @close="showExtensions = false">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("extensions") }}</h3>
<div>
<button class="icon" @click="showExtensions = false">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<p class="info">
{{ $t("extensions_info1") }}
</p>
<div>
<a
href="https://addons.mozilla.org/en-US/firefox/addon/postwoman"
target="_blank"
rel="noopener"
>
<button class="icon">
<svg
class="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm8.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.181 1.832-2.066 4.499-3.378 7.472-3.378 5.912 0 8.263 4.283 8.003 6.657z"
/>
</svg>
<span>Firefox</span>
<span
class="icon"
v-if="firefoxExtInstalled"
v-tooltip="$t('installed')"
>
<i class="material-icons">done</i>
</span>
</button>
</a>
</div>
<div>
<a
href="https://chrome.google.com/webstore/detail/postwoman-extension-for-c/amknoiejhlmhancpahfcfcfhllgkpbld"
target="_blank"
rel="noopener"
>
<button class="icon">
<svg
class="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
d="M2.897 4.181c2.43-2.828 5.763-4.181 9.072-4.181 4.288 0 8.535 2.273 10.717 6.554-2.722.001-6.984 0-9.293 0-1.674.001-2.755-.037-3.926.579-1.376.724-2.415 2.067-2.777 3.644l-3.793-6.596zm5.11 7.819c0 2.2 1.789 3.99 3.988 3.99s3.988-1.79 3.988-3.99-1.789-3.991-3.988-3.991-3.988 1.791-3.988 3.991zm5.536 5.223c-2.238.666-4.858-.073-6.293-2.549-1.095-1.891-3.989-6.933-5.305-9.225-1.33 2.04-1.945 4.294-1.945 6.507 0 5.448 3.726 10.65 9.673 11.818l3.87-6.551zm2.158-9.214c1.864 1.734 2.271 4.542 1.007 6.719-.951 1.641-3.988 6.766-5.46 9.248 7.189.443 12.752-5.36 12.752-11.972 0-1.313-.22-2.66-.69-3.995h-7.609z"
/>
</svg>
<span>Chrome</span>
<span
class="icon"
v-if="chromeExtInstalled"
v-tooltip="$t('installed')"
>
<i class="material-icons">done</i>
</span>
</button>
</a>
</div>
</div>
<div slot="footer"></div>
</modal>
<modal v-if="showShortcuts" @close="showShortcuts = false">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("shortcuts") }}</h3>
<div>
<button class="icon" @click="showShortcuts = false">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<div>
<label>{{ $t("send_request") }}</label>
<kbd>{{ getSpecialKey() }} G</kbd>
</div>
<div>
<label>{{ $t("save_to_collections") }}</label>
<kbd>{{ getSpecialKey() }} S</kbd>
</div>
<div>
<label>{{ $t("copy_request_link") }}</label>
<kbd>{{ getSpecialKey() }} K</kbd>
</div>
<div>
<label>{{ $t("reset_request") }}</label>
<kbd>{{ getSpecialKey() }} L</kbd>
</div>
</div>
<div slot="footer"></div>
</modal>
<modal v-if="showSupport" @close="showSupport = false">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("support_us_on") }}</h3>
<div>
<button class="icon" @click="showSupport = false">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<p class="info">
{{ $t("donate_info1") }}
</p>
<p class="info">
{{ $t("donate_info2") }}
</p>
<div>
<a
href="https://opencollective.com/postwoman"
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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
</div>
<div slot="footer"></div>
</modal>
</div>
</template>
<style lang="scss">
<style scoped lang="scss">
.footer-link {
margin: 8px 16px;
}
</style>
<script>
import intializePwa from "../assets/js/pwa";
import logo from "../components/logo";
import * as version from "../.postwoman/version.json";
import { hasExtensionInstalled } from "../functions/strategies/ExtensionStrategy";
import firebase from "firebase/app";
import { fb } from "../functions/fb";
export default {
components: {
logo
logo: () => import("../components/logo"),
modal: () => import("../components/modal"),
login: () => import("../components/firebase/login")
},
methods: {
getSpecialKey() {
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl";
},
linkActive(path) {
return {
"nuxt-link-exact-active": this.$route.path === path,
"nuxt-link-active": this.$route.path === path
};
},
logout() {
fb.currentUser = null;
firebase
.auth()
.signOut()
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
this.$toast.info(this.$t("logged_out"), {
icon: "vpn_key"
});
},
nativeShare() {
if (navigator.share) {
navigator
.share({
title: "Postwoman",
text:
"Postwoman • A free, fast and beautiful API request builder - Web alternative to Postman - Helps you create requests faster, saving precious time on development.",
url: "https://postwoman.io/"
})
.then(() => {})
.catch(console.error);
} else {
// fallback
}
}
},
@@ -184,15 +731,13 @@
// that can be called to show the user the installation
// prompt.
showInstallPrompt: null,
logoStyle() {
return (
this.$store.state.postwoman.settings.THEME_CLASS || ""
).includes("light")
? " filter: invert(100%); -webkit-filter: invert(100%);"
: "";
},
version: {}
version: {},
showExtensions: false,
showShortcuts: false,
showSupport: false,
extensionInstalled: hasExtensionInstalled(),
fb,
navigatorShare: navigator.share
};
},
@@ -207,12 +752,12 @@
this.$store.state.postwoman.settings.THEME_CLASS || "";
// Load theme color data from settings, or use default color.
let color = this.$store.state.postwoman.settings.THEME_COLOR || "#50fa7b";
let vibrant = this.$store.state.postwoman.settings.THEME_COLOR_VIBRANT;
if (vibrant == null) vibrant = true;
let vibrant =
this.$store.state.postwoman.settings.THEME_COLOR_VIBRANT || true;
document.documentElement.style.setProperty("--ac-color", color);
document.documentElement.style.setProperty(
"--act-color",
vibrant ? "rgb(37, 38, 40)" : "#ffffff"
vibrant ? "rgba(32, 33, 36, 1)" : "rgba(255, 255, 255, 1)"
);
})();
},
@@ -226,7 +771,7 @@
.querySelector("meta[name=theme-color]")
.setAttribute(
"content",
this.$store.state.postwoman.settings.THEME_TAB_COLOR || "#252628"
this.$store.state.postwoman.settings.THEME_TAB_COLOR || "#202124"
);
// Initializes the PWA code - checks if the app is installed,
@@ -235,13 +780,13 @@
this.showInstallPrompt = await intializePwa();
let cookiesAllowed = localStorage.getItem("cookiesAllowed") === "yes";
if (!cookiesAllowed) {
this.$toast.show("We use cookies", {
this.$toast.show(this.$t("we_use_cookies"), {
icon: "info",
duration: 5000,
theme: "toasted-primary",
action: [
{
text: "Dismiss",
text: this.$t("dismiss"),
onClick: (e, toastObject) => {
localStorage.setItem("cookiesAllowed", "yes");
toastObject.goAway(0);
@@ -250,6 +795,44 @@
]
});
}
let showExtensionsToast =
localStorage.getItem("showExtensionsToast") === "yes";
if (
!this.extensionInstalled &&
!showExtensionsToast
) {
setTimeout(() => {
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) => {
toastObject.goAway(0);
}
}
]
});
}, 15000);
}
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("scroll", event => {
@@ -259,6 +842,7 @@
let section = document.querySelector(link.hash);
if (
section &&
section.offsetTop <= fromTop &&
section.offsetTop + section.offsetHeight > fromTop
) {
@@ -268,12 +852,31 @@
}
});
});
console.log(
"%cWe ❤︎ open source!",
"background-color:white;padding:8px 16px;border-radius:8px;font-size:32px;color:red;"
);
console.log(
"%cContribute: https://github.com/liyasthomas/postwoman",
"background-color:black;padding:4px 8px;border-radius:8px;font-size:16px;color:white;"
);
},
watch: {
$route() {
this.$toast.clear();
// this.$toast.clear();
}
},
computed: {
availableLocales() {
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale);
}
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
</script>

View File

@@ -1,20 +1,24 @@
<template>
<div class="page page-error">
<img src="~static/icons/error.svg" alt="Error" class="error_banner" />
<img
src="~static/icons/error.svg"
:alt="$t('error')"
class="error_banner"
/>
<h2>{{ error.statusCode }}</h2>
<h3>{{ error.message }}</h3>
<p>
<nuxt-link to="/">
<button>Go Home</button>
<button>{{ $t("go_home") }}</button>
</nuxt-link>
</p>
<p>
<a href @click.prevent="reloadApplication">Reload</a>
<a href @click.prevent="reloadApplication">{{ $t("reload") }}</a>
</p>
</div>
</template>
<style lang="scss">
<style scoped lang="scss">
// Center the error page in the viewport.
.page-error {
display: flex;

View File

@@ -1,8 +1,5 @@
export default function ({
route,
redirect
}) {
if (route.fullPath !== '/') {
return redirect('/');
export default function({ route, redirect }) {
if (route.fullPath !== "/") {
return redirect("/");
}
}

View File

@@ -2,51 +2,65 @@
// TODO: Use these when rendering the pages (rather than just for head/meta tags...)
export const meta = {
name: "Postwoman",
shortDescription: "API request builder",
description: "The Postwoman API request builder helps you create your requests faster, saving you precious time on your development."
shortDescription: "A free, fast and beautiful API request builder",
description:
"Web alternative to Postman - Helps you create requests faster, saving precious time on development."
};
// Sets the base path for the router.
// Important for deploying to GitHub pages.
// -- Travis includes the author in the repo slug,
// so if there's a /, we need to get everything after it.
let repoName = (process.env.TRAVIS_REPO_SLUG || '').split('/').pop();
export const routerBase = process.env.DEPLOY_ENV === 'GH_PAGES' ? {
let repoName = (process.env.TRAVIS_REPO_SLUG || "").split("/").pop();
export const routerBase =
process.env.DEPLOY_ENV === "GH_PAGES"
? {
router: {
base: `/${repoName}/`
}
} : {
}
: {
router: {
base: '/'
base: "/"
}
};
export default {
mode: 'spa',
mode: "spa",
/*
** Headers of the page
*/
server: {
host: '0.0.0.0', // default: localhost
host: "0.0.0.0" // default: localhost
},
render: {
bundleRenderer: {
shouldPreload: (file, type) => {
return ["script", "style", "font"].includes(type);
}
}
},
head: {
title: `${meta.name} \u2022 ${meta.shortDescription}`,
meta: [{
charset: 'utf-8'
meta: [
{
charset: "utf-8"
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no, minimal-ui'
name: "viewport",
content:
"width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover, minimal-ui"
},
{
hid: 'description',
name: 'description',
content: meta.description || ''
hid: "description",
name: "description",
content: meta.description || ""
},
{
name: 'keywords',
content: 'postwoman, postwoman chrome, postwoman online, postwoman for mac, postwoman app, postwoman for windows, postwoman google chrome, postwoman chrome app, get postwoman, postwoman web, postwoman android, postwoman app for chrome, postwoman mobile app, postwoman web app, api, request, testing, tool, rest, websocket'
name: "keywords",
content:
"postwoman, postwoman chrome, postwoman online, postwoman for mac, postwoman app, postwoman for windows, postwoman google chrome, postwoman chrome app, get postwoman, postwoman web, postwoman android, postwoman app for chrome, postwoman mobile app, postwoman web app, api, request, testing, tool, rest, websocket, sse, graphql"
},
{
name: 'X-UA-Compatible',
name: "X-UA-Compatible",
content: "IE=edge, chrome=1"
},
{
@@ -59,156 +73,158 @@ export default {
},
{
itemprop: "image",
content: `${routerBase.router.base}icons/icon-192x192.png`
content: `https://postwoman.io/logo.jpg`
},
// Add to homescreen for Chrome on Android. Fallback for PWA (handled by nuxt)
{
name: 'application-name',
name: "application-name",
content: meta.name
},
// Add to homescreen for Safari on iOS
{
name: 'apple-mobile-web-app-capable',
content: 'yes'
name: "apple-mobile-web-app-capable",
content: "yes"
},
{
name: 'apple-mobile-web-app-status-bar-style',
content: 'black-translucent'
name: "apple-mobile-web-app-status-bar-style",
content: "black-translucent"
},
{
name: 'apple-mobile-web-app-title',
name: "apple-mobile-web-app-title",
content: meta.name
},
// Windows phone tile icon
{
name: 'msapplication-TileImage',
name: "msapplication-TileImage",
content: `${routerBase.router.base}icons/icon-144x144.png`
},
{
name: 'msapplication-TileColor',
content: '#252628'
name: "msapplication-TileColor",
content: "#202124"
},
{
name: 'msapplication-tap-highlight',
content: 'no'
name: "msapplication-tap-highlight",
content: "no"
},
// OpenGraph
{
property: 'og:site_name',
property: "og:site_name",
content: meta.name
},
{
property: 'og:url',
content: 'https://postwoman.io'
},
{
property: 'og:type',
content: 'website'
},
{
property: 'og:title',
content: `${meta.name} \u2022 ${meta.shortDescription}`
},
{
property: 'og:description',
content: meta.description
},
{
property: 'og:image',
content: `${routerBase.router.base}icons/icon-144x144.png`
},
// Twitter
{
name: 'twitter:card',
content: "summary"
},
{
name: 'twitter:site',
content: "@liyasthomas"
},
{
name: 'twitter:creator',
content: "@liyasthomas"
},
{
name: 'twitter:url',
property: "og:url",
content: "https://postwoman.io"
},
{
name: 'twitter:title',
content: meta.name
property: "og:type",
content: "website"
},
{
name: 'twitter:description',
content: meta.shortDescription
property: "og:title",
content: `${meta.name} \u2022 ${meta.shortDescription}`
},
{
name: 'twitter:image',
content: `${routerBase.router.base}icons/icon-144x144.png`
property: "og:description",
content: meta.description
},
{
property: "og:image",
content: `https://postwoman.io/logo.jpg`
},
// Twitter
{
name: "twitter:card",
content: "summary_large_image"
},
{
name: "twitter:site",
content: "@liyasthomas"
},
{
name: "twitter:creator",
content: "@liyasthomas"
},
{
name: "twitter:url",
content: "https://postwoman.io"
},
{
name: "twitter:title",
content: `${meta.name} \u2022 ${meta.shortDescription}`
},
{
name: "twitter:description",
content: meta.description
},
{
name: "twitter:image",
content: "https://postwoman.io/logo.jpg"
}
],
link: [{
rel: 'icon',
type: 'image/x-icon',
link: [
{
rel: "icon",
type: "image/x-icon",
href: `${routerBase.router.base}favicon.ico`
},
// Home-screen icons (iOS)
{
rel: 'apple-touch-icon',
rel: "apple-touch-icon",
href: `${routerBase.router.base}icons/icon-48x48.png`
},
{
rel: 'apple-touch-icon',
sizes: '72x72',
rel: "apple-touch-icon",
sizes: "72x72",
href: `${routerBase.router.base}icons/icon-72x72.png`
},
{
rel: 'apple-touch-icon',
sizes: '96x96',
rel: "apple-touch-icon",
sizes: "96x96",
href: `${routerBase.router.base}icons/icon-96x96.png`
},
{
rel: 'apple-touch-icon',
sizes: '144x144',
rel: "apple-touch-icon",
sizes: "144x144",
href: `${routerBase.router.base}icons/icon-144x144.png`
},
{
rel: 'apple-touch-icon',
sizes: '192x192',
rel: "apple-touch-icon",
sizes: "192x192",
href: `${routerBase.router.base}icons/icon-192x192.png`
},
}
]
},
/*
** Customize the progress-bar color
*/
loading: {
color: 'var(--ac-color)'
color: "var(--ac-color)"
},
/*
** Customize the loading indicator
*/
loadingIndicator: {
name: 'pulse',
color: 'var(--ac-color)',
background: 'var(--bg-color)'
name: "pulse",
color: "var(--ac-color)",
background: "var(--bg-color)"
},
/*
** Global CSS
*/
css: [
'@/assets/css/themes.scss',
'@/assets/css/fonts.scss',
'@/assets/css/styles.scss'
"~/assets/css/styles.scss",
"~/assets/css/themes.scss",
"~/assets/css/fonts.scss"
],
/*
** Plugins to load before mounting the App
*/
plugins: [{
src: '~/plugins/vuex-persist'
plugins: [
{
src: "~/plugins/vuex-persist"
},
{
src: '~/plugins/v-tooltip'
src: "~/plugins/v-tooltip"
}
],
/*
@@ -220,15 +236,19 @@ export default {
*/
modules: [
// See https://goo.gl/OOhYW5
['@nuxtjs/pwa'],
['@nuxtjs/axios'],
['@nuxtjs/toast'],
['@nuxtjs/google-analytics'],
['@nuxtjs/sitemap'],
['@nuxtjs/google-tag-manager', {
id: process.env.GTM_ID || 'GTM-MXWD8NQ'
}],
['@nuxtjs/robots']
["@nuxtjs/pwa"],
["@nuxtjs/axios"],
["@nuxtjs/toast"],
["@nuxtjs/google-analytics"],
["@nuxtjs/sitemap"],
[
"@nuxtjs/google-tag-manager",
{
id: process.env.GTM_ID || "GTM-MXWD8NQ"
}
],
["@nuxtjs/robots"],
["nuxt-i18n"]
],
pwa: {
manifest: {
@@ -237,45 +257,115 @@ export default {
display: "standalone",
theme_color: "#252628",
background_color: "#252628",
theme_color: "#202124",
background_color: "#202124",
start_url: `${routerBase.router.base}`
},
meta: {
description: meta.shortDescription,
theme_color: "#252628",
theme_color: "#202124"
},
icons: ((sizes) => {
icons: (sizes => {
let icons = [];
for (let size of sizes) {
icons.push({
"src": `${routerBase.router.base}icons/icon-${size}x${size}.png`,
"type": "image/png",
"sizes": `${size}x${size}`
src: `${routerBase.router.base}icons/icon-${size}x${size}.png`,
type: "image/png",
sizes: `${size}x${size}`
});
}
return icons;
})([48, 72, 96, 144, 192, 512])
},
toast: {
position: 'bottom-center',
position: "bottom-center",
duration: 3000,
theme: 'bubble',
theme: "bubble",
keepOnHover: true
},
googleAnalytics: {
id: process.env.GA_ID || 'UA-61422507-2'
id: process.env.GA_ID || "UA-61422507-2"
},
sitemap: {
hostname: 'https://postwoman.io'
hostname: "https://postwoman.io"
},
robots: {
UserAgent: '*',
Disallow: '',
Allow: '/',
Sitemap: 'https://postwoman.io/sitemap.xml'
UserAgent: "*",
Disallow: "",
Allow: "/",
Sitemap: "https://postwoman.io/sitemap.xml"
},
i18n: {
locales: [
{
code: "en",
name: "English",
iso: "en-US",
file: "en-US.js"
},
{
code: "es",
name: "Español",
iso: "es-ES",
file: "es-ES.js"
},
{
code: "fr",
name: "Français",
iso: "fr-FR",
file: "fr-FR.js"
},
{
code: "fa",
name: "Farsi",
iso: "fa-IR",
file: "fa-IR.js"
},
{
code: "pt",
name: "Português Brasileiro",
iso: "pt-BR",
file: "pt-BR.js"
},
{
code: "cn",
name: "简体中文",
iso: "zh-CN",
file: "zh-CN.js"
},
{
code: "id",
name: "Bahasa Indonesia",
iso: "id-ID",
file: "id-ID.js"
},
{
code: "tr",
name: "Türkçe",
iso: "tr-TR",
file: "tr-TR.js"
},
{
code: "de",
name: "Deutsch",
iso: "de-DE",
file: "de-DE.js"
},
{
code: "ja",
name: "日本語",
iso: "ja-JP",
file: "ja-JP.js"
}
],
defaultLocale: "en",
vueI18n: {
fallbackLocale: "en"
},
lazy: true,
langDir: "lang/"
},
/*
** Build configuration
@@ -296,4 +386,4 @@ export default {
** Router configuration
*/
...routerBase
}
};

5041
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "postwoman",
"version": "1.0.0",
"description": "A free, fast, and beautiful API request builder",
"version": "1.9.0",
"description": "A free, fast and beautiful API request builder",
"author": "liyasthomas",
"private": true,
"scripts": {
@@ -14,29 +14,34 @@
"generate": "nuxt generate",
"e2e": "cypress run",
"e2e:open": "cypress open",
"dev:e2e": "start-server-and-test dev http://localhost:3000 e2e:open",
"test": "start-server-and-test dev http://localhost:3000 e2e"
"dev:e2e": "server-test dev :3000 e2e:open",
"test": "start-server-and-test start http-get://localhost:3000 e2e"
},
"dependencies": {
"@nuxtjs/axios": "^5.8.0",
"@nuxtjs/google-analytics": "^2.2.1",
"@nuxtjs/axios": "^5.9.5",
"@nuxtjs/google-analytics": "^2.2.3",
"@nuxtjs/google-tag-manager": "^2.3.1",
"@nuxtjs/pwa": "^3.0.0-beta.19",
"@nuxtjs/pwa": "^3.0.0-beta.20",
"@nuxtjs/robots": "^2.4.2",
"@nuxtjs/sitemap": "^2.0.0",
"@nuxtjs/sitemap": "^2.0.1",
"@nuxtjs/toast": "^3.3.0",
"highlight.js": "^9.16.2",
"nuxt": "^2.10.2",
"v-tooltip": "^2.0.2",
"vue-virtual-scroll-list": "^1.4.2",
"ace-builds": "^1.4.8",
"firebase": "^7.9.1",
"graphql": "^14.6.0",
"graphql-language-service-interface": "^2.3.3",
"nuxt": "^2.11.0",
"nuxt-i18n": "^6.5.0",
"v-tooltip": "^2.0.3",
"vue-virtual-scroll-list": "^1.4.6",
"vuefire": "^2.2.1",
"vuejs-auto-complete": "^0.9.0",
"vuex-persist": "^2.1.1",
"yargs-parser": "^16.1.0"
"vuex-persist": "^2.2.0",
"yargs-parser": "^17.0.0"
},
"devDependencies": {
"cypress": "^3.6.0",
"node-sass": "^4.13.0",
"sass-loader": "^7.3.1",
"start-server-and-test": "^1.10.6"
"cypress": "^4.0.2",
"node-sass": "^4.13.1",
"sass-loader": "^8.0.2",
"start-server-and-test": "^1.10.8"
}
}

394
pages/doc.vue Normal file
View File

@@ -0,0 +1,394 @@
<template>
<div class="page">
<pw-section class="blue" :label="$t('collections')" ref="collections">
<ul>
<li>
<p class="info">
{{ $t("generate_docs_message") }}
</p>
</li>
</ul>
<ul>
<li>
<label for="collectionUpload">
<button
class="icon"
@click="$refs.collectionUpload.click()"
v-tooltip="$t('json')"
>
<i class="material-icons">folder</i>
<span>{{ $t("import_collections") }}</span>
</button>
</label>
<input
ref="collectionUpload"
name="collectionUpload"
type="file"
@change="uploadCollection"
/>
</li>
</ul>
<ul>
<li>
<Editor
v-model="collectionJSON"
:lang="'json'"
:options="{
maxLines: '16',
minLines: '8',
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
}"
/>
</li>
</ul>
<ul>
<li>
<button class="icon" @click="getDoc">
<i class="material-icons">book</i>
<span>{{ $t("generate_docs") }}</span>
</button>
</li>
</ul>
</pw-section>
<pw-section class="green" label="Documentation" ref="documentation">
<p v-if="this.items.length === 0" class="info">
{{ $t("generate_docs_first") }}
</p>
<div>
<span
class="collection"
v-for="(collection, index) in this.items"
:key="index"
>
<h2>
<i class="material-icons">folder</i>
{{ collection.name || $t("none") }}
</h2>
<span
class="folder"
v-for="(folder, index) in collection.folders"
:key="index"
>
<h3>
<i class="material-icons">folder_open</i>
{{ folder.name || $t("none") }}
</h3>
<span
class="request"
v-for="(request, index) in folder.requests"
:key="index"
>
<h4>
<i class="material-icons">insert_drive_file</i>
{{ request.name || $t("none") }}
</h4>
<p class="doc-desc" v-if="request.url">
<span>
{{ $t("url") }}: <code>{{ request.url || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.path">
<span>
{{ $t("path") }}:
<code>{{ request.path || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.method">
<span>
{{ $t("method") }}:
<code>{{ request.method || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.auth">
<span>
{{ $t("authentication") }}:
<code>{{ request.auth || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpUser">
<span>
{{ $t("username") }}:
<code>{{ request.httpUser || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpPassword">
<span>
{{ $t("password") }}:
<code>{{ request.httpPassword || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.bearerToken">
<span>
{{ $t("token") }}:
<code>{{ request.bearerToken || $t("none") }}</code>
</span>
</p>
<h4 v-if="request.headers.length > 0">{{ $t("headers") }}</h4>
<span v-if="request.headers">
<p
v-for="header in request.headers"
:key="header.key"
class="doc-desc"
>
<span>
{{ header.key || $t("none") }}:
<code>{{ header.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.params.length > 0">{{ $t("parameters") }}</h4>
<span v-if="request.params">
<p
v-for="parameter in request.params"
:key="parameter.key"
class="doc-desc"
>
<span>
{{ parameter.key || $t("none") }}:
<code>{{ parameter.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.bodyParam">{{ $t("payload") }}</h4>
<span v-if="request.bodyParam">
<p
v-for="payload in request.bodyParam"
:key="payload.key"
class="doc-desc"
>
<span>
{{ payload.key || $t("none") }}:
<code>{{ payload.value || $t("none") }}</code>
</span>
</p>
</span>
<p class="doc-desc" v-if="request.rawParams">
<span>
{{ $t("parameters") }}:
<code>{{ request.rawParams || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.contentType">
<span>
{{ $t("content_type") }}:
<code>{{ request.contentType || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.requestType">
<span>
{{ $t("request_type") }}:
<code>{{ request.requestType || $t("none") }}</code>
</span>
</p>
</span>
</span>
<span
class="request"
v-for="(request, index) in collection.requests"
:key="`request-${index}`"
>
<h4>
<i class="material-icons">insert_drive_file</i>
{{ request.name || $t("none") }}
</h4>
<p class="doc-desc" v-if="request.url">
<span>
{{ $t("url") }}: <code>{{ request.url || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.path">
<span>
{{ $t("path") }}: <code>{{ request.path || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.method">
<span>
{{ $t("method") }}:
<code>{{ request.method || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.auth">
<span>
{{ $t("authentication") }}:
<code>{{ request.auth || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpUser">
<span>
{{ $t("username") }}:
<code>{{ request.httpUser || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpPassword">
<span>
{{ $t("password") }}:
<code>{{ request.httpPassword || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.bearerToken">
<span>
{{ $t("token") }}:
<code>{{ request.bearerToken || $t("none") }}</code>
</span>
</p>
<h4 v-if="request.headers.length > 0">{{ $t("headers") }}</h4>
<span v-if="request.headers">
<p
v-for="header in request.headers"
:key="header.key"
class="doc-desc"
>
<span>
{{ header.key || $t("none") }}:
<code>{{ header.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.params.length > 0">{{ $t("parameters") }}</h4>
<span v-if="request.params">
<p
v-for="parameter in request.params"
:key="parameter.key"
class="doc-desc"
>
<span>
{{ parameter.key || $t("none") }}:
<code>{{ parameter.value || $t("none") }}</code>
</span>
</p>
</span>
<h4 v-if="request.bodyParam">{{ $t("payload") }}</h4>
<span v-if="request.bodyParam">
<p
v-for="payload in request.bodyParam"
:key="payload.key"
class="doc-desc"
>
<span>
{{ payload.key || $t("none") }}:
<code>{{ payload.value || $t("none") }}</code>
</span>
</p>
</span>
<p class="doc-desc" v-if="request.rawParams">
<span>
{{ $t("parameters") }}:
<code>{{ request.rawParams || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.contentType">
<span>
{{ $t("content_type") }}:
<code>{{ request.contentType || $t("none") }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.requestType">
<span>
{{ $t("request_type") }}:
<code>{{ request.requestType || $t("none") }}</code>
</span>
</p>
</span>
</span>
</div>
</pw-section>
</div>
</template>
<style scoped lang="scss">
.collection,
.folder,
.request,
.doc-desc {
display: flex;
flex-flow: column;
justify-content: center;
flex: 1;
padding: 16px;
.material-icons {
margin-right: 16px;
}
}
.folder {
border-left: 1px solid var(--brd-color);
margin: 16px 0 0;
}
.request {
border: 1px solid var(--brd-color);
border-radius: 8px;
margin: 16px 0 0;
h4 {
margin: 8px 0;
}
}
.doc-desc {
color: var(--fg-light-color);
border-bottom: 1px dashed var(--brd-color);
margin: 0;
&:last-child {
border-bottom: none;
}
}
</style>
<script>
import AceEditor from "../components/ace-editor";
export default {
components: {
"pw-section": () => import("../components/section"),
Editor: AceEditor
},
data() {
return {
collectionJSON: "[]",
items: []
};
},
methods: {
uploadCollection() {
this.rawInput = true;
let file = this.$refs.collectionUpload.files[0];
if (file !== undefined && file !== null) {
let reader = new FileReader();
reader.onload = ({ target }) => {
this.collectionJSON = target.result;
};
reader.readAsText(file);
this.$toast.info(this.$t("file_imported"), {
icon: "attach_file"
});
} else {
this.$toast.error(this.$t("choose_file"), {
icon: "attach_file"
});
}
},
getDoc() {
try {
this.items = JSON.parse(this.collectionJSON);
this.$toast.info(this.$t("docs_generated"), {
icon: "book"
});
} catch (e) {
this.$toast.error(e, {
icon: "code"
});
}
}
}
};
</script>

712
pages/graphql.vue Normal file
View File

@@ -0,0 +1,712 @@
<template>
<div class="page">
<div class="content">
<div class="page-columns inner-left">
<pw-section class="blue" :label="$t('endpoint')" ref="endpoint">
<ul>
<li>
<label for="url">{{ $t("url") }}</label>
<input
id="url"
type="url"
v-model="url"
@keyup.enter="getSchema()"
/>
</li>
<div>
<li>
<label for="get" class="hide-on-small-screen">&nbsp;</label>
<button id="get" name="get" @click="getSchema">
{{ $t("get_schema") }}
<span><i class="material-icons">send</i></span>
</button>
</li>
</div>
</ul>
</pw-section>
<pw-section class="orange" :label="$t('headers')" ref="headers">
<ul>
<li>
<div class="flex-wrap">
<label for="headerList">{{ $t("header_list") }}</label>
<div>
<button
class="icon"
@click="headers = []"
v-tooltip.bottom="$t('clear')"
>
<i class="material-icons">clear_all</i>
</button>
</div>
</div>
<textarea
id="headerList"
readonly
v-textarea-auto-height="headerString"
v-model="headerString"
:placeholder="$t('add_one_header')"
rows="1"
></textarea>
</li>
</ul>
<ul v-for="(header, index) in headers" :key="index">
<li>
<autocomplete
:placeholder="$t('header_count', { count: index + 1 })"
:source="commonHeaders"
:spellcheck="false"
:value="header.key"
@input="
$store.commit('setGQLHeaderKey', {
index,
value: $event
})
"
autofocus
/>
</li>
<li>
<input
:placeholder="$t('value_count', { count: index + 1 })"
:name="'value' + index"
:value="header.value"
@change="
$store.commit('setGQLHeaderValue', {
index,
value: $event.target.value
})
"
autofocus
/>
</li>
<div>
<li>
<button
class="icon"
@click="removeRequestHeader(index)"
v-tooltip.bottom="$t('delete')"
id="header"
>
<i class="material-icons">delete</i>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button class="icon" @click="addRequestHeader">
<i class="material-icons">add</i>
<span>{{ $t("add_new") }}</span>
</button>
</li>
</ul>
</pw-section>
<pw-section class="green" :label="$t('schema')" ref="schema">
<div class="flex-wrap">
<label>{{ $t("response") }}</label>
<div>
<button
class="icon"
@click="ToggleExpandResponse"
ref="ToggleExpandResponse"
v-tooltip="{
content: !expandResponse
? $t('expand_response')
: $t('collapse_response')
}"
>
<i class="material-icons">
{{ !expandResponse ? "unfold_more" : "unfold_less" }}
</i>
</button>
<button
class="icon"
@click="downloadResponse"
ref="downloadResponse"
v-tooltip="$t('download_file')"
>
<i class="material-icons">get_app</i>
</button>
<button
class="icon"
ref="copySchemaCode"
@click="copySchema"
v-tooltip="$t('copy_schema')"
>
<i class="material-icons">file_copy</i>
</button>
</div>
</div>
<Editor
:value="schemaString"
:lang="'graphqlschema'"
:options="{
maxLines: responseBodyMaxLines,
minLines: '16',
fontSize: '16px',
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false
}"
/>
</pw-section>
<pw-section class="cyan" :label="$t('query')" ref="query">
<div class="flex-wrap">
<label for="gqlQuery">{{ $t("query") }}</label>
<div>
<button
class="icon"
@click="runQuery()"
v-tooltip.bottom="$t('run_query')"
>
<i class="material-icons">play_arrow</i>
</button>
<button
class="icon"
@click="copyQuery"
ref="copyQueryButton"
v-tooltip="$t('copy_query')"
>
<i class="material-icons">file_copy</i>
</button>
</div>
</div>
<QueryEditor
ref="queryEditor"
v-model="gqlQueryString"
:options="{
maxLines: responseBodyMaxLines,
minLines: '16',
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
}"
/>
</pw-section>
<pw-section class="yellow" label="Variables" ref="variables">
<Editor
v-model="variableString"
:lang="'json'"
:options="{
maxLines: responseBodyMaxLines,
minLines: '16',
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
}"
/>
</pw-section>
<pw-section class="purple" label="Response" ref="response">
<div class="flex-wrap">
<label for="responseField">{{ $t("response") }}</label>
<div>
<button
class="icon"
@click="copyResponse"
ref="copyResponseButton"
v-tooltip="$t('copy_response')"
>
<i class="material-icons">file_copy</i>
</button>
</div>
</div>
<Editor
:value="responseString"
:lang="'json'"
:options="{
maxLines: responseBodyMaxLines,
minLines: '16',
fontSize: '16px',
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false
}"
/>
</pw-section>
</div>
<aside class="sticky-inner inner-right">
<pw-section class="purple" :label="$t('docs')" ref="docs">
<section>
<input
v-if="queryFields.length > 0"
id="queries-tab"
type="radio"
name="side"
checked="checked"
/>
<label v-if="queryFields.length > 0" for="queries-tab">
{{ $t("queries") }}
</label>
<div v-if="queryFields.length > 0" class="tab">
<div v-for="field in queryFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
</div>
</div>
<input
v-if="mutationFields.length > 0"
id="mutations-tab"
type="radio"
name="side"
checked="checked"
/>
<label v-if="mutationFields.length > 0" for="mutations-tab">
{{ $t("mutations") }}
</label>
<div v-if="mutationFields.length > 0" class="tab">
<div v-for="field in mutationFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
</div>
</div>
<input
v-if="subscriptionFields.length > 0"
id="subscriptions-tab"
type="radio"
name="side"
checked="checked"
/>
<label v-if="subscriptionFields.length > 0" for="subscriptions-tab">
{{ $t("subscriptions") }}
</label>
<div v-if="subscriptionFields.length > 0" class="tab">
<div v-for="field in subscriptionFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
</div>
</div>
<input
v-if="gqlTypes.length > 0"
id="gqltypes-tab"
type="radio"
name="side"
checked="checked"
/>
<label v-if="gqlTypes.length > 0" for="gqltypes-tab">
{{ $t("types") }}
</label>
<div v-if="gqlTypes.length > 0" class="tab">
<div
v-for="type in gqlTypes"
:key="type.name"
:id="`type_${type.name}`"
>
<gql-type
:gqlType="type"
:jumpTypeCallback="handleJumpToType"
/>
</div>
</div>
</section>
<p
v-if="
queryFields.length === 0 &&
mutationFields.length === 0 &&
subscriptionFields.length === 0 &&
gqlTypes.length === 0
"
class="info"
>
{{ $t("send_request_first") }}
</p>
</pw-section>
</aside>
</div>
</div>
</template>
<style scoped lang="scss">
.tab {
max-height: calc(100vh - 186px);
overflow: auto;
}
</style>
<script>
import axios from "axios";
import * as gql from "graphql";
import textareaAutoHeight from "../directives/textareaAutoHeight";
import { commonHeaders } from "../functions/headers";
import AceEditor from "../components/ace-editor";
import QueryEditor from "../components/graphql/queryeditor";
import { sendNetworkRequest } from "../functions/network";
export default {
directives: {
textareaAutoHeight
},
components: {
"pw-section": () => import("../components/section"),
"gql-field": () => import("../components/graphql/field"),
"gql-type": () => import("../components/graphql/type"),
autocomplete: () => import("../components/autocomplete"),
Editor: AceEditor,
QueryEditor: QueryEditor
},
data() {
return {
schemaString: "",
commonHeaders,
queryFields: [],
mutationFields: [],
subscriptionFields: [],
gqlTypes: [],
responseString: "",
copyButton: '<i class="material-icons">file_copy</i>',
downloadButton: '<i class="material-icons">get_app</i>',
doneButton: '<i class="material-icons">done</i>',
expandResponse: false,
responseBodyMaxLines: 16
};
},
computed: {
url: {
get() {
return this.$store.state.gql.url;
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "url" });
}
},
headers: {
get() {
return this.$store.state.gql.headers;
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "headers" });
}
},
gqlQueryString: {
get() {
return this.$store.state.gql.query;
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "query" });
}
},
variableString: {
get() {
return this.$store.state.gql.variablesJSONString;
},
set(value) {
this.$store.commit("setGQLState", {
value,
attribute: "variablesJSONString"
});
}
},
headerString() {
const result = this.headers
.filter(({ key }) => !!key)
.map(({ key, value }) => `${key}: ${value}`)
.join(",\n");
return result === "" ? "" : `${result}`;
}
},
methods: {
handleJumpToType(type) {
const typesTab = document.getElementById("gqltypes-tab");
typesTab.checked = true;
const rootTypeName = this.resolveRootType(type).name;
const target = document.getElementById(`type_${rootTypeName}`);
if (target) {
target.scrollIntoView({
behavior: "smooth"
});
}
},
resolveRootType(type) {
let t = type;
while (t.ofType != null) t = t.ofType;
return t;
},
copySchema() {
this.$refs.copySchemaCode.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.schemaString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copySchemaCode.innerHTML = this.copyButton),
1000
);
},
copyQuery() {
this.$refs.copyQueryButton.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.gqlQueryString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copyQueryButton.innerHTML = this.copyButton),
1000
);
},
copyResponse() {
this.$refs.copyResponseButton.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.responseString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copyResponseButton.innerHTML = this.copyButton),
1000
);
},
async runQuery() {
const startTime = Date.now();
this.$nuxt.$loading.start();
this.scrollInto("response");
try {
let headers = {};
this.headers.forEach(header => {
headers[header.key] = header.value;
});
let variables = JSON.parse(this.variableString);
const gqlQueryString = this.gqlQueryString;
const reqOptions = {
method: "post",
url: this.url,
headers: {
...headers,
"content-type": "application/json"
},
data: JSON.stringify({ query: gqlQueryString, variables })
};
const data = await sendNetworkRequest(reqOptions, this.$store);
this.responseString = JSON.stringify(data.data, null, 2);
this.$nuxt.$loading.finish();
const duration = Date.now() - startTime;
this.$toast.info(this.$t("finished_in", { duration }), {
icon: "done"
});
} catch (error) {
this.$nuxt.$loading.finish();
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
icon: "error"
});
console.log("Error", error);
}
},
async getSchema() {
const startTime = Date.now();
this.schemaString = this.$t("loading");
this.scrollInto("schema");
// Start showing the loading bar as soon as possible.
// The nuxt axios module will hide it when the request is made.
this.$nuxt.$loading.start();
try {
const query = JSON.stringify({
query: gql.getIntrospectionQuery()
});
let headers = {};
this.headers.forEach(header => {
headers[header.key] = header.value;
});
const reqOptions = {
method: "post",
url: this.url,
headers: {
...headers,
"content-type": "application/json"
},
data: query
};
// console.log(reqOptions);
const reqConfig = this.$store.state.postwoman.settings.PROXY_ENABLED
? {
method: "post",
url:
this.$store.state.postwoman.settings.PROXY_URL ||
`https://postwoman.apollotv.xyz/`,
data: reqOptions
}
: reqOptions;
const res = await axios(reqConfig);
const data = this.$store.state.postwoman.settings.PROXY_ENABLED
? res.data
: res;
const schema = gql.buildClientSchema(data.data.data);
this.schemaString = gql.printSchema(schema, {
commentDescriptions: true
});
if (schema.getQueryType()) {
const fields = schema.getQueryType().getFields();
const qFields = [];
for (const field in fields) {
qFields.push(fields[field]);
}
this.queryFields = qFields;
}
if (schema.getMutationType()) {
const fields = schema.getMutationType().getFields();
const mFields = [];
for (const field in fields) {
mFields.push(fields[field]);
}
this.mutationFields = mFields;
}
if (schema.getSubscriptionType()) {
const fields = schema.getSubscriptionType().getFields();
const sFields = [];
for (const field in fields) {
sFields.push(fields[field]);
}
this.subscriptionFields = sFields;
}
const typeMap = schema.getTypeMap();
const types = [];
const queryTypeName = schema.getQueryType()
? schema.getQueryType().name
: "";
const mutationTypeName = schema.getMutationType()
? schema.getMutationType().name
: "";
const subscriptionTypeName = schema.getSubscriptionType()
? schema.getSubscriptionType().name
: "";
for (const type in typeMap) {
if (
!typeMap[type].name.startsWith("__") &&
![queryTypeName, mutationTypeName, subscriptionTypeName].includes(
typeMap[type].name
) &&
typeMap[type] instanceof gql.GraphQLObjectType
) {
types.push(typeMap[type]);
}
}
this.gqlTypes = types;
this.$refs.queryEditor.setValidationSchema(schema);
this.$nuxt.$loading.finish();
const duration = Date.now() - startTime;
this.$toast.info(this.$t("finished_in", { duration }), {
icon: "done"
});
} catch (error) {
this.$nuxt.$loading.finish();
this.schemaString = `${error}. ${this.$t("check_console_details")}`;
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
icon: "error"
});
console.log("Error", error);
}
},
ToggleExpandResponse() {
this.expandResponse = !this.expandResponse;
this.responseBodyMaxLines =
this.responseBodyMaxLines == Infinity ? 16 : Infinity;
},
downloadResponse() {
const dataToWrite = JSON.stringify(this.schemaString, null, 2);
const file = new Blob([dataToWrite], { type: "application/json" });
const a = document.createElement("a");
const url = URL.createObjectURL(file);
a.href = url;
a.download = `${this.url} on ${Date()}.graphql`.replace(/\./g, "[dot]");
document.body.appendChild(a);
a.click();
this.$refs.downloadResponse.innerHTML = this.doneButton;
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.$refs.downloadResponse.innerHTML = this.downloadButton;
}, 1000);
},
addRequestHeader(index) {
this.$store.commit("addGQLHeader", {
key: "",
value: ""
});
return false;
},
removeRequestHeader(index) {
// .slice() is used so we get a separate array, rather than just a reference
const oldHeaders = this.headers.slice();
this.$store.commit("removeGQLHeader", index);
this.$toast.error(this.$t("deleted"), {
icon: "delete",
action: {
text: this.$t("undo"),
duration: 4000,
onClick: (e, toastObject) => {
this.headers = oldHeaders;
toastObject.remove();
}
}
});
// console.log(oldHeaders);
},
scrollInto(view) {
this.$refs[view].$el.scrollIntoView({
behavior: "smooth"
});
}
}
};
</script>

File diff suppressed because it is too large Load Diff

438
pages/realtime.vue Normal file
View File

@@ -0,0 +1,438 @@
<template>
<div class="page">
<section id="options">
<input id="tab-one" type="radio" name="options" checked="checked" />
<label for="tab-one">{{ $t("websocket") }}</label>
<div class="tab">
<pw-section class="blue" :label="$t('request')" ref="request">
<ul>
<li>
<label for="url">{{ $t("url") }}</label>
<input
id="url"
type="url"
:class="{ error: !urlValid }"
v-model="url"
@keyup.enter="urlValid ? toggleConnection() : null"
/>
</li>
<div>
<li>
<label for="connect" class="hide-on-small-screen">&nbsp;</label>
<button
:disabled="!urlValid"
id="connect"
name="connect"
@click="toggleConnection"
>
{{ !connectionState ? $t("connect") : $t("disconnect") }}
<span>
<i class="material-icons">
{{ !connectionState ? "sync" : "sync_disabled" }}
</i>
</span>
</button>
</li>
</div>
</ul>
</pw-section>
<pw-section
class="purple"
:label="$t('communication')"
id="response"
ref="response"
>
<ul>
<li>
<label for="log">{{ $t("log") }}</label>
<div id="log" name="log" class="log">
<span v-if="communication.log">
<span
v-for="(logEntry, index) in communication.log"
:style="{ color: logEntry.color }"
:key="index"
>@ {{ logEntry.ts }}{{ getSourcePrefix(logEntry.source)
}}{{ logEntry.payload }}</span
>
</span>
<span v-else>{{ $t("waiting_for_connection") }}</span>
</div>
</li>
</ul>
<ul>
<li>
<label for="message">{{ $t("message") }}</label>
<input
id="message"
name="message"
type="text"
v-model="communication.input"
:readonly="!connectionState"
@keyup.enter="connectionState ? sendMessage() : null"
/>
</li>
<div>
<li>
<label for="send" class="hide-on-small-screen">&nbsp;</label>
<button
id="send"
name="send"
:disabled="!connectionState"
@click="sendMessage"
>
{{ $t("send") }}
<span>
<i class="material-icons">send</i>
</span>
</button>
</li>
</div>
</ul>
</pw-section>
</div>
<input id="tab-two" type="radio" name="options" />
<label for="tab-two">{{ $t("sse") }}</label>
<div class="tab">
<pw-section class="blue" :label="$t('request')" ref="request">
<ul>
<li>
<label for="server">{{ $t("server") }}</label>
<input
id="server"
type="url"
:class="{ error: !serverValid }"
v-model="server"
@keyup.enter="serverValid ? toggleSSEConnection() : null"
/>
</li>
<div>
<li>
<label for="start" class="hide-on-small-screen">&nbsp;</label>
<button
:disabled="!serverValid"
id="start"
name="start"
@click="toggleSSEConnection"
>
{{ !connectionSSEState ? $t("start") : $t("stop") }}
<span>
<i class="material-icons">
{{ !connectionSSEState ? "sync" : "sync_disabled" }}
</i>
</span>
</button>
</li>
</div>
</ul>
</pw-section>
<pw-section
class="purple"
:label="$t('communication')"
id="response"
ref="response"
>
<ul>
<li>
<label for="log">{{ $t("events") }}</label>
<div id="log" name="log" class="log">
<span v-if="events.log">
<span
v-for="(logEntry, index) in events.log"
:style="{ color: logEntry.color }"
:key="index"
>@ {{ logEntry.ts }}{{ getSourcePrefix(logEntry.source)
}}{{ logEntry.payload }}</span
>
</span>
<span v-else>{{ $t("waiting_for_connection") }}</span>
</div>
<div id="result"></div>
</li>
</ul>
</pw-section>
</div>
</section>
</div>
</template>
<style scoped lang="scss">
div.log {
margin: 4px;
padding: 8px 16px;
width: calc(100% - 8px);
border-radius: 8px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
height: 256px;
overflow: auto;
&,
span {
font-size: 16px;
font-family: "Roboto Mono", monospace;
font-weight: 400;
}
span {
display: block;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
}
}
</style>
<script>
export default {
components: {
"pw-section": () => import("../components/section")
},
data() {
return {
connectionState: false,
url: "wss://echo.websocket.org",
socket: null,
communication: {
log: null,
input: ""
},
connectionSSEState: false,
server: "https://express-eventsource.herokuapp.com/events",
sse: null,
events: {
log: null,
input: ""
}
};
},
computed: {
urlValid() {
const protocol = "^(wss?:\\/\\/)?";
const validIP = new RegExp(
`${protocol}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
);
const validHostname = new RegExp(
`${protocol}(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9/])$`
);
return validIP.test(this.url) || validHostname.test(this.url);
},
serverValid() {
const protocol = "^(https?:\\/\\/)?";
const validIP = new RegExp(
`${protocol}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
);
const validHostname = new RegExp(
`${protocol}(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9/])$`
);
return validIP.test(this.server) || validHostname.test(this.server);
}
},
methods: {
toggleConnection() {
// If it is connecting:
if (!this.connectionState) return this.connect();
// Otherwise, it's disconnecting.
else return this.disconnect();
},
connect() {
this.communication.log = [
{
payload: this.$t("connecting_to", { name: this.url }),
source: "info",
color: "var(--ac-color)"
}
];
try {
this.socket = new WebSocket(this.url);
this.socket.onopen = event => {
this.connectionState = true;
this.communication.log = [
{
payload: this.$t("connected_to", { name: this.url }),
source: "info",
color: "var(--ac-color)",
ts: new Date().toLocaleTimeString()
}
];
this.$toast.success(this.$t("connected"), {
icon: "sync"
});
};
this.socket.onerror = event => {
this.handleError();
};
this.socket.onclose = event => {
this.connectionState = false;
this.communication.log.push({
payload: this.$t("disconnected_from", { name: this.url }),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
this.$toast.error(this.$t("disconnected"), {
icon: "sync_disabled"
});
};
this.socket.onmessage = event => {
this.communication.log.push({
payload: event.data,
source: "server",
ts: new Date().toLocaleTimeString()
});
};
} catch (ex) {
this.handleError(ex);
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error"
});
}
},
disconnect() {
this.socket.close();
},
handleError(error) {
this.disconnect();
this.connectionState = false;
this.communication.log.push({
payload: this.$t("error_occurred"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
if (error !== null)
this.communication.log.push({
payload: error,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
},
sendMessage() {
const message = this.communication.input;
this.socket.send(message);
this.communication.log.push({
payload: message,
source: "client",
ts: new Date().toLocaleTimeString()
});
this.communication.input = "";
},
collapse({ target }) {
const el = target.parentNode.className;
document.getElementsByClassName(el)[0].classList.toggle("hidden");
},
getSourcePrefix(source) {
const sourceEmojis = {
// Source used for info messages.
info: "\t [INFO]:\t",
// Source used for client to server messages.
client: "\t👽 [SENT]:\t",
// Source used for server to client messages.
server: "\t📥 [RECEIVED]:\t"
};
if (Object.keys(sourceEmojis).includes(source))
return sourceEmojis[source];
return "";
},
toggleSSEConnection() {
// If it is connecting:
if (!this.connectionSSEState) return this.start();
// Otherwise, it's disconnecting.
else return this.stop();
},
start() {
this.events.log = [
{
payload: this.$t("connecting_to", { name: this.server }),
source: "info",
color: "var(--ac-color)"
}
];
if (typeof EventSource !== "undefined") {
try {
this.sse = new EventSource(this.server);
this.sse.onopen = event => {
this.connectionSSEState = true;
this.events.log = [
{
payload: this.$t("connected_to", { name: this.server }),
source: "info",
color: "var(--ac-color)",
ts: new Date().toLocaleTimeString()
}
];
this.$toast.success(this.$t("connected"), {
icon: "sync"
});
};
this.sse.onerror = event => {
this.handleSSEError();
};
this.sse.onclose = event => {
this.connectionSSEState = false;
this.events.log.push({
payload: this.$t("disconnected_from", { name: this.server }),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
this.$toast.error(this.$t("disconnected"), {
icon: "sync_disabled"
});
};
this.sse.onmessage = event => {
this.events.log.push({
payload: event.data,
source: "server",
ts: new Date().toLocaleTimeString()
});
};
} catch (ex) {
this.handleSSEError(ex);
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error"
});
}
} else {
this.events.log = [
{
payload: this.$t("browser_support_sse"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
}
];
}
},
handleSSEError(error) {
this.stop();
this.connectionSSEState = false;
this.events.log.push({
payload: this.$t("error_occurred"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
if (error !== null)
this.events.log.push({
payload: error,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
},
stop() {
this.sse.onclose();
this.sse.close();
}
},
updated: function() {
this.$nextTick(function() {
const divLog = document.getElementById("log");
divLog.scrollBy(0, divLog.scrollHeight + 100);
});
}
};
</script>

View File

@@ -1,13 +1,96 @@
<template>
<div class="page">
<pw-section class="cyan" label="Theme" ref="theme">
<pw-section class="green" :label="$t('account')" ref="account">
<ul>
<li>
<h3 class="title">Background</h3>
<div v-if="fb.currentUser">
<button class="icon">
<img
v-if="fb.currentUser.photoURL"
:src="fb.currentUser.photoURL"
class="material-icons"
/>
<i v-else class="material-icons">account_circle</i>
<span>
{{ fb.currentUser.displayName || "Name not found" }}
</span>
</button>
<br />
<button class="icon">
<i class="material-icons">email</i>
<span>
{{ fb.currentUser.email || "Email not found" }}
</span>
</button>
<br />
<button class="icon" @click="logout">
<i class="material-icons">exit_to_app</i>
<span>{{ $t("logout") }}</span>
</button>
<br />
<p v-for="setting in fb.currentSettings" :key="setting.id">
<pw-toggle
:key="setting.name"
:on="setting.value"
@change="toggleSettings(setting.name, setting.value)"
>
{{ $t(setting.name) + " " + $t("sync") }}
{{ setting.value ? $t("enabled") : $t("disabled") }}
</pw-toggle>
</p>
<p v-if="fb.currentSettings.length !== 3">
<button class="" @click="initSettings">
<i class="material-icons">sync</i>
<span>{{ $t("turn_on") + " " + $t("sync") }}</span>
</button>
</p>
</div>
<div v-else>
<label>{{ $t("login_with") }}</label>
<p>
<button class="icon" @click="signInWithGoogle">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
class="material-icons"
>
<path
d="M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z"
/>
</svg>
<span>Google</span>
</button>
<br />
<button class="icon" @click="signInWithGithub">
<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>
<span>GitHub</span>
</button>
</p>
</div>
</li>
</ul>
</pw-section>
<pw-section class="cyan" :label="$t('theme')" ref="theme">
<ul>
<li>
<label>{{ $t("background") }}</label>
<div class="backgrounds">
<span
:key="theme.class"
@click="applyTheme(theme.class, theme.color)"
@click="applyTheme(theme)"
v-for="theme in themes"
>
<swatch
@@ -15,6 +98,7 @@
:class="{ vibrant: theme.vibrant }"
:color="theme.color"
:name="theme.name"
class="bg"
></swatch>
</span>
</div>
@@ -22,7 +106,7 @@
</ul>
<ul>
<li>
<h3 class="title">Color</h3>
<label>{{ $t("color") }}</label>
<div class="colors">
<span
:key="entry.color"
@@ -34,6 +118,7 @@
:class="{ vibrant: entry.vibrant }"
:color="entry.color"
:name="entry.name"
class="fg"
/>
</span>
</div>
@@ -41,39 +126,95 @@
</ul>
<ul>
<li>
<h3 class="title">Labels</h3>
<span>
<pw-toggle
:on="settings.FRAME_COLORS_ENABLED"
@change="toggleSetting('FRAME_COLORS_ENABLED')"
>Multi-color {{ settings.FRAME_COLORS_ENABLED ? "Enabled" : "Disabled" }}</pw-toggle>
>
{{ $t("multi_color") }}
{{
settings.FRAME_COLORS_ENABLED ? $t("enabled") : $t("disabled")
}}
</pw-toggle>
</span>
</li>
</ul>
</pw-section>
<br />
<pw-section class="blue" label="Proxy" ref="proxy">
<pw-section class="purple" :label="$t('extensions')" ref="extensions">
<ul>
<li>
<div class="flex-wrap">
<pw-toggle
:on="settings.EXTENSIONS_ENABLED"
@change="toggleSetting('EXTENSIONS_ENABLED')"
>
{{ $t("extensions_use_toggle") }}
</pw-toggle>
</div>
</li>
</ul>
</pw-section>
<pw-section class="blue" :label="$t('proxy')" ref="proxy">
<ul>
<li>
<div class="flex-wrap">
<span>
<pw-toggle
:on="settings.PROXY_ENABLED"
@change="toggleSetting('PROXY_ENABLED')"
>Proxy {{ settings.PROXY_ENABLED ? "enabled" : "disabled" }}</pw-toggle>
>
{{ $t("proxy") }}
{{ settings.PROXY_ENABLED ? $t("enabled") : $t("disabled") }}
</pw-toggle>
</span>
<a
href="https://github.com/liyasthomas/postwoman/wiki/Proxy"
target="_blank"
rel="noopener"
>
<button class="icon" v-tooltip="$t('wiki')">
<i class="material-icons">help</i>
</button>
</a>
</div>
</li>
</ul>
<ul>
<li>
<div class="flex-wrap">
<label for="url">{{ $t("url") }}</label>
<button
class="icon"
@click="resetProxy"
v-tooltip.bottom="$t('reset_default')"
>
<i class="material-icons">clear_all</i>
</button>
</div>
<input
id="url"
type="url"
v-model="settings.PROXY_URL"
:disabled="!settings.PROXY_ENABLED"
/>
</li>
</ul>
<ul class="info">
<li>
<p>
Postwoman's Proxy is hosted by ApolloTV.
<br />Read the ApolloTV privacy policy
{{ $t("postwoman_official_proxy_hosting") }}
<br />
{{ $t("read_the") }}
<a
class="link"
href="https://apollotv.xyz/legal"
target="_blank"
>here</a>.
rel="noopener"
>
{{ $t("apollotv_privacy_policy") }} </a
>.
</p>
</li>
</ul>
@@ -96,23 +237,17 @@
</div>
</template>
<style scoped>
.info {
margin-left: 4px;
color: var(--fg-light-color);
}
</style>
<style scoped lang="scss"></style>
<script>
import section from "../components/section";
import swatch from "../components/settings/swatch";
import toggle from "../components/toggle";
import firebase from "firebase/app";
import { fb } from "../functions/fb";
export default {
components: {
"pw-section": section,
"pw-toggle": toggle,
swatch: swatch
"pw-section": () => import("../components/section"),
"pw-toggle": () => import("../components/toggle"),
swatch: () => import("../components/settings/swatch")
},
data() {
@@ -122,26 +257,32 @@ export default {
// set the relevant values.
themes: [
{
color: "#252628",
name: "Kinda Dark",
class: ""
color: "#202124",
name: this.$t("kinda_dark"),
class: "",
aceEditor: "twilight"
},
{
color: "#ffffff",
name: "Clearly White",
name: this.$t("clearly_white"),
vibrant: true,
class: "light"
class: "light",
aceEditor: "iplastic"
},
{
color: "#000000",
name: "Just Black",
class: "black"
name: this.$t("just_black"),
class: "black",
aceEditor: "vibrant_ink"
},
{
color: "var(--bg-color)",
name: "Auto (system)",
color: "var(--ac-color)",
name: this.$t("auto_system"),
vibrant: window.matchMedia("(prefers-color-scheme: light)").matches,
class: "auto"
class: "auto",
aceEditor: window.matchMedia("(prefers-color-scheme: light)").matches
? "iplastic"
: "twilight"
}
],
// You can define a new color here! It will simply store the color value.
@@ -149,42 +290,42 @@ export default {
// If the color is vibrant, black is used as the active foreground color.
{
color: "#50fa7b",
name: "Green",
name: this.$t("green"),
vibrant: true
},
{
color: "#f1fa8c",
name: "Yellow",
name: this.$t("yellow"),
vibrant: true
},
{
color: "#ff79c6",
name: "Pink",
name: this.$t("pink"),
vibrant: true
},
{
color: "#ff5555",
name: "Red",
name: this.$t("red"),
vibrant: false
},
{
color: "#bd93f9",
name: "Purple",
name: this.$t("purple"),
vibrant: true
},
{
color: "#ffb86c",
name: "Orange",
name: this.$t("orange"),
vibrant: true
},
{
color: "#8be9fd",
name: "Cyan",
name: this.$t("cyan"),
vibrant: true
},
{
color: "#57b5f9",
name: "Blue",
name: this.$t("blue"),
vibrant: false
}
],
@@ -199,9 +340,19 @@ export default {
this.$store.state.postwoman.settings.FRAME_COLORS_ENABLED || false,
PROXY_ENABLED:
this.$store.state.postwoman.settings.PROXY_ENABLED || false,
PROXY_URL: this.$store.state.postwoman.settings.PROXY_URL || "",
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || ""
}
PROXY_URL:
this.$store.state.postwoman.settings.PROXY_URL ||
"https://postwoman.apollotv.xyz/",
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || "",
EXTENSIONS_ENABLED:
typeof this.$store.state.postwoman.settings.EXTENSIONS_ENABLED !==
"undefined"
? this.$store.state.postwoman.settings.EXTENSIONS_ENABLED
: true
},
doneButton: '<i class="material-icons">done</i>',
fb
};
},
@@ -216,28 +367,22 @@ export default {
},
methods: {
applyTheme(name, color) {
applyTheme({ class: name, color, aceEditor }) {
this.applySetting("THEME_CLASS", name);
this.applySetting("THEME_ACE_EDITOR", aceEditor);
document
.querySelector("meta[name=theme-color]")
.setAttribute("content", color);
this.applySetting("THEME_TAB_COLOR", color);
document.documentElement.className = name;
let imgGitHub = document.getElementById("imgGitHub");
imgGitHub.style["filter"] = "";
imgGitHub.style["webkit-filter"] = "invert(100%)";
if (name.includes("light")) {
imgGitHub.style["filter"] = "invert(100%)";
imgGitHub.style["webkit-filter"] = "invert(100%)";
}
},
setActiveColor(color, vibrant) {
// By default, the color is vibrant.
if (vibrant == null) vibrant = true;
if (vibrant === null) vibrant = true;
document.documentElement.style.setProperty("--ac-color", color);
document.documentElement.style.setProperty(
"--act-color",
vibrant ? "rgb(37, 38, 40)" : "#f8f8f2"
vibrant ? "rgba(32, 33, 36, 1)" : "rgba(255, 255, 255, 1)"
);
this.applySetting("THEME_COLOR", color.toUpperCase());
this.applySetting("THEME_COLOR_VIBRANT", vibrant);
@@ -258,11 +403,102 @@ export default {
toggleSetting(key) {
this.settings[key] = !this.settings[key];
this.$store.commit("postwoman/applySetting", [key, this.settings[key]]);
this.$router.replace("/settings", {
force: true
},
logout() {
fb.currentUser = null;
firebase
.auth()
.signOut()
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
this.$toast.info(this.$t("logged_out"), {
icon: "vpn_key"
});
},
signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
},
signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider();
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
},
toggleSettings(s, v) {
fb.writeSettings(s, !v);
},
initSettings() {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
},
resetProxy({ target }) {
this.settings.PROXY_URL = `https://postwoman.apollotv.xyz/`;
target.innerHTML = this.doneButton;
this.$toast.info(this.$t("cleared"), {
icon: "clear_all"
});
setTimeout(
() => (target.innerHTML = '<i class="material-icons">clear_all</i>'),
1000
);
}
},
beforeMount() {
this.settings.THEME_COLOR = this.getActiveColor();
},

View File

@@ -1,244 +0,0 @@
<template>
<div class="page">
<pw-section class="blue" label="Request" ref="request">
<ul>
<li>
<label for="url">URL</label>
<input
id="url"
type="url"
:class="{ error: !urlValid }"
v-model="url"
@keyup.enter="urlValid ? toggleConnection() : null"
/>
</li>
<li>
<label for="connect" class="hide-on-small-screen">&nbsp;</label>
<button :disabled="!urlValid" id="connect" name="connect" @click="toggleConnection">
{{ toggleConnectionVerb }}
<span>
<i class="material-icons" v-if="!connectionState">sync</i>
<i class="material-icons" v-if="connectionState">sync_disabled</i>
</span>
</button>
</li>
</ul>
</pw-section>
<br />
<pw-section class="purple" label="Communication" id="response" ref="response">
<ul>
<li>
<label for="log">Log</label>
<div id="log" name="log" class="log">
<span v-if="communication.log">
<span
v-for="(logEntry, index) in communication.log"
:style="{ color: logEntry.color }"
:key="index"
>@ {{ logEntry.ts }} {{ getSourcePrefix(logEntry.source) }} {{ logEntry.payload }}</span>
</span>
<span v-else>(waiting for connection)</span>
</div>
</li>
</ul>
<ul>
<li>
<label for="message">Message</label>
<input
id="message"
name="message"
type="text"
v-model="communication.input"
:readonly="!connectionState"
@keyup.enter="connectionState ? sendMessage() : null"
/>
</li>
<li>
<label for="send" class="hide-on-small-screen">&nbsp;</label>
<button id="send" name="send" :disabled="!connectionState" @click="sendMessage">
Send
<span>
<i class="material-icons">send</i>
</span>
</button>
</li>
</ul>
</pw-section>
</div>
</template>
<style lang="scss">
div.log {
margin: 4px;
padding: 8px 16px;
width: calc(100% - 8px);
border-radius: 8px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
height: 256px;
overflow: auto;
&,
span {
font-size: 18px;
font-family: "Roboto Mono", monospace;
}
span {
display: block;
white-space: pre-wrap;
}
}
</style>
<script>
import section from "../components/section";
export default {
components: {
"pw-section": section
},
data() {
return {
connectionState: false,
url: "wss://echo.websocket.org",
socket: null,
communication: {
log: null,
input: ""
}
};
},
computed: {
toggleConnectionVerb() {
return !this.connectionState ? "Connect" : "Disconnect";
},
urlValid() {
const pattern = new RegExp(
"^(wss?:\\/\\/)?" +
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" +
"((\\d{1,3}\\.){3}\\d{1,3}))" +
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" +
"(\\?[;&a-z\\d%_.~+=-]*)?" +
"(\\#[-a-z\\d_]*)?$",
"i"
);
return pattern.test(this.url);
}
},
methods: {
toggleConnection() {
// If it is connecting:
if (!this.connectionState) return this.connect();
// Otherwise, it's disconnecting.
else return this.disconnect();
},
connect() {
this.communication.log = [
{
payload: `Connecting to ${this.url}...`,
source: "info",
color: "var(--ac-color)"
}
];
try {
this.socket = new WebSocket(this.url);
this.socket.onopen = event => {
this.connectionState = true;
this.communication.log = [
{
payload: `Connected to ${this.url}.`,
source: "info",
color: "var(--ac-color)",
ts: new Date().toLocaleTimeString()
}
];
this.$toast.success("Connected", {
icon: "sync"
});
};
this.socket.onerror = event => {
this.handleError();
};
this.socket.onclose = event => {
this.connectionState = false;
this.communication.log.push({
payload: `Disconnected from ${this.url}.`,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
this.$toast.error("Disconnected", {
icon: "sync_disabled"
});
};
this.socket.onmessage = event => {
this.communication.log.push({
payload: event.data,
source: "server",
ts: new Date().toLocaleTimeString()
});
};
} catch (ex) {
this.handleError(ex);
this.$toast.error("Something went wrong!", {
icon: "error"
});
}
},
disconnect() {
if (this.socket != null) this.socket.close();
},
handleError(error) {
this.disconnect();
this.connectionState = false;
this.communication.log.push({
payload: `An error has occurred.`,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
if (error != null)
this.communication.log.push({
payload: error,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
},
sendMessage() {
const message = this.communication.input;
this.socket.send(message);
this.communication.log.push({
payload: message,
source: "client",
ts: new Date().toLocaleTimeString()
});
this.communication.input = "";
},
collapse({ target }) {
const el = target.parentNode.className;
document.getElementsByClassName(el)[0].classList.toggle("hidden");
},
getSourcePrefix(source) {
const sourceEmojis = {
// Source used for info messages.
info: "\t [INFO]:\t",
// Source used for client to server messages.
client: "\t👽 [SENT]:\t",
// Source used for server to client messages.
server: "\t📥 [RECEIVED]:\t"
};
if (Object.keys(sourceEmojis).includes(source))
return sourceEmojis[source];
return "";
}
},
updated: function() {
this.$nextTick(function() {
var divLog = document.getElementById("log");
divLog.scrollBy(0, divLog.scrollHeight + 100);
});
}
};
</script>

View File

@@ -1,4 +1,4 @@
import Vue from 'vue';
import VTooltip from 'v-tooltip';
import Vue from "vue";
import VTooltip from "v-tooltip";
Vue.use(VTooltip);

View File

@@ -1,7 +1,5 @@
import VuexPersistence from "vuex-persist";
export default ({
store
}) => {
export default ({ store }) => {
new VuexPersistence().plugin(store);
}
};

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 612.001 612.001"
style="enable-background:new 0 0 612.001 612.001;"
xml:space="preserve"
width="512px"
height="512px"
class=""
sodipodi:docname="logo.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1533"
inkscape:window-height="845"
id="namedview9"
showgrid="false"
inkscape:zoom="0.921875"
inkscape:cx="380.48543"
inkscape:cy="276.92414"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" /> <g
id="g3826"
transform="translate(-516.40798,-163.88978)"><circle
transform="scale(1,-1)"
style="stroke-width:1.19531453"
r="178.70923"
cy="-501.55591"
cx="822.40845"
id="circle3814" /><g
id="g3820"
transform="translate(516.40798,163.89028)"><g
id="g3818"><path
id="path3816"
data-old_color="#202124"
class="active-path"
data-original="#202124"
d="M 64.601,236.822 C 64.601,394.256 192.786,612 306.001,612 412.582,612 547.4,394.256 547.4,236.822 547.4,79.388 439.322,0 306,0 172.678,0 64.601,79.388 64.601,236.822 Z m 304.12,116.415 c 29.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.475 -70.598,40.195 -108.552,32.173 -8.022,-37.955 2.698,-79.078 32.173,-108.552 z M 134.727,321.063 c 37.954,-8.021 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.552 z"
inkscape:connector-curvature="0"
style="fill:#50fa7b" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -13,10 +13,10 @@
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 20 20"
viewBox="0 0 24 24"
xml:space="preserve"
width="20"
height="20"
width="24"
height="24"
sodipodi:docname="github.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata
id="metadata13"><rdf:RDF><cc:Work

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

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