💄 Introducing tabs, minor UI changes

This commit is contained in:
Basil K
2019-09-16 13:50:28 +05:30
parent d93c76373c
commit e34662baec
7 changed files with 252 additions and 205 deletions

View File

@@ -11,11 +11,11 @@ $responsiveWidth: 720px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, .5);
background-color: rgba(0, 0, 0, 0.5);
}
::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, .6);
background-color: rgba(0, 0, 0, 0.6);
}
::placeholder {
@@ -134,8 +134,7 @@ legend {
}
fieldset textarea,
fieldset pre
code {
fieldset pre code {
resize: vertical;
}
@@ -148,11 +147,11 @@ fieldset.blue legend {
}
fieldset.gray {
border-color: #BCC2CD;
border-color: #bcc2cd;
}
fieldset.gray legend {
color: #BCC2CD;
color: #bcc2cd;
}
fieldset.green {
@@ -226,7 +225,6 @@ pre {
width: calc(100% - 8px);
background-color: var(--bg-dark-color);
color: var(--fg-color);
font-weight: 700;
font-size: 18px;
font-family: monospace;
transition: all 0.2s ease-in-out;
@@ -278,7 +276,7 @@ input[type="checkbox"] {
justify-content: center;
margin: 8px 8px 8px 0;
color: transparent;
transition: .2s;
transition: 0.2s;
}
}
@@ -368,23 +366,23 @@ ol li {
}
.info-response {
background-color: #FFEB3B;
background-color: #ffeb3b;
}
.success-response {
background-color: #4BB543;
background-color: #4bb543;
}
.redir-response {
background-color: #FF5722;
background-color: #ff5722;
}
.cl-error-response {
background-color: #A63232;
background-color: #a63232;
}
.sv-error-response {
background-color: #B71C1C;
background-color: #b71c1c;
}
.missing-data-response {
@@ -403,7 +401,6 @@ fieldset#history {
position: absolute;
top: 44px;
right: 12px;
font-weight: 700;
font-family: monospace, monospace;
}
}
@@ -461,3 +458,37 @@ fieldset#history {
}
}
}
section {
display: flex;
flex-wrap: wrap;
}
div.tab {
width: 100%;
order: 1;
}
input[type="radio"],
div.tab {
display: none;
}
input[type="radio"] + label {
padding: 8px 16px;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
border-color: var(--err-color);
}
}
input[type="radio"]:checked + label {
border-color: var(--ac-color);
}
input[type="radio"]:checked + label + div.tab {
display: block;
}

View File

@@ -1,46 +1,54 @@
const axios = require('axios');
const fs = require('fs');
const { spawnSync } = require('child_process');
const runCommand = (command, args) => spawnSync(command, args).stdout.toString().replace(/\n/g, "");
const axios = require("axios");
const fs = require("fs");
const { spawnSync } = require("child_process");
const runCommand = (command, args) =>
spawnSync(command, args)
.stdout.toString()
.replace(/\n/g, "");
const FAIL_ON_ERROR = false;
const PW_BUILD_DATA_DIR = "./.postwoman";
const IS_DEV_MODE = process.argv.includes("--dev");
try {
(async () => {
// Create the build data directory if it does not exist.
if (!fs.existsSync(PW_BUILD_DATA_DIR)) {
fs.mkdirSync(PW_BUILD_DATA_DIR);
}
(async () => {
// Create the build data directory if it does not exist.
if (!fs.existsSync(PW_BUILD_DATA_DIR)) {
fs.mkdirSync(PW_BUILD_DATA_DIR);
}
let version = {};
// Get the current version name as the tag from Git.
version.name = process.env.TRAVIS_TAG || runCommand("git", ["tag"]);
let version = {};
// Get the current version name as the tag from Git.
version.name = (process.env.TRAVIS_TAG || runCommand('git', ['tag']));
// FALLBACK: If version.name was unset, let's grab it from GitHub.
if (!version.name) {
version.name = (await axios
.get("https://api.github.com/repos/liyasthomas/postwoman/releases")
// If we can't get it from GitHub, we'll resort to getting it from package.json
.catch(ex => ({
data: [{ tag_name: require("./package.json").version }]
}))).data[0]["tag_name"];
}
// FALLBACK: If version.name was unset, let's grab it from GitHub.
if(!version.name){
version.name = (
await axios.get("https://api.github.com/repos/liyasthomas/postwoman/releases")
// If we can't get it from GitHub, we'll resort to getting it from package.json
.catch(
(ex) => ({ data: [{ 'tag_name': require('./package.json').version }] })
)
).data[0]['tag_name'];
}
// Get the current version hash as the short hash from Git.
version.hash = runCommand("git", ["rev-parse", "--short", "HEAD"]);
// Get the 'variant' name as the branch, if it's not master.
version.variant =
process.env.TRAVIS_BRANCH ||
runCommand("git", ["branch"])
.split("* ")[1]
.split(" ")[0] + (IS_DEV_MODE ? " - DEV MODE" : "");
if (version.variant === "" || version.variant === "master")
delete version.variant;
// Get the current version hash as the short hash from Git.
version.hash = runCommand('git', ['rev-parse', '--short', 'HEAD']);
// Get the 'variant' name as the branch, if it's not master.
version.variant = (process.env.TRAVIS_BRANCH || runCommand('git', ['branch']).split("* ")[1].split(" ")[0] + (IS_DEV_MODE ? " - DEV MODE" : ""));
if(version.variant === "" || version.variant === "master") delete version.variant;
// Write version data into a file
fs.writeFileSync(PW_BUILD_DATA_DIR + "/version.json", JSON.stringify(version));
})();
}catch(ex){
console.error(ex);
process.exit(FAIL_ON_ERROR ? 1 : 0);
// Write version data into a file
fs.writeFileSync(
PW_BUILD_DATA_DIR + "/version.json",
JSON.stringify(version)
);
})();
} catch (ex) {
console.error(ex);
process.exit(FAIL_ON_ERROR ? 1 : 0);
}

