Initial prettier formatted files

This commit is contained in:
Dmitry Yankowski
2020-02-24 13:44:50 -05:00
parent 1543c990ca
commit 777e629b3d
83 changed files with 18556 additions and 19258 deletions

View File

@@ -1,6 +1,6 @@
import * as cookie from "cookie";
import * as URL from "url";
import * as querystring from "querystring";
import * as cookie from 'cookie'
import * as URL from 'url'
import * as querystring from 'querystring'
/**
* given this: [ 'msg1=value1', 'msg2=value2' ]
@@ -8,219 +8,215 @@ import * as querystring from "querystring";
* @param dataArguments
*/
const joinDataArguments = dataArguments => {
let data = "";
let data = ''
dataArguments.forEach((argument, i) => {
if (i === 0) {
data += argument;
data += argument
} else {
data += `&${argument}`;
data += `&${argument}`
}
});
return data;
};
})
return data
}
const parseCurlCommand = curlCommand => {
let newlineFound = /\r|\n/.exec(curlCommand);
let newlineFound = /\r|\n/.exec(curlCommand)
if (newlineFound) {
// remove newlines
curlCommand = curlCommand.replace(/\r|\n/g, "");
curlCommand = curlCommand.replace(/\r|\n/g, '')
}
// yargs parses -XPOST as separate arguments. just prescreen for it.
curlCommand = curlCommand.replace(/ -XPOST/, " -X POST");
curlCommand = curlCommand.replace(/ -XGET/, " -X GET");
curlCommand = curlCommand.replace(/ -XPUT/, " -X PUT");
curlCommand = curlCommand.replace(/ -XPATCH/, " -X PATCH");
curlCommand = curlCommand.replace(/ -XDELETE/, " -X DELETE");
curlCommand = curlCommand.trim();
let parsedArguments = require("yargs-parser")(curlCommand);
let cookieString;
let cookies;
let url = parsedArguments._[1];
curlCommand = curlCommand.replace(/ -XPOST/, ' -X POST')
curlCommand = curlCommand.replace(/ -XGET/, ' -X GET')
curlCommand = curlCommand.replace(/ -XPUT/, ' -X PUT')
curlCommand = curlCommand.replace(/ -XPATCH/, ' -X PATCH')
curlCommand = curlCommand.replace(/ -XDELETE/, ' -X DELETE')
curlCommand = curlCommand.trim()
let parsedArguments = require('yargs-parser')(curlCommand)
let cookieString
let cookies
let url = parsedArguments._[1]
if (!url) {
for (let argName in parsedArguments) {
if (typeof parsedArguments[argName] === "string") {
if (["http", "www."].includes(parsedArguments[argName])) {
url = parsedArguments[argName];
if (typeof parsedArguments[argName] === 'string') {
if (['http', 'www.'].includes(parsedArguments[argName])) {
url = parsedArguments[argName]
}
}
}
}
let headers;
let headers
const parseHeaders = headerFieldName => {
if (parsedArguments[headerFieldName]) {
if (!headers) {
headers = {};
headers = {}
}
if (!Array.isArray(parsedArguments[headerFieldName])) {
parsedArguments[headerFieldName] = [parsedArguments[headerFieldName]];
parsedArguments[headerFieldName] = [parsedArguments[headerFieldName]]
}
parsedArguments[headerFieldName].forEach(header => {
if (header.includes("Cookie")) {
if (header.includes('Cookie')) {
// stupid javascript tricks: closure
cookieString = header;
cookieString = header
} else {
let colonIndex = header.indexOf(":");
let headerName = header.substring(0, colonIndex);
let headerValue = header.substring(colonIndex + 1).trim();
headers[headerName] = headerValue;
let colonIndex = header.indexOf(':')
let headerName = header.substring(0, colonIndex)
let headerValue = header.substring(colonIndex + 1).trim()
headers[headerName] = headerValue
}
});
})
}
};
}
parseHeaders("H");
parseHeaders("header");
parseHeaders('H')
parseHeaders('header')
if (parsedArguments.A) {
if (!headers) {
headers = [];
headers = []
}
headers["User-Agent"] = parsedArguments.A;
} else if (parsedArguments["user-agent"]) {
headers['User-Agent'] = parsedArguments.A
} else if (parsedArguments['user-agent']) {
if (!headers) {
headers = [];
headers = []
}
headers["User-Agent"] = parsedArguments["user-agent"];
headers['User-Agent'] = parsedArguments['user-agent']
}
if (parsedArguments.b) {
cookieString = parsedArguments.b;
cookieString = parsedArguments.b
}
if (parsedArguments.cookie) {
cookieString = parsedArguments.cookie;
cookieString = parsedArguments.cookie
}
let multipartUploads;
let multipartUploads
if (parsedArguments.F) {
multipartUploads = {};
multipartUploads = {}
if (!Array.isArray(parsedArguments.F)) {
parsedArguments.F = [parsedArguments.F];
parsedArguments.F = [parsedArguments.F]
}
parsedArguments.F.forEach(multipartArgument => {
// input looks like key=value. value could be json or a file path prepended with an @
const [key, value] = multipartArgument.split("=", 2);
multipartUploads[key] = value;
});
const [key, value] = multipartArgument.split('=', 2)
multipartUploads[key] = value
})
}
if (cookieString) {
const cookieParseOptions = {
decode: s => s
};
decode: s => s,
}
// separate out cookie headers into separate data structure
// note: cookie is case insensitive
cookies = cookie.parse(
cookieString.replace(/^Cookie: /gi, ""),
cookieParseOptions
);
cookies = cookie.parse(cookieString.replace(/^Cookie: /gi, ''), cookieParseOptions)
}
let method;
if (parsedArguments.X === "POST") {
method = "post";
} else if (parsedArguments.X === "PUT" || parsedArguments["T"]) {
method = "put";
} else if (parsedArguments.X === "PATCH") {
method = "patch";
} else if (parsedArguments.X === "DELETE") {
method = "delete";
} else if (parsedArguments.X === "OPTIONS") {
method = "options";
let method
if (parsedArguments.X === 'POST') {
method = 'post'
} else if (parsedArguments.X === 'PUT' || parsedArguments['T']) {
method = 'put'
} else if (parsedArguments.X === 'PATCH') {
method = 'patch'
} else if (parsedArguments.X === 'DELETE') {
method = 'delete'
} else if (parsedArguments.X === 'OPTIONS') {
method = 'options'
} else if (
(parsedArguments["d"] ||
parsedArguments["data"] ||
parsedArguments["data-ascii"] ||
parsedArguments["data-binary"] ||
parsedArguments["F"] ||
parsedArguments["form"]) &&
!(parsedArguments["G"] || parsedArguments["get"])
(parsedArguments['d'] ||
parsedArguments['data'] ||
parsedArguments['data-ascii'] ||
parsedArguments['data-binary'] ||
parsedArguments['F'] ||
parsedArguments['form']) &&
!(parsedArguments['G'] || parsedArguments['get'])
) {
method = "post";
} else if (parsedArguments["I"] || parsedArguments["head"]) {
method = "head";
method = 'post'
} else if (parsedArguments['I'] || parsedArguments['head']) {
method = 'head'
} else {
method = "get";
method = 'get'
}
let compressed = !!parsedArguments.compressed;
let urlObject = URL.parse(url); // eslint-disable-line
let compressed = !!parsedArguments.compressed
let urlObject = URL.parse(url) // eslint-disable-line
// if GET request with data, convert data to query string
// NB: the -G flag does not change the http verb. It just moves the data into the url.
if (parsedArguments["G"] || parsedArguments["get"]) {
urlObject.query = urlObject.query ? urlObject.query : "";
let option =
"d" in parsedArguments ? "d" : "data" in parsedArguments ? "data" : null;
if (parsedArguments['G'] || parsedArguments['get']) {
urlObject.query = urlObject.query ? urlObject.query : ''
let option = 'd' in parsedArguments ? 'd' : 'data' in parsedArguments ? 'data' : null
if (option) {
let urlQueryString = "";
let urlQueryString = ''
if (!url.includes("?")) {
url += "?";
if (!url.includes('?')) {
url += '?'
} else {
urlQueryString += "&";
urlQueryString += '&'
}
if (typeof parsedArguments[option] === "object") {
urlQueryString += parsedArguments[option].join("&");
if (typeof parsedArguments[option] === 'object') {
urlQueryString += parsedArguments[option].join('&')
} else {
urlQueryString += parsedArguments[option];
urlQueryString += parsedArguments[option]
}
urlObject.query += urlQueryString;
url += urlQueryString;
delete parsedArguments[option];
urlObject.query += urlQueryString
url += urlQueryString
delete parsedArguments[option]
}
}
let query = querystring.parse(urlObject.query, null, null, {
maxKeys: 10000
});
maxKeys: 10000,
})
urlObject.search = null; // Clean out the search/query portion.
urlObject.search = null // Clean out the search/query portion.
const request = {
url,
urlWithoutQuery: URL.format(urlObject)
};
urlWithoutQuery: URL.format(urlObject),
}
if (compressed) {
request["compressed"] = true;
request['compressed'] = true
}
if (Object.keys(query).length > 0) {
request.query = query;
request.query = query
}
if (headers) {
request.headers = headers;
request.headers = headers
}
request["method"] = method;
request['method'] = method
if (cookies) {
request.cookies = cookies;
request.cookieString = cookieString.replace("Cookie: ", "");
request.cookies = cookies
request.cookieString = cookieString.replace('Cookie: ', '')
}
if (multipartUploads) {
request.multipartUploads = multipartUploads;
request.multipartUploads = multipartUploads
}
if (parsedArguments.data) {
request.data = parsedArguments.data;
} else if (parsedArguments["data-binary"]) {
request.data = parsedArguments["data-binary"];
request.isDataBinary = true;
} else if (parsedArguments["d"]) {
request.data = parsedArguments["d"];
} else if (parsedArguments["data-ascii"]) {
request.data = parsedArguments["data-ascii"];
request.data = parsedArguments.data
} else if (parsedArguments['data-binary']) {
request.data = parsedArguments['data-binary']
request.isDataBinary = true
} else if (parsedArguments['d']) {
request.data = parsedArguments['d']
} else if (parsedArguments['data-ascii']) {
request.data = parsedArguments['data-ascii']
}
if (parsedArguments["u"]) {
request.auth = parsedArguments["u"];
if (parsedArguments['u']) {
request.auth = parsedArguments['u']
}
if (parsedArguments["user"]) {
request.auth = parsedArguments["user"];
if (parsedArguments['user']) {
request.auth = parsedArguments['user']
}
if (Array.isArray(request.data)) {
request.dataArray = request.data;
request.data = joinDataArguments(request.data);
request.dataArray = request.data
request.data = joinDataArguments(request.data)
}
if (parsedArguments["k"] || parsedArguments["insecure"]) {
request.insecure = true;
if (parsedArguments['k'] || parsedArguments['insecure']) {
request.insecure = true
}
return request;
};
return request
}
export default parseCurlCommand;
export default parseCurlCommand

View File

@@ -1,4 +1,4 @@
const redirectUri = `${window.location.origin}/`;
const redirectUri = `${window.location.origin}/`
// GENERAL HELPER FUNCTIONS
@@ -13,23 +13,23 @@ const redirectUri = `${window.location.origin}/`;
const sendPostRequest = async (url, params) => {
const body = Object.keys(params)
.map(key => `${key}=${params[key]}`)
.join("&");
.join('&')
const options = {
method: "post",
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body
};
try {
const response = await fetch(url, options);
const data = await response.json();
return data;
} catch (err) {
console.error("Request failed", err);
throw err;
body,
}
};
try {
const response = await fetch(url, options)
const data = await response.json()
return data
} catch (err) {
console.error('Request failed', err)
throw err
}
}
/**
* Parse a query string into an object
@@ -39,16 +39,13 @@ const sendPostRequest = async (url, params) => {
*/
const parseQueryString = searchQuery => {
if (searchQuery === "") {
return {};
if (searchQuery === '') {
return {}
}
const segments = searchQuery.split("&").map(s => s.split("="));
const queryString = segments.reduce(
(obj, el) => ({ ...obj, [el[0]]: el[1] }),
{}
);
return queryString;
};
const segments = searchQuery.split('&').map(s => s.split('='))
const queryString = segments.reduce((obj, el) => ({ ...obj, [el[0]]: el[1] }), {})
return queryString
}
/**
* Get OAuth configuration from OpenID Discovery endpoint
@@ -58,20 +55,20 @@ const parseQueryString = searchQuery => {
const getTokenConfiguration = async endpoint => {
const options = {
method: "GET",
method: 'GET',
headers: {
"Content-type": "application/json"
}
};
try {
const response = await fetch(endpoint, options);
const config = await response.json();
return config;
} catch (err) {
console.error("Request failed", err);
throw err;
'Content-type': 'application/json',
},
}
};
try {
const response = await fetch(endpoint, options)
const config = await response.json()
return config
} catch (err) {
console.error('Request failed', err)
throw err
}
}
// PKCE HELPER FUNCTIONS
@@ -82,10 +79,10 @@ const getTokenConfiguration = async endpoint => {
*/
const generateRandomString = () => {
const array = new Uint32Array(28);
window.crypto.getRandomValues(array);
return Array.from(array, dec => `0${dec.toString(16)}`.substr(-2)).join("");
};
const array = new Uint32Array(28)
window.crypto.getRandomValues(array)
return Array.from(array, dec => `0${dec.toString(16)}`.substr(-2)).join('')
}
/**
* Calculate the SHA256 hash of the input text
@@ -94,10 +91,10 @@ const generateRandomString = () => {
*/
const sha256 = plain => {
const encoder = new TextEncoder();
const data = encoder.encode(plain);
return window.crypto.subtle.digest("SHA-256", data);
};
const encoder = new TextEncoder()
const data = encoder.encode(plain)
return window.crypto.subtle.digest('SHA-256', data)
}
/**
* Encodes the input string into Base64 format
@@ -113,9 +110,9 @@ const base64urlencode = (
// Then convert the base64 encoded to base64url encoded
// (replace + with -, replace / with _, trim trailing =)
btoa(String.fromCharCode.apply(null, new Uint8Array(str)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
/**
* Return the base64-urlencoded sha256 hash for the PKCE challenge
@@ -125,9 +122,9 @@ const base64urlencode = (
*/
const pkceChallengeFromVerifier = async v => {
const hashed = await sha256(v);
return base64urlencode(hashed);
};
const hashed = await sha256(v)
return base64urlencode(hashed)
}
// OAUTH REQUEST
@@ -144,32 +141,29 @@ const tokenRequest = async ({
authUrl,
accessTokenUrl,
clientId,
scope
scope,
}) => {
// Check oauth configuration
if (oidcDiscoveryUrl !== "") {
const {
authorization_endpoint,
token_endpoint
} = await getTokenConfiguration(oidcDiscoveryUrl);
authUrl = authorization_endpoint;
accessTokenUrl = token_endpoint;
if (oidcDiscoveryUrl !== '') {
const { authorization_endpoint, token_endpoint } = await getTokenConfiguration(oidcDiscoveryUrl)
authUrl = authorization_endpoint
accessTokenUrl = token_endpoint
}
// Store oauth information
localStorage.setItem("token_endpoint", accessTokenUrl);
localStorage.setItem("client_id", clientId);
localStorage.setItem('token_endpoint', accessTokenUrl)
localStorage.setItem('client_id', clientId)
// Create and store a random state value
const state = generateRandomString();
localStorage.setItem("pkce_state", state);
const state = generateRandomString()
localStorage.setItem('pkce_state', state)
// Create and store a new PKCE code_verifier (the plaintext random secret)
const code_verifier = generateRandomString();
localStorage.setItem("pkce_code_verifier", code_verifier);
const code_verifier = generateRandomString()
localStorage.setItem('pkce_code_verifier', code_verifier)
// Hash and base64-urlencode the secret to use as the challenge
const code_challenge = await pkceChallengeFromVerifier(code_verifier);
const code_challenge = await pkceChallengeFromVerifier(code_verifier)
// Build the authorization URL
const buildUrl = () =>
@@ -177,15 +171,13 @@ const tokenRequest = async ({
clientId
)}&state=${encodeURIComponent(state)}&scope=${encodeURIComponent(
scope
)}&redirect_uri=${encodeURIComponent(
redirectUri
)}&code_challenge=${encodeURIComponent(
)}&redirect_uri=${encodeURIComponent(redirectUri)}&code_challenge=${encodeURIComponent(
code_challenge
)}&code_challenge_method=S256`;
)}&code_challenge_method=S256`
// Redirect to the authorization server
window.location = buildUrl();
};
window.location = buildUrl()
}
// OAUTH REDIRECT HANDLING
@@ -197,42 +189,39 @@ const tokenRequest = async ({
*/
const oauthRedirect = async () => {
let tokenResponse = "";
let q = parseQueryString(window.location.search.substring(1));
let tokenResponse = ''
let q = parseQueryString(window.location.search.substring(1))
// Check if the server returned an error string
if (q.error) {
alert(`Error returned from authorization server: ${q.error}`);
alert(`Error returned from authorization server: ${q.error}`)
}
// If the server returned an authorization code, attempt to exchange it for an access token
if (q.code) {
// Verify state matches what we set at the beginning
if (localStorage.getItem("pkce_state") != q.state) {
alert("Invalid state");
if (localStorage.getItem('pkce_state') != q.state) {
alert('Invalid state')
} else {
try {
// Exchange the authorization code for an access token
tokenResponse = await sendPostRequest(
localStorage.getItem("token_endpoint"),
{
grant_type: "authorization_code",
code: q.code,
client_id: localStorage.getItem("client_id"),
redirect_uri: redirectUri,
code_verifier: localStorage.getItem("pkce_code_verifier")
}
);
tokenResponse = await sendPostRequest(localStorage.getItem('token_endpoint'), {
grant_type: 'authorization_code',
code: q.code,
client_id: localStorage.getItem('client_id'),
redirect_uri: redirectUri,
code_verifier: localStorage.getItem('pkce_code_verifier'),
})
} catch (err) {
console.log(`${error.error}\n\n${error.error_description}`);
console.log(`${error.error}\n\n${error.error_description}`)
}
}
// Clean these up since we don't need them anymore
localStorage.removeItem("pkce_state");
localStorage.removeItem("pkce_code_verifier");
localStorage.removeItem("token_endpoint");
localStorage.removeItem("client_id");
return tokenResponse;
localStorage.removeItem('pkce_state')
localStorage.removeItem('pkce_code_verifier')
localStorage.removeItem('token_endpoint')
localStorage.removeItem('client_id')
return tokenResponse
}
return tokenResponse;
};
return tokenResponse
}
export { tokenRequest, oauthRedirect };
export { tokenRequest, oauthRedirect }

View File

@@ -2,55 +2,50 @@ export default () => {
//*** Determine whether or not the PWA has been installed. ***//
// Step 1: Check local storage
let pwaInstalled = localStorage.getItem("pwaInstalled") === "yes";
let pwaInstalled = localStorage.getItem('pwaInstalled') === 'yes'
// Step 2: Check if the display-mode is standalone. (Only permitted for PWAs.)
if (
!pwaInstalled &&
window.matchMedia("(display-mode: standalone)").matches
) {
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
if (!pwaInstalled && window.matchMedia('(display-mode: standalone)').matches) {
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
}
// Step 3: Check if the navigator is in standalone mode. (Again, only permitted for PWAs.)
if (!pwaInstalled && window.navigator.standalone === true) {
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
}
//*** If the PWA has not been installed, show the install PWA prompt.. ***//
let deferredPrompt = null;
window.addEventListener("beforeinstallprompt", event => {
deferredPrompt = event;
let deferredPrompt = null
window.addEventListener('beforeinstallprompt', event => {
deferredPrompt = event
// Show the install button if the prompt appeared.
if (!pwaInstalled) {
document.querySelector("#installPWA").style.display = "inline-flex";
document.querySelector('#installPWA').style.display = 'inline-flex'
}
});
})
// When the app is installed, remove install prompts.
window.addEventListener("appinstalled", event => {
localStorage.setItem("pwaInstalled", "yes");
pwaInstalled = true;
document.getElementById("installPWA").style.display = "none";
});
window.addEventListener('appinstalled', event => {
localStorage.setItem('pwaInstalled', 'yes')
pwaInstalled = true
document.getElementById('installPWA').style.display = 'none'
})
// When the app is uninstalled, add the prompts back
return async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
let outcome = await deferredPrompt.userChoice;
deferredPrompt.prompt()
let outcome = await deferredPrompt.userChoice
if (outcome === "accepted") {
console.log("Postwoman was installed successfully.");
if (outcome === 'accepted') {
console.log('Postwoman was installed successfully.')
} else {
console.log(
"Postwoman could not be installed. (Installation rejected by user.)"
);
console.log('Postwoman could not be installed. (Installation rejected by user.)')
}
deferredPrompt = null;
deferredPrompt = null
}
};
};
}
}

View File

@@ -1,63 +1,59 @@
const axios = require("axios");
const fs = require("fs");
const { spawnSync } = require("child_process");
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, "");
.replace(/\n/g, '')
const FAIL_ON_ERROR = false;
const PW_BUILD_DATA_DIR = "./.postwoman";
const IS_DEV_MODE = process.argv.includes("--dev");
const FAIL_ON_ERROR = false
const PW_BUILD_DATA_DIR = './.postwoman'
const IS_DEV_MODE = process.argv.includes('--dev')
try {
(async () => {
;(async () => {
// Create the build data directory if it does not exist.
if (!fs.existsSync(PW_BUILD_DATA_DIR)) {
fs.mkdirSync(PW_BUILD_DATA_DIR);
fs.mkdirSync(PW_BUILD_DATA_DIR)
}
let version = {};
let version = {}
// Get the current version name as the tag from Git.
version.name =
process.env.TRAVIS_TAG ||
runCommand("git", ["tag --sort=committerdate | tail -1"]);
process.env.TRAVIS_TAG || runCommand('git', ['tag --sort=committerdate | tail -1'])
// 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")
.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
}
]
tag_name: require('./package.json').version,
},
],
}))
).data[0]["tag_name"];
).data[0]['tag_name']
}
// Get the current version hash as the short hash from Git.
version.hash = runCommand("git", ["rev-parse", "--short", "HEAD"]);
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 (["", "master"].includes(version.variant)) {
delete version.variant;
runCommand('git', ['branch'])
.split('* ')[1]
.split(' ')[0] + (IS_DEV_MODE ? ' - DEV MODE' : '')
if (['', 'master'].includes(version.variant)) {
delete version.variant
}
// Write version data into a file
fs.writeFileSync(
`${PW_BUILD_DATA_DIR}/version.json`,
JSON.stringify(version)
);
})();
fs.writeFileSync(`${PW_BUILD_DATA_DIR}/version.json`, JSON.stringify(version))
})()
} catch (ex) {
console.error(ex);
process.exit(FAIL_ON_ERROR ? 1 : 0);
console.error(ex)
process.exit(FAIL_ON_ERROR ? 1 : 0)
}

View File

@@ -3,89 +3,87 @@
</template>
<script>
const DEFAULT_THEME = "twilight";
const DEFAULT_THEME = 'twilight'
import ace from "ace-builds";
import "ace-builds/webpack-resolver";
import ace from 'ace-builds'
import 'ace-builds/webpack-resolver'
export default {
props: {
value: {
type: String,
default: ""
default: '',
},
theme: {
type: String,
required: false
required: false,
},
lang: {
type: String,
default: "json"
default: 'json',
},
options: {
type: Object,
default: {}
}
default: {},
},
},
data() {
return {
editor: null,
cacheValue: ""
};
cacheValue: '',
}
},
watch: {
value(value) {
if (value !== this.cacheValue) {
this.editor.session.setValue(value, 1);
this.cacheValue = value;
this.editor.session.setValue(value, 1)
this.cacheValue = value
}
},
theme() {
this.editor.setTheme("ace/theme/" + this.defineTheme());
this.editor.setTheme('ace/theme/' + this.defineTheme())
},
lang(value) {
this.editor.getSession().setMode("ace/mode/" + value);
this.editor.getSession().setMode('ace/mode/' + value)
},
options(value) {
this.editor.setOptions(value);
}
this.editor.setOptions(value)
},
},
mounted() {
const editor = ace.edit(this.$refs.editor, {
theme: `ace/theme/${this.defineTheme()}`,
mode: `ace/mode/${this.lang}`,
...this.options
});
...this.options,
})
if (this.value) editor.setValue(this.value, 1);
if (this.value) editor.setValue(this.value, 1)
this.editor = editor;
this.cacheValue = this.value;
this.editor = editor
this.cacheValue = this.value
editor.on("change", () => {
const content = editor.getValue();
this.$emit("input", content);
this.cacheValue = content;
});
editor.on('change', () => {
const content = editor.getValue()
this.$emit('input', content)
this.cacheValue = content
})
},
methods: {
defineTheme() {
if (this.theme) {
return this.theme;
return this.theme
}
return (
this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
);
}
return this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
},
},
beforeDestroy() {
this.editor.destroy();
this.editor.container.remove();
}
};
this.editor.destroy()
this.editor.container.remove()
},
}
</script>

View File

@@ -57,7 +57,7 @@
display: block;
padding: 8px 16px;
font-size: 16px;
font-family: "Roboto Mono", monospace;
font-family: 'Roboto Mono', monospace;
font-weight: 400;
&:last-child {
@@ -76,42 +76,42 @@
</style>
<script>
const KEY_TAB = 9;
const KEY_ESC = 27;
const KEY_TAB = 9
const KEY_ESC = 27
const KEY_ARROW_UP = 38;
const KEY_ARROW_DOWN = 40;
const KEY_ARROW_UP = 38
const KEY_ARROW_DOWN = 40
export default {
props: {
spellcheck: {
type: Boolean,
default: true,
required: false
required: false,
},
placeholder: {
type: String,
default: "",
required: false
default: '',
required: false,
},
source: {
type: Array,
required: true
required: true,
},
value: {
type: String,
default: "",
required: false
}
default: '',
required: false,
},
},
watch: {
text() {
this.$emit("input", this.text);
}
this.$emit('input', this.text)
},
},
data() {
@@ -120,69 +120,67 @@ export default {
selectionStart: 0,
suggestionsOffsetLeft: 0,
currentSuggestionIndex: -1,
suggestionsVisible: false
};
suggestionsVisible: false,
}
},
methods: {
updateSuggestions(event) {
// Hide suggestions if ESC pressed.
if (event.which && event.which === KEY_ESC) {
event.preventDefault();
this.suggestionsVisible = false;
this.currentSuggestionIndex = -1;
return;
event.preventDefault()
this.suggestionsVisible = false
this.currentSuggestionIndex = -1
return
}
// As suggestions is a reactive property, this implicitly
// causes suggestions to update.
this.selectionStart = this.$refs.acInput.selectionStart;
this.suggestionsOffsetLeft = 12 * this.selectionStart;
this.suggestionsVisible = true;
this.selectionStart = this.$refs.acInput.selectionStart
this.suggestionsOffsetLeft = 12 * this.selectionStart
this.suggestionsVisible = true
},
forceSuggestion(text) {
let input = this.text.substring(0, this.selectionStart);
this.text = input + text;
let input = this.text.substring(0, this.selectionStart)
this.text = input + text
this.selectionStart = this.text.length;
this.suggestionsVisible = true;
this.currentSuggestionIndex = -1;
this.selectionStart = this.text.length
this.suggestionsVisible = true
this.currentSuggestionIndex = -1
},
handleKeystroke(event) {
switch (event.which) {
case KEY_ARROW_UP:
event.preventDefault();
event.preventDefault()
this.currentSuggestionIndex =
this.currentSuggestionIndex - 1 >= 0
? this.currentSuggestionIndex - 1
: 0;
break;
this.currentSuggestionIndex - 1 >= 0 ? this.currentSuggestionIndex - 1 : 0
break
case KEY_ARROW_DOWN:
event.preventDefault();
event.preventDefault()
this.currentSuggestionIndex =
this.currentSuggestionIndex < this.suggestions.length - 1
? this.currentSuggestionIndex + 1
: this.suggestions.length - 1;
break;
: this.suggestions.length - 1
break
case KEY_TAB:
event.preventDefault();
event.preventDefault()
let activeSuggestion = this.suggestions[
this.currentSuggestionIndex >= 0 ? this.currentSuggestionIndex : 0
];
]
if (activeSuggestion) {
let input = this.text.substring(0, this.selectionStart);
this.text = input + activeSuggestion;
let input = this.text.substring(0, this.selectionStart)
this.text = input + activeSuggestion
}
break;
break
default:
break;
break
}
}
},
},
computed: {
@@ -192,7 +190,7 @@ export default {
* @returns {default.props.source|{type, required}}
*/
suggestions() {
let input = this.text.substring(0, this.selectionStart);
let input = this.text.substring(0, this.selectionStart)
return (
this.source
@@ -200,20 +198,20 @@ export default {
return (
entry.toLowerCase().startsWith(input.toLowerCase()) &&
input.toLowerCase() !== entry.toLowerCase()
);
)
})
// Cut off the part that's already been typed.
.map(entry => entry.substring(this.selectionStart))
// We only want the top 6 suggestions.
.slice(0, 6)
);
}
)
},
},
mounted() {
this.updateSuggestions({
target: this.$refs.acInput
});
}
};
target: this.$refs.acInput,
})
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("new_collection") }}</h3>
<h3 class="title">{{ $t('new_collection') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -31,10 +31,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="addNewCollection">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -43,44 +43,42 @@
</template>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
props: {
show: Boolean
show: Boolean,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
methods: {
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
fb.writeCollections(JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)))
}
}
},
addNewCollection() {
if (!this.$data.name) {
this.$toast.info($t("invalid_collection_name"));
return;
this.$toast.info($t('invalid_collection_name'))
return
}
this.$store.commit("postwoman/addNewCollection", {
name: this.$data.name
});
this.$emit("hide-modal");
this.syncCollections();
this.$store.commit('postwoman/addNewCollection', {
name: this.$data.name,
})
this.$emit('hide-modal')
this.syncCollections()
},
hideModal() {
this.$emit("hide-modal");
}
}
};
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("new_folder") }}</h3>
<h3 class="title">{{ $t('new_folder') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -31,10 +31,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="addNewFolder">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -47,27 +47,27 @@ export default {
props: {
show: Boolean,
collection: Object,
collectionIndex: Number
collectionIndex: Number,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
methods: {
addNewFolder() {
this.$store.commit("postwoman/addNewFolder", {
this.$store.commit('postwoman/addNewFolder', {
folder: { name: this.$data.name },
collectionIndex: this.$props.collectionIndex
});
this.hideModal();
collectionIndex: this.$props.collectionIndex,
})
this.hideModal()
},
hideModal() {
this.$emit("hide-modal");
}
}
};
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -17,23 +17,19 @@
<div>
<button class="icon" @click="$emit('add-folder')" v-close-popover>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("new_folder") }}</span>
<span>{{ $t('new_folder') }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="$emit('edit-collection')"
v-close-popover
>
<button class="icon" @click="$emit('edit-collection')" v-close-popover>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
<span>{{ $t('edit') }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeCollection" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
<span>{{ $t('delete') }}</span>
</button>
</div>
</template>
@@ -51,12 +47,8 @@
@edit-request="$emit('edit-request', $event)"
/>
</li>
<li
v-if="
collection.folders.length === 0 && collection.requests.length === 0
"
>
<label>{{ $t("collection_empty") }}</label>
<li v-if="collection.folders.length === 0 && collection.requests.length === 0">
<label>{{ $t('collection_empty') }}</label>
</li>
</ul>
<ul>
@@ -71,7 +63,7 @@
request,
collectionIndex,
folderIndex: undefined,
requestIndex: index
requestIndex: index,
})
"
/>
@@ -97,32 +89,32 @@ ul li {
<script>
export default {
components: {
folder: () => import("./folder"),
request: () => import("./request")
folder: () => import('./folder'),
request: () => import('./request'),
},
props: {
collectionIndex: Number,
collection: Object
collection: Object,
},
data() {
return {
showChildren: false,
selectedFolder: {}
};
selectedFolder: {},
}
},
methods: {
toggleShowChildren() {
this.showChildren = !this.showChildren;
this.showChildren = !this.showChildren
},
removeCollection() {
if (!confirm("Are you sure you want to remove this Collection?")) return;
this.$store.commit("postwoman/removeCollection", {
collectionIndex: this.collectionIndex
});
if (!confirm('Are you sure you want to remove this Collection?')) return
this.$store.commit('postwoman/removeCollection', {
collectionIndex: this.collectionIndex,
})
},
editFolder(collectionIndex, folder, folderIndex) {
this.$emit("edit-folder", { collectionIndex, folder, folderIndex });
}
}
};
this.$emit('edit-folder', { collectionIndex, folder, folderIndex })
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("edit_collection") }}</h3>
<h3 class="title">{{ $t('edit_collection') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -31,10 +31,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="saveCollection">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -47,35 +47,35 @@ export default {
props: {
show: Boolean,
editingCollection: Object,
editingCollectionIndex: Number
editingCollectionIndex: Number,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
methods: {
saveCollection() {
if (!this.$data.name) {
this.$toast.info($t("invalid_collection_name"));
return;
this.$toast.info($t('invalid_collection_name'))
return
}
const collectionUpdated = {
...this.$props.editingCollection,
name: this.$data.name
};
this.$store.commit("postwoman/editCollection", {
name: this.$data.name,
}
this.$store.commit('postwoman/editCollection', {
collection: collectionUpdated,
collectionIndex: this.$props.editingCollectionIndex
});
this.$emit("hide-modal");
collectionIndex: this.$props.editingCollectionIndex,
})
this.$emit('hide-modal')
},
hideModal() {
this.$emit("hide-modal");
}
}
};
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("edit_folder") }}</h3>
<h3 class="title">{{ $t('edit_folder') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,12 +17,7 @@
<div slot="body">
<ul>
<li>
<input
type="text"
v-model="name"
:placeholder="folder.name"
@keyup.enter="editFolder"
/>
<input type="text" v-model="name" :placeholder="folder.name" @keyup.enter="editFolder" />
</li>
</ul>
</div>
@@ -31,10 +26,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="editFolder">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -49,28 +44,28 @@ export default {
collection: Object,
collectionIndex: Number,
folder: Object,
folderIndex: Number
folderIndex: Number,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
methods: {
editFolder() {
this.$store.commit("postwoman/editFolder", {
this.$store.commit('postwoman/editFolder', {
collectionIndex: this.$props.collectionIndex,
folder: { ...this.$props.folder, name: this.$data.name },
folderIndex: this.$props.folderIndex
});
this.hideModal();
folderIndex: this.$props.folderIndex,
})
this.hideModal()
},
hideModal() {
this.$emit("hide-modal");
}
}
};
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("edit_request") }}</h3>
<h3 class="title">{{ $t('edit_request') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,7 +17,7 @@
<div slot="body">
<ul>
<li>
<label for="selectLabel">{{ $t("label") }}</label>
<label for="selectLabel">{{ $t('label') }}</label>
<input
type="text"
id="selectLabel"
@@ -25,24 +25,14 @@
@keyup.enter="saveRequest"
:placeholder="request.name"
/>
<label for="selectCollection">{{ $t("collection") }}</label>
<label for="selectCollection">{{ $t('collection') }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectCollection"
v-model="requestUpdateData.collectionIndex"
>
<select type="text" id="selectCollection" v-model="requestUpdateData.collectionIndex">
<option :key="undefined" :value="undefined" hidden disabled selected>{{
$t('current_collection')
}}</option>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>{{ $t("current_collection") }}</option
>
<option
v-for="(collection, index) in $store.state.postwoman
.collections"
v-for="(collection, index) in $store.state.postwoman.collections"
:key="index"
:value="index"
>
@@ -50,19 +40,11 @@
</option>
</select>
</span>
<label for="selectFolder">{{ $t("folder") }}</label>
<label for="selectFolder">{{ $t('folder') }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectFolder"
v-model="requestUpdateData.folderIndex"
>
<select type="text" id="selectFolder" v-model="requestUpdateData.folderIndex">
<option :key="undefined" :value="undefined">/</option>
<option
v-for="(folder, index) in folders"
:key="index"
:value="index"
>
<option v-for="(folder, index) in folders" :key="index" :value="index">
{{ folder.name }}
</option>
</select>
@@ -75,10 +57,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="saveRequest">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -93,42 +75,39 @@ export default {
collectionIndex: Number,
folderIndex: Number,
request: Object,
requestIndex: Number
requestIndex: Number,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
requestUpdateData: {
name: undefined,
collectionIndex: undefined,
folderIndex: undefined
}
};
folderIndex: undefined,
},
}
},
watch: {
"requestUpdateData.collectionIndex": function resetFolderIndex() {
'requestUpdateData.collectionIndex': function resetFolderIndex() {
// if user choosen some folder, than selected other collection, which doesn't have any folders
// than `requestUpdateData.folderIndex` won't be reseted
this.$data.requestUpdateData.folderIndex = undefined;
}
this.$data.requestUpdateData.folderIndex = undefined
},
},
computed: {
folders() {
const userSelectedAnyCollection =
this.$data.requestUpdateData.collectionIndex !== undefined;
if (!userSelectedAnyCollection) return [];
const userSelectedAnyCollection = this.$data.requestUpdateData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
return this.$store.state.postwoman.collections[
this.$data.requestUpdateData.collectionIndex
].folders;
}
return this.$store.state.postwoman.collections[this.$data.requestUpdateData.collectionIndex]
.folders
},
},
methods: {
saveRequest() {
const userSelectedAnyCollection =
this.$data.requestUpdateData.collectionIndex !== undefined;
const userSelectedAnyCollection = this.$data.requestUpdateData.collectionIndex !== undefined
const requestUpdated = {
...this.$props.request,
@@ -136,25 +115,25 @@ export default {
collection: userSelectedAnyCollection
? this.$data.requestUpdateData.collectionIndex
: this.$props.collectionIndex,
folder: this.$data.requestUpdateData.folderIndex
};
folder: this.$data.requestUpdateData.folderIndex,
}
// pass data separately to don't depend on request's collection, folder fields
// probably, they should be deprecated because they don't describe request itself
this.$store.commit("postwoman/editRequest", {
this.$store.commit('postwoman/editRequest', {
requestOldCollectionIndex: this.$props.collectionIndex,
requestOldFolderIndex: this.$props.folderIndex,
requestOldIndex: this.$props.requestIndex,
requestNew: requestUpdated,
requestNewCollectionIndex: requestUpdated.collection,
requestNewFolderIndex: requestUpdated.folder
});
requestNewFolderIndex: requestUpdated.folder,
})
this.hideModal();
this.hideModal()
},
hideModal() {
this.$emit("hide-modal");
}
}
};
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -17,13 +17,13 @@
<div>
<button class="icon" @click="editFolder" v-close-popover>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
<span>{{ $t('edit') }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeFolder" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
<span>{{ $t('delete') }}</span>
</button>
</div>
</template>
@@ -43,13 +43,13 @@
request,
collectionIndex,
folderIndex,
requestIndex: index
requestIndex: index,
})
"
/>
</li>
<li v-if="folder.requests.length === 0">
<label>{{ $t("folder_empty") }}</label>
<label>{{ $t('folder_empty') }}</label>
</li>
</ul>
</div>
@@ -74,33 +74,33 @@ export default {
props: {
folder: Object,
collectionIndex: Number,
folderIndex: Number
folderIndex: Number,
},
components: {
request: () => import("./request")
request: () => import('./request'),
},
data() {
return {
showChildren: false
};
showChildren: false,
}
},
methods: {
toggleShowChildren() {
this.showChildren = !this.showChildren;
this.showChildren = !this.showChildren
},
selectRequest(request) {
this.$store.commit("postwoman/selectRequest", { request });
this.$store.commit('postwoman/selectRequest', { request })
},
removeFolder() {
if (!confirm("Are you sure you want to remove this folder?")) return;
this.$store.commit("postwoman/removeFolder", {
if (!confirm('Are you sure you want to remove this folder?')) return
this.$store.commit('postwoman/removeFolder', {
collectionIndex: this.collectionIndex,
folderIndex: this.folderIndex
});
folderIndex: this.folderIndex,
})
},
editFolder() {
this.$emit("edit-folder");
}
}
};
this.$emit('edit-folder')
},
},
}
</script>

View File

@@ -14,18 +14,12 @@
<div class="flex-wrap">
<span
v-tooltip="{
content: !fb.currentUser
? $t('login_first')
: $t('replace_current')
content: !fb.currentUser ? $t('login_first') : $t('replace_current'),
}"
>
<button
:disabled="!fb.currentUser"
class="icon"
@click="syncCollections"
>
<button :disabled="!fb.currentUser" class="icon" @click="syncCollections">
<i class="material-icons">folder_shared</i>
<span>{{ $t("import_from_sync") }}</span>
<span>{{ $t('import_from_sync') }}</span>
</button>
</span>
<button
@@ -34,7 +28,7 @@
v-tooltip="$t('replace_current')"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("replace_json") }}</span>
<span>{{ $t('replace_json') }}</span>
<input
type="file"
@change="replaceWithJSON"
@@ -49,7 +43,7 @@
v-tooltip="$t('preserve_current')"
>
<i class="material-icons">folder_special</i>
<span>{{ $t("import_json") }}</span>
<span>{{ $t('import_json') }}</span>
<input
type="file"
@change="importFromJSON"
@@ -70,14 +64,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button
class="icon primary"
@click="exportJSON"
v-tooltip="$t('download_file')"
>
{{ $t("export") }}
<button class="icon primary" @click="exportJSON" v-tooltip="$t('download_file')">
{{ $t('export') }}
</button>
</span>
</div>
@@ -86,239 +76,211 @@
</template>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
data() {
return {
fb
};
fb,
}
},
props: {
show: Boolean
show: Boolean,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
computed: {
collectionJson() {
return JSON.stringify(this.$store.state.postwoman.collections, null, 2);
}
return JSON.stringify(this.$store.state.postwoman.collections, null, 2)
},
},
methods: {
hideModal() {
this.$emit("hide-modal");
this.$emit('hide-modal')
},
openDialogChooseFileToReplaceWith() {
this.$refs.inputChooseFileToReplaceWith.click();
this.$refs.inputChooseFileToReplaceWith.click()
},
openDialogChooseFileToImportFrom() {
this.$refs.inputChooseFileToImportFrom.click();
this.$refs.inputChooseFileToImportFrom.click()
},
replaceWithJSON() {
let reader = new FileReader();
let reader = new FileReader()
reader.onload = event => {
let content = event.target.result;
let collections = JSON.parse(content);
let content = event.target.result
let collections = JSON.parse(content)
if (collections[0]) {
let [name, folders, requests] = Object.keys(collections[0]);
if (
name === "name" &&
folders === "folders" &&
requests === "requests"
) {
let [name, folders, requests] = Object.keys(collections[0])
if (name === 'name' && folders === 'folders' && requests === 'requests') {
// Do nothing
}
} else if (
collections.info &&
collections.info.schema.includes("v2.1.0")
) {
collections = this.parsePostmanCollection(collections);
} else if (collections.info && collections.info.schema.includes('v2.1.0')) {
collections = this.parsePostmanCollection(collections)
} else {
return this.failedImport();
return this.failedImport()
}
this.$store.commit("postwoman/importCollections", collections);
this.fileImported();
};
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0]);
this.$store.commit('postwoman/importCollections', collections)
this.fileImported()
}
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0])
},
importFromJSON() {
let reader = new FileReader();
let reader = new FileReader()
reader.onload = event => {
let content = event.target.result;
let collections = JSON.parse(content);
let content = event.target.result
let collections = JSON.parse(content)
if (collections[0]) {
let [name, folders, requests] = Object.keys(collections[0]);
if (
name === "name" &&
folders === "folders" &&
requests === "requests"
) {
let [name, folders, requests] = Object.keys(collections[0])
if (name === 'name' && folders === 'folders' && requests === 'requests') {
// Do nothing
}
} else if (
collections.info &&
collections.info.schema.includes("v2.1.0")
) {
collections = this.parsePostmanCollection(collections);
} else if (collections.info && collections.info.schema.includes('v2.1.0')) {
collections = this.parsePostmanCollection(collections)
} else {
return this.failedImport();
return this.failedImport()
}
this.$store.commit("postwoman/importCollections", collections);
this.fileImported();
};
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0]);
this.$store.commit('postwoman/importCollections', collections)
this.fileImported()
}
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0])
},
exportJSON() {
let text = this.collectionJson;
text = text.replace(/\n/g, "\r\n");
let text = this.collectionJson
text = text.replace(/\n/g, '\r\n')
let blob = new Blob([text], {
type: "text/json"
});
let anchor = document.createElement("a");
anchor.download = "postwoman-collection.json";
anchor.href = window.URL.createObjectURL(blob);
anchor.target = "_blank";
anchor.style.display = "none";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
type: 'text/json',
})
let anchor = document.createElement('a')
anchor.download = 'postwoman-collection.json'
anchor.href = window.URL.createObjectURL(blob)
anchor.target = '_blank'
anchor.style.display = 'none'
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
this.$toast.success(this.$t('download_started'), {
icon: 'done',
})
},
syncCollections() {
this.$store.commit("postwoman/replaceCollections", fb.currentCollections);
this.fileImported();
this.$store.commit('postwoman/replaceCollections', fb.currentCollections)
this.fileImported()
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
icon: "folder_shared"
});
this.$toast.info(this.$t('file_imported'), {
icon: 'folder_shared',
})
},
failedImport() {
this.$toast.error(this.$t("import_failed"), {
icon: "error"
});
this.$toast.error(this.$t('import_failed'), {
icon: 'error',
})
},
parsePostmanCollection(collection, folders = true) {
let postwomanCollection = folders
? [
{
name: "",
name: '',
folders: [],
requests: []
}
requests: [],
},
]
: {
name: "",
requests: []
};
name: '',
requests: [],
}
for (let collectionItem of collection.item) {
if (collectionItem.request) {
if (postwomanCollection[0]) {
postwomanCollection[0].name = collection.info
? collection.info.name
: "";
postwomanCollection[0].requests.push(
this.parsePostmanRequest(collectionItem)
);
postwomanCollection[0].name = collection.info ? collection.info.name : ''
postwomanCollection[0].requests.push(this.parsePostmanRequest(collectionItem))
} else {
postwomanCollection.name = collection.name ? collection.name : "";
postwomanCollection.requests.push(
this.parsePostmanRequest(collectionItem)
);
postwomanCollection.name = collection.name ? collection.name : ''
postwomanCollection.requests.push(this.parsePostmanRequest(collectionItem))
}
} else if (collectionItem.item) {
if (collectionItem.item[0]) {
postwomanCollection[0].folders.push(
this.parsePostmanCollection(collectionItem, false)
);
postwomanCollection[0].folders.push(this.parsePostmanCollection(collectionItem, false))
}
}
}
return postwomanCollection;
return postwomanCollection
},
parsePostmanRequest(requestObject) {
let pwRequest = {
url: "",
path: "",
method: "",
auth: "",
httpUser: "",
httpPassword: "",
passwordFieldType: "password",
bearerToken: "",
url: '',
path: '',
method: '',
auth: '',
httpUser: '',
httpPassword: '',
passwordFieldType: 'password',
bearerToken: '',
headers: [],
params: [],
bodyParams: [],
rawParams: "",
rawParams: '',
rawInput: false,
contentType: "",
requestType: "",
name: ""
};
contentType: '',
requestType: '',
name: '',
}
pwRequest.name = requestObject.name;
pwRequest.name = requestObject.name
let requestObjectUrl = requestObject.request.url.raw.match(
/^(.+:\/\/[^\/]+|{[^\/]+})(\/[^\?]+|).*$/
);
pwRequest.url = requestObjectUrl[1];
pwRequest.path = requestObjectUrl[2] ? requestObjectUrl[2] : "";
pwRequest.method = requestObject.request.method;
let itemAuth = requestObject.request.auth
? requestObject.request.auth
: "";
let authType = itemAuth ? itemAuth.type : "";
if (authType === "basic") {
pwRequest.auth = "Basic Auth";
)
pwRequest.url = requestObjectUrl[1]
pwRequest.path = requestObjectUrl[2] ? requestObjectUrl[2] : ''
pwRequest.method = requestObject.request.method
let itemAuth = requestObject.request.auth ? requestObject.request.auth : ''
let authType = itemAuth ? itemAuth.type : ''
if (authType === 'basic') {
pwRequest.auth = 'Basic Auth'
pwRequest.httpUser =
itemAuth.basic[0].key === "username"
? itemAuth.basic[0].value
: itemAuth.basic[1].value;
itemAuth.basic[0].key === 'username' ? itemAuth.basic[0].value : itemAuth.basic[1].value
pwRequest.httpPassword =
itemAuth.basic[0].key === "password"
? itemAuth.basic[0].value
: itemAuth.basic[1].value;
} else if (authType === "oauth2") {
pwRequest.auth = "OAuth 2.0";
itemAuth.basic[0].key === 'password' ? itemAuth.basic[0].value : itemAuth.basic[1].value
} else if (authType === 'oauth2') {
pwRequest.auth = 'OAuth 2.0'
pwRequest.bearerToken =
itemAuth.oauth2[0].key === "accessToken"
itemAuth.oauth2[0].key === 'accessToken'
? itemAuth.oauth2[0].value
: itemAuth.oauth2[1].value;
} else if (authType === "bearer") {
pwRequest.auth = "Bearer Token";
pwRequest.bearerToken = itemAuth.bearer[0].value;
: itemAuth.oauth2[1].value
} else if (authType === 'bearer') {
pwRequest.auth = 'Bearer Token'
pwRequest.bearerToken = itemAuth.bearer[0].value
}
let requestObjectHeaders = requestObject.request.header;
let requestObjectHeaders = requestObject.request.header
if (requestObjectHeaders) {
pwRequest.headers = requestObjectHeaders;
pwRequest.headers = requestObjectHeaders
for (let header of pwRequest.headers) {
delete header.name;
delete header.type;
delete header.name
delete header.type
}
}
let requestObjectParams = requestObject.request.url.query;
let requestObjectParams = requestObject.request.url.query
if (requestObjectParams) {
pwRequest.params = requestObjectParams;
pwRequest.params = requestObjectParams
for (let param of pwRequest.params) {
delete param.disabled;
delete param.disabled
}
}
if (requestObject.request.body) {
if (requestObject.request.body.mode === "urlencoded") {
let params = requestObject.request.body.urlencoded;
pwRequest.bodyParams = params ? params : [];
if (requestObject.request.body.mode === 'urlencoded') {
let params = requestObject.request.body.urlencoded
pwRequest.bodyParams = params ? params : []
for (let param of pwRequest.bodyParams) {
delete param.type;
delete param.type
}
} else if (requestObject.request.body.mode === "raw") {
pwRequest.rawInput = true;
pwRequest.rawParams = requestObject.request.body.raw;
} else if (requestObject.request.body.mode === 'raw') {
pwRequest.rawInput = true
pwRequest.rawParams = requestObject.request.body.raw
}
}
return pwRequest;
}
}
};
return pwRequest
},
},
}
</script>

View File

@@ -43,12 +43,12 @@ TODO:
<div>
<button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i>
<span>{{ $t("new") }}</span>
<span>{{ $t('new') }}</span>
</button>
</div>
<div>
<button class="icon" @click="displayModalImportExport(true)">
{{ $t("import_export") }}
{{ $t('import_export') }}
</button>
<!-- <a
href="https://github.com/liyasthomas/postwoman/wiki/Collections"
@@ -89,7 +89,7 @@ TODO:
<nuxt-link :to="localePath('doc')" :aria-label="$t('documentation')">
<button class="icon">
<i class="material-icons">books</i>
<span>{{ $t("generate_docs") }}</span>
<span>{{ $t('generate_docs') }}</span>
</button>
</nuxt-link>
</pw-section>
@@ -107,20 +107,20 @@ ul {
</style>
<script>
import collection from "./collection";
import { fb } from "../../functions/fb";
import collection from './collection'
import { fb } from '../../functions/fb'
export default {
components: {
collection,
"pw-section": () => import("../section"),
addCollection: () => import("./addCollection"),
addFolder: () => import("./addFolder"),
editCollection: () => import("./editCollection"),
editFolder: () => import("./editFolder"),
editRequest: () => import("./editRequest"),
importExportCollections: () => import("./importExportCollections"),
VirtualList: () => import("vue-virtual-scroll-list")
'pw-section': () => import('../section'),
addCollection: () => import('./addCollection'),
addFolder: () => import('./addFolder'),
editCollection: () => import('./editCollection'),
editFolder: () => import('./editFolder'),
editRequest: () => import('./editRequest'),
importExportCollections: () => import('./importExportCollections'),
VirtualList: () => import('vue-virtual-scroll-list'),
},
data() {
return {
@@ -135,100 +135,98 @@ export default {
editingFolder: undefined,
editingFolderIndex: undefined,
editingRequest: undefined,
editingRequestIndex: undefined
};
editingRequestIndex: undefined,
}
},
computed: {
collections() {
return this.$store.state.postwoman.collections;
}
return this.$store.state.postwoman.collections
},
},
async mounted() {
this._keyListener = function(e) {
if (e.key === "Escape") {
e.preventDefault();
this.showModalAdd = this.showModalEdit = this.showModalImportExport = this.showModalAddFolder = this.showModalEditFolder = this.showModalEditRequest = false;
if (e.key === 'Escape') {
e.preventDefault()
this.showModalAdd = this.showModalEdit = this.showModalImportExport = this.showModalAddFolder = this.showModalEditFolder = this.showModalEditRequest = false
}
};
document.addEventListener("keydown", this._keyListener.bind(this));
}
document.addEventListener('keydown', this._keyListener.bind(this))
},
methods: {
displayModalAdd(shouldDisplay) {
this.showModalAdd = shouldDisplay;
this.showModalAdd = shouldDisplay
},
displayModalEdit(shouldDisplay) {
this.showModalEdit = shouldDisplay;
this.showModalEdit = shouldDisplay
if (!shouldDisplay) this.resetSelectedData();
if (!shouldDisplay) this.resetSelectedData()
},
displayModalImportExport(shouldDisplay) {
this.showModalImportExport = shouldDisplay;
this.showModalImportExport = shouldDisplay
},
displayModalAddFolder(shouldDisplay) {
this.showModalAddFolder = shouldDisplay;
this.showModalAddFolder = shouldDisplay
if (!shouldDisplay) this.resetSelectedData();
if (!shouldDisplay) this.resetSelectedData()
},
displayModalEditFolder(shouldDisplay) {
this.showModalEditFolder = shouldDisplay;
this.showModalEditFolder = shouldDisplay
if (!shouldDisplay) this.resetSelectedData();
if (!shouldDisplay) this.resetSelectedData()
},
displayModalEditRequest(shouldDisplay) {
this.showModalEditRequest = shouldDisplay;
this.showModalEditRequest = shouldDisplay
if (!shouldDisplay) this.resetSelectedData();
if (!shouldDisplay) this.resetSelectedData()
},
editCollection(collection, collectionIndex) {
this.$data.editingCollection = collection;
this.$data.editingCollectionIndex = collectionIndex;
this.displayModalEdit(true);
this.syncCollections();
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.displayModalEdit(true)
this.syncCollections()
},
addFolder(collection, collectionIndex) {
this.$data.editingCollection = collection;
this.$data.editingCollectionIndex = collectionIndex;
this.displayModalAddFolder(true);
this.syncCollections();
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.displayModalAddFolder(true)
this.syncCollections()
},
editFolder(payload) {
const { collectionIndex, folder, folderIndex } = payload;
this.$data.editingCollection = collection;
this.$data.editingCollectionIndex = collectionIndex;
this.$data.editingFolder = folder;
this.$data.editingFolderIndex = folderIndex;
this.displayModalEditFolder(true);
this.syncCollections();
const { collectionIndex, folder, folderIndex } = payload
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.$data.editingFolder = folder
this.$data.editingFolderIndex = folderIndex
this.displayModalEditFolder(true)
this.syncCollections()
},
editRequest(payload) {
const { request, collectionIndex, folderIndex, requestIndex } = payload;
this.$data.editingCollectionIndex = collectionIndex;
this.$data.editingFolderIndex = folderIndex;
this.$data.editingRequest = request;
this.$data.editingRequestIndex = requestIndex;
this.displayModalEditRequest(true);
this.syncCollections();
const { request, collectionIndex, folderIndex, requestIndex } = payload
this.$data.editingCollectionIndex = collectionIndex
this.$data.editingFolderIndex = folderIndex
this.$data.editingRequest = request
this.$data.editingRequestIndex = requestIndex
this.displayModalEditRequest(true)
this.syncCollections()
},
resetSelectedData() {
this.$data.editingCollection = undefined;
this.$data.editingCollectionIndex = undefined;
this.$data.editingFolder = undefined;
this.$data.editingFolderIndex = undefined;
this.$data.editingRequest = undefined;
this.$data.editingRequestIndex = undefined;
this.$data.editingCollection = undefined
this.$data.editingCollectionIndex = undefined
this.$data.editingFolder = undefined
this.$data.editingFolderIndex = undefined
this.$data.editingRequest = undefined
this.$data.editingRequestIndex = undefined
},
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
fb.writeCollections(JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)))
}
}
}
},
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
document.removeEventListener('keydown', this._keyListener)
},
}
</script>

View File

@@ -1,11 +1,7 @@
<template>
<div class="flex-wrap">
<div>
<button
class="icon"
@click="selectRequest()"
v-tooltip="$t('use_request')"
>
<button class="icon" @click="selectRequest()" v-tooltip="$t('use_request')">
<i class="material-icons">insert_drive_file</i>
<span>{{ request.name }}</span>
</button>
@@ -18,13 +14,13 @@
<div>
<button class="icon" @click="$emit('edit-request')" v-close-popover>
<i class="material-icons">edit</i>
<span>{{ $t("edit") }}</span>
<span>{{ $t('edit') }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeRequest" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
<span>{{ $t('delete') }}</span>
</button>
</div>
</template>
@@ -51,20 +47,20 @@ export default {
request: Object,
collectionIndex: Number,
folderIndex: Number,
requestIndex: Number
requestIndex: Number,
},
methods: {
selectRequest() {
this.$store.commit("postwoman/selectRequest", { request: this.request });
this.$store.commit('postwoman/selectRequest', { request: this.request })
},
removeRequest() {
if (!confirm("Are you sure you want to remove this request?")) return;
this.$store.commit("postwoman/removeRequest", {
if (!confirm('Are you sure you want to remove this request?')) return
this.$store.commit('postwoman/removeRequest', {
collectionIndex: this.collectionIndex,
folderIndex: this.folderIndex,
requestIndex: this.requestIndex
});
}
}
};
requestIndex: this.requestIndex,
})
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("save_request_as") }}</h3>
<h3 class="title">{{ $t('save_request_as') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -17,7 +17,7 @@
<div slot="body">
<ul>
<li>
<label for="selectLabel">{{ $t("label") }}</label>
<label for="selectLabel">{{ $t('label') }}</label>
<input
type="text"
id="selectLabel"
@@ -25,24 +25,14 @@
:placeholder="defaultRequestName"
@keyup.enter="saveRequestAs"
/>
<label for="selectCollection">{{ $t("collection") }}</label>
<label for="selectCollection">{{ $t('collection') }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectCollection"
v-model="requestData.collectionIndex"
>
<select type="text" id="selectCollection" v-model="requestData.collectionIndex">
<option :key="undefined" :value="undefined" hidden disabled selected>{{
$t('select_collection')
}}</option>
<option
:key="undefined"
:value="undefined"
hidden
disabled
selected
>{{ $t("select_collection") }}</option
>
<option
v-for="(collection, index) in $store.state.postwoman
.collections"
v-for="(collection, index) in $store.state.postwoman.collections"
:key="index"
:value="index"
>
@@ -50,36 +40,20 @@
</option>
</select>
</span>
<label for="selectFolder">{{ $t("folder") }}</label>
<label for="selectFolder">{{ $t('folder') }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectFolder"
v-model="requestData.folderIndex"
>
<select type="text" id="selectFolder" v-model="requestData.folderIndex">
<option :key="undefined" :value="undefined">/</option>
<option
v-for="(folder, index) in folders"
:key="index"
:value="index"
>
<option v-for="(folder, index) in folders" :key="index" :value="index">
{{ folder.name }}
</option>
</select>
</span>
<label for="selectRequest">{{ $t("request") }}</label>
<label for="selectRequest">{{ $t('request') }}</label>
<span class="select-wrapper">
<select
type="text"
id="selectRequest"
v-model="requestData.requestIndex"
>
<select type="text" id="selectRequest" v-model="requestData.requestIndex">
<option :key="undefined" :value="undefined">/</option>
<option
v-for="(folder, index) in requests"
:key="index"
:value="index"
>
<option v-for="(folder, index) in requests" :key="index" :value="index">
{{ folder.name }}
</option>
</select>
@@ -92,10 +66,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="saveRequestAs">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -104,123 +78,113 @@
</template>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
props: {
show: Boolean,
editingRequest: Object
editingRequest: Object,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
defaultRequestName: "My Request",
defaultRequestName: 'My Request',
requestData: {
name: undefined,
collectionIndex: undefined,
folderIndex: undefined,
requestIndex: undefined
}
};
requestIndex: undefined,
},
}
},
watch: {
"requestData.collectionIndex": function resetFolderAndRequestIndex() {
'requestData.collectionIndex': function resetFolderAndRequestIndex() {
// if user choosen some folder, than selected other collection, which doesn't have any folders
// than `requestUpdateData.folderIndex` won't be reseted
this.$data.requestData.folderIndex = undefined;
this.$data.requestData.requestIndex = undefined;
this.$data.requestData.folderIndex = undefined
this.$data.requestData.requestIndex = undefined
},
'requestData.folderIndex': function resetRequestIndex() {
this.$data.requestData.requestIndex = undefined
},
"requestData.folderIndex": function resetRequestIndex() {
this.$data.requestData.requestIndex = undefined;
}
},
computed: {
folders() {
const userSelectedAnyCollection =
this.$data.requestData.collectionIndex !== undefined;
if (!userSelectedAnyCollection) return [];
const userSelectedAnyCollection = this.$data.requestData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
const noCollectionAvailable =
this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
] !== undefined;
if (!noCollectionAvailable) return [];
this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex] !==
undefined
if (!noCollectionAvailable) return []
return this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
].folders;
return this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex].folders
},
requests() {
const userSelectedAnyCollection =
this.$data.requestData.collectionIndex !== undefined;
if (!userSelectedAnyCollection) return [];
const userSelectedAnyCollection = this.$data.requestData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
const userSelectedAnyFolder =
this.$data.requestData.folderIndex !== undefined;
const userSelectedAnyFolder = this.$data.requestData.folderIndex !== undefined
if (userSelectedAnyFolder) {
const collection = this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
];
const folder = collection.folders[this.$data.requestData.folderIndex];
const requests = folder.requests;
return requests;
]
const folder = collection.folders[this.$data.requestData.folderIndex]
const requests = folder.requests
return requests
} else {
const collection = this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
];
]
const noCollectionAvailable =
this.$store.state.postwoman.collections[
this.$data.requestData.collectionIndex
] !== undefined;
if (!noCollectionAvailable) return [];
this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex] !==
undefined
if (!noCollectionAvailable) return []
const requests = collection.requests;
return requests;
const requests = collection.requests
return requests
}
}
},
},
methods: {
syncCollections() {
if (fb.currentUser !== null) {
if (fb.currentSettings[0].value) {
fb.writeCollections(
JSON.parse(JSON.stringify(this.$store.state.postwoman.collections))
);
fb.writeCollections(JSON.parse(JSON.stringify(this.$store.state.postwoman.collections)))
}
}
},
saveRequestAs() {
const userDidntSpecifyCollection =
this.$data.requestData.collectionIndex === undefined;
const userDidntSpecifyCollection = this.$data.requestData.collectionIndex === undefined
if (userDidntSpecifyCollection) {
this.$toast.error(this.$t("select_collection"), {
icon: "error"
});
return;
this.$toast.error(this.$t('select_collection'), {
icon: 'error',
})
return
}
const requestUpdated = {
...this.$props.editingRequest,
name: this.$data.requestData.name || this.$data.defaultRequestName,
collection: this.$data.requestData.collectionIndex
};
collection: this.$data.requestData.collectionIndex,
}
this.$store.commit("postwoman/saveRequestAs", {
this.$store.commit('postwoman/saveRequestAs', {
request: requestUpdated,
collectionIndex: this.$data.requestData.collectionIndex,
folderIndex: this.$data.requestData.folderIndex,
requestIndex: this.$data.requestData.requestIndex
});
requestIndex: this.$data.requestData.requestIndex,
})
this.hideModal();
this.syncCollections();
this.hideModal()
this.syncCollections()
},
hideModal() {
this.$emit("hide-modal");
this.$emit("hide-model"); // for backward compatibility // TODO: use fixed event
}
}
};
this.$emit('hide-modal')
this.$emit('hide-model') // for backward compatibility // TODO: use fixed event
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("new_environment") }}</h3>
<h3 class="title">{{ $t('new_environment') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -31,10 +31,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="addNewEnvironment">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -43,52 +43,50 @@
</template>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
props: {
show: Boolean
show: Boolean,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
methods: {
syncEnvironments() {
if (fb.currentUser !== null) {
if (fb.currentSettings[1].value) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
);
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
}
}
},
addNewEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"));
return;
this.$toast.info(this.$t('invalid_environment_name'))
return
}
let newEnvironment = [
{
name: this.$data.name,
variables: []
}
];
this.$store.commit("postwoman/importAddEnvironments", {
variables: [],
},
]
this.$store.commit('postwoman/importAddEnvironments', {
environments: newEnvironment,
confirmation: "Environment added"
});
this.$emit("hide-modal");
this.syncEnvironments();
confirmation: 'Environment added',
})
this.$emit('hide-modal')
this.syncEnvironments()
},
hideModal() {
this.$data.name = undefined;
this.$emit("hide-modal");
}
}
};
this.$data.name = undefined
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -4,7 +4,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("edit_environment") }}</h3>
<h3 class="title">{{ $t('edit_environment') }}</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
@@ -28,13 +28,9 @@
<ul>
<li>
<div class="flex-wrap">
<label for="variableList">{{ $t("env_variable_list") }}</label>
<label for="variableList">{{ $t('env_variable_list') }}</label>
<div>
<button
class="icon"
@click="clearContent($event)"
v-tooltip.bottom="$t('clear')"
>
<button class="icon" @click="clearContent($event)" v-tooltip.bottom="$t('clear')">
<i class="material-icons">clear_all</i>
</button>
</div>
@@ -49,10 +45,7 @@
></textarea>
</li>
</ul>
<ul
v-for="(variable, index) in this.editingEnvCopy.variables"
:key="index"
>
<ul v-for="(variable, index) in this.editingEnvCopy.variables" :key="index">
<li>
<input
:placeholder="$t('parameter_count', { count: index + 1 })"
@@ -61,7 +54,7 @@
@change="
$store.commit('postwoman/setVariableKey', {
index,
value: $event.target.value
value: $event.target.value,
})
"
autofocus
@@ -72,14 +65,12 @@
:placeholder="$t('value_count', { count: index + 1 })"
:name="'value' + index"
:value="
typeof variable.value === 'string'
? variable.value
: JSON.stringify(variable.value)
typeof variable.value === 'string' ? variable.value : JSON.stringify(variable.value)
"
@change="
$store.commit('postwoman/setVariableValue', {
index,
value: $event.target.value
value: $event.target.value,
})
"
/>
@@ -101,7 +92,7 @@
<li>
<button class="icon" @click="addEnvironmentVariable">
<i class="material-icons">add</i>
<span>{{ $t("add_new") }}</span>
<span>{{ $t('add_new') }}</span>
</button>
</li>
</ul>
@@ -111,10 +102,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button class="icon primary" @click="saveEnvironment">
{{ $t("save") }}
{{ $t('save') }}
</button>
</span>
</div>
@@ -123,99 +114,94 @@
</template>
<script>
import textareaAutoHeight from "../../directives/textareaAutoHeight";
import textareaAutoHeight from '../../directives/textareaAutoHeight'
export default {
directives: {
textareaAutoHeight
textareaAutoHeight,
},
props: {
show: Boolean,
editingEnvironment: Object,
editingEnvironmentIndex: Number
editingEnvironmentIndex: Number,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
data() {
return {
name: undefined
};
name: undefined,
}
},
watch: {
editingEnvironment: function(update) {
this.name = this.$props.editingEnvironment && this.$props.editingEnvironment.name
? this.$props.editingEnvironment.name
: undefined
this.$store.commit(
"postwoman/setEditingEnvironment",
this.$props.editingEnvironment
);
}
this.name =
this.$props.editingEnvironment && this.$props.editingEnvironment.name
? this.$props.editingEnvironment.name
: undefined
this.$store.commit('postwoman/setEditingEnvironment', this.$props.editingEnvironment)
},
},
computed: {
editingEnvCopy() {
return this.$store.state.postwoman.editingEnvironment;
return this.$store.state.postwoman.editingEnvironment
},
variableString() {
const result = this.editingEnvCopy.variables;
return result === "" ? "" : JSON.stringify(result);
}
const result = this.editingEnvCopy.variables
return result === '' ? '' : JSON.stringify(result)
},
},
methods: {
clearContent(e) {
this.$store.commit("postwoman/removeVariables", []);
e.target.innerHTML = this.doneButton;
this.$toast.info(this.$t("cleared"), {
icon: "clear_all"
});
setTimeout(
() => (e.target.innerHTML = '<i class="material-icons">clear_all</i>'),
1000
);
this.$store.commit('postwoman/removeVariables', [])
e.target.innerHTML = this.doneButton
this.$toast.info(this.$t('cleared'), {
icon: 'clear_all',
})
setTimeout(() => (e.target.innerHTML = '<i class="material-icons">clear_all</i>'), 1000)
},
addEnvironmentVariable() {
let value = { key: "", value: "" };
this.$store.commit("postwoman/addVariable", value);
let value = { key: '', value: '' }
this.$store.commit('postwoman/addVariable', value)
},
removeEnvironmentVariable(index) {
let variableIndex = index;
const oldVariables = this.editingEnvCopy.variables.slice();
let variableIndex = index
const oldVariables = this.editingEnvCopy.variables.slice()
const newVariables = this.editingEnvCopy.variables.filter(
(variable, index) => variableIndex !== index
);
)
this.$store.commit("postwoman/removeVariable", newVariables);
this.$toast.error(this.$t("deleted"), {
icon: "delete",
this.$store.commit('postwoman/removeVariable', newVariables)
this.$toast.error(this.$t('deleted'), {
icon: 'delete',
action: {
text: this.$t("undo"),
text: this.$t('undo'),
onClick: (e, toastObject) => {
this.$store.commit("postwoman/removeVariable", oldVariables);
toastObject.remove();
}
}
});
this.$store.commit('postwoman/removeVariable', oldVariables)
toastObject.remove()
},
},
})
},
saveEnvironment() {
if (!this.$data.name) {
this.$toast.info(this.$t("invalid_environment_name"));
return;
this.$toast.info(this.$t('invalid_environment_name'))
return
}
const environmentUpdated = {
...this.editingEnvCopy,
name: this.$data.name
};
this.$store.commit("postwoman/saveEnvironment", {
name: this.$data.name,
}
this.$store.commit('postwoman/saveEnvironment', {
environment: environmentUpdated,
environmentIndex: this.$props.editingEnvironmentIndex
});
this.$emit("hide-modal");
environmentIndex: this.$props.editingEnvironmentIndex,
})
this.$emit('hide-modal')
},
hideModal() {
this.$data.name = undefined;
this.$emit("hide-modal");
}
}
};
this.$data.name = undefined
this.$emit('hide-modal')
},
},
}
</script>

View File

@@ -1,11 +1,7 @@
<template>
<div class="flex-wrap">
<div>
<button
class="icon"
@click="$emit('select-environment')"
v-tooltip="$t('use_environment')"
>
<button class="icon" @click="$emit('select-environment')" v-tooltip="$t('use_environment')">
<i class="material-icons">insert_drive_file</i>
<span>{{ environment.name }}</span>
</button>
@@ -16,19 +12,15 @@
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="$emit('edit-environment')"
v-close-popover
>
<button class="icon" @click="$emit('edit-environment')" v-close-popover>
<i class="material-icons">create</i>
<span>{{ $t("edit") }}</span>
<span>{{ $t('edit') }}</span>
</button>
</div>
<div>
<button class="icon" @click="removeEnvironment" v-close-popover>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
<span>{{ $t('delete') }}</span>
</button>
</div>
</template>
@@ -53,13 +45,13 @@ ul li {
export default {
props: {
environment: Object,
environmentIndex: Number
environmentIndex: Number,
},
methods: {
removeEnvironment() {
if (!confirm("Are you sure you want to remove this environment?")) return;
this.$store.commit("postwoman/removeEnvironment", this.environmentIndex);
}
}
};
if (!confirm('Are you sure you want to remove this environment?')) return
this.$store.commit('postwoman/removeEnvironment', this.environmentIndex)
},
},
}
</script>

View File

@@ -14,18 +14,12 @@
<div class="flex-wrap">
<span
v-tooltip="{
content: !fb.currentUser
? $t('login_first')
: $t('replace_current')
content: !fb.currentUser ? $t('login_first') : $t('replace_current'),
}"
>
<button
:disabled="!fb.currentUser"
class="icon"
@click="syncEnvironments"
>
<button :disabled="!fb.currentUser" class="icon" @click="syncEnvironments">
<i class="material-icons">folder_shared</i>
<span>{{ $t("import_from_sync") }}</span>
<span>{{ $t('import_from_sync') }}</span>
</button>
</span>
<button
@@ -34,7 +28,7 @@
v-tooltip="$t('replace_current')"
>
<i class="material-icons">create_new_folder</i>
<span>{{ $t("replace_json") }}</span>
<span>{{ $t('replace_json') }}</span>
<input
type="file"
@change="replaceWithJSON"
@@ -49,7 +43,7 @@
v-tooltip="$t('preserve_current')"
>
<i class="material-icons">folder_special</i>
<span>{{ $t("import_json") }}</span>
<span>{{ $t('import_json') }}</span>
<input
type="file"
@change="importFromJSON"
@@ -70,14 +64,10 @@
<span></span>
<span>
<button class="icon" @click="hideModal">
{{ $t("cancel") }}
{{ $t('cancel') }}
</button>
<button
class="icon primary"
@click="exportJSON"
v-tooltip="$t('download_file')"
>
{{ $t("export") }}
<button class="icon primary" @click="exportJSON" v-tooltip="$t('download_file')">
{{ $t('export') }}
</button>
</span>
</div>
@@ -86,88 +76,85 @@
</template>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
data() {
return {
fb
};
fb,
}
},
props: {
show: Boolean
show: Boolean,
},
components: {
modal: () => import("../../components/modal")
modal: () => import('../../components/modal'),
},
computed: {
environmentJson() {
return JSON.stringify(this.$store.state.postwoman.environments, null, 2);
}
return JSON.stringify(this.$store.state.postwoman.environments, null, 2)
},
},
methods: {
hideModal() {
this.$emit("hide-modal");
this.$emit('hide-modal')
},
openDialogChooseFileToReplaceWith() {
this.$refs.inputChooseFileToReplaceWith.click();
this.$refs.inputChooseFileToReplaceWith.click()
},
openDialogChooseFileToImportFrom() {
this.$refs.inputChooseFileToImportFrom.click();
this.$refs.inputChooseFileToImportFrom.click()
},
replaceWithJSON() {
let reader = new FileReader();
let reader = new FileReader()
reader.onload = event => {
let content = event.target.result;
let environments = JSON.parse(content);
this.$store.commit("postwoman/replaceEnvironments", environments);
};
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0]);
this.fileImported();
let content = event.target.result
let environments = JSON.parse(content)
this.$store.commit('postwoman/replaceEnvironments', environments)
}
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0])
this.fileImported()
},
importFromJSON() {
let reader = new FileReader();
let reader = new FileReader()
reader.onload = event => {
let content = event.target.result;
let environments = JSON.parse(content);
let confirmation = this.$t("file_imported")
this.$store.commit("postwoman/importAddEnvironments", {
let content = event.target.result
let environments = JSON.parse(content)
let confirmation = this.$t('file_imported')
this.$store.commit('postwoman/importAddEnvironments', {
environments,
confirmation
});
};
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0]);
confirmation,
})
}
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0])
},
exportJSON() {
let text = this.environmentJson;
text = text.replace(/\n/g, "\r\n");
let text = this.environmentJson
text = text.replace(/\n/g, '\r\n')
let blob = new Blob([text], {
type: "text/json"
});
let anchor = document.createElement("a");
anchor.download = "postwoman-environment.json";
anchor.href = window.URL.createObjectURL(blob);
anchor.target = "_blank";
anchor.style.display = "none";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
type: 'text/json',
})
let anchor = document.createElement('a')
anchor.download = 'postwoman-environment.json'
anchor.href = window.URL.createObjectURL(blob)
anchor.target = '_blank'
anchor.style.display = 'none'
document.body.appendChild(anchor)
anchor.click()
document.body.removeChild(anchor)
this.$toast.success(this.$t('download_started'), {
icon: 'done',
})
},
syncEnvironments() {
this.$store.commit(
"postwoman/replaceEnvironments",
fb.currentEnvironments
);
this.fileImported();
this.$store.commit('postwoman/replaceEnvironments', fb.currentEnvironments)
this.fileImported()
},
fileImported() {
this.$toast.info(this.$t("file_imported"), {
icon: "folder_shared"
});
}
}
};
this.$toast.info(this.$t('file_imported'), {
icon: 'folder_shared',
})
},
},
}
</script>

View File

@@ -1,10 +1,5 @@
<template>
<pw-section
class="green"
icon="history"
:label="$t('environment')"
ref="environment"
>
<pw-section class="green" icon="history" :label="$t('environment')" ref="environment">
<addEnvironment :show="showModalAdd" @hide-modal="displayModalAdd(false)" />
<editEnvironment
:show="showModalEdit"
@@ -20,12 +15,12 @@
<div>
<button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i>
<span>{{ $t("new") }}</span>
<span>{{ $t('new') }}</span>
</button>
</div>
<div>
<button class="icon" @click="displayModalImportExport(true)">
{{ $t("import_export") }}
{{ $t('import_export') }}
</button>
</div>
</div>
@@ -39,10 +34,7 @@
:remain="Math.min(5, environments.length)"
>
<ul>
<li
v-for="(environment, index) in environments"
:key="environment.name"
>
<li v-for="(environment, index) in environments" :key="environment.name">
<environment
:environmentIndex="index"
:environment="environment"
@@ -70,20 +62,20 @@ ul {
</style>
<script>
import environment from "./environment";
import { fb } from "../../functions/fb";
import environment from './environment'
import { fb } from '../../functions/fb'
const updateOnLocalStorage = (propertyName, property) =>
window.localStorage.setItem(propertyName, JSON.stringify(property));
window.localStorage.setItem(propertyName, JSON.stringify(property))
export default {
components: {
environment,
"pw-section": () => import("../section"),
addEnvironment: () => import("./addEnvironment"),
editEnvironment: () => import("./editEnvironment"),
importExportEnvironment: () => import("./importExportEnvironment"),
VirtualList: () => import("vue-virtual-scroll-list")
'pw-section': () => import('../section'),
addEnvironment: () => import('./addEnvironment'),
editEnvironment: () => import('./editEnvironment'),
importExportEnvironment: () => import('./importExportEnvironment'),
VirtualList: () => import('vue-virtual-scroll-list'),
},
data() {
return {
@@ -91,57 +83,55 @@ export default {
showModalAdd: false,
showModalEdit: false,
editingEnvironment: undefined,
editingEnvironmentIndex: undefined
};
editingEnvironmentIndex: undefined,
}
},
computed: {
environments() {
return this.$store.state.postwoman.environments;
}
return this.$store.state.postwoman.environments
},
},
async mounted() {
this._keyListener = function(e) {
if (e.key === "Escape") {
e.preventDefault();
this.showModalImportExport = false;
if (e.key === 'Escape') {
e.preventDefault()
this.showModalImportExport = false
}
};
document.addEventListener("keydown", this._keyListener.bind(this));
}
document.addEventListener('keydown', this._keyListener.bind(this))
},
methods: {
displayModalAdd(shouldDisplay) {
this.showModalAdd = shouldDisplay;
this.showModalAdd = shouldDisplay
},
displayModalEdit(shouldDisplay) {
this.showModalEdit = shouldDisplay;
this.showModalEdit = shouldDisplay
if (!shouldDisplay) this.resetSelectedData();
if (!shouldDisplay) this.resetSelectedData()
},
displayModalImportExport(shouldDisplay) {
this.showModalImportExport = shouldDisplay;
this.showModalImportExport = shouldDisplay
},
editEnvironment(environment, environmentIndex) {
this.$data.editingEnvironment = environment;
this.$data.editingEnvironmentIndex = environmentIndex;
this.displayModalEdit(true);
this.syncEnvironments;
this.$data.editingEnvironment = environment
this.$data.editingEnvironmentIndex = environmentIndex
this.displayModalEdit(true)
this.syncEnvironments
},
resetSelectedData() {
this.$data.editingEnvironment = undefined;
this.$data.editingEnvironmentIndex = undefined;
this.$data.editingEnvironment = undefined
this.$data.editingEnvironmentIndex = undefined
},
syncEnvironments() {
if (fb.currentUser !== null) {
if (fb.currentSettings[1].value) {
fb.writeEnvironments(
JSON.parse(JSON.stringify(this.$store.state.postwoman.environments))
);
fb.writeEnvironments(JSON.parse(JSON.stringify(this.$store.state.postwoman.environments)))
}
}
}
},
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
document.removeEventListener('keydown', this._keyListener)
},
}
</script>

View File

@@ -10,7 +10,7 @@
<div class="show-on-large-screen">
<li class="info">
<label>
{{ feed.label || $t("no_label") }}
{{ feed.label || $t('no_label') }}
</label>
</li>
<button class="icon" @click="deleteFeed(feed)">
@@ -19,14 +19,14 @@
</div>
<div class="show-on-large-screen">
<li class="info clamb-3">
<label>{{ feed.message || $t("empty") }}</label>
<label>{{ feed.message || $t('empty') }}</label>
</li>
</div>
</ul>
</virtual-list>
<ul v-else>
<li>
<label class="info">{{ $t("empty") }}</label>
<label class="info">{{ $t('empty') }}</label>
</li>
</ul>
</template>
@@ -55,24 +55,24 @@ ol {
</style>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
components: {
VirtualList: () => import("vue-virtual-scroll-list")
VirtualList: () => import('vue-virtual-scroll-list'),
},
data() {
return {
fb
};
fb,
}
},
methods: {
deleteFeed(feed) {
fb.deleteFeed(feed.id);
this.$toast.error(this.$t("deleted"), {
icon: "delete"
});
}
}
};
fb.deleteFeed(feed.id)
this.$toast.error(this.$t('deleted'), {
icon: 'delete',
})
},
},
}
</script>

View File

@@ -46,24 +46,24 @@ ol {
</style>
<script>
import { fb } from "../../functions/fb";
import { fb } from '../../functions/fb'
export default {
data() {
return {
message: null,
label: null
};
label: null,
}
},
methods: {
formPost() {
if (!(this.message || this.label)) {
return;
return
}
fb.writeFeeds(this.message, this.label);
this.message = null;
this.label = null;
}
}
};
fb.writeFeeds(this.message, this.label)
this.message = null
this.label = null
},
},
}
</script>

View File

@@ -41,75 +41,75 @@
</template>
<script>
import firebase from "firebase/app";
import { fb } from "../../functions/fb";
import firebase from 'firebase/app'
import { fb } from '../../functions/fb'
export default {
data() {
return {
fb
};
fb,
}
},
methods: {
signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
const provider = new firebase.auth.GoogleAuthProvider()
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
this.$toast.info(`${this.$t('turn_on')} ${this.$t('sync')}`, {
icon: 'sync',
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
text: this.$t('yes'),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", false);
fb.writeSettings("syncCollections", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
fb.writeSettings('syncHistory', false)
fb.writeSettings('syncCollections', true)
this.$router.push({ path: '/settings' })
toastObject.remove()
},
},
})
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
icon: 'error',
})
})
},
signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider();
const provider = new firebase.auth.GithubAuthProvider()
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
this.$toast.info(`${this.$t('turn_on')} ${this.$t('sync')}`, {
icon: 'sync',
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
text: this.$t('yes'),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", false);
fb.writeSettings("syncCollections", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
fb.writeSettings('syncHistory', false)
fb.writeSettings('syncCollections', true)
this.$router.push({ path: '/settings' })
toastObject.remove()
},
},
})
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
}
}
};
icon: 'error',
})
})
},
},
}
</script>

View File

@@ -11,28 +11,28 @@
<style scoped lang="scss"></style>
<script>
import typelink from "./typelink";
import typelink from './typelink'
export default {
components: {
typelink: typelink
typelink: typelink,
},
props: {
gqlArg: Object
gqlArg: Object,
},
computed: {
argName() {
return this.gqlArg.name;
return this.gqlArg.name
},
argType() {
return this.gqlArg.type;
}
return this.gqlArg.type
},
},
methods: {
jumpCallback(typeName) {}
}
};
jumpCallback(typeName) {},
},
}
</script>

View File

@@ -6,10 +6,7 @@
(
<span v-for="(field, index) in fieldArgs" :key="index">
{{ field.name }}:
<typelink
:gqlType="field.type"
:jumpTypeCallback="jumpTypeCallback"
/>
<typelink :gqlType="field.type" :jumpTypeCallback="jumpTypeCallback" />
<span v-if="index !== fieldArgs.length - 1">
,
</span>
@@ -23,7 +20,7 @@
</div>
<div class="field-deprecated" v-if="gqlField.isDeprecated">
{{ $t("deprecated") }}
{{ $t('deprecated') }}
</div>
</div>
</template>
@@ -53,16 +50,16 @@
</style>
<script>
import typelink from "./typelink";
import typelink from './typelink'
export default {
components: {
typelink: typelink
typelink: typelink,
},
props: {
gqlField: Object,
jumpTypeCallback: Function
jumpTypeCallback: Function,
},
computed: {
@@ -71,23 +68,21 @@ export default {
return (
acc +
`${arg.name}: ${arg.type.toString()}${
index !== this.gqlField.args.length - 1 ? ", " : ""
index !== this.gqlField.args.length - 1 ? ', ' : ''
}`
);
}, "");
const argsString = args.length > 0 ? `(${args})` : "";
return `${
this.gqlField.name
}${argsString}: ${this.gqlField.type.toString()}`;
)
}, '')
const argsString = args.length > 0 ? `(${args})` : ''
return `${this.gqlField.name}${argsString}: ${this.gqlField.type.toString()}`
},
fieldName() {
return this.gqlField.name;
return this.gqlField.name
},
fieldArgs() {
return this.gqlField.args || [];
}
}
};
return this.gqlField.args || []
},
},
}
</script>

View File

@@ -3,86 +3,79 @@
</template>
<script>
const DEFAULT_THEME = "twilight";
const DEFAULT_THEME = 'twilight'
import ace from "ace-builds";
import * as gql from "graphql";
import { getAutocompleteSuggestions } from "graphql-language-service-interface";
import "ace-builds/webpack-resolver";
import "ace-builds/src-noconflict/ext-language_tools";
import debounce from "../../functions/utils/debounce";
import ace from 'ace-builds'
import * as gql from 'graphql'
import { getAutocompleteSuggestions } from 'graphql-language-service-interface'
import 'ace-builds/webpack-resolver'
import 'ace-builds/src-noconflict/ext-language_tools'
import debounce from '../../functions/utils/debounce'
export default {
props: {
value: {
type: String,
default: ""
default: '',
},
theme: {
type: String,
required: false
required: false,
},
lang: {
type: String,
default: "json"
default: 'json',
},
options: {
type: Object,
default: {}
}
default: {},
},
},
data() {
return {
editor: null,
cacheValue: "",
validationSchema: null
};
cacheValue: '',
validationSchema: null,
}
},
watch: {
value(value) {
if (value !== this.cacheValue) {
this.editor.session.setValue(value, 1);
this.cacheValue = value;
this.editor.session.setValue(value, 1)
this.cacheValue = value
}
},
theme() {
this.editor.setTheme(`ace/theme/${this.defineTheme()}`);
this.editor.setTheme(`ace/theme/${this.defineTheme()}`)
},
lang(value) {
this.editor.getSession().setMode(`ace/mode/${value}`);
this.editor.getSession().setMode(`ace/mode/${value}`)
},
options(value) {
this.editor.setOptions(value);
}
this.editor.setOptions(value)
},
},
mounted() {
let langTools = ace.require("ace/ext/language_tools");
let langTools = ace.require('ace/ext/language_tools')
const editor = ace.edit(this.$refs.editor, {
theme: `ace/theme/${this.defineTheme()}`,
mode: `ace/mode/${this.lang}`,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
...this.options
});
...this.options,
})
const completer = {
getCompletions: (
editor,
_session,
{ row, column },
_prefix,
callback
) => {
getCompletions: (editor, _session, { row, column }, _prefix, callback) => {
if (this.validationSchema) {
const completions = getAutocompleteSuggestions(
this.validationSchema,
editor.getValue(),
{ line: row, character: column }
);
const completions = getAutocompleteSuggestions(this.validationSchema, editor.getValue(), {
line: row,
character: column,
})
callback(
null,
@@ -90,64 +83,60 @@ export default {
name: label,
value: label,
score: 1.0,
meta: detail
meta: detail,
}))
);
)
} else {
callback(null, []);
callback(null, [])
}
}
};
},
}
langTools.setCompleters([completer]);
langTools.setCompleters([completer])
if (this.value) editor.setValue(this.value, 1);
if (this.value) editor.setValue(this.value, 1)
this.editor = editor;
this.cacheValue = this.value;
this.editor = editor
this.cacheValue = this.value
editor.on("change", () => {
const content = editor.getValue();
this.$emit("input", content);
this.parseContents(content);
this.cacheValue = content;
});
editor.on('change', () => {
const content = editor.getValue()
this.$emit('input', content)
this.parseContents(content)
this.cacheValue = content
})
this.parseContents(this.value);
this.parseContents(this.value)
},
methods: {
defineTheme() {
if (this.theme) {
return this.theme;
return this.theme
} else {
return (
this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
);
return this.$store.state.postwoman.settings.THEME_ACE_EDITOR || DEFAULT_THEME
}
},
setValidationSchema(schema) {
this.validationSchema = schema;
this.parseContents(this.cacheValue);
this.validationSchema = schema
this.parseContents(this.cacheValue)
},
parseContents: debounce(function(content) {
if (content !== "") {
if (content !== '') {
try {
const doc = gql.parse(content);
const doc = gql.parse(content)
if (this.validationSchema) {
this.editor.session.setAnnotations(
gql
.validate(this.validationSchema, doc)
.map(({ locations, message }) => ({
row: locations[0].line - 1,
column: locations[0].column - 1,
text: message,
type: "error"
}))
);
gql.validate(this.validationSchema, doc).map(({ locations, message }) => ({
row: locations[0].line - 1,
column: locations[0].column - 1,
text: message,
type: 'error',
}))
)
}
} catch (e) {
this.editor.session.setAnnotations([
@@ -155,19 +144,19 @@ export default {
row: e.locations[0].line - 1,
column: e.locations[0].column - 1,
text: e.message,
type: "error"
}
]);
type: 'error',
},
])
}
} else {
this.editor.session.setAnnotations([]);
this.editor.session.setAnnotations([])
}
}, 2000)
}, 2000),
},
beforeDestroy() {
this.editor.destroy();
this.editor.container.remove();
}
};
this.editor.destroy()
this.editor.container.remove()
},
}
</script>

View File

@@ -6,7 +6,7 @@
</div>
<div v-if="gqlType.getFields">
<h5>{{ $t("fields") }}</h5>
<h5>{{ $t('fields') }}</h5>
<div v-for="field in gqlType.getFields()" :key="field.name">
<gql-field :gqlField="field" :jumpTypeCallback="jumpTypeCallback" />
</div>
@@ -33,12 +33,12 @@
<script>
export default {
components: {
"gql-field": () => import("./field")
'gql-field': () => import('./field'),
},
props: {
gqlType: {},
jumpTypeCallback: Function
}
};
jumpTypeCallback: Function,
},
}
</script>

View File

@@ -5,7 +5,7 @@
<style scoped lang="scss">
.typelink {
color: var(--ac-color);
font-family: "Roboto Mono", monospace;
font-family: 'Roboto Mono', monospace;
font-weight: 400;
cursor: pointer;
}
@@ -16,19 +16,19 @@ export default {
props: {
gqlType: null,
// (typeName: string) => void
jumpTypeCallback: Function
jumpTypeCallback: Function,
},
computed: {
typeString() {
return this.gqlType.toString();
}
return this.gqlType.toString()
},
},
methods: {
jumpToType() {
this.jumpTypeCallback(this.gqlType);
}
}
};
this.jumpTypeCallback(this.gqlType)
},
},
}
</script>

View File

@@ -28,11 +28,11 @@
:class="{ stared: entry.star }"
@click="toggleStar(entry)"
v-tooltip="{
content: !entry.star ? $t('add_star') : $t('remove_star')
content: !entry.star ? $t('add_star') : $t('remove_star'),
}"
>
<i class="material-icons">
{{ entry.star ? "star" : "star_border" }}
{{ entry.star ? 'star' : 'star_border' }}
</i>
</button>
<li>
@@ -73,7 +73,7 @@
v-close-popover
>
<i class="material-icons">restore</i>
<span>{{ $t("restore") }}</span>
<span>{{ $t('restore') }}</span>
</button>
</div>
<div>
@@ -85,7 +85,7 @@
v-close-popover
>
<i class="material-icons">delete</i>
<span>{{ $t("delete") }}</span>
<span>{{ $t('delete') }}</span>
</button>
</div>
</template>
@@ -162,15 +162,13 @@
</transition>
</ul>
</virtual-list>
<ul
:class="{ hidden: filteredHistory.length != 0 || history.length === 0 }"
>
<ul :class="{ hidden: filteredHistory.length != 0 || history.length === 0 }">
<li>
<label>{{ $t("nothing_found") }} "{{ filterText }}"</label>
<label>{{ $t('nothing_found') }} "{{ filterText }}"</label>
</li>
</ul>
<p v-if="history.length === 0" class="info">
{{ $t("history_empty") }}
{{ $t('history_empty') }}
</p>
<div v-if="history.length !== 0">
<div class="flex-wrap" v-if="!isClearingHistory">
@@ -181,7 +179,7 @@
@click="enableHistoryClearing"
>
<i class="material-icons">clear_all</i>
<span>{{ $t("clear_all") }}</span>
<span>{{ $t('clear_all') }}</span>
</button>
<v-popover>
<button class="tooltip-target icon" v-tooltip="$t('sort')">
@@ -191,49 +189,45 @@
<div>
<button class="icon" @click="sort_by_label()" v-close-popover>
<i class="material-icons">sort_by_alpha</i>
<span>{{ $t("label") }}</span>
<span>{{ $t('label') }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_time()" v-close-popover>
<i class="material-icons">access_time</i>
<span>{{ $t("time") }}</span>
<span>{{ $t('time') }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="sort_by_status_code()"
v-close-popover
>
<button class="icon" @click="sort_by_status_code()" v-close-popover>
<i class="material-icons">assistant</i>
<span>{{ $t("status") }}</span>
<span>{{ $t('status') }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_url()" v-close-popover>
<i class="material-icons">language</i>
<span>{{ $t("url") }}</span>
<span>{{ $t('url') }}</span>
</button>
</div>
<div>
<button class="icon" @click="sort_by_path()" v-close-popover>
<i class="material-icons">timeline</i>
<span>{{ $t("path") }}</span>
<span>{{ $t('path') }}</span>
</button>
</div>
<div v-if="showMore">
<button class="icon" @click="sort_by_duration()" v-close-popover>
<i class="material-icons">timer</i>
<span>{{ $t("duration") }}</span>
<span>{{ $t('duration') }}</span>
</button>
</div>
<div>
<button class="icon" @click="toggleCollapse()">
<i class="material-icons">
{{ !showMore ? "first_page" : "last_page" }}
{{ !showMore ? 'first_page' : 'last_page' }}
</i>
<span>{{ !showMore ? $t("show_more") : $t("hide_more") }}</span>
<span>{{ !showMore ? $t('show_more') : $t('hide_more') }}</span>
</button>
</div>
</template>
@@ -241,7 +235,7 @@
</div>
<div class="flex-wrap" v-else>
<label for="clear-history-button" class="info">
{{ $t("are_you_sure") }}
{{ $t('are_you_sure') }}
</label>
<div>
<button
@@ -301,7 +295,7 @@ ol {
position: absolute;
top: 10px;
right: 10px;
font-family: "Roboto Mono", monospace;
font-family: 'Roboto Mono', monospace;
font-weight: 400;
background-color: transparent;
padding: 2px 6px;
@@ -326,24 +320,24 @@ ol {
</style>
<script>
import { findStatusGroup } from "../pages/index";
import { fb } from "../functions/fb";
import { findStatusGroup } from '../pages/index'
import { fb } from '../functions/fb'
const updateOnLocalStorage = (propertyName, property) =>
window.localStorage.setItem(propertyName, JSON.stringify(property));
window.localStorage.setItem(propertyName, JSON.stringify(property))
export default {
components: {
"pw-section": () => import("./section"),
VirtualList: () => import("vue-virtual-scroll-list")
'pw-section': () => import('./section'),
VirtualList: () => import('vue-virtual-scroll-list'),
},
data() {
return {
history:
fb.currentUser !== null
? fb.currentHistory
: JSON.parse(window.localStorage.getItem("history")) || [],
filterText: "",
: JSON.parse(window.localStorage.getItem('history')) || [],
filterText: '',
showFilter: false,
isClearingHistory: false,
reverse_sort_label: false,
@@ -351,166 +345,144 @@ export default {
reverse_sort_status_code: false,
reverse_sort_url: false,
reverse_sort_path: false,
showMore: false
};
showMore: false,
}
},
computed: {
filteredHistory() {
this.history =
fb.currentUser !== null
? fb.currentHistory
: JSON.parse(window.localStorage.getItem("history")) || [];
: JSON.parse(window.localStorage.getItem('history')) || []
return this.history.filter(entry => {
const filterText = this.filterText.toLowerCase();
const filterText = this.filterText.toLowerCase()
return Object.keys(entry).some(key => {
let value = entry[key];
value = typeof value !== "string" ? value.toString() : value;
return value.toLowerCase().includes(filterText);
});
});
}
let value = entry[key]
value = typeof value !== 'string' ? value.toString() : value
return value.toLowerCase().includes(filterText)
})
})
},
},
methods: {
clearHistory() {
if (fb.currentUser !== null) {
fb.clearHistory();
fb.clearHistory()
}
this.history = [];
this.filterText = "";
this.disableHistoryClearing();
updateOnLocalStorage("history", this.history);
this.$toast.error(this.$t("history_deleted"), {
icon: "delete"
});
this.history = []
this.filterText = ''
this.disableHistoryClearing()
updateOnLocalStorage('history', this.history)
this.$toast.error(this.$t('history_deleted'), {
icon: 'delete',
})
},
useHistory(entry) {
this.$emit("useHistory", entry);
this.$emit('useHistory', entry)
},
findEntryStatus(entry) {
const foundStatusGroup = findStatusGroup(entry.status);
const foundStatusGroup = findStatusGroup(entry.status)
return (
foundStatusGroup || {
className: ""
className: '',
}
);
)
},
deleteHistory(entry) {
if (fb.currentUser !== null) {
fb.deleteHistory(entry);
fb.deleteHistory(entry)
}
this.history.splice(this.history.indexOf(entry), 1);
this.history.splice(this.history.indexOf(entry), 1)
if (this.history.length === 0) {
this.filterText = "";
this.filterText = ''
}
updateOnLocalStorage("history", this.history);
this.$toast.error(this.$t("deleted"), {
icon: "delete"
});
updateOnLocalStorage('history', this.history)
this.$toast.error(this.$t('deleted'), {
icon: 'delete',
})
},
addEntry(entry) {
this.history.push(entry);
updateOnLocalStorage("history", this.history);
this.history.push(entry)
updateOnLocalStorage('history', this.history)
},
enableHistoryClearing() {
if (!this.history || !this.history.length) return;
this.isClearingHistory = true;
if (!this.history || !this.history.length) return
this.isClearingHistory = true
},
disableHistoryClearing() {
this.isClearingHistory = false;
this.isClearingHistory = false
},
sort_by_time() {
let byDate = this.history.slice(0);
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;
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);
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;
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);
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;
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_label() {
let byLabel = this.history.slice(0);
let byLabel = this.history.slice(0)
byLabel.sort((a, b) => {
if (this.reverse_sort_label)
return a.label === b.label ? 0 : +(a.label < b.label) || -1;
else return a.label === b.label ? 0 : +(a.label > b.label) || -1;
});
this.history = byLabel;
this.reverse_sort_label = !this.reverse_sort_label;
if (this.reverse_sort_label) return a.label === b.label ? 0 : +(a.label < b.label) || -1
else return a.label === b.label ? 0 : +(a.label > b.label) || -1
})
this.history = byLabel
this.reverse_sort_label = !this.reverse_sort_label
},
sort_by_path() {
let byPath = this.history.slice(0);
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;
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
},
sort_by_duration() {
let byDuration = this.history.slice(0);
let byDuration = this.history.slice(0)
byDuration.sort((a, b) => {
if (this.reverse_sort_duration)
return a.duration === b.duration
? 0
: +(a.duration < b.duration) || -1;
else
return a.duration === b.duration
? 0
: +(a.duration > b.duration) || -1;
});
this.history = byDuration;
this.reverse_sort_duration = !this.reverse_sort_duration;
return a.duration === b.duration ? 0 : +(a.duration < b.duration) || -1
else return a.duration === b.duration ? 0 : +(a.duration > b.duration) || -1
})
this.history = byDuration
this.reverse_sort_duration = !this.reverse_sort_duration
},
toggleCollapse() {
this.showMore = !this.showMore;
this.showMore = !this.showMore
},
toggleStar(entry) {
if (fb.currentUser !== null) {
fb.toggleStar(entry, !entry.star);
fb.toggleStar(entry, !entry.star)
}
entry.star = !entry.star;
updateOnLocalStorage("history", this.history);
}
}
};
entry.star = !entry.star
updateOnLocalStorage('history', this.history)
},
},
}
</script>

View File

@@ -49,8 +49,8 @@
export default {
props: {
color: {
type: String
}
}
};
type: String,
},
},
}
</script>

View File

@@ -1,12 +1,9 @@
<template>
<fieldset
:id="label.toLowerCase()"
:class="{ 'no-colored-frames': !frameColorsEnabled }"
>
<fieldset :id="label.toLowerCase()" :class="{ 'no-colored-frames': !frameColorsEnabled }">
<legend @click.prevent="collapse">
<span>{{ label }}</span>
<i class="material-icons">
{{ isCollapsed ? "expand_more" : "expand_less" }}
{{ isCollapsed ? 'expand_more' : 'expand_less' }}
</i>
</legend>
<div class="collapsible" :class="{ hidden: collapsed }">
@@ -25,32 +22,32 @@ fieldset.no-colored-frames legend {
export default {
computed: {
frameColorsEnabled() {
return this.$store.state.postwoman.settings.FRAME_COLORS_ENABLED || false;
}
return this.$store.state.postwoman.settings.FRAME_COLORS_ENABLED || false
},
},
data() {
return {
isCollapsed: false
};
isCollapsed: false,
}
},
props: {
label: {
type: String,
default: "Section"
default: 'Section',
},
collapsed: {
type: Boolean
}
type: Boolean,
},
},
methods: {
collapse({ target }) {
const parent = target.parentNode.parentNode;
parent.querySelector(".collapsible").classList.toggle("hidden");
this.isCollapsed = !this.isCollapsed;
}
}
};
const parent = target.parentNode.parentNode
parent.querySelector('.collapsible').classList.toggle('hidden')
this.isCollapsed = !this.isCollapsed
},
},
}
</script>

View File

@@ -45,15 +45,15 @@ export default {
props: {
color: {
type: String,
required: true
required: true,
},
name: {
type: String
type: String,
},
active: {
type: Boolean,
default: false
}
}
};
default: false,
},
},
}
</script>

View File

@@ -84,15 +84,15 @@ export default {
props: {
on: {
type: Boolean,
default: false
}
default: false,
},
},
methods: {
toggle() {
const containsOnClass = this.$refs.toggle.classList.toggle("on");
this.$emit("change", containsOnClass);
}
}
};
const containsOnClass = this.$refs.toggle.classList.toggle('on')
this.$emit('change', containsOnClass)
},
},
}
</script>

View File

@@ -1,8 +1,8 @@
export default {
name: "textareaAutoHeight",
name: 'textareaAutoHeight',
update({ scrollHeight, clientHeight, style }) {
if (scrollHeight !== clientHeight) {
style.minHeight = `${scrollHeight}px`;
style.minHeight = `${scrollHeight}px`
}
}
};
},
}

View File

@@ -10,11 +10,7 @@
"target": "postwoman",
"public": "dist",
"cleanUrls": true,
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
},
"storage": {
"rules": "storage.rules"

View File

@@ -23,4 +23,4 @@
// ]
"indexes": [],
"fieldOverrides": []
}
}

View File

@@ -1,11 +1,11 @@
const mimeToMode = {
"text/plain": "plain_text",
"text/html": "html",
"application/xml": "xml",
"application/hal+json": "json",
"application/json": "json"
'text/plain': 'plain_text',
'text/html': 'html',
'application/xml': 'xml',
'application/hal+json': 'json',
'application/json': 'json',
}
export function getEditorLangForMimeType(mimeType) {
return mimeToMode[mimeType] || "plain_text";
return mimeToMode[mimeType] || 'plain_text'
}

View File

@@ -1,22 +1,22 @@
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/auth";
import firebase from 'firebase/app'
import 'firebase/firestore'
import 'firebase/auth'
// Initialize Firebase, copied from cloud console
const firebaseConfig = {
apiKey: "AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM",
authDomain: "postwoman-api.firebaseapp.com",
databaseURL: "https://postwoman-api.firebaseio.com",
projectId: "postwoman-api",
storageBucket: "postwoman-api.appspot.com",
messagingSenderId: "421993993223",
appId: "1:421993993223:web:ec0baa8ee8c02ffa1fc6a2",
measurementId: "G-ERJ6025CEB"
};
firebase.initializeApp(firebaseConfig);
apiKey: 'AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM',
authDomain: 'postwoman-api.firebaseapp.com',
databaseURL: 'https://postwoman-api.firebaseio.com',
projectId: 'postwoman-api',
storageBucket: 'postwoman-api.appspot.com',
messagingSenderId: '421993993223',
appId: '1:421993993223:web:ec0baa8ee8c02ffa1fc6a2',
measurementId: 'G-ERJ6025CEB',
}
firebase.initializeApp(firebaseConfig)
// a reference to the users collection
const usersCollection = firebase.firestore().collection("users");
const usersCollection = firebase.firestore().collection('users')
// the shared state object that any vue component
// can get access to
@@ -34,21 +34,21 @@ export const fb = {
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
message,
label
};
label,
}
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.collection('feeds')
.add(dt)
.catch(e => console.error("error inserting", dt, e));
.catch(e => console.error('error inserting', dt, e))
},
deleteFeed: id => {
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.collection('feeds')
.doc(id)
.delete()
.catch(e => console.error("error deleting", id, e));
.catch(e => console.error('error deleting', id, e))
},
writeSettings: async (setting, value) => {
const st = {
@@ -57,47 +57,47 @@ export const fb = {
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
name: setting,
value
};
value,
}
usersCollection
.doc(fb.currentUser.uid)
.collection("settings")
.collection('settings')
.doc(setting)
.set(st)
.catch(e => console.error("error updating", st, e));
.catch(e => console.error('error updating', st, e))
},
writeHistory: async entry => {
const hs = entry;
const hs = entry
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.collection('history')
.add(hs)
.catch(e => console.error("error inserting", hs, e));
.catch(e => console.error('error inserting', hs, e))
},
deleteHistory: entry => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.collection('history')
.doc(entry.id)
.delete()
.catch(e => console.error("error deleting", entry, e));
.catch(e => console.error('error deleting', entry, e))
},
clearHistory: () => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.collection('history')
.get()
.then(({ docs }) => {
docs.forEach(e => fb.deleteHistory(e));
});
docs.forEach(e => fb.deleteHistory(e))
})
},
toggleStar: (entry, value) => {
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.collection('history')
.doc(entry.id)
.update({ star: value })
.catch(e => console.error("error deleting", entry, e));
.catch(e => console.error('error deleting', entry, e))
},
writeCollections: async collection => {
const cl = {
@@ -105,14 +105,14 @@ export const fb = {
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
collection: collection
};
collection: collection,
}
usersCollection
.doc(fb.currentUser.uid)
.collection("collections")
.doc("sync")
.collection('collections')
.doc('sync')
.set(cl)
.catch(e => console.error("error updating", cl, e));
.catch(e => console.error('error updating', cl, e))
},
writeEnvironments: async environment => {
const ev = {
@@ -120,21 +120,21 @@ export const fb = {
author: fb.currentUser.uid,
author_name: fb.currentUser.displayName,
author_image: fb.currentUser.photoURL,
environment: environment
};
environment: environment,
}
usersCollection
.doc(fb.currentUser.uid)
.collection("environments")
.doc("sync")
.collection('environments')
.doc('sync')
.set(ev)
.catch(e => console.error("error updating", ev, e));
}
};
.catch(e => console.error('error updating', ev, e))
},
}
// When a user logs in or out, save that in the store
firebase.auth().onAuthStateChanged(user => {
if (user) {
fb.currentUser = user;
fb.currentUser = user
fb.currentUser.providerData.forEach(profile => {
let us = {
updatedOn: new Date(),
@@ -142,80 +142,80 @@ firebase.auth().onAuthStateChanged(user => {
name: profile.displayName,
email: profile.email,
photoUrl: profile.photoURL,
uid: profile.uid
};
uid: profile.uid,
}
usersCollection
.doc(fb.currentUser.uid)
.set(us)
.catch(e => console.error("error updating", us, e));
});
.catch(e => console.error('error updating', us, e))
})
usersCollection
.doc(fb.currentUser.uid)
.collection("feeds")
.orderBy("createdOn", "desc")
.collection('feeds')
.orderBy('createdOn', 'desc')
.onSnapshot(feedsRef => {
const feeds = [];
const feeds = []
feedsRef.forEach(doc => {
const feed = doc.data();
feed.id = doc.id;
feeds.push(feed);
});
fb.currentFeeds = feeds;
});
const feed = doc.data()
feed.id = doc.id
feeds.push(feed)
})
fb.currentFeeds = feeds
})
usersCollection
.doc(fb.currentUser.uid)
.collection("settings")
.collection('settings')
.onSnapshot(settingsRef => {
const settings = [];
const settings = []
settingsRef.forEach(doc => {
const setting = doc.data();
setting.id = doc.id;
settings.push(setting);
});
fb.currentSettings = settings;
});
const setting = doc.data()
setting.id = doc.id
settings.push(setting)
})
fb.currentSettings = settings
})
usersCollection
.doc(fb.currentUser.uid)
.collection("history")
.collection('history')
.onSnapshot(historyRef => {
const history = [];
const history = []
historyRef.forEach(doc => {
const entry = doc.data();
entry.id = doc.id;
history.push(entry);
});
fb.currentHistory = history;
});
const entry = doc.data()
entry.id = doc.id
history.push(entry)
})
fb.currentHistory = history
})
usersCollection
.doc(fb.currentUser.uid)
.collection("collections")
.collection('collections')
.onSnapshot(collectionsRef => {
const collections = [];
const collections = []
collectionsRef.forEach(doc => {
const collection = doc.data();
collection.id = doc.id;
collections.push(collection);
});
fb.currentCollections = collections[0].collection;
});
const collection = doc.data()
collection.id = doc.id
collections.push(collection)
})
fb.currentCollections = collections[0].collection
})
usersCollection
.doc(fb.currentUser.uid)
.collection("environments")
.collection('environments')
.onSnapshot(environmentsRef => {
const environments = [];
const environments = []
environmentsRef.forEach(doc => {
const environment = doc.data();
environment.id = doc.id;
environments.push(environment);
});
fb.currentEnvironments = environments[0].environment;
});
const environment = doc.data()
environment.id = doc.id
environments.push(environment)
})
fb.currentEnvironments = environments[0].environment
})
} else {
fb.currentUser = null;
fb.currentUser = null
}
});
})

View File

@@ -1,124 +1,124 @@
export const commonHeaders = [
"WWW-Authenticate",
"Authorization",
"Proxy-Authenticate",
"Proxy-Authorization",
"Age",
"Cache-Control",
"Clear-Site-Data",
"Expires",
"Pragma",
"Warning",
"Accept-CH",
"Accept-CH-Lifetime",
"Early-Data",
"Content-DPR",
"DPR",
"Device-Memory",
"Save-Data",
"Viewport-Width",
"Width",
"Last-Modified",
"ETag",
"If-Match",
"If-None-Match",
"If-Modified-Since",
"If-Unmodified-Since",
"Vary",
"Connection",
"Keep-Alive",
"Accept",
"Accept-Charset",
"Accept-Encoding",
"Accept-Language",
"Expect",
"Max-Forwards",
"Cookie",
"Set-Cookie",
"Cookie2",
"Set-Cookie2",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials",
"Access-Control-Allow-Headers",
"Access-Control-Allow-Methods",
"Access-Control-Expose-Headers",
"Access-Control-Max-Age",
"Access-Control-Request-Headers",
"Access-Control-Request-Method",
"Origin",
"Service-Worker-Allowed",
"Timing-Allow-Origin",
"X-Permitted-Cross-Domain-Policies",
"DNT",
"Tk",
"Content-Disposition",
"Content-Length",
"Content-Type",
"Content-Encoding",
"Content-Language",
"Content-Location",
"Forwarded",
"X-Forwarded-For",
"X-Forwarded-Host",
"X-Forwarded-Proto",
"Via",
"Location",
"From",
"Host",
"Referer",
"Referrer-Policy",
"User-Agent",
"Allow",
"Server",
"Accept-Ranges",
"Range",
"If-Range",
"Content-Range",
"Cross-Origin-Opener-Policy",
"Cross-Origin-Resource-Policy",
"Content-Security-Policy",
"Content-Security-Policy-Report-Only",
"Expect-CT",
"Feature-Policy",
"Public-Key-Pins",
"Public-Key-Pins-Report-Only",
"Strict-Transport-Security",
"Upgrade-Insecure-Requests",
"X-Content-Type-Options",
"X-Download-Options",
"X-Frame-Options",
"X-Powered-By",
"X-XSS-Protection",
"Last-Event-ID",
"NEL",
"Ping-From",
"Ping-To",
"Report-To",
"Transfer-Encoding",
"TE",
"Trailer",
"Sec-WebSocket-Key",
"Sec-WebSocket-Extensions",
"Sec-WebSocket-Accept",
"Sec-WebSocket-Protocol",
"Sec-WebSocket-Version",
"Accept-Push-Policy",
"Accept-Signature",
"Alt-Svc",
"Date",
"Large-Allocation",
"Link",
"Push-Policy",
"Retry-After",
"Signature",
"Signed-Headers",
"Server-Timing",
"SourceMap",
"Upgrade",
"X-DNS-Prefetch-Control",
"X-Firefox-Spdy",
"X-Pingback",
"X-Requested-With",
"X-Robots-Tag",
"X-UA-Compatible"
];
'WWW-Authenticate',
'Authorization',
'Proxy-Authenticate',
'Proxy-Authorization',
'Age',
'Cache-Control',
'Clear-Site-Data',
'Expires',
'Pragma',
'Warning',
'Accept-CH',
'Accept-CH-Lifetime',
'Early-Data',
'Content-DPR',
'DPR',
'Device-Memory',
'Save-Data',
'Viewport-Width',
'Width',
'Last-Modified',
'ETag',
'If-Match',
'If-None-Match',
'If-Modified-Since',
'If-Unmodified-Since',
'Vary',
'Connection',
'Keep-Alive',
'Accept',
'Accept-Charset',
'Accept-Encoding',
'Accept-Language',
'Expect',
'Max-Forwards',
'Cookie',
'Set-Cookie',
'Cookie2',
'Set-Cookie2',
'Access-Control-Allow-Origin',
'Access-Control-Allow-Credentials',
'Access-Control-Allow-Headers',
'Access-Control-Allow-Methods',
'Access-Control-Expose-Headers',
'Access-Control-Max-Age',
'Access-Control-Request-Headers',
'Access-Control-Request-Method',
'Origin',
'Service-Worker-Allowed',
'Timing-Allow-Origin',
'X-Permitted-Cross-Domain-Policies',
'DNT',
'Tk',
'Content-Disposition',
'Content-Length',
'Content-Type',
'Content-Encoding',
'Content-Language',
'Content-Location',
'Forwarded',
'X-Forwarded-For',
'X-Forwarded-Host',
'X-Forwarded-Proto',
'Via',
'Location',
'From',
'Host',
'Referer',
'Referrer-Policy',
'User-Agent',
'Allow',
'Server',
'Accept-Ranges',
'Range',
'If-Range',
'Content-Range',
'Cross-Origin-Opener-Policy',
'Cross-Origin-Resource-Policy',
'Content-Security-Policy',
'Content-Security-Policy-Report-Only',
'Expect-CT',
'Feature-Policy',
'Public-Key-Pins',
'Public-Key-Pins-Report-Only',
'Strict-Transport-Security',
'Upgrade-Insecure-Requests',
'X-Content-Type-Options',
'X-Download-Options',
'X-Frame-Options',
'X-Powered-By',
'X-XSS-Protection',
'Last-Event-ID',
'NEL',
'Ping-From',
'Ping-To',
'Report-To',
'Transfer-Encoding',
'TE',
'Trailer',
'Sec-WebSocket-Key',
'Sec-WebSocket-Extensions',
'Sec-WebSocket-Accept',
'Sec-WebSocket-Protocol',
'Sec-WebSocket-Version',
'Accept-Push-Policy',
'Accept-Signature',
'Alt-Svc',
'Date',
'Large-Allocation',
'Link',
'Push-Policy',
'Retry-After',
'Signature',
'Signed-Headers',
'Server-Timing',
'SourceMap',
'Upgrade',
'X-DNS-Prefetch-Control',
'X-Firefox-Spdy',
'X-Pingback',
'X-Requested-With',
'X-Robots-Tag',
'X-UA-Compatible',
]

View File

@@ -1,20 +1,16 @@
import AxiosStrategy from "./strategies/AxiosStrategy";
import ExtensionStrategy, {
hasExtensionInstalled
} from "./strategies/ExtensionStrategy";
import FirefoxStrategy from "./strategies/FirefoxStrategy";
import ChromeStrategy, {
hasChromeExtensionInstalled
} from "./strategies/ChromeStrategy";
import AxiosStrategy from './strategies/AxiosStrategy'
import ExtensionStrategy, { hasExtensionInstalled } from './strategies/ExtensionStrategy'
import FirefoxStrategy from './strategies/FirefoxStrategy'
import ChromeStrategy, { hasChromeExtensionInstalled } from './strategies/ChromeStrategy'
const isExtensionsAllowed = ({ state }) =>
typeof state.postwoman.settings.EXTENSIONS_ENABLED === "undefined" ||
state.postwoman.settings.EXTENSIONS_ENABLED;
typeof state.postwoman.settings.EXTENSIONS_ENABLED === 'undefined' ||
state.postwoman.settings.EXTENSIONS_ENABLED
const runAppropriateStrategy = (req, store) => {
if (isExtensionsAllowed(store)) {
if (hasExtensionInstalled()) {
return ExtensionStrategy(req, store);
return ExtensionStrategy(req, store)
}
// The following strategies are deprecated and kept to support older version of the extensions
@@ -22,21 +18,19 @@ const runAppropriateStrategy = (req, store) => {
// Chrome Provides a chrome object for scripts to access
// Check its availability to say whether you are in Google Chrome
if (window.chrome && hasChromeExtensionInstalled()) {
return ChromeStrategy(req, store);
return ChromeStrategy(req, store)
}
// The firefox plugin injects a function to send requests through it
// If that is available, then we can use the FirefoxStrategy
if (window.firefoxExtSendRequest) {
return FirefoxStrategy(req, store);
return FirefoxStrategy(req, store)
}
}
return AxiosStrategy(req, store);
};
return AxiosStrategy(req, store)
}
const sendNetworkRequest = (req, store) =>
runAppropriateStrategy(req, store).finally(() =>
window.$nuxt.$loading.finish()
);
runAppropriateStrategy(req, store).finally(() => window.$nuxt.$loading.finish())
export { sendNetworkRequest };
export { sendNetworkRequest }

View File

@@ -1,13 +1,13 @@
const PASS = "PASS";
const FAIL = "FAIL";
const ERROR = "ERROR";
const PASS = 'PASS'
const FAIL = 'FAIL'
const ERROR = 'ERROR'
const styles = {
[PASS]: { icon: "check", class: "success-response" },
[FAIL]: { icon: "close", class: "cl-error-response" },
[ERROR]: { icon: "close", class: "cl-error-response" },
none: { icon: "", class: "" }
};
[PASS]: { icon: 'check', class: 'success-response' },
[FAIL]: { icon: 'close', class: 'cl-error-response' },
[ERROR]: { icon: 'close', class: 'cl-error-response' },
none: { icon: '', class: '' },
}
// TODO: probably have to use a more global state for `test`
@@ -15,161 +15,133 @@ export default function runTestScriptWithVariables(script, variables) {
let pw = {
_errors: [],
_testReports: [],
_report: "",
_report: '',
expect(value) {
try {
return expect(value, this._testReports);
return expect(value, this._testReports)
} catch (e) {
pw._testReports.push({ result: ERROR, message: e });
pw._testReports.push({ result: ERROR, message: e })
}
},
test: (descriptor, func) => test(descriptor, func, pw._testReports)
test: (descriptor, func) => test(descriptor, func, pw._testReports),
// globals that the script is allowed to have access to.
};
Object.assign(pw, variables);
}
Object.assign(pw, variables)
// run pre-request script within this function so that it has access to the pw object.
new Function("pw", script)(pw);
new Function('pw', script)(pw)
//
const testReports = pw._testReports.map(item => {
if (item.result) {
item.styles = styles[item.result];
item.styles = styles[item.result]
} else {
item.styles = styles.none;
item.styles = styles.none
}
return item;
});
return { report: pw._report, errors: pw._errors, testResults: testReports };
return item
})
return { report: pw._report, errors: pw._errors, testResults: testReports }
}
function test(descriptor, func, _testReports) {
_testReports.push({ startBlock: descriptor });
_testReports.push({ startBlock: descriptor })
try {
func();
func()
} catch (e) {
_testReports.push({ result: ERROR, message: e });
_testReports.push({ result: ERROR, message: e })
}
_testReports.push({ endBlock: true });
_testReports.push({ endBlock: true })
// TODO: Organize and generate text report of each {descriptor: true} section in testReports.
// add checkmark or x depending on if each testReport is pass=true or pass=false
}
function expect(expectValue, _testReports) {
return new Expectation(expectValue, null, _testReports);
return new Expectation(expectValue, null, _testReports)
}
class Expectation {
constructor(expectValue, _not, _testReports) {
this.expectValue = expectValue;
this.not = _not || new Expectation(this.expectValue, true, _testReports);
this._testReports = _testReports; // this values is used within Test.it, which wraps Expectation and passes _testReports value.
this.expectValue = expectValue
this.not = _not || new Expectation(this.expectValue, true, _testReports)
this._testReports = _testReports // this values is used within Test.it, which wraps Expectation and passes _testReports value.
this._satisfies = function(expectValue, targetValue) {
// Used for testing if two values match the expectation, which could be === OR !==, depending on if not
// was used. Expectation#_satisfies prevents the need to have an if(this.not) branch in every test method.
// Signature is _satisfies([expectValue,] targetValue): if only one argument is given, it is assumed the targetValue, and expectValue is set to this.expectValue
if (!targetValue) {
targetValue = expectValue;
expectValue = this.expectValue;
targetValue = expectValue
expectValue = this.expectValue
}
if (this.not === true) {
// test the inverse. this.not is always truthly, but an Expectation that is inverted will always be strictly `true`
return expectValue !== targetValue;
return expectValue !== targetValue
} else {
return expectValue === targetValue;
return expectValue === targetValue
}
};
}
}
_fmtNot(message) {
// given a string with "(not)" in it, replaces with "not" or "", depending if the expectation is expecting the positive or inverse (this._not)
if (this.not === true) {
return message.replace("(not)", "not ");
return message.replace('(not)', 'not ')
} else {
return message.replace("(not)", "");
return message.replace('(not)', '')
}
}
_fail(message) {
this._testReports.push({ result: FAIL, message });
this._testReports.push({ result: FAIL, message })
}
_pass(message) {
this._testReports.push({ result: PASS });
this._testReports.push({ result: PASS })
}
// TEST METHODS DEFINED BELOW
// these are the usual methods that would follow expect(...)
toBe(value) {
return this._satisfies(value)
? this._pass()
: this._fail(
this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`)
);
: this._fail(this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`))
}
toHaveProperty(value) {
return this._satisfies(this.expectValue.hasOwnProperty(value), true)
? this._pass()
: this._fail(
this._fmtNot(
`Expected object ${this.expectValue} to (not)have property ${value}`
)
);
this._fmtNot(`Expected object ${this.expectValue} to (not)have property ${value}`)
)
}
toBeLevel2xx() {
const code = parseInt(this.expectValue);
const code = parseInt(this.expectValue)
if (Number.isNaN(code)) {
return this._fail(
`Expected 200-level status but could not parse value ${this.expectValue}`
);
return this._fail(`Expected 200-level status but could not parse value ${this.expectValue}`)
}
return this._satisfies(code >= 200 && code < 300)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 200-level status`
)
);
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 200-level status`))
}
toBeLevel3xx() {
const code = parseInt(this.expectValue);
const code = parseInt(this.expectValue)
if (Number.isNaN(code)) {
return this._fail(
`Expected 300-level status but could not parse value ${this.expectValue}`
);
return this._fail(`Expected 300-level status but could not parse value ${this.expectValue}`)
}
return this._satisfies(code >= 300 && code < 400)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 300-level status`
)
);
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 300-level status`))
}
toBeLevel4xx() {
const code = parseInt(this.expectValue);
const code = parseInt(this.expectValue)
if (Number.isNaN(code)) {
return this._fail(
`Expected 400-level status but could not parse value ${this.expectValue}`
);
return this._fail(`Expected 400-level status but could not parse value ${this.expectValue}`)
}
return this._satisfies(code >= 400 && code < 500)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 400-level status`
)
);
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 400-level status`))
}
toBeLevel5xx() {
const code = parseInt(this.expectValue);
const code = parseInt(this.expectValue)
if (Number.isNaN(code)) {
return this._fail(
`Expected 500-level status but could not parse value ${this.expectValue}`
);
return this._fail(`Expected 500-level status but could not parse value ${this.expectValue}`)
}
return this._satisfies(code >= 500 && code < 600)
? this._pass()
: this._fail(
this._fmtNot(
`Expected ${this.expectValue} to (not)be 500-level status`
)
);
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 500-level status`))
}
}

View File

@@ -1,20 +1,20 @@
export default function getEnvironmentVariablesFromScript(script) {
let _variables = {};
let _variables = {}
// the pw object is the proxy by which pre-request scripts can pass variables to the request.
// for security and control purposes, this is the only way a pre-request script should modify variables.
let pw = {
environment: {
set: (key, value) => (_variables[key] = value)
set: (key, value) => (_variables[key] = value),
},
env: {
set: (key, value) => (_variables[key] = value)
}
set: (key, value) => (_variables[key] = value),
},
// globals that the script is allowed to have access to.
};
}
// run pre-request script within this function so that it has access to the pw object.
new Function("pw", script)(pw);
new Function('pw', script)(pw)
return _variables;
return _variables
}

View File

@@ -1,23 +1,23 @@
import axios from "axios";
import axios from 'axios'
const axiosWithProxy = async (req, { state }) => {
const { data } = await axios.post(
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
state.postwoman.settings.PROXY_URL || 'https://postwoman.apollotv.xyz/',
req
);
return data;
};
)
return data
}
const axiosWithoutProxy = async (req, _store) => {
const res = await axios(req);
return res;
};
const res = await axios(req)
return res
}
const axiosStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return axiosWithProxy(req, store);
return axiosWithProxy(req, store)
}
return axiosWithoutProxy(req, store);
};
return axiosWithoutProxy(req, store)
}
export default axiosStrategy;
export default axiosStrategy

View File

@@ -1,63 +1,61 @@
const EXTENSION_ID = "amknoiejhlmhancpahfcfcfhllgkpbld";
const EXTENSION_ID = 'amknoiejhlmhancpahfcfcfhllgkpbld'
// Check if the Chrome Extension is present
// The Chrome extension injects an empty span to help detection.
// Also check for the presence of window.chrome object to confirm smooth operations
export const hasChromeExtensionInstalled = () =>
document.getElementById("chromePWExtensionDetect") !== null;
document.getElementById('chromePWExtensionDetect') !== null
const chromeWithoutProxy = (req, _store) =>
new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
EXTENSION_ID,
{
messageType: "send-req",
messageType: 'send-req',
data: {
config: req
}
config: req,
},
},
({ data }) => {
if (data.error) {
reject(data.error);
reject(data.error)
} else {
resolve(data.response);
resolve(data.response)
}
}
);
});
)
})
const chromeWithProxy = (req, { state }) =>
new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
EXTENSION_ID,
{
messageType: "send-req",
messageType: 'send-req',
data: {
config: {
method: "post",
url:
state.postwoman.settings.PROXY_URL ||
"https://postwoman.apollotv.xyz/",
data: req
}
}
method: 'post',
url: state.postwoman.settings.PROXY_URL || 'https://postwoman.apollotv.xyz/',
data: req,
},
},
},
({ data }) => {
if (data.error) {
reject(error);
reject(error)
} else {
resolve(data.response.data);
resolve(data.response.data)
}
}
);
});
)
})
const chromeStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return chromeWithProxy(req, store);
return chromeWithProxy(req, store)
} else {
return chromeWithoutProxy(req, store);
return chromeWithoutProxy(req, store)
}
};
}
export default chromeStrategy;
export default chromeStrategy

View File

@@ -1,26 +1,25 @@
export const hasExtensionInstalled = () =>
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== "undefined";
typeof window.__POSTWOMAN_EXTENSION_HOOK__ !== 'undefined'
const extensionWithProxy = async (req, { state }) => {
const { data } = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest({
method: "post",
url:
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
data: req
});
return data;
};
method: 'post',
url: state.postwoman.settings.PROXY_URL || 'https://postwoman.apollotv.xyz/',
data: req,
})
return data
}
const extensionWithoutProxy = async (req, _store) => {
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest(req);
return res;
};
const res = await window.__POSTWOMAN_EXTENSION_HOOK__.sendRequest(req)
return res
}
const extensionStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return extensionWithProxy(req, store);
return extensionWithProxy(req, store)
}
return extensionWithoutProxy(req, store);
};
return extensionWithoutProxy(req, store)
}
export default extensionStrategy;
export default extensionStrategy

View File

@@ -1,50 +1,46 @@
const firefoxWithProxy = (req, { state }) =>
new Promise((resolve, reject) => {
const eventListener = event => {
window.removeEventListener("firefoxExtSendRequestComplete", event);
window.removeEventListener('firefoxExtSendRequestComplete', event)
if (event.detail.error) {
reject(JSON.parse(event.detail.error));
reject(JSON.parse(event.detail.error))
} else {
resolve(JSON.parse(event.detail.response).data);
resolve(JSON.parse(event.detail.response).data)
}
};
}
window.addEventListener("firefoxExtSendRequestComplete", eventListener);
window.addEventListener('firefoxExtSendRequestComplete', eventListener)
window.firefoxExtSendRequest({
method: "post",
url:
state.postwoman.settings.PROXY_URL || "https://postwoman.apollotv.xyz/",
data: req
});
});
method: 'post',
url: state.postwoman.settings.PROXY_URL || 'https://postwoman.apollotv.xyz/',
data: req,
})
})
const firefoxWithoutProxy = (req, _store) =>
new Promise((resolve, reject) => {
const eventListener = ({ detail }) => {
window.removeEventListener(
"firefoxExtSendRequestComplete",
eventListener
);
window.removeEventListener('firefoxExtSendRequestComplete', eventListener)
if (detail.error) {
reject(JSON.parse(detail.error));
reject(JSON.parse(detail.error))
} else {
resolve(JSON.parse(detail.response));
resolve(JSON.parse(detail.response))
}
};
}
window.addEventListener("firefoxExtSendRequestComplete", eventListener);
window.addEventListener('firefoxExtSendRequestComplete', eventListener)
window.firefoxExtSendRequest(req);
});
window.firefoxExtSendRequest(req)
})
const firefoxStrategy = (req, store) => {
if (store.state.postwoman.settings.PROXY_ENABLED) {
return firefoxWithProxy(req, store);
return firefoxWithProxy(req, store)
}
return firefoxWithoutProxy(req, store);
};
return firefoxWithoutProxy(req, store)
}
export default firefoxStrategy;
export default firefoxStrategy

View File

@@ -1,7 +1,7 @@
export default function parseTemplateString(string, variables) {
if (!variables || !string) {
return string;
return string
}
const searchTerm = /<<([^>]*)>>/g; // "<<myVariable>>"
return string.replace(searchTerm, (match, p1) => variables[p1] || "");
const searchTerm = /<<([^>]*)>>/g // "<<myVariable>>"
return string.replace(searchTerm, (match, p1) => variables[p1] || '')
}

View File

@@ -3,13 +3,13 @@
// functions which might be called frequently
// NOTE : Don't use lambda functions as this doesn't get bound properly in them, use the 'function (args) {}' format
const debounce = (func, delay) => {
let inDebounce;
let inDebounce
return function() {
const context = this;
const args = arguments;
clearTimeout(inDebounce);
inDebounce = setTimeout(() => func.apply(context, args), delay);
};
};
const context = this
const args = arguments
clearTimeout(inDebounce)
inDebounce = setTimeout(() => func.apply(context, args), delay)
}
}
export default debounce;
export default debounce

View File

@@ -1,90 +1,90 @@
export default {
home: "Startseite",
realtime: "Echtzeit",
graphql: "GraphQL",
settings: "Einstellungen",
request: "Anfrage",
install_pwa: "PWA installieren",
support_us: "Unterstütze uns",
tweet: "Twittern",
options: "Optionen",
communication: "Kommunikation",
endpoint: "Endpunkt",
schema: "Schema",
theme: "Design",
subscribe: "Abonnieren",
choose_language: "Sprache auswählen",
shortcuts: "Tastenkombinationen",
send_request: "Anfrage senden",
save_to_collections: "In Sammlungen speichern",
copy_request_link: "Anfragelink kopieren",
reset_request: "Anfrage zurücksetzen",
support_us_on: "Unterstütze uns auf",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript-Code",
method: "Methode",
path: "Pfad",
label: "Beschriftung",
again: "Wiederholen",
content_type: "Content-Typ",
raw_input: "Rohdaten-Eingabe",
parameter_list: "Parameterliste",
raw_request_body: "Rohdaten der Anfrage",
show_code: "Code zeigen",
hide_code: "Code ausblenden",
show_prerequest_script: "Preanfrageskript anzeigen",
hide_prerequest_script: "Preanfrageskript ausblenden",
authentication: "Authentifizierung",
authentication_type: "Authentifizierungs-Typ",
include_in_url: "In URL einfügen",
parameters: "Parameter",
expand_response: "Antwort ausklappen",
collapse_response: "Antwort einklappen",
hide_preview: "Vorschau verstecken",
preview_html: "HTML-Vorschau",
history: "Verlauf",
collections: "Kollektionen",
import_curl: "cURL importieren",
import: "Importieren",
generate_code: "Code generieren",
request_type: "Anfrage-Typ",
generated_code: "Generierter Code",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(warte auf Verbindung)",
message: "Nachricht",
sse: "SSE",
server: "Server",
events: "Ereignisse",
url: "URL",
get_schema: "Schema abrufen",
header_list: "Headerliste",
add_new: "Neu hinzufügen",
response: "Antwort",
query: "Abfrage",
queries: "Abfragen",
query_variables: "Variablen",
mutations: "Mutationen",
subscriptions: "Abonnements",
types: "Typen",
send: "Senden",
background: "Hintergrund",
color: "Farbe",
labels: "Bezeichner",
multi_color: "Mehrfarbig",
enabled: "Aktiviert",
disabled: "Deaktiviert",
proxy: "Proxy",
home: 'Startseite',
realtime: 'Echtzeit',
graphql: 'GraphQL',
settings: 'Einstellungen',
request: 'Anfrage',
install_pwa: 'PWA installieren',
support_us: 'Unterstütze uns',
tweet: 'Twittern',
options: 'Optionen',
communication: 'Kommunikation',
endpoint: 'Endpunkt',
schema: 'Schema',
theme: 'Design',
subscribe: 'Abonnieren',
choose_language: 'Sprache auswählen',
shortcuts: 'Tastenkombinationen',
send_request: 'Anfrage senden',
save_to_collections: 'In Sammlungen speichern',
copy_request_link: 'Anfragelink kopieren',
reset_request: 'Anfrage zurücksetzen',
support_us_on: 'Unterstütze uns auf',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'JavaScript-Code',
method: 'Methode',
path: 'Pfad',
label: 'Beschriftung',
again: 'Wiederholen',
content_type: 'Content-Typ',
raw_input: 'Rohdaten-Eingabe',
parameter_list: 'Parameterliste',
raw_request_body: 'Rohdaten der Anfrage',
show_code: 'Code zeigen',
hide_code: 'Code ausblenden',
show_prerequest_script: 'Preanfrageskript anzeigen',
hide_prerequest_script: 'Preanfrageskript ausblenden',
authentication: 'Authentifizierung',
authentication_type: 'Authentifizierungs-Typ',
include_in_url: 'In URL einfügen',
parameters: 'Parameter',
expand_response: 'Antwort ausklappen',
collapse_response: 'Antwort einklappen',
hide_preview: 'Vorschau verstecken',
preview_html: 'HTML-Vorschau',
history: 'Verlauf',
collections: 'Kollektionen',
import_curl: 'cURL importieren',
import: 'Importieren',
generate_code: 'Code generieren',
request_type: 'Anfrage-Typ',
generated_code: 'Generierter Code',
status: 'Status',
headers: 'Headers',
websocket: 'WebSocket',
waiting_for_connection: '(warte auf Verbindung)',
message: 'Nachricht',
sse: 'SSE',
server: 'Server',
events: 'Ereignisse',
url: 'URL',
get_schema: 'Schema abrufen',
header_list: 'Headerliste',
add_new: 'Neu hinzufügen',
response: 'Antwort',
query: 'Abfrage',
queries: 'Abfragen',
query_variables: 'Variablen',
mutations: 'Mutationen',
subscriptions: 'Abonnements',
types: 'Typen',
send: 'Senden',
background: 'Hintergrund',
color: 'Farbe',
labels: 'Bezeichner',
multi_color: 'Mehrfarbig',
enabled: 'Aktiviert',
disabled: 'Deaktiviert',
proxy: 'Proxy',
postwoman_official_proxy_hosting:
"Postwomans offizieller Proxy wird durch ApolloTV bereitgestellt.",
read_the: "Lies die",
apollotv_privacy_policy: "ApolloTV Datenschutzerklärung",
contact_us: "Kontaktiere uns",
connect: "Verbinden",
disconnect: "Trennen",
start: "Start",
stop: "Stopp"
};
'Postwomans offizieller Proxy wird durch ApolloTV bereitgestellt.',
read_the: 'Lies die',
apollotv_privacy_policy: 'ApolloTV Datenschutzerklärung',
contact_us: 'Kontaktiere uns',
connect: 'Verbinden',
disconnect: 'Trennen',
start: 'Start',
stop: 'Stopp',
}

View File

@@ -1,278 +1,273 @@
export default {
home: "Home",
realtime: "Realtime",
graphql: "GraphQL",
settings: "Settings",
request: "Request",
install_pwa: "Install PWA",
support_us: "Support us",
tweet: "Tweet",
options: "Options",
communication: "Communication",
endpoint: "Endpoint",
schema: "Schema",
theme: "Theme",
subscribe: "Subscribe",
choose_language: "Choose Language",
shortcuts: "Shortcuts",
send_request: "Send Request",
save_to_collections: "Save to Collections",
copy_request_link: "Copy Request Link",
reset_request: "Reset Request",
support_us_on: "Support us on",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript Code",
method: "Method",
path: "Path",
label: "Label",
content_type: "Content Type",
raw_input: "Raw input",
parameter_list: "Parameter List",
raw_request_body: "Raw Request Body",
show_code: "Show Code",
hide_code: "Hide Code",
show_prerequest_script: "Show Pre-Request Script",
hide_prerequest_script: "Hide Pre-Request Script",
authentication: "Authentication",
authentication_type: "Authentication type",
include_in_url: "Include in URL",
parameters: "Parameters",
expand_response: "Expand response",
collapse_response: "Collapse response",
hide_preview: "Hide Preview",
preview_html: "Preview HTML",
history: "History",
collections: "Collections",
environment: "Environment",
new_environment: "New Environment",
my_new_environment: "My New Environment",
edit_environment: "Edit Environment",
env_variable_list: "Variable List",
invalid_environment_name: "Please provide a valid name for the environment",
use_environment: "Use Environment",
add_one_variable: "(add at least one variable)",
import_curl: "Import cURL",
import: "Import",
generate_code: "Generate code",
request_type: "Request type",
generated_code: "Generated code",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(waiting for connection)",
message: "Message",
sse: "SSE",
server: "Server",
events: "Events",
url: "URL",
get_schema: "Get schema",
header_list: "Header list",
add_new: "Add new",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Subscriptions",
types: "Types",
send: "Send",
background: "Background",
color: "Color",
labels: "Labels",
multi_color: "Multi-color",
enabled: "Enabled",
disabled: "Disabled",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Postwoman's Official Proxy is hosted by ApolloTV.",
read_the: "Read the",
apollotv_privacy_policy: "ApolloTV privacy policy",
contact_us: "Contact us",
connect: "Connect",
disconnect: "Disconnect",
start: "Start",
stop: "Stop",
access_token: "Access Token",
token_list: "Token List",
get_token: "Get New Token",
manage_token: "Manage Access Token",
save_token: "Save Access Token",
use_token: "Use Saved Token",
request_token: "Request Token",
save_token_req: "Save Token Request",
manage_token_req: "Manage Token Request",
use_token_req: "Use Token Request",
token_req_name: "Request Name",
token_req_details: "Request Details",
token_name: "Token Name",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "Auth URL",
access_token_url: "Access Token URL",
client_id: "Client ID",
scope: "Scope",
state: "State",
token_req_list: "Token Request List",
no_path: "No path",
no_label: "No label",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "No pre-request script",
search: "Search",
history_empty: "History is empty",
history_deleted: "History Deleted",
clear: "Clear",
clear_all: "Clear All",
cleared: "Cleared",
close: "Close",
sort: "Sort",
time: "Time",
duration: "Duration",
no_duration: "No duration",
show_more: "Show more",
hide_more: "Hide more",
collection: "Collection",
current_collection: "Current Collection",
select_collection: "Select a Collection",
create_collection: "Create a Collection",
new: "New",
import_export: "Import / Export",
more: "More",
folder: "Folder",
new_folder: "New Folder",
my_new_folder: "My New Folder",
folder_empty: "Folder is empty",
edit_folder: "Edit Folder",
edit: "Edit",
delete: "Delete",
deleted: "Deleted",
undo: "Undo",
collection_empty: "Collection is empty",
invalid_collection_name: "Please provide a valid name for the collection",
new_collection: "New Collection",
my_new_collection: "My New Collection",
edit_collection: "Edit Collection",
edit_request: "Edit Request",
save_request_as: "Save Request As",
export: "Export",
connecting_to: "Connecting to {name}...",
connected: "Connected",
connected_to: "Connected to {name}",
disconnected: "Disconnected",
disconnected_from: "Disconnected from {name}",
something_went_wrong: "Something went wrong!",
error_occurred: "An error has occurred.",
browser_support_sse:
"This browser doesn't seems to have Server Sent Events support.",
log: "Log",
no_url: "No URL",
run_query: "Run Query",
copy_query: "Copy Query",
kinda_dark: "Kinda Dark",
clearly_white: "Clearly White",
just_black: "Just Black",
auto_system: "Auto (system)",
green: "Green",
yellow: "Yellow",
pink: "Pink",
red: "Red",
purple: "Purple",
orange: "Orange",
cyan: "Cyan",
blue: "Blue",
loading: "Loading...",
fetching: "Fetching...",
waiting_send_req: "(waiting to send request)",
cancel: "Cancel",
save: "Save",
dismiss: "Dismiss",
are_you_sure: "Are you sure?",
yes: "Yes",
no: "No",
restore: "Restore",
add_star: "Add star",
remove_star: "Remove star",
nothing_found: "Nothing found",
replace_current: "Replace current",
replace_json: "Replace with JSON",
preserve_current: "Preserve current",
import_json: "Import from JSON",
download_file: "Download file",
upload_file: "Upload file",
copy_response: "Copy response",
copy_code: "Copy code",
copy_schema: "Copy Schema",
use_request: "Use request",
documentation: "Documentation",
docs: "Docs",
reset_default: "Reset to default",
fields: "FIELDS",
deprecated: "DEPRECATED",
add_one_header: "(add at least one header)",
add_one_parameter: "(add at least one parameter)",
header_count: "header {count}",
parameter_count: "parameter {count}",
variable_count: "variable {count}",
value_count: "value {count}",
send_request_first: "Send a request first",
generate_docs: "Generate Documentation",
generate_docs_message:
"Import any Postwoman Collection to Generate Documentation on-the-go.",
generate_docs_first: "Generate documentation first",
docs_generated: "Documentation generated",
import_collections: "Import collections",
optional: "(optional)",
json: "JSON",
none: "None",
username: "Username",
password: "Password",
token: "Token",
payload: "Payload",
choose_file: "Choose a file",
file_imported: "File imported",
import_failed: "Import failed",
f12_details: "(F12 for details)",
we_use_cookies: "We use cookies",
copied_to_clipboard: "Copied to clipboard",
finished_in: "Finished in {duration}ms",
check_console_details: "Check console for details.",
download_started: "Download started",
url_invalid_format: "URL is not formatted properly",
curl_invalid_format: "cURL is not formatted properly",
enable_proxy: "Try enabling Proxy",
complete_config_urls: "Please complete configuration urls.",
token_request_saved: "Token request saved",
home: 'Home',
realtime: 'Realtime',
graphql: 'GraphQL',
settings: 'Settings',
request: 'Request',
install_pwa: 'Install PWA',
support_us: 'Support us',
tweet: 'Tweet',
options: 'Options',
communication: 'Communication',
endpoint: 'Endpoint',
schema: 'Schema',
theme: 'Theme',
subscribe: 'Subscribe',
choose_language: 'Choose Language',
shortcuts: 'Shortcuts',
send_request: 'Send Request',
save_to_collections: 'Save to Collections',
copy_request_link: 'Copy Request Link',
reset_request: 'Reset Request',
support_us_on: 'Support us on',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'JavaScript Code',
method: 'Method',
path: 'Path',
label: 'Label',
content_type: 'Content Type',
raw_input: 'Raw input',
parameter_list: 'Parameter List',
raw_request_body: 'Raw Request Body',
show_code: 'Show Code',
hide_code: 'Hide Code',
show_prerequest_script: 'Show Pre-Request Script',
hide_prerequest_script: 'Hide Pre-Request Script',
authentication: 'Authentication',
authentication_type: 'Authentication type',
include_in_url: 'Include in URL',
parameters: 'Parameters',
expand_response: 'Expand response',
collapse_response: 'Collapse response',
hide_preview: 'Hide Preview',
preview_html: 'Preview HTML',
history: 'History',
collections: 'Collections',
environment: 'Environment',
new_environment: 'New Environment',
my_new_environment: 'My New Environment',
edit_environment: 'Edit Environment',
env_variable_list: 'Variable List',
invalid_environment_name: 'Please provide a valid name for the environment',
use_environment: 'Use Environment',
add_one_variable: '(add at least one variable)',
import_curl: 'Import cURL',
import: 'Import',
generate_code: 'Generate code',
request_type: 'Request type',
generated_code: 'Generated code',
status: 'Status',
headers: 'Headers',
websocket: 'WebSocket',
waiting_for_connection: '(waiting for connection)',
message: 'Message',
sse: 'SSE',
server: 'Server',
events: 'Events',
url: 'URL',
get_schema: 'Get schema',
header_list: 'Header list',
add_new: 'Add new',
response: 'Response',
query: 'Query',
queries: 'Queries',
query_variables: 'Variables',
mutations: 'Mutations',
subscriptions: 'Subscriptions',
types: 'Types',
send: 'Send',
background: 'Background',
color: 'Color',
labels: 'Labels',
multi_color: 'Multi-color',
enabled: 'Enabled',
disabled: 'Disabled',
proxy: 'Proxy',
postwoman_official_proxy_hosting: "Postwoman's Official Proxy is hosted by ApolloTV.",
read_the: 'Read the',
apollotv_privacy_policy: 'ApolloTV privacy policy',
contact_us: 'Contact us',
connect: 'Connect',
disconnect: 'Disconnect',
start: 'Start',
stop: 'Stop',
access_token: 'Access Token',
token_list: 'Token List',
get_token: 'Get New Token',
manage_token: 'Manage Access Token',
save_token: 'Save Access Token',
use_token: 'Use Saved Token',
request_token: 'Request Token',
save_token_req: 'Save Token Request',
manage_token_req: 'Manage Token Request',
use_token_req: 'Use Token Request',
token_req_name: 'Request Name',
token_req_details: 'Request Details',
token_name: 'Token Name',
oidc_discovery_url: 'OIDC Discovery URL',
auth_url: 'Auth URL',
access_token_url: 'Access Token URL',
client_id: 'Client ID',
scope: 'Scope',
state: 'State',
token_req_list: 'Token Request List',
no_path: 'No path',
no_label: 'No label',
prerequest_script: 'Pre-Request Script',
no_prerequest_script: 'No pre-request script',
search: 'Search',
history_empty: 'History is empty',
history_deleted: 'History Deleted',
clear: 'Clear',
clear_all: 'Clear All',
cleared: 'Cleared',
close: 'Close',
sort: 'Sort',
time: 'Time',
duration: 'Duration',
no_duration: 'No duration',
show_more: 'Show more',
hide_more: 'Hide more',
collection: 'Collection',
current_collection: 'Current Collection',
select_collection: 'Select a Collection',
create_collection: 'Create a Collection',
new: 'New',
import_export: 'Import / Export',
more: 'More',
folder: 'Folder',
new_folder: 'New Folder',
my_new_folder: 'My New Folder',
folder_empty: 'Folder is empty',
edit_folder: 'Edit Folder',
edit: 'Edit',
delete: 'Delete',
deleted: 'Deleted',
undo: 'Undo',
collection_empty: 'Collection is empty',
invalid_collection_name: 'Please provide a valid name for the collection',
new_collection: 'New Collection',
my_new_collection: 'My New Collection',
edit_collection: 'Edit Collection',
edit_request: 'Edit Request',
save_request_as: 'Save Request As',
export: 'Export',
connecting_to: 'Connecting to {name}...',
connected: 'Connected',
connected_to: 'Connected to {name}',
disconnected: 'Disconnected',
disconnected_from: 'Disconnected from {name}',
something_went_wrong: 'Something went wrong!',
error_occurred: 'An error has occurred.',
browser_support_sse: "This browser doesn't seems to have Server Sent Events support.",
log: 'Log',
no_url: 'No URL',
run_query: 'Run Query',
copy_query: 'Copy Query',
kinda_dark: 'Kinda Dark',
clearly_white: 'Clearly White',
just_black: 'Just Black',
auto_system: 'Auto (system)',
green: 'Green',
yellow: 'Yellow',
pink: 'Pink',
red: 'Red',
purple: 'Purple',
orange: 'Orange',
cyan: 'Cyan',
blue: 'Blue',
loading: 'Loading...',
fetching: 'Fetching...',
waiting_send_req: '(waiting to send request)',
cancel: 'Cancel',
save: 'Save',
dismiss: 'Dismiss',
are_you_sure: 'Are you sure?',
yes: 'Yes',
no: 'No',
restore: 'Restore',
add_star: 'Add star',
remove_star: 'Remove star',
nothing_found: 'Nothing found',
replace_current: 'Replace current',
replace_json: 'Replace with JSON',
preserve_current: 'Preserve current',
import_json: 'Import from JSON',
download_file: 'Download file',
upload_file: 'Upload file',
copy_response: 'Copy response',
copy_code: 'Copy code',
copy_schema: 'Copy Schema',
use_request: 'Use request',
documentation: 'Documentation',
docs: 'Docs',
reset_default: 'Reset to default',
fields: 'FIELDS',
deprecated: 'DEPRECATED',
add_one_header: '(add at least one header)',
add_one_parameter: '(add at least one parameter)',
header_count: 'header {count}',
parameter_count: 'parameter {count}',
variable_count: 'variable {count}',
value_count: 'value {count}',
send_request_first: 'Send a request first',
generate_docs: 'Generate Documentation',
generate_docs_message: 'Import any Postwoman Collection to Generate Documentation on-the-go.',
generate_docs_first: 'Generate documentation first',
docs_generated: 'Documentation generated',
import_collections: 'Import collections',
optional: '(optional)',
json: 'JSON',
none: 'None',
username: 'Username',
password: 'Password',
token: 'Token',
payload: 'Payload',
choose_file: 'Choose a file',
file_imported: 'File imported',
import_failed: 'Import failed',
f12_details: '(F12 for details)',
we_use_cookies: 'We use cookies',
copied_to_clipboard: 'Copied to clipboard',
finished_in: 'Finished in {duration}ms',
check_console_details: 'Check console for details.',
download_started: 'Download started',
url_invalid_format: 'URL is not formatted properly',
curl_invalid_format: 'cURL is not formatted properly',
enable_proxy: 'Try enabling Proxy',
complete_config_urls: 'Please complete configuration urls.',
token_request_saved: 'Token request saved',
donate_info1:
"If you have enjoyed the productivity of using Postwoman, consider donating as a sign of appreciation.",
donate_info2:
"You can support Postwoman development via the following methods:",
one_time_recurring: "One-time or recurring",
one_time: "One-time",
recurring: "Recurring",
wiki: "Wiki",
error: "Error",
go_home: "Go Home",
reload: "Reload",
enter_curl: "Enter cURL",
empty: "Empty",
extensions: "Extensions",
extensions_use_toggle:
"Use the browser extension to send requests (if present)",
extensions_info1: "Browser extension that simplifies access to Postwoman",
extensions_info2: "Get Postwoman browser extension!",
installed: "Installed",
login_with: "Login with",
logged_out: "Logged out",
logout: "Logout",
account: "Account",
scrollInto_use_toggle: "Auto scroll",
sync: "Sync",
syncHistory: "History",
syncCollections: "Collections",
syncEnvironments: "Environments",
turn_on: "Turn on",
login_first: "Login first",
paste_a_note: "Paste a note",
import_from_sync: "Import from Sync",
notes: "Notes"
};
'If you have enjoyed the productivity of using Postwoman, consider donating as a sign of appreciation.',
donate_info2: 'You can support Postwoman development via the following methods:',
one_time_recurring: 'One-time or recurring',
one_time: 'One-time',
recurring: 'Recurring',
wiki: 'Wiki',
error: 'Error',
go_home: 'Go Home',
reload: 'Reload',
enter_curl: 'Enter cURL',
empty: 'Empty',
extensions: 'Extensions',
extensions_use_toggle: 'Use the browser extension to send requests (if present)',
extensions_info1: 'Browser extension that simplifies access to Postwoman',
extensions_info2: 'Get Postwoman browser extension!',
installed: 'Installed',
login_with: 'Login with',
logged_out: 'Logged out',
logout: 'Logout',
account: 'Account',
scrollInto_use_toggle: 'Auto scroll',
sync: 'Sync',
syncHistory: 'History',
syncCollections: 'Collections',
syncEnvironments: 'Environments',
turn_on: 'Turn on',
login_first: 'Login first',
paste_a_note: 'Paste a note',
import_from_sync: 'Import from Sync',
notes: 'Notes',
}

View File

@@ -1,264 +1,262 @@
export default {
home: "Inicio",
realtime: "Tiempo real",
graphql: "GraphQL",
settings: "Ajustes",
request: "Petición",
install_pwa: "Instalar PWA",
support_us: "Ayúdanos",
tweet: "Tweet",
options: "Opciones",
communication: "Comunicación",
endpoint: "Endpoint",
schema: "Esquema",
theme: "Tema",
subscribe: "Subscribirse",
choose_language: "Seleccione un idioma",
shortcuts: "Atajos",
send_request: "Enviar petición",
save_to_collections: "Guardar en las Colecciones",
copy_request_link: "Copiar enlace de la petición",
reset_request: "Reiniciar Petición",
support_us_on: "Ayúdanos en",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "Código JavaScript",
method: "Método",
path: "Ruta",
label: "Etiqueta",
again: "De nuevo",
content_type: "Tipo de Contenido",
raw_input: "Datos sin Procesar",
parameter_list: "Lista de Parámetros",
raw_request_body: "Cuerpo de la Solicitud sin Procesar",
show_code: "Mostrar el código",
hide_code: "Ocultar el código",
show_prerequest_script: "Mostrar Script pre solicitud",
hide_prerequest_script: "Ocultar Script pre solicitud",
authentication: "Autenticación",
authentication_type: "Tipo de autenticación",
include_in_url: "Incluir en el URL",
parameters: "Parámetros",
expand_response: "Ampliar Respuesta",
collapse_response: "Contraer Respuesta",
hide_preview: "Ocultar la vista previa",
preview_html: "Vista Previa del HTML",
history: "Historial",
collections: "Colecciones",
import_curl: "Importar cURL",
import: "Importar",
generate_code: "Generar código",
request_type: "Tipo de Petición",
generated_code: "Código Generado",
status: "Estado",
headers: "Cabeceras",
websocket: "WebSocket",
waiting_for_connection: "(esperando por conexión)",
message: "Mensaje",
sse: "SSE",
server: "Servidor",
events: "Eventos",
url: "URL",
get_schema: "Obtener esquema",
header_list: "Lista de Cabeceras",
add_new: "Agregar nuevo",
response: "Respuesta",
query: "Consulta",
queries: "Consultas",
query_variables: "Variables",
mutations: "Mutaciones",
subscriptions: "Subscripciones",
types: "Tipos",
send: "Enviar",
background: "Fondo",
color: "Color",
labels: "Etiquetas",
multi_color: "Multicolor",
enabled: "Habilitado",
disabled: "Deshabilitado",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
read_the: "Leer la",
apollotv_privacy_policy: "Política de Privacidad de ApolloTV",
contact_us: "Contáctenos",
connect: "Conectar",
disconnect: "Desconectar",
start: "Comienzo",
stop: "Detener",
access_token: "Token de acceso",
token_list: "Lista de token",
get_token: "Obtener un nuevo token",
manage_token: "Gestionar el token de acceso",
save_token: "Guardar el token de acceso",
use_token: "Usar token guardado",
request_token: "Petición del token",
save_token_req: "Guardar la petición del token",
manage_token_req: "Gestionar la petición del token",
use_token_req: "Usar el token de la petición",
token_req_name: "Nombre de la petición",
token_req_details: "Petición de detalles",
token_name: "Nombre del token",
oidc_discovery_url: "URL de descubrimiento de OIDC",
auth_url: "URL de autenticación",
access_token_url: "URL de token de acceso",
client_id: "ID del cliente",
scope: "Alcance",
state: "Estado",
token_req_list: "Lista de solicitud de token",
no_path: "Sin ruta",
no_label: "Sin etiqueta",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "Script sin pre-requisito",
search: "buscar historial",
history_empty: "Historial vacío",
history_deleted: "Historial borrado",
clear: "Limpiar",
clear_all: "Limpiar todo",
cleared: "Limpiado",
close: "Cerrar",
sort: "Ordenar",
time: "Tiempo",
duration: "Duración",
no_duration: "Sin duración",
show_more: "Mostrar más",
hide_more: "Ocultar más",
collection: "Colección",
current_collection: "Actual colección",
select_collection: "Seleccionar una colección",
create_collection: "Crear una colección",
new: "Nuevo",
import_export: "Importar / Exportar",
more: "Más",
folder: "Directorio",
new_folder: "Nuevo directorio",
my_new_folder: "Mi nuevo directorio",
folder_empty: "Directorio vacío",
edit_folder: "Editar directorio",
edit: "Editar",
delete: "Borrar",
deleted: "Borrado",
undo: "Deshacer",
collection_empty: "Colección vacía",
new_collection: "Nueva colección",
my_new_collection: "Mi nueva colección",
edit_collection: "Editar colección",
edit_request: "Editar petición",
save_request_as: "Guardar petición como",
export: "Exportar",
connecting_to: "Conectando a {name}...",
connected: "Conectado",
connected_to: "Conectado a {name}",
disconnected: "Desconectado",
disconnected_from: "Desconectado desde {name}",
something_went_wrong: "Algo ha salido mal!",
error_occurred: "Ha ocurrido un error.",
home: 'Inicio',
realtime: 'Tiempo real',
graphql: 'GraphQL',
settings: 'Ajustes',
request: 'Petición',
install_pwa: 'Instalar PWA',
support_us: 'Ayúdanos',
tweet: 'Tweet',
options: 'Opciones',
communication: 'Comunicación',
endpoint: 'Endpoint',
schema: 'Esquema',
theme: 'Tema',
subscribe: 'Subscribirse',
choose_language: 'Seleccione un idioma',
shortcuts: 'Atajos',
send_request: 'Enviar petición',
save_to_collections: 'Guardar en las Colecciones',
copy_request_link: 'Copiar enlace de la petición',
reset_request: 'Reiniciar Petición',
support_us_on: 'Ayúdanos en',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'Código JavaScript',
method: 'Método',
path: 'Ruta',
label: 'Etiqueta',
again: 'De nuevo',
content_type: 'Tipo de Contenido',
raw_input: 'Datos sin Procesar',
parameter_list: 'Lista de Parámetros',
raw_request_body: 'Cuerpo de la Solicitud sin Procesar',
show_code: 'Mostrar el código',
hide_code: 'Ocultar el código',
show_prerequest_script: 'Mostrar Script pre solicitud',
hide_prerequest_script: 'Ocultar Script pre solicitud',
authentication: 'Autenticación',
authentication_type: 'Tipo de autenticación',
include_in_url: 'Incluir en el URL',
parameters: 'Parámetros',
expand_response: 'Ampliar Respuesta',
collapse_response: 'Contraer Respuesta',
hide_preview: 'Ocultar la vista previa',
preview_html: 'Vista Previa del HTML',
history: 'Historial',
collections: 'Colecciones',
import_curl: 'Importar cURL',
import: 'Importar',
generate_code: 'Generar código',
request_type: 'Tipo de Petición',
generated_code: 'Código Generado',
status: 'Estado',
headers: 'Cabeceras',
websocket: 'WebSocket',
waiting_for_connection: '(esperando por conexión)',
message: 'Mensaje',
sse: 'SSE',
server: 'Servidor',
events: 'Eventos',
url: 'URL',
get_schema: 'Obtener esquema',
header_list: 'Lista de Cabeceras',
add_new: 'Agregar nuevo',
response: 'Respuesta',
query: 'Consulta',
queries: 'Consultas',
query_variables: 'Variables',
mutations: 'Mutaciones',
subscriptions: 'Subscripciones',
types: 'Tipos',
send: 'Enviar',
background: 'Fondo',
color: 'Color',
labels: 'Etiquetas',
multi_color: 'Multicolor',
enabled: 'Habilitado',
disabled: 'Deshabilitado',
proxy: 'Proxy',
postwoman_official_proxy_hosting: 'Proxy Oficial de Postwoman está hospedado en ApolloTV.',
read_the: 'Leer la',
apollotv_privacy_policy: 'Política de Privacidad de ApolloTV',
contact_us: 'Contáctenos',
connect: 'Conectar',
disconnect: 'Desconectar',
start: 'Comienzo',
stop: 'Detener',
access_token: 'Token de acceso',
token_list: 'Lista de token',
get_token: 'Obtener un nuevo token',
manage_token: 'Gestionar el token de acceso',
save_token: 'Guardar el token de acceso',
use_token: 'Usar token guardado',
request_token: 'Petición del token',
save_token_req: 'Guardar la petición del token',
manage_token_req: 'Gestionar la petición del token',
use_token_req: 'Usar el token de la petición',
token_req_name: 'Nombre de la petición',
token_req_details: 'Petición de detalles',
token_name: 'Nombre del token',
oidc_discovery_url: 'URL de descubrimiento de OIDC',
auth_url: 'URL de autenticación',
access_token_url: 'URL de token de acceso',
client_id: 'ID del cliente',
scope: 'Alcance',
state: 'Estado',
token_req_list: 'Lista de solicitud de token',
no_path: 'Sin ruta',
no_label: 'Sin etiqueta',
prerequest_script: 'Pre-Request Script',
no_prerequest_script: 'Script sin pre-requisito',
search: 'buscar historial',
history_empty: 'Historial vacío',
history_deleted: 'Historial borrado',
clear: 'Limpiar',
clear_all: 'Limpiar todo',
cleared: 'Limpiado',
close: 'Cerrar',
sort: 'Ordenar',
time: 'Tiempo',
duration: 'Duración',
no_duration: 'Sin duración',
show_more: 'Mostrar más',
hide_more: 'Ocultar más',
collection: 'Colección',
current_collection: 'Actual colección',
select_collection: 'Seleccionar una colección',
create_collection: 'Crear una colección',
new: 'Nuevo',
import_export: 'Importar / Exportar',
more: 'Más',
folder: 'Directorio',
new_folder: 'Nuevo directorio',
my_new_folder: 'Mi nuevo directorio',
folder_empty: 'Directorio vacío',
edit_folder: 'Editar directorio',
edit: 'Editar',
delete: 'Borrar',
deleted: 'Borrado',
undo: 'Deshacer',
collection_empty: 'Colección vacía',
new_collection: 'Nueva colección',
my_new_collection: 'Mi nueva colección',
edit_collection: 'Editar colección',
edit_request: 'Editar petición',
save_request_as: 'Guardar petición como',
export: 'Exportar',
connecting_to: 'Conectando a {name}...',
connected: 'Conectado',
connected_to: 'Conectado a {name}',
disconnected: 'Desconectado',
disconnected_from: 'Desconectado desde {name}',
something_went_wrong: 'Algo ha salido mal!',
error_occurred: 'Ha ocurrido un error.',
browser_support_sse:
"Este navegador parace no tener soporte a los eventos enviados desde el servidor.",
log: "Bitácora",
no_url: "Sin URL",
run_query: "Ejecutar consulta",
copy_query: "Copiar consulta",
kinda_dark: "Un poco oscúro",
clearly_white: "Claramento blanco",
just_black: "Solo Negro",
auto_system: "Autenticación (sistema)",
green: "Verde",
yellow: "Amarillo",
pink: "Rosado",
red: "Rojo",
purple: "Púrpura",
orange: "Anaranjado",
cyan: "Cian",
blue: "Azul",
loading: "Cargando...",
fetching: "Recuperando...",
waiting_send_req: "(esperando para enviar la petición)",
cancel: "Cancelar",
save: "Guardar",
dismiss: "Descartar",
are_you_sure: "Está seguro?",
yes: "",
no: "No",
restore: "Restaurar",
add_star: "Agregar estrella",
remove_star: "Eliminar estrella",
nothing_found: "No se encontró nada",
replace_current: "Reemplaza el actual",
replace_json: "Reemplazar con JSON",
preserve_current: "Preservar el actual",
import_json: "Importar desde JSON",
download_file: "Descargar archivo",
upload_file: "Cargar archivo",
copy_response: "Copiar respuesta",
copy_code: "Copiar codigo",
copy_schema: "Copiar Esquema",
use_request: "Usar la petición",
documentation: "Documentación",
docs: "Documentos",
reset_default: "Reiniciar valores por defecto",
fields: "CAMPOS",
deprecated: "OBSOLETO",
add_one_header: "(agregar al menos una cabecera)",
add_one_parameter: "(agregar al menos un parámetro)",
header_count: "cabecera {count}",
parameter_count: "parámetro {count}",
variable_count: "variable {count}",
value_count: "valor {count}",
send_request_first: "Enviar primero la petición",
generate_docs: "Generar la Documentación",
'Este navegador parace no tener soporte a los eventos enviados desde el servidor.',
log: 'Bitácora',
no_url: 'Sin URL',
run_query: 'Ejecutar consulta',
copy_query: 'Copiar consulta',
kinda_dark: 'Un poco oscúro',
clearly_white: 'Claramento blanco',
just_black: 'Solo Negro',
auto_system: 'Autenticación (sistema)',
green: 'Verde',
yellow: 'Amarillo',
pink: 'Rosado',
red: 'Rojo',
purple: 'Púrpura',
orange: 'Anaranjado',
cyan: 'Cian',
blue: 'Azul',
loading: 'Cargando...',
fetching: 'Recuperando...',
waiting_send_req: '(esperando para enviar la petición)',
cancel: 'Cancelar',
save: 'Guardar',
dismiss: 'Descartar',
are_you_sure: 'Está seguro?',
yes: '',
no: 'No',
restore: 'Restaurar',
add_star: 'Agregar estrella',
remove_star: 'Eliminar estrella',
nothing_found: 'No se encontró nada',
replace_current: 'Reemplaza el actual',
replace_json: 'Reemplazar con JSON',
preserve_current: 'Preservar el actual',
import_json: 'Importar desde JSON',
download_file: 'Descargar archivo',
upload_file: 'Cargar archivo',
copy_response: 'Copiar respuesta',
copy_code: 'Copiar codigo',
copy_schema: 'Copiar Esquema',
use_request: 'Usar la petición',
documentation: 'Documentación',
docs: 'Documentos',
reset_default: 'Reiniciar valores por defecto',
fields: 'CAMPOS',
deprecated: 'OBSOLETO',
add_one_header: '(agregar al menos una cabecera)',
add_one_parameter: '(agregar al menos un parámetro)',
header_count: 'cabecera {count}',
parameter_count: 'parámetro {count}',
variable_count: 'variable {count}',
value_count: 'valor {count}',
send_request_first: 'Enviar primero la petición',
generate_docs: 'Generar la Documentación',
generate_docs_message:
"Importar cualquier Colección de Postwoman para Generar la Documentación sobre la marcha.",
generate_docs_first: "Generar primero la documentación",
docs_generated: "Documentación generada",
import_collections: "Importar colecciones",
optional: "(opcional)",
json: "JSON",
none: "Nada",
username: "Nombre de usuario",
password: "Contrasaeña",
token: "Token",
payload: "Carga",
choose_file: "Seleccione un archivo",
file_imported: "Archivo imporado",
f12_details: "(F12 para ver detalles)",
we_use_cookies: "Usamos las cookies",
copied_to_clipboard: "Copiado al portapapeles",
finished_in: "Terminado en {duration}ms",
check_console_details: "Verifique la consola para más detalles.",
download_started: "Inició la descarga",
url_invalid_format: "La URL no está formateado apropiadamente",
curl_invalid_format: "El cURL no está formateado apropiadamente",
enable_proxy: "Pruebe habilitando el Proxy",
complete_config_urls: "Por favor, termine la configuración de las urls.",
token_request_saved: "La petición de tToken ha sido guardada",
'Importar cualquier Colección de Postwoman para Generar la Documentación sobre la marcha.',
generate_docs_first: 'Generar primero la documentación',
docs_generated: 'Documentación generada',
import_collections: 'Importar colecciones',
optional: '(opcional)',
json: 'JSON',
none: 'Nada',
username: 'Nombre de usuario',
password: 'Contrasaeña',
token: 'Token',
payload: 'Carga',
choose_file: 'Seleccione un archivo',
file_imported: 'Archivo imporado',
f12_details: '(F12 para ver detalles)',
we_use_cookies: 'Usamos las cookies',
copied_to_clipboard: 'Copiado al portapapeles',
finished_in: 'Terminado en {duration}ms',
check_console_details: 'Verifique la consola para más detalles.',
download_started: 'Inició la descarga',
url_invalid_format: 'La URL no está formateado apropiadamente',
curl_invalid_format: 'El cURL no está formateado apropiadamente',
enable_proxy: 'Pruebe habilitando el Proxy',
complete_config_urls: 'Por favor, termine la configuración de las urls.',
token_request_saved: 'La petición de tToken ha sido guardada',
donate_info1:
"Si le ha gustado su productividad usando Postwoman, considere hacer una donación como un signo de su apreciación.",
donate_info2:
"Puede ayudar al desarrollo de Postwoman mediante los siguientes métodos:",
one_time_recurring: "Una vez o recurrente",
one_time: "Una vez",
recurring: "Recurrente",
wiki: "Wiki",
error: "Error",
go_home: "Ir al inicio",
reload: "Recargar",
enter_curl: "Intruduzca cURL",
empty: "Vacío",
extensions: "Extensiones",
extensions_info1: "Extensión del navegador que simplifica el acceso a Postwoman",
extensions_info2: "Obtener la extensión del navegador de Postwoman!",
installed: "Instalado",
login_with: "Iniciar sesión con",
logged_out: "Sesión cerreda",
logout: "Cerrar sesión",
account: "Cuenta",
sync: "Sync",
syncHistory: "Historial",
syncCollections: "Colecciones",
turn_on: "Encender",
login_first: "Inicie sesión primero",
paste_a_collection: "Pegar una Colección",
import_from_sync: "Importar desde Sync"
};
'Si le ha gustado su productividad usando Postwoman, considere hacer una donación como un signo de su apreciación.',
donate_info2: 'Puede ayudar al desarrollo de Postwoman mediante los siguientes métodos:',
one_time_recurring: 'Una vez o recurrente',
one_time: 'Una vez',
recurring: 'Recurrente',
wiki: 'Wiki',
error: 'Error',
go_home: 'Ir al inicio',
reload: 'Recargar',
enter_curl: 'Intruduzca cURL',
empty: 'Vacío',
extensions: 'Extensiones',
extensions_info1: 'Extensión del navegador que simplifica el acceso a Postwoman',
extensions_info2: 'Obtener la extensión del navegador de Postwoman!',
installed: 'Instalado',
login_with: 'Iniciar sesión con',
logged_out: 'Sesión cerreda',
logout: 'Cerrar sesión',
account: 'Cuenta',
sync: 'Sync',
syncHistory: 'Historial',
syncCollections: 'Colecciones',
turn_on: 'Encender',
login_first: 'Inicie sesión primero',
paste_a_collection: 'Pegar una Colección',
import_from_sync: 'Importar desde Sync',
}

View File

@@ -1,90 +1,89 @@
export default {
home: "خانه",
realtime: "بلادرنگ",
graphql: "GraphQL",
settings: "تنظیمات",
request: "درخواست",
install_pwa: "نصب PWA",
support_us: "از ما حمایت کنید",
tweet: "Tweet",
options: "گزینه‌ها",
communication: "ارتباط",
endpoint: "Endpoint",
schema: "Schema",
theme: "پوسته",
subscribe: "اشتراک",
choose_language: "تغییر زبان",
shortcuts: "میانبرها",
send_request: "ارسال درخواست",
save_to_collections: "ذخیره در کلکسیون",
copy_request_link: "کپی لینک درخواست",
reset_request: "بازنشانی درخواست",
support_us_on: "حمایت از ما از طریق",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "کد JavaScript",
method: "متد",
path: "مسیر",
label: "برچسب",
again: "دوباره",
content_type: "Content Type",
raw_input: "ورودی raw",
parameter_list: "لیست پارامترها",
raw_request_body: "Raw Request Body",
show_code: "نمایش کد",
hide_code: "عدم نمایش کد",
show_prerequest_script: "Show Pre-Request Script",
hide_prerequest_script: "Hide Pre-Request Script",
authentication: "Authentication",
authentication_type: "Authentication type",
include_in_url: "در URL گنجانده شود",
parameters: "پارامترها",
expand_response: "نمایش کامل پاسخ",
collapse_response: "نمایش مختصر پاسخ",
hide_preview: "مخفی کردن نمایش",
preview_html: "نمایش HTML",
history: "تاریخچه",
collections: "کلکسیون",
import_curl: "وارد کردن cURL",
import: "وارد کردن",
generate_code: "تولید کد",
request_type: "Request type",
generated_code: "کد تولید شده",
status: "Status",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(منتظر برقراری اتصال)",
message: "پیام",
sse: "SSE",
server: "سرور",
events: "رویداد",
url: "URL",
get_schema: "دریافت Schema",
header_list: "لیست Header",
add_new: "افزودن",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Subscriptions",
types: "Types",
send: "ارسال",
background: "پس زمینه",
color: "رنگ",
labels: "برچسب‌ها",
multi_color: "چند رنگی",
enabled: "فعال",
disabled: "غیر فعال",
proxy: "پراکسی",
postwoman_official_proxy_hosting:
"پراکسی Postwoman برروی هاست ApolloTV قرار دارد.",
read_the: "بخوانید",
apollotv_privacy_policy: "خط مشی رازداری ApolloTV",
contact_us: "Contact us",
connect: "Connect",
disconnect: "Disconnect",
start: "Start",
stop: "Stop"
};
home: 'خانه',
realtime: 'بلادرنگ',
graphql: 'GraphQL',
settings: 'تنظیمات',
request: 'درخواست',
install_pwa: 'نصب PWA',
support_us: 'از ما حمایت کنید',
tweet: 'Tweet',
options: 'گزینه‌ها',
communication: 'ارتباط',
endpoint: 'Endpoint',
schema: 'Schema',
theme: 'پوسته',
subscribe: 'اشتراک',
choose_language: 'تغییر زبان',
shortcuts: 'میانبرها',
send_request: 'ارسال درخواست',
save_to_collections: 'ذخیره در کلکسیون',
copy_request_link: 'کپی لینک درخواست',
reset_request: 'بازنشانی درخواست',
support_us_on: 'حمایت از ما از طریق',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'کد JavaScript',
method: 'متد',
path: 'مسیر',
label: 'برچسب',
again: 'دوباره',
content_type: 'Content Type',
raw_input: 'ورودی raw',
parameter_list: 'لیست پارامترها',
raw_request_body: 'Raw Request Body',
show_code: 'نمایش کد',
hide_code: 'عدم نمایش کد',
show_prerequest_script: 'Show Pre-Request Script',
hide_prerequest_script: 'Hide Pre-Request Script',
authentication: 'Authentication',
authentication_type: 'Authentication type',
include_in_url: 'در URL گنجانده شود',
parameters: 'پارامترها',
expand_response: 'نمایش کامل پاسخ',
collapse_response: 'نمایش مختصر پاسخ',
hide_preview: 'مخفی کردن نمایش',
preview_html: 'نمایش HTML',
history: 'تاریخچه',
collections: 'کلکسیون',
import_curl: 'وارد کردن cURL',
import: 'وارد کردن',
generate_code: 'تولید کد',
request_type: 'Request type',
generated_code: 'کد تولید شده',
status: 'Status',
headers: 'Headers',
websocket: 'WebSocket',
waiting_for_connection: '(منتظر برقراری اتصال)',
message: 'پیام',
sse: 'SSE',
server: 'سرور',
events: 'رویداد',
url: 'URL',
get_schema: 'دریافت Schema',
header_list: 'لیست Header',
add_new: 'افزودن',
response: 'Response',
query: 'Query',
queries: 'Queries',
query_variables: 'Variables',
mutations: 'Mutations',
subscriptions: 'Subscriptions',
types: 'Types',
send: 'ارسال',
background: 'پس زمینه',
color: 'رنگ',
labels: 'برچسب‌ها',
multi_color: 'چند رنگی',
enabled: 'فعال',
disabled: 'غیر فعال',
proxy: 'پراکسی',
postwoman_official_proxy_hosting: 'پراکسی Postwoman برروی هاست ApolloTV قرار دارد.',
read_the: 'بخوانید',
apollotv_privacy_policy: 'خط مشی رازداری ApolloTV',
contact_us: 'Contact us',
connect: 'Connect',
disconnect: 'Disconnect',
start: 'Start',
stop: 'Stop',
}

View File

@@ -1,264 +1,262 @@
export default {
home: "Accueil",
realtime: "Temps réel",
graphql: "GraphQL",
settings: "Paramètres",
request: "Request",
install_pwa: "Installer la PWA",
support_us: "Nous supporter",
tweet: "Tweeter",
options: "Options",
communication: "Communication",
endpoint: "Endpoint",
schema: "Schéma",
theme: "Thème",
home: 'Accueil',
realtime: 'Temps réel',
graphql: 'GraphQL',
settings: 'Paramètres',
request: 'Request',
install_pwa: 'Installer la PWA',
support_us: 'Nous supporter',
tweet: 'Tweeter',
options: 'Options',
communication: 'Communication',
endpoint: 'Endpoint',
schema: 'Schéma',
theme: 'Thème',
subscribe: "S'inscrire",
choose_language: "Sélectionner une langue",
shortcuts: "Raccourcis",
send_request: "Envoyer la requête",
save_to_collections: "Sauvegarder dans les collections",
copy_request_link: "Copier le lien de la requête",
reset_request: "Réinitialiser la requête",
support_us_on: "Supportez-nous sur",
open_collective: "Ouvrir Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "Code JavaScript",
method: "Méthode",
choose_language: 'Sélectionner une langue',
shortcuts: 'Raccourcis',
send_request: 'Envoyer la requête',
save_to_collections: 'Sauvegarder dans les collections',
copy_request_link: 'Copier le lien de la requête',
reset_request: 'Réinitialiser la requête',
support_us_on: 'Supportez-nous sur',
open_collective: 'Ouvrir Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'Code JavaScript',
method: 'Méthode',
path: "Chemin d'accès",
label: "Libellé",
again: "Réessayer",
content_type: "Type de contenu",
raw_input: "Texte brut",
parameter_list: "Liste des paramètres",
raw_request_body: "Corps de la requête en texte brut",
show_code: "Afficher le code",
hide_code: "Masquer le code",
show_prerequest_script: "Afficher le script de pré-requête",
hide_prerequest_script: "Masquer le script de pré-requête",
authentication: "Authentification",
label: 'Libellé',
again: 'Réessayer',
content_type: 'Type de contenu',
raw_input: 'Texte brut',
parameter_list: 'Liste des paramètres',
raw_request_body: 'Corps de la requête en texte brut',
show_code: 'Afficher le code',
hide_code: 'Masquer le code',
show_prerequest_script: 'Afficher le script de pré-requête',
hide_prerequest_script: 'Masquer le script de pré-requête',
authentication: 'Authentification',
authentication_type: "Type d'authentification",
include_in_url: "Inclure dans l'URL",
parameters: "Paramètres",
expand_response: "Agrandir la réponse",
collapse_response: "Réduire la réponse",
hide_preview: "Masquer la prévisualisation",
preview_html: "Prévisualiser le HTML",
history: "Historique",
collections: "Collections",
import_curl: "Importer en cURL",
importer: "Importer",
generate_code: "Générer le code",
request_type: "Type de requête",
generated_code: "Code généré",
status: "Statut",
headers: "En-têtes",
websocket: "WebSocket",
waiting_for_connection: "(en attente de connexion)",
message: "Message",
sse: "SSE",
server: "Serveur",
events: "Évènements",
url: "URL",
get_schema: "Récuperer le schéma",
parameters: 'Paramètres',
expand_response: 'Agrandir la réponse',
collapse_response: 'Réduire la réponse',
hide_preview: 'Masquer la prévisualisation',
preview_html: 'Prévisualiser le HTML',
history: 'Historique',
collections: 'Collections',
import_curl: 'Importer en cURL',
importer: 'Importer',
generate_code: 'Générer le code',
request_type: 'Type de requête',
generated_code: 'Code généré',
status: 'Statut',
headers: 'En-têtes',
websocket: 'WebSocket',
waiting_for_connection: '(en attente de connexion)',
message: 'Message',
sse: 'SSE',
server: 'Serveur',
events: 'Évènements',
url: 'URL',
get_schema: 'Récuperer le schéma',
header_list: "Liste d'en-têtes",
add_new: "Ajouter",
response: "Réponse",
query: "Requête",
queries: "Requêtes",
query_variables: "Variables",
mutations: "Mutations",
subscriptions: "Abonnements",
types: "Types",
send: "Envoyer",
background: "Arrière-plan",
color: "Couleur",
labels: "Libellés",
multi_color: "Multi-couleurs",
enabled: "Activé",
disabled: "Désactivé",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Le proxy officiel de Postwoman est hébergé par ApolloTV.",
read_the: "Lire la",
apollotv_privacy_policy: "politique de confidentialité ApolloTV",
contact_us: "Contactez nous",
connect: "Relier",
disconnect: "Déconnecter",
start: "Début",
stop: "Arrêtez",
add_new: 'Ajouter',
response: 'Réponse',
query: 'Requête',
queries: 'Requêtes',
query_variables: 'Variables',
mutations: 'Mutations',
subscriptions: 'Abonnements',
types: 'Types',
send: 'Envoyer',
background: 'Arrière-plan',
color: 'Couleur',
labels: 'Libellés',
multi_color: 'Multi-couleurs',
enabled: 'Activé',
disabled: 'Désactivé',
proxy: 'Proxy',
postwoman_official_proxy_hosting: 'Le proxy officiel de Postwoman est hébergé par ApolloTV.',
read_the: 'Lire la',
apollotv_privacy_policy: 'politique de confidentialité ApolloTV',
contact_us: 'Contactez nous',
connect: 'Relier',
disconnect: 'Déconnecter',
start: 'Début',
stop: 'Arrêtez',
access_token: "Token d'accès",
token_list: "Liste des Tokens",
get_token: "Obtenir un nouveau Token",
manage_token: "Gérer le Token",
save_token: "Sauvegarder le Token",
use_token: "Utiliser un Token",
request_token: "Demander un Token",
save_token_req: "Sauvegarder la requête ",
manage_token_req: "Gérer la requête avec Token",
use_token_req: "Utiliser la requête avec Token",
token_req_name: "Nom de la requête",
token_req_details: "Détails de la requête",
token_name: "Nom du Token",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "Auth URL",
token_list: 'Liste des Tokens',
get_token: 'Obtenir un nouveau Token',
manage_token: 'Gérer le Token',
save_token: 'Sauvegarder le Token',
use_token: 'Utiliser un Token',
request_token: 'Demander un Token',
save_token_req: 'Sauvegarder la requête ',
manage_token_req: 'Gérer la requête avec Token',
use_token_req: 'Utiliser la requête avec Token',
token_req_name: 'Nom de la requête',
token_req_details: 'Détails de la requête',
token_name: 'Nom du Token',
oidc_discovery_url: 'OIDC Discovery URL',
auth_url: 'Auth URL',
access_token_url: "URL du Token d'accès",
client_id: "Client ID",
scope: "Scope",
state: "État",
token_req_list: "Liste des requêtes avec Token",
no_path: "Aucun chemin",
no_label: "Aucun label",
prerequest_script: "Pre-Request Script",
no_prerequest_script: "No pre-request script",
search: "Historique de la recherche",
client_id: 'Client ID',
scope: 'Scope',
state: 'État',
token_req_list: 'Liste des requêtes avec Token',
no_path: 'Aucun chemin',
no_label: 'Aucun label',
prerequest_script: 'Pre-Request Script',
no_prerequest_script: 'No pre-request script',
search: 'Historique de la recherche',
history_empty: "L'historique est vide",
history_deleted: "Historique supprimé",
clear: "Nettoyer",
clear_all: "Tout nettoyer",
cleared: "Nettoyé",
close: "Fermer",
sort: "Trier",
time: "Temps",
duration: "Durée",
no_duration: "Aucune durée",
history_deleted: 'Historique supprimé',
clear: 'Nettoyer',
clear_all: 'Tout nettoyer',
cleared: 'Nettoyé',
close: 'Fermer',
sort: 'Trier',
time: 'Temps',
duration: 'Durée',
no_duration: 'Aucune durée',
show_more: "Plus d'informations",
hide_more: "Moins d'informations",
collection: "Collection",
current_collection: "Collection Actuelle",
select_collection: "Selectionner une Collection",
create_collection: "Créer une Collection",
new: "Nouveau",
import_export: "Importer / Exporter",
more: "Plus",
folder: "Dossier",
new_folder: "Nouveau Dossier",
my_new_folder: "Mon Nouveau Dossier",
folder_empty: "Ce Dossier est vide",
edit_folder: "Éditer le Dossier",
edit: "Éditer",
delete: "Supprimer",
deleted: "Supprimé",
undo: "Annuler",
collection_empty: "Cette Collection est vide",
new_collection: "Nouvelle Collection",
my_new_collection: "Ma Nouvelle Collection",
edit_collection: "Éditer la Collection",
edit_request: "Éditer ma requête",
save_request_as: "Sauvegarder ma requête sous",
export: "Exporter",
connecting_to: "Connexion à {name}...",
connected: "Connecté",
connected_to: "Connecté à {name}",
disconnected: "Déconnecté",
disconnected_from: "Déconnecté sur {name}",
collection: 'Collection',
current_collection: 'Collection Actuelle',
select_collection: 'Selectionner une Collection',
create_collection: 'Créer une Collection',
new: 'Nouveau',
import_export: 'Importer / Exporter',
more: 'Plus',
folder: 'Dossier',
new_folder: 'Nouveau Dossier',
my_new_folder: 'Mon Nouveau Dossier',
folder_empty: 'Ce Dossier est vide',
edit_folder: 'Éditer le Dossier',
edit: 'Éditer',
delete: 'Supprimer',
deleted: 'Supprimé',
undo: 'Annuler',
collection_empty: 'Cette Collection est vide',
new_collection: 'Nouvelle Collection',
my_new_collection: 'Ma Nouvelle Collection',
edit_collection: 'Éditer la Collection',
edit_request: 'Éditer ma requête',
save_request_as: 'Sauvegarder ma requête sous',
export: 'Exporter',
connecting_to: 'Connexion à {name}...',
connected: 'Connecté',
connected_to: 'Connecté à {name}',
disconnected: 'Déconnecté',
disconnected_from: 'Déconnecté sur {name}',
something_went_wrong: "Quelque chose n'a pas marché!",
error_occurred: "Une erreur s'est produite.",
browser_support_sse:
"Ce navigateur ne semble pas prendre en charge les événements envoyés par le serveur.",
log: "Log",
no_url: "Aucune URL",
run_query: "Lancer une recherche",
copy_query: "Copier la recherche",
kinda_dark: "Plutôt Sombre",
clearly_white: "Clairement Blanc",
just_black: "Seulement Noir",
auto_system: "Auth (système)",
green: "Vert",
yellow: "Jaune",
pink: "Rose",
red: "Rouge",
purple: "Violet",
orange: "Orange",
cyan: "Cyan",
blue: "Bleue",
loading: "Chargement...",
fetching: "Récupération...",
'Ce navigateur ne semble pas prendre en charge les événements envoyés par le serveur.',
log: 'Log',
no_url: 'Aucune URL',
run_query: 'Lancer une recherche',
copy_query: 'Copier la recherche',
kinda_dark: 'Plutôt Sombre',
clearly_white: 'Clairement Blanc',
just_black: 'Seulement Noir',
auto_system: 'Auth (système)',
green: 'Vert',
yellow: 'Jaune',
pink: 'Rose',
red: 'Rouge',
purple: 'Violet',
orange: 'Orange',
cyan: 'Cyan',
blue: 'Bleue',
loading: 'Chargement...',
fetching: 'Récupération...',
waiting_send_req: "(en attente de l'envoi de la demande)",
cancel: "Annuler",
save: "Sauvarder",
dismiss: "Dismiss",
are_you_sure: "Êtes-vous sûr?",
yes: "Oui",
no: "Non",
restore: "Restaurer",
add_star: "Ajouter une étoile",
remove_star: "Supprimer une étoile",
cancel: 'Annuler',
save: 'Sauvarder',
dismiss: 'Dismiss',
are_you_sure: 'Êtes-vous sûr?',
yes: 'Oui',
no: 'Non',
restore: 'Restaurer',
add_star: 'Ajouter une étoile',
remove_star: 'Supprimer une étoile',
nothing_found: "Rien n'a été trouvé",
replace_current: "Remplacer l'actuel",
replace_json: "Replacer avec du JSON",
replace_json: 'Replacer avec du JSON',
preserve_current: "Conserver l'actuel",
import_json: "Importer depuis un JSON",
download_file: "Télécharger un fichier",
upload_file: "Charger un fichier",
copy_response: "Copier la réponse",
copy_code: "Copier le code",
copy_schema: "Copier le Schéma",
use_request: "Utiliser cette requête",
documentation: "Documentation",
docs: "Docs",
reset_default: "Rétablir la valeur par défaut",
fields: "CHAMPS",
deprecated: "DÉPRÉCIÉ",
add_one_header: "(ajouter au moins un en-tête)",
add_one_parameter: "(ajouter au moins un paramètre)",
header_count: "{count} en-tête",
parameter_count: "{count} paramètre",
variable_count: "{count} variable",
value_count: "{count} valeur",
import_json: 'Importer depuis un JSON',
download_file: 'Télécharger un fichier',
upload_file: 'Charger un fichier',
copy_response: 'Copier la réponse',
copy_code: 'Copier le code',
copy_schema: 'Copier le Schéma',
use_request: 'Utiliser cette requête',
documentation: 'Documentation',
docs: 'Docs',
reset_default: 'Rétablir la valeur par défaut',
fields: 'CHAMPS',
deprecated: 'DÉPRÉCIÉ',
add_one_header: '(ajouter au moins un en-tête)',
add_one_parameter: '(ajouter au moins un paramètre)',
header_count: '{count} en-tête',
parameter_count: '{count} paramètre',
variable_count: '{count} variable',
value_count: '{count} valeur',
send_request_first: "Envoyez d'abord une requête",
generate_docs: "Genérer une Documentation",
generate_docs: 'Genérer une Documentation',
generate_docs_message:
"Importer n'importe quelle collection de Postwoman pour générer de la documentation en déplacement.",
generate_docs_first: "Générer la documentation d'abord",
docs_generated: "Documentation générée",
import_collections: "Importer les collections",
optional: "(optionnel)",
json: "JSON",
none: "Aucun",
username: "Username",
password: "Password",
token: "Token",
payload: "Payload",
choose_file: "Choisir un fichier",
file_imported: "Fichier importé",
f12_details: "(F12 pour voir les détails)",
we_use_cookies: "Nous utilisons des cookies",
copied_to_clipboard: "Copié dans le presse-papier",
finished_in: "Fini en {duration}ms",
check_console_details: "Consultez la console pour plus de détails.",
download_started: "Téléchargement démarré",
docs_generated: 'Documentation générée',
import_collections: 'Importer les collections',
optional: '(optionnel)',
json: 'JSON',
none: 'Aucun',
username: 'Username',
password: 'Password',
token: 'Token',
payload: 'Payload',
choose_file: 'Choisir un fichier',
file_imported: 'Fichier importé',
f12_details: '(F12 pour voir les détails)',
we_use_cookies: 'Nous utilisons des cookies',
copied_to_clipboard: 'Copié dans le presse-papier',
finished_in: 'Fini en {duration}ms',
check_console_details: 'Consultez la console pour plus de détails.',
download_started: 'Téléchargement démarré',
url_invalid_format: "L'URL n'est pas formatée correctement",
curl_invalid_format: "cURL n'est pas formaté correctement",
enable_proxy: "Essayez en activant le Proxy",
complete_config_urls: "Veuillez compléter les urls de configuration.",
token_request_saved: "Requête de Token sauvegardé",
enable_proxy: 'Essayez en activant le Proxy',
complete_config_urls: 'Veuillez compléter les urls de configuration.',
token_request_saved: 'Requête de Token sauvegardé',
donate_info1:
"Si vous avez apprécié la productivité de l'utilisation de Postwoman, considérez le don comme un signe d'appréciation.",
donate_info2:
"Vous pouvez soutenir le développement de Postwoman par les méthodes suivantes :",
one_time_recurring: "Ponctuel ou récurrent",
one_time: "Une fois",
recurring: "Récurrent",
wiki: "Wiki",
error: "Erreur",
donate_info2: 'Vous pouvez soutenir le développement de Postwoman par les méthodes suivantes :',
one_time_recurring: 'Ponctuel ou récurrent',
one_time: 'Une fois',
recurring: 'Récurrent',
wiki: 'Wiki',
error: 'Erreur',
go_home: "Aller à l'accueil",
reload: "Recharger",
enter_curl: "Entrer cURL",
empty: "Vide",
extensions: "Extensions",
reload: 'Recharger',
enter_curl: 'Entrer cURL',
empty: 'Vide',
extensions: 'Extensions',
extensions_info1: "Extension pour navigateur qui simplifie l'accès à Postwoman",
extensions_info2: "Obtenez l'extension Postwoman pour navigateur !",
installed: "Installé",
login_with: "Se connecter avec",
logged_out: "Se déconnecter",
logout: "Déconnexion",
account: "Compte",
sync: "Synchroniser",
syncHistory: "Historique",
syncCollections: "Collections",
turn_on: "Activer",
installed: 'Installé',
login_with: 'Se connecter avec',
logged_out: 'Se déconnecter',
logout: 'Déconnexion',
account: 'Compte',
sync: 'Synchroniser',
syncHistory: 'Historique',
syncCollections: 'Collections',
turn_on: 'Activer',
login_first: "Se connecter d'abord",
paste_a_collection: "Coller une collection",
import_from_sync: "Importer depuis la synchronisation"
};
paste_a_collection: 'Coller une collection',
import_from_sync: 'Importer depuis la synchronisation',
}

View File

@@ -1,90 +1,89 @@
export default {
home: "Beranda",
realtime: "Waktu Nyata",
graphql: "GraphQL",
settings: "Pengaturan",
request: "Permintaan",
install_pwa: "Pasang PWA",
support_us: "Dukung kami",
tweet: "Cuitkan",
options: "Opsi",
communication: "Komunikasi",
endpoint: "Titik Akhir",
schema: "Skema",
theme: "Tema",
subscribe: "Berlangganan",
choose_language: "Pilih Bahasa",
shortcuts: "Pintasan",
send_request: "Kirim Permintaan",
save_to_collections: "Simpan ke Koleksi",
copy_request_link: "Salin Tautan Permintaan",
reset_request: "Atur Ulang Permintaan",
support_us_on: "Dukung kami di",
open_collective: "Open Collective",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "Kode Javascript",
method: "Metode",
path: "Lintasan",
label: "Label",
again: "Lagi",
content_type: "Jenis Konten",
raw_input: "Masukan mentah",
parameter_list: "Daftar parameter",
raw_request_body: "Badan Permintaan Mentah",
show_code: "Tampilkan Kode",
hide_code: "Sembunyikan Kode",
show_prerequest_script: "Tampilkan Skrip Pra-Permintaan",
hide_prerequest_script: "Sembunyikan Skrip Pra-Permintaan",
authentication: "Autentikasi",
authentication_type: "Jenis Autentikasi",
include_in_url: "Sertakan di URL",
parameters: "Parameter",
expand_response: "Bentangkan Balasan",
collapse_response: "Ciutkan Balasan",
hide_preview: "Sembunyikan Pratinjau",
preview_html: "Pratinjau HTML",
history: "Riwayat",
collections: "Koleksi",
import_curl: "Impor cURL",
import: "Impor",
generate_code: "Hasilkan kode",
request_type: "Jenis permintaan",
generated_code: "Kode yang dihasilkan",
status: "Status",
headers: "Header",
websocket: "WebSocket",
waiting_for_connection: "(Menunggu sambungan)",
message: "Pesan",
sse: "SSE",
server: "Peladen",
events: "Kejadian",
url: "URL",
get_schema: "Ambil skema",
header_list: "Daftar header",
add_new: "Tambah baru",
response: "Balasan",
query: "Kueri",
queries: "Kueri",
query_variables: "Variables",
mutations: "Mutasi",
subscriptions: "Langganan",
types: "Jenis",
send: "Kirim",
background: "Latar belakang",
color: "Warna",
labels: "Label",
multi_color: "Warna beragam",
enabled: "diaktifkan",
disabled: "dinonaktifkan",
proxy: "Proksi",
postwoman_official_proxy_hosting:
"Proksi Resmi Postwoman dalam penginangan ApolloTV.",
read_the: "Bacalah",
apollotv_privacy_policy: "kebijakan privasi ApolloTV",
contact_us: "Hubungi kami",
connect: "Menghubungkan",
disconnect: "Memutuskan",
start: "Mulai",
stop: "Berhenti"
};
home: 'Beranda',
realtime: 'Waktu Nyata',
graphql: 'GraphQL',
settings: 'Pengaturan',
request: 'Permintaan',
install_pwa: 'Pasang PWA',
support_us: 'Dukung kami',
tweet: 'Cuitkan',
options: 'Opsi',
communication: 'Komunikasi',
endpoint: 'Titik Akhir',
schema: 'Skema',
theme: 'Tema',
subscribe: 'Berlangganan',
choose_language: 'Pilih Bahasa',
shortcuts: 'Pintasan',
send_request: 'Kirim Permintaan',
save_to_collections: 'Simpan ke Koleksi',
copy_request_link: 'Salin Tautan Permintaan',
reset_request: 'Atur Ulang Permintaan',
support_us_on: 'Dukung kami di',
open_collective: 'Open Collective',
paypal: 'Paypal',
patreon: 'Patreon',
javascript_code: 'Kode Javascript',
method: 'Metode',
path: 'Lintasan',
label: 'Label',
again: 'Lagi',
content_type: 'Jenis Konten',
raw_input: 'Masukan mentah',
parameter_list: 'Daftar parameter',
raw_request_body: 'Badan Permintaan Mentah',
show_code: 'Tampilkan Kode',
hide_code: 'Sembunyikan Kode',
show_prerequest_script: 'Tampilkan Skrip Pra-Permintaan',
hide_prerequest_script: 'Sembunyikan Skrip Pra-Permintaan',
authentication: 'Autentikasi',
authentication_type: 'Jenis Autentikasi',
include_in_url: 'Sertakan di URL',
parameters: 'Parameter',
expand_response: 'Bentangkan Balasan',
collapse_response: 'Ciutkan Balasan',
hide_preview: 'Sembunyikan Pratinjau',
preview_html: 'Pratinjau HTML',
history: 'Riwayat',
collections: 'Koleksi',
import_curl: 'Impor cURL',
import: 'Impor',
generate_code: 'Hasilkan kode',
request_type: 'Jenis permintaan',
generated_code: 'Kode yang dihasilkan',
status: 'Status',
headers: 'Header',
websocket: 'WebSocket',
waiting_for_connection: '(Menunggu sambungan)',
message: 'Pesan',
sse: 'SSE',
server: 'Peladen',
events: 'Kejadian',
url: 'URL',
get_schema: 'Ambil skema',
header_list: 'Daftar header',
add_new: 'Tambah baru',
response: 'Balasan',
query: 'Kueri',
queries: 'Kueri',
query_variables: 'Variables',
mutations: 'Mutasi',
subscriptions: 'Langganan',
types: 'Jenis',
send: 'Kirim',
background: 'Latar belakang',
color: 'Warna',
labels: 'Label',
multi_color: 'Warna beragam',
enabled: 'diaktifkan',
disabled: 'dinonaktifkan',
proxy: 'Proksi',
postwoman_official_proxy_hosting: 'Proksi Resmi Postwoman dalam penginangan ApolloTV.',
read_the: 'Bacalah',
apollotv_privacy_policy: 'kebijakan privasi ApolloTV',
contact_us: 'Hubungi kami',
connect: 'Menghubungkan',
disconnect: 'Memutuskan',
start: 'Mulai',
stop: 'Berhenti',
}

View File

@@ -1,245 +1,245 @@
export default {
home: "ホーム",
realtime: "リアルタイム",
graphql: "GraphQL",
settings: "設定",
request: "リクエスト",
install_pwa: "PWAをインストール",
support_us: "寄付",
tweet: "ツイート",
options: "オプション",
communication: "通信",
endpoint: "エンドポイント",
schema: "スキーマ",
theme: "テーマ",
subscribe: "登録",
choose_language: "言語の選択",
shortcuts: "ショートカット",
send_request: "リクエストを送信",
save_to_collections: "コレクションに保存",
copy_request_link: "リクエストURLをコピー",
reset_request: "リクエストをリセット",
support_us_on: "以下より寄付",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScriptコード",
method: "メソッド",
path: "パス",
label: "ラベル",
again: "",
content_type: "Content Type",
raw_input: "Raw入力",
parameter_list: "パラメータリスト",
raw_request_body: "Rawリクエストボディー",
show_code: "コードを表示",
hide_code: "コードを非表示",
show_prerequest_script: "プレリクエストスクリプトを表示",
hide_prerequest_script: "プレリクエストスクリプトを非表示",
authentication: "認証",
authentication_type: "認証タイプ",
include_in_url: "URLに含む",
parameters: "パラメータ",
expand_response: "レスポンスを広げる",
collapse_response: "レスポンスを狭める",
hide_preview: "プレビューしない",
preview_html: "HTMLプレビュー表示",
history: "履歴",
collections: "コレクション",
import_curl: "cURLをインポート",
import: "インポート",
generate_code: "コード生成",
request_type: "リクエストタイプ",
generated_code: "生成されたコード",
status: "ステータス",
headers: "ヘッダー",
websocket: "ウェブソケット",
waiting_for_connection: "(接続待ち)",
message: "メッセージ",
sse: "SSE",
server: "サーバ",
events: "イベント",
url: "URL",
get_schema: "スキーマを取得",
header_list: "ヘッダーリスト",
add_new: "追加",
response: "レスポンス",
query: "クエリ",
queries: "クエリ",
query_variables: "変数",
mutations: "ミューテーション",
subscriptions: "サブスクリプション",
types: "タイプ",
send: "送信",
background: "背景",
color: "色",
labels: "ラベル",
multi_color: "マルチカラー",
enabled: "有効",
disabled: "無効",
proxy: "プロキシ",
postwoman_official_proxy_hosting:
"Postwomanの公式プロキシは、Apollo TVがホストしています。",
read_the: "プライバシーポリシー",
apollotv_privacy_policy: "を読む",
contact_us: "お問い合わせ",
connect: "接続",
disconnect: "切断",
start: "開始",
stop: "停止",
access_token: "アクセストークン",
token_list: "トークンリスト",
get_token: "新しいトークンを取得",
manage_token: "アクセストークンを管理",
save_token: "アクセストークンを保存",
use_token: "アクセストークンを使用",
request_token: "トークンリクエスト",
save_token_req: "トークンリクエストを保存",
manage_token_req: "トークンリクエストを管理",
use_token_req: "トークンリクエストを使用",
token_req_name: "リクエスト名",
token_req_details: "リクエスト詳細",
token_name: "トークン名",
oidc_discovery_url: "OIDC Discovery URL",
auth_url: "認証URL",
access_token_url: "アクセストークンURL",
client_id: "クライアントID",
scope: "スコープ",
state: "ステート",
token_req_list: "トークンリクエストリスト",
no_path: "パス無し",
no_label: "ラベル無し",
prerequest_script: "プレリクエストスクリプト",
no_prerequest_script: "プレリクエストスクリプト無し",
search: "検索履歴",
history_empty: "履歴が空です",
history_deleted: "履歴が削除された",
clear: "クリア",
clear_all: "全てクリア",
cleared: "クリアされた",
close: "閉じる",
sort: "ソート",
time: "時間",
duration: "期間",
no_duration: "期間なし",
show_more: "もっと表示する",
hide_more: "隠す",
collection: "コレクション",
current_collection: "現在のコレクション",
select_collection: "コレクションを選択",
create_collection: "コレクションを作成",
new: "新規",
import_export: "インポート・エクスポート",
more: "More",
folder: "フォルダ",
new_folder: "新しいフォルダー",
my_new_folder: "私の新しいフォルダー",
folder_empty: "フォルダーが空です",
edit_folder: "フォルダーを編集",
edit: "編集",
delete: "削除",
deleted: "削除された",
undo: "元に戻す",
collection_empty: "コレクションが空です",
new_collection: "新しいコレクション",
my_new_collection: "私の新しいコレクション",
edit_collection: "コレクションを編集",
edit_request: "リクエストを編集",
save_request_as: "名前を付けてリクエストを保存",
export: "エクスポート",
connecting_to: "{name}に接続中...",
connected: "接続した",
connected_to: "{name}に接続した",
disconnected: "切断された",
disconnected_from: "{name}から切断された",
something_went_wrong: "何かの問題が起きた",
error_occurred: "エラーが発生した",
browser_support_sse: "このブラウザはサーバー送信イベントのサポートがないようです。",
log: "ログ",
no_url: "URL無し",
run_query: "クエリを実行",
copy_query: "クエリをコピー",
kinda_dark: "ちょっと暗い",
clearly_white: "明らかに白",
just_black: "ただの黒",
auto_system: "オート(システム)",
green: "緑",
yellow: "黄",
pink: "ピンク",
red: "赤",
purple: "紫",
orange: "オレンジ",
cyan: "シヤン",
blue: "青",
loading: "ロード中...",
fetching: "フェッチ中...",
waiting_send_req: "(リクエスト送信待ち)",
cancel: "キャンセル",
save: "保存",
dismiss: "Dismiss",
are_you_sure: "よろしいですか?",
yes: "はい",
no: "いいえ",
restore: "リストア",
add_star: "星を付ける",
remove_star: "星を外す",
nothing_found: "何も見つからない",
replace_current: "置換",
replace_json: "JSONに置換",
preserve_current: "保持",
import_json: "JSONをインポート",
download_file: "ファイルをダウンロード",
upload_file: "ファイルをアップロード",
copy_response: "レスポンスをコピー",
copy_code: "コードをコピー",
copy_schema: "スキーマをコピー",
use_request: "リクエストを使用",
documentation: "ドキュメンテーション",
docs: "ドキュメント",
reset_default: "デフォルトにリセット",
fields: "FIELDS",
deprecated: "DEPRECATED",
add_one_header: "(ヘッダーを少なくとも1つ追加してください",
add_one_parameter: "パラメータを少なくとも1つ追加してください",
header_count: "ヘッダー {count}",
parameter_count: "パラメータ {count}",
variable_count: "変数 {count}",
value_count: "値 {count}",
send_request_first: "リクエストを先に送信してください",
generate_docs: "ドキュメンテーションを生成",
generate_docs_message: "Postwomanのコレクションをインポートし、直ちにドキュメンテーションを生成",
generate_docs_first: "ドキュメントを先に生成してください",
docs_generated: "ドキュメンテーションを生成した",
import_collections: "コレクションをインポート",
optional: "(オプション)",
json: "JSON",
none: "なし",
username: "ユーザー名",
password: "パスワード",
token: "トークン",
payload: "ペイロード",
choose_file: "ファイルを選択",
file_imported: "ファイルをインポートした",
f12_details: "F12を押して詳細を確認してください",
we_use_cookies: "クッキーを使用します。",
copied_to_clipboard: "クリップボードにコピーした",
finished_in: "{duration}msで終了した",
check_console_details: "コンソールより詳細を確認してください",
download_started: "ダウンロードを開始した",
url_invalid_format: "URLが正しくフォーマットされていない",
curl_invalid_format: "cURLが正しくフォーマットされていない",
enable_proxy: "プロキシを有効にしてみてください",
complete_config_urls: "設定URLsを入力してください",
token_request_saved: "トークンリクエストを保存した",
donate_info1: "Postwomanを非常に役に立つと思われる場合、感謝の印として寄付のご検討をお願いします。",
donate_info2: "以下の方法でPostwomanの開発をサポートできます",
one_time_recurring: "一度又は定期的",
one_time: "一度",
recurring: "定期的",
wiki: "Wiki",
error: "エラー",
go_home: "ホームに戻る",
reload: "リロード",
enter_curl: "cURLを入力",
empty: "空"
};
home: 'ホーム',
realtime: 'リアルタイム',
graphql: 'GraphQL',
settings: '設定',
request: 'リクエスト',
install_pwa: 'PWAをインストール',
support_us: '寄付',
tweet: 'ツイート',
options: 'オプション',
communication: '通信',
endpoint: 'エンドポイント',
schema: 'スキーマ',
theme: 'テーマ',
subscribe: '登録',
choose_language: '言語の選択',
shortcuts: 'ショートカット',
send_request: 'リクエストを送信',
save_to_collections: 'コレクションに保存',
copy_request_link: 'リクエストURLをコピー',
reset_request: 'リクエストをリセット',
support_us_on: '以下より寄付',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'JavaScriptコード',
method: 'メソッド',
path: 'パス',
label: 'ラベル',
again: '',
content_type: 'Content Type',
raw_input: 'Raw入力',
parameter_list: 'パラメータリスト',
raw_request_body: 'Rawリクエストボディー',
show_code: 'コードを表示',
hide_code: 'コードを非表示',
show_prerequest_script: 'プレリクエストスクリプトを表示',
hide_prerequest_script: 'プレリクエストスクリプトを非表示',
authentication: '認証',
authentication_type: '認証タイプ',
include_in_url: 'URLに含む',
parameters: 'パラメータ',
expand_response: 'レスポンスを広げる',
collapse_response: 'レスポンスを狭める',
hide_preview: 'プレビューしない',
preview_html: 'HTMLプレビュー表示',
history: '履歴',
collections: 'コレクション',
import_curl: 'cURLをインポート',
import: 'インポート',
generate_code: 'コード生成',
request_type: 'リクエストタイプ',
generated_code: '生成されたコード',
status: 'ステータス',
headers: 'ヘッダー',
websocket: 'ウェブソケット',
waiting_for_connection: '(接続待ち)',
message: 'メッセージ',
sse: 'SSE',
server: 'サーバ',
events: 'イベント',
url: 'URL',
get_schema: 'スキーマを取得',
header_list: 'ヘッダーリスト',
add_new: '追加',
response: 'レスポンス',
query: 'クエリ',
queries: 'クエリ',
query_variables: '変数',
mutations: 'ミューテーション',
subscriptions: 'サブスクリプション',
types: 'タイプ',
send: '送信',
background: '背景',
color: '色',
labels: 'ラベル',
multi_color: 'マルチカラー',
enabled: '有効',
disabled: '無効',
proxy: 'プロキシ',
postwoman_official_proxy_hosting: 'Postwomanの公式プロキシは、Apollo TVがホストしています。',
read_the: 'プライバシーポリシー',
apollotv_privacy_policy: 'を読む',
contact_us: 'お問い合わせ',
connect: '接続',
disconnect: '切断',
start: '開始',
stop: '停止',
access_token: 'アクセストークン',
token_list: 'トークンリスト',
get_token: '新しいトークンを取得',
manage_token: 'アクセストークンを管理',
save_token: 'アクセストークンを保存',
use_token: 'アクセストークンを使用',
request_token: 'トークンをリクエスト',
save_token_req: 'トークンリクエストを保存',
manage_token_req: 'トークンリクエストを管理',
use_token_req: 'トークンリクエストを使用',
token_req_name: 'リクエスト名',
token_req_details: 'リクエスト詳細',
token_name: 'トークン名',
oidc_discovery_url: 'OIDC Discovery URL',
auth_url: '認証URL',
access_token_url: 'アクセストークンURL',
client_id: 'クライアントID',
scope: 'スコープ',
state: 'ステート',
token_req_list: 'トークンリクエストリスト',
no_path: 'パス無し',
no_label: 'ラベル無し',
prerequest_script: 'プレリクエストスクリプト',
no_prerequest_script: 'プレリクエストスクリプト無し',
search: '検索履歴',
history_empty: '履歴が空です',
history_deleted: '履歴が削除された',
clear: 'クリア',
clear_all: '全てクリア',
cleared: 'クリアされた',
close: '閉じる',
sort: 'ソート',
time: '時間',
duration: '期間',
no_duration: '期間なし',
show_more: 'もっと表示する',
hide_more: '隠す',
collection: 'コレクション',
current_collection: '現在のコレクション',
select_collection: 'コレクションを選択',
create_collection: 'コレクションを作成',
new: '新規',
import_export: 'インポート・エクスポート',
more: 'More',
folder: 'フォルダ',
new_folder: '新しいフォルダー',
my_new_folder: '私の新しいフォルダー',
folder_empty: 'フォルダーが空です',
edit_folder: 'フォルダーを編集',
edit: '編集',
delete: '削除',
deleted: '削除された',
undo: '元に戻す',
collection_empty: 'コレクションが空です',
new_collection: '新しいコレクション',
my_new_collection: '私の新しいコレクション',
edit_collection: 'コレクションを編集',
edit_request: 'リクエストを編集',
save_request_as: '名前を付けてリクエストを保存',
export: 'エクスポート',
connecting_to: '{name}に接続中...',
connected: '接続した',
connected_to: '{name}に接続した',
disconnected: '切断された',
disconnected_from: '{name}から切断された',
something_went_wrong: '何かの問題が起きた',
error_occurred: 'エラーが発生した',
browser_support_sse: 'このブラウザはサーバー送信イベントのサポートがないようです。',
log: 'ログ',
no_url: 'URL無し',
run_query: 'クエリを実行',
copy_query: 'クエリをコピー',
kinda_dark: 'ちょっと暗い',
clearly_white: '明らかに白',
just_black: 'ただの黒',
auto_system: 'オート(システム)',
green: '緑',
yellow: '黄',
pink: 'ピンク',
red: '赤',
purple: '紫',
orange: 'オレンジ',
cyan: 'シヤン',
blue: '青',
loading: 'ロード中...',
fetching: 'フェッチ中...',
waiting_send_req: '(リクエスト送信待ち)',
cancel: 'キャンセル',
save: '保存',
dismiss: 'Dismiss',
are_you_sure: 'よろしいですか?',
yes: 'はい',
no: 'いいえ',
restore: 'リストア',
add_star: '星を付ける',
remove_star: '星を外す',
nothing_found: '何も見つからない',
replace_current: '置換',
replace_json: 'JSONに置換',
preserve_current: '保持',
import_json: 'JSONをインポート',
download_file: 'ファイルをダウンロード',
upload_file: 'ファイルをアップロード',
copy_response: 'レスポンスをコピー',
copy_code: 'コードをコピー',
copy_schema: 'スキーマをコピー',
use_request: 'リクエストを使用',
documentation: 'ドキュメンテーション',
docs: 'ドキュメント',
reset_default: 'デフォルトにリセット',
fields: 'FIELDS',
deprecated: 'DEPRECATED',
add_one_header: 'ヘッダーを少なくとも1つ追加してください',
add_one_parameter: '(パラメータを少なくとも1つ追加してください',
header_count: 'ヘッダー {count}',
parameter_count: 'パラメータ {count}',
variable_count: '変数 {count}',
value_count: '値 {count}',
send_request_first: 'リクエストを先に送信してください',
generate_docs: 'ドキュメンテーションを生成',
generate_docs_message: 'Postwomanのコレクションをインポートし、直ちにドキュメンテーションを生成',
generate_docs_first: 'ドキュメントを先に生成してください',
docs_generated: 'ドキュメンテーションを生成した',
import_collections: 'コレクションをインポート',
optional: '(オプション)',
json: 'JSON',
none: 'なし',
username: 'ユーザー名',
password: 'パスワード',
token: 'トークン',
payload: 'ペイロード',
choose_file: 'ファイルを選択',
file_imported: 'ファイルをインポートした',
f12_details: 'F12を押して詳細を確認してください',
we_use_cookies: 'クッキーを使用します。',
copied_to_clipboard: 'クリップボードにコピーした',
finished_in: '{duration}msで終了した',
check_console_details: 'コンソールより詳細を確認してください',
download_started: 'ダウンロードを開始した',
url_invalid_format: 'URLが正しくフォーマットされていない',
curl_invalid_format: 'cURLが正しくフォーマットされていない',
enable_proxy: 'プロキシを有効にしてみてください',
complete_config_urls: '設定URLsを入力してください',
token_request_saved: 'トークンリクエストを保存した',
donate_info1:
'Postwomanを非常に役に立つと思われる場合、感謝の印として寄付のご検討をお願いします。',
donate_info2: '以下の方法でPostwomanの開発をサポートできます',
one_time_recurring: '一度又は定期的',
one_time: '一度',
recurring: '定期的',
wiki: 'Wiki',
error: 'エラー',
go_home: 'ホームに戻る',
reload: 'リロード',
enter_curl: 'cURLを入力',
empty: '空',
}

View File

@@ -1,89 +1,89 @@
export default {
home: "Home",
realtime: "Tempo real",
graphql: "GraphQL",
settings: "Configurações",
request: "Request",
install_pwa: "Instalar PWA",
support_us: "Nos ajude",
tweet: "Tweet",
options: "Opções",
communication: "Comunicação",
endpoint: "Endpoint",
schema: "Schema",
theme: "Tema",
subscribe: "Subscribe",
choose_language: "Escolher idioma",
shortcuts: "Atalhos",
send_request: "Enviar request",
save_to_collections: "Salvar nas coleções",
copy_request_link: "Copiar link da request",
reset_request: "Reiniciar request",
support_us_on: "Nos ajude no",
open_collective: "Abrir coletivamente",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "Codigo JavaScript",
method: "Método",
path: "Caminho",
label: "Label",
again: "Novamente",
content_type: "Content Type",
raw_input: "Raw input",
parameter_list: "Lista de parâmetros",
raw_request_body: "Raw request body",
show_code: "Mostrar código",
hide_code: "Esconder código",
show_prerequest_script: "Mostrar script de pré-request",
hide_prerequest_script: "Esconder script de pré-request",
authentication: "Autenticação",
authentication_type: "Tipo de autenticação",
include_in_url: "Incluir na url",
parameters: "Parâmetros",
expand_response: "Expandir response",
collapse_response: "Esconder response",
hide_preview: "Esconder preview",
preview_html: "Preview html",
history: "Histórico",
collections: "Coleções",
import_curl: "Importar curl",
import: "Importar",
generate_code: "Gerar código",
request_type: "Tipo de request",
generated_code: "Código gerado",
status: "Status",
headers: "Headers",
websocket: "Websocket",
waiting_for_connection: "(aguardando conexão)",
message: "Mensagem",
sse: "SSE",
server: "Servidor",
events: "Eventos",
url: "URL",
get_schema: "Get schema",
header_list: "Lista de headers",
add_new: "Adicionar novo",
response: "Response",
query: "Query",
queries: "Queries",
query_variables: "Variáveis",
mutations: "Mutações",
subscriptions: "Assinaturas",
types: "Tipos",
send: "Enviar",
background: "Fundo",
color: "Cor",
labels: "Labels",
multi_color: "Multi cor",
enabled: "Ativado",
disabled: "Desativado",
proxy: "Proxy",
home: 'Home',
realtime: 'Tempo real',
graphql: 'GraphQL',
settings: 'Configurações',
request: 'Request',
install_pwa: 'Instalar PWA',
support_us: 'Nos ajude',
tweet: 'Tweet',
options: 'Opções',
communication: 'Comunicação',
endpoint: 'Endpoint',
schema: 'Schema',
theme: 'Tema',
subscribe: 'Subscribe',
choose_language: 'Escolher idioma',
shortcuts: 'Atalhos',
send_request: 'Enviar request',
save_to_collections: 'Salvar nas coleções',
copy_request_link: 'Copiar link da request',
reset_request: 'Reiniciar request',
support_us_on: 'Nos ajude no',
open_collective: 'Abrir coletivamente',
paypal: 'Paypal',
patreon: 'Patreon',
javascript_code: 'Codigo JavaScript',
method: 'Método',
path: 'Caminho',
label: 'Label',
again: 'Novamente',
content_type: 'Content Type',
raw_input: 'Raw input',
parameter_list: 'Lista de parâmetros',
raw_request_body: 'Raw request body',
show_code: 'Mostrar código',
hide_code: 'Esconder código',
show_prerequest_script: 'Mostrar script de pré-request',
hide_prerequest_script: 'Esconder script de pré-request',
authentication: 'Autenticação',
authentication_type: 'Tipo de autenticação',
include_in_url: 'Incluir na url',
parameters: 'Parâmetros',
expand_response: 'Expandir response',
collapse_response: 'Esconder response',
hide_preview: 'Esconder preview',
preview_html: 'Preview html',
history: 'Histórico',
collections: 'Coleções',
import_curl: 'Importar curl',
import: 'Importar',
generate_code: 'Gerar código',
request_type: 'Tipo de request',
generated_code: 'Código gerado',
status: 'Status',
headers: 'Headers',
websocket: 'Websocket',
waiting_for_connection: '(aguardando conexão)',
message: 'Mensagem',
sse: 'SSE',
server: 'Servidor',
events: 'Eventos',
url: 'URL',
get_schema: 'Get schema',
header_list: 'Lista de headers',
add_new: 'Adicionar novo',
response: 'Response',
query: 'Query',
queries: 'Queries',
query_variables: 'Variáveis',
mutations: 'Mutações',
subscriptions: 'Assinaturas',
types: 'Tipos',
send: 'Enviar',
background: 'Fundo',
color: 'Cor',
labels: 'Labels',
multi_color: 'Multi cor',
enabled: 'Ativado',
disabled: 'Desativado',
proxy: 'Proxy',
postwoman_official_proxy_hosting: "Postwoman's alojamento proxy oficial",
read_the: "Leia o",
apollotv_privacy_policy: "ApolloTV Política de Privacidade",
contact_us: "Contate-Nos",
connect: "Conectar",
disconnect: "Desconectar",
start: "Começar",
stop: "Pare"
};
read_the: 'Leia o',
apollotv_privacy_policy: 'ApolloTV Política de Privacidade',
contact_us: 'Contate-Nos',
connect: 'Conectar',
disconnect: 'Desconectar',
start: 'Começar',
stop: 'Pare',
}

View File

@@ -1,90 +1,89 @@
export default {
home: "Ana Sayfa",
realtime: "Realtime",
graphql: "GraphQL",
settings: "Ayarlar",
request: "İstek",
install_pwa: "PWA yükle",
support_us: "Bize destek ol",
tweet: "Tweet",
options: "Options",
communication: "İletişim",
endpoint: "Endpoint",
schema: "Taslak",
theme: "Tema",
subscribe: "Abonelik",
choose_language: "Dil seç",
shortcuts: "Kısayollar",
send_request: "İstek gönder",
save_to_collections: "Koleksiyonları kaydet",
copy_request_link: "İstek adresini kopyala",
reset_request: "İstekleri resetle",
support_us_on: "Bizi destekle",
open_collective: "Open Collective",
paypal: "PayPal",
patreon: "Patreon",
javascript_code: "JavaScript code",
method: "Metot",
path: "Yol",
label: "Etiket",
again: "Yeniden",
content_type: "İçerik tipi",
raw_input: "Raw giriş",
parameter_list: "Parametre listesi",
raw_request_body: "Raw istek içeriği",
show_code: "Kodu göster",
hide_code: "Kodu gizle",
show_prerequest_script: "Pre-Request scriptini göster",
hide_prerequest_script: "Pre-Request scriptini gizle",
authentication: "Authentication",
authentication_type: "Authentication tipi",
home: 'Ana Sayfa',
realtime: 'Realtime',
graphql: 'GraphQL',
settings: 'Ayarlar',
request: 'İstek',
install_pwa: 'PWA yükle',
support_us: 'Bize destek ol',
tweet: 'Tweet',
options: 'Options',
communication: 'İletişim',
endpoint: 'Endpoint',
schema: 'Taslak',
theme: 'Tema',
subscribe: 'Abonelik',
choose_language: 'Dil seç',
shortcuts: 'Kısayollar',
send_request: 'İstek gönder',
save_to_collections: 'Koleksiyonları kaydet',
copy_request_link: 'İstek adresini kopyala',
reset_request: 'İstekleri resetle',
support_us_on: 'Bizi destekle',
open_collective: 'Open Collective',
paypal: 'PayPal',
patreon: 'Patreon',
javascript_code: 'JavaScript code',
method: 'Metot',
path: 'Yol',
label: 'Etiket',
again: 'Yeniden',
content_type: 'İçerik tipi',
raw_input: 'Raw giriş',
parameter_list: 'Parametre listesi',
raw_request_body: 'Raw istek içeriği',
show_code: 'Kodu göster',
hide_code: 'Kodu gizle',
show_prerequest_script: 'Pre-Request scriptini göster',
hide_prerequest_script: 'Pre-Request scriptini gizle',
authentication: 'Authentication',
authentication_type: 'Authentication tipi',
include_in_url: "URL'den içeri aktar",
parameters: "Parametre",
expand_response: "Cevabı genişlet",
collapse_response: "Cevap daralt",
hide_preview: "Görüntülemeyi gizle",
preview_html: "HTML formatında görüntüle",
history: "Geçmiş",
collections: "Koleksiyonlar",
import_curl: "cURL içeri aktar",
import: "İçeri Aktar",
generate_code: "Kod Üret",
request_type: "Request tipi",
generated_code: "Üretilen Kod",
status: "Durum",
headers: "Headers",
websocket: "WebSocket",
waiting_for_connection: "(esperando por conexión)",
message: "Mesaj",
sse: "SSE",
server: "Server",
events: "Events",
url: "URL",
get_schema: "Taslak",
header_list: "Header listesi",
add_new: "Yeni Ekle",
response: "Cevap",
query: "Sorgu",
queries: "Sorgular",
query_variables: "Değişkenler",
mutations: "Değişimler",
subscriptions: "Aboneler",
types: "Tipler",
send: "Gönder",
background: "Arka Plan",
color: "Renk",
labels: "Etiketler",
multi_color: "Çoklu renk",
enabled: "Aktif",
disabled: "Aktif değil",
proxy: "Proxy",
postwoman_official_proxy_hosting:
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
read_the: "Leer la",
apollotv_privacy_policy: "ApolloTV gizlilik politikaları",
contact_us: "Bizimle iletişime geçin",
connect: "Bağlan",
disconnect: "Kesmek",
start: "Başla",
stop: "Durdurmak"
};
parameters: 'Parametre',
expand_response: 'Cevabı genişlet',
collapse_response: 'Cevap daralt',
hide_preview: 'Görüntülemeyi gizle',
preview_html: 'HTML formatında görüntüle',
history: 'Geçmiş',
collections: 'Koleksiyonlar',
import_curl: 'cURL içeri aktar',
import: 'İçeri Aktar',
generate_code: 'Kod Üret',
request_type: 'Request tipi',
generated_code: 'Üretilen Kod',
status: 'Durum',
headers: 'Headers',
websocket: 'WebSocket',
waiting_for_connection: '(esperando por conexión)',
message: 'Mesaj',
sse: 'SSE',
server: 'Server',
events: 'Events',
url: 'URL',
get_schema: 'Taslak',
header_list: 'Header listesi',
add_new: 'Yeni Ekle',
response: 'Cevap',
query: 'Sorgu',
queries: 'Sorgular',
query_variables: 'Değişkenler',
mutations: 'Değişimler',
subscriptions: 'Aboneler',
types: 'Tipler',
send: 'Gönder',
background: 'Arka Plan',
color: 'Renk',
labels: 'Etiketler',
multi_color: 'Çoklu renk',
enabled: 'Aktif',
disabled: 'Aktif değil',
proxy: 'Proxy',
postwoman_official_proxy_hosting: 'Proxy Oficial de Postwoman está hospedado en ApolloTV.',
read_the: 'Leer la',
apollotv_privacy_policy: 'ApolloTV gizlilik politikaları',
contact_us: 'Bizimle iletişime geçin',
connect: 'Bağlan',
disconnect: 'Kesmek',
start: 'Başla',
stop: 'Durdurmak',
}

View File

@@ -1,89 +1,89 @@
export default {
home: "主页",
realtime: "长连接",
graphql: "GraphQL",
settings: "设置",
request: "请求",
install_pwa: "安装PWA应用",
support_us: "支持我们",
tweet: "推特",
options: "选项",
communication: "联系我们",
endpoint: "服务端点",
schema: "模式",
theme: "主题",
subscribe: "订阅",
choose_language: "选择语言",
shortcuts: "快捷键",
send_request: "发送请求",
save_to_collections: "保存到收藏夹",
copy_request_link: "复制请求链接",
reset_request: "重置请求",
support_us_on: "支持我们",
open_collective: "Open Collective",
paypal: "Paypal",
patreon: "Patreon",
javascript_code: "JavaScript代码",
method: "方法",
path: "路径",
label: "标签",
again: "重试",
content_type: "内容类型",
raw_input: "raw数据",
parameter_list: "参数列表",
raw_request_body: "raw请求主体",
show_code: "显示代码",
hide_code: "隐藏代码",
show_prerequest_script: "显示预请求脚本",
hide_prerequest_script: "隐藏预请求脚本",
authentication: "认证方式",
authentication_type: "认证类型",
include_in_url: "包含在URL中",
parameters: "参数",
expand_response: "展开显示响应内容",
collapse_response: "折叠显示响应内容",
hide_preview: "隐藏预览",
preview_html: "预览HTML",
history: "历史记录",
collections: "收藏夹",
import_curl: "批量导入",
import: "导入",
generate_code: "生成代码",
request_type: "请求类型",
generated_code: "生成的代码",
status: "状态码",
headers: "请求头",
websocket: "Websocket",
waiting_for_connection: "(等待连接)",
message: "消息内容",
sse: "SSE",
server: "Server",
events: "事件",
url: "地址",
get_schema: "获取模式",
header_list: "请求头列表",
add_new: "添加",
response: "响应",
query: "查询",
queries: "查询",
query_variables: "变数",
mutations: "Mutations",
subscriptions: "订阅",
types: "种类",
send: "发送",
background: "背景",
color: "颜色",
labels: "标签",
multi_color: "彩色",
enabled: "已启用",
disabled: "已禁用",
proxy: "代理",
postwoman_official_proxy_hosting: "Postwoman的官方代理由ApolloTV托管",
read_the: "阅读",
apollotv_privacy_policy: "ApolloTV隐私政策",
contact_us: "联系我们",
connect: "连接",
disconnect: "断开",
start: "开始",
stop: "停止"
};
home: '主页',
realtime: '长连接',
graphql: 'GraphQL',
settings: '设置',
request: '请求',
install_pwa: '安装PWA应用',
support_us: '支持我们',
tweet: '推特',
options: '选项',
communication: '联系我们',
endpoint: '服务端点',
schema: '模式',
theme: '主题',
subscribe: '订阅',
choose_language: '选择语言',
shortcuts: '快捷键',
send_request: '发送请求',
save_to_collections: '保存到收藏夹',
copy_request_link: '复制请求链接',
reset_request: '重置请求',
support_us_on: '支持我们',
open_collective: 'Open Collective',
paypal: 'Paypal',
patreon: 'Patreon',
javascript_code: 'JavaScript代码',
method: '方法',
path: '路径',
label: '标签',
again: '重试',
content_type: '内容类型',
raw_input: 'raw数据',
parameter_list: '参数列表',
raw_request_body: 'raw请求主体',
show_code: '显示代码',
hide_code: '隐藏代码',
show_prerequest_script: '显示预请求脚本',
hide_prerequest_script: '隐藏预请求脚本',
authentication: '认证方式',
authentication_type: '认证类型',
include_in_url: '包含在URL中',
parameters: '参数',
expand_response: '展开显示响应内容',
collapse_response: '折叠显示响应内容',
hide_preview: '隐藏预览',
preview_html: '预览HTML',
history: '历史记录',
collections: '收藏夹',
import_curl: '批量导入',
import: '导入',
generate_code: '生成代码',
request_type: '请求类型',
generated_code: '生成的代码',
status: '状态码',
headers: '请求头',
websocket: 'Websocket',
waiting_for_connection: '(等待连接)',
message: '消息内容',
sse: 'SSE',
server: 'Server',
events: '事件',
url: '地址',
get_schema: '获取模式',
header_list: '请求头列表',
add_new: '添加',
response: '响应',
query: '查询',
queries: '查询',
query_variables: '变数',
mutations: 'Mutations',
subscriptions: '订阅',
types: '种类',
send: '发送',
background: '背景',
color: '颜色',
labels: '标签',
multi_color: '彩色',
enabled: '已启用',
disabled: '已禁用',
proxy: '代理',
postwoman_official_proxy_hosting: 'Postwoman的官方代理由ApolloTV托管',
read_the: '阅读',
apollotv_privacy_policy: 'ApolloTV隐私政策',
contact_us: '联系我们',
connect: '连接',
disconnect: '断开',
start: '开始',
stop: '停止',
}

View File

@@ -304,11 +304,9 @@
<button
class="icon"
v-tooltip="
(fb.currentUser.displayName ||
'<label><i>Name not found</i></label>') +
(fb.currentUser.displayName || '<label><i>Name not found</i></label>') +
'<br>' +
(fb.currentUser.email ||
'<label><i>Email not found</i></label>')
(fb.currentUser.email || '<label><i>Email not found</i></label>')
"
aria-label="Account"
>
@@ -326,7 +324,7 @@
<button class="icon">
<i class="material-icons">settings</i>
<span>
{{ $t("settings") }}
{{ $t('settings') }}
</span>
</button>
</nuxt-link>
@@ -334,7 +332,7 @@
<div>
<button class="icon" @click="logout" v-close-popover>
<i class="material-icons">exit_to_app</i>
<span>{{ $t("logout") }}</span>
<span>{{ $t('logout') }}</span>
</button>
</div>
</template>
@@ -346,33 +344,21 @@
</button>
<template slot="popover">
<div>
<button
class="icon"
@click="showExtensions = true"
v-close-popover
>
<button class="icon" @click="showExtensions = true" v-close-popover>
<i class="material-icons">extension</i>
<span>{{ $t("extensions") }}</span>
<span>{{ $t('extensions') }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="showShortcuts = true"
v-close-popover
>
<button class="icon" @click="showShortcuts = true" v-close-popover>
<i class="material-icons">keyboard</i>
<span>{{ $t("shortcuts") }}</span>
<span>{{ $t('shortcuts') }}</span>
</button>
</div>
<div>
<button
class="icon"
@click="showSupport = true"
v-close-popover
>
<button class="icon" @click="showSupport = true" v-close-popover>
<i class="material-icons">favorite</i>
<span>{{ $t("support_us") }}</span>
<span>{{ $t('support_us') }}</span>
</button>
</div>
<div>
@@ -391,7 +377,7 @@
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>{{ $t("tweet") }}</span>
<span>{{ $t('tweet') }}</span>
</button>
<button
v-if="navigatorShare"
@@ -414,10 +400,7 @@
<span v-if="version.name" class="mono">
<a
class="footer-link"
:href="
'https://github.com/liyasthomas/postwoman/releases/tag/' +
version.name
"
:href="'https://github.com/liyasthomas/postwoman/releases/tag/' + version.name"
target="_blank"
rel="noopener"
v-tooltip="'GitHub'"
@@ -443,20 +426,12 @@
<!-- <span v-if="version.variant">({{version.variant}})</span> -->
</span>
<span>
<a
href="https://liyasthomas.web.app"
target="_blank"
rel="noopener"
>
<a href="https://liyasthomas.web.app" target="_blank" rel="noopener">
<button class="icon" v-tooltip="'Liyas Thomas'">
🦄
</button>
</a>
<a
href="mailto:liyascthomas@gmail.com"
target="_blank"
rel="noopener"
>
<a href="mailto:liyascthomas@gmail.com" target="_blank" rel="noopener">
<button class="icon" v-tooltip="$t('contact_us')">
<i class="material-icons">email</i>
</button>
@@ -487,7 +462,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("extensions") }}</h3>
<h3 class="title">{{ $t('extensions') }}</h3>
<div>
<button class="icon" @click="showExtensions = false">
<i class="material-icons">close</i>
@@ -499,7 +474,7 @@
</div>
<div slot="body">
<p class="info">
{{ $t("extensions_info1") }}
{{ $t('extensions_info1') }}
</p>
<div>
<a
@@ -520,11 +495,7 @@
/>
</svg>
<span>Firefox</span>
<span
class="icon"
v-if="firefoxExtInstalled"
v-tooltip="$t('installed')"
>
<span class="icon" v-if="firefoxExtInstalled" v-tooltip="$t('installed')">
<i class="material-icons">done</i>
</span>
</button>
@@ -549,11 +520,7 @@
/>
</svg>
<span>Chrome</span>
<span
class="icon"
v-if="chromeExtInstalled"
v-tooltip="$t('installed')"
>
<span class="icon" v-if="chromeExtInstalled" v-tooltip="$t('installed')">
<i class="material-icons">done</i>
</span>
</button>
@@ -567,7 +534,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("shortcuts") }}</h3>
<h3 class="title">{{ $t('shortcuts') }}</h3>
<div>
<button class="icon" @click="showShortcuts = false">
<i class="material-icons">close</i>
@@ -579,19 +546,19 @@
</div>
<div slot="body">
<div>
<label>{{ $t("send_request") }}</label>
<label>{{ $t('send_request') }}</label>
<kbd>{{ getSpecialKey() }} G</kbd>
</div>
<div>
<label>{{ $t("save_to_collections") }}</label>
<label>{{ $t('save_to_collections') }}</label>
<kbd>{{ getSpecialKey() }} S</kbd>
</div>
<div>
<label>{{ $t("copy_request_link") }}</label>
<label>{{ $t('copy_request_link') }}</label>
<kbd>{{ getSpecialKey() }} K</kbd>
</div>
<div>
<label>{{ $t("reset_request") }}</label>
<label>{{ $t('reset_request') }}</label>
<kbd>{{ getSpecialKey() }} L</kbd>
</div>
</div>
@@ -602,7 +569,7 @@
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">{{ $t("support_us_on") }}</h3>
<h3 class="title">{{ $t('support_us_on') }}</h3>
<div>
<button class="icon" @click="showSupport = false">
<i class="material-icons">close</i>
@@ -614,10 +581,10 @@
</div>
<div slot="body">
<p class="info">
{{ $t("donate_info1") }}
{{ $t('donate_info1') }}
</p>
<p class="info">
{{ $t("donate_info2") }}
{{ $t('donate_info2') }}
</p>
<div>
<a
@@ -628,7 +595,7 @@
>
<button class="icon">
<i class="material-icons">donut_large</i>
<span>{{ $t("open_collective") }}</span>
<span>{{ $t('open_collective') }}</span>
</button>
</a>
</div>
@@ -641,7 +608,7 @@
>
<button class="icon">
<i class="material-icons">payment</i>
<span>{{ $t("paypal") }}</span>
<span>{{ $t('paypal') }}</span>
</button>
</a>
</div>
@@ -654,7 +621,7 @@
>
<button class="icon">
<i class="material-icons">local_parking</i>
<span>{{ $t("patreon") }}</span>
<span>{{ $t('patreon') }}</span>
</button>
</a>
</div>
@@ -671,58 +638,58 @@
</style>
<script>
import intializePwa from "../assets/js/pwa";
import * as version from "../.postwoman/version.json";
import { hasExtensionInstalled } from "../functions/strategies/ExtensionStrategy";
import firebase from "firebase/app";
import { fb } from "../functions/fb";
import intializePwa from '../assets/js/pwa'
import * as version from '../.postwoman/version.json'
import { hasExtensionInstalled } from '../functions/strategies/ExtensionStrategy'
import firebase from 'firebase/app'
import { fb } from '../functions/fb'
export default {
components: {
logo: () => import("../components/logo"),
modal: () => import("../components/modal"),
login: () => import("../components/firebase/login")
logo: () => import('../components/logo'),
modal: () => import('../components/modal'),
login: () => import('../components/firebase/login'),
},
methods: {
getSpecialKey() {
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl";
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? '⌘' : 'Ctrl'
},
linkActive(path) {
return {
"nuxt-link-exact-active": this.$route.path === path,
"nuxt-link-active": this.$route.path === path
};
'nuxt-link-exact-active': this.$route.path === path,
'nuxt-link-active': this.$route.path === path,
}
},
logout() {
fb.currentUser = null;
fb.currentUser = null
firebase
.auth()
.signOut()
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
this.$toast.info(this.$t("logged_out"), {
icon: "vpn_key"
});
icon: 'error',
})
})
this.$toast.info(this.$t('logged_out'), {
icon: 'vpn_key',
})
},
nativeShare() {
if (navigator.share) {
navigator
.share({
title: "Postwoman",
title: 'Postwoman',
text:
"Postwoman • A free, fast and beautiful API request builder - Web alternative to Postman - Helps you create requests faster, saving precious time on development.",
url: "https://postwoman.io/"
'Postwoman • A free, fast and beautiful API request builder - Web alternative to Postman - Helps you create requests faster, saving precious time on development.',
url: 'https://postwoman.io/',
})
.then(() => {})
.catch(console.error);
.catch(console.error)
} else {
// fallback
}
}
},
},
data() {
@@ -737,146 +704,137 @@ export default {
showSupport: false,
extensionInstalled: hasExtensionInstalled(),
fb,
navigatorShare: navigator.share
};
navigatorShare: navigator.share,
}
},
beforeMount() {
// Set version data
this.version = version.default;
this.version = version.default
// Load theme settings
(() => {
;(() => {
// Apply theme from settings.
document.documentElement.className =
this.$store.state.postwoman.settings.THEME_CLASS || "";
document.documentElement.className = this.$store.state.postwoman.settings.THEME_CLASS || ''
// Load theme color data from settings, or use default color.
let color = this.$store.state.postwoman.settings.THEME_COLOR || "#50fa7b";
let vibrant =
this.$store.state.postwoman.settings.THEME_COLOR_VIBRANT || true;
document.documentElement.style.setProperty("--ac-color", color);
let color = this.$store.state.postwoman.settings.THEME_COLOR || '#50fa7b'
let vibrant = this.$store.state.postwoman.settings.THEME_COLOR_VIBRANT || true
document.documentElement.style.setProperty('--ac-color', color)
document.documentElement.style.setProperty(
"--act-color",
vibrant ? "rgba(32, 33, 36, 1)" : "rgba(255, 255, 255, 1)"
);
})();
'--act-color',
vibrant ? 'rgba(32, 33, 36, 1)' : 'rgba(255, 255, 255, 1)'
)
})()
},
mounted() {
if (process.client) {
document.body.classList.add("afterLoad");
document.body.classList.add('afterLoad')
}
document
.querySelector("meta[name=theme-color]")
.setAttribute(
"content",
this.$store.state.postwoman.settings.THEME_TAB_COLOR || "#202124"
);
.querySelector('meta[name=theme-color]')
.setAttribute('content', this.$store.state.postwoman.settings.THEME_TAB_COLOR || '#202124')
// Initializes the PWA code - checks if the app is installed,
// etc.
(async () => {
this.showInstallPrompt = await intializePwa();
let cookiesAllowed = localStorage.getItem("cookiesAllowed") === "yes";
;(async () => {
this.showInstallPrompt = await intializePwa()
let cookiesAllowed = localStorage.getItem('cookiesAllowed') === 'yes'
if (!cookiesAllowed) {
this.$toast.show(this.$t("we_use_cookies"), {
icon: "info",
this.$toast.show(this.$t('we_use_cookies'), {
icon: 'info',
duration: 5000,
theme: "toasted-primary",
theme: 'toasted-primary',
action: [
{
text: this.$t("dismiss"),
text: this.$t('dismiss'),
onClick: (e, toastObject) => {
localStorage.setItem("cookiesAllowed", "yes");
toastObject.goAway(0);
}
}
]
});
localStorage.setItem('cookiesAllowed', 'yes')
toastObject.goAway(0)
},
},
],
})
}
let showExtensionsToast =
localStorage.getItem("showExtensionsToast") === "yes";
if (
!this.extensionInstalled &&
!showExtensionsToast
) {
let showExtensionsToast = localStorage.getItem('showExtensionsToast') === 'yes'
if (!this.extensionInstalled && !showExtensionsToast) {
setTimeout(() => {
this.$toast.show(this.$t("extensions_info2"), {
icon: "extension",
this.$toast.show(this.$t('extensions_info2'), {
icon: 'extension',
duration: 5000,
theme: "toasted-primary",
theme: 'toasted-primary',
action: [
{
text: this.$t("yes"),
text: this.$t('yes'),
onClick: (e, toastObject) => {
this.showExtensions = true;
localStorage.setItem("showExtensionsToast", "yes");
toastObject.goAway(0);
}
this.showExtensions = true
localStorage.setItem('showExtensionsToast', 'yes')
toastObject.goAway(0)
},
},
{
text: this.$t("no"),
text: this.$t('no'),
onClick: (e, toastObject) => {
toastObject.goAway(0);
}
}
]
});
}, 15000);
toastObject.goAway(0)
},
},
],
})
}, 15000)
}
this._keyListener = function(e) {
if (e.key === "Escape") {
e.preventDefault();
this.showExtensions = this.showShortcuts = this.showSupport = false;
if (e.key === 'Escape') {
e.preventDefault()
this.showExtensions = this.showShortcuts = this.showSupport = false
}
};
document.addEventListener("keydown", this._keyListener.bind(this));
})();
}
document.addEventListener('keydown', this._keyListener.bind(this))
})()
window.addEventListener("scroll", event => {
let mainNavLinks = document.querySelectorAll("nav ul li a");
let fromTop = window.scrollY;
window.addEventListener('scroll', event => {
let mainNavLinks = document.querySelectorAll('nav ul li a')
let fromTop = window.scrollY
mainNavLinks.forEach(link => {
let section = document.querySelector(link.hash);
let section = document.querySelector(link.hash)
if (
section &&
section.offsetTop <= fromTop &&
section.offsetTop + section.offsetHeight > fromTop
) {
link.classList.add("current");
link.classList.add('current')
} else {
link.classList.remove("current");
link.classList.remove('current')
}
});
});
})
})
console.log(
"%cWe ❤︎ open source!",
"background-color:white;padding:8px 16px;border-radius:8px;font-size:32px;color:red;"
);
'%cWe ❤︎ open source!',
'background-color:white;padding:8px 16px;border-radius:8px;font-size:32px;color:red;'
)
console.log(
"%cContribute: https://github.com/liyasthomas/postwoman",
"background-color:black;padding:4px 8px;border-radius:8px;font-size:16px;color:white;"
);
'%cContribute: https://github.com/liyasthomas/postwoman',
'background-color:black;padding:4px 8px;border-radius:8px;font-size:16px;color:white;'
)
},
watch: {
$route() {
// this.$toast.clear();
}
},
},
computed: {
availableLocales() {
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale);
}
return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale)
},
},
beforeDestroy() {
document.removeEventListener("keydown", this._keyListener);
}
};
document.removeEventListener('keydown', this._keyListener)
},
}
</script>

View File

@@ -1,19 +1,15 @@
<template>
<div class="page page-error">
<img
src="~static/icons/error.svg"
:alt="$t('error')"
class="error_banner"
/>
<img src="~static/icons/error.svg" :alt="$t('error')" class="error_banner" />
<h2>{{ error.statusCode }}</h2>
<h3>{{ error.message }}</h3>
<p>
<nuxt-link to="/">
<button>{{ $t("go_home") }}</button>
<button>{{ $t('go_home') }}</button>
</nuxt-link>
</p>
<p>
<a href @click.prevent="reloadApplication">{{ $t("reload") }}</a>
<a href @click.prevent="reloadApplication">{{ $t('reload') }}</a>
</p>
</div>
</template>
@@ -35,20 +31,20 @@
<script>
export default {
props: ["error"],
props: ['error'],
methods: {
reloadApplication() {
this.$router.push("/", () => window.location.reload());
}
this.$router.push('/', () => window.location.reload())
},
},
head() {
return {
bodyAttrs: {
class: "sticky-footer"
}
};
}
};
class: 'sticky-footer',
},
}
},
}
</script>

View File

@@ -1,5 +1,5 @@
export default function({ route, redirect }) {
if (route.fullPath !== "/") {
return redirect("/");
if (route.fullPath !== '/') {
return redirect('/')
}
}

View File

@@ -1,231 +1,227 @@
// Some helpful application constants.
// TODO: Use these when rendering the pages (rather than just for head/meta tags...)
export const meta = {
name: "Postwoman",
shortDescription: "A free, fast and beautiful API request builder",
name: 'Postwoman',
shortDescription: 'A free, fast and beautiful API request builder',
description:
"Web alternative to Postman - Helps you create requests faster, saving precious time on development."
};
'Web alternative to Postman - Helps you create requests faster, saving precious time on development.',
}
// Sets the base path for the router.
// Important for deploying to GitHub pages.
// -- Travis includes the author in the repo slug,
// so if there's a /, we need to get everything after it.
let repoName = (process.env.TRAVIS_REPO_SLUG || "").split("/").pop();
let repoName = (process.env.TRAVIS_REPO_SLUG || '').split('/').pop()
export const routerBase =
process.env.DEPLOY_ENV === "GH_PAGES"
process.env.DEPLOY_ENV === 'GH_PAGES'
? {
router: {
base: `/${repoName}/`
}
base: `/${repoName}/`,
},
}
: {
router: {
base: "/"
}
};
base: '/',
},
}
export default {
mode: "spa",
mode: 'spa',
/*
** Headers of the page
*/
server: {
host: "0.0.0.0" // default: localhost
host: '0.0.0.0', // default: localhost
},
render: {
bundleRenderer: {
shouldPreload: (file, type) => {
return ["script", "style", "font"].includes(type);
}
}
return ['script', 'style', 'font'].includes(type)
},
},
},
head: {
title: `${meta.name} \u2022 ${meta.shortDescription}`,
meta: [
{
charset: "utf-8"
charset: 'utf-8',
},
{
name: "viewport",
name: 'viewport',
content:
"width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover, minimal-ui"
'width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover, minimal-ui',
},
{
hid: "description",
name: "description",
content: meta.description || ""
hid: 'description',
name: 'description',
content: meta.description || '',
},
{
name: "keywords",
name: 'keywords',
content:
"postwoman, postwoman chrome, postwoman online, postwoman for mac, postwoman app, postwoman for windows, postwoman google chrome, postwoman chrome app, get postwoman, postwoman web, postwoman android, postwoman app for chrome, postwoman mobile app, postwoman web app, api, request, testing, tool, rest, websocket, sse, graphql"
'postwoman, postwoman chrome, postwoman online, postwoman for mac, postwoman app, postwoman for windows, postwoman google chrome, postwoman chrome app, get postwoman, postwoman web, postwoman android, postwoman app for chrome, postwoman mobile app, postwoman web app, api, request, testing, tool, rest, websocket, sse, graphql',
},
{
name: "X-UA-Compatible",
content: "IE=edge, chrome=1"
name: 'X-UA-Compatible',
content: 'IE=edge, chrome=1',
},
{
itemprop: "name",
content: `${meta.name} \u2022 ${meta.shortDescription}`
itemprop: 'name',
content: `${meta.name} \u2022 ${meta.shortDescription}`,
},
{
itemprop: "description",
content: meta.description
itemprop: 'description',
content: meta.description,
},
{
itemprop: "image",
content: `https://postwoman.io/logo.jpg`
itemprop: 'image',
content: `https://postwoman.io/logo.jpg`,
},
// Add to homescreen for Chrome on Android. Fallback for PWA (handled by nuxt)
{
name: "application-name",
content: meta.name
name: 'application-name',
content: meta.name,
},
// Add to homescreen for Safari on iOS
{
name: "apple-mobile-web-app-capable",
content: "yes"
name: 'apple-mobile-web-app-capable',
content: 'yes',
},
{
name: "apple-mobile-web-app-status-bar-style",
content: "black-translucent"
name: 'apple-mobile-web-app-status-bar-style',
content: 'black-translucent',
},
{
name: "apple-mobile-web-app-title",
content: meta.name
name: 'apple-mobile-web-app-title',
content: meta.name,
},
// Windows phone tile icon
{
name: "msapplication-TileImage",
content: `${routerBase.router.base}icons/icon-144x144.png`
name: 'msapplication-TileImage',
content: `${routerBase.router.base}icons/icon-144x144.png`,
},
{
name: "msapplication-TileColor",
content: "#202124"
name: 'msapplication-TileColor',
content: '#202124',
},
{
name: "msapplication-tap-highlight",
content: "no"
name: 'msapplication-tap-highlight',
content: 'no',
},
// OpenGraph
{
property: "og:site_name",
content: meta.name
property: 'og:site_name',
content: meta.name,
},
{
property: "og:url",
content: "https://postwoman.io"
property: 'og:url',
content: 'https://postwoman.io',
},
{
property: "og:type",
content: "website"
property: 'og:type',
content: 'website',
},
{
property: "og:title",
content: `${meta.name} \u2022 ${meta.shortDescription}`
property: 'og:title',
content: `${meta.name} \u2022 ${meta.shortDescription}`,
},
{
property: "og:description",
content: meta.description
property: 'og:description',
content: meta.description,
},
{
property: "og:image",
content: `https://postwoman.io/logo.jpg`
property: 'og:image',
content: `https://postwoman.io/logo.jpg`,
},
// Twitter
{
name: "twitter:card",
content: "summary_large_image"
name: 'twitter:card',
content: 'summary_large_image',
},
{
name: "twitter:site",
content: "@liyasthomas"
name: 'twitter:site',
content: '@liyasthomas',
},
{
name: "twitter:creator",
content: "@liyasthomas"
name: 'twitter:creator',
content: '@liyasthomas',
},
{
name: "twitter:url",
content: "https://postwoman.io"
name: 'twitter:url',
content: 'https://postwoman.io',
},
{
name: "twitter:title",
content: `${meta.name} \u2022 ${meta.shortDescription}`
name: 'twitter:title',
content: `${meta.name} \u2022 ${meta.shortDescription}`,
},
{
name: "twitter:description",
content: meta.description
name: 'twitter:description',
content: meta.description,
},
{
name: "twitter:image",
content: "https://postwoman.io/logo.jpg"
}
name: 'twitter:image',
content: 'https://postwoman.io/logo.jpg',
},
],
link: [
{
rel: "icon",
type: "image/x-icon",
href: `${routerBase.router.base}favicon.ico`
rel: 'icon',
type: 'image/x-icon',
href: `${routerBase.router.base}favicon.ico`,
},
// Home-screen icons (iOS)
{
rel: "apple-touch-icon",
href: `${routerBase.router.base}icons/icon-48x48.png`
rel: 'apple-touch-icon',
href: `${routerBase.router.base}icons/icon-48x48.png`,
},
{
rel: "apple-touch-icon",
sizes: "72x72",
href: `${routerBase.router.base}icons/icon-72x72.png`
rel: 'apple-touch-icon',
sizes: '72x72',
href: `${routerBase.router.base}icons/icon-72x72.png`,
},
{
rel: "apple-touch-icon",
sizes: "96x96",
href: `${routerBase.router.base}icons/icon-96x96.png`
rel: 'apple-touch-icon',
sizes: '96x96',
href: `${routerBase.router.base}icons/icon-96x96.png`,
},
{
rel: "apple-touch-icon",
sizes: "144x144",
href: `${routerBase.router.base}icons/icon-144x144.png`
rel: 'apple-touch-icon',
sizes: '144x144',
href: `${routerBase.router.base}icons/icon-144x144.png`,
},
{
rel: "apple-touch-icon",
sizes: "192x192",
href: `${routerBase.router.base}icons/icon-192x192.png`
}
]
rel: 'apple-touch-icon',
sizes: '192x192',
href: `${routerBase.router.base}icons/icon-192x192.png`,
},
],
},
/*
** Customize the progress-bar color
*/
loading: {
color: "var(--ac-color)"
color: 'var(--ac-color)',
},
/*
** Customize the loading indicator
*/
loadingIndicator: {
name: "pulse",
color: "var(--ac-color)",
background: "var(--bg-color)"
name: 'pulse',
color: 'var(--ac-color)',
background: 'var(--bg-color)',
},
/*
** Global CSS
*/
css: [
"~/assets/css/styles.scss",
"~/assets/css/themes.scss",
"~/assets/css/fonts.scss"
],
css: ['~/assets/css/styles.scss', '~/assets/css/themes.scss', '~/assets/css/fonts.scss'],
/*
** Plugins to load before mounting the App
*/
plugins: [
{
src: "~/plugins/vuex-persist"
src: '~/plugins/vuex-persist',
},
{
src: "~/plugins/v-tooltip"
}
src: '~/plugins/v-tooltip',
},
],
/*
** Nuxt.js dev-modules
@@ -236,136 +232,136 @@ export default {
*/
modules: [
// See https://goo.gl/OOhYW5
["@nuxtjs/pwa"],
["@nuxtjs/axios"],
["@nuxtjs/toast"],
["@nuxtjs/google-analytics"],
["@nuxtjs/sitemap"],
['@nuxtjs/pwa'],
['@nuxtjs/axios'],
['@nuxtjs/toast'],
['@nuxtjs/google-analytics'],
['@nuxtjs/sitemap'],
[
"@nuxtjs/google-tag-manager",
'@nuxtjs/google-tag-manager',
{
id: process.env.GTM_ID || "GTM-MXWD8NQ"
}
id: process.env.GTM_ID || 'GTM-MXWD8NQ',
},
],
["@nuxtjs/robots"],
["nuxt-i18n"]
['@nuxtjs/robots'],
['nuxt-i18n'],
],
pwa: {
manifest: {
name: meta.name,
short_name: meta.name,
display: "standalone",
display: 'standalone',
theme_color: "#202124",
background_color: "#202124",
start_url: `${routerBase.router.base}`
theme_color: '#202124',
background_color: '#202124',
start_url: `${routerBase.router.base}`,
},
meta: {
description: meta.shortDescription,
theme_color: "#202124"
theme_color: '#202124',
},
icons: (sizes => {
let icons = [];
let icons = []
for (let size of sizes) {
icons.push({
src: `${routerBase.router.base}icons/icon-${size}x${size}.png`,
type: "image/png",
sizes: `${size}x${size}`
});
type: 'image/png',
sizes: `${size}x${size}`,
})
}
return icons;
})([48, 72, 96, 144, 192, 512])
return icons
})([48, 72, 96, 144, 192, 512]),
},
toast: {
position: "bottom-center",
position: 'bottom-center',
duration: 3000,
theme: "bubble",
keepOnHover: true
theme: 'bubble',
keepOnHover: true,
},
googleAnalytics: {
id: process.env.GA_ID || "UA-61422507-2"
id: process.env.GA_ID || 'UA-61422507-2',
},
sitemap: {
hostname: "https://postwoman.io"
hostname: 'https://postwoman.io',
},
robots: {
UserAgent: "*",
Disallow: "",
Allow: "/",
Sitemap: "https://postwoman.io/sitemap.xml"
UserAgent: '*',
Disallow: '',
Allow: '/',
Sitemap: 'https://postwoman.io/sitemap.xml',
},
i18n: {
locales: [
{
code: "en",
name: "English",
iso: "en-US",
file: "en-US.js"
code: 'en',
name: 'English',
iso: 'en-US',
file: 'en-US.js',
},
{
code: "es",
name: "Español",
iso: "es-ES",
file: "es-ES.js"
code: 'es',
name: 'Español',
iso: 'es-ES',
file: 'es-ES.js',
},
{
code: "fr",
name: "Français",
iso: "fr-FR",
file: "fr-FR.js"
code: 'fr',
name: 'Français',
iso: 'fr-FR',
file: 'fr-FR.js',
},
{
code: "fa",
name: "Farsi",
iso: "fa-IR",
file: "fa-IR.js"
code: 'fa',
name: 'Farsi',
iso: 'fa-IR',
file: 'fa-IR.js',
},
{
code: "pt",
name: "Português Brasileiro",
iso: "pt-BR",
file: "pt-BR.js"
code: 'pt',
name: 'Português Brasileiro',
iso: 'pt-BR',
file: 'pt-BR.js',
},
{
code: "cn",
name: "简体中文",
iso: "zh-CN",
file: "zh-CN.js"
code: 'cn',
name: '简体中文',
iso: 'zh-CN',
file: 'zh-CN.js',
},
{
code: "id",
name: "Bahasa Indonesia",
iso: "id-ID",
file: "id-ID.js"
code: 'id',
name: 'Bahasa Indonesia',
iso: 'id-ID',
file: 'id-ID.js',
},
{
code: "tr",
name: "Türkçe",
iso: "tr-TR",
file: "tr-TR.js"
code: 'tr',
name: 'Türkçe',
iso: 'tr-TR',
file: 'tr-TR.js',
},
{
code: "de",
name: "Deutsch",
iso: "de-DE",
file: "de-DE.js"
code: 'de',
name: 'Deutsch',
iso: 'de-DE',
file: 'de-DE.js',
},
{
code: "ja",
name: "日本語",
iso: "ja-JP",
file: "ja-JP.js"
}
code: 'ja',
name: '日本語',
iso: 'ja-JP',
file: 'ja-JP.js',
},
],
defaultLocale: "en",
defaultLocale: 'en',
vueI18n: {
fallbackLocale: "en"
fallbackLocale: 'en',
},
lazy: true,
langDir: "lang/"
langDir: 'lang/',
},
/*
** Build configuration
@@ -374,16 +370,16 @@ export default {
/*
** You can extend webpack config here
*/
extend(config, ctx) {}
extend(config, ctx) {},
},
/*
** Generate configuration
*/
generate: {
fallback: true
fallback: true,
},
/*
** Router configuration
*/
...routerBase
};
...routerBase,
}

26532
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +1,51 @@
{
"name": "postwoman",
"version": "1.9.0",
"description": "A free, fast and beautiful API request builder",
"author": "liyasthomas",
"private": true,
"scripts": {
"predev": "node build.js --dev",
"dev": "nuxt",
"prebuild": "node build.js",
"build": "nuxt build",
"start": "nuxt start",
"pregenerate": "node build.js",
"generate": "nuxt generate",
"e2e": "cypress run",
"e2e:open": "cypress open",
"dev:e2e": "server-test dev :3000 e2e:open",
"prettier": "prettier --write **/*.{html,js,json,ts,tsx, vue}",
"test": "start-server-and-test start http-get://localhost:3000 e2e"
},
"dependencies": {
"@nuxtjs/axios": "^5.9.5",
"@nuxtjs/google-analytics": "^2.2.3",
"@nuxtjs/google-tag-manager": "^2.3.1",
"@nuxtjs/pwa": "^3.0.0-beta.20",
"@nuxtjs/robots": "^2.4.2",
"@nuxtjs/sitemap": "^2.0.1",
"@nuxtjs/toast": "^3.3.0",
"ace-builds": "^1.4.8",
"firebase": "^7.9.1",
"graphql": "^14.6.0",
"graphql-language-service-interface": "^2.3.3",
"nuxt": "^2.11.0",
"nuxt-i18n": "^6.5.0",
"v-tooltip": "^2.0.3",
"vue-virtual-scroll-list": "^1.4.6",
"vuefire": "^2.2.1",
"vuejs-auto-complete": "^0.9.0",
"vuex-persist": "^2.2.0",
"yargs-parser": "^17.0.0"
},
"devDependencies": {
"cypress": "^4.0.2",
"husky": "^4.2.3",
"lint-staged": "^10.0.7",
"node-sass": "^4.13.1",
"prettier": "^1.19.1",
"sass-loader": "^8.0.2",
"start-server-and-test": "^1.10.8"
}
"name": "postwoman",
"version": "1.9.0",
"description": "A free, fast and beautiful API request builder",
"author": "liyasthomas",
"private": true,
"scripts": {
"predev": "node build.js --dev",
"dev": "nuxt",
"prebuild": "node build.js",
"build": "nuxt build",
"start": "nuxt start",
"pregenerate": "node build.js",
"generate": "nuxt generate",
"e2e": "cypress run",
"e2e:open": "cypress open",
"dev:e2e": "server-test dev :3000 e2e:open",
"prettier": "prettier --write **/*.{html,js,json,ts,tsx,vue}",
"test": "start-server-and-test start http-get://localhost:3000 e2e"
},
"dependencies": {
"@nuxtjs/axios": "^5.9.5",
"@nuxtjs/google-analytics": "^2.2.3",
"@nuxtjs/google-tag-manager": "^2.3.1",
"@nuxtjs/pwa": "^3.0.0-beta.20",
"@nuxtjs/robots": "^2.4.2",
"@nuxtjs/sitemap": "^2.0.1",
"@nuxtjs/toast": "^3.3.0",
"ace-builds": "^1.4.8",
"firebase": "^7.9.1",
"graphql": "^14.6.0",
"graphql-language-service-interface": "^2.3.3",
"nuxt": "^2.11.0",
"nuxt-i18n": "^6.5.0",
"v-tooltip": "^2.0.3",
"vue-virtual-scroll-list": "^1.4.6",
"vuefire": "^2.2.1",
"vuejs-auto-complete": "^0.9.0",
"vuex-persist": "^2.2.0",
"yargs-parser": "^17.0.0"
},
"devDependencies": {
"cypress": "^4.0.2",
"husky": "^4.2.3",
"lint-staged": "^10.0.7",
"node-sass": "^4.13.1",
"prettier": "^1.19.1",
"sass-loader": "^8.0.2",
"start-server-and-test": "^1.10.8"
}
}

View File

@@ -4,20 +4,16 @@
<ul>
<li>
<p class="info">
{{ $t("generate_docs_message") }}
{{ $t('generate_docs_message') }}
</p>
</li>
</ul>
<ul>
<li>
<label for="collectionUpload">
<button
class="icon"
@click="$refs.collectionUpload.click()"
v-tooltip="$t('json')"
>
<button class="icon" @click="$refs.collectionUpload.click()" v-tooltip="$t('json')">
<i class="material-icons">folder</i>
<span>{{ $t("import_collections") }}</span>
<span>{{ $t('import_collections') }}</span>
</button>
</label>
<input
@@ -39,7 +35,7 @@
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
useWorker: false,
}"
/>
</li>
@@ -48,7 +44,7 @@
<li>
<button class="icon" @click="getDoc">
<i class="material-icons">book</i>
<span>{{ $t("generate_docs") }}</span>
<span>{{ $t('generate_docs') }}</span>
</button>
</li>
</ul>
@@ -56,132 +52,108 @@
<pw-section class="green" label="Documentation" ref="documentation">
<p v-if="this.items.length === 0" class="info">
{{ $t("generate_docs_first") }}
{{ $t('generate_docs_first') }}
</p>
<div>
<span
class="collection"
v-for="(collection, index) in this.items"
:key="index"
>
<span class="collection" v-for="(collection, index) in this.items" :key="index">
<h2>
<i class="material-icons">folder</i>
{{ collection.name || $t("none") }}
{{ collection.name || $t('none') }}
</h2>
<span
class="folder"
v-for="(folder, index) in collection.folders"
:key="index"
>
<span class="folder" v-for="(folder, index) in collection.folders" :key="index">
<h3>
<i class="material-icons">folder_open</i>
{{ folder.name || $t("none") }}
{{ folder.name || $t('none') }}
</h3>
<span
class="request"
v-for="(request, index) in folder.requests"
:key="index"
>
<span class="request" v-for="(request, index) in folder.requests" :key="index">
<h4>
<i class="material-icons">insert_drive_file</i>
{{ request.name || $t("none") }}
{{ request.name || $t('none') }}
</h4>
<p class="doc-desc" v-if="request.url">
<span>
{{ $t("url") }}: <code>{{ request.url || $t("none") }}</code>
{{ $t('url') }}: <code>{{ request.url || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.path">
<span>
{{ $t("path") }}:
<code>{{ request.path || $t("none") }}</code>
{{ $t('path') }}:
<code>{{ request.path || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.method">
<span>
{{ $t("method") }}:
<code>{{ request.method || $t("none") }}</code>
{{ $t('method') }}:
<code>{{ request.method || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.auth">
<span>
{{ $t("authentication") }}:
<code>{{ request.auth || $t("none") }}</code>
{{ $t('authentication') }}:
<code>{{ request.auth || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpUser">
<span>
{{ $t("username") }}:
<code>{{ request.httpUser || $t("none") }}</code>
{{ $t('username') }}:
<code>{{ request.httpUser || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpPassword">
<span>
{{ $t("password") }}:
<code>{{ request.httpPassword || $t("none") }}</code>
{{ $t('password') }}:
<code>{{ request.httpPassword || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.bearerToken">
<span>
{{ $t("token") }}:
<code>{{ request.bearerToken || $t("none") }}</code>
{{ $t('token') }}:
<code>{{ request.bearerToken || $t('none') }}</code>
</span>
</p>
<h4 v-if="request.headers.length > 0">{{ $t("headers") }}</h4>
<h4 v-if="request.headers.length > 0">{{ $t('headers') }}</h4>
<span v-if="request.headers">
<p
v-for="header in request.headers"
:key="header.key"
class="doc-desc"
>
<p v-for="header in request.headers" :key="header.key" class="doc-desc">
<span>
{{ header.key || $t("none") }}:
<code>{{ header.value || $t("none") }}</code>
{{ header.key || $t('none') }}:
<code>{{ header.value || $t('none') }}</code>
</span>
</p>
</span>
<h4 v-if="request.params.length > 0">{{ $t("parameters") }}</h4>
<h4 v-if="request.params.length > 0">{{ $t('parameters') }}</h4>
<span v-if="request.params">
<p
v-for="parameter in request.params"
:key="parameter.key"
class="doc-desc"
>
<p v-for="parameter in request.params" :key="parameter.key" class="doc-desc">
<span>
{{ parameter.key || $t("none") }}:
<code>{{ parameter.value || $t("none") }}</code>
{{ parameter.key || $t('none') }}:
<code>{{ parameter.value || $t('none') }}</code>
</span>
</p>
</span>
<h4 v-if="request.bodyParam">{{ $t("payload") }}</h4>
<h4 v-if="request.bodyParam">{{ $t('payload') }}</h4>
<span v-if="request.bodyParam">
<p
v-for="payload in request.bodyParam"
:key="payload.key"
class="doc-desc"
>
<p v-for="payload in request.bodyParam" :key="payload.key" class="doc-desc">
<span>
{{ payload.key || $t("none") }}:
<code>{{ payload.value || $t("none") }}</code>
{{ payload.key || $t('none') }}:
<code>{{ payload.value || $t('none') }}</code>
</span>
</p>
</span>
<p class="doc-desc" v-if="request.rawParams">
<span>
{{ $t("parameters") }}:
<code>{{ request.rawParams || $t("none") }}</code>
{{ $t('parameters') }}:
<code>{{ request.rawParams || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.contentType">
<span>
{{ $t("content_type") }}:
<code>{{ request.contentType || $t("none") }}</code>
{{ $t('content_type') }}:
<code>{{ request.contentType || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.requestType">
<span>
{{ $t("request_type") }}:
<code>{{ request.requestType || $t("none") }}</code>
{{ $t('request_type') }}:
<code>{{ request.requestType || $t('none') }}</code>
</span>
</p>
</span>
@@ -193,103 +165,91 @@
>
<h4>
<i class="material-icons">insert_drive_file</i>
{{ request.name || $t("none") }}
{{ request.name || $t('none') }}
</h4>
<p class="doc-desc" v-if="request.url">
<span>
{{ $t("url") }}: <code>{{ request.url || $t("none") }}</code>
{{ $t('url') }}: <code>{{ request.url || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.path">
<span>
{{ $t("path") }}: <code>{{ request.path || $t("none") }}</code>
{{ $t('path') }}: <code>{{ request.path || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.method">
<span>
{{ $t("method") }}:
<code>{{ request.method || $t("none") }}</code>
{{ $t('method') }}:
<code>{{ request.method || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.auth">
<span>
{{ $t("authentication") }}:
<code>{{ request.auth || $t("none") }}</code>
{{ $t('authentication') }}:
<code>{{ request.auth || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpUser">
<span>
{{ $t("username") }}:
<code>{{ request.httpUser || $t("none") }}</code>
{{ $t('username') }}:
<code>{{ request.httpUser || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.httpPassword">
<span>
{{ $t("password") }}:
<code>{{ request.httpPassword || $t("none") }}</code>
{{ $t('password') }}:
<code>{{ request.httpPassword || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.bearerToken">
<span>
{{ $t("token") }}:
<code>{{ request.bearerToken || $t("none") }}</code>
{{ $t('token') }}:
<code>{{ request.bearerToken || $t('none') }}</code>
</span>
</p>
<h4 v-if="request.headers.length > 0">{{ $t("headers") }}</h4>
<h4 v-if="request.headers.length > 0">{{ $t('headers') }}</h4>
<span v-if="request.headers">
<p
v-for="header in request.headers"
:key="header.key"
class="doc-desc"
>
<p v-for="header in request.headers" :key="header.key" class="doc-desc">
<span>
{{ header.key || $t("none") }}:
<code>{{ header.value || $t("none") }}</code>
{{ header.key || $t('none') }}:
<code>{{ header.value || $t('none') }}</code>
</span>
</p>
</span>
<h4 v-if="request.params.length > 0">{{ $t("parameters") }}</h4>
<h4 v-if="request.params.length > 0">{{ $t('parameters') }}</h4>
<span v-if="request.params">
<p
v-for="parameter in request.params"
:key="parameter.key"
class="doc-desc"
>
<p v-for="parameter in request.params" :key="parameter.key" class="doc-desc">
<span>
{{ parameter.key || $t("none") }}:
<code>{{ parameter.value || $t("none") }}</code>
{{ parameter.key || $t('none') }}:
<code>{{ parameter.value || $t('none') }}</code>
</span>
</p>
</span>
<h4 v-if="request.bodyParam">{{ $t("payload") }}</h4>
<h4 v-if="request.bodyParam">{{ $t('payload') }}</h4>
<span v-if="request.bodyParam">
<p
v-for="payload in request.bodyParam"
:key="payload.key"
class="doc-desc"
>
<p v-for="payload in request.bodyParam" :key="payload.key" class="doc-desc">
<span>
{{ payload.key || $t("none") }}:
<code>{{ payload.value || $t("none") }}</code>
{{ payload.key || $t('none') }}:
<code>{{ payload.value || $t('none') }}</code>
</span>
</p>
</span>
<p class="doc-desc" v-if="request.rawParams">
<span>
{{ $t("parameters") }}:
<code>{{ request.rawParams || $t("none") }}</code>
{{ $t('parameters') }}:
<code>{{ request.rawParams || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.contentType">
<span>
{{ $t("content_type") }}:
<code>{{ request.contentType || $t("none") }}</code>
{{ $t('content_type') }}:
<code>{{ request.contentType || $t('none') }}</code>
</span>
</p>
<p class="doc-desc" v-if="request.requestType">
<span>
{{ $t("request_type") }}:
<code>{{ request.requestType || $t("none") }}</code>
{{ $t('request_type') }}:
<code>{{ request.requestType || $t('none') }}</code>
</span>
</p>
</span>
@@ -342,53 +302,53 @@
</style>
<script>
import AceEditor from "../components/ace-editor";
import AceEditor from '../components/ace-editor'
export default {
components: {
"pw-section": () => import("../components/section"),
Editor: AceEditor
'pw-section': () => import('../components/section'),
Editor: AceEditor,
},
data() {
return {
collectionJSON: "[]",
items: []
};
collectionJSON: '[]',
items: [],
}
},
methods: {
uploadCollection() {
this.rawInput = true;
let file = this.$refs.collectionUpload.files[0];
this.rawInput = true
let file = this.$refs.collectionUpload.files[0]
if (file !== undefined && file !== null) {
let reader = new FileReader();
let reader = new FileReader()
reader.onload = ({ target }) => {
this.collectionJSON = target.result;
};
reader.readAsText(file);
this.$toast.info(this.$t("file_imported"), {
icon: "attach_file"
});
this.collectionJSON = target.result
}
reader.readAsText(file)
this.$toast.info(this.$t('file_imported'), {
icon: 'attach_file',
})
} else {
this.$toast.error(this.$t("choose_file"), {
icon: "attach_file"
});
this.$toast.error(this.$t('choose_file'), {
icon: 'attach_file',
})
}
},
getDoc() {
try {
this.items = JSON.parse(this.collectionJSON);
this.$toast.info(this.$t("docs_generated"), {
icon: "book"
});
this.items = JSON.parse(this.collectionJSON)
this.$toast.info(this.$t('docs_generated'), {
icon: 'book',
})
} catch (e) {
this.$toast.error(e, {
icon: "code"
});
icon: 'code',
})
}
}
}
};
},
},
}
</script>

View File

@@ -5,19 +5,14 @@
<pw-section class="blue" :label="$t('endpoint')" ref="endpoint">
<ul>
<li>
<label for="url">{{ $t("url") }}</label>
<input
id="url"
type="url"
v-model="url"
@keyup.enter="getSchema()"
/>
<label for="url">{{ $t('url') }}</label>
<input id="url" type="url" v-model="url" @keyup.enter="getSchema()" />
</li>
<div>
<li>
<label for="get" class="hide-on-small-screen">&nbsp;</label>
<button id="get" name="get" @click="getSchema">
{{ $t("get_schema") }}
{{ $t('get_schema') }}
<span><i class="material-icons">send</i></span>
</button>
</li>
@@ -29,13 +24,9 @@
<ul>
<li>
<div class="flex-wrap">
<label for="headerList">{{ $t("header_list") }}</label>
<label for="headerList">{{ $t('header_list') }}</label>
<div>
<button
class="icon"
@click="headers = []"
v-tooltip.bottom="$t('clear')"
>
<button class="icon" @click="headers = []" v-tooltip.bottom="$t('clear')">
<i class="material-icons">clear_all</i>
</button>
</div>
@@ -60,7 +51,7 @@
@input="
$store.commit('setGQLHeaderKey', {
index,
value: $event
value: $event,
})
"
autofocus
@@ -74,7 +65,7 @@
@change="
$store.commit('setGQLHeaderValue', {
index,
value: $event.target.value
value: $event.target.value,
})
"
autofocus
@@ -97,7 +88,7 @@
<li>
<button class="icon" @click="addRequestHeader">
<i class="material-icons">add</i>
<span>{{ $t("add_new") }}</span>
<span>{{ $t('add_new') }}</span>
</button>
</li>
</ul>
@@ -105,20 +96,18 @@
<pw-section class="green" :label="$t('schema')" ref="schema">
<div class="flex-wrap">
<label>{{ $t("response") }}</label>
<label>{{ $t('response') }}</label>
<div>
<button
class="icon"
@click="ToggleExpandResponse"
ref="ToggleExpandResponse"
v-tooltip="{
content: !expandResponse
? $t('expand_response')
: $t('collapse_response')
content: !expandResponse ? $t('expand_response') : $t('collapse_response'),
}"
>
<i class="material-icons">
{{ !expandResponse ? "unfold_more" : "unfold_less" }}
{{ !expandResponse ? 'unfold_more' : 'unfold_less' }}
</i>
</button>
<button
@@ -149,20 +138,16 @@
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false
useWorker: false,
}"
/>
</pw-section>
<pw-section class="cyan" :label="$t('query')" ref="query">
<div class="flex-wrap">
<label for="gqlQuery">{{ $t("query") }}</label>
<label for="gqlQuery">{{ $t('query') }}</label>
<div>
<button
class="icon"
@click="runQuery()"
v-tooltip.bottom="$t('run_query')"
>
<button class="icon" @click="runQuery()" v-tooltip.bottom="$t('run_query')">
<i class="material-icons">play_arrow</i>
</button>
<button
@@ -184,7 +169,7 @@
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
useWorker: false,
}"
/>
</pw-section>
@@ -199,14 +184,14 @@
fontSize: '16px',
autoScrollEditorIntoView: true,
showPrintMargin: false,
useWorker: false
useWorker: false,
}"
/>
</pw-section>
<pw-section class="purple" label="Response" ref="response">
<div class="flex-wrap">
<label for="responseField">{{ $t("response") }}</label>
<label for="responseField">{{ $t('response') }}</label>
<div>
<button
class="icon"
@@ -228,7 +213,7 @@
autoScrollEditorIntoView: true,
readOnly: true,
showPrintMargin: false,
useWorker: false
useWorker: false,
}"
/>
</pw-section>
@@ -244,14 +229,11 @@
checked="checked"
/>
<label v-if="queryFields.length > 0" for="queries-tab">
{{ $t("queries") }}
{{ $t('queries') }}
</label>
<div v-if="queryFields.length > 0" class="tab">
<div v-for="field in queryFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
<gql-field :gqlField="field" :jumpTypeCallback="handleJumpToType" />
</div>
</div>
@@ -263,14 +245,11 @@
checked="checked"
/>
<label v-if="mutationFields.length > 0" for="mutations-tab">
{{ $t("mutations") }}
{{ $t('mutations') }}
</label>
<div v-if="mutationFields.length > 0" class="tab">
<div v-for="field in mutationFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
<gql-field :gqlField="field" :jumpTypeCallback="handleJumpToType" />
</div>
</div>
@@ -282,14 +261,11 @@
checked="checked"
/>
<label v-if="subscriptionFields.length > 0" for="subscriptions-tab">
{{ $t("subscriptions") }}
{{ $t('subscriptions') }}
</label>
<div v-if="subscriptionFields.length > 0" class="tab">
<div v-for="field in subscriptionFields" :key="field.name">
<gql-field
:gqlField="field"
:jumpTypeCallback="handleJumpToType"
/>
<gql-field :gqlField="field" :jumpTypeCallback="handleJumpToType" />
</div>
</div>
@@ -301,18 +277,11 @@
checked="checked"
/>
<label v-if="gqlTypes.length > 0" for="gqltypes-tab">
{{ $t("types") }}
{{ $t('types') }}
</label>
<div v-if="gqlTypes.length > 0" class="tab">
<div
v-for="type in gqlTypes"
:key="type.name"
:id="`type_${type.name}`"
>
<gql-type
:gqlType="type"
:jumpTypeCallback="handleJumpToType"
/>
<div v-for="type in gqlTypes" :key="type.name" :id="`type_${type.name}`">
<gql-type :gqlType="type" :jumpTypeCallback="handleJumpToType" />
</div>
</div>
</section>
@@ -326,7 +295,7 @@
"
class="info"
>
{{ $t("send_request_first") }}
{{ $t('send_request_first') }}
</p>
</pw-section>
</aside>
@@ -342,373 +311,352 @@
</style>
<script>
import axios from "axios";
import * as gql from "graphql";
import textareaAutoHeight from "../directives/textareaAutoHeight";
import { commonHeaders } from "../functions/headers";
import AceEditor from "../components/ace-editor";
import QueryEditor from "../components/graphql/queryeditor";
import { sendNetworkRequest } from "../functions/network";
import axios from 'axios'
import * as gql from 'graphql'
import textareaAutoHeight from '../directives/textareaAutoHeight'
import { commonHeaders } from '../functions/headers'
import AceEditor from '../components/ace-editor'
import QueryEditor from '../components/graphql/queryeditor'
import { sendNetworkRequest } from '../functions/network'
export default {
directives: {
textareaAutoHeight
textareaAutoHeight,
},
components: {
"pw-section": () => import("../components/section"),
"gql-field": () => import("../components/graphql/field"),
"gql-type": () => import("../components/graphql/type"),
autocomplete: () => import("../components/autocomplete"),
'pw-section': () => import('../components/section'),
'gql-field': () => import('../components/graphql/field'),
'gql-type': () => import('../components/graphql/type'),
autocomplete: () => import('../components/autocomplete'),
Editor: AceEditor,
QueryEditor: QueryEditor
QueryEditor: QueryEditor,
},
data() {
return {
schemaString: "",
schemaString: '',
commonHeaders,
queryFields: [],
mutationFields: [],
subscriptionFields: [],
gqlTypes: [],
responseString: "",
responseString: '',
copyButton: '<i class="material-icons">file_copy</i>',
downloadButton: '<i class="material-icons">get_app</i>',
doneButton: '<i class="material-icons">done</i>',
expandResponse: false,
responseBodyMaxLines: 16
};
responseBodyMaxLines: 16,
}
},
computed: {
url: {
get() {
return this.$store.state.gql.url;
return this.$store.state.gql.url
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "url" });
}
this.$store.commit('setGQLState', { value, attribute: 'url' })
},
},
headers: {
get() {
return this.$store.state.gql.headers;
return this.$store.state.gql.headers
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "headers" });
}
this.$store.commit('setGQLState', { value, attribute: 'headers' })
},
},
gqlQueryString: {
get() {
return this.$store.state.gql.query;
return this.$store.state.gql.query
},
set(value) {
this.$store.commit("setGQLState", { value, attribute: "query" });
}
this.$store.commit('setGQLState', { value, attribute: 'query' })
},
},
variableString: {
get() {
return this.$store.state.gql.variablesJSONString;
return this.$store.state.gql.variablesJSONString
},
set(value) {
this.$store.commit("setGQLState", {
this.$store.commit('setGQLState', {
value,
attribute: "variablesJSONString"
});
}
attribute: 'variablesJSONString',
})
},
},
headerString() {
const result = this.headers
.filter(({ key }) => !!key)
.map(({ key, value }) => `${key}: ${value}`)
.join(",\n");
return result === "" ? "" : `${result}`;
}
.join(',\n')
return result === '' ? '' : `${result}`
},
},
methods: {
handleJumpToType(type) {
const typesTab = document.getElementById("gqltypes-tab");
typesTab.checked = true;
const typesTab = document.getElementById('gqltypes-tab')
typesTab.checked = true
const rootTypeName = this.resolveRootType(type).name;
const rootTypeName = this.resolveRootType(type).name
const target = document.getElementById(`type_${rootTypeName}`);
const target = document.getElementById(`type_${rootTypeName}`)
if (target && this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED) {
target.scrollIntoView({
behavior: "smooth"
});
behavior: 'smooth',
})
}
},
resolveRootType(type) {
let t = type;
while (t.ofType != null) t = t.ofType;
return t;
let t = type
while (t.ofType != null) t = t.ofType
return t
},
copySchema() {
this.$refs.copySchemaCode.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.schemaString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copySchemaCode.innerHTML = this.copyButton),
1000
);
this.$refs.copySchemaCode.innerHTML = this.doneButton
const aux = document.createElement('textarea')
aux.innerText = this.schemaString
document.body.appendChild(aux)
aux.select()
document.execCommand('copy')
document.body.removeChild(aux)
this.$toast.success(this.$t('copied_to_clipboard'), {
icon: 'done',
})
setTimeout(() => (this.$refs.copySchemaCode.innerHTML = this.copyButton), 1000)
},
copyQuery() {
this.$refs.copyQueryButton.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.gqlQueryString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copyQueryButton.innerHTML = this.copyButton),
1000
);
this.$refs.copyQueryButton.innerHTML = this.doneButton
const aux = document.createElement('textarea')
aux.innerText = this.gqlQueryString
document.body.appendChild(aux)
aux.select()
document.execCommand('copy')
document.body.removeChild(aux)
this.$toast.success(this.$t('copied_to_clipboard'), {
icon: 'done',
})
setTimeout(() => (this.$refs.copyQueryButton.innerHTML = this.copyButton), 1000)
},
copyResponse() {
this.$refs.copyResponseButton.innerHTML = this.doneButton;
const aux = document.createElement("textarea");
aux.innerText = this.responseString;
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
this.$toast.success(this.$t("copied_to_clipboard"), {
icon: "done"
});
setTimeout(
() => (this.$refs.copyResponseButton.innerHTML = this.copyButton),
1000
);
this.$refs.copyResponseButton.innerHTML = this.doneButton
const aux = document.createElement('textarea')
aux.innerText = this.responseString
document.body.appendChild(aux)
aux.select()
document.execCommand('copy')
document.body.removeChild(aux)
this.$toast.success(this.$t('copied_to_clipboard'), {
icon: 'done',
})
setTimeout(() => (this.$refs.copyResponseButton.innerHTML = this.copyButton), 1000)
},
async runQuery() {
const startTime = Date.now();
const startTime = Date.now()
this.$nuxt.$loading.start();
this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED &&
this.scrollInto("response");
this.$nuxt.$loading.start()
this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED && this.scrollInto('response')
try {
let headers = {};
let headers = {}
this.headers.forEach(header => {
headers[header.key] = header.value;
});
headers[header.key] = header.value
})
let variables = JSON.parse(this.variableString);
let variables = JSON.parse(this.variableString)
const gqlQueryString = this.gqlQueryString;
const gqlQueryString = this.gqlQueryString
const reqOptions = {
method: "post",
method: 'post',
url: this.url,
headers: {
...headers,
"content-type": "application/json"
'content-type': 'application/json',
},
data: JSON.stringify({ query: gqlQueryString, variables })
};
data: JSON.stringify({ query: gqlQueryString, variables }),
}
const data = await sendNetworkRequest(reqOptions, this.$store);
const data = await sendNetworkRequest(reqOptions, this.$store)
this.responseString = JSON.stringify(data.data, null, 2);
this.responseString = JSON.stringify(data.data, null, 2)
this.$nuxt.$loading.finish();
const duration = Date.now() - startTime;
this.$toast.info(this.$t("finished_in", { duration }), {
icon: "done"
});
this.$nuxt.$loading.finish()
const duration = Date.now() - startTime
this.$toast.info(this.$t('finished_in', { duration }), {
icon: 'done',
})
} catch (error) {
this.$nuxt.$loading.finish();
this.$nuxt.$loading.finish()
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
icon: "error"
});
console.log("Error", error);
this.$toast.error(`${error} ${this.$t('f12_details')}`, {
icon: 'error',
})
console.log('Error', error)
}
},
async getSchema() {
const startTime = Date.now();
this.schemaString = this.$t("loading");
this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED &&
this.scrollInto("schema");
const startTime = Date.now()
this.schemaString = this.$t('loading')
this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED && this.scrollInto('schema')
// Start showing the loading bar as soon as possible.
// The nuxt axios module will hide it when the request is made.
this.$nuxt.$loading.start();
this.$nuxt.$loading.start()
try {
const query = JSON.stringify({
query: gql.getIntrospectionQuery()
});
query: gql.getIntrospectionQuery(),
})
let headers = {};
let headers = {}
this.headers.forEach(header => {
headers[header.key] = header.value;
});
headers[header.key] = header.value
})
const reqOptions = {
method: "post",
method: 'post',
url: this.url,
headers: {
...headers,
"content-type": "application/json"
'content-type': 'application/json',
},
data: query
};
data: query,
}
// console.log(reqOptions);
const reqConfig = this.$store.state.postwoman.settings.PROXY_ENABLED
? {
method: "post",
method: 'post',
url:
this.$store.state.postwoman.settings.PROXY_URL ||
`https://postwoman.apollotv.xyz/`,
data: reqOptions
this.$store.state.postwoman.settings.PROXY_URL || `https://postwoman.apollotv.xyz/`,
data: reqOptions,
}
: reqOptions;
: reqOptions
const res = await axios(reqConfig);
const res = await axios(reqConfig)
const data = this.$store.state.postwoman.settings.PROXY_ENABLED
? res.data
: res;
const data = this.$store.state.postwoman.settings.PROXY_ENABLED ? res.data : res
const schema = gql.buildClientSchema(data.data.data);
const schema = gql.buildClientSchema(data.data.data)
this.schemaString = gql.printSchema(schema, {
commentDescriptions: true
});
commentDescriptions: true,
})
if (schema.getQueryType()) {
const fields = schema.getQueryType().getFields();
const qFields = [];
const fields = schema.getQueryType().getFields()
const qFields = []
for (const field in fields) {
qFields.push(fields[field]);
qFields.push(fields[field])
}
this.queryFields = qFields;
this.queryFields = qFields
}
if (schema.getMutationType()) {
const fields = schema.getMutationType().getFields();
const mFields = [];
const fields = schema.getMutationType().getFields()
const mFields = []
for (const field in fields) {
mFields.push(fields[field]);
mFields.push(fields[field])
}
this.mutationFields = mFields;
this.mutationFields = mFields
}
if (schema.getSubscriptionType()) {
const fields = schema.getSubscriptionType().getFields();
const sFields = [];
const fields = schema.getSubscriptionType().getFields()
const sFields = []
for (const field in fields) {
sFields.push(fields[field]);
sFields.push(fields[field])
}
this.subscriptionFields = sFields;
this.subscriptionFields = sFields
}
const typeMap = schema.getTypeMap();
const types = [];
const typeMap = schema.getTypeMap()
const types = []
const queryTypeName = schema.getQueryType()
? schema.getQueryType().name
: "";
const mutationTypeName = schema.getMutationType()
? schema.getMutationType().name
: "";
const queryTypeName = schema.getQueryType() ? schema.getQueryType().name : ''
const mutationTypeName = schema.getMutationType() ? schema.getMutationType().name : ''
const subscriptionTypeName = schema.getSubscriptionType()
? schema.getSubscriptionType().name
: "";
: ''
for (const type in typeMap) {
if (
!typeMap[type].name.startsWith("__") &&
![queryTypeName, mutationTypeName, subscriptionTypeName].includes(
typeMap[type].name
) &&
!typeMap[type].name.startsWith('__') &&
![queryTypeName, mutationTypeName, subscriptionTypeName].includes(typeMap[type].name) &&
typeMap[type] instanceof gql.GraphQLObjectType
) {
types.push(typeMap[type]);
types.push(typeMap[type])
}
}
this.gqlTypes = types;
this.$refs.queryEditor.setValidationSchema(schema);
this.$nuxt.$loading.finish();
const duration = Date.now() - startTime;
this.$toast.info(this.$t("finished_in", { duration }), {
icon: "done"
});
this.gqlTypes = types
this.$refs.queryEditor.setValidationSchema(schema)
this.$nuxt.$loading.finish()
const duration = Date.now() - startTime
this.$toast.info(this.$t('finished_in', { duration }), {
icon: 'done',
})
} catch (error) {
this.$nuxt.$loading.finish();
this.schemaString = `${error}. ${this.$t("check_console_details")}`;
this.$toast.error(`${error} ${this.$t("f12_details")}`, {
icon: "error"
});
console.log("Error", error);
this.$nuxt.$loading.finish()
this.schemaString = `${error}. ${this.$t('check_console_details')}`
this.$toast.error(`${error} ${this.$t('f12_details')}`, {
icon: 'error',
})
console.log('Error', error)
}
},
ToggleExpandResponse() {
this.expandResponse = !this.expandResponse;
this.responseBodyMaxLines =
this.responseBodyMaxLines == Infinity ? 16 : Infinity;
this.expandResponse = !this.expandResponse
this.responseBodyMaxLines = this.responseBodyMaxLines == Infinity ? 16 : Infinity
},
downloadResponse() {
const dataToWrite = JSON.stringify(this.schemaString, null, 2);
const file = new Blob([dataToWrite], { type: "application/json" });
const a = document.createElement("a");
const url = URL.createObjectURL(file);
a.href = url;
a.download = `${this.url} on ${Date()}.graphql`.replace(/\./g, "[dot]");
document.body.appendChild(a);
a.click();
this.$refs.downloadResponse.innerHTML = this.doneButton;
this.$toast.success(this.$t("download_started"), {
icon: "done"
});
const dataToWrite = JSON.stringify(this.schemaString, null, 2)
const file = new Blob([dataToWrite], { type: 'application/json' })
const a = document.createElement('a')
const url = URL.createObjectURL(file)
a.href = url
a.download = `${this.url} on ${Date()}.graphql`.replace(/\./g, '[dot]')
document.body.appendChild(a)
a.click()
this.$refs.downloadResponse.innerHTML = this.doneButton
this.$toast.success(this.$t('download_started'), {
icon: 'done',
})
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
this.$refs.downloadResponse.innerHTML = this.downloadButton;
}, 1000);
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
this.$refs.downloadResponse.innerHTML = this.downloadButton
}, 1000)
},
addRequestHeader(index) {
this.$store.commit("addGQLHeader", {
key: "",
value: ""
});
return false;
this.$store.commit('addGQLHeader', {
key: '',
value: '',
})
return false
},
removeRequestHeader(index) {
// .slice() is used so we get a separate array, rather than just a reference
const oldHeaders = this.headers.slice();
const oldHeaders = this.headers.slice()
this.$store.commit("removeGQLHeader", index);
this.$toast.error(this.$t("deleted"), {
icon: "delete",
this.$store.commit('removeGQLHeader', index)
this.$toast.error(this.$t('deleted'), {
icon: 'delete',
action: {
text: this.$t("undo"),
text: this.$t('undo'),
duration: 4000,
onClick: (e, toastObject) => {
this.headers = oldHeaders;
toastObject.remove();
}
}
});
this.headers = oldHeaders
toastObject.remove()
},
},
})
// console.log(oldHeaders);
},
scrollInto(view) {
this.$refs[view].$el.scrollIntoView({
behavior: "smooth"
});
}
}
};
behavior: 'smooth',
})
},
},
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -2,12 +2,12 @@
<div class="page">
<section id="options">
<input id="tab-one" type="radio" name="options" checked="checked" />
<label for="tab-one">{{ $t("websocket") }}</label>
<label for="tab-one">{{ $t('websocket') }}</label>
<div class="tab">
<pw-section class="blue" :label="$t('request')" ref="request">
<ul>
<li>
<label for="url">{{ $t("url") }}</label>
<label for="url">{{ $t('url') }}</label>
<input
id="url"
type="url"
@@ -19,16 +19,11 @@
<div>
<li>
<label for="connect" class="hide-on-small-screen">&nbsp;</label>
<button
:disabled="!urlValid"
id="connect"
name="connect"
@click="toggleConnection"
>
{{ !connectionState ? $t("connect") : $t("disconnect") }}
<button :disabled="!urlValid" id="connect" name="connect" @click="toggleConnection">
{{ !connectionState ? $t('connect') : $t('disconnect') }}
<span>
<i class="material-icons">
{{ !connectionState ? "sync" : "sync_disabled" }}
{{ !connectionState ? 'sync' : 'sync_disabled' }}
</i>
</span>
</button>
@@ -37,15 +32,10 @@
</ul>
</pw-section>
<pw-section
class="purple"
:label="$t('communication')"
id="response"
ref="response"
>
<pw-section class="purple" :label="$t('communication')" id="response" ref="response">
<ul>
<li>
<label for="log">{{ $t("log") }}</label>
<label for="log">{{ $t('log') }}</label>
<div id="log" name="log" class="log">
<span v-if="communication.log">
<span
@@ -56,13 +46,13 @@
}}{{ logEntry.payload }}</span
>
</span>
<span v-else>{{ $t("waiting_for_connection") }}</span>
<span v-else>{{ $t('waiting_for_connection') }}</span>
</div>
</li>
</ul>
<ul>
<li>
<label for="message">{{ $t("message") }}</label>
<label for="message">{{ $t('message') }}</label>
<input
id="message"
name="message"
@@ -75,13 +65,8 @@
<div>
<li>
<label for="send" class="hide-on-small-screen">&nbsp;</label>
<button
id="send"
name="send"
:disabled="!connectionState"
@click="sendMessage"
>
{{ $t("send") }}
<button id="send" name="send" :disabled="!connectionState" @click="sendMessage">
{{ $t('send') }}
<span>
<i class="material-icons">send</i>
</span>
@@ -92,12 +77,12 @@
</pw-section>
</div>
<input id="tab-two" type="radio" name="options" />
<label for="tab-two">{{ $t("sse") }}</label>
<label for="tab-two">{{ $t('sse') }}</label>
<div class="tab">
<pw-section class="blue" :label="$t('request')" ref="request">
<ul>
<li>
<label for="server">{{ $t("server") }}</label>
<label for="server">{{ $t('server') }}</label>
<input
id="server"
type="url"
@@ -115,10 +100,10 @@
name="start"
@click="toggleSSEConnection"
>
{{ !connectionSSEState ? $t("start") : $t("stop") }}
{{ !connectionSSEState ? $t('start') : $t('stop') }}
<span>
<i class="material-icons">
{{ !connectionSSEState ? "sync" : "sync_disabled" }}
{{ !connectionSSEState ? 'sync' : 'sync_disabled' }}
</i>
</span>
</button>
@@ -127,15 +112,10 @@
</ul>
</pw-section>
<pw-section
class="purple"
:label="$t('communication')"
id="response"
ref="response"
>
<pw-section class="purple" :label="$t('communication')" id="response" ref="response">
<ul>
<li>
<label for="log">{{ $t("events") }}</label>
<label for="log">{{ $t('events') }}</label>
<div id="log" name="log" class="log">
<span v-if="events.log">
<span
@@ -146,7 +126,7 @@
}}{{ logEntry.payload }}</span
>
</span>
<span v-else>{{ $t("waiting_for_connection") }}</span>
<span v-else>{{ $t('waiting_for_connection') }}</span>
</div>
<div id="result"></div>
</li>
@@ -171,7 +151,7 @@ div.log {
&,
span {
font-size: 16px;
font-family: "Roboto Mono", monospace;
font-family: 'Roboto Mono', monospace;
font-weight: 400;
}
@@ -187,252 +167,251 @@ div.log {
<script>
export default {
components: {
"pw-section": () => import("../components/section")
'pw-section': () => import('../components/section'),
},
data() {
return {
connectionState: false,
url: "wss://echo.websocket.org",
url: 'wss://echo.websocket.org',
socket: null,
communication: {
log: null,
input: ""
input: '',
},
connectionSSEState: false,
server: "https://express-eventsource.herokuapp.com/events",
server: 'https://express-eventsource.herokuapp.com/events',
sse: null,
events: {
log: null,
input: ""
}
};
input: '',
},
}
},
computed: {
urlValid() {
const protocol = "^(wss?:\\/\\/)?";
const protocol = '^(wss?:\\/\\/)?'
const validIP = new RegExp(
`${protocol}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
);
)
const validHostname = new RegExp(
`${protocol}(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9/])$`
);
return validIP.test(this.url) || validHostname.test(this.url);
)
return validIP.test(this.url) || validHostname.test(this.url)
},
serverValid() {
const protocol = "^(https?:\\/\\/)?";
const protocol = '^(https?:\\/\\/)?'
const validIP = new RegExp(
`${protocol}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`
);
)
const validHostname = new RegExp(
`${protocol}(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9/])$`
);
return validIP.test(this.server) || validHostname.test(this.server);
}
)
return validIP.test(this.server) || validHostname.test(this.server)
},
},
methods: {
toggleConnection() {
// If it is connecting:
if (!this.connectionState) return this.connect();
if (!this.connectionState) return this.connect()
// Otherwise, it's disconnecting.
else return this.disconnect();
else return this.disconnect()
},
connect() {
this.communication.log = [
{
payload: this.$t("connecting_to", { name: this.url }),
source: "info",
color: "var(--ac-color)"
}
];
payload: this.$t('connecting_to', { name: this.url }),
source: 'info',
color: 'var(--ac-color)',
},
]
try {
this.socket = new WebSocket(this.url);
this.socket = new WebSocket(this.url)
this.socket.onopen = event => {
this.connectionState = true;
this.connectionState = true
this.communication.log = [
{
payload: this.$t("connected_to", { name: this.url }),
source: "info",
color: "var(--ac-color)",
ts: new Date().toLocaleTimeString()
}
];
this.$toast.success(this.$t("connected"), {
icon: "sync"
});
};
payload: this.$t('connected_to', { name: this.url }),
source: 'info',
color: 'var(--ac-color)',
ts: new Date().toLocaleTimeString(),
},
]
this.$toast.success(this.$t('connected'), {
icon: 'sync',
})
}
this.socket.onerror = event => {
this.handleError();
};
this.handleError()
}
this.socket.onclose = event => {
this.connectionState = false;
this.connectionState = false
this.communication.log.push({
payload: this.$t("disconnected_from", { name: this.url }),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
this.$toast.error(this.$t("disconnected"), {
icon: "sync_disabled"
});
};
payload: this.$t('disconnected_from', { name: this.url }),
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
this.$toast.error(this.$t('disconnected'), {
icon: 'sync_disabled',
})
}
this.socket.onmessage = event => {
this.communication.log.push({
payload: event.data,
source: "server",
ts: new Date().toLocaleTimeString()
});
};
source: 'server',
ts: new Date().toLocaleTimeString(),
})
}
} catch (ex) {
this.handleError(ex);
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error"
});
this.handleError(ex)
this.$toast.error(this.$t('something_went_wrong'), {
icon: 'error',
})
}
},
disconnect() {
this.socket.close();
this.socket.close()
},
handleError(error) {
this.disconnect();
this.connectionState = false;
this.disconnect()
this.connectionState = false
this.communication.log.push({
payload: this.$t("error_occurred"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
payload: this.$t('error_occurred'),
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
if (error !== null)
this.communication.log.push({
payload: error,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
},
sendMessage() {
const message = this.communication.input;
this.socket.send(message);
const message = this.communication.input
this.socket.send(message)
this.communication.log.push({
payload: message,
source: "client",
ts: new Date().toLocaleTimeString()
});
this.communication.input = "";
source: 'client',
ts: new Date().toLocaleTimeString(),
})
this.communication.input = ''
},
collapse({ target }) {
const el = target.parentNode.className;
document.getElementsByClassName(el)[0].classList.toggle("hidden");
const el = target.parentNode.className
document.getElementsByClassName(el)[0].classList.toggle('hidden')
},
getSourcePrefix(source) {
const sourceEmojis = {
// Source used for info messages.
info: "\t [INFO]:\t",
info: '\t [INFO]:\t',
// Source used for client to server messages.
client: "\t👽 [SENT]:\t",
client: '\t👽 [SENT]:\t',
// Source used for server to client messages.
server: "\t📥 [RECEIVED]:\t"
};
if (Object.keys(sourceEmojis).includes(source))
return sourceEmojis[source];
return "";
server: '\t📥 [RECEIVED]:\t',
}
if (Object.keys(sourceEmojis).includes(source)) return sourceEmojis[source]
return ''
},
toggleSSEConnection() {
// If it is connecting:
if (!this.connectionSSEState) return this.start();
if (!this.connectionSSEState) return this.start()
// Otherwise, it's disconnecting.
else return this.stop();
else return this.stop()
},
start() {
this.events.log = [
{
payload: this.$t("connecting_to", { name: this.server }),
source: "info",
color: "var(--ac-color)"
}
];
if (typeof EventSource !== "undefined") {
payload: this.$t('connecting_to', { name: this.server }),
source: 'info',
color: 'var(--ac-color)',
},
]
if (typeof EventSource !== 'undefined') {
try {
this.sse = new EventSource(this.server);
this.sse = new EventSource(this.server)
this.sse.onopen = event => {
this.connectionSSEState = true;
this.connectionSSEState = true
this.events.log = [
{
payload: this.$t("connected_to", { name: this.server }),
source: "info",
color: "var(--ac-color)",
ts: new Date().toLocaleTimeString()
}
];
this.$toast.success(this.$t("connected"), {
icon: "sync"
});
};
payload: this.$t('connected_to', { name: this.server }),
source: 'info',
color: 'var(--ac-color)',
ts: new Date().toLocaleTimeString(),
},
]
this.$toast.success(this.$t('connected'), {
icon: 'sync',
})
}
this.sse.onerror = event => {
this.handleSSEError();
};
this.handleSSEError()
}
this.sse.onclose = event => {
this.connectionSSEState = false;
this.connectionSSEState = false
this.events.log.push({
payload: this.$t("disconnected_from", { name: this.server }),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
this.$toast.error(this.$t("disconnected"), {
icon: "sync_disabled"
});
};
payload: this.$t('disconnected_from', { name: this.server }),
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
this.$toast.error(this.$t('disconnected'), {
icon: 'sync_disabled',
})
}
this.sse.onmessage = event => {
this.events.log.push({
payload: event.data,
source: "server",
ts: new Date().toLocaleTimeString()
});
};
source: 'server',
ts: new Date().toLocaleTimeString(),
})
}
} catch (ex) {
this.handleSSEError(ex);
this.$toast.error(this.$t("something_went_wrong"), {
icon: "error"
});
this.handleSSEError(ex)
this.$toast.error(this.$t('something_went_wrong'), {
icon: 'error',
})
}
} else {
this.events.log = [
{
payload: this.$t("browser_support_sse"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
}
];
payload: this.$t('browser_support_sse'),
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
},
]
}
},
handleSSEError(error) {
this.stop();
this.connectionSSEState = false;
this.stop()
this.connectionSSEState = false
this.events.log.push({
payload: this.$t("error_occurred"),
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
payload: this.$t('error_occurred'),
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
if (error !== null)
this.events.log.push({
payload: error,
source: "info",
color: "#ff5555",
ts: new Date().toLocaleTimeString()
});
source: 'info',
color: '#ff5555',
ts: new Date().toLocaleTimeString(),
})
},
stop() {
this.sse.onclose();
this.sse.close();
}
this.sse.onclose()
this.sse.close()
},
},
updated: function() {
this.$nextTick(function() {
const divLog = document.getElementById("log");
divLog.scrollBy(0, divLog.scrollHeight + 100);
});
}
};
const divLog = document.getElementById('log')
divLog.scrollBy(0, divLog.scrollHeight + 100)
})
},
}
</script>

View File

@@ -12,20 +12,20 @@
/>
<i v-else class="material-icons">account_circle</i>
<span>
{{ fb.currentUser.displayName || "Name not found" }}
{{ fb.currentUser.displayName || 'Name not found' }}
</span>
</button>
<br />
<button class="icon">
<i class="material-icons">email</i>
<span>
{{ fb.currentUser.email || "Email not found" }}
{{ fb.currentUser.email || 'Email not found' }}
</span>
</button>
<br />
<button class="icon" @click="logout">
<i class="material-icons">exit_to_app</i>
<span>{{ $t("logout") }}</span>
<span>{{ $t('logout') }}</span>
</button>
<br />
<p v-for="setting in fb.currentSettings" :key="setting.id">
@@ -34,19 +34,19 @@
:on="setting.value"
@change="toggleSettings(setting.name, setting.value)"
>
{{ $t(setting.name) + " " + $t("sync") }}
{{ setting.value ? $t("enabled") : $t("disabled") }}
{{ $t(setting.name) + ' ' + $t('sync') }}
{{ setting.value ? $t('enabled') : $t('disabled') }}
</pw-toggle>
</p>
<p v-if="fb.currentSettings.length !== 3">
<button class="" @click="initSettings">
<i class="material-icons">sync</i>
<span>{{ $t("turn_on") + " " + $t("sync") }}</span>
<span>{{ $t('turn_on') + ' ' + $t('sync') }}</span>
</button>
</p>
</div>
<div v-else>
<label>{{ $t("login_with") }}</label>
<label>{{ $t('login_with') }}</label>
<p>
<button class="icon" @click="signInWithGoogle">
<svg
@@ -86,13 +86,9 @@
<pw-section class="cyan" :label="$t('theme')" ref="theme">
<ul>
<li>
<label>{{ $t("background") }}</label>
<label>{{ $t('background') }}</label>
<div class="backgrounds">
<span
:key="theme.class"
@click="applyTheme(theme)"
v-for="theme in themes"
>
<span :key="theme.class" @click="applyTheme(theme)" v-for="theme in themes">
<swatch
:active="settings.THEME_CLASS === theme.class"
:class="{ vibrant: theme.vibrant }"
@@ -106,7 +102,7 @@
</ul>
<ul>
<li>
<label>{{ $t("color") }}</label>
<label>{{ $t('color') }}</label>
<div class="colors">
<span
:key="entry.color"
@@ -131,25 +127,21 @@
:on="settings.FRAME_COLORS_ENABLED"
@change="toggleSetting('FRAME_COLORS_ENABLED')"
>
{{ $t("multi_color") }}
{{
settings.FRAME_COLORS_ENABLED ? $t("enabled") : $t("disabled")
}}
{{ $t('multi_color') }}
{{ settings.FRAME_COLORS_ENABLED ? $t('enabled') : $t('disabled') }}
</pw-toggle>
</span>
</li>
</ul>
<ul>
</ul>
<ul>
<li>
<span>
<pw-toggle
:on="settings.SCROLL_INTO_ENABLED"
@change="toggleSetting('SCROLL_INTO_ENABLED')"
>
{{ $t("scrollInto_use_toggle") }}
{{
settings.SCROLL_INTO_ENABLED ? $t("enabled") : $t("disabled")
}}
{{ $t('scrollInto_use_toggle') }}
{{ settings.SCROLL_INTO_ENABLED ? $t('enabled') : $t('disabled') }}
</pw-toggle>
</span>
</li>
@@ -164,7 +156,7 @@
:on="settings.EXTENSIONS_ENABLED"
@change="toggleSetting('EXTENSIONS_ENABLED')"
>
{{ $t("extensions_use_toggle") }}
{{ $t('extensions_use_toggle') }}
</pw-toggle>
</div>
</li>
@@ -176,12 +168,9 @@
<li>
<div class="flex-wrap">
<span>
<pw-toggle
:on="settings.PROXY_ENABLED"
@change="toggleSetting('PROXY_ENABLED')"
>
{{ $t("proxy") }}
{{ settings.PROXY_ENABLED ? $t("enabled") : $t("disabled") }}
<pw-toggle :on="settings.PROXY_ENABLED" @change="toggleSetting('PROXY_ENABLED')">
{{ $t('proxy') }}
{{ settings.PROXY_ENABLED ? $t('enabled') : $t('disabled') }}
</pw-toggle>
</span>
<a
@@ -199,12 +188,8 @@
<ul>
<li>
<div class="flex-wrap">
<label for="url">{{ $t("url") }}</label>
<button
class="icon"
@click="resetProxy"
v-tooltip.bottom="$t('reset_default')"
>
<label for="url">{{ $t('url') }}</label>
<button class="icon" @click="resetProxy" v-tooltip.bottom="$t('reset_default')">
<i class="material-icons">clear_all</i>
</button>
</div>
@@ -219,16 +204,11 @@
<ul class="info">
<li>
<p>
{{ $t("postwoman_official_proxy_hosting") }}
{{ $t('postwoman_official_proxy_hosting') }}
<br />
{{ $t("read_the") }}
<a
class="link"
href="https://apollotv.xyz/legal"
target="_blank"
rel="noopener"
>
{{ $t("apollotv_privacy_policy") }} </a
{{ $t('read_the') }}
<a class="link" href="https://apollotv.xyz/legal" target="_blank" rel="noopener">
{{ $t('apollotv_privacy_policy') }} </a
>.
</p>
</li>
@@ -255,14 +235,14 @@
<style scoped lang="scss"></style>
<script>
import firebase from "firebase/app";
import { fb } from "../functions/fb";
import firebase from 'firebase/app'
import { fb } from '../functions/fb'
export default {
components: {
"pw-section": () => import("../components/section"),
"pw-toggle": () => import("../components/toggle"),
swatch: () => import("../components/settings/swatch")
'pw-section': () => import('../components/section'),
'pw-toggle': () => import('../components/toggle'),
swatch: () => import('../components/settings/swatch'),
},
data() {
@@ -272,265 +252,253 @@ export default {
// set the relevant values.
themes: [
{
color: "#202124",
name: this.$t("kinda_dark"),
class: "",
aceEditor: "twilight"
color: '#202124',
name: this.$t('kinda_dark'),
class: '',
aceEditor: 'twilight',
},
{
color: "#ffffff",
name: this.$t("clearly_white"),
color: '#ffffff',
name: this.$t('clearly_white'),
vibrant: true,
class: "light",
aceEditor: "iplastic"
class: 'light',
aceEditor: 'iplastic',
},
{
color: "#000000",
name: this.$t("just_black"),
class: "black",
aceEditor: "vibrant_ink"
color: '#000000',
name: this.$t('just_black'),
class: 'black',
aceEditor: 'vibrant_ink',
},
{
color: "var(--ac-color)",
name: this.$t("auto_system"),
vibrant: window.matchMedia("(prefers-color-scheme: light)").matches,
class: "auto",
aceEditor: window.matchMedia("(prefers-color-scheme: light)").matches
? "iplastic"
: "twilight"
}
color: 'var(--ac-color)',
name: this.$t('auto_system'),
vibrant: window.matchMedia('(prefers-color-scheme: light)').matches,
class: 'auto',
aceEditor: window.matchMedia('(prefers-color-scheme: light)').matches
? 'iplastic'
: 'twilight',
},
],
// You can define a new color here! It will simply store the color value.
colors: [
// If the color is vibrant, black is used as the active foreground color.
{
color: "#50fa7b",
name: this.$t("green"),
vibrant: true
color: '#50fa7b',
name: this.$t('green'),
vibrant: true,
},
{
color: "#f1fa8c",
name: this.$t("yellow"),
vibrant: true
color: '#f1fa8c',
name: this.$t('yellow'),
vibrant: true,
},
{
color: "#ff79c6",
name: this.$t("pink"),
vibrant: true
color: '#ff79c6',
name: this.$t('pink'),
vibrant: true,
},
{
color: "#ff5555",
name: this.$t("red"),
vibrant: false
color: '#ff5555',
name: this.$t('red'),
vibrant: false,
},
{
color: "#bd93f9",
name: this.$t("purple"),
vibrant: true
color: '#bd93f9',
name: this.$t('purple'),
vibrant: true,
},
{
color: "#ffb86c",
name: this.$t("orange"),
vibrant: true
color: '#ffb86c',
name: this.$t('orange'),
vibrant: true,
},
{
color: "#8be9fd",
name: this.$t("cyan"),
vibrant: true
color: '#8be9fd',
name: this.$t('cyan'),
vibrant: true,
},
{
color: "#57b5f9",
name: this.$t("blue"),
vibrant: false
}
color: '#57b5f9',
name: this.$t('blue'),
vibrant: false,
},
],
settings: {
SCROLL_INTO_ENABLED:
typeof this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED !==
"undefined"
SCROLL_INTO_ENABLED:
typeof this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED !== 'undefined'
? this.$store.state.postwoman.settings.SCROLL_INTO_ENABLED
: true,
THEME_COLOR: "",
THEME_TAB_COLOR: "",
THEME_COLOR: '',
THEME_TAB_COLOR: '',
THEME_COLOR_VIBRANT: true,
FRAME_COLORS_ENABLED:
this.$store.state.postwoman.settings.FRAME_COLORS_ENABLED || false,
PROXY_ENABLED:
this.$store.state.postwoman.settings.PROXY_ENABLED || false,
FRAME_COLORS_ENABLED: this.$store.state.postwoman.settings.FRAME_COLORS_ENABLED || false,
PROXY_ENABLED: this.$store.state.postwoman.settings.PROXY_ENABLED || false,
PROXY_URL:
this.$store.state.postwoman.settings.PROXY_URL ||
"https://postwoman.apollotv.xyz/",
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || "",
this.$store.state.postwoman.settings.PROXY_URL || 'https://postwoman.apollotv.xyz/',
PROXY_KEY: this.$store.state.postwoman.settings.PROXY_KEY || '',
EXTENSIONS_ENABLED:
typeof this.$store.state.postwoman.settings.EXTENSIONS_ENABLED !==
"undefined"
typeof this.$store.state.postwoman.settings.EXTENSIONS_ENABLED !== 'undefined'
? this.$store.state.postwoman.settings.EXTENSIONS_ENABLED
: true
: true,
},
doneButton: '<i class="material-icons">done</i>',
fb
};
fb,
}
},
watch: {
proxySettings: {
deep: true,
handler(value) {
this.applySetting("PROXY_URL", value.url);
this.applySetting("PROXY_KEY", value.key);
}
}
this.applySetting('PROXY_URL', value.url)
this.applySetting('PROXY_KEY', value.key)
},
},
},
methods: {
applyTheme({ class: name, color, aceEditor }) {
this.applySetting("THEME_CLASS", name);
this.applySetting("THEME_ACE_EDITOR", aceEditor);
document
.querySelector("meta[name=theme-color]")
.setAttribute("content", color);
this.applySetting("THEME_TAB_COLOR", color);
document.documentElement.className = name;
this.applySetting('THEME_CLASS', name)
this.applySetting('THEME_ACE_EDITOR', aceEditor)
document.querySelector('meta[name=theme-color]').setAttribute('content', color)
this.applySetting('THEME_TAB_COLOR', color)
document.documentElement.className = name
},
setActiveColor(color, vibrant) {
// By default, the color is vibrant.
if (vibrant === null) vibrant = true;
document.documentElement.style.setProperty("--ac-color", color);
if (vibrant === null) vibrant = true
document.documentElement.style.setProperty('--ac-color', color)
document.documentElement.style.setProperty(
"--act-color",
vibrant ? "rgba(32, 33, 36, 1)" : "rgba(255, 255, 255, 1)"
);
this.applySetting("THEME_COLOR", color.toUpperCase());
this.applySetting("THEME_COLOR_VIBRANT", vibrant);
'--act-color',
vibrant ? 'rgba(32, 33, 36, 1)' : 'rgba(255, 255, 255, 1)'
)
this.applySetting('THEME_COLOR', color.toUpperCase())
this.applySetting('THEME_COLOR_VIBRANT', vibrant)
},
getActiveColor() {
// This strips extra spaces and # signs from the strings.
const strip = str => str.replace(/#/g, "").replace(/ /g, "");
const strip = str => str.replace(/#/g, '').replace(/ /g, '')
return `#${strip(
window
.getComputedStyle(document.documentElement)
.getPropertyValue("--ac-color")
).toUpperCase()}`;
window.getComputedStyle(document.documentElement).getPropertyValue('--ac-color')
).toUpperCase()}`
},
applySetting(key, value) {
this.settings[key] = value;
this.$store.commit("postwoman/applySetting", [key, value]);
this.settings[key] = value
this.$store.commit('postwoman/applySetting', [key, value])
},
toggleSetting(key) {
this.settings[key] = !this.settings[key];
this.$store.commit("postwoman/applySetting", [key, this.settings[key]]);
this.settings[key] = !this.settings[key]
this.$store.commit('postwoman/applySetting', [key, this.settings[key]])
},
logout() {
fb.currentUser = null;
fb.currentUser = null
firebase
.auth()
.signOut()
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
this.$toast.info(this.$t("logged_out"), {
icon: "vpn_key"
});
icon: 'error',
})
})
this.$toast.info(this.$t('logged_out'), {
icon: 'vpn_key',
})
},
signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
const provider = new firebase.auth.GoogleAuthProvider()
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
this.$toast.info(`${this.$t('turn_on')} ${this.$t('sync')}`, {
icon: 'sync',
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
text: this.$t('yes'),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
fb.writeSettings('syncHistory', true)
fb.writeSettings('syncCollections', true)
fb.writeSettings('syncEnvironments', true)
this.$router.push({ path: '/settings' })
toastObject.remove()
},
},
})
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
icon: 'error',
})
})
},
signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider();
const provider = new firebase.auth.GithubAuthProvider()
firebase
.auth()
.signInWithPopup(provider)
.then(({ additionalUserInfo }) => {
if (additionalUserInfo.isNewUser) {
this.$toast.info(`${this.$t("turn_on")} ${this.$t("sync")}`, {
icon: "sync",
this.$toast.info(`${this.$t('turn_on')} ${this.$t('sync')}`, {
icon: 'sync',
duration: null,
closeOnSwipe: false,
action: {
text: this.$t("yes"),
text: this.$t('yes'),
onClick: (e, toastObject) => {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
this.$router.push({ path: "/settings" });
toastObject.remove();
}
}
});
fb.writeSettings('syncHistory', true)
fb.writeSettings('syncCollections', true)
fb.writeSettings('syncEnvironments', true)
this.$router.push({ path: '/settings' })
toastObject.remove()
},
},
})
}
})
.catch(err => {
this.$toast.show(err.message || err, {
icon: "error"
});
});
icon: 'error',
})
})
},
toggleSettings(s, v) {
fb.writeSettings(s, !v);
fb.writeSettings(s, !v)
},
initSettings() {
fb.writeSettings("syncHistory", true);
fb.writeSettings("syncCollections", true);
fb.writeSettings("syncEnvironments", true);
fb.writeSettings('syncHistory', true)
fb.writeSettings('syncCollections', true)
fb.writeSettings('syncEnvironments', true)
},
resetProxy({ target }) {
this.settings.PROXY_URL = `https://postwoman.apollotv.xyz/`;
target.innerHTML = this.doneButton;
this.$toast.info(this.$t("cleared"), {
icon: "clear_all"
});
setTimeout(
() => (target.innerHTML = '<i class="material-icons">clear_all</i>'),
1000
);
}
this.settings.PROXY_URL = `https://postwoman.apollotv.xyz/`
target.innerHTML = this.doneButton
this.$toast.info(this.$t('cleared'), {
icon: 'clear_all',
})
setTimeout(() => (target.innerHTML = '<i class="material-icons">clear_all</i>'), 1000)
},
},
beforeMount() {
this.settings.THEME_COLOR = this.getActiveColor();
this.settings.THEME_COLOR = this.getActiveColor()
},
computed: {
proxySettings() {
return {
url: this.settings.PROXY_URL,
key: this.settings.PROXY_KEY
};
}
}
};
key: this.settings.PROXY_KEY,
}
},
},
}
</script>

View File

@@ -1,4 +1,4 @@
import Vue from "vue";
import VTooltip from "v-tooltip";
import Vue from 'vue'
import VTooltip from 'v-tooltip'
Vue.use(VTooltip);
Vue.use(VTooltip)

View File

@@ -1,5 +1,5 @@
import VuexPersistence from "vuex-persist";
import VuexPersistence from 'vuex-persist'
export default ({ store }) => {
new VuexPersistence().plugin(store);
};
new VuexPersistence().plugin(store)
}

View File

@@ -1,24 +1,24 @@
import Vuex from "vuex";
import state from "./state";
import VuexPersist from "vuex-persist";
import Vuex from 'vuex'
import state from './state'
import VuexPersist from 'vuex-persist'
export default {
install(Vue) {
Vue.use(Vuex);
Vue.use(Vuex)
const vuexLocalStorage = new VuexPersist({
key: "vuex",
key: 'vuex',
storage: window.localStorage,
reducer: ({ ...request }) => ({
...request
})
});
...request,
}),
})
const store = new Vuex.Store({
state,
plugins: [vuexLocalStorage.plugin]
});
plugins: [vuexLocalStorage.plugin],
})
Vue.prototype.$store = store;
}
};
Vue.prototype.$store = store
},
}

View File

@@ -1,97 +1,97 @@
export default {
setState({ request }, { attribute, value }) {
request[attribute] = value;
request[attribute] = value
},
setGQLState({ gql }, { attribute, value }) {
gql[attribute] = value;
gql[attribute] = value
},
addGQLHeader({ gql }, object) {
gql.headers.push(object);
gql.headers.push(object)
},
removeGQLHeader({ gql }, index) {
gql.headers.splice(index, 1);
gql.headers.splice(index, 1)
},
setGQLHeaderKey({ gql }, { index, value }) {
gql.headers[index].key = value;
gql.headers[index].key = value
},
setGQLHeaderValue({ gql }, { index, value }) {
gql.headers[index].value = value;
gql.headers[index].value = value
},
addHeaders({ request }, value) {
request.headers.push(value);
request.headers.push(value)
},
removeHeaders({ request }, index) {
request.headers.splice(index, 1);
request.headers.splice(index, 1)
},
setKeyHeader({ request }, { index, value }) {
request.headers[index].key = value;
request.headers[index].key = value
},
setValueHeader({ request }, { index, value }) {
request.headers[index].value = value;
request.headers[index].value = value
},
addParams({ request }, value) {
request.params.push(value);
request.params.push(value)
},
removeParams({ request }, index) {
request.params.splice(index, 1);
request.params.splice(index, 1)
},
setKeyParams({ request }, { index, value }) {
request.params[index].key = value;
request.params[index].key = value
},
setValueParams({ request }, { index, value }) {
request.params[index].value = value;
request.params[index].value = value
},
addBodyParams({ request }, value) {
request.bodyParams.push(value);
request.bodyParams.push(value)
},
removeBodyParams({ request }, index) {
request.bodyParams.splice(index, 1);
request.bodyParams.splice(index, 1)
},
setKeyBodyParams({ request }, { index, value }) {
request.bodyParams[index].key = value;
request.bodyParams[index].key = value
},
setValueBodyParams({ request }, { index, value }) {
request.bodyParams[index].value = value;
request.bodyParams[index].value = value
},
setOAuth2({ oauth2 }, { attribute, value }) {
oauth2[attribute] = value;
oauth2[attribute] = value
},
addOAuthToken({ oauth2 }, value) {
oauth2.tokens.push(value);
oauth2.tokens.push(value)
},
removeOAuthToken({ oauth2 }, index) {
oauth2.tokens.splice(index, 1);
oauth2.tokens.splice(index, 1)
},
setOAuthTokenName({ oauth2 }, { index, value }) {
oauth2.tokens[index].name = value;
oauth2.tokens[index].name = value
},
addOAuthTokenReq({ oauth2 }, value) {
oauth2.tokenReqs.push(value);
oauth2.tokenReqs.push(value)
},
removeOAuthTokenReq({ oauth2 }, index) {
oauth2.tokenReqs.splice(index, 1);
}
};
oauth2.tokenReqs.splice(index, 1)
},
}

View File

@@ -1,27 +1,27 @@
import Vue from "vue";
import Vue from 'vue'
export const SETTINGS_KEYS = [
/**
* Whether or not to enable scrolling to a specified element, when certain
* actions are triggered.
*/
"SCROLL_INTO_ENABLED",
'SCROLL_INTO_ENABLED',
/**
* The CSS class that should be applied to the root element.
* Essentially, the name of the background theme.
*/
"THEME_CLASS",
'THEME_CLASS',
/**
* The hex color code for the currently active theme.
*/
"THEME_COLOR",
'THEME_COLOR',
/**
* The hex color code for browser tab color.
*/
"THEME_TAB_COLOR",
'THEME_TAB_COLOR',
/**
* Whether or not THEME_COLOR is considered 'vibrant'.
@@ -30,247 +30,237 @@ export const SETTINGS_KEYS = [
* any text placed on the theme color will have its color
* inverted from white to black.
*/
"THEME_COLOR_VIBRANT",
'THEME_COLOR_VIBRANT',
/**
* The Ace editor theme
*/
"THEME_ACE_EDITOR",
'THEME_ACE_EDITOR',
/**
* Normally, section frames are multicolored in the UI
* to emphasise the different sections.
* This setting allows that to be turned off.
*/
"FRAME_COLORS_ENABLED",
'FRAME_COLORS_ENABLED',
/**
* Whether or not requests should be proxied.
*/
"PROXY_ENABLED",
'PROXY_ENABLED',
/**
* The URL of the proxy to connect to for requests.
*/
"PROXY_URL",
'PROXY_URL',
/**
* The security key of the proxy.
*/
"PROXY_KEY",
'PROXY_KEY',
/**
* An array of properties to exclude from the URL.
* e.g. 'auth'
*/
"URL_EXCLUDES",
'URL_EXCLUDES',
/**
* A boolean value indicating whether to use the browser extensions
* to run the requests
*/
"EXTENSIONS_ENABLED"
];
'EXTENSIONS_ENABLED',
]
export const state = () => ({
settings: {},
collections: [
{
name: "My Collection",
name: 'My Collection',
folders: [],
requests: []
}
requests: [],
},
],
environments: [
{
name: "My Environment Variables",
variables: []
}
name: 'My Environment Variables',
variables: [],
},
],
editingEnvironment: {},
selectedRequest: {},
editingRequest: {}
});
editingRequest: {},
})
export const mutations = {
applySetting({ settings }, setting) {
if (
setting === null ||
!(setting instanceof Array) ||
setting.length !== 2
) {
throw new Error(
"You must provide a setting (array in the form [key, value])"
);
if (setting === null || !(setting instanceof Array) || setting.length !== 2) {
throw new Error('You must provide a setting (array in the form [key, value])')
}
const [key, value] = setting;
const [key, value] = setting
// Do not just remove this check.
// Add your settings key to the SETTINGS_KEYS array at the
// top of the file.
// This is to ensure that application settings remain documented.
if (!SETTINGS_KEYS.includes(key)) {
throw new Error(`The settings structure does not include the key ${key}`);
throw new Error(`The settings structure does not include the key ${key}`)
}
settings[key] = value;
settings[key] = value
},
removeVariables({ editingEnvironment }, value) {
editingEnvironment.variables = value;
editingEnvironment.variables = value
},
setEditingEnvironment(state, value) {
state.editingEnvironment = { ...value };
state.editingEnvironment = { ...value }
},
setVariableKey({ editingEnvironment }, { index, value }) {
editingEnvironment.variables[index].key = value;
editingEnvironment.variables[index].key = value
},
setVariableValue({ editingEnvironment }, { index, value }) {
editingEnvironment.variables[index].value = testValue(value);
editingEnvironment.variables[index].value = testValue(value)
},
removeVariable({ editingEnvironment }, variables) {
editingEnvironment.variables = variables;
editingEnvironment.variables = variables
},
addVariable({ editingEnvironment }, value) {
editingEnvironment.variables.push(value);
editingEnvironment.variables.push(value)
},
replaceEnvironments(state, environments) {
state.environments = environments;
state.environments = environments
},
importAddEnvironments(state, { environments, confirmation }) {
const duplicateEnvironment = environments.some(
item => {
return state.environments.some(
item2 => {
return item.name.toLowerCase() === item2.name.toLowerCase();
});
}
);
const duplicateEnvironment = environments.some(item => {
return state.environments.some(item2 => {
return item.name.toLowerCase() === item2.name.toLowerCase()
})
})
if (duplicateEnvironment) {
this.$toast.info("Duplicate environment");
return;
};
state.environments = [...state.environments, ...environments];
this.$toast.info('Duplicate environment')
return
}
state.environments = [...state.environments, ...environments]
let index = 0;
let index = 0
for (let environment of state.environments) {
environment.environmentIndex = index;
index += 1;
environment.environmentIndex = index
index += 1
}
this.$toast.info(confirmation, {
icon: "folder_shared"
});
icon: 'folder_shared',
})
},
removeEnvironment({ environments }, environmentIndex) {
environments.splice(environmentIndex, 1);
environments.splice(environmentIndex, 1)
},
saveEnvironment({ environments }, payload) {
const { environment, environmentIndex } = payload;
const { name } = environment;
const duplicateEnvironment = environments.length === 1
? false
: environments.some(
item =>
item.environmentIndex !== environmentIndex &&
item.name.toLowerCase() === name.toLowerCase()
);
const { environment, environmentIndex } = payload
const { name } = environment
const duplicateEnvironment =
environments.length === 1
? false
: environments.some(
item =>
item.environmentIndex !== environmentIndex &&
item.name.toLowerCase() === name.toLowerCase()
)
if (duplicateEnvironment) {
this.$toast.info("Duplicate environment");
return;
this.$toast.info('Duplicate environment')
return
}
environments[environmentIndex] = environment;
environments[environmentIndex] = environment
},
replaceCollections(state, collections) {
state.collections = collections;
state.collections = collections
},
importCollections(state, collections) {
state.collections = [...state.collections, ...collections];
state.collections = [...state.collections, ...collections]
let index = 0;
let index = 0
for (let collection of collections) {
collection.collectionIndex = index;
index += 1;
collection.collectionIndex = index
index += 1
}
},
addNewCollection({ collections }, collection) {
const { name } = collection;
const { name } = collection
const duplicateCollection = collections.some(
item => item.name.toLowerCase() === name.toLowerCase()
);
)
if (duplicateCollection) {
this.$toast.info("Duplicate collection");
return;
this.$toast.info('Duplicate collection')
return
}
collections.push({
name: "",
name: '',
folders: [],
requests: [],
...collection
});
...collection,
})
},
removeCollection({ collections }, payload) {
const { collectionIndex } = payload;
collections.splice(collectionIndex, 1);
const { collectionIndex } = payload
collections.splice(collectionIndex, 1)
},
editCollection({ collections }, payload) {
const {
collection: { name },
collectionIndex
} = payload;
collectionIndex,
} = payload
const duplicateCollection = collections.some(
item => item.name.toLowerCase() === name.toLowerCase()
);
)
if (duplicateCollection) {
this.$toast.info("Duplicate collection");
return;
this.$toast.info('Duplicate collection')
return
}
collections[collectionIndex] = collection;
collections[collectionIndex] = collection
},
addNewFolder({ collections }, payload) {
const { collectionIndex, folder } = payload;
const { collectionIndex, folder } = payload
collections[collectionIndex].folders.push({
name: "",
name: '',
requests: [],
...folder
});
...folder,
})
},
editFolder({ collections }, payload) {
const { collectionIndex, folder, folderIndex } = payload;
Vue.set(collections[collectionIndex].folders, folderIndex, folder);
const { collectionIndex, folder, folderIndex } = payload
Vue.set(collections[collectionIndex].folders, folderIndex, folder)
},
removeFolder({ collections }, payload) {
const { collectionIndex, folderIndex } = payload;
collections[collectionIndex].folders.splice(folderIndex, 1);
const { collectionIndex, folderIndex } = payload
collections[collectionIndex].folders.splice(folderIndex, 1)
},
addRequest({ collections }, payload) {
const { request } = payload;
const { request } = payload
// Request that is directly attached to collection
if (request.folder === -1) {
collections[request.collection].requests.push(request);
return;
collections[request.collection].requests.push(request)
return
}
collections[request.collection].folders[request.folder].requests.push(
request
);
collections[request.collection].folders[request.folder].requests.push(request)
},
editRequest({ collections }, payload) {
@@ -280,148 +270,116 @@ export const mutations = {
requestOldIndex,
requestNew,
requestNewCollectionIndex,
requestNewFolderIndex
} = payload;
requestNewFolderIndex,
} = payload
const changedCollection =
requestOldCollectionIndex !== requestNewCollectionIndex;
const changedFolder = requestOldFolderIndex !== requestNewFolderIndex;
const changedPlace = changedCollection || changedFolder;
const changedCollection = requestOldCollectionIndex !== requestNewCollectionIndex
const changedFolder = requestOldFolderIndex !== requestNewFolderIndex
const changedPlace = changedCollection || changedFolder
// set new request
if (requestNewFolderIndex !== undefined) {
Vue.set(
collections[requestNewCollectionIndex].folders[requestNewFolderIndex]
.requests,
collections[requestNewCollectionIndex].folders[requestNewFolderIndex].requests,
requestOldIndex,
requestNew
);
)
} else {
Vue.set(
collections[requestNewCollectionIndex].requests,
requestOldIndex,
requestNew
);
Vue.set(collections[requestNewCollectionIndex].requests, requestOldIndex, requestNew)
}
// remove old request
if (changedPlace) {
if (requestOldFolderIndex !== undefined) {
collections[requestOldCollectionIndex].folders[
requestOldFolderIndex
].requests.splice(requestOldIndex, 1);
} else {
collections[requestOldCollectionIndex].requests.splice(
collections[requestOldCollectionIndex].folders[requestOldFolderIndex].requests.splice(
requestOldIndex,
1
);
)
} else {
collections[requestOldCollectionIndex].requests.splice(requestOldIndex, 1)
}
}
},
saveRequestAs({ collections }, payload) {
const { request, collectionIndex, folderIndex, requestIndex } = payload;
const { request, collectionIndex, folderIndex, requestIndex } = payload
const specifiedCollection = collectionIndex !== undefined;
const specifiedFolder = folderIndex !== undefined;
const specifiedRequest = requestIndex !== undefined;
const specifiedCollection = collectionIndex !== undefined
const specifiedFolder = folderIndex !== undefined
const specifiedRequest = requestIndex !== undefined
if (specifiedCollection && specifiedFolder && specifiedRequest) {
Vue.set(
collections[collectionIndex].folders[folderIndex].requests,
requestIndex,
request
);
Vue.set(collections[collectionIndex].folders[folderIndex].requests, requestIndex, request)
} else if (specifiedCollection && specifiedFolder && !specifiedRequest) {
const requests =
collections[collectionIndex].folders[folderIndex].requests;
const lastRequestIndex = requests.length - 1;
Vue.set(requests, lastRequestIndex + 1, request);
const requests = collections[collectionIndex].folders[folderIndex].requests
const lastRequestIndex = requests.length - 1
Vue.set(requests, lastRequestIndex + 1, request)
} else if (specifiedCollection && !specifiedFolder && specifiedRequest) {
const requests = collections[collectionIndex].requests;
Vue.set(requests, requestIndex, request);
const requests = collections[collectionIndex].requests
Vue.set(requests, requestIndex, request)
} else if (specifiedCollection && !specifiedFolder && !specifiedRequest) {
const requests = collections[collectionIndex].requests;
const lastRequestIndex = requests.length - 1;
Vue.set(requests, lastRequestIndex + 1, request);
const requests = collections[collectionIndex].requests
const lastRequestIndex = requests.length - 1
Vue.set(requests, lastRequestIndex + 1, request)
}
},
saveRequest({ collections }, payload) {
const { request } = payload;
const { request } = payload
// Remove the old request from collection
if (request.hasOwnProperty("oldCollection") && request.oldCollection > -1) {
if (request.hasOwnProperty('oldCollection') && request.oldCollection > -1) {
const folder =
request.hasOwnProperty("oldFolder") && request.oldFolder >= -1
request.hasOwnProperty('oldFolder') && request.oldFolder >= -1
? request.oldFolder
: request.folder;
: request.folder
if (folder > -1) {
collections[request.oldCollection].folders[folder].requests.splice(
request.requestIndex,
1
);
collections[request.oldCollection].folders[folder].requests.splice(request.requestIndex, 1)
} else {
collections[request.oldCollection].requests.splice(
request.requestIndex,
1
);
collections[request.oldCollection].requests.splice(request.requestIndex, 1)
}
} else if (
request.hasOwnProperty("oldFolder") &&
request.oldFolder !== -1
) {
collections[request.collection].folders[folder].requests.splice(
request.requestIndex,
1
);
} else if (request.hasOwnProperty('oldFolder') && request.oldFolder !== -1) {
collections[request.collection].folders[folder].requests.splice(request.requestIndex, 1)
}
delete request.oldCollection;
delete request.oldFolder;
delete request.oldCollection
delete request.oldFolder
// Request that is directly attached to collection
if (request.folder === -1) {
Vue.set(
collections[request.collection].requests,
request.requestIndex,
request
);
return;
Vue.set(collections[request.collection].requests, request.requestIndex, request)
return
}
Vue.set(
collections[request.collection].folders[request.folder].requests,
request.requestIndex,
request
);
)
},
removeRequest({ collections }, payload) {
const { collectionIndex, folderIndex, requestIndex } = payload;
const { collectionIndex, folderIndex, requestIndex } = payload
// Request that is directly attached to collection
if (folderIndex === -1) {
collections[collectionIndex].requests.splice(requestIndex, 1);
return;
collections[collectionIndex].requests.splice(requestIndex, 1)
return
}
collections[collectionIndex].folders[folderIndex].requests.splice(
requestIndex,
1
);
collections[collectionIndex].folders[folderIndex].requests.splice(requestIndex, 1)
},
selectRequest(state, { request }) {
state.selectedRequest = Object.assign({}, request);
}
};
state.selectedRequest = Object.assign({}, request)
},
}
function testValue(myValue) {
try {
return JSON.parse(myValue);
} catch(ex) {
// Now we know it's a string just leave it as a string value.
return myValue;
return JSON.parse(myValue)
} catch (ex) {
// Now we know it's a string just leave it as a string value.
return myValue
}
}

View File

@@ -1,38 +1,38 @@
export default () => ({
request: {
method: "GET",
url: "https://httpbin.org",
path: "/get",
label: "",
auth: "None",
httpUser: "",
httpPassword: "",
passwordFieldType: "password",
bearerToken: "",
method: 'GET',
url: 'https://httpbin.org',
path: '/get',
label: '',
auth: 'None',
httpUser: '',
httpPassword: '',
passwordFieldType: 'password',
bearerToken: '',
headers: [],
params: [],
bodyParams: [],
rawParams: "",
rawParams: '',
rawInput: false,
requestType: "",
contentType: ""
requestType: '',
contentType: '',
},
gql: {
url: "https://rickandmortyapi.com/graphql",
url: 'https://rickandmortyapi.com/graphql',
headers: [],
variablesJSONString: "{}",
query: ""
variablesJSONString: '{}',
query: '',
},
oauth2: {
tokens: [],
tokenReqs: [],
tokenReqSelect: "",
tokenReqName: "",
accessTokenName: "",
oidcDiscoveryUrl: "",
authUrl: "",
accessTokenUrl: "",
clientId: "",
scope: ""
}
});
tokenReqSelect: '',
tokenReqName: '',
accessTokenName: '',
oidcDiscoveryUrl: '',
authUrl: '',
accessTokenUrl: '',
clientId: '',
scope: '',
},
})

View File

@@ -1 +1 @@
{ "message": "FAKE Cat API" }
{ "message": "FAKE Cat API" }

View File

@@ -1,7 +1,7 @@
describe('Visit home', () => {
it('Have a page title with "Postwoman"', () => {
cy.visit('/', { retryOnStatusCodeFailure: true })
.get('title')
.should('contain','Postwoman')
.get('title')
.should('contain', 'Postwoman')
})
})

View File

@@ -3,13 +3,13 @@ describe('Authentication', () => {
cy.visit(`?&auth=Basic Auth&httpUser=foo&httpPassword=bar`, { retryOnStatusCodeFailure: true })
.get('input[name="http_basic_user"]', { timeout: 500 })
.invoke('val')
.then((user) => {
.then(user => {
expect(user === 'foo').to.equal(true)
})
.get('input[name="http_basic_passwd"]')
.invoke('val')
.then((pass) => {
.then(pass => {
expect(pass === 'bar').to.equal(true)
})
})
@@ -30,5 +30,5 @@ describe('Authentication', () => {
.url()
.should('contain', 'foo')
.should('contain', 'bar')
})
})
})

View File

@@ -1,9 +1,12 @@
describe('Proxy disabled - local request', () => {
it('Change default url with query and make a request to local cat api', () => {
cy.seedAndVisit('catapi', '/?url=https://api.thecatapi.com&path=')
.get('#url').then((el) => expect(el.val() === 'https://api.thecatapi.com').to.equal(true))
.get("#path").then((el) => expect(el.val() === '').to.equal(true))
.get('#response-details-wrapper').should($wrapper => {
.get('#url')
.then(el => expect(el.val() === 'https://api.thecatapi.com').to.equal(true))
.get('#path')
.then(el => expect(el.val() === '').to.equal(true))
.get('#response-details-wrapper')
.should($wrapper => {
expect($wrapper).to.contain('FAKE Cat API')
})
})
@@ -12,8 +15,10 @@ describe('Proxy disabled - local request', () => {
describe('Proxy enabled - external request', () => {
it('Enable the proxy and make a request to the real cat api', () => {
cy.enableProxy('/?url=https://api.thecatapi.com&path=')
.get('#send').click()
.get('#response-details-wrapper').should($wrapper => {
.get('#send')
.click()
.get('#response-details-wrapper')
.should($wrapper => {
expect($wrapper).to.contain('Cat API')
})
})

View File

@@ -1,29 +1,31 @@
/**
* Creates cy.seedAndVisit() function
* This function will go to some path and wait for some fake response from 'src/tests/fixtures/*.json'
* @param { String } seedData The name of json at 'src/tests/fixtures/
* @param { String } path The path or query parameters to go -ex. '/?path=/api/users'
* @param { String } method The fake request method
*/
* Creates cy.seedAndVisit() function
* This function will go to some path and wait for some fake response from 'src/tests/fixtures/*.json'
* @param { String } seedData The name of json at 'src/tests/fixtures/
* @param { String } path The path or query parameters to go -ex. '/?path=/api/users'
* @param { String } method The fake request method
*/
Cypress.Commands.add('seedAndVisit', (seedData, path = '/', method = 'GET') => {
cy.server()
.route(method, 'https://api.thecatapi.com/', `fixture:${seedData}`).as('load')
.route(method, 'https://api.thecatapi.com/', `fixture:${seedData}`)
.as('load')
cy.visit(path)
.get('#send').click()
.wait('@load')
.get('#send')
.click()
.wait('@load')
})
/**
* Creates cy.enableProxy() function
* This function will enable the proxy and navigate back to a given path
* @param { String } goBackPath The page go back
*/
Cypress.Commands.add('enableProxy', (goBackPath) => {
* Creates cy.enableProxy() function
* This function will enable the proxy and navigate back to a given path
* @param { String } goBackPath The page go back
*/
Cypress.Commands.add('enableProxy', goBackPath => {
cy.visit('/settings')
.get('#proxy')
.find('.toggle')
.click( { force: true } )
.click({ force: true })
.should('have.class', 'on')
.visit(goBackPath)
})
})

View File

@@ -1 +1 @@
import './commands'
import './commands'