diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..630e82e79 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# https://editorconfig.org + +root = true + +[*] +indent_size = 2 +indent_style = space +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore index 8c6652cb0..0a9095b32 100644 --- a/.gitignore +++ b/.gitignore @@ -79,7 +79,6 @@ dist # IDE / Editor .idea -.editorconfig # Service worker sw.* diff --git a/README.md b/README.md index 882df0b82..3c14dbeea 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)_**

@@ -35,11 +37,13 @@ When I wrote this, only God and I understood what I was doing. Now, only God kno :zap: **Real-time**: Send requests and get/copy responses right away! **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. + - `GET` - Retrieve information about the REST API resource + - `HEAD` - Asks for a response identical to that of a GET request, but without the response body. + - `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 + - `PATCH` - Applies partial modifications to a REST API resource _History entries are synced with local session storage_ @@ -57,7 +61,7 @@ _Customized themes are also synced with local session storage_ **Features:** - Instant loading with Service Workers - Offline support - - Low RAM/memory and CUP usage + - Low RAM/memory and CPU usage :electric_plug: **Web Socket**: Establish full-duplex communication channels over a single TCP connection @@ -80,6 +84,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_ + +:alarm_clock: **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 +174,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) diff --git a/assets/css/styles.scss b/assets/css/styles.scss index 2e8da6c47..76364d5f8 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,15 +183,36 @@ pre { select, input, option { - height: 38px; + height: 41px; } 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); } } @@ -242,6 +251,15 @@ ol li { } @media (max-width: $responsiveWidth) { + header { + display: block; + text-align: center; + + nav { + display: inline-flex; + margin-top: 20px; + } + } ul, ol { @@ -252,6 +270,10 @@ ol li { ol li { display: flex; } + + .hide-on-small-screen { + display: none; + } } #installPWA { @@ -278,6 +300,14 @@ ol li { background-color: #B71C1C; } +.missing-data-response { + background-color: #676767; +} + +.virtual-list::-webkit-scrollbar { + width: 0; +} + fieldset#history { .method-list-item { position: relative; @@ -291,8 +321,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; @@ -300,6 +335,10 @@ fieldset#history { border-radius: 4px; margin: 4px; + textarea { + width: 100%; + } + #response-details { margin: 0; } @@ -311,8 +350,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..3d8273a69 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -3,55 +3,54 @@
-

Postwoman

+

+ Postwoman

API request builder

-
- -
- + diff --git a/package-lock.json b/package-lock.json index a4a37c695..23c80fb45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9997,6 +9997,11 @@ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==" }, + "vue-virtual-scroll-list": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.4.2.tgz", + "integrity": "sha512-jcXl1cYDxGZX+aF9vsUauXWnUkXm8oQxnvLTJ8UMTmMxwzbmlHX7vs0xGDdEej91vJpBNrdNNseWPxboTvI+UA==" + }, "vuex": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.1.tgz", diff --git a/package.json b/package.json index 0230a2b48..fce0bb2d3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@nuxtjs/pwa": "^3.0.0-0", "nuxt": "^2.0.0", + "vue-virtual-scroll-list": "^1.4.2", "vuex-persist": "^2.0.1" }, "devDependencies": { diff --git a/pages/index.vue b/pages/index.vue index d9f0acc77..bfa91faa1 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -6,10 +6,12 @@
  • @@ -21,12 +23,12 @@
  • - +
  • - + - + +
      +
    • + + +
    • +
    • + + + {{entry.status}} +
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    diff --git a/pages/settings.vue b/pages/settings.vue index 9ed43f5df..04a968cd9 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -19,10 +19,13 @@ -

    - - -

    + + +
    @@ -126,6 +129,13 @@ applyTheme(name) { this.applySetting('THEME_CLASS', name); 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. diff --git a/pages/websocket.vue b/pages/websocket.vue index d7334b479..c374e04ea 100644 --- a/pages/websocket.vue +++ b/pages/websocket.vue @@ -7,7 +7,7 @@
  • - +
  • @@ -18,7 +18,7 @@
    - {{ getSourcePrefix(logEntry.source) }} {{ logEntry.payload }} + @ {{ logEntry.ts }} {{ getSourcePrefix(logEntry.source) }} {{ logEntry.payload }} (Waiting for connection...)
    @@ -30,7 +30,7 @@
  • - +
  • @@ -113,7 +113,8 @@ this.communication.log = [{ payload: `Connected to ${this.url}.`, source: 'info', - color: 'lime' + color: 'lime', + ts: (new Date()).toLocaleTimeString() }]; }; this.socket.onerror = (event) => { @@ -124,13 +125,15 @@ this.communication.log.push({ payload: `Disconnected from ${this.url}.`, source: 'info', - color: 'red' + color: 'red', + ts: (new Date()).toLocaleTimeString() }); }; this.socket.onmessage = (event) => { this.communication.log.push({ payload: event.data, - source: 'server' + source: 'server', + ts: (new Date()).toLocaleTimeString() }); } } catch (ex) { @@ -146,12 +149,14 @@ this.communication.log.push({ payload: `An error has occurred.`, source: 'info', - color: 'red' + color: 'red', + ts: (new Date()).toLocaleTimeString() }); if (error != null) this.communication.log.push({ payload: error, source: 'info', - color: 'red' + color: 'red', + ts: (new Date()).toLocaleTimeString() }); }, sendMessage() { @@ -159,7 +164,8 @@ this.socket.send(message); this.communication.log.push({ payload: message, - source: 'client' + source: 'client', + ts: (new Date()).toLocaleTimeString() }); this.communication.input = ""; }, @@ -172,15 +178,21 @@ getSourcePrefix(source) { const sourceEmojis = { // Source used for info messages. - 'info': 'ℹ️ [INFO]:\t', + 'info': '\tℹ️ [INFO]:\t', // Source used for client to server messages. - 'client': '👽 [SENT]:\t', + 'client': '\t👽 [SENT]:\t', // Source used for server to client messages. - 'server': '📥 [RECEIVED]:\t' + '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) + }) } }