diff --git a/CHANGELOG.md b/CHANGELOG.md index 787c128e7bf..7775dfe6802 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,9 @@ - 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)) @@ -75,9 +77,8 @@ - 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)) -- Enhancements [\#531](https://github.com/liyasthomas/postwoman/pull/531) ([jamesgeorge007](https://github.com/jamesgeorge007)) - Updating spanish translation [\#529](https://github.com/liyasthomas/postwoman/pull/529) ([liyasthomas](https://github.com/liyasthomas)) -- even merge [\#528](https://github.com/liyasthomas/postwoman/pull/528) ([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) @@ -94,6 +95,7 @@ - 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)) @@ -110,7 +112,6 @@ - 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) -- API Documentation won't be generated [\#456](https://github.com/liyasthomas/postwoman/issues/456) **Closed issues:** @@ -121,15 +122,15 @@ - 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) -- \* ../.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) - 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 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)) - 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)) @@ -160,7 +161,6 @@ - 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) -- multipart/form-data support [\#434](https://github.com/liyasthomas/postwoman/issues/434) - 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) @@ -189,15 +189,16 @@ - 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)) -- Added ability to run GraphQL queries [\#346](https://github.com/liyasthomas/postwoman/pull/346) ([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) @@ -214,6 +215,7 @@ **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) @@ -245,6 +247,7 @@ - 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:** @@ -275,7 +278,6 @@ - ⬆️ 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)) -- Improving translate for pt-BR [\#396](https://github.com/liyasthomas/postwoman/pull/396) ([GustavoBezerra](https://github.com/GustavoBezerra)) - 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)) @@ -297,7 +299,6 @@ - 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)) -- ♻️ Refactor Functions [\#344](https://github.com/liyasthomas/postwoman/pull/344) ([athul](https://github.com/athul)) ## [v1.0.0](https://github.com/liyasthomas/postwoman/tree/v1.0.0) (2019-11-04) @@ -378,7 +379,6 @@ - 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) -- Handling request failures when build number is obtained from GitHub [\#122](https://github.com/liyasthomas/postwoman/issues/122) - 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) diff --git a/README.md b/README.md index 0093dee1540..111eff34225 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ _**All `i18n` contributions are welcome to `i18n` [branch](https://github.com/li - **[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) ([GitHub](https://github.com/AndrewBastin/postwoman-firefox))  |  [![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-chrome)) + [![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_16x16.png) **Firefox**](https://addons.mozilla.org/en-US/firefox/addon/postwoman)  |  [![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.** @@ -315,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 diff --git a/assets/css/styles.scss b/assets/css/styles.scss index 2bb3bba07fa..ef24d4e8133 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -22,13 +22,11 @@ $responsiveWidth: 768px; ::-webkit-scrollbar { width: 4px; height: 4px; - border-radius: 4px; - background-color: var(--bg-light-color); + background-color: var(--bg-dark-color); } ::-webkit-scrollbar-thumb { background-color: var(--fg-light-color); - border-radius: 8px; &:hover { background-color: var(--fg-color); @@ -60,9 +58,9 @@ body { 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; } @@ -76,6 +74,10 @@ a { color: inherit; text-decoration: none; transition: all 0.2s ease-in-out; + + &.link { + color: var(--ac-color); + } } header, @@ -146,7 +148,8 @@ footer { z-index: 1; height: 100vh; padding: 0 8px; - background-color: var(--bg-light-color); + background-color: var(--bg-dark-color); + transition: all 0.2s ease-in-out; } .main { @@ -173,6 +176,7 @@ nav.primary-nav { svg { fill: var(--fg-light-color); + transition: all 0.2s ease-in-out; } a { @@ -186,7 +190,6 @@ nav.primary-nav { color: var(--fg-light-color); fill: var(--fg-light-color); margin: 8px 0; - transition: all 0.2s ease-in-out; &:hover { color: var(--fg-color); @@ -263,11 +266,16 @@ 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: $bgcolor; @@ -422,7 +430,6 @@ button { color: var(--act-color); fill: var(--act-color); box-shadow: inset 0 0 0 2px var(--fg-color); - transition: all 0.2s ease-in-out; } &.icon { @@ -437,7 +444,6 @@ button { color: var(--fg-color); fill: var(--fg-color); box-shadow: none; - transition: all 0.2s ease-in-out; } } @@ -472,8 +478,19 @@ button { fieldset { margin: 16px 0; border-radius: 16px; - transition: all 0.2s ease-in-out; 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 { @@ -483,6 +500,7 @@ legend { color: var(--fg-color); font-weight: 700; cursor: pointer; + transition: all 0.2s ease-in-out; * { vertical-align: middle; @@ -565,7 +583,6 @@ code { &:not([readonly]):not(.ace_editor):active, &:not([readonly]):not(.ace_editor):focus { box-shadow: inset 0 0 0 2px var(--fg-light-color); - transition: all 0.2s ease-in-out; } } @@ -576,7 +593,6 @@ code { &:active, &:focus { box-shadow: inset 0 0 0 2px var(--fg-light-color); - transition: all 0.2s ease-in-out; } } @@ -681,6 +697,7 @@ input[type="checkbox"] { label { padding: 4px; color: var(--fg-light-color); + transition: all 0.2s ease-in-out; } ul, @@ -805,6 +822,7 @@ ol li { section { display: flex; flex-wrap: wrap; + border-radius: 16px; } .tab { @@ -884,18 +902,19 @@ input[type="radio"]:checked + label + .tab { padding: 0; width: 100%; background-color: var(--bg-color); - transition: all 0.2s ease-in-out; box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.45); } nav.primary-nav { flex-flow: row nowrap; overflow: auto; - justify-content: space-around; + 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; diff --git a/components/collections/importExportCollections.vue b/components/collections/importExportCollections.vue index 6d79fb21e74..44ebe6c1361 100644 --- a/components/collections/importExportCollections.vue +++ b/components/collections/importExportCollections.vue @@ -121,12 +121,19 @@ export default { 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') { + 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 if ( + collections.info && + collections.info.schema.includes("v2.1.0") + ) { + collections = this.parsePostmanCollection(collections); } else { return this.failedImport(); } @@ -141,11 +148,18 @@ export default { 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') { + 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')) { + } else if ( + collections.info && + collections.info.schema.includes("v2.1.0") + ) { collections = this.parsePostmanCollection(collections); } else { return this.failedImport(); @@ -188,28 +202,38 @@ export default { }); }, parsePostmanCollection(collection, folders = true) { - let postwomanCollection = folders ? [{ - "name": "", - "folders": [], - "requests": [] - }] + let postwomanCollection = folders + ? [ + { + name: "", + folders: [], + requests: [] + } + ] : { - "name": "", - "requests": [] - }; - for(let collectionItem of collection.item) { + 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)); + 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)); + 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)); + postwomanCollection[0].folders.push( + this.parsePostmanCollection(collectionItem, false) + ); } } } @@ -217,46 +241,51 @@ export default { }, parsePostmanRequest(requestObject) { let pwRequest = { - "url": "", - "path": "", - "method": "", - "auth": "", - "httpUser": "", - "httpPassword": "", - "passwordFieldType": "password", - "bearerToken": "", - "headers": [], - "params": [], - "bodyParams": [], - "rawParams": "", - "rawInput": false, - "contentType": "", - "requestType": "", - "name": "", + 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(/^(.+:\/\/[^\/]+|{[^\/]+})(\/[^\?]+|).*$/); + 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 + 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; + 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; + 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; @@ -280,7 +309,7 @@ export default { if (requestObject.request.body.mode === "urlencoded") { let params = requestObject.request.body.urlencoded; pwRequest.bodyParams = params ? params : []; - for(let param of pwRequest.bodyParams) { + for (let param of pwRequest.bodyParams) { delete param.type; } } else if (requestObject.request.body.mode === "raw") { diff --git a/components/environments/addEnvironment.vue b/components/environments/addEnvironment.vue new file mode 100644 index 00000000000..43ef6636bf6 --- /dev/null +++ b/components/environments/addEnvironment.vue @@ -0,0 +1,94 @@ + + + diff --git a/components/environments/editEnvironment.vue b/components/environments/editEnvironment.vue new file mode 100644 index 00000000000..9c15b33e289 --- /dev/null +++ b/components/environments/editEnvironment.vue @@ -0,0 +1,221 @@ + + + diff --git a/components/environments/environment.vue b/components/environments/environment.vue new file mode 100644 index 00000000000..8fda531985b --- /dev/null +++ b/components/environments/environment.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/components/environments/importExportEnvironment.vue b/components/environments/importExportEnvironment.vue new file mode 100644 index 00000000000..9b834c376b6 --- /dev/null +++ b/components/environments/importExportEnvironment.vue @@ -0,0 +1,173 @@ + + + diff --git a/components/environments/index.vue b/components/environments/index.vue new file mode 100644 index 00000000000..9ea17141054 --- /dev/null +++ b/components/environments/index.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/components/firebase/login.vue b/components/firebase/login.vue index 0f06d87b254..64581db3404 100644 --- a/components/firebase/login.vue +++ b/components/firebase/login.vue @@ -57,9 +57,9 @@ export default { firebase .auth() .signInWithPopup(provider) - .then(res => { - if (res.additionalUserInfo.isNewUser) { - this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), { + .then(({ additionalUserInfo }) => { + if (additionalUserInfo.isNewUser) { + this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, { icon: "sync", duration: null, closeOnSwipe: false, @@ -86,9 +86,9 @@ export default { firebase .auth() .signInWithPopup(provider) - .then(res => { - if (res.additionalUserInfo.isNewUser) { - this.$toast.info(this.$t("turn_on") + " " + this.$t("sync"), { + .then(({ additionalUserInfo }) => { + if (additionalUserInfo.isNewUser) { + this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, { icon: "sync", duration: null, closeOnSwipe: false, diff --git a/components/graphql/queryeditor.vue b/components/graphql/queryeditor.vue index 7a4e90c659e..56fe6bc3563 100644 --- a/components/graphql/queryeditor.vue +++ b/components/graphql/queryeditor.vue @@ -7,7 +7,9 @@ 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 { @@ -46,10 +48,10 @@ export default { } }, theme() { - this.editor.setTheme("ace/theme/" + this.defineTheme()); + this.editor.setTheme(`ace/theme/${this.defineTheme()}`); }, lang(value) { - this.editor.getSession().setMode("ace/mode/" + value); + this.editor.getSession().setMode(`ace/mode/${value}`); }, options(value) { this.editor.setOptions(value); @@ -57,12 +59,48 @@ export default { }, 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, + 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; @@ -101,14 +139,14 @@ export default { if (this.validationSchema) { this.editor.session.setAnnotations( - gql.validate(this.validationSchema, doc).map(err => { - return { - row: err.locations[0].line - 1, - column: err.locations[0].column - 1, - text: err.message, + gql + .validate(this.validationSchema, doc) + .map(({ locations, message }) => ({ + row: locations[0].line - 1, + column: locations[0].column - 1, + text: message, type: "error" - }; - }) + })) ); } } catch (e) { diff --git a/components/settings/swatch.vue b/components/settings/swatch.vue index 0d0dc870b3b..55373c58d98 100644 --- a/components/settings/swatch.vue +++ b/components/settings/swatch.vue @@ -20,6 +20,7 @@ border-radius: 100%; border: 3px solid var(--bg-dark-color); cursor: pointer; + transition: all 0.2s ease-in-out; &.fg { color: var(--act-color); diff --git a/functions/editorutils.js b/functions/editorutils.js new file mode 100644 index 00000000000..c8e14a5f99f --- /dev/null +++ b/functions/editorutils.js @@ -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"; +} diff --git a/functions/fb.js b/functions/fb.js index c73a655fcd2..32076b51d34 100644 --- a/functions/fb.js +++ b/functions/fb.js @@ -26,6 +26,7 @@ export const fb = { currentSettings: [], currentHistory: [], currentCollections: [], + currentEnvironments: [], writeFeeds: async (message, label) => { const dt = { createdOn: new Date(), @@ -112,6 +113,21 @@ export const fb = { .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)); } }; @@ -186,6 +202,19 @@ firebase.auth().onAuthStateChanged(user => { }); 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; } diff --git a/functions/headers.js b/functions/headers.js index 9fbc2938e51..ffc6b5d5f34 100644 --- a/functions/headers.js +++ b/functions/headers.js @@ -121,4 +121,4 @@ export const commonHeaders = [ "X-Requested-With", "X-Robots-Tag", "X-UA-Compatible" -] +]; diff --git a/functions/network.js b/functions/network.js index 9294ba03638..57cc634b87e 100644 --- a/functions/network.js +++ b/functions/network.js @@ -1,18 +1,28 @@ import AxiosStrategy from "./strategies/AxiosStrategy"; +import ExtensionStrategy, { + hasExtensionInstalled +} from "./strategies/ExtensionStrategy"; import FirefoxStrategy from "./strategies/FirefoxStrategy"; -import ChromeStrategy, { hasChromeExtensionInstalled } from "./strategies/ChromeStrategy"; +import ChromeStrategy, { + hasChromeExtensionInstalled +} from "./strategies/ChromeStrategy"; -const isExtensionsAllowed = ({ state }) => { - return typeof state.postwoman.settings.EXTENSIONS_ENABLED === 'undefined' - || state.postwoman.settings.EXTENSIONS_ENABLED; -} +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); + 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 @@ -22,10 +32,11 @@ const runAppropriateStrategy = (req, store) => { } return AxiosStrategy(req, store); -} +}; const sendNetworkRequest = (req, store) => - runAppropriateStrategy(req, store) - .finally(() => window.$nuxt.$loading.finish()); + runAppropriateStrategy(req, store).finally(() => + window.$nuxt.$loading.finish() + ); export { sendNetworkRequest }; diff --git a/functions/strategies/ChromeStrategy.js b/functions/strategies/ChromeStrategy.js index 03c05ea0caa..fe88338cb2f 100644 --- a/functions/strategies/ChromeStrategy.js +++ b/functions/strategies/ChromeStrategy.js @@ -3,47 +3,54 @@ 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 = () => { - return document.getElementById("chromePWExtensionDetect") !== null; -} +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 - } - }, (message) => { - if (message.data.error) { - reject(message.data.error); - } else { - resolve(message.data.response); +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 +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); } } - }, (message) => { - if (message.data.error) { - reject(error); - } else { - resolve(message.data.response.data); - } - } - ) -}); + ); + }); const chromeStrategy = (req, store) => { if (store.state.postwoman.settings.PROXY_ENABLED) { @@ -51,6 +58,6 @@ const chromeStrategy = (req, store) => { } else { return chromeWithoutProxy(req, store); } -} +}; export default chromeStrategy; diff --git a/functions/strategies/ExtensionStrategy.js b/functions/strategies/ExtensionStrategy.js new file mode 100644 index 00000000000..e12e167e8df --- /dev/null +++ b/functions/strategies/ExtensionStrategy.js @@ -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; diff --git a/lang/en-US.js b/lang/en-US.js index 63b786060b2..bf055db9610 100644 --- a/lang/en-US.js +++ b/lang/en-US.js @@ -45,6 +45,14 @@ export default { 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", @@ -248,7 +256,8 @@ export default { enter_curl: "Enter cURL", empty: "Empty", extensions: "Extensions", - extensions_use_toggle: "Use the browser extension to send requests (if present)", + 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", @@ -259,6 +268,7 @@ export default { sync: "Sync", syncHistory: "History", syncCollections: "Collections", + syncEnvironments: "Environments", turn_on: "Turn on", login_first: "Login first", paste_a_note: "Paste a note", diff --git a/layouts/default.vue b/layouts/default.vue index 4302a71f88e..ed40616edcb 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -247,6 +247,11 @@ brush +
  • + + extensions + +
  • public @@ -408,7 +413,7 @@
    @@ -668,7 +673,7 @@