From 0a9ea15b5899c275aacb7cf7113e184777ba4abf Mon Sep 17 00:00:00 2001 From: Jonathan Cremin <jonathan@crem.in> Date: Sun, 23 Oct 2016 23:04:32 +0100 Subject: [PATCH] Add error handling to the frontend --- app.js | 3 +++ lib/error-handler.js | 39 ++++++++++++++++++++++++++++++ public/src/components/search.vue | 41 ++++++++++++++++++++++---------- public/src/style/style.css | 6 ++--- public/src/views/index.vue | 2 +- routes/index.js | 4 ++-- 6 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 lib/error-handler.js diff --git a/app.js b/app.js index 461218e..ca4e7aa 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ import recent from './routes/recent'; import search from './routes/search'; import share from './routes/share'; import itunesProxy from './routes/itunes-proxy'; +import errorHandler from './lib/error-handler'; const debug = debuglog('match.audio'); @@ -22,6 +23,8 @@ process.env.VUE_ENV = 'server'; const app = koa(); +app.use(errorHandler()); + app.use(bodyparser()); app.use(cors()); app.use(compress({ flush: zlib.Z_SYNC_FLUSH })); diff --git a/lib/error-handler.js b/lib/error-handler.js new file mode 100644 index 0000000..d6c8020 --- /dev/null +++ b/lib/error-handler.js @@ -0,0 +1,39 @@ +import debuglog from 'debug'; + +const debug = debuglog('match.audio'); + +export default function () { + return function* error(next) { + this.set('Server', 'Nintendo 64'); + try { + yield next; + } catch (err) { + if (err.status === 404) { + this.body = '404 Page Not Found'; + } else if (err.status >= 400 && err.status < 500) { + this.status = err.status; + this.body = err.error; + } else { + debug('Error: %o', err); + throw err; + } + } + + if (this.status !== 404) return; + + switch (this.accepts('html', 'json')) { + case 'html': + this.type = 'html'; + this.body = '404 Page Not Found'; + break; + case 'json': + this.body = { + message: 'Page Not Found', + }; + break; + default: + this.type = 'text'; + this.body = 'Page Not Found'; + } + }; +} diff --git a/public/src/components/search.vue b/public/src/components/search.vue index 82ced27..3bcded1 100644 --- a/public/src/components/search.vue +++ b/public/src/components/search.vue @@ -1,12 +1,18 @@ <template> - <form role="form" method="post" action="/search" v-on:submit="submit"> - <p class="control has-addons"> - <input class="input is-expanded is-large" type="text" placeholder="Paste your link here" v-model="url"> - <button type="submit" class="button is-primary is-large"> - Share Music - </button> - </p> - </form> + <div class="search"> + <form role="form" method="post" action="/search" v-on:submit="submit"> + <p class="control has-addons"> + <input class="input is-expanded is-large" type="text" placeholder="Paste your link here" v-model="url"> + <button type="submit" class="button is-primary is-large" v-bind:class="{ 'is-loading': submitting }"> + Share Music + </button> + </p> + </form> + <div class="notification is-warning" v-if="error"> + <button class="delete" v-on:click="error = false"></button> + {{ error }} + </div> + </div> </template> <script> @@ -16,15 +22,23 @@ export default { name: 'search-view', data() { return { + error: null, + submitting: false, url: '', }; }, methods: { submit (event) { + this.submitting = true; event.preventDefault(); musicSearch(this.url).end((req, res) => { - const item = res.body; - this.$router.push(`/${item.service}/${item.albumName ? 'track' : 'album'}/${item.externalId}`); + this.submitting = false; + if (res.status == 200) { + const item = res.body; + this.$router.push(`/${item.service}/${item.albumName ? 'track' : 'album'}/${item.externalId}`); + } else { + this.error = res.body.message; + } }); }, }, @@ -47,8 +61,11 @@ export default { .input:focus { border-color: #FE4365; } +.search { + margin-bottom: 25vh; +} form { - margin-bottom: 50px; - margin-top: 200px; + margin-top: 25vh; + margin-bottom: 20px; } </style> diff --git a/public/src/style/style.css b/public/src/style/style.css index a31f3ed..d7176a7 100644 --- a/public/src/style/style.css +++ b/public/src/style/style.css @@ -39,7 +39,7 @@ h1 .lighter { margin-bottom: 30px; } .home { - width: 600px; + max-width: 600px; margin-top: 40px; } p { @@ -76,8 +76,8 @@ p { border-color: #FE4365; } form { - margin-bottom: 50px; - margin-top: 200px; + margin-top: 25vh; + margin-bottom: 20px; } /* share.vue */ diff --git a/public/src/views/index.vue b/public/src/views/index.vue index a0172fe..a7bda41 100644 --- a/public/src/views/index.vue +++ b/public/src/views/index.vue @@ -103,7 +103,7 @@ export default { margin-bottom: 30px; } .home { - width: 600px; + max-width: 600px; margin-top: 40px; } p { diff --git a/routes/index.js b/routes/index.js index 4e68417..fc06b49 100644 --- a/routes/index.js +++ b/routes/index.js @@ -33,10 +33,10 @@ export default function* () { const html = yield render(url, initialState); const head = { - title: `Share Music`, + title: 'Share Music', shareUrl: `${this.request.origin}${url}`, image: `${this.request.origin}/assets/images/logo-512.png`, - } + }; yield this.render('index', { initialState,