View File

@@ -1,11 +1,9 @@
<template>
<div class="autocomplete-wrapper">
<label>
<slot />
<input type="text" :placeholder="placeholder" v-model="value" @input="updateSuggestions" @keyup="updateSuggestions" @click="updateSuggestions" @keydown="handleKeystroke" ref="acInput" :spellcheck="spellcheck" :autocapitalize="spellcheck" :autocorrect="spellcheck">
<ul class="suggestions" v-if="suggestions.length > 0 && suggestionsVisible" :style="{ transform: `translate(${suggestionsOffsetLeft}px, 0)` }">
<li v-for="(suggestion, index) in suggestions" @click.prevent="forceSuggestion(suggestion)" :class="{ active: currentSuggestionIndex === index }">{{ suggestion }}</li>
<li v-for="(suggestion, index) in suggestions" @click.prevent="forceSuggestion(suggestion)" :class="{ active: currentSuggestionIndex === index }" :key="index">{{ suggestion }}</li>
</ul>
</label>
</div>
@@ -13,7 +11,6 @@
<style lang="scss" scoped>
.autocomplete-wrapper {
position: relative;
input:focus+ul.suggestions,
@@ -28,7 +25,6 @@
top: 90%;
margin: 0 4px;
left: 0;
padding: 0;
border-radius: 0 0 4px 4px;
z-index: 9999;
@@ -55,7 +51,6 @@
}
}
}
}
</style>

View File

