Revert "Revert "Migrate Postwoman to Nuxt.js (full Vue and SCSS support)""
92
.gitignore
vendored
@@ -1 +1,91 @@
|
||||
node_modules
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# Nuxt generate
|
||||
dist
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# IDE / Editor
|
||||
.idea
|
||||
.editorconfig
|
||||
|
||||
# Service worker
|
||||
sw.*
|
||||
|
||||
# Mac OSX
|
||||
.DS_Store
|
||||
|
||||
# Vim swap files
|
||||
*.swp
|
||||
|
||||
31
.travis.yml
@@ -7,9 +7,28 @@
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "node"
|
||||
notifications:
|
||||
webhooks: https://www.travisbuddy.com
|
||||
env:
|
||||
- MY_VAR=EverythignIsAwesome
|
||||
- NODE_ENV=TEST
|
||||
- "8"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- "node_modules"
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
install:
|
||||
- npm install
|
||||
- npm run generate
|
||||
|
||||
script:
|
||||
- echo "Skipping tests"
|
||||
|
||||
deploy:
|
||||
provider: pages
|
||||
skip-cleanup: true
|
||||
github-token: $GITHUB_ACCESS_TOKEN # Set in travis-ci.org dashboard, marked secure https://docs.travis-ci.com/user/deployment/pages/#Setting-the-GitHub-token
|
||||
target-branch: gh-pages
|
||||
local-dir: dist
|
||||
on:
|
||||
branch: master
|
||||
|
||||
88
404.html
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no">
|
||||
<title>Postwoman - API request builder</title>
|
||||
<meta name="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<meta itemprop="name" content="Postwoman - API request builder">
|
||||
<meta itemprop="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
|
||||
<meta itemprop="image" content="icons/icon-192x192.png">
|
||||
<!-- See https://goo.gl/OOhYW5 -->
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<!-- See https://goo.gl/qRE0vM -->
|
||||
<meta name="theme-color" content="#121212">
|
||||
<!-- Add to homescreen for Chrome on Android. Fallback for manifest.json -->
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="application-name" content="Postwoman - API request builder">
|
||||
<!-- Add to homescreen for Safari on iOS -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="Postwoman - API request builder">
|
||||
<!-- Homescreen icons -->
|
||||
<link rel="apple-touch-icon" href="icons/icon-48x48.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="icons/icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="96x96" href="icons/icon-96x96.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="icons/icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="icons/icon-192x192.png">
|
||||
<!-- Tile icon for Windows 8 (144x144 + tile color) -->
|
||||
<meta name="msapplication-TileImage" content="icons/icon-144x144.png">
|
||||
<meta name="msapplication-TileColor" content="#121212">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<!-- OpenGraph -->
|
||||
<meta property="og:site_name" content="Postwoman - API request builder">
|
||||
<meta property="og:url" content="https://liyasthomas.github.io/postwoman">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Postwoman - API request builder">
|
||||
<meta property="og:description" content="API request builder">
|
||||
<meta property="og:image" content="icons/icon-144x144.png">
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@liyasthomas">
|
||||
<meta name="twitter:creator" content="@liyasthomas">
|
||||
<meta name="twitter:url" content="https://liyasthomas.github.io/postwoman">
|
||||
<meta name="twitter:title" content="Postwoman - API request builder">
|
||||
<meta name="twitter:description" content="API request builder">
|
||||
<meta name="twitter:image" content="icons/icon-144x144.png">
|
||||
<!-- Web Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('sw.js').then(function(registration) {
|
||||
console.log('ServiceWorker registration successful with scope: ', registration.scope);
|
||||
}).catch(function(err) {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main id="app">
|
||||
<header>
|
||||
<div>
|
||||
<a href="index.html">
|
||||
<h1 class="logo"><img src="icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
|
||||
</a>
|
||||
<h3>API request builder</h3>
|
||||
</div>
|
||||
</header>
|
||||
<h1>404 - Page not found</h1>
|
||||
<p><a href="index.html"><button>Go Home</button></a></p>
|
||||
<footer>
|
||||
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
|
||||
<button id="installPWA" onclick="installPWA()">
|
||||
Install PWA
|
||||
</button>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
36
README.md
@@ -2,27 +2,27 @@
|
||||
When I wrote this, only God and I understood what I was doing. Now, only God knows.
|
||||
```
|
||||
<div align="center">
|
||||
<a href="https://liyas-thomas.firebaseapp.com"><img src="https://raw.githubusercontent.com/liyasthomas/templates/master/assets/logo.gif" alt="Liyas Thomas" width="200"></a>
|
||||
<br>
|
||||
<h1>Liyas Thomas</h1>
|
||||
<sub>Built with ❤︎ by
|
||||
<a href="https://github.com/liyasthomas">liyasthomas</a> and
|
||||
<a href="https://github.com/liyasthomas/postwoman/graphs/contributors">contributors</a>
|
||||
</sub>
|
||||
<a href="https://liyas-thomas.firebaseapp.com"><img src="https://raw.githubusercontent.com/liyasthomas/templates/master/assets/logo.gif" alt="Liyas Thomas" width="200"></a>
|
||||
<br>
|
||||
<h1>Liyas Thomas</h1>
|
||||
<sub>Built with ❤︎ by
|
||||
<a href="https://github.com/liyasthomas">liyasthomas</a> and
|
||||
<a href="https://github.com/liyasthomas/postwoman/graphs/contributors">contributors</a>
|
||||
</sub>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
[](https://travis-ci.org/liyasthomas/postwoman) [](https://github.com/liyasthomas/postwoman/releases/latest) [](https://github.com/liyasthomas/postwoman/archive/master.zip) [](https://github.com/liyasthomas/postwoman/blob/master/LICENSE) [](https://github.com/liyasthomas/postwoman/issues) [](https://liyas-thomas.firebaseapp.com) [](https://www.paypal.me/liyascthomas) [](https://www.buymeacoffee.com/liyasthomas)
|
||||
|
||||
# <img src="icons/icon-48x48.png" alt="postwoman" width="32"> Postwoman
|
||||
# <img src="static/icon.png" alt="postwoman" width="32"> Postwoman
|
||||
|
||||
### 👽 API request builder by [Liyas Thomas](https://github.com/liyasthomas)
|
||||
|
||||
<div align="center">
|
||||
<br>
|
||||
<img src="icons/screely.png" alt="postwoman" width="100%">
|
||||
<img src="icons/screely2.png" alt="postwoman" width="100%">
|
||||
<img src="static/screely.png" alt="postwoman" width="100%">
|
||||
<img src="static/screely2.png" alt="postwoman" width="100%">
|
||||
<br>
|
||||
</div>
|
||||
|
||||
@@ -58,15 +58,25 @@ You're done!
|
||||
* HTML - For the web framework
|
||||
* CSS - For styling components
|
||||
* JavaScript - For magic!
|
||||
* [Vue](https://vuejs.org/) - To add to the JavaScript magic!
|
||||
* [Nuxt](https://nuxtjs.org/) - To add to the Vue magic! <!-- (Nuxt helps create the PWA and single page application.) -->
|
||||
|
||||
---
|
||||
|
||||
## Developing
|
||||
|
||||
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
|
||||
1. Install dependencies by running `npm install` within the `postwoman` directory.
|
||||
1. Start the development server with `npm start`.
|
||||
1. Open development site by going to [http://localhost:8080](http://localhost:8080) in your browser.
|
||||
1. Install dependencies by running `npm install` within the directory that you cloned (probably `postwoman`).
|
||||
1. Start the development server with `npm run dev`.
|
||||
1. Open development site by going to [http://localhost:3000](http://localhost:3000) in your browser.
|
||||
|
||||
---
|
||||
|
||||
## Releasing
|
||||
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
|
||||
1. Install dependencies by running `npm install` within the directory that you cloned (probably `postwoman`).
|
||||
1. Build the release files with `npm run build`.
|
||||
1. Find the built project in `./dist`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
7
assets/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# ASSETS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
|
||||
2
assets/css/fonts.scss
Normal file
@@ -0,0 +1,2 @@
|
||||
// Poppins (Google Fonts)
|
||||
@import url("https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap");
|
||||
@@ -70,13 +70,15 @@ footer {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
color: var(--ac-color);
|
||||
body.sticky-footer footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
.logo {
|
||||
color: var(--ac-color);
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -213,3 +215,7 @@ ol li {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
#installPWA {
|
||||
display: none;
|
||||
}
|
||||
54
assets/js/pwa.js
Normal file
@@ -0,0 +1,54 @@
|
||||
export default () => {
|
||||
//*** Determine whether or not the PWA has been installed. ***//
|
||||
|
||||
// Step 1: Check local storage
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//*** If the PWA has not been installed, show the install PWA prompt.. ***//
|
||||
let deferredPrompt = null;
|
||||
window.addEventListener('beforeinstallprompt', (event) => {
|
||||
deferredPrompt = event;
|
||||
|
||||
// Show the install button if the prompt appeared.
|
||||
if (!pwaInstalled) {
|
||||
document.querySelector('#installPWA').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
// When the app is installed, remove install prompts.
|
||||
window.addEventListener('appinstalled', (event) => {
|
||||
localStorage.setItem('pwaInstalled', 'yes');
|
||||
pwaInstalled = true;
|
||||
document.getElementById('installPWA').style.display = 'none';
|
||||
});
|
||||
|
||||
// When the app is uninstalled, add the prompts back
|
||||
|
||||
|
||||
return async () => {
|
||||
if (deferredPrompt) {
|
||||
deferredPrompt.prompt();
|
||||
let outcome = await deferredPrompt.userChoice;
|
||||
|
||||
if (outcome === 'accepted') {
|
||||
console.log('Postwoman was installed successfully.')
|
||||
} else {
|
||||
console.log('Postwoman could not be installed. (Installation rejected by user.)')
|
||||
}
|
||||
deferredPrompt = null;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
7
components/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# COMPONENTS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
The components directory contains your Vue.js Components.
|
||||
|
||||
_Nuxt.js doesn't supercharge these components._
|
||||
319
index.html
@@ -1,319 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no">
|
||||
<title>Postwoman - API request builder</title>
|
||||
<meta name="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<meta itemprop="name" content="Postwoman - API request builder">
|
||||
<meta itemprop="description" content="The Postwoman API request builder helps you create your requests faster, saving you precious time on your development.">
|
||||
<meta itemprop="image" content="icons/icon-192x192.png">
|
||||
<!-- See https://goo.gl/OOhYW5 -->
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<!-- See https://goo.gl/qRE0vM -->
|
||||
<meta name="theme-color" content="#121212">
|
||||
<!-- Add to homescreen for Chrome on Android. Fallback for manifest.json -->
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="application-name" content="Postwoman - API request builder">
|
||||
<!-- Add to homescreen for Safari on iOS -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="Postwoman - API request builder">
|
||||
<!-- Homescreen icons -->
|
||||
<link rel="apple-touch-icon" href="icons/icon-48x48.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="icons/icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="96x96" href="icons/icon-96x96.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="icons/icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="icons/icon-192x192.png">
|
||||
<!-- Tile icon for Windows 8 (144x144 + tile color) -->
|
||||
<meta name="msapplication-TileImage" content="icons/icon-144x144.png">
|
||||
<meta name="msapplication-TileColor" content="#121212">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<!-- OpenGraph -->
|
||||
<meta property="og:site_name" content="Postwoman - API request builder">
|
||||
<meta property="og:url" content="https://liyasthomas.github.io/postwoman">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Postwoman - API request builder">
|
||||
<meta property="og:description" content="API request builder">
|
||||
<meta property="og:image" content="icons/icon-144x144.png">
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@liyasthomas">
|
||||
<meta name="twitter:creator" content="@liyasthomas">
|
||||
<meta name="twitter:url" content="https://liyasthomas.github.io/postwoman">
|
||||
<meta name="twitter:title" content="Postwoman - API request builder">
|
||||
<meta name="twitter:description" content="API request builder">
|
||||
<meta name="twitter:image" content="icons/icon-144x144.png">
|
||||
<!-- Web Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:500,700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('sw.js').then(function(registration) {
|
||||
console.log('ServiceWorker registration successful with scope: ', registration.scope);
|
||||
}).catch(function(err) {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main id="app">
|
||||
<header>
|
||||
<div>
|
||||
<a href="">
|
||||
<h1 class="logo"><img src="icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
|
||||
</a>
|
||||
<h3>API request builder</h3>
|
||||
</div>
|
||||
</header>
|
||||
<fieldset class="request" ref="request">
|
||||
<legend v-on:click="collapse">Request ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="method">Method</label>
|
||||
<select v-model="method">
|
||||
<option>GET</option>
|
||||
<option>POST</option>
|
||||
<option>PUT</option>
|
||||
<option>DELETE</option>
|
||||
<option>OPTIONS</option>
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<label for="url">URL</label>
|
||||
<input type="url" v-bind:class="{ error: urlNotValid }" v-model="url" v-on:keyup.enter="sendRequest">
|
||||
</li>
|
||||
<li>
|
||||
<label for="path">Path</label>
|
||||
<input v-model="path" v-on:keyup.enter="sendRequest">
|
||||
</li>
|
||||
<li>
|
||||
<label for="action"> </label>
|
||||
<button v-bind:class="{ disabled: urlNotValid }" name="action" @click="sendRequest">Send</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="reqbody" v-if="method === 'POST' || method === 'PUT'">
|
||||
<legend v-on:click="collapse">Request Body ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label>Content Type</label>
|
||||
<select v-model="contentType">
|
||||
<option>application/json</option>
|
||||
<option>www-form/urlencoded</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<ol v-for="(param, index) in bodyParams">
|
||||
<li>
|
||||
<label :for="'bparam'+index">Key {{index + 1}}</label>
|
||||
<input :name="'bparam'+index" v-model="param.key">
|
||||
</li>
|
||||
<li>
|
||||
<label :for="'bvalue'+index">Value {{index + 1}}</label>
|
||||
<input :name="'bvalue'+index" v-model="param.value">
|
||||
</li>
|
||||
<li>
|
||||
<label for="request"> </label>
|
||||
<button name="request" @click="removeRequestBodyParam(index)">Remove</button>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="addrequest">Action</label>
|
||||
<button name="addrequest" @click="addRequestBodyParam">Add</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="request">Parameter List</label>
|
||||
<textarea name="request" rows="1" readonly>{{rawRequestBody || '(add at least one parameter)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="authentication hidden">
|
||||
<legend v-on:click="collapse">Authentication ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="auth">Authentication Type</label>
|
||||
<select v-model="auth">
|
||||
<option>None</option>
|
||||
<option>Basic</option>
|
||||
<option>Bearer Token</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-if="auth === 'Basic'">
|
||||
<li>
|
||||
<label for="http_basic_user">User</label>
|
||||
<input v-model="httpUser">
|
||||
</li>
|
||||
<li>
|
||||
<label for="http_basic_passwd">Password</label>
|
||||
<input v-model="httpPassword" type="password">
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-if="auth === 'Bearer Token'">
|
||||
<li>
|
||||
<label for="bearer_token">Token</label>
|
||||
<input v-model="bearerToken">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="parameters hidden">
|
||||
<legend v-on:click="collapse">Parameters ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ol v-for="(param, index) in params">
|
||||
<li>
|
||||
<label :for="'param'+index">Key {{index + 1}}</label>
|
||||
<input :name="'param'+index" v-model="param.key">
|
||||
</li>
|
||||
<li>
|
||||
<label :for="'value'+index">Value {{index + 1}}</label>
|
||||
<input :name="'value'+index" v-model="param.value">
|
||||
</li>
|
||||
<li>
|
||||
<label for="param"> </label>
|
||||
<button name="param" @click="removeRequestParam(index)">Remove</button>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="add">Action</label>
|
||||
<button name="add" @click="addRequestParam">Add</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="request">Parameter List</label>
|
||||
<textarea name="request" rows="1" readonly>{{queryString || '(add at least one parameter)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="response" id="response" ref="response">
|
||||
<legend v-on:click="collapse">Response ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="status">status</label>
|
||||
<input name="status" type="text" readonly :value="response.status || '(waiting to send request)'">
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-for="(value, key) in response.headers">
|
||||
<li>
|
||||
<label for="value">{{key}}</label>
|
||||
<input name="value" :value="value" readonly>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="body">response</label>
|
||||
<textarea name="body" rows="10" readonly>{{response.body || '(waiting to send request)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="history">
|
||||
<legend v-on:click="collapse">History ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<button v-bind:class="{ disabled: noHistoryToClear }" v-on:click="clearHistory">Clear History</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-for="entry in history">
|
||||
<li>
|
||||
<label for="time">Time</label>
|
||||
<input name="time" type="text" readonly :value="entry.time">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">Method</label>
|
||||
<input name="name" type="text" readonly :value="entry.method">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">URL</label>
|
||||
<input name="name" type="text" readonly :value="entry.url">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">Path</label>
|
||||
<input name="name" type="text" readonly :value="entry.path">
|
||||
</li>
|
||||
<li>
|
||||
<label for="delete"> </label>
|
||||
<button name="delete" @click="deleteHistory(entry)">Delete</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for="use"> </label>
|
||||
<button name="use" @click="useHistory(entry)">Use</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<footer>
|
||||
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
|
||||
<button id="installPWA" onclick="installPWA()">
|
||||
Install PWA
|
||||
</button>
|
||||
</footer>
|
||||
</main>
|
||||
<script src="script.js"></script>
|
||||
<script>
|
||||
let pwaInstalled = localStorage.getItem('pwaInstalled') == 'yes'
|
||||
if (window.matchMedia('(display-mode: standalone)').matches) {
|
||||
localStorage.setItem('pwaInstalled', 'yes')
|
||||
pwaInstalled = true
|
||||
}
|
||||
if (window.navigator.standalone === true) {
|
||||
localStorage.setItem('pwaInstalled', 'yes')
|
||||
pwaInstalled = true
|
||||
}
|
||||
if (pwaInstalled) {
|
||||
document.getElementById('installPWA').style.display = 'none'
|
||||
} else {
|
||||
document.getElementById('installPWA').style.display = 'block'
|
||||
}
|
||||
let deferredPrompt = null
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
deferredPrompt = e
|
||||
})
|
||||
async function installPWA() {
|
||||
if (deferredPrompt) {
|
||||
deferredPrompt.prompt()
|
||||
deferredPrompt.userChoice.then(({
|
||||
outcome
|
||||
}) => {
|
||||
if (outcome === 'accepted') {
|
||||
console.log('Your PWA has been installed')
|
||||
} else {
|
||||
console.log('User chose to not install your PWA')
|
||||
}
|
||||
deferredPrompt = null
|
||||
})
|
||||
}
|
||||
}
|
||||
window.addEventListener('appinstalled', (evt) => {
|
||||
localStorage.setItem('pwaInstalled', 'yes')
|
||||
pwaInstalled = true
|
||||
document.getElementById('installPWA').style.display = 'none'
|
||||
})
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
12
jsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["./*"],
|
||||
"@/*": ["./*"],
|
||||
"~~/*": ["./*"],
|
||||
"@@/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", ".nuxt", "dist"]
|
||||
}
|
||||
7
layouts/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# LAYOUTS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your Application Layouts.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
|
||||
62
layouts/default.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<header>
|
||||
<div class="slide-in">
|
||||
<nuxt-link to="/">
|
||||
<h1 class="logo"><img src="~static/icons/logo.svg" alt="" style="height: 24px; margin-right: 16px">Postwoman</h1>
|
||||
</nuxt-link>
|
||||
<h3>Lightweight API request builder</h3>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<nuxt id="main" />
|
||||
|
||||
<footer>
|
||||
<a href="https://github.com/liyasthomas/postwoman" target="_blank"><img src="~static/icons/github.svg" alt="" style="margin-right: 16px">GitHub</a>
|
||||
<button id="installPWA" @click.prevent="showInstallPrompt()">
|
||||
Install PWA
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.slide-in {
|
||||
position: relative;
|
||||
animation: slideIn 0.4s forwards ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
left: -30px;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
header, #main, footer {
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import intializePwa from '../assets/js/pwa';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
showInstallPrompt: null
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
(async () => {
|
||||
this.showInstallPrompt = await intializePwa();
|
||||
})();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
35
layouts/error.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="page page-error">
|
||||
<h1>{{ error.statusCode }}</h1>
|
||||
<h2>{{ error.message }}</h2>
|
||||
<br>
|
||||
<p><nuxt-link to="/"><button>Go Home</button></nuxt-link></p>
|
||||
<p><a href="/">Reload</a></p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
// Center the error page in the viewport.
|
||||
.page-error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100%;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['error'],
|
||||
head () {
|
||||
return {
|
||||
bodyAttrs: {
|
||||
class: 'sticky-footer'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "Postwoman",
|
||||
"short_name": "Postwoman",
|
||||
"description": "API request builder",
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/icon-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./",
|
||||
"display": "standalone",
|
||||
"theme_color": "#121212",
|
||||
"background_color": "#121212"
|
||||
}
|
||||
8
middleware/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# MIDDLEWARE
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your application middleware.
|
||||
Middleware let you define custom functions that can be run before rendering either a page or a group of pages.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).
|
||||
138
nuxt.config.js
Normal file
@@ -0,0 +1,138 @@
|
||||
// Some helpful application constants.
|
||||
// TODO: Use these when rendering the pages (rather than just for head/meta tags...)
|
||||
const meta = {
|
||||
name: "Postwoman",
|
||||
shortDescription: "Lightweight API request builder",
|
||||
description: "The Postwoman API request builder helps you create your requests faster, saving you precious time on your development."
|
||||
};
|
||||
|
||||
export default {
|
||||
mode: 'spa',
|
||||
/*
|
||||
** Headers of the page
|
||||
*/
|
||||
head: {
|
||||
title: `${meta.name} \u2022 ${meta.shortDescription}`,
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no, minimal-ui' },
|
||||
{ hid: 'description', name: 'description', content: meta.description || '' },
|
||||
|
||||
{ name: 'X-UA-Compatible', content: "IE=edge, chrome=1" },
|
||||
{ itemprop: "name", content: `${meta.name} \u2022 ${meta.shortDescription}` },
|
||||
{ itemprop: "description", content: meta.description },
|
||||
{ itemprop: "image", content: "/icons/icon-192x192.png" },
|
||||
|
||||
// Add to homescreen for Chrome on Android. Fallback for PWA (handled by nuxt)
|
||||
{ name: 'application-name', content: meta.name },
|
||||
|
||||
// Add to homescreen for Safari on iOS
|
||||
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
||||
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' },
|
||||
{ name: 'apple-mobile-web-app-title', content: meta.name },
|
||||
|
||||
// Windows phone tile icon
|
||||
{ name: 'msapplication-TileImage', content: 'icons/icon-144x144.png' },
|
||||
{ name: 'msapplication-TileColor', content: '#121212' },
|
||||
{ name: 'msapplication-tap-highlight', content: 'no' },
|
||||
|
||||
// OpenGraph
|
||||
{ property: 'og:site_name', content: meta.name },
|
||||
{ property: 'og:url', content: 'https://liyasthomas.github.io/postwoman' },
|
||||
{ property: 'og:type', content: 'website' },
|
||||
{ property: 'og:title', content: `${meta.name} \u2022 ${meta.shortDescription}` },
|
||||
{ property: 'og:description', content: meta.description },
|
||||
{ property: 'og:image', content: '/icons/icon-144x144.png' },
|
||||
|
||||
// Twitter
|
||||
{ name: 'twitter:card', content: "summary" },
|
||||
{ name: 'twitter:site', content: "@liyasthomas" },
|
||||
{ name: 'twitter:creator', content: "@liyasthomas" },
|
||||
{ name: 'twitter:url', content: "https://liyasthomas.github.io/postwoman" },
|
||||
{ name: 'twitter:title', content: meta.name },
|
||||
{ name: 'twitter:description', content: meta.shortDescription },
|
||||
{ name: 'twitter:image', content: '/icons/icon-144x144.png' },
|
||||
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
|
||||
|
||||
// Home-screen icons (iOS)
|
||||
{ rel: 'apple-touch-icon', href: '/icons/icon-48x48.png' },
|
||||
{ rel: 'apple-touch-icon', sizes: '72x72', href: '/icons/icon-72x72.png' },
|
||||
{ rel: 'apple-touch-icon', sizes: '96x96', href: '/icons/icon-96x96.png' },
|
||||
{ rel: 'apple-touch-icon', sizes: '144x144', href: '/icons/icon-144x144.png' },
|
||||
{ rel: 'apple-touch-icon', sizes: '192x192', href: '/icons/icon-192x192.png' },
|
||||
]
|
||||
},
|
||||
/*
|
||||
** Customize the progress-bar color
|
||||
*/
|
||||
loading: { color: '#88FB4F' },
|
||||
/*
|
||||
** Global CSS
|
||||
*/
|
||||
css: [
|
||||
'@/assets/css/fonts.scss',
|
||||
'@/assets/css/styles.scss'
|
||||
],
|
||||
/*
|
||||
** Plugins to load before mounting the App
|
||||
*/
|
||||
plugins: [
|
||||
],
|
||||
/*
|
||||
** Nuxt.js dev-modules
|
||||
*/
|
||||
buildModules: [
|
||||
],
|
||||
/*
|
||||
** Nuxt.js modules
|
||||
*/
|
||||
modules: [
|
||||
// See https://goo.gl/OOhYW5
|
||||
['@nuxtjs/pwa', {
|
||||
manifest: {
|
||||
name: meta.name,
|
||||
short_name: meta.name,
|
||||
description: meta.shortDescription,
|
||||
|
||||
display: "standalone",
|
||||
theme_color: "#121212",
|
||||
background_color: "#121212",
|
||||
|
||||
icons: ((sizes) => {
|
||||
let icons = [];
|
||||
|
||||
for(let size of sizes){
|
||||
icons.push({
|
||||
"src": `/icons/icon-${size}x${size}.png`,
|
||||
"type": "image/png",
|
||||
"sizes": `${size}x${size}`
|
||||
});
|
||||
}
|
||||
|
||||
return icons;
|
||||
})([48, 72, 96, 144, 192, 512])
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
/*
|
||||
** Build configuration
|
||||
*/
|
||||
build: {
|
||||
/*
|
||||
** You can extend webpack config here
|
||||
*/
|
||||
extend (config, ctx) {
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
** Generate configuration
|
||||
*/
|
||||
generate: {
|
||||
fallback: true
|
||||
}
|
||||
}
|
||||
11139
package-lock.json
generated
Normal file
35
package.json
@@ -1,18 +1,21 @@
|
||||
{
|
||||
"name": "Postwoman",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/liyasthomas/postwoman.git"
|
||||
},
|
||||
"description": "API request builder",
|
||||
"author": "liyasthomas",
|
||||
"version": "0.1.0",
|
||||
"devDependencies": {
|
||||
"http-server": "^0.11.1",
|
||||
"jshint": "^2.10.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "http-server -c-1",
|
||||
"test": "jshint travis.js"
|
||||
}
|
||||
"name": "postwoman",
|
||||
"version": "1.0.0",
|
||||
"description": "Lightweight API request builder by Liyas Thomas",
|
||||
"author": "liyasthomas",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "nuxt",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start",
|
||||
"generate": "nuxt generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"nuxt": "^2.0.0",
|
||||
"@nuxtjs/pwa": "^3.0.0-0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-sass": "^4.12.0",
|
||||
"sass-loader": "^7.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
6
pages/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# PAGES
|
||||
|
||||
This directory contains your Application Views and Routes.
|
||||
The framework reads all the `*.vue` files inside this directory and creates the router of your application.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
|
||||
380
pages/index.vue
Normal file
@@ -0,0 +1,380 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
|
||||
<fieldset class="request" ref="request">
|
||||
<legend v-on:click="collapse">Request ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="method">Method</label>
|
||||
<select v-model="method">
|
||||
<option>GET</option>
|
||||
<option>POST</option>
|
||||
<option>PUT</option>
|
||||
<option>DELETE</option>
|
||||
<option>OPTIONS</option>
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<label for="url">URL</label>
|
||||
<input type="url" v-bind:class="{ error: urlNotValid }" v-model="url" v-on:keyup.enter="sendRequest">
|
||||
</li>
|
||||
<li>
|
||||
<label for="path">Path</label>
|
||||
<input v-model="path" v-on:keyup.enter="sendRequest">
|
||||
</li>
|
||||
<li>
|
||||
<label for="action"> </label>
|
||||
<button v-bind:class="{ disabled: urlNotValid }" name="action" @click="sendRequest">Send</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="reqbody" v-if="method === 'POST' || method === 'PUT'">
|
||||
<legend v-on:click="collapse">Request Body ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label>Content Type</label>
|
||||
<select v-model="contentType">
|
||||
<option>application/json</option>
|
||||
<option>www-form/urlencoded</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<ol v-for="(param, index) in bodyParams">
|
||||
<li>
|
||||
<label :for="'bparam'+index">Key {{index + 1}}</label>
|
||||
<input :name="'bparam'+index" v-model="param.key">
|
||||
</li>
|
||||
<li>
|
||||
<label :for="'bvalue'+index">Value {{index + 1}}</label>
|
||||
<input :name="'bvalue'+index" v-model="param.value">
|
||||
</li>
|
||||
<li>
|
||||
<label for="request"> </label>
|
||||
<button name="request" @click="removeRequestBodyParam(index)">Remove</button>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="addrequest">Action</label>
|
||||
<button name="addrequest" @click="addRequestBodyParam">Add</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="request">Parameter List</label>
|
||||
<textarea name="request" rows="1" readonly>{{rawRequestBody || '(add at least one parameter)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="authentication hidden">
|
||||
<legend v-on:click="collapse">Authentication ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="auth">Authentication Type</label>
|
||||
<select v-model="auth">
|
||||
<option>None</option>
|
||||
<option>Basic</option>
|
||||
<option>Bearer Token</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-if="auth === 'Basic'">
|
||||
<li>
|
||||
<label for="http_basic_user">User</label>
|
||||
<input v-model="httpUser">
|
||||
</li>
|
||||
<li>
|
||||
<label for="http_basic_passwd">Password</label>
|
||||
<input v-model="httpPassword" type="password">
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-if="auth === 'Bearer Token'">
|
||||
<li>
|
||||
<label for="bearer_token">Token</label>
|
||||
<input v-model="bearerToken">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="parameters hidden">
|
||||
<legend v-on:click="collapse">Parameters ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ol v-for="(param, index) in params">
|
||||
<li>
|
||||
<label :for="'param'+index">Key {{index + 1}}</label>
|
||||
<input :name="'param'+index" v-model="param.key">
|
||||
</li>
|
||||
<li>
|
||||
<label :for="'value'+index">Value {{index + 1}}</label>
|
||||
<input :name="'value'+index" v-model="param.value">
|
||||
</li>
|
||||
<li>
|
||||
<label for="param"> </label>
|
||||
<button name="param" @click="removeRequestParam(index)">Remove</button>
|
||||
</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="add">Action</label>
|
||||
<button name="add" @click="addRequestParam">Add</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="request">Parameter List</label>
|
||||
<textarea name="request" rows="1" readonly>{{queryString || '(add at least one parameter)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="response" id="response" ref="response">
|
||||
<legend v-on:click="collapse">Response ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<label for="status">status</label>
|
||||
<input name="status" type="text" readonly :value="response.status || '(waiting to send request)'">
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-for="(value, key) in response.headers">
|
||||
<li>
|
||||
<label for="value">{{key}}</label>
|
||||
<input name="value" :value="value" readonly>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<label for="body">response</label>
|
||||
<textarea name="body" rows="10" readonly>{{response.body || '(waiting to send request)'}}</textarea>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="history">
|
||||
<legend v-on:click="collapse">History ↕</legend>
|
||||
<div class="collapsible">
|
||||
<ul>
|
||||
<li>
|
||||
<button v-bind:class="{ disabled: noHistoryToClear }" v-on:click="clearHistory">Clear History</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-for="entry in history">
|
||||
<li>
|
||||
<label for="time">Time</label>
|
||||
<input name="time" type="text" readonly :value="entry.time">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">Method</label>
|
||||
<input name="name" type="text" readonly :value="entry.method">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">URL</label>
|
||||
<input name="name" type="text" readonly :value="entry.url">
|
||||
</li>
|
||||
<li>
|
||||
<label for="name">Path</label>
|
||||
<input name="name" type="text" readonly :value="entry.path">
|
||||
</li>
|
||||
<li>
|
||||
<label for="delete"> </label>
|
||||
<button name="delete" @click="deleteHistory(entry)">Delete</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for="use"> </label>
|
||||
<button name="use" @click="useHistory(entry)">Use</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const parseHeaders = xhr => {
|
||||
const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
|
||||
const headerMap = {};
|
||||
headers.forEach(line => {
|
||||
const parts = line.split(': ');
|
||||
const header = parts.shift().toLowerCase();
|
||||
const value = parts.join(': ');
|
||||
headerMap[header] = value
|
||||
});
|
||||
return headerMap
|
||||
};
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
method: 'GET',
|
||||
url: 'https://reqres.in',
|
||||
auth: 'None',
|
||||
path: '/api/users',
|
||||
httpUser: '',
|
||||
httpPassword: '',
|
||||
bearerToken: '',
|
||||
params: [],
|
||||
bodyParams: [],
|
||||
contentType: 'application/json',
|
||||
response: {
|
||||
status: '',
|
||||
headers: '',
|
||||
body: ''
|
||||
},
|
||||
history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
noHistoryToClear() {
|
||||
return this.history.length === 0;
|
||||
},
|
||||
urlNotValid() {
|
||||
const pattern = new RegExp('^(https?:\\/\\/)?' +
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' +
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' +
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' +
|
||||
'(\\#[-a-z\\d_]*)?$', 'i')
|
||||
return !pattern.test(this.url)
|
||||
},
|
||||
rawRequestBody() {
|
||||
const {
|
||||
bodyParams
|
||||
} = this
|
||||
if (this.contentType === 'application/json') {
|
||||
try {
|
||||
const obj = JSON.parse(`{${bodyParams.filter(({ key }) => !!key).map(({ key, value }) => `
|
||||
"${key}": "${value}"
|
||||
`).join()}}`)
|
||||
return JSON.stringify(obj)
|
||||
} catch (ex) {
|
||||
return 'invalid'
|
||||
}
|
||||
} else {
|
||||
return bodyParams
|
||||
.filter(({
|
||||
key
|
||||
}) => !!key)
|
||||
.map(({
|
||||
key,
|
||||
value
|
||||
}) => `${key}=${encodeURIComponent(value)}`).join('&')
|
||||
}
|
||||
},
|
||||
queryString() {
|
||||
const result = this.params
|
||||
.filter(({
|
||||
key
|
||||
}) => !!key)
|
||||
.map(({
|
||||
key,
|
||||
value
|
||||
}) => `${key}=${encodeURIComponent(value)}`).join('&')
|
||||
return result == '' ? '' : `?${result}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteHistory(entry) {
|
||||
this.history.splice(this.history.indexOf(entry), 1)
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
},
|
||||
clearHistory() {
|
||||
this.history = []
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
},
|
||||
useHistory({
|
||||
method,
|
||||
url,
|
||||
path
|
||||
}) {
|
||||
this.method = method
|
||||
this.url = url
|
||||
this.path = path
|
||||
this.$refs.request.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
},
|
||||
collapse({
|
||||
target
|
||||
}) {
|
||||
const el = target.parentNode.className
|
||||
document.getElementsByClassName(el)[0].classList.toggle('hidden')
|
||||
},
|
||||
sendRequest() {
|
||||
if (this.urlNotValid) {
|
||||
alert('Please check the formatting of the URL')
|
||||
return
|
||||
}
|
||||
const n = new Date().toLocaleTimeString()
|
||||
this.history = [{
|
||||
time: n,
|
||||
method: this.method,
|
||||
url: this.url,
|
||||
path: this.path
|
||||
}, ...this.history]
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
if (this.$refs.response.classList.contains('hidden')) {
|
||||
this.$refs.response.classList.toggle('hidden')
|
||||
}
|
||||
this.$refs.response.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
this.response.status = 'Fetching...'
|
||||
this.response.body = 'Loading...'
|
||||
const xhr = new XMLHttpRequest()
|
||||
const user = this.auth === 'Basic' ? this.httpUser : null
|
||||
const pswd = this.auth === 'Basic' ? this.httpPassword : null
|
||||
xhr.open(this.method, this.url + this.path + this.queryString, true, user, pswd)
|
||||
if (this.auth === 'Bearer Token') {
|
||||
xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken);
|
||||
}
|
||||
if (this.method === 'POST' || this.method === 'PUT') {
|
||||
const requestBody = this.rawRequestBody
|
||||
xhr.setRequestHeader('Content-Length', requestBody.length)
|
||||
xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`)
|
||||
xhr.send(requestBody)
|
||||
} else {
|
||||
xhr.send()
|
||||
}
|
||||
xhr.onload = e => {
|
||||
this.response.status = xhr.status
|
||||
const headers = this.response.headers = parseHeaders(xhr)
|
||||
if ((headers['content-type'] || '').startsWith('application/json')) {
|
||||
this.response.body = JSON.stringify(JSON.parse(xhr.responseText), null, 2)
|
||||
} else {
|
||||
this.response.body = xhr.responseText
|
||||
}
|
||||
}
|
||||
xhr.onerror = e => {
|
||||
this.response.status = xhr.status
|
||||
this.response.body = xhr.statusText
|
||||
}
|
||||
},
|
||||
addRequestParam() {
|
||||
this.params.push({
|
||||
key: '',
|
||||
value: ''
|
||||
})
|
||||
return false
|
||||
},
|
||||
removeRequestParam(index) {
|
||||
this.params.splice(index, 1)
|
||||
},
|
||||
addRequestBodyParam() {
|
||||
this.bodyParams.push({
|
||||
key: '',
|
||||
value: ''
|
||||
})
|
||||
return false
|
||||
},
|
||||
removeRequestBodyParam(index) {
|
||||
this.bodyParams.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
7
plugins/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# PLUGINS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains Javascript plugins that you want to run before mounting the root Vue.js application.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).
|
||||
179
script.js
@@ -1,179 +0,0 @@
|
||||
const parseHeaders = xhr => {
|
||||
const headers = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/)
|
||||
const headerMap = {}
|
||||
headers.forEach(line => {
|
||||
const parts = line.split(': ')
|
||||
const header = parts.shift().toLowerCase()
|
||||
const value = parts.join(': ')
|
||||
headerMap[header] = value
|
||||
})
|
||||
return headerMap
|
||||
}
|
||||
const app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
method: 'GET',
|
||||
url: 'https://reqres.in',
|
||||
auth: 'None',
|
||||
path: '/api/users',
|
||||
httpUser: '',
|
||||
httpPassword: '',
|
||||
bearerToken: '',
|
||||
params: [],
|
||||
bodyParams: [],
|
||||
contentType: 'application/json',
|
||||
response: {
|
||||
status: '',
|
||||
headers: '',
|
||||
body: ''
|
||||
},
|
||||
history: window.localStorage.getItem('history') ? JSON.parse(window.localStorage.getItem('history')) : []
|
||||
},
|
||||
computed: {
|
||||
noHistoryToClear() {
|
||||
return this.history.length === 0;
|
||||
},
|
||||
urlNotValid() {
|
||||
const pattern = new RegExp('^(https?:\\/\\/)?' +
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' +
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))' +
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?' +
|
||||
'(\\#[-a-z\\d_]*)?$', 'i')
|
||||
return !pattern.test(this.url)
|
||||
},
|
||||
rawRequestBody() {
|
||||
const {
|
||||
bodyParams
|
||||
} = this
|
||||
if (this.contentType === 'application/json') {
|
||||
try {
|
||||
const obj = JSON.parse(`{${bodyParams.filter(({ key }) => !!key).map(({ key, value }) => `
|
||||
"${key}": "${value}"
|
||||
`).join()}}`)
|
||||
return JSON.stringify(obj)
|
||||
} catch (ex) {
|
||||
return 'invalid'
|
||||
}
|
||||
} else {
|
||||
return bodyParams
|
||||
.filter(({
|
||||
key
|
||||
}) => !!key)
|
||||
.map(({
|
||||
key,
|
||||
value
|
||||
}) => `${key}=${encodeURIComponent(value)}`).join('&')
|
||||
}
|
||||
},
|
||||
queryString() {
|
||||
const result = this.params
|
||||
.filter(({
|
||||
key
|
||||
}) => !!key)
|
||||
.map(({
|
||||
key,
|
||||
value
|
||||
}) => `${key}=${encodeURIComponent(value)}`).join('&')
|
||||
return result == '' ? '' : `?${result}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteHistory(entry) {
|
||||
this.history.splice(this.history.indexOf(entry), 1)
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
},
|
||||
clearHistory() {
|
||||
this.history = []
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
},
|
||||
useHistory({
|
||||
method,
|
||||
url,
|
||||
path
|
||||
}) {
|
||||
this.method = method
|
||||
this.url = url
|
||||
this.path = path
|
||||
this.$refs.request.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
},
|
||||
collapse({
|
||||
target
|
||||
}) {
|
||||
const el = target.parentNode.className
|
||||
document.getElementsByClassName(el)[0].classList.toggle('hidden')
|
||||
},
|
||||
sendRequest() {
|
||||
if (this.urlNotValid) {
|
||||
alert('Please check the formatting of the URL')
|
||||
return
|
||||
}
|
||||
const n = new Date().toLocaleTimeString()
|
||||
this.history = [{
|
||||
time: n,
|
||||
method: this.method,
|
||||
url: this.url,
|
||||
path: this.path
|
||||
}, ...this.history]
|
||||
window.localStorage.setItem('history', JSON.stringify(this.history))
|
||||
if (this.$refs.response.classList.contains('hidden')) {
|
||||
this.$refs.response.classList.toggle('hidden')
|
||||
}
|
||||
this.$refs.response.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
this.response.status = 'Fetching...'
|
||||
this.response.body = 'Loading...'
|
||||
const xhr = new XMLHttpRequest()
|
||||
const user = this.auth === 'Basic' ? this.httpUser : null
|
||||
const pswd = this.auth === 'Basic' ? this.httpPassword : null
|
||||
xhr.open(this.method, this.url + this.path + this.queryString, true, user, pswd)
|
||||
if (this.auth === 'Bearer Token') {
|
||||
xhr.setRequestHeader('Authorization', 'Bearer ' + this.bearerToken);
|
||||
}
|
||||
if (this.method === 'POST' || this.method === 'PUT') {
|
||||
const requestBody = this.rawRequestBody
|
||||
xhr.setRequestHeader('Content-Length', requestBody.length)
|
||||
xhr.setRequestHeader('Content-Type', `${this.contentType}; charset=utf-8`)
|
||||
xhr.send(requestBody)
|
||||
} else {
|
||||
xhr.send()
|
||||
}
|
||||
xhr.onload = e => {
|
||||
this.response.status = xhr.status
|
||||
const headers = this.response.headers = parseHeaders(xhr)
|
||||
if ((headers['content-type'] || '').startsWith('application/json')) {
|
||||
this.response.body = JSON.stringify(JSON.parse(xhr.responseText), null, 2)
|
||||
} else {
|
||||
this.response.body = xhr.responseText
|
||||
}
|
||||
}
|
||||
xhr.onerror = e => {
|
||||
this.response.status = xhr.status
|
||||
this.response.body = xhr.statusText
|
||||
}
|
||||
},
|
||||
addRequestParam() {
|
||||
this.params.push({
|
||||
key: '',
|
||||
value: ''
|
||||
})
|
||||
return false
|
||||
},
|
||||
removeRequestParam(index) {
|
||||
this.params.splice(index, 1)
|
||||
},
|
||||
addRequestBodyParam() {
|
||||
this.bodyParams.push({
|
||||
key: '',
|
||||
value: ''
|
||||
})
|
||||
return false
|
||||
},
|
||||
removeRequestBodyParam(index) {
|
||||
this.bodyParams.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
11
static/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# STATIC
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your static files.
|
||||
Each file inside this directory is mapped to `/`.
|
||||
Thus you'd want to delete this README.md before deploying to production.
|
||||
|
||||
Example: `/static/robots.txt` is mapped as `/robots.txt`.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
static/icons/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
10
store/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# STORE
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your Vuex Store files.
|
||||
Vuex Store option is implemented in the Nuxt.js framework.
|
||||
|
||||
Creating a file in this directory automatically activates the option in the framework.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).
|
||||
148
sw.js
@@ -1,148 +0,0 @@
|
||||
importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');
|
||||
if (workbox) {
|
||||
console.log(`Yay! Workbox is loaded 🎉`);
|
||||
} else {
|
||||
console.log(`Boo! Workbox didn't load 😬`);
|
||||
}
|
||||
workbox.routing.registerRoute(
|
||||
new RegExp('.*\.js'),
|
||||
new workbox.strategies.NetworkFirst()
|
||||
);
|
||||
workbox.routing.registerRoute(
|
||||
// Cache CSS files.
|
||||
/\.css$/,
|
||||
// Use cache but update in the background.
|
||||
new workbox.strategies.StaleWhileRevalidate({
|
||||
// Use a custom cache name.
|
||||
cacheName: 'css-cache',
|
||||
})
|
||||
);
|
||||
workbox.routing.registerRoute(
|
||||
// Cache image files.
|
||||
/\.(?:png|jpg|jpeg|svg|gif)$/,
|
||||
// Use the cache if it's available.
|
||||
new workbox.strategies.CacheFirst({
|
||||
// Use a custom cache name.
|
||||
cacheName: 'image-cache',
|
||||
plugins: [
|
||||
new workbox.expiration.Plugin({
|
||||
// Cache only 20 images.
|
||||
maxEntries: 20,
|
||||
// Cache for a maximum of a week.
|
||||
maxAgeSeconds: 7 * 24 * 60 * 60,
|
||||
})
|
||||
],
|
||||
})
|
||||
);
|
||||
workbox.precaching.precacheAndRoute([
|
||||
'/postwoman/style.css',
|
||||
'/postwoman/script.js',
|
||||
{
|
||||
url: '/postwoman/index.html',
|
||||
revision: '383676'
|
||||
},
|
||||
]);
|
||||
var CACHE_VERSION = 1;
|
||||
var CURRENT_CACHES = {
|
||||
prefetch: 'prefetch-cache-v' + CACHE_VERSION
|
||||
};
|
||||
self.addEventListener('install', function (event) {
|
||||
var now = Date.now();
|
||||
var urlsToPrefetch = [
|
||||
'/postwoman/index.html',
|
||||
];
|
||||
// All of these logging statements should be visible via the "Inspect" interface
|
||||
// for the relevant SW accessed via chrome://serviceworker-internals
|
||||
console.log('Handling install event. Resources to prefetch:', urlsToPrefetch);
|
||||
event.waitUntil(
|
||||
caches.open(CURRENT_CACHES.prefetch).then(function (cache) {
|
||||
var cachePromises = urlsToPrefetch.map(function (urlToPrefetch) {
|
||||
// This constructs a new URL object using the service worker's script location as the base
|
||||
// for relative URLs.
|
||||
var url = new URL(urlToPrefetch, location.href);
|
||||
// Append a cache-bust=TIMESTAMP URL parameter to each URL's query string.
|
||||
// This is particularly important when precaching resources that are later used in the
|
||||
// fetch handler as responses directly, without consulting the network (i.e. cache-first).
|
||||
// If we were to get back a response from the HTTP browser cache for this precaching request
|
||||
// then that stale response would be used indefinitely, or at least until the next time
|
||||
// the service worker script changes triggering the install flow.
|
||||
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now;
|
||||
// It's very important to use {mode: 'no-cors'} if there is any chance that
|
||||
// the resources being fetched are served off of a server that doesn't support
|
||||
// CORS (http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
|
||||
// In this example, www.chromium.org doesn't support CORS, and the fetch()
|
||||
// would fail if the default mode of 'cors' was used for the fetch() request.
|
||||
// The drawback of hardcoding {mode: 'no-cors'} is that the response from all
|
||||
// cross-origin hosts will always be opaque
|
||||
// (https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cross-origin-resources)
|
||||
// and it is not possible to determine whether an opaque response represents a success or failure
|
||||
// (https://github.com/whatwg/fetch/issues/14).
|
||||
var request = new Request(url, {
|
||||
mode: 'no-cors'
|
||||
});
|
||||
return fetch(request).then(function (response) {
|
||||
if (response.status >= 400) {
|
||||
throw new Error('request for ' + urlToPrefetch +
|
||||
' failed with status ' + response.statusText);
|
||||
}
|
||||
// Use the original URL without the cache-busting parameter as the key for cache.put().
|
||||
return cache.put(urlToPrefetch, response);
|
||||
}).catch(function (error) {
|
||||
console.error('Not caching ' + urlToPrefetch + ' due to ' + error);
|
||||
});
|
||||
});
|
||||
return Promise.all(cachePromises).then(function () {
|
||||
console.log('Pre-fetching complete.');
|
||||
});
|
||||
}).catch(function (error) {
|
||||
console.error('Pre-fetching failed:', error);
|
||||
})
|
||||
);
|
||||
});
|
||||
self.addEventListener('activate', function (event) {
|
||||
// Delete all caches that aren't named in CURRENT_CACHES.
|
||||
// While there is only one cache in this example, the same logic will handle the case where
|
||||
// there are multiple versioned caches.
|
||||
var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function (key) {
|
||||
return CURRENT_CACHES[key];
|
||||
});
|
||||
event.waitUntil(
|
||||
caches.keys().then(function (cacheNames) {
|
||||
return Promise.all(
|
||||
cacheNames.map(function (cacheName) {
|
||||
if (expectedCacheNames.indexOf(cacheName) === -1) {
|
||||
// If this cache name isn't present in the array of "expected" cache names, then delete it.
|
||||
console.log('Deleting out of date cache:', cacheName);
|
||||
return caches.delete(cacheName);
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
self.addEventListener('fetch', function (event) {
|
||||
console.log('Handling fetch event for', event.request.url);
|
||||
event.respondWith(
|
||||
// caches.match() will look for a cache entry in all of the caches available to the service worker.
|
||||
// It's an alternative to first opening a specific named cache and then matching on that.
|
||||
caches.match(event.request).then(function (response) {
|
||||
if (response) {
|
||||
console.log('Found response in cache:', response);
|
||||
return response;
|
||||
}
|
||||
console.log('No response found in cache. About to fetch from network...');
|
||||
// event.request will always have the proper mode set ('cors, 'no-cors', etc.) so we don't
|
||||
// have to hardcode 'no-cors' like we do when fetch()ing in the install handler.
|
||||
return fetch(event.request).then(function (response) {
|
||||
console.log('Response from network is:', response);
|
||||
return response;
|
||||
}).catch(function (error) {
|
||||
// This catch() will handle exceptions thrown from the fetch() operation.
|
||||
// Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
|
||||
// It will return a normal response object that has the appropriate error code set.
|
||||
console.error('Fetching failed:', error);
|
||||
throw error;
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||