Merge pull request #596 from dmitryyankowski/feature/prettier-formatting
Feature: Add prettier/pretty-quick formatting w/ Husky pre-commit
This commit is contained in:
5
.huskyrc
Normal file
5
.huskyrc
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"hooks": {
|
||||
"pre-commit": "npm run pretty-quick"
|
||||
}
|
||||
}
|
||||
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@@ -0,0 +1,7 @@
|
||||
.dependabot
|
||||
.github
|
||||
.nuxt
|
||||
.postwoman
|
||||
.vscode
|
||||
package-lock.json
|
||||
node_modules
|
||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"printWidth": 100
|
||||
}
|
||||
@@ -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,121 +8,118 @@ 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];
|
||||
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")) {
|
||||
// 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;
|
||||
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;
|
||||
let method
|
||||
if (parsedArguments.X === "POST") {
|
||||
method = "post";
|
||||
method = "post"
|
||||
} else if (parsedArguments.X === "PUT" || parsedArguments["T"]) {
|
||||
method = "put";
|
||||
method = "put"
|
||||
} else if (parsedArguments.X === "PATCH") {
|
||||
method = "patch";
|
||||
method = "patch"
|
||||
} else if (parsedArguments.X === "DELETE") {
|
||||
method = "delete";
|
||||
method = "delete"
|
||||
} else if (parsedArguments.X === "OPTIONS") {
|
||||
method = "options";
|
||||
method = "options"
|
||||
} else if (
|
||||
(parsedArguments["d"] ||
|
||||
parsedArguments["data"] ||
|
||||
@@ -132,95 +129,94 @@ const parseCurlCommand = curlCommand => {
|
||||
parsedArguments["form"]) &&
|
||||
!(parsedArguments["G"] || parsedArguments["get"])
|
||||
) {
|
||||
method = "post";
|
||||
method = "post"
|
||||
} else if (parsedArguments["I"] || parsedArguments["head"]) {
|
||||
method = "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;
|
||||
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 += "?";
|
||||
url += "?"
|
||||
} else {
|
||||
urlQueryString += "&";
|
||||
urlQueryString += "&"
|
||||
}
|
||||
|
||||
if (typeof parsedArguments[option] === "object") {
|
||||
urlQueryString += parsedArguments[option].join("&");
|
||||
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;
|
||||
request.data = parsedArguments.data
|
||||
} else if (parsedArguments["data-binary"]) {
|
||||
request.data = parsedArguments["data-binary"];
|
||||
request.isDataBinary = true;
|
||||
request.data = parsedArguments["data-binary"]
|
||||
request.isDataBinary = true
|
||||
} else if (parsedArguments["d"]) {
|
||||
request.data = parsedArguments["d"];
|
||||
request.data = parsedArguments["d"]
|
||||
} else if (parsedArguments["data-ascii"]) {
|
||||
request.data = parsedArguments["data-ascii"];
|
||||
request.data = parsedArguments["data-ascii"]
|
||||
}
|
||||
|
||||
if (parsedArguments["u"]) {
|
||||
request.auth = parsedArguments["u"];
|
||||
request.auth = parsedArguments["u"]
|
||||
}
|
||||
if (parsedArguments["user"]) {
|
||||
request.auth = 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;
|
||||
request.insecure = true
|
||||
}
|
||||
return request;
|
||||
};
|
||||
return request
|
||||
}
|
||||
|
||||
export default parseCurlCommand;
|
||||
export default parseCurlCommand
|
||||
|
||||
@@ -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",
|
||||
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
|
||||
@@ -40,15 +40,12 @@ const sendPostRequest = async (url, params) => {
|
||||
|
||||
const parseQueryString = searchQuery => {
|
||||
if (searchQuery === "") {
|
||||
return {};
|
||||
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
|
||||
@@ -60,18 +57,18 @@ const getTokenConfiguration = async endpoint => {
|
||||
const options = {
|
||||
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
|
||||
@@ -115,7 +112,7 @@ const base64urlencode = (
|
||||
btoa(String.fromCharCode.apply(null, new Uint8Array(str)))
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
.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;
|
||||
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");
|
||||
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 }
|
||||
|
||||
@@ -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;
|
||||
let deferredPrompt = null
|
||||
window.addEventListener("beforeinstallprompt", event => {
|
||||
deferredPrompt = 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";
|
||||
});
|
||||
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.");
|
||||
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
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
48
build.js
48
build.js
@@ -1,27 +1,26 @@
|
||||
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) {
|
||||
@@ -32,32 +31,29 @@ try {
|
||||
.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" : "");
|
||||
.split(" ")[0] + (IS_DEV_MODE ? " - DEV MODE" : "")
|
||||
if (["", "master"].includes(version.variant)) {
|
||||
delete 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)
|
||||
}
|
||||
|
||||
@@ -19,44 +19,44 @@
|
||||
</style>
|
||||
|
||||
<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 {
|
||||
initialized: false,
|
||||
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() {
|
||||
@@ -68,18 +68,18 @@ export default {
|
||||
});
|
||||
},
|
||||
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, {
|
||||
mode: `ace/mode/${this.lang}`,
|
||||
...this.options
|
||||
});
|
||||
...this.options,
|
||||
})
|
||||
|
||||
// Set the theme and show the editor only after it's been set to prevent FOUC.
|
||||
editor.setTheme(`ace/theme/${this.defineTheme()}`, () => {
|
||||
@@ -90,25 +90,23 @@ export default {
|
||||
|
||||
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;
|
||||
});
|
||||
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
|
||||
},
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
|
||||
@@ -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
|
||||
required: false,
|
||||
},
|
||||
|
||||
source: {
|
||||
type: Array,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
required: false
|
||||
}
|
||||
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>
|
||||
|
||||
@@ -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();
|
||||
name: this.$data.name,
|
||||
})
|
||||
this.$emit("hide-modal")
|
||||
this.syncCollections()
|
||||
},
|
||||
hideModal() {
|
||||
this.$emit("hide-modal");
|
||||
}
|
||||
}
|
||||
};
|
||||
this.$emit("hide-modal")
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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", {
|
||||
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>
|
||||
|
||||
@@ -21,11 +21,7 @@
|
||||
</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>
|
||||
</button>
|
||||
@@ -51,11 +47,7 @@
|
||||
@edit-request="$emit('edit-request', $event)"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
v-if="
|
||||
collection.folders.length === 0 && collection.requests.length === 0
|
||||
"
|
||||
>
|
||||
<li v-if="collection.folders.length === 0 && collection.requests.length === 0">
|
||||
<label>{{ $t("collection_empty") }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -71,7 +63,7 @@
|
||||
request,
|
||||
collectionIndex,
|
||||
folderIndex: undefined,
|
||||
requestIndex: index
|
||||
requestIndex: index,
|
||||
})
|
||||
"
|
||||
/>
|
||||
@@ -98,31 +90,31 @@ ul li {
|
||||
export default {
|
||||
components: {
|
||||
folder: () => import("./folder"),
|
||||
request: () => import("./request")
|
||||
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;
|
||||
if (!confirm("Are you sure you want to remove this Collection?")) return
|
||||
this.$store.commit("postwoman/removeCollection", {
|
||||
collectionIndex: this.collectionIndex
|
||||
});
|
||||
collectionIndex: this.collectionIndex,
|
||||
})
|
||||
},
|
||||
editFolder(collectionIndex, folder, folderIndex) {
|
||||
this.$emit("edit-folder", { collectionIndex, folder, folderIndex });
|
||||
}
|
||||
}
|
||||
};
|
||||
this.$emit("edit-folder", { collectionIndex, folder, folderIndex })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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
|
||||
};
|
||||
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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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", {
|
||||
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>
|
||||
|
||||
@@ -27,22 +27,12 @@
|
||||
/>
|
||||
<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"
|
||||
>
|
||||
@@ -52,17 +42,9 @@
|
||||
</span>
|
||||
<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>
|
||||
@@ -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() {
|
||||
// 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,8 +115,8 @@ 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
|
||||
@@ -147,14 +126,14 @@ export default {
|
||||
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>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
request,
|
||||
collectionIndex,
|
||||
folderIndex,
|
||||
requestIndex: index
|
||||
requestIndex: index,
|
||||
})
|
||||
"
|
||||
/>
|
||||
@@ -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;
|
||||
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>
|
||||
|
||||
@@ -14,16 +14,10 @@
|
||||
<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>
|
||||
</button>
|
||||
@@ -72,11 +66,7 @@
|
||||
<button class="icon" @click="hideModal">
|
||||
{{ $t("cancel") }}
|
||||
</button>
|
||||
<button
|
||||
class="icon primary"
|
||||
@click="exportJSON"
|
||||
v-tooltip="$t('download_file')"
|
||||
>
|
||||
<button class="icon primary" @click="exportJSON" v-tooltip="$t('download_file')">
|
||||
{{ $t("export") }}
|
||||
</button>
|
||||
</span>
|
||||
@@ -86,120 +76,106 @@
|
||||
</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);
|
||||
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"
|
||||
});
|
||||
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"
|
||||
});
|
||||
icon: "folder_shared",
|
||||
})
|
||||
},
|
||||
failedImport() {
|
||||
this.$toast.error(this.$t("import_failed"), {
|
||||
icon: "error"
|
||||
});
|
||||
icon: "error",
|
||||
})
|
||||
},
|
||||
parsePostmanCollection(collection, folders = true) {
|
||||
let postwomanCollection = folders
|
||||
@@ -207,37 +183,29 @@ export default {
|
||||
{
|
||||
name: "",
|
||||
folders: [],
|
||||
requests: []
|
||||
}
|
||||
requests: [],
|
||||
},
|
||||
]
|
||||
: {
|
||||
name: "",
|
||||
requests: []
|
||||
};
|
||||
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 = {
|
||||
@@ -256,69 +224,63 @@ export default {
|
||||
rawInput: false,
|
||||
contentType: "",
|
||||
requestType: "",
|
||||
name: ""
|
||||
};
|
||||
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 : "";
|
||||
)
|
||||
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.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;
|
||||
itemAuth.basic[0].key === "password" ? itemAuth.basic[0].value : itemAuth.basic[1].value
|
||||
} else if (authType === "oauth2") {
|
||||
pwRequest.auth = "OAuth 2.0";
|
||||
pwRequest.auth = "OAuth 2.0"
|
||||
pwRequest.bearerToken =
|
||||
itemAuth.oauth2[0].key === "accessToken"
|
||||
? itemAuth.oauth2[0].value
|
||||
: itemAuth.oauth2[1].value;
|
||||
: itemAuth.oauth2[1].value
|
||||
} else if (authType === "bearer") {
|
||||
pwRequest.auth = "Bearer Token";
|
||||
pwRequest.bearerToken = itemAuth.bearer[0].value;
|
||||
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 : [];
|
||||
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;
|
||||
pwRequest.rawInput = true
|
||||
pwRequest.rawParams = requestObject.request.body.raw
|
||||
}
|
||||
}
|
||||
return pwRequest;
|
||||
}
|
||||
}
|
||||
};
|
||||
return pwRequest
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -107,8 +107,8 @@ ul {
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import collection from "./collection";
|
||||
import { fb } from "../../functions/fb";
|
||||
import collection from "./collection"
|
||||
import { fb } from "../../functions/fb"
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -120,7 +120,7 @@ export default {
|
||||
editFolder: () => import("./editFolder"),
|
||||
editRequest: () => import("./editRequest"),
|
||||
importExportCollections: () => import("./importExportCollections"),
|
||||
VirtualList: () => import("vue-virtual-scroll-list")
|
||||
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;
|
||||
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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
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>
|
||||
|
||||
@@ -27,22 +27,12 @@
|
||||
/>
|
||||
<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"
|
||||
>
|
||||
@@ -52,34 +42,18 @@
|
||||
</span>
|
||||
<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>
|
||||
<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>
|
||||
@@ -104,15 +78,15 @@
|
||||
</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 {
|
||||
@@ -121,106 +95,96 @@ export default {
|
||||
name: undefined,
|
||||
collectionIndex: undefined,
|
||||
folderIndex: undefined,
|
||||
requestIndex: undefined
|
||||
}
|
||||
};
|
||||
requestIndex: undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"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;
|
||||
}
|
||||
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;
|
||||
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", {
|
||||
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>
|
||||
|
||||
@@ -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: []
|
||||
}
|
||||
];
|
||||
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>
|
||||
|
||||
@@ -30,11 +30,7 @@
|
||||
<div class="flex-wrap">
|
||||
<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,
|
||||
})
|
||||
"
|
||||
/>
|
||||
@@ -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.$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
|
||||
);
|
||||
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.$store.commit("postwoman/removeVariable", newVariables)
|
||||
this.$toast.error(this.$t("deleted"), {
|
||||
icon: "delete",
|
||||
action: {
|
||||
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
|
||||
};
|
||||
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>
|
||||
|
||||
@@ -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,11 +12,7 @@
|
||||
</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>
|
||||
</button>
|
||||
@@ -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>
|
||||
|
||||
@@ -14,16 +14,10 @@
|
||||
<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>
|
||||
</button>
|
||||
@@ -72,11 +66,7 @@
|
||||
<button class="icon" @click="hideModal">
|
||||
{{ $t("cancel") }}
|
||||
</button>
|
||||
<button
|
||||
class="icon primary"
|
||||
@click="exportJSON"
|
||||
v-tooltip="$t('download_file')"
|
||||
>
|
||||
<button class="icon primary" @click="exportJSON" v-tooltip="$t('download_file')">
|
||||
{{ $t("export") }}
|
||||
</button>
|
||||
</span>
|
||||
@@ -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 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);
|
||||
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"
|
||||
});
|
||||
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"
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
icon: "folder_shared",
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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"
|
||||
@@ -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,11 +62,11 @@ 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: {
|
||||
@@ -83,7 +75,7 @@ export default {
|
||||
addEnvironment: () => import("./addEnvironment"),
|
||||
editEnvironment: () => import("./editEnvironment"),
|
||||
importExportEnvironment: () => import("./importExportEnvironment"),
|
||||
VirtualList: () => import("vue-virtual-scroll-list")
|
||||
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;
|
||||
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>
|
||||
|
||||
@@ -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);
|
||||
fb.deleteFeed(feed.id)
|
||||
this.$toast.error(this.$t("deleted"), {
|
||||
icon: "delete"
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
icon: "delete",
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -41,19 +41,19 @@
|
||||
</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)
|
||||
@@ -66,23 +66,23 @@ export default {
|
||||
action: {
|
||||
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)
|
||||
@@ -95,21 +95,21 @@ export default {
|
||||
action: {
|
||||
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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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: {
|
||||
@@ -73,21 +70,19 @@ export default {
|
||||
`${arg.name}: ${arg.type.toString()}${
|
||||
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>
|
||||
|
||||
@@ -19,33 +19,33 @@
|
||||
</style>
|
||||
|
||||
<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() {
|
||||
@@ -53,15 +53,15 @@ export default {
|
||||
initialized: false,
|
||||
editor: null,
|
||||
cacheValue: "",
|
||||
validationSchema: null
|
||||
};
|
||||
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() {
|
||||
@@ -73,21 +73,28 @@ export default {
|
||||
});
|
||||
},
|
||||
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, {
|
||||
mode: `ace/mode/${this.lang}`,
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
...this.options
|
||||
...this.options,
|
||||
})
|
||||
|
||||
// Set the theme and show the editor only after it's been set to prevent FOUC.
|
||||
editor.setTheme(`ace/theme/${this.defineTheme()}`, () => {
|
||||
this.$nextTick().then(() => {
|
||||
this.initialized = true;
|
||||
});
|
||||
});
|
||||
|
||||
// Set the theme and show the editor only after it's been set to prevent FOUC.
|
||||
@@ -98,19 +105,12 @@ export default {
|
||||
});
|
||||
|
||||
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,
|
||||
@@ -118,64 +118,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;
|
||||
});
|
||||
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 !== "") {
|
||||
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([
|
||||
@@ -183,14 +179,14 @@ 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() {
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
"gql-field": () => import("./field")
|
||||
"gql-field": () => import("./field"),
|
||||
},
|
||||
|
||||
props: {
|
||||
gqlType: {},
|
||||
jumpTypeCallback: Function
|
||||
}
|
||||
};
|
||||
jumpTypeCallback: Function,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
: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">
|
||||
@@ -162,9 +162,7 @@
|
||||
</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>
|
||||
</li>
|
||||
@@ -201,11 +199,7 @@
|
||||
</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>
|
||||
</button>
|
||||
@@ -326,16 +320,16 @@ 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")
|
||||
VirtualList: () => import("vue-virtual-scroll-list"),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -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.history = []
|
||||
this.filterText = ""
|
||||
this.disableHistoryClearing()
|
||||
updateOnLocalStorage("history", this.history)
|
||||
this.$toast.error(this.$t("history_deleted"), {
|
||||
icon: "delete"
|
||||
});
|
||||
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);
|
||||
updateOnLocalStorage("history", this.history)
|
||||
this.$toast.error(this.$t("deleted"), {
|
||||
icon: "delete"
|
||||
});
|
||||
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>
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: String
|
||||
}
|
||||
}
|
||||
};
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<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">
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -2,7 +2,7 @@ export default {
|
||||
name: "textareaAutoHeight",
|
||||
update({ scrollHeight, clientHeight, style }) {
|
||||
if (scrollHeight !== clientHeight) {
|
||||
style.minHeight = `${scrollHeight}px`;
|
||||
style.minHeight = `${scrollHeight}px`
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
@@ -10,11 +10,7 @@
|
||||
"target": "postwoman",
|
||||
"public": "dist",
|
||||
"cleanUrls": true,
|
||||
"ignore": [
|
||||
"firebase.json",
|
||||
"**/.*",
|
||||
"**/node_modules/**"
|
||||
]
|
||||
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
|
||||
},
|
||||
"storage": {
|
||||
"rules": "storage.rules"
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
// ]
|
||||
"indexes": [],
|
||||
"fieldOverrides": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ const mimeToMode = {
|
||||
"text/html": "html",
|
||||
"application/xml": "xml",
|
||||
"application/hal+json": "json",
|
||||
"application/json": "json"
|
||||
"application/json": "json",
|
||||
}
|
||||
|
||||
export function getEditorLangForMimeType(mimeType) {
|
||||
return mimeToMode[mimeType] || "plain_text";
|
||||
return mimeToMode[mimeType] || "plain_text"
|
||||
}
|
||||
|
||||
140
functions/fb.js
140
functions/fb.js
@@ -1,6 +1,6 @@
|
||||
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 = {
|
||||
@@ -11,12 +11,12 @@ const firebaseConfig = {
|
||||
storageBucket: "postwoman-api.appspot.com",
|
||||
messagingSenderId: "421993993223",
|
||||
appId: "1:421993993223:web:ec0baa8ee8c02ffa1fc6a2",
|
||||
measurementId: "G-ERJ6025CEB"
|
||||
};
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
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,13 +34,13 @@ export const fb = {
|
||||
author_name: fb.currentUser.displayName,
|
||||
author_image: fb.currentUser.photoURL,
|
||||
message,
|
||||
label
|
||||
};
|
||||
label,
|
||||
}
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.collection("feeds")
|
||||
.add(dt)
|
||||
.catch(e => console.error("error inserting", dt, e));
|
||||
.catch(e => console.error("error inserting", dt, e))
|
||||
},
|
||||
deleteFeed: id => {
|
||||
usersCollection
|
||||
@@ -48,7 +48,7 @@ export const fb = {
|
||||
.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,22 +57,22 @@ export const fb = {
|
||||
author_name: fb.currentUser.displayName,
|
||||
author_image: fb.currentUser.photoURL,
|
||||
name: setting,
|
||||
value
|
||||
};
|
||||
value,
|
||||
}
|
||||
usersCollection
|
||||
.doc(fb.currentUser.uid)
|
||||
.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")
|
||||
.add(hs)
|
||||
.catch(e => console.error("error inserting", hs, e));
|
||||
.catch(e => console.error("error inserting", hs, e))
|
||||
},
|
||||
deleteHistory: entry => {
|
||||
usersCollection
|
||||
@@ -80,7 +80,7 @@ export const fb = {
|
||||
.collection("history")
|
||||
.doc(entry.id)
|
||||
.delete()
|
||||
.catch(e => console.error("error deleting", entry, e));
|
||||
.catch(e => console.error("error deleting", entry, e))
|
||||
},
|
||||
clearHistory: () => {
|
||||
usersCollection
|
||||
@@ -88,8 +88,8 @@ export const fb = {
|
||||
.collection("history")
|
||||
.get()
|
||||
.then(({ docs }) => {
|
||||
docs.forEach(e => fb.deleteHistory(e));
|
||||
});
|
||||
docs.forEach(e => fb.deleteHistory(e))
|
||||
})
|
||||
},
|
||||
toggleStar: (entry, value) => {
|
||||
usersCollection
|
||||
@@ -97,7 +97,7 @@ export const fb = {
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
.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")
|
||||
.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
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -120,5 +120,5 @@ export const commonHeaders = [
|
||||
"X-Pingback",
|
||||
"X-Requested-With",
|
||||
"X-Robots-Tag",
|
||||
"X-UA-Compatible"
|
||||
];
|
||||
"X-UA-Compatible",
|
||||
]
|
||||
|
||||
@@ -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;
|
||||
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 }
|
||||
|
||||
@@ -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: "" }
|
||||
};
|
||||
none: { icon: "", class: "" },
|
||||
}
|
||||
|
||||
// TODO: probably have to use a more global state for `test`
|
||||
|
||||
@@ -18,158 +18,130 @@ export default function runTestScriptWithVariables(script, variables) {
|
||||
_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`))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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/",
|
||||
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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
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) => {
|
||||
@@ -13,18 +13,18 @@ const chromeWithoutProxy = (req, _store) =>
|
||||
{
|
||||
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) => {
|
||||
@@ -35,29 +35,27 @@ const chromeWithProxy = (req, { state }) =>
|
||||
data: {
|
||||
config: {
|
||||
method: "post",
|
||||
url:
|
||||
state.postwoman.settings.PROXY_URL ||
|
||||
"https://postwoman.apollotv.xyz/",
|
||||
data: req
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
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
|
||||
|
||||
@@ -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
|
||||
});
|
||||
});
|
||||
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
|
||||
|
||||
@@ -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] || "")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -86,5 +86,5 @@ export default {
|
||||
connect: "Verbinden",
|
||||
disconnect: "Trennen",
|
||||
start: "Start",
|
||||
stop: "Stopp"
|
||||
};
|
||||
stop: "Stopp",
|
||||
}
|
||||
|
||||
@@ -85,8 +85,7 @@ export default {
|
||||
enabled: "Enabled",
|
||||
disabled: "Disabled",
|
||||
proxy: "Proxy",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Postwoman's Official Proxy is hosted by ApolloTV.",
|
||||
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",
|
||||
@@ -162,8 +161,7 @@ export default {
|
||||
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.",
|
||||
browser_support_sse: "This browser doesn't seems to have Server Sent Events support.",
|
||||
log: "Log",
|
||||
no_url: "No URL",
|
||||
run_query: "Run Query",
|
||||
@@ -216,8 +214,7 @@ export default {
|
||||
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_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",
|
||||
@@ -244,8 +241,7 @@ export default {
|
||||
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:",
|
||||
donate_info2: "You can support Postwoman development via the following methods:",
|
||||
one_time_recurring: "One-time or recurring",
|
||||
one_time: "One-time",
|
||||
recurring: "Recurring",
|
||||
@@ -256,8 +252,7 @@ export default {
|
||||
enter_curl: "Enter cURL",
|
||||
empty: "Empty",
|
||||
extensions: "Extensions",
|
||||
extensions_use_toggle:
|
||||
"Use the browser extension to send requests (if present)",
|
||||
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",
|
||||
@@ -274,5 +269,5 @@ export default {
|
||||
login_first: "Login first",
|
||||
paste_a_note: "Paste a note",
|
||||
import_from_sync: "Import from Sync",
|
||||
notes: "Notes"
|
||||
};
|
||||
notes: "Notes",
|
||||
}
|
||||
|
||||
@@ -78,8 +78,7 @@ export default {
|
||||
enabled: "Habilitado",
|
||||
disabled: "Deshabilitado",
|
||||
proxy: "Proxy",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
|
||||
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",
|
||||
@@ -235,8 +234,7 @@ export default {
|
||||
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:",
|
||||
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",
|
||||
@@ -260,5 +258,5 @@ export default {
|
||||
turn_on: "Encender",
|
||||
login_first: "Inicie sesión primero",
|
||||
paste_a_collection: "Pegar una Colección",
|
||||
import_from_sync: "Importar desde Sync"
|
||||
};
|
||||
import_from_sync: "Importar desde Sync",
|
||||
}
|
||||
|
||||
@@ -78,13 +78,12 @@ export default {
|
||||
enabled: "فعال",
|
||||
disabled: "غیر فعال",
|
||||
proxy: "پراکسی",
|
||||
postwoman_official_proxy_hosting:
|
||||
"پراکسی Postwoman برروی هاست ApolloTV قرار دارد.",
|
||||
postwoman_official_proxy_hosting: "پراکسی Postwoman برروی هاست ApolloTV قرار دارد.",
|
||||
read_the: "بخوانید",
|
||||
apollotv_privacy_policy: "خط مشی رازداری ApolloTV",
|
||||
contact_us: "Contact us",
|
||||
connect: "Connect",
|
||||
disconnect: "Disconnect",
|
||||
start: "Start",
|
||||
stop: "Stop"
|
||||
};
|
||||
stop: "Stop",
|
||||
}
|
||||
|
||||
@@ -78,8 +78,7 @@ export default {
|
||||
enabled: "Activé",
|
||||
disabled: "Désactivé",
|
||||
proxy: "Proxy",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Le proxy officiel de Postwoman est hébergé par ApolloTV.",
|
||||
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",
|
||||
@@ -235,8 +234,7 @@ export default {
|
||||
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 :",
|
||||
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",
|
||||
@@ -260,5 +258,5 @@ export default {
|
||||
turn_on: "Activer",
|
||||
login_first: "Se connecter d'abord",
|
||||
paste_a_collection: "Coller une collection",
|
||||
import_from_sync: "Importer depuis la synchronisation"
|
||||
};
|
||||
import_from_sync: "Importer depuis la synchronisation",
|
||||
}
|
||||
|
||||
@@ -78,13 +78,12 @@ export default {
|
||||
enabled: "diaktifkan",
|
||||
disabled: "dinonaktifkan",
|
||||
proxy: "Proksi",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Proksi Resmi Postwoman dalam penginangan ApolloTV.",
|
||||
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"
|
||||
};
|
||||
stop: "Berhenti",
|
||||
}
|
||||
|
||||
@@ -78,8 +78,7 @@ export default {
|
||||
enabled: "有効",
|
||||
disabled: "無効",
|
||||
proxy: "プロキシ",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Postwomanの公式プロキシは、Apollo TVがホストしています。",
|
||||
postwoman_official_proxy_hosting: "Postwomanの公式プロキシは、Apollo TVがホストしています。",
|
||||
read_the: "プライバシーポリシー",
|
||||
apollotv_privacy_policy: "を読む",
|
||||
contact_us: "お問い合わせ",
|
||||
@@ -231,7 +230,8 @@ export default {
|
||||
enable_proxy: "プロキシを有効にしてみてください",
|
||||
complete_config_urls: "設定URLsを入力してください",
|
||||
token_request_saved: "トークンリクエストを保存した",
|
||||
donate_info1: "Postwomanを非常に役に立つと思われる場合、感謝の印として寄付のご検討をお願いします。",
|
||||
donate_info1:
|
||||
"Postwomanを非常に役に立つと思われる場合、感謝の印として寄付のご検討をお願いします。",
|
||||
donate_info2: "以下の方法でPostwomanの開発をサポートできます:",
|
||||
one_time_recurring: "一度又は定期的",
|
||||
one_time: "一度",
|
||||
@@ -241,5 +241,5 @@ export default {
|
||||
go_home: "ホームに戻る",
|
||||
reload: "リロード",
|
||||
enter_curl: "cURLを入力",
|
||||
empty: "空"
|
||||
};
|
||||
empty: "空",
|
||||
}
|
||||
|
||||
@@ -85,5 +85,5 @@ export default {
|
||||
connect: "Conectar",
|
||||
disconnect: "Desconectar",
|
||||
start: "Começar",
|
||||
stop: "Pare"
|
||||
};
|
||||
stop: "Pare",
|
||||
}
|
||||
|
||||
@@ -78,13 +78,12 @@ export default {
|
||||
enabled: "Aktif",
|
||||
disabled: "Aktif değil",
|
||||
proxy: "Proxy",
|
||||
postwoman_official_proxy_hosting:
|
||||
"Proxy Oficial de Postwoman está hospedado en ApolloTV.",
|
||||
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"
|
||||
};
|
||||
stop: "Durdurmak",
|
||||
}
|
||||
|
||||
@@ -85,5 +85,5 @@ export default {
|
||||
connect: "连接",
|
||||
disconnect: "断开",
|
||||
start: "开始",
|
||||
stop: "停止"
|
||||
};
|
||||
stop: "停止",
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
@@ -346,31 +344,19 @@
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</button>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -671,42 +638,42 @@
|
||||
</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")
|
||||
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-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"
|
||||
});
|
||||
});
|
||||
icon: "error",
|
||||
})
|
||||
})
|
||||
this.$toast.info(this.$t("logged_out"), {
|
||||
icon: "vpn_key"
|
||||
});
|
||||
icon: "vpn_key",
|
||||
})
|
||||
},
|
||||
nativeShare() {
|
||||
if (navigator.share) {
|
||||
@@ -715,14 +682,14 @@ export default {
|
||||
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/"
|
||||
url: "https://postwoman.io/",
|
||||
})
|
||||
.then(() => {})
|
||||
.catch(console.error);
|
||||
.catch(console.error)
|
||||
} else {
|
||||
// fallback
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -737,48 +704,43 @@ 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)"
|
||||
);
|
||||
})();
|
||||
)
|
||||
})()
|
||||
},
|
||||
|
||||
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"
|
||||
);
|
||||
.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",
|
||||
@@ -788,19 +750,15 @@ export default {
|
||||
{
|
||||
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",
|
||||
@@ -810,73 +768,73 @@ export default {
|
||||
{
|
||||
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"),
|
||||
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;
|
||||
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;
|
||||
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;"
|
||||
);
|
||||
)
|
||||
console.log(
|
||||
"%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>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<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>
|
||||
@@ -39,16 +35,16 @@ export default {
|
||||
|
||||
methods: {
|
||||
reloadApplication() {
|
||||
this.$router.push("/", () => window.location.reload());
|
||||
}
|
||||
this.$router.push("/", () => window.location.reload())
|
||||
},
|
||||
},
|
||||
|
||||
head() {
|
||||
return {
|
||||
bodyAttrs: {
|
||||
class: "sticky-footer"
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
class: "sticky-footer",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export default function({ route, redirect }) {
|
||||
if (route.fullPath !== "/") {
|
||||
return redirect("/");
|
||||
return redirect("/")
|
||||
}
|
||||
}
|
||||
|
||||
172
nuxt.config.js
172
nuxt.config.js
@@ -4,201 +4,201 @@ export const meta = {
|
||||
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"
|
||||
? {
|
||||
router: {
|
||||
base: `/${repoName}/`
|
||||
}
|
||||
base: `/${repoName}/`,
|
||||
},
|
||||
}
|
||||
: {
|
||||
router: {
|
||||
base: "/"
|
||||
}
|
||||
};
|
||||
base: "/",
|
||||
},
|
||||
}
|
||||
export default {
|
||||
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",
|
||||
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 || ""
|
||||
content: meta.description || "",
|
||||
},
|
||||
{
|
||||
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"
|
||||
content: "IE=edge, chrome=1",
|
||||
},
|
||||
{
|
||||
itemprop: "name",
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`,
|
||||
},
|
||||
{
|
||||
itemprop: "description",
|
||||
content: meta.description
|
||||
content: meta.description,
|
||||
},
|
||||
{
|
||||
itemprop: "image",
|
||||
content: `https://postwoman.io/logo.jpg`
|
||||
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
|
||||
content: meta.name,
|
||||
},
|
||||
// Add to homescreen for Safari on iOS
|
||||
{
|
||||
name: "apple-mobile-web-app-capable",
|
||||
content: "yes"
|
||||
content: "yes",
|
||||
},
|
||||
{
|
||||
name: "apple-mobile-web-app-status-bar-style",
|
||||
content: "black-translucent"
|
||||
content: "black-translucent",
|
||||
},
|
||||
{
|
||||
name: "apple-mobile-web-app-title",
|
||||
content: meta.name
|
||||
content: meta.name,
|
||||
},
|
||||
// Windows phone tile icon
|
||||
{
|
||||
name: "msapplication-TileImage",
|
||||
content: `${routerBase.router.base}icons/icon-144x144.png`
|
||||
content: `${routerBase.router.base}icons/icon-144x144.png`,
|
||||
},
|
||||
{
|
||||
name: "msapplication-TileColor",
|
||||
content: "#202124"
|
||||
content: "#202124",
|
||||
},
|
||||
{
|
||||
name: "msapplication-tap-highlight",
|
||||
content: "no"
|
||||
content: "no",
|
||||
},
|
||||
// OpenGraph
|
||||
{
|
||||
property: "og:site_name",
|
||||
content: meta.name
|
||||
content: meta.name,
|
||||
},
|
||||
{
|
||||
property: "og:url",
|
||||
content: "https://postwoman.io"
|
||||
content: "https://postwoman.io",
|
||||
},
|
||||
{
|
||||
property: "og:type",
|
||||
content: "website"
|
||||
content: "website",
|
||||
},
|
||||
{
|
||||
property: "og:title",
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`,
|
||||
},
|
||||
{
|
||||
property: "og:description",
|
||||
content: meta.description
|
||||
content: meta.description,
|
||||
},
|
||||
{
|
||||
property: "og:image",
|
||||
content: `https://postwoman.io/logo.jpg`
|
||||
content: `https://postwoman.io/logo.jpg`,
|
||||
},
|
||||
// Twitter
|
||||
{
|
||||
name: "twitter:card",
|
||||
content: "summary_large_image"
|
||||
content: "summary_large_image",
|
||||
},
|
||||
{
|
||||
name: "twitter:site",
|
||||
content: "@liyasthomas"
|
||||
content: "@liyasthomas",
|
||||
},
|
||||
{
|
||||
name: "twitter:creator",
|
||||
content: "@liyasthomas"
|
||||
content: "@liyasthomas",
|
||||
},
|
||||
{
|
||||
name: "twitter:url",
|
||||
content: "https://postwoman.io"
|
||||
content: "https://postwoman.io",
|
||||
},
|
||||
{
|
||||
name: "twitter:title",
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`
|
||||
content: `${meta.name} \u2022 ${meta.shortDescription}`,
|
||||
},
|
||||
{
|
||||
name: "twitter:description",
|
||||
content: meta.description
|
||||
content: meta.description,
|
||||
},
|
||||
{
|
||||
name: "twitter:image",
|
||||
content: "https://postwoman.io/logo.jpg"
|
||||
}
|
||||
content: "https://postwoman.io/logo.jpg",
|
||||
},
|
||||
],
|
||||
link: [
|
||||
{
|
||||
rel: "icon",
|
||||
type: "image/x-icon",
|
||||
href: `${routerBase.router.base}favicon.ico`
|
||||
href: `${routerBase.router.base}favicon.ico`,
|
||||
},
|
||||
// Home-screen icons (iOS)
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
href: `${routerBase.router.base}icons/icon-48x48.png`
|
||||
href: `${routerBase.router.base}icons/icon-48x48.png`,
|
||||
},
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "72x72",
|
||||
href: `${routerBase.router.base}icons/icon-72x72.png`
|
||||
href: `${routerBase.router.base}icons/icon-72x72.png`,
|
||||
},
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "96x96",
|
||||
href: `${routerBase.router.base}icons/icon-96x96.png`
|
||||
href: `${routerBase.router.base}icons/icon-96x96.png`,
|
||||
},
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "144x144",
|
||||
href: `${routerBase.router.base}icons/icon-144x144.png`
|
||||
href: `${routerBase.router.base}icons/icon-144x144.png`,
|
||||
},
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "192x192",
|
||||
href: `${routerBase.router.base}icons/icon-192x192.png`
|
||||
}
|
||||
]
|
||||
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
|
||||
@@ -206,26 +206,22 @@ export default {
|
||||
loadingIndicator: {
|
||||
name: "pulse",
|
||||
color: "var(--ac-color)",
|
||||
background: "var(--bg-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
|
||||
@@ -244,11 +240,11 @@ export default {
|
||||
[
|
||||
"@nuxtjs/google-tag-manager",
|
||||
{
|
||||
id: process.env.GTM_ID || "GTM-MXWD8NQ"
|
||||
}
|
||||
id: process.env.GTM_ID || "GTM-MXWD8NQ",
|
||||
},
|
||||
],
|
||||
["@nuxtjs/robots"],
|
||||
["nuxt-i18n"]
|
||||
["nuxt-i18n"],
|
||||
],
|
||||
pwa: {
|
||||
manifest: {
|
||||
@@ -259,43 +255,43 @@ export default {
|
||||
|
||||
theme_color: "#202124",
|
||||
background_color: "#202124",
|
||||
start_url: `${routerBase.router.base}`
|
||||
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}`
|
||||
});
|
||||
sizes: `${size}x${size}`,
|
||||
})
|
||||
}
|
||||
return icons;
|
||||
})([48, 72, 96, 144, 192, 512])
|
||||
return icons
|
||||
})([48, 72, 96, 144, 192, 512]),
|
||||
},
|
||||
toast: {
|
||||
position: "bottom-center",
|
||||
duration: 3000,
|
||||
theme: "bubble",
|
||||
keepOnHover: true
|
||||
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"
|
||||
Sitemap: "https://postwoman.io/sitemap.xml",
|
||||
},
|
||||
i18n: {
|
||||
locales: [
|
||||
@@ -303,55 +299,55 @@ export default {
|
||||
code: "en",
|
||||
name: "English",
|
||||
iso: "en-US",
|
||||
file: "en-US.js"
|
||||
file: "en-US.js",
|
||||
},
|
||||
{
|
||||
code: "es",
|
||||
name: "Español",
|
||||
iso: "es-ES",
|
||||
file: "es-ES.js"
|
||||
file: "es-ES.js",
|
||||
},
|
||||
{
|
||||
code: "fr",
|
||||
name: "Français",
|
||||
iso: "fr-FR",
|
||||
file: "fr-FR.js"
|
||||
file: "fr-FR.js",
|
||||
},
|
||||
{
|
||||
code: "fa",
|
||||
name: "Farsi",
|
||||
iso: "fa-IR",
|
||||
file: "fa-IR.js"
|
||||
file: "fa-IR.js",
|
||||
},
|
||||
{
|
||||
code: "pt",
|
||||
name: "Português Brasileiro",
|
||||
iso: "pt-BR",
|
||||
file: "pt-BR.js"
|
||||
file: "pt-BR.js",
|
||||
},
|
||||
{
|
||||
code: "cn",
|
||||
name: "简体中文",
|
||||
iso: "zh-CN",
|
||||
file: "zh-CN.js"
|
||||
file: "zh-CN.js",
|
||||
},
|
||||
{
|
||||
code: "id",
|
||||
name: "Bahasa Indonesia",
|
||||
iso: "id-ID",
|
||||
file: "id-ID.js"
|
||||
file: "id-ID.js",
|
||||
},
|
||||
{
|
||||
code: "tr",
|
||||
name: "Türkçe",
|
||||
iso: "tr-TR",
|
||||
file: "tr-TR.js"
|
||||
file: "tr-TR.js",
|
||||
},
|
||||
{
|
||||
code: "de",
|
||||
name: "Deutsch",
|
||||
iso: "de-DE",
|
||||
file: "de-DE.js"
|
||||
file: "de-DE.js",
|
||||
},
|
||||
{
|
||||
code: "ja",
|
||||
@@ -368,10 +364,10 @@ export default {
|
||||
],
|
||||
defaultLocale: "en",
|
||||
vueI18n: {
|
||||
fallbackLocale: "en"
|
||||
fallbackLocale: "en",
|
||||
},
|
||||
lazy: true,
|
||||
langDir: "lang/"
|
||||
langDir: "lang/",
|
||||
},
|
||||
/*
|
||||
** Build configuration
|
||||
@@ -380,16 +376,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,
|
||||
}
|
||||
|
||||
663
package-lock.json
generated
663
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "postwoman",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -1860,11 +1860,23 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
|
||||
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz",
|
||||
"integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/q": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
|
||||
@@ -2378,6 +2390,12 @@
|
||||
"resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
|
||||
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
|
||||
},
|
||||
"array-differ": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
|
||||
"integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
|
||||
"dev": true
|
||||
},
|
||||
"array-find-index": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||
@@ -2389,11 +2407,23 @@
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"array-union": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||
"dev": true
|
||||
},
|
||||
"array-unique": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
||||
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
|
||||
},
|
||||
"arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"dev": true
|
||||
},
|
||||
"ascli": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz",
|
||||
@@ -3565,6 +3595,12 @@
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
|
||||
},
|
||||
"compare-versions": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
|
||||
"integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
|
||||
"dev": true
|
||||
},
|
||||
"component-emitter": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||
@@ -4293,6 +4329,12 @@
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
|
||||
},
|
||||
"dedent": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
|
||||
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
|
||||
"dev": true
|
||||
},
|
||||
"deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
@@ -5214,6 +5256,15 @@
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"find-versions": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz",
|
||||
"integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"firebase": {
|
||||
"version": "7.9.1",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-7.9.1.tgz",
|
||||
@@ -5514,6 +5565,12 @@
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"dev": true
|
||||
},
|
||||
"get-own-enumerable-property-symbols": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
|
||||
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
|
||||
"dev": true
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||
@@ -6519,6 +6576,132 @@
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
|
||||
"integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="
|
||||
},
|
||||
"husky": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz",
|
||||
"integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^3.0.0",
|
||||
"ci-info": "^2.0.0",
|
||||
"compare-versions": "^3.5.1",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"find-versions": "^3.2.0",
|
||||
"opencollective-postinstall": "^2.0.2",
|
||||
"pkg-dir": "^4.2.0",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"slash": "^3.0.0",
|
||||
"which-pm-runs": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
|
||||
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
|
||||
"integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-better-errors": "^1.0.1",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@@ -6884,6 +7067,12 @@
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"is-regexp": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
|
||||
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
|
||||
"dev": true
|
||||
},
|
||||
"is-resolvable": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
|
||||
@@ -7148,6 +7337,239 @@
|
||||
"invert-kv": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"lines-and-columns": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
|
||||
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
|
||||
"dev": true
|
||||
},
|
||||
"lint-staged": {
|
||||
"version": "10.0.7",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.7.tgz",
|
||||
"integrity": "sha512-Byj0F4l7GYUpYYHEqyFH69NiI6ICTg0CeCKbhRorL+ickbzILKUlZLiyCkljZV02wnoh7yH7PmFyYm9PRNwk9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^3.0.0",
|
||||
"commander": "^4.0.1",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"dedent": "^0.7.0",
|
||||
"execa": "^3.4.0",
|
||||
"listr": "^0.14.3",
|
||||
"log-symbols": "^3.0.0",
|
||||
"micromatch": "^4.0.2",
|
||||
"normalize-path": "^3.0.0",
|
||||
"please-upgrade-node": "^3.2.0",
|
||||
"string-argv": "0.3.1",
|
||||
"stringify-object": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
||||
"dev": true
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
|
||||
"integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.1.0",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
|
||||
"integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
|
||||
"integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"human-signals": "^1.1.1",
|
||||
"is-stream": "^2.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^4.0.0",
|
||||
"onetime": "^5.1.0",
|
||||
"p-finally": "^2.0.0",
|
||||
"signal-exit": "^3.0.2",
|
||||
"strip-final-newline": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
|
||||
"integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
|
||||
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
||||
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.0.5"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
|
||||
"integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
|
||||
"dev": true
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
|
||||
"integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-better-errors": "^1.0.1",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"listr": {
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz",
|
||||
@@ -7914,11 +8336,30 @@
|
||||
"run-queue": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"mri": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
|
||||
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"multimatch": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz",
|
||||
"integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"array-differ": "^3.0.0",
|
||||
"array-union": "^2.1.0",
|
||||
"arrify": "^2.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"mustache": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz",
|
||||
@@ -8408,6 +8849,12 @@
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"opencollective-postinstall": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz",
|
||||
"integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==",
|
||||
"dev": true
|
||||
},
|
||||
"opener": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
|
||||
@@ -8543,6 +8990,23 @@
|
||||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"callsites": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"parse-asn1": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
|
||||
@@ -8701,6 +9165,15 @@
|
||||
"find-up": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"please-upgrade-node": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
|
||||
"integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver-compare": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||
@@ -9709,6 +10182,144 @@
|
||||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"pretty-quick": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.1.tgz",
|
||||
"integrity": "sha512-y7bJt77XadjUr+P1uKqZxFWLddvj3SKY6EU4BuQtMxmmEFSMpbN132pUWdSG1g1mtUfO0noBvn7wBf0BVeomHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"execa": "^2.1.0",
|
||||
"find-up": "^4.1.0",
|
||||
"ignore": "^5.1.4",
|
||||
"mri": "^1.1.4",
|
||||
"multimatch": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
|
||||
"integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz",
|
||||
"integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^3.0.0",
|
||||
"onetime": "^5.1.0",
|
||||
"p-finally": "^2.0.0",
|
||||
"signal-exit": "^3.0.2",
|
||||
"strip-final-newline": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
|
||||
"integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
|
||||
"dev": true
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz",
|
||||
"integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
|
||||
"integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
|
||||
"dev": true
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"pretty-time": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz",
|
||||
@@ -10463,6 +11074,18 @@
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
},
|
||||
"semver-compare": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
||||
"dev": true
|
||||
},
|
||||
"semver-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==",
|
||||
"dev": true
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
@@ -10646,6 +11269,12 @@
|
||||
"xmlbuilder": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
|
||||
@@ -11192,6 +11821,12 @@
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
||||
},
|
||||
"string-argv": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
|
||||
"integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
@@ -11260,6 +11895,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"stringify-object": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
|
||||
"integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-own-enumerable-property-symbols": "^3.0.0",
|
||||
"is-obj": "^1.0.1",
|
||||
"is-regexp": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
@@ -13101,6 +13747,12 @@
|
||||
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
|
||||
"dev": true
|
||||
},
|
||||
"which-pm-runs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
|
||||
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
|
||||
"dev": true
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
@@ -13280,6 +13932,15 @@
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
},
|
||||
"yaml": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.7.2.tgz",
|
||||
"integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.6.3"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
|
||||
|
||||
95
package.json
95
package.json
@@ -1,47 +1,52 @@
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"node-sass": "^4.13.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",
|
||||
"pretty-quick": "pretty-quick --pattern \"**/*.*(html|js|json|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",
|
||||
"pretty-quick": "^2.0.1",
|
||||
"sass-loader": "^8.0.2",
|
||||
"start-server-and-test": "^1.10.8"
|
||||
}
|
||||
}
|
||||
|
||||
106
pages/doc.vue
106
pages/doc.vue
@@ -11,11 +11,7 @@
|
||||
<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>
|
||||
</button>
|
||||
@@ -39,7 +35,7 @@
|
||||
fontSize: '16px',
|
||||
autoScrollEditorIntoView: true,
|
||||
showPrintMargin: false,
|
||||
useWorker: false
|
||||
useWorker: false,
|
||||
}"
|
||||
/>
|
||||
</li>
|
||||
@@ -59,29 +55,17 @@
|
||||
{{ $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") }}
|
||||
</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") }}
|
||||
</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") }}
|
||||
@@ -129,11 +113,7 @@
|
||||
</p>
|
||||
<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>
|
||||
@@ -142,11 +122,7 @@
|
||||
</span>
|
||||
<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>
|
||||
@@ -155,11 +131,7 @@
|
||||
</span>
|
||||
<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>
|
||||
@@ -237,11 +209,7 @@
|
||||
</p>
|
||||
<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>
|
||||
@@ -250,11 +218,7 @@
|
||||
</span>
|
||||
<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>
|
||||
@@ -263,11 +227,7 @@
|
||||
</span>
|
||||
<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>
|
||||
@@ -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
|
||||
Editor: AceEditor,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
collectionJSON: "[]",
|
||||
items: []
|
||||
};
|
||||
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.collectionJSON = target.result
|
||||
}
|
||||
reader.readAsText(file)
|
||||
this.$toast.info(this.$t("file_imported"), {
|
||||
icon: "attach_file"
|
||||
});
|
||||
icon: "attach_file",
|
||||
})
|
||||
} else {
|
||||
this.$toast.error(this.$t("choose_file"), {
|
||||
icon: "attach_file"
|
||||
});
|
||||
icon: "attach_file",
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
getDoc() {
|
||||
try {
|
||||
this.items = JSON.parse(this.collectionJSON);
|
||||
this.items = JSON.parse(this.collectionJSON)
|
||||
this.$toast.info(this.$t("docs_generated"), {
|
||||
icon: "book"
|
||||
});
|
||||
icon: "book",
|
||||
})
|
||||
} catch (e) {
|
||||
this.$toast.error(e, {
|
||||
icon: "code"
|
||||
});
|
||||
icon: "code",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -6,12 +6,7 @@
|
||||
<ul>
|
||||
<li>
|
||||
<label for="url">{{ $t("url") }}</label>
|
||||
<input
|
||||
id="url"
|
||||
type="url"
|
||||
v-model="url"
|
||||
@keyup.enter="getSchema()"
|
||||
/>
|
||||
<input id="url" type="url" v-model="url" @keyup.enter="getSchema()" />
|
||||
</li>
|
||||
<div>
|
||||
<li>
|
||||
@@ -31,11 +26,7 @@
|
||||
<div class="flex-wrap">
|
||||
<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
|
||||
@@ -112,9 +103,7 @@
|
||||
@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">
|
||||
@@ -149,7 +138,7 @@
|
||||
autoScrollEditorIntoView: true,
|
||||
readOnly: true,
|
||||
showPrintMargin: false,
|
||||
useWorker: false
|
||||
useWorker: false,
|
||||
}"
|
||||
/>
|
||||
</pw-section>
|
||||
@@ -158,11 +147,7 @@
|
||||
<div class="flex-wrap">
|
||||
<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,7 +184,7 @@
|
||||
fontSize: '16px',
|
||||
autoScrollEditorIntoView: true,
|
||||
showPrintMargin: false,
|
||||
useWorker: false
|
||||
useWorker: false,
|
||||
}"
|
||||
/>
|
||||
</pw-section>
|
||||
@@ -228,7 +213,7 @@
|
||||
autoScrollEditorIntoView: true,
|
||||
readOnly: true,
|
||||
showPrintMargin: false,
|
||||
useWorker: false
|
||||
useWorker: false,
|
||||
}"
|
||||
/>
|
||||
</pw-section>
|
||||
@@ -248,10 +233,7 @@
|
||||
</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>
|
||||
|
||||
@@ -267,10 +249,7 @@
|
||||
</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>
|
||||
|
||||
@@ -286,10 +265,7 @@
|
||||
</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>
|
||||
|
||||
@@ -304,15 +280,8 @@
|
||||
{{ $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>
|
||||
@@ -342,17 +311,17 @@
|
||||
</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"),
|
||||
@@ -360,7 +329,7 @@ export default {
|
||||
"gql-type": () => import("../components/graphql/type"),
|
||||
autocomplete: () => import("../components/autocomplete"),
|
||||
Editor: AceEditor,
|
||||
QueryEditor: QueryEditor
|
||||
QueryEditor: QueryEditor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -375,195 +344,184 @@ export default {
|
||||
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", {
|
||||
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.$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
|
||||
);
|
||||
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.$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
|
||||
);
|
||||
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.$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
|
||||
);
|
||||
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",
|
||||
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.$nuxt.$loading.finish()
|
||||
const duration = Date.now() - startTime
|
||||
this.$toast.info(this.$t("finished_in", { duration }), {
|
||||
icon: "done"
|
||||
});
|
||||
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);
|
||||
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",
|
||||
url: this.url,
|
||||
headers: {
|
||||
...headers,
|
||||
"content-type": "application/json"
|
||||
"content-type": "application/json",
|
||||
},
|
||||
data: query
|
||||
};
|
||||
data: query,
|
||||
}
|
||||
|
||||
// console.log(reqOptions);
|
||||
|
||||
@@ -571,144 +529,134 @@ export default {
|
||||
? {
|
||||
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
|
||||
) &&
|
||||
![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.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"
|
||||
});
|
||||
icon: "done",
|
||||
})
|
||||
} catch (error) {
|
||||
this.$nuxt.$loading.finish();
|
||||
this.schemaString = `${error}. ${this.$t("check_console_details")}`;
|
||||
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);
|
||||
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;
|
||||
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"
|
||||
});
|
||||
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;
|
||||
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.$store.commit("removeGQLHeader", index)
|
||||
this.$toast.error(this.$t("deleted"), {
|
||||
icon: "delete",
|
||||
action: {
|
||||
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>
|
||||
|
||||
1556
pages/index.vue
1556
pages/index.vue
File diff suppressed because it is too large
Load Diff
@@ -19,12 +19,7 @@
|
||||
<div>
|
||||
<li>
|
||||
<label for="connect" class="hide-on-small-screen"> </label>
|
||||
<button
|
||||
:disabled="!urlValid"
|
||||
id="connect"
|
||||
name="connect"
|
||||
@click="toggleConnection"
|
||||
>
|
||||
<button :disabled="!urlValid" id="connect" name="connect" @click="toggleConnection">
|
||||
{{ !connectionState ? $t("connect") : $t("disconnect") }}
|
||||
<span>
|
||||
<i class="material-icons">
|
||||
@@ -37,12 +32,7 @@
|
||||
</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>
|
||||
@@ -75,12 +65,7 @@
|
||||
<div>
|
||||
<li>
|
||||
<label for="send" class="hide-on-small-screen"> </label>
|
||||
<button
|
||||
id="send"
|
||||
name="send"
|
||||
:disabled="!connectionState"
|
||||
@click="sendMessage"
|
||||
>
|
||||
<button id="send" name="send" :disabled="!connectionState" @click="sendMessage">
|
||||
{{ $t("send") }}
|
||||
<span>
|
||||
<i class="material-icons">send</i>
|
||||
@@ -127,12 +112,7 @@
|
||||
</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>
|
||||
@@ -187,7 +167,7 @@ div.log {
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
"pw-section": () => import("../components/section")
|
||||
"pw-section": () => import("../components/section"),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -196,132 +176,132 @@ export default {
|
||||
socket: null,
|
||||
communication: {
|
||||
log: null,
|
||||
input: ""
|
||||
input: "",
|
||||
},
|
||||
connectionSSEState: false,
|
||||
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)"
|
||||
}
|
||||
];
|
||||
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()
|
||||
}
|
||||
];
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
},
|
||||
]
|
||||
this.$toast.success(this.$t("connected"), {
|
||||
icon: "sync"
|
||||
});
|
||||
};
|
||||
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()
|
||||
});
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
this.$toast.error(this.$t("disconnected"), {
|
||||
icon: "sync_disabled"
|
||||
});
|
||||
};
|
||||
icon: "sync_disabled",
|
||||
})
|
||||
}
|
||||
this.socket.onmessage = event => {
|
||||
this.communication.log.push({
|
||||
payload: event.data,
|
||||
source: "server",
|
||||
ts: new Date().toLocaleTimeString()
|
||||
});
|
||||
};
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
}
|
||||
} catch (ex) {
|
||||
this.handleError(ex);
|
||||
this.handleError(ex)
|
||||
this.$toast.error(this.$t("something_went_wrong"), {
|
||||
icon: "error"
|
||||
});
|
||||
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()
|
||||
});
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
if (error !== null)
|
||||
this.communication.log.push({
|
||||
payload: error,
|
||||
source: "info",
|
||||
color: "#ff5555",
|
||||
ts: new Date().toLocaleTimeString()
|
||||
});
|
||||
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 = "";
|
||||
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 = {
|
||||
@@ -330,70 +310,69 @@ export default {
|
||||
// Source used for client to server messages.
|
||||
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)"
|
||||
}
|
||||
];
|
||||
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()
|
||||
}
|
||||
];
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
},
|
||||
]
|
||||
this.$toast.success(this.$t("connected"), {
|
||||
icon: "sync"
|
||||
});
|
||||
};
|
||||
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()
|
||||
});
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
this.$toast.error(this.$t("disconnected"), {
|
||||
icon: "sync_disabled"
|
||||
});
|
||||
};
|
||||
icon: "sync_disabled",
|
||||
})
|
||||
}
|
||||
this.sse.onmessage = event => {
|
||||
this.events.log.push({
|
||||
payload: event.data,
|
||||
source: "server",
|
||||
ts: new Date().toLocaleTimeString()
|
||||
});
|
||||
};
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
}
|
||||
} catch (ex) {
|
||||
this.handleSSEError(ex);
|
||||
this.handleSSEError(ex)
|
||||
this.$toast.error(this.$t("something_went_wrong"), {
|
||||
icon: "error"
|
||||
});
|
||||
icon: "error",
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.events.log = [
|
||||
@@ -401,38 +380,38 @@ export default {
|
||||
payload: this.$t("browser_support_sse"),
|
||||
source: "info",
|
||||
color: "#ff5555",
|
||||
ts: new Date().toLocaleTimeString()
|
||||
}
|
||||
];
|
||||
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()
|
||||
});
|
||||
ts: new Date().toLocaleTimeString(),
|
||||
})
|
||||
if (error !== null)
|
||||
this.events.log.push({
|
||||
payload: error,
|
||||
source: "info",
|
||||
color: "#ff5555",
|
||||
ts: new Date().toLocaleTimeString()
|
||||
});
|
||||
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>
|
||||
|
||||
@@ -88,11 +88,7 @@
|
||||
<li>
|
||||
<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 }"
|
||||
@@ -132,9 +128,7 @@
|
||||
@change="toggleSetting('FRAME_COLORS_ENABLED')"
|
||||
>
|
||||
{{ $t("multi_color") }}
|
||||
{{
|
||||
settings.FRAME_COLORS_ENABLED ? $t("enabled") : $t("disabled")
|
||||
}}
|
||||
{{ settings.FRAME_COLORS_ENABLED ? $t("enabled") : $t("disabled") }}
|
||||
</pw-toggle>
|
||||
</span>
|
||||
</li>
|
||||
@@ -147,9 +141,7 @@
|
||||
@change="toggleSetting('SCROLL_INTO_ENABLED')"
|
||||
>
|
||||
{{ $t("scrollInto_use_toggle") }}
|
||||
{{
|
||||
settings.SCROLL_INTO_ENABLED ? $t("enabled") : $t("disabled")
|
||||
}}
|
||||
{{ settings.SCROLL_INTO_ENABLED ? $t("enabled") : $t("disabled") }}
|
||||
</pw-toggle>
|
||||
</span>
|
||||
</li>
|
||||
@@ -176,10 +168,7 @@
|
||||
<li>
|
||||
<div class="flex-wrap">
|
||||
<span>
|
||||
<pw-toggle
|
||||
:on="settings.PROXY_ENABLED"
|
||||
@change="toggleSetting('PROXY_ENABLED')"
|
||||
>
|
||||
<pw-toggle :on="settings.PROXY_ENABLED" @change="toggleSetting('PROXY_ENABLED')">
|
||||
{{ $t("proxy") }}
|
||||
{{ settings.PROXY_ENABLED ? $t("enabled") : $t("disabled") }}
|
||||
</pw-toggle>
|
||||
@@ -200,11 +189,7 @@
|
||||
<li>
|
||||
<div class="flex-wrap">
|
||||
<label for="url">{{ $t("url") }}</label>
|
||||
<button
|
||||
class="icon"
|
||||
@click="resetProxy"
|
||||
v-tooltip.bottom="$t('reset_default')"
|
||||
>
|
||||
<button class="icon" @click="resetProxy" v-tooltip.bottom="$t('reset_default')">
|
||||
<i class="material-icons">clear_all</i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -222,12 +207,7 @@
|
||||
{{ $t("postwoman_official_proxy_hosting") }}
|
||||
<br />
|
||||
{{ $t("read_the") }}
|
||||
<a
|
||||
class="link"
|
||||
href="https://apollotv.xyz/legal"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<a class="link" href="https://apollotv.xyz/legal" target="_blank" rel="noopener">
|
||||
{{ $t("apollotv_privacy_policy") }} </a
|
||||
>.
|
||||
</p>
|
||||
@@ -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")
|
||||
swatch: () => import("../components/settings/swatch"),
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -275,20 +255,20 @@ export default {
|
||||
color: "#202124",
|
||||
name: this.$t("kinda_dark"),
|
||||
class: "",
|
||||
aceEditor: "twilight"
|
||||
aceEditor: "twilight",
|
||||
},
|
||||
{
|
||||
color: "#ffffff",
|
||||
name: this.$t("clearly_white"),
|
||||
vibrant: true,
|
||||
class: "light",
|
||||
aceEditor: "iplastic"
|
||||
aceEditor: "iplastic",
|
||||
},
|
||||
{
|
||||
color: "#000000",
|
||||
name: this.$t("just_black"),
|
||||
class: "black",
|
||||
aceEditor: "vibrant_ink"
|
||||
aceEditor: "vibrant_ink",
|
||||
},
|
||||
{
|
||||
color: "var(--ac-color)",
|
||||
@@ -297,8 +277,8 @@ export default {
|
||||
class: "auto",
|
||||
aceEditor: window.matchMedia("(prefers-color-scheme: light)").matches
|
||||
? "iplastic"
|
||||
: "twilight"
|
||||
}
|
||||
: "twilight",
|
||||
},
|
||||
],
|
||||
// You can define a new color here! It will simply store the color value.
|
||||
colors: [
|
||||
@@ -306,43 +286,43 @@ export default {
|
||||
{
|
||||
color: "#50fa7b",
|
||||
name: this.$t("green"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#f1fa8c",
|
||||
name: this.$t("yellow"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#ff79c6",
|
||||
name: this.$t("pink"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#ff5555",
|
||||
name: this.$t("red"),
|
||||
vibrant: false
|
||||
vibrant: false,
|
||||
},
|
||||
{
|
||||
color: "#bd93f9",
|
||||
name: this.$t("purple"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#ffb86c",
|
||||
name: this.$t("orange"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#8be9fd",
|
||||
name: this.$t("cyan"),
|
||||
vibrant: true
|
||||
vibrant: true,
|
||||
},
|
||||
{
|
||||
color: "#57b5f9",
|
||||
name: this.$t("blue"),
|
||||
vibrant: false
|
||||
}
|
||||
vibrant: false,
|
||||
},
|
||||
],
|
||||
|
||||
settings: {
|
||||
@@ -357,91 +337,83 @@ export default {
|
||||
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/",
|
||||
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);
|
||||
)
|
||||
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"
|
||||
});
|
||||
});
|
||||
icon: "error",
|
||||
})
|
||||
})
|
||||
this.$toast.info(this.$t("logged_out"), {
|
||||
icon: "vpn_key"
|
||||
});
|
||||
icon: "vpn_key",
|
||||
})
|
||||
},
|
||||
signInWithGoogle() {
|
||||
const provider = new firebase.auth.GoogleAuthProvider();
|
||||
const provider = new firebase.auth.GoogleAuthProvider()
|
||||
firebase
|
||||
.auth()
|
||||
.signInWithPopup(provider)
|
||||
@@ -454,24 +426,24 @@ export default {
|
||||
action: {
|
||||
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)
|
||||
@@ -484,54 +456,51 @@ export default {
|
||||
action: {
|
||||
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.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
|
||||
);
|
||||
}
|
||||
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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
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
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Vue from "vue";
|
||||
import Vue from "vue"
|
||||
|
||||
export const SETTINGS_KEYS = [
|
||||
/**
|
||||
@@ -68,8 +68,8 @@ export const SETTINGS_KEYS = [
|
||||
* A boolean value indicating whether to use the browser extensions
|
||||
* to run the requests
|
||||
*/
|
||||
"EXTENSIONS_ENABLED"
|
||||
];
|
||||
"EXTENSIONS_ENABLED",
|
||||
]
|
||||
|
||||
export const state = () => ({
|
||||
settings: {},
|
||||
@@ -77,200 +77,190 @@ export const state = () => ({
|
||||
{
|
||||
name: "My Collection",
|
||||
folders: [],
|
||||
requests: []
|
||||
}
|
||||
requests: [],
|
||||
},
|
||||
],
|
||||
environments: [
|
||||
{
|
||||
name: "My Environment Variables",
|
||||
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: "",
|
||||
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: "",
|
||||
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) {
|
||||
const folder =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ export default () => ({
|
||||
rawParams: "",
|
||||
rawInput: false,
|
||||
requestType: "",
|
||||
contentType: ""
|
||||
contentType: "",
|
||||
},
|
||||
gql: {
|
||||
url: "https://rickandmortyapi.com/graphql",
|
||||
headers: [],
|
||||
variablesJSONString: "{}",
|
||||
query: ""
|
||||
query: "",
|
||||
},
|
||||
oauth2: {
|
||||
tokens: [],
|
||||
@@ -33,6 +33,6 @@ export default () => ({
|
||||
authUrl: "",
|
||||
accessTokenUrl: "",
|
||||
clientId: "",
|
||||
scope: ""
|
||||
}
|
||||
});
|
||||
scope: "",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1 +1 @@
|
||||
{ "message": "FAKE Cat API" }
|
||||
{ "message": "FAKE Cat API" }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
describe('Visit home', () => {
|
||||
describe("Visit home", () => {
|
||||
it('Have a page title with "Postwoman"', () => {
|
||||
cy.visit('/', { retryOnStatusCodeFailure: true })
|
||||
.get('title')
|
||||
.should('contain','Postwoman')
|
||||
cy.visit("/", { retryOnStatusCodeFailure: true })
|
||||
.get("title")
|
||||
.should("contain", "Postwoman")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
describe('Authentication', () => {
|
||||
describe("Authentication", () => {
|
||||
it(`Change default auth user and pass with url`, () => {
|
||||
cy.visit(`?&auth=Basic Auth&httpUser=foo&httpPassword=bar`, { retryOnStatusCodeFailure: true })
|
||||
.get('input[name="http_basic_user"]', { timeout: 500 })
|
||||
.invoke('val')
|
||||
.then((user) => {
|
||||
expect(user === 'foo').to.equal(true)
|
||||
.invoke("val")
|
||||
.then(user => {
|
||||
expect(user === "foo").to.equal(true)
|
||||
})
|
||||
|
||||
.get('input[name="http_basic_passwd"]')
|
||||
.invoke('val')
|
||||
.then((pass) => {
|
||||
expect(pass === 'bar').to.equal(true)
|
||||
.invoke("val")
|
||||
.then(pass => {
|
||||
expect(pass === "bar").to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('Enable user and pass at url with toggler', () => {
|
||||
cy.visit('/', { retryOnStatusCodeFailure: true })
|
||||
.get('#auth')
|
||||
.select('Basic Auth')
|
||||
it("Enable user and pass at url with toggler", () => {
|
||||
cy.visit("/", { retryOnStatusCodeFailure: true })
|
||||
.get("#auth")
|
||||
.select("Basic Auth")
|
||||
.get('input[name="http_basic_user"]', { timeout: 500 })
|
||||
.type('foo')
|
||||
.type("foo")
|
||||
.get('input[name="http_basic_passwd"]', { timeout: 500 })
|
||||
.type('bar')
|
||||
.type("bar")
|
||||
.url()
|
||||
.should('not.contain', 'foo')
|
||||
.should('not.contain', 'bar')
|
||||
.get('.toggle')
|
||||
.should("not.contain", "foo")
|
||||
.should("not.contain", "bar")
|
||||
.get(".toggle")
|
||||
.click()
|
||||
.url()
|
||||
.should('contain', 'foo')
|
||||
.should('contain', 'bar')
|
||||
})
|
||||
.should("contain", "foo")
|
||||
.should("contain", "bar")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
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 => {
|
||||
expect($wrapper).to.contain('FAKE Cat API')
|
||||
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 => {
|
||||
expect($wrapper).to.contain("FAKE Cat API")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
Cypress.Commands.add('seedAndVisit', (seedData, path = '/', method = 'GET') => {
|
||||
* 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) => {
|
||||
cy.visit('/settings')
|
||||
.get('#proxy')
|
||||
.find('.toggle')
|
||||
.click( { force: true } )
|
||||
.should('have.class', 'on')
|
||||
* 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 })
|
||||
.should("have.class", "on")
|
||||
.visit(goBackPath)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1 +1 @@
|
||||
import './commands'
|
||||
import "./commands"
|
||||
|
||||
Reference in New Issue
Block a user