@@ -1,47 +1,45 @@
<template>
<fieldset :id="label.toLowerCase()" :class="{ 'no-colored-frames': noFrameColors }">
<legend @click.prevent="collapse">{{ label }} </legend>
<div class="collapsible" :class="{ hidden: collapsed }">
<slot />
</div>
</fieldset>
<fieldset :id="label.toLowerCase()" :class="{ 'no-colored-frames': noFrameColors }">
<legend @click.prevent="collapse">{{ label }} </legend>
<div class="collapsible" :class="{ hidden: collapsed }">
<slot />
</div>
</fieldset>
</template>
<style>
fieldset.no-colored-frames {
border-color: #afafaf !important;
}
fieldset.no-colored-frames {
border-color: #afafaf !important;
}
fieldset.no-colored-frames legend {
color: var(--ac-color);
}
fieldset.no-colored-frames legend {
color: var(--ac-color);
}
</style>
<script>
export default {
computed: {
noFrameColors () {
return this.$store.state.postwoman.settings.DISABLE_FRAME_COLORS || false;
}
},
props: {
"label": {
type: String,
default: "Section"
},
"collapsed": {
type: Boolean
}
},
methods: {
collapse({ target }) {
const parent = target.parentNode;
parent.querySelector(".collapsible").classList.toggle('hidden');
},
}
export default {
computed: {
noFrameColors() {
return this.$store.state.postwoman.settings.DISABLE_FRAME_COLORS || false;
}
},
props: {
label: {
type: String,
default: "Section"
},
collapsed: {
type: Boolean
}
},
methods: {
collapse({ target }) {
const parent = target.parentNode;
parent.querySelector(".collapsible").classList.toggle("hidden");
}
}
};
</script>

View File

@@ -35,12 +35,13 @@
<!-- 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">{{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>
</span>
<span v-if="version.variant"> ({{ version.variant }})</span>
&#x2022; </span>by <a href="https://liyasthomas.web.app" target="_blank">Liyas Thomas 🦄</a>
- <a v-bind:href="'https://github.com/liyasthomas/postwoman/commit/' + version.hash" target="_blank">{{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>
</p>
</footer>
</div>

View File

@@ -223,113 +223,127 @@
</li>
</ul>
</pw-section>
<pw-section class="green" collapsed label="Authentication">
<ul>
<li>
<label for="auth">Authentication Type</label>
<select v-model="auth">
<option>None</option>
<option>Basic</option>
<option>Bearer Token</option>
</select>
</li>
</ul>
<ul v-if="auth === 'Basic'">
<li>
<label for="http_basic_user">User</label>
<input v-model="httpUser">
</li>
<li>
<label for="http_basic_passwd">Password</label>
<input :type="passwordFieldType" v-model="httpPassword">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="switchVisibility">&nbsp;</label>
<button class="icon" 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" />
</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" />
</svg>
</button>
</li>
</div>
</ul>
<ul v-if="auth === 'Bearer Token'">
<li>
<label for="bearer_token">Token</label>
<input v-model="bearerToken">
</li>
</ul>
</pw-section>
<pw-section class="orange" collapsed label="Headers">
<ul v-for="(header, index) in headers" :key="index">
<li>
<label :for="'header'+index">Header {{index + 1}}</label>
<input :name="'header'+index" v-model="header.key" @keyup.prevent="setRouteQueryState" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :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)" name="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>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button @click="addRequestHeader" name="add">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="request">Header List</label>
<textarea name="request" readonly v-textarea-auto-height="headerString" v-model="headerString" placeholder="(add at least one header)" rows="1"></textarea>
</li>
</ul>
</pw-section>
<pw-section class="pink" collapsed label="Parameters">
<ul v-for="(param, index) in params" :key="index">
<li>
<label :for="'param'+index">Parameter {{index + 1}}</label>
<input :name="'param'+index" v-model="param.key" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :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)" name="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>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button @click="addRequestParam" name="add">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" readonly v-textarea-auto-height="queryString" v-model="queryString" placeholder="(add at least one parameter)" rows="1"></textarea>
</li>
</ul>
</pw-section>
<section>
<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">
<ul>
<li>
<label for="auth">Authentication Type</label>
<select v-model="auth">
<option>None</option>
<option>Basic</option>
<option>Bearer Token</option>
</select>
</li>
</ul>
<ul v-if="auth === 'Basic'">
<li>
<label for="http_basic_user">User</label>
<input v-model="httpUser">
</li>
<li>
<label for="http_basic_passwd">Password</label>
<input :type="passwordFieldType" v-model="httpPassword">
</li>
<div>
<li>
<label class="hide-on-small-screen" for="switchVisibility">&nbsp;</label>
<button class="icon" 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" />
</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" />
</svg>
</button>
</li>
</div>
</ul>
<ul v-if="auth === 'Bearer Token'">
<li>
<label for="bearer_token">Token</label>
<input v-model="bearerToken">
</li>
</ul>
</pw-section>
</div>
<input id="tab-two" type="radio" name="grp">
<label for="tab-two">Headers</label>
<div class="tab">
<pw-section class="orange" label="Headers">
<ul v-for="(header, index) in headers" :key="index">
<li>
<label :for="'header'+index">Header {{index + 1}}</label>
<input :name="'header'+index" v-model="header.key" @keyup.prevent="setRouteQueryState" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :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)" name="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>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button @click="addRequestHeader" name="add">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="request">Header List</label>
<textarea name="request" readonly v-textarea-auto-height="headerString" v-model="headerString" placeholder="(add at least one header)" rows="1"></textarea>
</li>
</ul>
</pw-section>
</div>
<input id="tab-three" type="radio" name="grp">
<label for="tab-three">Parameters</label>
<div class="tab">
<pw-section class="pink" label="Parameters">
<ul v-for="(param, index) in params" :key="index">
<li>
<label :for="'param'+index">Parameter {{index + 1}}</label>
<input :name="'param'+index" v-model="param.key" autofocus>
</li>
<li>
<label :for="'value'+index">Value {{index + 1}}</label>
<input :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)" name="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>
</button>
</li>
</div>
</ul>
<ul>
<li>
<button @click="addRequestParam" name="add">Add New</button>
</li>
</ul>
<ul>
<li>
<label for="request">Parameter List</label>
<textarea name="request" readonly v-textarea-auto-height="queryString" v-model="queryString" placeholder="(add at least one parameter)" rows="1"></textarea>
</li>
</ul>
</pw-section>
</div>
</section>
<history @useHistory="handleUseHistory" ref="historyComponent"></history>
</div>
</template>

View File

@@ -28,7 +28,7 @@
<label for="log">Log</label>
<div id="log" name="log" class="log">
<span v-if="communication.log">
<span v-for="logEntry in communication.log" :style="{ color: logEntry.color }">@ {{ logEntry.ts }} {{ getSourcePrefix(logEntry.source) }} {{ logEntry.payload }}</span>
<span v-for="(logEntry, index) in communication.log" :style="{ color: logEntry.color }" :key="index">@ {{ logEntry.ts }} {{ getSourcePrefix(logEntry.source) }} {{ logEntry.payload }}</span>
</span>
<span v-else>(Waiting for connection...)</span>
</div>