Merge branch 'master' into sync-path-and-parameters

This commit is contained in:
Hossein Nedaee
2019-09-23 00:47:36 +03:30
21 changed files with 439 additions and 367 deletions

View File

@@ -1,6 +0,0 @@
[Dolphin]
Timestamp=2019,8,23,13,58,13
Version=4
[Settings]
HiddenFilesShown=true

3
.gitignore vendored
View File

@@ -91,3 +91,6 @@ sw.*
# Postwoman build data
.postwoman
# File explorer
.directory

View File

@@ -13,7 +13,7 @@ When I wrote this, only God and I understood what I was doing. Now, only God kno
---
[![Build Status](https://travis-ci.com/liyasthomas/postwoman.svg?branch=master)](https://travis-ci.com/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all.svg)](https://github.com/liyasthomas/postwoman/releases/latest) [![repo size](https://img.shields.io/github/repo-size/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/archive/master.zip) [![license](https://img.shields.io/github/license/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/blob/master/LICENSE) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/liyasthomas/postwoman/issues) [![Website](https://img.shields.io/website-up-down-green-red/https/shields.io.svg?label=website)](https://liyas-thomas.firebaseapp.com) [![Donate](https://img.shields.io/badge/$-donate-ff69b4.svg)](https://www.paypal.me/liyascthomas) [![Buy me a coffee](https://img.shields.io/badge/$-BuyMeACoffee-orange.svg)](https://www.buymeacoffee.com/liyasthomas)
[![Build Status](https://travis-ci.com/liyasthomas/postwoman.svg?branch=master)](https://travis-ci.com/liyasthomas/postwoman) [![GitHub release](https://img.shields.io/github/release/liyasthomas/postwoman/all.svg)](https://github.com/liyasthomas/postwoman/releases/latest) [![repo size](https://img.shields.io/github/repo-size/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/archive/master.zip) [![license](https://img.shields.io/github/license/liyasthomas/postwoman.svg)](https://github.com/liyasthomas/postwoman/blob/master/LICENSE) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/liyasthomas/postwoman/issues) [![Website](https://img.shields.io/website-up-down-green-red/https/shields.io.svg?label=website)](https://liyas-thomas.firebaseapp.com) [![Donate](https://img.shields.io/badge/$-donate-blue.svg)](https://www.paypal.me/liyascthomas) [![Buy me a coffee](https://img.shields.io/badge/$-BuyMeACoffee-orange.svg)](https://www.buymeacoffee.com/liyasthomas) [![Chat on Telegram](https://img.shields.io/badge/chat-Telegram-blueviolet)](https://t.me/postwoman_app) [![Chat on Discord](https://img.shields.io/badge/chat-Discord-violet?logo=discord)](https://discord.gg/GAMWxmR)
# <img src="static/icon.png" alt="postwoman" width="32"> Postwoman
@@ -21,6 +21,8 @@ When I wrote this, only God and I understood what I was doing. Now, only God kno
**Start here: _[Story behind Postwoman](https://dev.to/liyasthomas/i-created-postwoman-an-online-open-source-api-request-builder-41md)_**
**Chat here: _[Telegram](https://t.me/postwoman_app), [Discord](https://discord.gg/GAMWxmR)_**
<div align="center">
<br>
<img src="static/screenshot.gif" alt="postwoman" width="100%">
@@ -205,6 +207,9 @@ See the [CHANGELOG](CHANGELOG.md) file for details.
<td align="center"><a href="https://github.com/larouxn"><img src="https://github.com/larouxn.png?size=100" 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/JacobAnavisca"><img src="https://github.com/JacobAnavisca.png?size=100" 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>
</tr>
<tr>
<td align="center"><a href="https://github.com/nityanandagohain"><img src="https://github.com/nityanandagohain.png?size=100" 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>
</tr>
</table>
<!-- ALL-CONTRIBUTORS-LIST:END -->

View File

@@ -1,2 +1,2 @@
// Poppins (Google Fonts)
@import url("https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap");
@import url("https://fonts.googleapis.com/css?family=Poppins:400,600&display=swap");

View File

@@ -11,15 +11,17 @@ $responsiveWidth: 720px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.3);
border-radius: 8px;
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, 0.6);
background-color: rgba(0, 0, 0, 0.5);
}
::placeholder {
color: var(--fg-color);
color: var(--fg-light-color);
opacity: 0.3;
}
* {
@@ -32,25 +34,26 @@ a {
display: inline-flex;
color: inherit;
text-decoration: none;
font-weight: 700;
font-weight: 600;
}
body {
background-color: var(--bg-color);
color: var(--fg-color);
font-weight: 500;
font-weight: 400;
font-size: 16px;
font-family: "Poppins", "Roboto", "Noto", sans-serif;
line-height: 1.5;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
font-family: "Poppins", "Roboto", "Noto", sans-serif;
}
h1,
h2,
h3 {
margin: 0;
font-weight: 700;
font-weight: 600;
}
h3.title {
@@ -90,16 +93,18 @@ button {
align-items: center;
justify-content: center;
margin: 4px;
padding: 8px 16px;
border-radius: 4px;
padding: 0 16px;
border-radius: 20px;
background-color: var(--ac-color);
color: var(--act-color);
font-weight: 700;
font-weight: 600;
font-size: 16px;
font-family: "Poppins", "Roboto", "Noto", sans-serif;
cursor: pointer;
transition: all 0.2s ease-in-out;
fill: var(--act-color);
height: 40px;
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.02);
cursor: pointer;
span {
display: inline-flex;
@@ -108,28 +113,31 @@ button {
&.icon {
background-color: var(--bg-color);
color: var(--ac-color);
fill: var(--ac-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):focus {
background-color: var(--bg-color);
box-shadow: inset 0 0 0 2px var(--ac-color);
color: var(--ac-color);
fill: var(--ac-color);
&:not([disabled]):hover {
color: var(--act-color);
fill: var(--act-color);
}
}
fieldset {
margin: 16px 0;
border: 2px solid var(--fg-color);
border-radius: 4px;
border: 1px solid var(--brd-color);
border-radius: 8px;
background-color: var(--bg-color);
}
legend {
color: var(--fg-color);
font-weight: 700;
font-weight: 600;
cursor: pointer;
}
@@ -138,74 +146,38 @@ fieldset pre code {
resize: vertical;
}
fieldset.blue {
border-color: #57b5f9;
}
fieldset.blue legend {
color: #57b5f9;
}
fieldset.gray {
border-color: #bcc2cd;
}
fieldset.gray legend {
color: #bcc2cd;
}
fieldset.green {
border-color: #50fa7b;
}
fieldset.green legend {
color: #50fa7b;
}
fieldset.cyan {
border-color: #8be9fd;
}
fieldset.cyan legend {
color: #8be9fd;
}
fieldset.purple {
border-color: #bd93f9;
}
fieldset.purple legend {
color: #bd93f9;
}
fieldset.orange {
border-color: #ffb86c;
}
fieldset.orange legend {
color: #ffb86c;
}
fieldset.pink {
border-color: #ff79c6;
}
fieldset.pink legend {
color: #ff79c6;
}
fieldset.red {
border-color: #ff5555;
}
fieldset.red legend {
color: #ff5555;
}
fieldset.yellow {
border-color: #f1fa8c;
}
fieldset.yellow legend {
color: #f1fa8c;
}
@@ -221,19 +193,18 @@ textarea,
pre {
margin: 4px;
padding: 8px;
border-radius: 4px;
width: calc(100% - 8px);
border-radius: 8px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
font-size: 18px;
font-size: 16px;
font-family: monospace;
transition: all 0.2s ease-in-out;
user-select: all;
user-select: text;
width: calc(100% - 8px);
min-height: 40px;
&:not([readonly]):hover,
&:not([readonly]):focus {
background-color: var(--bg-color);
box-shadow: inset 0 0 0 2px var(--ac-color);
&:not([readonly]):hover {
background-color: var(--bg-dark-color);
}
}
@@ -243,6 +214,7 @@ pre {
code {
height: 336px;
border-radius: 8px;
}
.hljs,
@@ -254,7 +226,7 @@ code {
select,
input,
option {
height: 41px;
height: 40px;
}
input[type="checkbox"] {
@@ -267,8 +239,8 @@ input[type="checkbox"] {
&:before {
content: "\2714";
border: 2px solid var(--fg-color);
border-radius: 4px;
border: 1px solid var(--fg-color);
border-radius: 8px;
display: inline-flex;
height: 16px;
width: 16px;
@@ -276,7 +248,7 @@ input[type="checkbox"] {
justify-content: center;
margin: 8px 8px 8px 0;
color: transparent;
transition: 0.2s;
transition: all 0.2s ease-in-out;
}
}
@@ -291,18 +263,19 @@ input[type="checkbox"] {
.disabled,
[disabled] {
background-color: var(--err-color);
color: #b2b2b2;
fill: #b2b2b2;
color: var(--fg-light-color);
fill: var(--fg-light-color);
cursor: default;
&.icon {
color: #b2b2b2;
fill: #b2b2b2;
color: var(--bg-color);
fill: var(--bg-color);
}
}
label {
padding: 4px;
color: var(--fg-light-color);
}
ul,
@@ -366,23 +339,23 @@ ol li {
}
.info-response {
background-color: #ffeb3b;
color: #ffeb3b;
}
.success-response {
background-color: #4bb543;
color: #4bb543;
}
.redir-response {
background-color: #ff5722;
color: #ff5722;
}
.cl-error-response {
background-color: #a63232;
color: #a63232;
}
.sv-error-response {
background-color: #b71c1c;
color: #b71c1c;
}
.missing-data-response {
@@ -399,7 +372,7 @@ fieldset#history {
span {
position: absolute;
top: 44px;
top: 12px;
right: 12px;
font-family: monospace, monospace;
}
@@ -421,7 +394,7 @@ fieldset#history {
#response-details-wrapper {
position: relative;
overflow: hidden;
border-radius: 4px;
border-radius: 8px;
textarea {
margin: 0;
@@ -478,15 +451,15 @@ input[type="radio"] + label {
padding: 8px 16px;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: all 0.2s ease;
transition: all 0.2s ease-in-out;
&:hover {
border-color: var(--err-color);
border-color: var(--brd-color);
}
}
input[type="radio"]:checked + label {
border-color: var(--ac-color);
border-color: var(--fg-color);
}
input[type="radio"]:checked + label + div.tab {

View File

@@ -7,37 +7,43 @@
// Dark is the default theme variant.
:root {
--bg-dark-color: #44475a;
// Dark Background color
--bg-dark-color: rgb(41, 42, 45);
// Background color
--bg-color: #282a36;
--bg-color: rgb(37, 38, 40);
// Auto-complete color
--atc-color: #3C4556;
--atc-color: rgb(49, 49, 55);
// Text color
--fg-color: #f8f8f2;
--fg-color: rgb(247, 248, 248);
// Light Text color
--fg-light-color: rgb(150, 155, 160);
// Border color
--brd-color: rgb(48, 47, 55);
// Error color
--err-color: #3C4556;
// Active color
--err-color: rgb(41, 42, 45);
// Acent color
--ac-color: #50fa7b;
// Active text color
--act-color: #282a36;
--act-color: rgb(37, 38, 40);
}
:root.light {
--bg-dark-color: #e1e4eb;
// Dark Background color
--bg-dark-color: #e8f0fe;
// Background color
--bg-color: #ebeef5;
--bg-color: #fff;
// Auto-complete color
--atc-color: #e1e4eb;
--atc-color: #ebebeb;
// Text color
--fg-color: #5d5d5f;
--fg-color: #525252;
// Light Text color
--fg-light-color: rgb(150, 155, 160);
// Border color
--brd-color: #f2f2f2;
// Error color
--err-color: invert(#3C4556, 1);
// Active color
--err-color: invert(#303341, 1);
// Acent color
--ac-color: #57b5f9;
// Active text color
--act-color: #ebeef5;
--act-color: #fff;
}

View File

@@ -40,7 +40,7 @@ function parseCurlCommand(curlCommand) {
if (!url) {
for (let argName in parsedArguments) {
if (typeof parsedArguments[argName] === 'string') {
if (parsedArguments[argName].indexOf('http') === 0 || parsedArguments[argName].indexOf('www.') === 0) {
if (['http', 'www.'].includes(parsedArguments[argName])) {
url = parsedArguments[argName];
}
}
@@ -57,7 +57,7 @@ function parseCurlCommand(curlCommand) {
parsedArguments[headerFieldName] = [parsedArguments[headerFieldName]];
}
parsedArguments[headerFieldName].forEach(function(header) {
if (header.indexOf('Cookie') !== -1) {
if (header.includes('Cookie')) {
// stupid javascript tricks: closure
cookieString = header;
} else {
@@ -149,7 +149,7 @@ function parseCurlCommand(curlCommand) {
if (option) {
let urlQueryString = '';
if (url.indexOf('?') < 0) {
if (!url.includes('?')) {
url += '?';
} else {
urlQueryString += '&';

View File

@@ -23,7 +23,7 @@ export default () => {
// Show the install button if the prompt appeared.
if (!pwaInstalled) {
document.querySelector('#installPWA').style.display = 'block';
document.querySelector('#installPWA').style.display = 'inline-flex';
}
});

View File

@@ -39,7 +39,7 @@ try {
runCommand("git", ["branch"])
.split("* ")[1]
.split(" ")[0] + (IS_DEV_MODE ? " - DEV MODE" : "");
if (version.variant === "" || version.variant === "master")
if (["", "master"].includes(version.variant))
delete version.variant;
// Write version data into a file

View File

@@ -2,43 +2,50 @@
<pw-section class="gray" label="History">
<ul>
<li id="filter-history">
<label for="filter-history-input">Search</label>
<input id="filter-history-input" type="text" placeholder="search history" :readonly="history.length === 0 || isClearingHistory" v-model="filterText">
<input aria-label="Search" type="text" placeholder="search history" :readonly="history.length === 0" v-model="filterText">
</li>
</ul>
<virtual-list class="virtual-list" :class="{filled: filteredHistory.length}" :size="89" :remain="Math.min(5, filteredHistory.length)">
<ul>
<li @click="sort_by_time()">
<label for="">Time</label>
</li>
<li @click="sort_by_status_code()">
<label for="">Status Code</label>
</li>
<li @click="sort_by_url()">
<label for="">URL</label>
</li>
<li @click="sort_by_path()">
<label for="">Path</label>
</li>
</ul>
<virtual-list class="virtual-list" :class="{filled: filteredHistory.length}" :size="54" :remain="Math.min(5, filteredHistory.length)">
<ul v-for="(entry, index) in filteredHistory" :key="index" class="entry">
<li>
<label :for="'time#'+index">Time</label>
<input :id="'time#'+index" type="text" readonly :value="entry.time" :title="entry.date">
<input aria-label="Time" type="text" readonly :value="entry.time" :title="entry.date">
</li>
<li class="method-list-item">
<label :for="'time#'+index">Method</label>
<input :id="'method#'+index" type="text" readonly :value="entry.method" :class="findEntryStatus(entry).className" :style="{'--status-code': entry.status}">
<span class="entry-status-code">{{entry.status}}</span>
<input aria-label="Method" type="text" readonly :value="entry.method" :class="findEntryStatus(entry).className" :style="{'--status-code': entry.status}">
<span class="entry-status-code" :class="findEntryStatus(entry).className" :style="{'--status-code': entry.status}">{{entry.status}}</span>
</li>
<li>
<label :for="'url#'+index">URL</label>
<input :id="'url#'+index" type="text" readonly :value="entry.url">
<input aria-label="URL" type="text" readonly :value="entry.url">
</li>
<li>
<label :for="'path#'+index">Path</label>
<input :id="'path#'+index" type="text" readonly :value="entry.path">
<input aria-label="Path" type="text" readonly :value="entry.path">
</li>
<div class="show-on-small-screen">
<li>
<label :for="'delete-button#'+index" class="hide-on-small-screen">&nbsp;</label>
<button class="icon" :id="'delete-button#'+index" :disabled="isClearingHistory" @click="deleteHistory(entry)">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd">
<path d="M19 24h-14c-1.104 0-2-.896-2-2v-17h-1v-2h6v-1.5c0-.827.673-1.5 1.5-1.5h5c.825 0 1.5.671 1.5 1.5v1.5h6v2h-1v17c0 1.104-.896 2-2 2zm0-19h-14v16.5c0 .276.224.5.5.5h13c.276 0 .5-.224.5-.5v-16.5zm-9 4c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm6 0c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm-2-7h-4v1h4v-1z"/>
<button class="icon" :id="'delete-button#'+index" @click="deleteHistory(entry)" aria-label="Delete">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M5.633 22.031c1.135 1.313 3.735 1.969 6.334 1.969 2.601 0 5.199-.656 6.335-1.969.081-.404 3.698-18.468 3.698-18.882 0-2.473-7.338-3.149-10-3.149-4.992 0-10 1.242-10 3.144 0 .406 3.556 18.488 3.633 18.887zm6.418-16.884c-4.211 0-7.625-.746-7.625-1.667s3.414-1.667 7.625-1.667 7.624.746 7.624 1.667-3.413 1.667-7.624 1.667z"/>
</svg>
</button>
</li>
<li>
<label :for="'use-button#'+index" class="hide-on-small-screen">&nbsp;</label>
<button class="icon" :id="'use-button#'+index" :disabled="isClearingHistory" @click="useHistory(entry)">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M14.078 7.061l2.861 2.862-10.799 10.798-3.584.723.724-3.585 10.798-10.798zm0-2.829l-12.64 12.64-1.438 7.128 7.127-1.438 12.642-12.64-5.691-5.69zm7.105 4.277l2.817-2.82-5.691-5.689-2.816 2.817 5.69 5.692z" />
<button class="icon" :id="'use-button#'+index" @click="useHistory(entry)" aria-label="Edit">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M19.769 9.923l-12.642 12.639-7.127 1.438 1.438-7.128 12.641-12.64 5.69 5.691zm1.414-1.414l2.817-2.82-5.691-5.689-2.816 2.817 5.69 5.692z"/>
</svg>
</button>
</li>
@@ -52,16 +59,16 @@
</ul>
<ul>
<li v-if="!isClearingHistory">
<button id="clear-history-button" :disabled="history.length === 0" @click="enableHistoryClearing">Clear All</button>
<button class="icon" id="clear-history-button" :disabled="history.length === 0" @click="enableHistoryClearing">Clear All</button>
</li>
<li v-else>
<div class="flex-wrap">
<label for="clear-history-button">Are you sure?</label>
<div>
<button id="confirm-clear-history-button" @click="clearHistory">
<button class="icon" id="confirm-clear-history-button" @click="clearHistory">
Yes
</button>
<button id="reject-clear-history-button" @click="disableHistoryClearing">
<button class="icon" id="reject-clear-history-button" @click="disableHistoryClearing">
No
</button>
</div>
@@ -89,7 +96,11 @@
history: localStorageHistory || [],
filterText: '',
showFilter: false,
isClearingHistory: false
isClearingHistory: false,
reverse_sort_time: false,
reverse_sort_status_code: false,
reverse_sort_url: false,
reverse_sort_path: false
}
},
computed: {
@@ -137,6 +148,56 @@
},
disableHistoryClearing() {
this.isClearingHistory = false;
},
sort_by_time() {
let byDate = this.history.slice(0);
byDate.sort((a,b) =>{
let date_a = a.date.split("/");
let date_b = b.date.split("/");
let time_a = a.time.split(":")
let time_b = b.time.split(":")
let final_a = new Date(date_a[2], date_a[1], date_a[0], time_a[0], time_a[1], time_a[2]);
let final_b = new Date(date_b[2], date_b[1], date_b[0], time_b[0], time_b[1], time_b[2]);
if(this.reverse_sort_time)
return final_b - final_a;
else
return final_a - final_b;
})
this.history = byDate;
this.reverse_sort_time = !this.reverse_sort_time;
},
sort_by_status_code() {
let byCode = this.history.slice(0);
byCode.sort((a,b) =>{
if(this.reverse_sort_status_code)
return b.status - a.status;
else
return a.status - b.status;
})
this.history = byCode;
this.reverse_sort_status_code = !this.reverse_sort_status_code;
},
sort_by_url() {
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;
});
this.history = byUrl;
this.reverse_sort_url = !this.reverse_sort_url;
},
sort_by_path() {
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;
});
this.history = byPath;
this.reverse_sort_path = !this.reverse_sort_path;
}
}
}
@@ -151,7 +212,7 @@
@media (max-width: 720px) {
.virtual-list.filled {
min-height: 380px;
min-height: 200px;
}
}

View File

@@ -25,7 +25,7 @@
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.75);
background-color: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
@@ -48,8 +48,8 @@
padding: 12px;
transition: all 0.2s ease;
background-color: var(--bg-color);
border: 2px solid var(--ac-color);
border-radius: 4px;
border-radius: 8px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 16px 70px;
}
/*
@@ -69,6 +69,6 @@
.modal-fade-enter .modal-container,
.modal-fade-leave-active .modal-container {
transform: scale(0.9);
transition: all .2s ease;
transition: all 0.1s ease-in-out;
}
</style>

View File

@@ -8,12 +8,8 @@
</template>
<style>
fieldset.no-colored-frames {
border-color: #afafaf !important;
}
fieldset.no-colored-frames legend {
color: var(--ac-color);
color: var(--fg-color);
}
</style>

View File

@@ -1,68 +1,70 @@
<template>
<div class="color" :data-color="color">
<span :style="{backgroundColor: color}" class="preview">
<svg v-if="active" class="activeTick" width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M21 6.285l-11.16 12.733-6.84-6.018 1.319-1.49 5.341 4.686 9.865-11.196 1.475 1.285z"/></svg>
</span>
{{ name || color }}
</div>
<div class="color" :data-color="color">
<span :style="{backgroundColor: color}" class="preview">
<svg v-if="active" class="activeTick" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="12"/>
</svg>
</span>
{{ name || color }}
</div>
</template>
<style lang="scss">
.color {
display: inline-block;
vertical-align: middle;
.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;
cursor: pointer;
height: 40px;
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);
}
.preview {
vertical-align: middle;
display: inline-block;
width: 32px;
height: 32px;
border-radius: 100%;
margin-right: 8px;
position: relative;
.activeTick {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
fill: white;
}
}
&.active {
background-color: var(--bg-dark-color);
}
.color.vibrant {
.preview .activeTick {
fill: black;
}
.preview {
vertical-align: middle;
display: inline-block;
border-radius: 100%;
margin-right: 8px;
padding: 16px;
position: relative;
.activeTick {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
fill: #fff;
}
}
}
.color.vibrant {
.preview .activeTick {
fill: var(--act-color);
}
}
</style>
<script>
export default {
props: {
'color': {
type: String,
required: true
},
'name': {
type: String
},
'active': {
type: Boolean,
default: false
}
}
export default {
props: {
'color': {
type: String,
required: true
},
'name': {
type: String
},
'active': {
type: Boolean,
default: false
}
}
</script>
}
</script>

View File

@@ -4,8 +4,7 @@
<div>
<div class="slide-in">
<nuxt-link to="/">
<h1 class="logo">
<logo alt="" style="height: 24px; margin-right: 16px" />Postwoman</h1>
<h1 class="logo"><logo alt="" style="height: 24px; margin-right: 16px"></logo>Postwoman</h1>
</nuxt-link>
<h3>API request builder</h3>
</div>
@@ -15,7 +14,7 @@
<nuxt-link to="/settings" aria-label="Settings">
<!-- Settings cog -->
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 14.187v-4.374c-2.148-.766-2.726-.802-3.027-1.529-.303-.729.083-1.169 1.059-3.223l-3.093-3.093c-2.026.963-2.488 1.364-3.224 1.059-.727-.302-.768-.889-1.527-3.027h-4.375c-.764 2.144-.8 2.725-1.529 3.027-.752.313-1.203-.1-3.223-1.059l-3.093 3.093c.977 2.055 1.362 2.493 1.059 3.224-.302.727-.881.764-3.027 1.528v4.375c2.139.76 2.725.8 3.027 1.528.304.734-.081 1.167-1.059 3.223l3.093 3.093c1.999-.95 2.47-1.373 3.223-1.059.728.302.764.88 1.529 3.027h4.374c.758-2.131.799-2.723 1.537-3.031.745-.308 1.186.099 3.215 1.062l3.093-3.093c-.975-2.05-1.362-2.492-1.059-3.223.3-.726.88-.763 3.027-1.528zm-4.875.764c-.577 1.394-.068 2.458.488 3.578l-1.084 1.084c-1.093-.543-2.161-1.076-3.573-.49-1.396.581-1.79 1.693-2.188 2.877h-1.534c-.398-1.185-.791-2.297-2.183-2.875-1.419-.588-2.507-.045-3.579.488l-1.083-1.084c.557-1.118 1.066-2.18.487-3.58-.579-1.391-1.691-1.784-2.876-2.182v-1.533c1.185-.398 2.297-.791 2.875-2.184.578-1.394.068-2.459-.488-3.579l1.084-1.084c1.082.538 2.162 1.077 3.58.488 1.392-.577 1.785-1.69 2.183-2.875h1.534c.398 1.185.792 2.297 2.184 2.875 1.419.588 2.506.045 3.579-.488l1.084 1.084c-.556 1.121-1.065 2.187-.488 3.58.577 1.391 1.689 1.784 2.875 2.183v1.534c-1.188.398-2.302.791-2.877 2.183zm-7.125-5.951c1.654 0 3 1.346 3 3s-1.346 3-3 3-3-1.346-3-3 1.346-3 3-3zm0-2c-2.762 0-5 2.238-5 5s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5z" />
<path d="M24 13.616v-3.232c-1.651-.587-2.694-.752-3.219-2.019v-.001c-.527-1.271.1-2.134.847-3.707l-2.285-2.285c-1.561.742-2.433 1.375-3.707.847h-.001c-1.269-.526-1.435-1.576-2.019-3.219h-3.232c-.582 1.635-.749 2.692-2.019 3.219h-.001c-1.271.528-2.132-.098-3.707-.847l-2.285 2.285c.745 1.568 1.375 2.434.847 3.707-.527 1.271-1.584 1.438-3.219 2.02v3.232c1.632.58 2.692.749 3.219 2.019.53 1.282-.114 2.166-.847 3.707l2.285 2.286c1.562-.743 2.434-1.375 3.707-.847h.001c1.27.526 1.436 1.579 2.019 3.219h3.232c.582-1.636.75-2.69 2.027-3.222h.001c1.262-.524 2.12.101 3.698.851l2.285-2.286c-.744-1.563-1.375-2.433-.848-3.706.527-1.271 1.588-1.44 3.221-2.021zm-12 2.384c-2.209 0-4-1.791-4-4s1.791-4 4-4 4 1.791 4 4-1.791 4-4 4z"/>
</svg>
</nuxt-link>
</nav>
@@ -25,23 +24,30 @@
<footer>
<!-- Top section of footer: GitHub/install links -->
<div>
<div>
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img id="imgGitHub" src="~static/icons/github.svg" alt="" :style="logoStyle()">GitHub</a>
</div>
<button id="installPWA" @click.prevent="showInstallPrompt()">
Install PWA
<a href="https://github.com/liyasthomas/postwoman" target="_blank" rel="noopener"><img id="imgGitHub" src="~static/icons/github.svg" alt="" :style="logoStyle()">GitHub</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');">
<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>
</button>
<button class="icon" id="installPWA" @click.prevent="showInstallPrompt()">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M12 4.435c-1.989-5.399-12-4.597-12 3.568 0 4.068 3.06 9.481 12 14.997 8.94-5.516 12-10.929 12-14.997 0-8.118-10-8.999-12-3.568z"/>
</svg>
<span>Install PWA</span>
</button>
</div>
<!-- Bottom section of footer: version/author information -->
<p class="align-center">
<span v-if="version.name">
<a v-bind:href="'https://github.com/liyasthomas/postwoman/releases/tag/' + version.name" target="_blank">{{version.name}}</a>
<a v-bind:href="'https://github.com/liyasthomas/postwoman/releases/tag/' + version.name" target="_blank" rel="noopener">{{version.name}}</a>
<span v-if="version.hash">
- <a v-bind:href="'https://github.com/liyasthomas/postwoman/commit/' + version.hash" target="_blank">{{version.hash}}</a>
- <a v-bind: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>
&#x2022;
</span> by <a href="https://liyasthomas.web.app" target="_blank">Liyas Thomas 🦄</a>
</span> by <a href="https://liyasthomas.web.app" target="_blank" rel="noopener">Liyas Thomas 🦄</a>
</p>
</footer>
</div>
@@ -72,7 +78,7 @@
}
footer {
margin: 40px auto;
margin: 32px auto;
}
nav {
@@ -105,12 +111,12 @@
right: 0;
z-index: -1;
background-color: var(--ac-color);
border-radius: 4px;
border-radius: 8px;
margin: auto;
}
&:not(.nuxt-link-exact-active):hover:before {
animation: linkHover 0.3s forwards ease-in-out;
animation: linkHover 0.2s forwards ease-in-out;
}
@keyframes linkHover {
@@ -165,7 +171,7 @@
let vibrant = this.$store.state.postwoman.settings.THEME_COLOR_VIBRANT;
if (vibrant == null) vibrant = true;
document.documentElement.style.setProperty('--ac-color', color);
document.documentElement.style.setProperty('--act-color', vibrant ? '#121212' : '#fff');
document.documentElement.style.setProperty('--act-color', vibrant ? 'rgb(37, 38, 40)' : '#fff');
})();
},

View File

@@ -84,7 +84,7 @@ export default {
},
{
name: 'msapplication-TileColor',
content: '#282a36'
content: '#252628'
},
{
name: 'msapplication-tap-highlight',
@@ -216,8 +216,8 @@ export default {
short_name: meta.name,
description: meta.shortDescription,
display: "standalone",
theme_color: "#282a36",
background_color: "#282a36",
theme_color: "#252628",
background_color: "#252628",
start_url: `${routerBase.router.base}`,
icons: ((sizes) => {
let icons = [];

View File

@@ -3,7 +3,9 @@
<pw-section class="yellow" label="Import" ref="import">
<ul>
<li>
<button id="show-modal" @click="showModal = true">Import cURL</button>
<button class="icon" id="show-modal" @click="showModal = true">
Import cURL
</button>
</li>
</ul>
<pw-modal v-if="showModal" @close="showModal = false">
@@ -14,8 +16,8 @@
<h3 class="title">Import cURL</h3>
<div>
<button class="icon" @click="toggleModal">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M23 20.168l-8.185-8.187 8.185-8.174-2.832-2.807-8.182 8.179-8.176-8.179-2.81 2.81 8.186 8.196-8.186 8.184 2.81 2.81 8.203-8.192 8.18 8.192z" />
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">
<path d="M23.954 21.03l-9.184-9.095 9.092-9.174-2.832-2.807-9.09 9.179-9.176-9.088-2.81 2.81 9.186 9.105-9.095 9.184 2.81 2.81 9.112-9.192 9.18 9.1z"/>
</svg>
</button>
</div>
@@ -33,7 +35,9 @@
<div slot="footer">
<ul>
<li>
<button @click="handleImport">Import</button>
<button class="icon" @click="handleImport">
Import
</button>
</li>
</ul>
</div>
@@ -65,20 +69,20 @@
<li>
<label class="hide-on-small-screen" for="copyRequest">&nbsp;</label>
<button class="icon" @click="copyRequest" id="copyRequest" ref="copyRequest" :disabled="!isValidURL">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M22 6v16h-16v-16h16zm2-2h-20v20h20v-20zm-24 17v-21h21v2h-19v19h-2z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M19.647 15.247c-1.278 0-2.429.551-3.225 1.429l-7.788-3.846c.062-.343.079-.64.067-.942l8.058-4.231c.769.682 1.78 1.097 2.889 1.097 2.404-.001 4.352-1.949 4.352-4.353s-1.948-4.353-4.353-4.353-4.353 1.949-4.353 4.353c0 .18.012.356.033.53l-7.828 4.111c-.793-.829-1.908-1.347-3.146-1.347-2.405 0-4.353 1.949-4.353 4.353s1.948 4.353 4.353 4.353c1.013 0 1.943-.347 2.684-.927l8.26 4.078-.001.047c0 2.404 1.948 4.353 4.353 4.353s4.351-1.949 4.351-4.353-1.948-4.352-4.353-4.352z"/>
</svg>
<span>Share URL</span>
<span>Permalink</span>
</button>
</li>
<li>
<label class="hide-on-small-screen" for="code">&nbsp;</label>
<button class="icon" id="code" v-on:click="isHidden = !isHidden" :disabled="!isValidURL">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="isHidden">
<path d="M12.015 7c4.751 0 8.063 3.012 9.504 4.636-1.401 1.837-4.713 5.364-9.504 5.364-4.42 0-7.93-3.536-9.478-5.407 1.493-1.647 4.817-4.593 9.478-4.593zm0-2c-7.569 0-12.015 6.551-12.015 6.551s4.835 7.449 12.015 7.449c7.733 0 11.985-7.449 11.985-7.449s-4.291-6.551-11.985-6.551zm-.015 5c1.103 0 2 .897 2 2s-.897 2-2 2-2-.897-2-2 .897-2 2-2zm0-2c-2.209 0-4 1.792-4 4 0 2.209 1.791 4 4 4s4-1.791 4-4c0-2.208-1.791-4-4-4z" />
<path d="M15 12c0 1.654-1.346 3-3 3s-3-1.346-3-3 1.346-3 3-3 3 1.346 3 3zm9-.449s-4.252 8.449-11.985 8.449c-7.18 0-12.015-8.449-12.015-8.449s4.446-7.551 12.015-7.551c7.694 0 11.985 7.551 11.985 7.551zm-7 .449c0-2.757-2.243-5-5-5s-5 2.243-5 5 2.243 5 5 5 5-2.243 5-5z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="!isHidden">
<path d="M19.604 2.562l-3.346 3.137c-1.27-.428-2.686-.699-4.243-.699-7.569 0-12.015 6.551-12.015 6.551s1.928 2.951 5.146 5.138l-2.911 2.909 1.414 1.414 17.37-17.035-1.415-1.415zm-6.016 5.779c-3.288-1.453-6.681 1.908-5.265 5.206l-1.726 1.707c-1.814-1.16-3.225-2.65-4.06-3.66 1.493-1.648 4.817-4.594 9.478-4.594.927 0 1.796.119 2.61.315l-1.037 1.026zm-2.883 7.431l5.09-4.993c1.017 3.111-2.003 6.067-5.09 4.993zm13.295-4.221s-4.252 7.449-11.985 7.449c-1.379 0-2.662-.291-3.851-.737l1.614-1.583c.715.193 1.458.32 2.237.32 4.791 0 8.104-3.527 9.504-5.364-.729-.822-1.956-1.99-3.587-2.952l1.489-1.46c2.982 1.9 4.579 4.327 4.579 4.327z" />
<path d="M11.885 14.988l3.104-3.098.011.11c0 1.654-1.346 3-3 3l-.115-.012zm8.048-8.032l-3.274 3.268c.212.554.341 1.149.341 1.776 0 2.757-2.243 5-5 5-.631 0-1.229-.13-1.785-.344l-2.377 2.372c1.276.588 2.671.972 4.177.972 7.733 0 11.985-8.449 11.985-8.449s-1.415-2.478-4.067-4.595zm1.431-3.536l-18.619 18.58-1.382-1.422 3.455-3.447c-3.022-2.45-4.818-5.58-4.818-5.58s4.446-7.551 12.015-7.551c1.825 0 3.456.426 4.886 1.075l3.081-3.075 1.382 1.42zm-13.751 10.922l1.519-1.515c-.077-.264-.132-.538-.132-.827 0-1.654 1.346-3 3-3 .291 0 .567.055.833.134l1.518-1.515c-.704-.382-1.496-.619-2.351-.619-2.757 0-5 2.243-5 5 0 .852.235 1.641.613 2.342z"/>
</svg>
<span>{{ isHidden ? 'Show Code' : 'Hide Code' }}</span>
</button>
@@ -89,15 +93,72 @@
<button :disabled="!isValidURL" @click="sendRequest" class="show" id="send" ref="sendButton">
Send <span id="hidden-message">Again</span>
<span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 12l11 3.1 7-8.1-8.156 5.672-4.312-1.202 15.362-7.68-3.974 14.57-3.75-3.339-2.17 2.925v-.769l-2-.56v7.383l4.473-6.031 4.527 4.031 6-22z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 0l-6 22-8.129-7.239 7.802-8.234-10.458 7.227-7.215-1.754 24-12zm-15 16.668v7.332l3.258-4.431-3.258-2.901z"/>
</svg>
</span>
</button>
</li>
</ul>
<div class="blue" label="Request Body" v-if="method === 'POST' || method === 'PUT' || method === 'PATCH'">
<ul>
<li>
<label for="contentType">Content Type</label>
<autocomplete :source="validContentTypes" :spellcheck="false" v-model="contentType">Content Type
</autocomplete>
<span>
<pw-toggle :on="rawInput" @change="rawInput = !rawInput">
Raw Input {{ rawInput ? "Enabled" : "Disabled" }}
</pw-toggle>
</span>
</li>
</ul>
<div v-if="!rawInput">
<ul>
<li>
<label for="reqParamList">Parameter List</label>
<textarea id="reqParamList" readonly v-textarea-auto-height="rawRequestBody" v-model="rawRequestBody" placeholder="(add at least one parameter)" rows="1"></textarea>
</li>
</ul>
<ul v-for="(param, index) in bodyParams" :key="index">
<li>
<input :placeholder="'key '+(index+1)" :name="'bparam'+index" v-model="param.key" @keyup.prevent="setRouteQueryState" autofocus>
</li>
<li>
<input :placeholder="'value '+(index+1)" :id="'bvalue'+index" :name="'bvalue'+index" v-model="param.value" @keyup.prevent="setRouteQueryState">
</li>
<div>
<li>
<button class="icon" @click="removeRequestBodyParam(index)" id="delParam">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M5.633 22.031c1.135 1.313 3.735 1.969 6.334 1.969 2.601 0 5.199-.656 6.335-1.969.081-.404 3.698-18.468 3.698-18.882 0-2.473-7.338-3.149-10-3.149-4.992 0-10 1.242-10 3.144 0 .406 3.556 18.488 3.633 18.887zm6.418-16.884c-4.211 0-7.625-.746-7.625-1.667s3.414-1.667 7.625-1.667 7.624.746 7.624 1.667-3.413 1.667-7.624 1.667z"/>
</svg>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button class="icon" @click="addRequestBodyParam" name="addrequest">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/>
</svg>
<span>Add New</span>
</button>
</li>
</ul>
</div>
<div v-else>
<ul>
<li>
<label for="rawBody">Raw Request Body</label>
<textarea id="rawBody" @keydown="formatRawParams" rows="8" v-model="rawParams" v-textarea-auto-height="rawParams"></textarea>
</li>
</ul>
</div>
</div>
</pw-section>
<pw-section class="blue" label="Request Code" ref="requestCode" v-if="!isHidden">
<pw-section class="blue" label="Code" ref="requestCode" v-if="!isHidden">
<ul>
<li>
<label for="requestType">Request Type</label>
@@ -114,8 +175,8 @@
<label for="generatedCode">Generated Code</label>
<div>
<button class="icon" @click="copyRequestCode" id="copyRequestCode" ref="copyRequestCode">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M22 6v16h-16v-16h16zm2-2h-20v20h20v-20zm-24 17v-21h21v2h-19v19h-2z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M19.647 15.247c-1.278 0-2.429.551-3.225 1.429l-7.788-3.846c.062-.343.079-.64.067-.942l8.058-4.231c.769.682 1.78 1.097 2.889 1.097 2.404-.001 4.352-1.949 4.352-4.353s-1.948-4.353-4.353-4.353-4.353 1.949-4.353 4.353c0 .18.012.356.033.53l-7.828 4.111c-.793-.829-1.908-1.347-3.146-1.347-2.405 0-4.353 1.949-4.353 4.353s1.948 4.353 4.353 4.353c1.013 0 1.943-.347 2.684-.927l8.26 4.078-.001.047c0 2.404 1.948 4.353 4.353 4.353s4.351-1.949 4.351-4.353-1.948-4.352-4.353-4.352z"/>
</svg>
<span>Copy</span>
</button>
@@ -125,60 +186,6 @@
</li>
</ul>
</pw-section>
<pw-section class="blue" label="Request Body" v-if="method === 'POST' || method === 'PUT' || method === 'PATCH'">
<ul>
<li>
<autocomplete :source="validContentTypes" :spellcheck="false" v-model="contentType">Content Type
</autocomplete>
<span>
<pw-toggle :on="rawInput" @change="rawInput = !rawInput">
Raw Input {{ rawInput ? "Enabled" : "Disabled" }}
</pw-toggle>
</span>
</li>
</ul>
<div v-if="!rawInput">
<ul v-for="(param, index) in bodyParams" :key="index">
<li>
<label :for="'bparam'+index">Key {{index + 1}}</label>
<input :id="'bparam'+index" :name="'bparam'+index" v-model="param.key" @keyup.prevent="setRouteQueryState" autofocus>
</li>
<li>
<label :for="'bvalue'+index">Value {{index + 1}}</label>
<input :id="'bvalue'+index" :name="'bvalue'+index" v-model="param.value" @keyup.prevent="setRouteQueryState">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="delParam">&nbsp;</label>
<button class="icon" @click="removeRequestBodyParam(index)" id="delParam">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd">
<path d="M19 24h-14c-1.104 0-2-.896-2-2v-17h-1v-2h6v-1.5c0-.827.673-1.5 1.5-1.5h5c.825 0 1.5.671 1.5 1.5v1.5h6v2h-1v17c0 1.104-.896 2-2 2zm0-19h-14v16.5c0 .276.224.5.5.5h13c.276 0 .5-.224.5-.5v-16.5zm-9 4c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm6 0c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm-2-7h-4v1h4v-1z" />
</svg>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button @click="addRequestBodyParam" name="addrequest">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="reqParamList">Parameter List</label>
<textarea id="reqParamList" readonly v-textarea-auto-height="rawRequestBody" v-model="rawRequestBody" placeholder="(add at least one parameter)" rows="1"></textarea>
</li>
</ul>
</div>
<div v-else>
<ul>
<li>
<label for="rawBody">Raw Request Body</label>
<textarea id="rawBody" @keydown="formatRawParams" rows="8" v-model="rawParams" v-textarea-auto-height="rawParams"></textarea>
</li>
</ul>
</div>
</pw-section>
<pw-section class="purple" id="response" label="Response" ref="response">
<ul>
<li>
@@ -198,8 +205,8 @@
<label for="body">response</label>
<div>
<button class="icon" @click="copyResponse" ref="copyResponse" v-if="response.body">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M22 6v16h-16v-16h16zm2-2h-20v20h20v-20zm-24 17v-21h21v2h-19v19h-2z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M19.647 15.247c-1.278 0-2.429.551-3.225 1.429l-7.788-3.846c.062-.343.079-.64.067-.942l8.058-4.231c.769.682 1.78 1.097 2.889 1.097 2.404-.001 4.352-1.949 4.352-4.353s-1.948-4.353-4.353-4.353-4.353 1.949-4.353 4.353c0 .18.012.356.033.53l-7.828 4.111c-.793-.829-1.908-1.347-3.146-1.347-2.405 0-4.353 1.949-4.353 4.353s1.948 4.353 4.353 4.353c1.013 0 1.943-.347 2.684-.927l8.26 4.078-.001.047c0 2.404 1.948 4.353 4.353 4.353s4.351-1.949 4.351-4.353-1.948-4.352-4.353-4.352z"/>
</svg>
<span>Copy</span>
</button>
@@ -227,7 +234,7 @@
<input id="tab-one" type="radio" name="grp" checked="checked">
<label for="tab-one">Authentication</label>
<div class="tab">
<pw-section class="green" label="Authentication">
<pw-section class="cyan" label="Authentication">
<ul>
<li>
<label for="auth">Authentication Type</label>
@@ -240,22 +247,19 @@
</ul>
<ul v-if="auth === 'Basic'">
<li>
<label for="http_basic_user">User</label>
<input id="http_basic_user" name="http_basic_user" v-model="httpUser">
<input placeholder="User" name="http_basic_user" v-model="httpUser">
</li>
<li>
<label for="http_basic_passwd">Password</label>
<input id="http_basic_passwd" name="http_basic_passwd" :type="passwordFieldType" v-model="httpPassword">
<input placeholder="Password" name="http_basic_passwd" :type="passwordFieldType" v-model="httpPassword">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="switchVisibility">&nbsp;</label>
<button class="icon" id="switchVisibility" ref="switchVisibility" @click="switchVisibility">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="passwordFieldType === 'text'">
<path d="M12.015 7c4.751 0 8.063 3.012 9.504 4.636-1.401 1.837-4.713 5.364-9.504 5.364-4.42 0-7.93-3.536-9.478-5.407 1.493-1.647 4.817-4.593 9.478-4.593zm0-2c-7.569 0-12.015 6.551-12.015 6.551s4.835 7.449 12.015 7.449c7.733 0 11.985-7.449 11.985-7.449s-4.291-6.551-11.985-6.551zm-.015 5c1.103 0 2 .897 2 2s-.897 2-2 2-2-.897-2-2 .897-2 2-2zm0-2c-2.209 0-4 1.792-4 4 0 2.209 1.791 4 4 4s4-1.791 4-4c0-2.208-1.791-4-4-4z" />
<path d="M15 12c0 1.654-1.346 3-3 3s-3-1.346-3-3 1.346-3 3-3 3 1.346 3 3zm9-.449s-4.252 8.449-11.985 8.449c-7.18 0-12.015-8.449-12.015-8.449s4.446-7.551 12.015-7.551c7.694 0 11.985 7.551 11.985 7.551zm-7 .449c0-2.757-2.243-5-5-5s-5 2.243-5 5 2.243 5 5 5 5-2.243 5-5z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="passwordFieldType !== 'text'">
<path d="M19.604 2.562l-3.346 3.137c-1.27-.428-2.686-.699-4.243-.699-7.569 0-12.015 6.551-12.015 6.551s1.928 2.951 5.146 5.138l-2.911 2.909 1.414 1.414 17.37-17.035-1.415-1.415zm-6.016 5.779c-3.288-1.453-6.681 1.908-5.265 5.206l-1.726 1.707c-1.814-1.16-3.225-2.65-4.06-3.66 1.493-1.648 4.817-4.594 9.478-4.594.927 0 1.796.119 2.61.315l-1.037 1.026zm-2.883 7.431l5.09-4.993c1.017 3.111-2.003 6.067-5.09 4.993zm13.295-4.221s-4.252 7.449-11.985 7.449c-1.379 0-2.662-.291-3.851-.737l1.614-1.583c.715.193 1.458.32 2.237.32 4.791 0 8.104-3.527 9.504-5.364-.729-.822-1.956-1.99-3.587-2.952l1.489-1.46c2.982 1.9 4.579 4.327 4.579 4.327z" />
<path d="M11.885 14.988l3.104-3.098.011.11c0 1.654-1.346 3-3 3l-.115-.012zm8.048-8.032l-3.274 3.268c.212.554.341 1.149.341 1.776 0 2.757-2.243 5-5 5-.631 0-1.229-.13-1.785-.344l-2.377 2.372c1.276.588 2.671.972 4.177.972 7.733 0 11.985-8.449 11.985-8.449s-1.415-2.478-4.067-4.595zm1.431-3.536l-18.619 18.58-1.382-1.422 3.455-3.447c-3.022-2.45-4.818-5.58-4.818-5.58s4.446-7.551 12.015-7.551c1.825 0 3.456.426 4.886 1.075l3.081-3.075 1.382 1.42zm-13.751 10.922l1.519-1.515c-.077-.264-.132-.538-.132-.827 0-1.654 1.346-3 3-3 .291 0 .567.055.833.134l1.518-1.515c-.704-.382-1.496-.619-2.351-.619-2.757 0-5 2.243-5 5 0 .852.235 1.641.613 2.342z"/>
</svg>
</button>
</li>
@@ -263,8 +267,7 @@
</ul>
<ul v-if="auth === 'Bearer Token'">
<li>
<label for="bearer_token">Token</label>
<input id="bearer_token" name="bearer_token" v-model="bearerToken">
<input placeholder="Token" name="bearer_token" v-model="bearerToken">
</li>
</ul>
</pw-section>
@@ -273,21 +276,24 @@
<label for="tab-two">Headers</label>
<div class="tab">
<pw-section class="orange" label="Headers">
<ul>
<li>
<label for="headerList">Header List</label>
<textarea id="headerList" readonly v-textarea-auto-height="headerString" v-model="headerString" placeholder="(add at least one header)" rows="1"></textarea>
</li>
</ul>
<ul v-for="(header, index) in headers" :key="index">
<li>
<label :for="'header'+index">Header {{index + 1}}</label>
<input :id="'header'+index" :name="'header'+index" v-model="header.key" @keyup.prevent="setRouteQueryState" autofocus>
<input :placeholder="'header '+(index+1)" :name="'header'+index" v-model="header.key" @keyup.prevent="setRouteQueryState" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :id="'value'+index" :name="'value'+index" v-model="header.value" @keyup.prevent="setRouteQueryState">
<input :placeholder="'value '+(index+1)" :name="'value'+index" v-model="header.value" @keyup.prevent="setRouteQueryState">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="header">&nbsp;</label>
<button class="icon" @click="removeRequestHeader(index)" id="header">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd">
<path d="M19 24h-14c-1.104 0-2-.896-2-2v-17h-1v-2h6v-1.5c0-.827.673-1.5 1.5-1.5h5c.825 0 1.5.671 1.5 1.5v1.5h6v2h-1v17c0 1.104-.896 2-2 2zm0-19h-14v16.5c0 .276.224.5.5.5h13c.276 0 .5-.224.5-.5v-16.5zm-9 4c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm6 0c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm-2-7h-4v1h4v-1z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M5.633 22.031c1.135 1.313 3.735 1.969 6.334 1.969 2.601 0 5.199-.656 6.335-1.969.081-.404 3.698-18.468 3.698-18.882 0-2.473-7.338-3.149-10-3.149-4.992 0-10 1.242-10 3.144 0 .406 3.556 18.488 3.633 18.887zm6.418-16.884c-4.211 0-7.625-.746-7.625-1.667s3.414-1.667 7.625-1.667 7.624.746 7.624 1.667-3.413 1.667-7.624 1.667z"/>
</svg>
</button>
</li>
@@ -295,13 +301,12 @@
</ul>
<ul>
<li>
<button @click="addRequestHeader">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="headerList">Header List</label>
<textarea id="headerList" readonly v-textarea-auto-height="headerString" v-model="headerString" placeholder="(add at least one header)" rows="1"></textarea>
<button class="icon" @click="addRequestHeader">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/>
</svg>
<span>Add New</span>
</button>
</li>
</ul>
</pw-section>
@@ -310,21 +315,24 @@
<label for="tab-three">Parameters</label>
<div class="tab">
<pw-section class="pink" label="Parameters">
<ul>
<li>
<label for="paramList">Parameter List</label>
<textarea id="paramList" readonly v-textarea-auto-height="queryString" v-model="queryString" placeholder="(add at least one parameter)" rows="1"></textarea>
</li>
</ul>
<ul v-for="(param, index) in params" :key="index">
<li>
<label :for="'param'+index">Parameter {{index + 1}}</label>
<input :id="'param'+index" :name="'param'+index" v-model="param.key" autofocus>
<input :placeholder="'parameter '+(index+1)" :name="'param'+index" v-model="param.key" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :id="'value'+index" :name="'value'+index" v-model="param.value">
<input :placeholder="'value '+(index+1)" :name="'value'+index" v-model="param.value">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="param">&nbsp;</label>
<button class="icon" @click="removeRequestParam(index)" id="param">
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd">
<path d="M19 24h-14c-1.104 0-2-.896-2-2v-17h-1v-2h6v-1.5c0-.827.673-1.5 1.5-1.5h5c.825 0 1.5.671 1.5 1.5v1.5h6v2h-1v17c0 1.104-.896 2-2 2zm0-19h-14v16.5c0 .276.224.5.5.5h13c.276 0 .5-.224.5-.5v-16.5zm-9 4c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm6 0c0-.552-.448-1-1-1s-1 .448-1 1v9c0 .552.448 1 1 1s1-.448 1-1v-9zm-2-7h-4v1h4v-1z" />
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M5.633 22.031c1.135 1.313 3.735 1.969 6.334 1.969 2.601 0 5.199-.656 6.335-1.969.081-.404 3.698-18.468 3.698-18.882 0-2.473-7.338-3.149-10-3.149-4.992 0-10 1.242-10 3.144 0 .406 3.556 18.488 3.633 18.887zm6.418-16.884c-4.211 0-7.625-.746-7.625-1.667s3.414-1.667 7.625-1.667 7.624.746 7.624 1.667-3.413 1.667-7.624 1.667z"/>
</svg>
</button>
</li>
@@ -332,13 +340,12 @@
</ul>
<ul>
<li>
<button @click="addRequestParam">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="paramList">Parameter List</label>
<textarea id="paramList" readonly v-textarea-auto-height="queryString" v-model="queryString" placeholder="(add at least one parameter)" rows="1"></textarea>
<button class="icon" @click="addRequestParam">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/>
</svg>
<span>Add New</span>
</button>
</li>
</ul>
</pw-section>
@@ -420,8 +427,8 @@
data() {
return {
showModal: false,
copyButton: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M22 6v16h-16v-16h16zm2-2h-20v20h20v-20zm-24 17v-21h21v2h-19v19h-2z" /></svg>',
copiedButton: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M22 2v20h-20v-20h20zm2-2h-24v24h24v-24zm-5.541 8.409l-1.422-1.409-7.021 7.183-3.08-2.937-1.395 1.435 4.5 4.319 8.418-8.591z"/></svg>',
copyButton: '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M19.647 15.247c-1.278 0-2.429.551-3.225 1.429l-7.788-3.846c.062-.343.079-.64.067-.942l8.058-4.231c.769.682 1.78 1.097 2.889 1.097 2.404-.001 4.352-1.949 4.352-4.353s-1.948-4.353-4.353-4.353-4.353 1.949-4.353 4.353c0 .18.012.356.033.53l-7.828 4.111c-.793-.829-1.908-1.347-3.146-1.347-2.405 0-4.353 1.949-4.353 4.353s1.948 4.353 4.353 4.353c1.013 0 1.943-.347 2.684-.927l8.26 4.078-.001.047c0 2.404 1.948 4.353 4.353 4.353s4.351-1.949 4.351-4.353-1.948-4.352-4.353-4.352z"/></svg>',
copiedButton: '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg>',
method: 'GET',
url: 'https://reqres.in',
auth: 'None',
@@ -511,7 +518,7 @@
value
}) => `${key}=${value}`).join('&')
queryString = queryString === '' ? '' : `?${queryString}`
if(path.indexOf('?') !== -1) {
if(path.includes('?')) {
path = path.slice(0, path.indexOf('?')) + queryString;
} else {
path = path + queryString
@@ -897,7 +904,7 @@
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
setTimeout(() => this.$refs.copyRequest.innerHTML = this.copyButton + '<span>Share URL</span>', 1500)
setTimeout(() => this.$refs.copyRequest.innerHTML = this.copyButton + '<span>Permalink</span>', 1500)
}
},
copyRequestCode() {

View File

@@ -79,8 +79,8 @@
// You should copy the existing light theme as a template and then just
// set the relevant values.
themes: [{
"color": "#282a36",
"name": "Dark (Default)",
"color": "rgb(37, 38, 40)",
"name": "Dark (default)",
"class": ""
},
{
@@ -95,7 +95,7 @@
// If the color is vibrant, black is used as the active foreground color.
{
"color": "#50fa7b",
"name": "Green (Default)",
"name": "Green (default)",
"vibrant": true
},
{
@@ -174,7 +174,7 @@
// By default, the color is vibrant.
if (vibrant == null) vibrant = true;
document.documentElement.style.setProperty('--ac-color', color);
document.documentElement.style.setProperty('--act-color', vibrant ? '#282a36' : '#f8f8f2');
document.documentElement.style.setProperty('--act-color', vibrant ? 'rgb(37, 38, 40)' : '#f8f8f2');
this.applySetting('THEME_COLOR', color.toUpperCase());
this.applySetting('THEME_COLOR_VIBRANT', vibrant);
},

View File

@@ -6,20 +6,22 @@
<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>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="!connectionState">
<path d="M21.921 2.081c2.771 2.772 2.771 7.269 0 10.042l-3.84 3.839-2.121-2.122 3.839-3.84c1.599-1.598 1.599-4.199-.001-5.797-1.598-1.599-4.199-1.599-5.797-.001l-3.84 3.839-2.121-2.121 3.84-3.839c2.771-2.773 7.267-2.773 10.041 0zm-8.082 13.879l-3.84 3.839c-1.598 1.6-4.199 1.599-5.799 0-1.598-1.598-1.598-4.2 0-5.797l3.84-3.84-2.121-2.121-3.84 3.84c-2.771 2.772-2.772 7.268 0 10.041 2.773 2.772 7.27 2.773 10.041 0l3.84-3.84-2.121-2.122z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="connectionState">
<path d="M14.9 19.143l-2.78 2.779c-2.771 2.772-7.268 2.772-10.041 0-2.772-2.773-2.771-7.269 0-10.041l2.779-2.779 2.121 2.121-2.779 2.779c-1.598 1.598-1.598 4.2 0 5.797 1.6 1.6 4.201 1.6 5.799 0l2.779-2.777 2.122 2.121zm-3.02-17.063l-2.779 2.779 2.121 2.121 2.78-2.779c1.598-1.598 4.199-1.598 5.795.001 1.602 1.598 1.602 4.199.004 5.797l-2.779 2.779 2.121 2.121 2.779-2.778c2.771-2.773 2.771-7.269 0-10.041-2.774-2.772-7.27-2.772-10.042 0zm-5.945-.795l1.44-.204.438 3.083-1.438.205-.44-3.084zm-4.855 6.09l.206-1.441 3.084.44-.206 1.44-3.084-.439zm4.793-2.521l-1.028 1.03-2.205-2.203 1.029-1.029 2.204 2.202zm12.191 17.86l-1.441.204-.438-3.083 1.439-.205.44 3.084zm4.856-6.09l-.207 1.441-3.084-.439.207-1.441 3.084.439zm-4.793 2.52l1.027-1.029 2.205 2.204-1.029 1.029-2.203-2.204z"/>
</svg>
</span>
</button>
</li>
<div>
<li>
<label for="connect" class="hide-on-small-screen">&nbsp;</label>
<button :disabled="!urlValid" id="connect" name="connect" @click="toggleConnection">
{{ toggleConnectionVerb }}
<span>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" v-if="connectionState">
<path d="M16 0l-3 9h9l-1.866 2h-14.4l10.266-11zm2.267 13h-14.4l-1.867 2h9l-3 9 10.267-11z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" v-if="!connectionState">
<path d="M8 24l3-9h-9l14-15-3 9h9l-14 15z"/>
</svg>
</span>
</button>
</li>
</div>
</ul>
</pw-section>
<pw-section class="purple" label="Communication" id="response" ref="response">
@@ -30,7 +32,7 @@
<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>
<span v-else>(waiting for connection)</span>
</div>
</li>
</ul>
@@ -39,17 +41,19 @@
<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>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M0 12l11 3.1 7-8.1-8.156 5.672-4.312-1.202 15.362-7.68-3.974 14.57-3.75-3.339-2.17 2.925v-.769l-2-.56v7.383l4.473-6.031 4.527 4.031 6-22z" />
</svg>
</span>
</button>
</li>
<div>
<li>
<label for="send" class="hide-on-small-screen">&nbsp;</label>
<button id="send" name="send" :disabled="!connectionState" @click="sendMessage">
Send
<span>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24">
<path d="M24 0l-6 22-8.129-7.239 7.802-8.234-10.458 7.227-7.215-1.754 24-12zm-15 16.668v7.332l3.258-4.431-3.258-2.901z"/>
</svg>
</span>
</button>
</li>
</div>
</ul>
</pw-section>
</div>
@@ -59,7 +63,7 @@
margin: 4px;
padding: 8px 16px;
width: calc(100% - 8px);
border-radius: 4px;
border-radius: 8px;
background-color: var(--bg-dark-color);
color: var(--fg-color);
height: 256px;
@@ -67,7 +71,6 @@
&,
span {
font-weight: 700;
font-size: 18px;
font-family: monospace;
}

16
static/.htaccess Normal file
View File

@@ -0,0 +1,16 @@
<IfModule mod_expires.c>
ExpiresActive On
# Images
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# CSS, JavaScript
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB