mirror of
https://github.com/taigrr/homer
synced 2025-01-18 04:53:12 -08:00
Add offline cache + improve layout
This commit is contained in:
parent
e41196e76e
commit
9baec9aec2
17
app.css
17
app.css
@ -4,7 +4,7 @@ html {
|
|||||||
body {
|
body {
|
||||||
font-family: 'Raleway', sans-serif;
|
font-family: 'Raleway', sans-serif;
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
height: 100%; }
|
min-height: 100%; }
|
||||||
body h1, body h2, body h3, body h4, body h5, body h6 {
|
body h1, body h2, body h3, body h4, body h5, body h6 {
|
||||||
font-family: 'Lato', sans-serif; }
|
font-family: 'Lato', sans-serif; }
|
||||||
body h1 {
|
body h1 {
|
||||||
@ -66,7 +66,7 @@ body {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis; }
|
text-overflow: ellipsis; }
|
||||||
body #main-section .column {
|
body #main-section .container {
|
||||||
padding: 1.2rem .75rem; }
|
padding: 1.2rem .75rem; }
|
||||||
body #main-section .message {
|
body #main-section .message {
|
||||||
margin-top: 45px;
|
margin-top: 45px;
|
||||||
@ -82,7 +82,7 @@ body {
|
|||||||
background-color: #4285f4;
|
background-color: #4285f4;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1rem;
|
top: 1rem;
|
||||||
right: -0.3rem;
|
right: -0.2rem;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: all 0.2s ease-out;
|
transition: all 0.2s ease-out;
|
||||||
@ -137,3 +137,14 @@ body {
|
|||||||
height: 20px; }
|
height: 20px; }
|
||||||
body .search-bar:focus-within .search-label::before {
|
body .search-bar:focus-within .search-label::before {
|
||||||
color: #4a4a4a; }
|
color: #4a4a4a; }
|
||||||
|
body .offline-message {
|
||||||
|
text-align: center;
|
||||||
|
margin: 35px 0; }
|
||||||
|
body .offline-message i {
|
||||||
|
font-size: 2rem; }
|
||||||
|
body .offline-message i.fa-redo-alt {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #3273dc; }
|
||||||
|
59
app.js
59
app.js
@ -1,42 +1,53 @@
|
|||||||
var app = new Vue({
|
const app = new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
config: null,
|
config: null,
|
||||||
filter: ''
|
offline: false,
|
||||||
|
filter: '',
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
created: function () {
|
||||||
let that = this;
|
let that = this;
|
||||||
|
|
||||||
return getConfig().then(function (config) {
|
this.checkOffline();
|
||||||
const size = 3;
|
that.getConfig().then(function (config) {
|
||||||
config.services.forEach(function (service) {
|
|
||||||
service.rows = [];
|
|
||||||
items = service.items;
|
|
||||||
while (items.length) {
|
|
||||||
service.rows.push(items.splice(0, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service.rows.length) {
|
|
||||||
let last = service.rows.length - 1;
|
|
||||||
service.rows[last] = service.rows[last].concat(Array(size - service.rows[last].length));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
that.config = config;
|
that.config = config;
|
||||||
}).catch(function () {
|
}).catch(function () {
|
||||||
console.error('Fail to get config');
|
that.offline = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', function () {
|
||||||
|
if (document.visibilityState == "visible") {
|
||||||
|
that.checkOffline();
|
||||||
}
|
}
|
||||||
|
}, false);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
checkOffline: function () {
|
||||||
|
let that = this;
|
||||||
|
return fetch(window.location.href + "?alive", {
|
||||||
|
method: 'HEAD',
|
||||||
|
cache: 'no-store'
|
||||||
|
}).then(function () {
|
||||||
|
that.offline = false;
|
||||||
|
}).catch(function () {
|
||||||
|
that.offline = true;
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
getConfig: function (event) {
|
||||||
function getConfig() {
|
|
||||||
return fetch('config.yml').then(function (response) {
|
return fetch('config.yml').then(function (response) {
|
||||||
if (response.status !== 200) {
|
if (response.status != 200) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.text().then(function (body) {
|
return response.text().then(function (body) {
|
||||||
return jsyaml.load(body);
|
return jsyaml.load(body);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
navigator.serviceWorker.register('/worker.js');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
23
app.scss
23
app.scss
@ -6,7 +6,7 @@ html { height: 100%; }
|
|||||||
body {
|
body {
|
||||||
font-family: 'Raleway', sans-serif;
|
font-family: 'Raleway', sans-serif;
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
font-family: 'Lato', sans-serif;
|
font-family: 'Lato', sans-serif;
|
||||||
@ -109,7 +109,7 @@ body {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column {
|
.container {
|
||||||
padding: 1.2rem .75rem;
|
padding: 1.2rem .75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ body {
|
|||||||
background-color: $secondary-color;
|
background-color: $secondary-color;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1rem;
|
top: 1rem;
|
||||||
right: -0.3rem;
|
right: -0.2rem;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: all 0.2s ease-out;
|
transition: all 0.2s ease-out;
|
||||||
@ -213,4 +213,21 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.offline-message {
|
||||||
|
text-align: center;
|
||||||
|
margin: 35px 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.fa-redo-alt {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #3273dc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
title: "Simple homepage"
|
title: "Simple homepage"
|
||||||
subtitle: "Homer"
|
subtitle: "Homer"
|
||||||
logo: "assets/homer.png"
|
logo: "assets/logo.png"
|
||||||
icon: "fas fa-skull-crossbones"
|
icon: "fas fa-skull-crossbones"
|
||||||
|
|
||||||
# Optional message
|
# Optional message
|
||||||
|
43
index.html
43
index.html
@ -7,8 +7,8 @@
|
|||||||
<meta name="robots" content="noindex">
|
<meta name="robots" content="noindex">
|
||||||
<link rel="icon" type="image/png" href="assets/favicon.png">
|
<link rel="icon" type="image/png" href="assets/favicon.png">
|
||||||
<title>Homer</title>
|
<title>Homer</title>
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU"
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css"
|
||||||
crossorigin="anonymous">
|
integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Lato|Raleway" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Lato|Raleway" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="app.css">
|
<link rel="stylesheet" href="app.css">
|
||||||
@ -18,18 +18,18 @@
|
|||||||
<div id="app" v-if="config">
|
<div id="app" v-if="config">
|
||||||
<div id="bighead">
|
<div id="bighead">
|
||||||
<section class="first-line">
|
<section class="first-line">
|
||||||
<div class="container">
|
<div v-cloak class="container">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img v-if="config.logo" :src="config.logo" />
|
<img v-if="config.logo" :src="config.logo" />
|
||||||
<i v-if="config.icon" :class="config.icon"></i>
|
<i v-if="config.icon" :class="config.icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="dashboard-title">
|
<div class="dashboard-title">
|
||||||
<span v-cloak class="headline">{{ config.subtitle }}</span>
|
<span class="headline">{{ config.subtitle }}</span>
|
||||||
<h1 v-cloak>{{ config.title }}</h1>
|
<h1>{{ config.title }}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div v-if="config.links" class="container-fluid">
|
<div v-cloak v-if="config.links" class="container-fluid">
|
||||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-menu">
|
<div class="navbar-menu">
|
||||||
@ -52,9 +52,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section id="main-section" class="section">
|
<section id="main-section" class="section">
|
||||||
<div class="container">
|
<div v-cloak class="container">
|
||||||
|
<div v-if="offline" class="offline-message">
|
||||||
|
<i class="far fa-dizzy"></i>
|
||||||
|
<h1>You're offline bro. <i class="fas fa-redo-alt" v-on:click="checkOffline()"></i></h1>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
<!-- Optional messages -->
|
<!-- Optional messages -->
|
||||||
<article v-cloak v-if="config && config.message" class="message" :class="config.message.style">
|
<article v-if="config && config.message" class="message" :class="config.message.style">
|
||||||
<div v-if="config.message.title" class="message-header">
|
<div v-if="config.message.title" class="message-header">
|
||||||
<p>{{ config.message.title }}</p>
|
<p>{{ config.message.title }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -63,16 +68,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<h2 v-cloak v-if="filter"><i class="fas fa-search"></i> Search</h2>
|
<h2 v-if="filter"><i class="fas fa-search"></i> Search</h2>
|
||||||
|
|
||||||
<div v-for="(group, index) in config.services">
|
<div v-for="(group, index) in config.services">
|
||||||
<h2 v-if="!filter && group.name"><i v-if="group.icon" :class="group.icon"></i><span v-else>#</span>
|
<h2 v-if="!filter && group.name"><i v-if="group.icon" :class="group.icon"></i><span v-else>#</span>
|
||||||
{{ group.name }}</h2>
|
{{ group.name }}</h2>
|
||||||
<div v-for="items in group.rows">
|
<div class="columns is-multiline">
|
||||||
<div class="columns">
|
<div v-for="item in group.items"
|
||||||
<div v-for="item in items" v-if="!filter || (item && (item.name.toLowerCase().includes(filter.toLowerCase()) || (item.tag && item.tag.toLowerCase().includes(filter.toLowerCase()))))"
|
v-if="!filter || (item && (item.name.toLowerCase().includes(filter.toLowerCase()) || (item.tag && item.tag.toLowerCase().includes(filter.toLowerCase()))))"
|
||||||
class="column">
|
class="column is-one-third-widescreen">
|
||||||
<div>
|
|
||||||
<div v-if='item' class="card">
|
<div v-if='item' class="card">
|
||||||
<a :href="item.url">
|
<a :href="item.url">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
@ -92,7 +96,7 @@
|
|||||||
<p class="subtitle is-6">{{ item.subtitle }}</p>
|
<p class="subtitle is-6">{{ item.subtitle }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<strong v-if="item.tag" class="tag">#{{ item.tag }}</strong>
|
<strong class="tag" v-if="item.tag">#{{ item.tag }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -101,20 +105,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="content has-text-centered">
|
<div class="content has-text-centered">
|
||||||
<p>Created with <span class="has-text-danger">❤️</span> with <a href="https://bulma.io/">bulma</a>, <a href="https://vuejs.org/">vuejs</a>
|
<p>Created with <span class="has-text-danger">❤️</span> with <a href="https://bulma.io/">bulma</a>, <a
|
||||||
& <a href="#">font awesome</a> // Fork me on <a href="https://github.com/bastienwirtz/homer"><i class="fab fa-github-alt"></i></a></p>
|
href="https://vuejs.org/">vuejs</a>
|
||||||
|
& <a href="#">font awesome</a> // Fork me on <a href="https://github.com/bastienwirtz/homer"><i
|
||||||
|
class="fab fa-github-alt"></i></a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="https://unpkg.com/vue"></script>
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.2/dist/vue.min.js"></script>
|
||||||
<script src="vendors/js-yaml.min.js"></script>
|
<script src="vendors/js-yaml.min.js"></script>
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
32
worker.js
Normal file
32
worker.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
self.addEventListener('install', event => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches
|
||||||
|
.open('homer')
|
||||||
|
.then(cache =>
|
||||||
|
cache.addAll([
|
||||||
|
'/',
|
||||||
|
'/index.html',
|
||||||
|
'/config.yml',
|
||||||
|
'/app.css',
|
||||||
|
'/app.js',
|
||||||
|
'/vendors/js-yaml.min.js',
|
||||||
|
'/assets/logo.png',
|
||||||
|
'https://use.fontawesome.com/releases/v5.5.0/css/all.css',
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
|
||||||
|
'https://fonts.googleapis.com/css?family=Lato|Raleway',
|
||||||
|
'https://cdn.jsdelivr.net/npm/vue@2.6.2/dist/vue.min.js',
|
||||||
|
])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
self.addEventListener('fetch', event => {
|
||||||
|
event.respondWith(
|
||||||
|
caches.match(event.request).then(response => {
|
||||||
|
if (response) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
return fetch(event.request);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user