From 52431e67a4df59e8dff27bb5c2626cb1a280d024 Mon Sep 17 00:00:00 2001 From: Jacob Anavisca Date: Tue, 27 Aug 2019 00:07:41 -0400 Subject: [PATCH 01/12] Added support for headers --- assets/css/styles.scss | 8 ++++++ pages/index.vue | 61 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index 4774b393e..c790d9fd2 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -172,6 +172,14 @@ fieldset.purple legend { color: #C198FB; } +fieldset.orange { + border-color: #FF9800; +} + +fieldset.orange legend { + color: #FF9800; +} + .collapsible.hidden { display: none; } diff --git a/pages/index.vue b/pages/index.vue index 135aa4832..4e437b1f5 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -34,6 +34,7 @@ @@ -103,7 +104,36 @@ - + +
    +
  1. + + +
  2. +
  3. + + +
  4. +
  5. + + +
  6. +
+
    +
  • + + +
  • +
+
    +
  • + + +
  • +
+
+ +
  1. @@ -132,7 +162,7 @@ - +
    • @@ -235,6 +265,7 @@ httpUser: '', httpPassword: '', bearerToken: '', + headers: [], params: [], bodyParams: [], rawParams: '', @@ -287,6 +318,17 @@ }) => `${key}=${encodeURIComponent(value)}`).join('&') } }, + headerString() { + const result = this.headers + .filter(({ + key + }) => !!key) + .map(({ + key, + value + }) => `${key}: ${value}`).join(',\n') + return result == '' ? '' : `${result}` + }, queryString() { const result = this.params .filter(({ @@ -339,6 +381,11 @@ if (this.auth === 'Bearer Token') { xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken); } + if (this.headers) { + this.headers.forEach(function (element) { + xhr.setRequestHeader(element.key, element.value) + }) + } if (this.method === 'POST' || this.method === 'PUT') { const requestBody = this.rawInput ? this.rawParams : this.rawRequestBody; xhr.setRequestHeader('Content-Length', requestBody.length) @@ -375,6 +422,16 @@ this.response.body = xhr.statusText } }, + addRequestHeader() { + this.headers.push({ + key: '', + value: '' + }) + return false + }, + removeRequestHeader(index) { + this.headers.splice(index, 1) + }, addRequestParam() { this.params.push({ key: '', From 30a42907b5cb0ba49799f119cd0880f6947ea28d Mon Sep 17 00:00:00 2001 From: Jacob Anavisca Date: Tue, 27 Aug 2019 00:09:40 -0400 Subject: [PATCH 02/12] Removing test option --- pages/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/index.vue b/pages/index.vue index 4e437b1f5..241e78320 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -34,7 +34,6 @@ From 66268b194cbd15fcf10c386867ff5457020e4689 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Tue, 27 Aug 2019 10:18:41 +0530 Subject: [PATCH 03/12] :lipstick: Minor UI update --- assets/css/styles.scss | 22 +++++++++------------- pages/index.vue | 19 ++++++++++--------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index c790d9fd2..0b820c0f0 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -65,8 +65,7 @@ footer { justify-content: space-between; } - -@media(max-width: $responsiveWidth){ +@media(max-width: $responsiveWidth) { header { display: block; text-align: center; @@ -78,7 +77,6 @@ footer { } } - nav { a:not(:last-of-type) { margin-right: 15px; @@ -173,11 +171,11 @@ fieldset.purple legend { } fieldset.orange { - border-color: #FF9800; + border-color: #F5A623; } fieldset.orange legend { - color: #FF9800; + color: #F5A623; } .collapsible.hidden { @@ -210,7 +208,8 @@ option { input[type="checkbox"] { width: initial; - &, & + label { + &, + & + label { vertical-align: middle; } } @@ -242,18 +241,15 @@ ol li { flex-direction: column; flex-grow: 1; } -.flex-wrap{ + +.flex-wrap { display: flex; justify-content: space-between; -} -.btn-copy{ - padding: 6px 14px; - font-size: 11px; - margin-right: 15px; - + align-items: center; } @media (max-width: $responsiveWidth) { + ul, ol { flex-direction: column; diff --git a/pages/index.vue b/pages/index.vue index 241e78320..ac4c9a6ea 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -69,7 +69,8 @@
    -
    +
    +
    @@ -103,7 +104,7 @@
    - +
    1. @@ -132,7 +133,7 @@ - +
      1. @@ -161,7 +162,7 @@ - +
        • @@ -176,11 +177,11 @@
        • -
          - - -
          - +
          + + +
          +
        From 0d0ec37edfe1403a6823364421df015085681060 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Tue, 27 Aug 2019 13:02:44 +0530 Subject: [PATCH 04/12] :pencil2: Updated features --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 95402d899..5402130fa 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,57 @@ When I wrote this, only God and I understood what I was doing. Now, only God kno ### Features :sparkles: -:heart: **Lightweight and minimal**: Crafted with minimalistic UI design +:heart: **Lightweight**: Crafted with minimalistic UI design -:electric_plug: **Real-time demo**: Send requests and get response right away! + - Faster, lighter, cleaner, minimal & responsive -:robot: **VIBGYOR**: Neon combination of colors for background and foreground +:zap: **Real-time**: Send requests and get/copy responses right away! -:sparkles: **PWA**: Install as a PWA on your device +**Methods:** + - GET - Retrieve information about the REST API resource + - POST - Create a REST API resource + - PUT - Update a REST API resource + - DELETE - Delete a REST API resource or related component + - OPTIONS - Describe the communication options for the target resource. + +_History entries are synced with local session storage_ + +:rainbow: **VIBGYOR**: Neon combination background, foreground & accent colors - because customization === freedom :sparkles: + +**Customizations:** + - Dark and Light background themes + - Choose accent color + - Toggle multi-colored frames + +_Customized themes are also synced with local session storage_ + +:fire: **PWA**: Install as a **[PWA](https://developers.google.com/web/progressive-web-apps)** on your device + +**Features:** + - Instant loading with Service Workers + - Offline support + - Low RAM/memory and CUP usage + +:electric_plug: **Web Socket**: Establish full-duplex communication channels over a single TCP connection + + - Send and receive data + +:closed_lock_with_key: **Authentication**: Allows to identity the end user + +**Types:** + - None + - Basic authentication using username and password + - Token based authentication + +:loudspeaker: **Headers**: Describes the format the body of your request is being sent as + +:mailbox: **Parameters**: Use request parameters to set varying parts in simulated requests + +:mailbox: **Request Body**: Used to send and receive data via the REST API + +**Options:** + - Set content Type + - Toggle between RAW input and parameter list --- From 36a07290f224e987ac968e13873ab6630ac2d375 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Tue, 27 Aug 2019 13:04:06 +0530 Subject: [PATCH 05/12] :pencil2: Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5402130fa..882df0b82 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ _Customized themes are also synced with local session storage_ :mailbox: **Parameters**: Use request parameters to set varying parts in simulated requests -:mailbox: **Request Body**: Used to send and receive data via the REST API +:page_with_curl: **Request Body**: Used to send and receive data via the REST API **Options:** - Set content Type From f265046676485480d9d654f2647921a02c073524 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Tue, 27 Aug 2019 17:22:24 +0530 Subject: [PATCH 06/12] :rotating_light: Lint --- assets/css/styles.scss | 17 +- components/settings/swatch.vue | 11 +- pages/index.vue | 518 ++++++++++++++++----------------- pages/settings.vue | 246 ++++++++-------- pages/websocket.vue | 184 +++++------- 5 files changed, 470 insertions(+), 506 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index 0b820c0f0..c58fca5ab 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -20,16 +20,6 @@ $responsiveWidth: 720px; font-family: "Poppins", "Roboto", "Noto", sans-serif; } -@keyframes fadein { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - a { display: inline-flex; color: inherit; @@ -42,7 +32,6 @@ body { color: var(--fg-color); font-weight: 500; line-height: 1.5; - animation: fadein 0.2s; -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; -webkit-user-select: none; @@ -56,6 +45,10 @@ h3 { font-weight: 700; } +h3.title { + margin: 4px; +} + header, footer { display: flex; @@ -85,9 +78,9 @@ nav { body.sticky-footer footer { position: fixed; + right: 0; bottom: 0; left: 0; - right: 0; } .logo { diff --git a/components/settings/swatch.vue b/components/settings/swatch.vue index 262c718f2..40f9bd1b1 100644 --- a/components/settings/swatch.vue +++ b/components/settings/swatch.vue @@ -12,10 +12,11 @@ display: inline-block; vertical-align: middle; - padding: 8px 15px; - margin: 5px; + padding: 8px 16px; + margin: 4px; background-color: rgba(93, 93, 93, 0.2); border-radius: 4px; + cursor: pointer; &.active { background-color: rgba(93, 93, 93, 0.3); @@ -24,10 +25,10 @@ .preview { vertical-align: middle; display: inline-block; - width: 36px; - height: 36px; + width: 32px; + height: 32px; border-radius: 100%; - margin-right: 10px; + margin-right: 8px; position: relative; .activeTick { diff --git a/pages/index.vue b/pages/index.vue index ac4c9a6ea..2cb4ddc04 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -1,6 +1,5 @@ - diff --git a/pages/settings.vue b/pages/settings.vue index bb34e09d5..c5a11311a 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -1,126 +1,130 @@ - \ No newline at end of file + } + + diff --git a/pages/websocket.vue b/pages/websocket.vue index cd371346c..d7334b479 100644 --- a/pages/websocket.vue +++ b/pages/websocket.vue @@ -1,6 +1,5 @@ - + From 8912004dcc92889adc368faed1be9902aa518924 Mon Sep 17 00:00:00 2001 From: NBTX Date: Wed, 28 Aug 2019 01:10:00 +0100 Subject: [PATCH 07/12] Adds HTML preview, solves https://github.com/liyasthomas/postwoman/issues/41 --- assets/css/styles.scss | 28 +++++++++- pages/index.vue | 113 +++++++++++++++++++++++++++++------------ 2 files changed, 107 insertions(+), 34 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index c58fca5ab..2e8da6c47 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -171,7 +171,7 @@ fieldset.orange legend { color: #F5A623; } -.collapsible.hidden { +.hidden { display: none; } @@ -290,3 +290,29 @@ fieldset#history { } } } + +.align-left { text-align: left; } +.align-right { text-align: right; } + +#response-details-wrapper { + position: relative; + overflow: hidden; + border-radius: 4px; + margin: 4px; + + #response-details { + margin: 0; + } + + .covers-response { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: white; + + height: 100%; + width: 100%; + } +} \ No newline at end of file diff --git a/pages/index.vue b/pages/index.vue index 2cb4ddc04..ce4828dec 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -175,7 +175,15 @@ - + +
        + + +
        + +
        + +
      2. @@ -279,7 +287,8 @@ headers: '', body: '' }, - history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : [] + history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : [], + previewEnabled: false } }, computed: { @@ -340,6 +349,10 @@ value }) => `${key}=${encodeURIComponent(value)}`).join('&') return result == '' ? '' : `?${result}` + }, + + responseType () { + return (this.response.headers['content-type'] || '').split(';')[0].toLowerCase(); } }, methods: { @@ -367,66 +380,78 @@ }) }, sendRequest() { + if (!this.isValidURL) { + alert('Please check the formatting of the URL'); + return + } + if (this.$refs.response.$el.classList.contains('hidden')) { this.$refs.response.$el.classList.toggle('hidden') } + this.$refs.response.$el.scrollIntoView({ behavior: 'smooth' - }) - this.response.status = 'Fetching...' - this.response.body = 'Loading...' - const xhr = new XMLHttpRequest() - const user = this.auth === 'Basic' ? this.httpUser : null - const pswd = this.auth === 'Basic' ? this.httpPassword : null - xhr.open(this.method, this.url + this.path + this.queryString, true, user, pswd) - if (this.auth === 'Bearer Token') { - xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken); - } + }); + + this.response.status = 'Fetching...'; + this.response.body = 'Loading...'; + + const xhr = new XMLHttpRequest(); + const user = this.auth === 'Basic' ? this.httpUser : null; + const password = this.auth === 'Basic' ? this.httpPassword : null; + xhr.open(this.method, this.url + this.path + this.queryString, true, user, password); + + if (this.auth === 'Bearer Token') xhr.setRequestHeader( + 'Authorization', + 'Bearer ' + this.bearerToken + ); + if (this.headers) { this.headers.forEach(function(element) { xhr.setRequestHeader(element.key, element.value) }) } + if (this.method === 'POST' || this.method === 'PUT') { const requestBody = this.rawInput ? this.rawParams : this.rawRequestBody; - xhr.setRequestHeader('Content-Length', requestBody.length) - xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`) - xhr.send(requestBody) + xhr.setRequestHeader('Content-Length', requestBody.length); + xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`); + xhr.send(requestBody); } else { - xhr.send() + xhr.send(); } + xhr.onload = e => { - this.response.status = xhr.status - const headers = this.response.headers = parseHeaders(xhr) + this.response.status = xhr.status; + const headers = this.response.headers = parseHeaders(xhr); + + this.response.body = xhr.responseText; if ((headers['content-type'] || '').startsWith('application/json')) { - this.response.body = JSON.stringify(JSON.parse(xhr.responseText), null, 2) - } else { - this.response.body = xhr.responseText + this.response.body = JSON.stringify(JSON.parse(this.response.body), null, 2); } - if (!this.isValidURL) { - alert('Please check the formatting of the URL'); - return - } - const n = new Date().toLocaleTimeString() + + const n = new Date().toLocaleTimeString(); this.history = [{ status: xhr.status, time: n, method: this.method, url: this.url, path: this.path - }, ...this.history] - window.localStorage.setItem('history', JSON.stringify(this.history)) - } + }, ...this.history]; + window.localStorage.setItem('history', JSON.stringify(this.history)); + }; + xhr.onerror = e => { - this.response.status = xhr.status - this.response.body = xhr.statusText + this.response.status = xhr.status; + this.response.body = xhr.statusText; } }, addRequestHeader() { this.headers.push({ key: '', value: '' - }) + }); + return false }, removeRequestHeader(index) { @@ -474,12 +499,34 @@ return false; } }, + copyResponse() { var copyText = document.getElementById("response-details"); copyText.select(); document.execCommand("copy"); + }, + + togglePreview () { + this.previewEnabled = !this.previewEnabled; + + if(this.previewEnabled) { + // If you want to add 'preview' support for other response types, + // just add them here. + if(this.responseType === "text/html"){ + // If the preview already has that URL loaded, let's not bother re-loading it all. + if(this.$refs.previewFrame.getAttribute('data-previewing-url') === this.url) + return; + + // Use DOMParser to parse document HTML. + const previewDocument = new DOMParser().parseFromString(this.response.body, this.responseType); + // Inject tag to head, to fix relative CSS/HTML paths. + previewDocument.head.innerHTML = `` + previewDocument.head.innerHTML; + // Finally, set the iframe source to the resulting HTML. + this.$refs.previewFrame.srcdoc = previewDocument.documentElement.outerHTML; + this.$refs.previewFrame.setAttribute('data-previewing-url', this.url); + } + } } } } - From 38f6f4ef2eff2976003ce8674045c08b30dc9e73 Mon Sep 17 00:00:00 2001 From: NBTX Date: Wed, 28 Aug 2019 01:32:37 +0100 Subject: [PATCH 08/12] Close preview when a new request is made --- pages/index.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/index.vue b/pages/index.vue index ce4828dec..d9f0acc77 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -393,6 +393,7 @@ behavior: 'smooth' }); + this.previewEnabled = false; this.response.status = 'Fetching...'; this.response.body = 'Loading...'; From 1a38f519f4cfa9fc53ec9e180bf42fd2619d4c0f Mon Sep 17 00:00:00 2001 From: Nicholas Palenchar Date: Tue, 27 Aug 2019 21:01:01 -0400 Subject: [PATCH 09/12] fixes #74 fallback for findEntryStatus when match is missing or otherwise invalid --- assets/css/styles.scss | 4 ++++ pages/index.vue | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index c58fca5ab..1c061a7f3 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -278,6 +278,10 @@ ol li { background-color: #B71C1C; } +.missing-data-response { + background-color: #676767; +} + fieldset#history { .method-list-item { position: relative; diff --git a/pages/index.vue b/pages/index.vue index 2cb4ddc04..2d07d9103 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -241,6 +241,13 @@ statusCodeRegex: new RegExp(/[5][0-9]+/), className: 'sv-error-response' }, + { + // this object is a catch-all for when no other objects match and should always be last + name: 'unknown', + statusCodeRegex: new RegExp(/.*/), + className: 'missing-data-response' + } + ]; const parseHeaders = xhr => { const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/); From ae2d99675455dbf3dd71a976d1ab0eb9b48cff9b Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Wed, 28 Aug 2019 10:02:40 +0530 Subject: [PATCH 10/12] :art: Fixed few UI glitches --- assets/css/styles.scss | 45 +++++++++++++++++++++-------------- layouts/default.vue | 54 +++++++++++++++++++++++------------------- pages/index.vue | 47 +++++++++++------------------------- pages/websocket.vue | 4 ++-- 4 files changed, 72 insertions(+), 78 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index ec5240a09..bb0e3b2cb 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -58,18 +58,6 @@ footer { justify-content: space-between; } -@media(max-width: $responsiveWidth) { - header { - display: block; - text-align: center; - - nav { - display: inline-flex; - margin-top: 20px; - } - } -} - nav { a:not(:last-of-type) { margin-right: 15px; @@ -182,8 +170,8 @@ textarea, pre { margin: 4px; padding: 8px 16px; - width: calc(100% - 8px); border-radius: 4px; + width: calc(100% - 8px); background-color: var(--bg-dark-color); color: var(--fg-color); font-weight: 700; @@ -195,7 +183,7 @@ pre { select, input, option { - height: 38px; + height: 41px; } input[type="checkbox"] { @@ -242,6 +230,15 @@ ol li { } @media (max-width: $responsiveWidth) { + header { + display: block; + text-align: center; + + nav { + display: inline-flex; + margin-top: 20px; + } + } ul, ol { @@ -252,6 +249,10 @@ ol li { ol li { display: flex; } + + .hide-on-small-screen { + display: none; + } } #installPWA { @@ -295,8 +296,13 @@ fieldset#history { } } -.align-left { text-align: left; } -.align-right { text-align: right; } +.align-left { + text-align: left; +} + +.align-right { + text-align: right; +} #response-details-wrapper { position: relative; @@ -304,6 +310,10 @@ fieldset#history { border-radius: 4px; margin: 4px; + textarea { + width: 100%; + } + #response-details { margin: 0; } @@ -315,8 +325,7 @@ fieldset#history { right: 0; bottom: 0; background-color: white; - height: 100%; width: 100%; } -} \ No newline at end of file +} diff --git a/layouts/default.vue b/layouts/default.vue index 7f439597a..aa5f2f463 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -3,55 +3,54 @@
        -

        Postwoman

        +

        + Postwoman

        API request builder

        -
        - - - + diff --git a/pages/index.vue b/pages/index.vue index 495f28c7d..95fd0c97c 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -21,7 +21,7 @@
      3. - +
      4. @@ -51,7 +51,7 @@
      5. - +
      @@ -111,7 +111,7 @@
    2. - +
    @@ -139,7 +139,7 @@
  2. - +
@@ -175,12 +175,10 @@ -
-
@@ -212,11 +210,11 @@
  • - +
  • - +
  • @@ -255,7 +253,6 @@ statusCodeRegex: new RegExp(/.*/), className: 'missing-data-response' } - ]; const parseHeaders = xhr => { const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/); @@ -357,8 +354,7 @@ }) => `${key}=${encodeURIComponent(value)}`).join('&') return result == '' ? '' : `?${result}` }, - - responseType () { + responseType() { return (this.response.headers['content-type'] || '').split(';')[0].toLowerCase(); } }, @@ -391,35 +387,28 @@ alert('Please check the formatting of the URL'); return } - if (this.$refs.response.$el.classList.contains('hidden')) { this.$refs.response.$el.classList.toggle('hidden') } - this.$refs.response.$el.scrollIntoView({ behavior: 'smooth' }); - this.previewEnabled = false; this.response.status = 'Fetching...'; this.response.body = 'Loading...'; - const xhr = new XMLHttpRequest(); const user = this.auth === 'Basic' ? this.httpUser : null; const password = this.auth === 'Basic' ? this.httpPassword : null; xhr.open(this.method, this.url + this.path + this.queryString, true, user, password); - if (this.auth === 'Bearer Token') xhr.setRequestHeader( - 'Authorization', - 'Bearer ' + this.bearerToken + 'Authorization', + 'Bearer ' + this.bearerToken ); - if (this.headers) { this.headers.forEach(function(element) { xhr.setRequestHeader(element.key, element.value) }) } - if (this.method === 'POST' || this.method === 'PUT') { const requestBody = this.rawInput ? this.rawParams : this.rawRequestBody; xhr.setRequestHeader('Content-Length', requestBody.length); @@ -428,16 +417,13 @@ } else { xhr.send(); } - xhr.onload = e => { this.response.status = xhr.status; const headers = this.response.headers = parseHeaders(xhr); - this.response.body = xhr.responseText; if ((headers['content-type'] || '').startsWith('application/json')) { this.response.body = JSON.stringify(JSON.parse(this.response.body), null, 2); } - const n = new Date().toLocaleTimeString(); this.history = [{ status: xhr.status, @@ -448,7 +434,6 @@ }, ...this.history]; window.localStorage.setItem('history', JSON.stringify(this.history)); }; - xhr.onerror = e => { this.response.status = xhr.status; this.response.body = xhr.statusText; @@ -459,7 +444,6 @@ key: '', value: '' }); - return false }, removeRequestHeader(index) { @@ -507,24 +491,20 @@ return false; } }, - copyResponse() { var copyText = document.getElementById("response-details"); copyText.select(); document.execCommand("copy"); }, - - togglePreview () { + togglePreview() { this.previewEnabled = !this.previewEnabled; - - if(this.previewEnabled) { + if (this.previewEnabled) { // If you want to add 'preview' support for other response types, // just add them here. - if(this.responseType === "text/html"){ + if (this.responseType === "text/html") { // If the preview already has that URL loaded, let's not bother re-loading it all. - if(this.$refs.previewFrame.getAttribute('data-previewing-url') === this.url) + if (this.$refs.previewFrame.getAttribute('data-previewing-url') === this.url) return; - // Use DOMParser to parse document HTML. const previewDocument = new DOMParser().parseFromString(this.response.body, this.responseType); // Inject tag to head, to fix relative CSS/HTML paths. @@ -537,4 +517,5 @@ } } } + diff --git a/pages/websocket.vue b/pages/websocket.vue index d7334b479..1d0d8d1da 100644 --- a/pages/websocket.vue +++ b/pages/websocket.vue @@ -7,7 +7,7 @@
  • - +
  • @@ -30,7 +30,7 @@
  • - +
  • From 16523814448969f75c108a0abb0336aea8ecb9a7 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Wed, 28 Aug 2019 10:47:31 +0530 Subject: [PATCH 11/12] :art: Styled input checkbox --- assets/css/styles.scss | 23 ++++++++++++++++++++++- pages/settings.vue | 11 +++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index bb0e3b2cb..9c7a5de8a 100644 --- a/assets/css/styles.scss +++ b/assets/css/styles.scss @@ -187,11 +187,32 @@ option { } input[type="checkbox"] { - width: initial; + display: none; &, & + label { vertical-align: middle; + cursor: pointer; + + &:before { + content: "\2714"; + border: 2px solid var(--fg-color); + border-radius: 4px; + display: inline-flex; + height: 16px; + width: 16px; + align-items: center; + justify-content: center; + margin: 8px 8px 8px 0; + color: transparent; + transition: .2s; + } + } + + &:checked + label:before { + background-color: var(--ac-color); + border-color: var(--ac-color); + color: var(--act-color); } } diff --git a/pages/settings.vue b/pages/settings.vue index c5a11311a..fa6b17d7a 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -19,10 +19,13 @@
    -

    - - -

    + + + From f004a9c322d94e302154457bd40b75348588bdb2 Mon Sep 17 00:00:00 2001 From: Liyas Thomas Date: Wed, 28 Aug 2019 14:27:42 +0530 Subject: [PATCH 12/12] :pencil2: Updated features list and added 'Story behind Postwoman' --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 882df0b82..515307816 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,9 @@ When I wrote this, only God and I understood what I was doing. Now, only God kno # postwoman Postwoman -### 👽 API request builder by [Liyas Thomas](https://github.com/liyasthomas) +### API request builder + +**Start here: _[Story behind Postwoman](https://dev.to/liyasthomas/i-created-postwoman-an-online-open-source-api-request-builder-41md)_**

    @@ -80,6 +82,21 @@ _Customized themes are also synced with local session storage_ - Set content Type - Toggle between RAW input and parameter list +:wave: **Responses**: Contains the status line, headers and the message/response body + +_HTML responses have "Preview HTML" feature_ + +:: **History**: Request entries are synced with local session storage to reuse with a single click + +**Fields** + - Timestamp + - Method + - Status code + - URL + - Path + +_History entries can be deleted one-by-one or all together_ + --- ## Demo @@ -155,6 +172,7 @@ See the [CHANGELOG](CHANGELOG.md) file for details. ### Testing and Debugging * [Liyas Thomas](https://github.com/liyasthomas) +* ([contributors](https://github.com/liyasthomas/postwoman/graphs/contributors)) ### Contributors * [NBTX](https://github.com/NBTX)