Compare commits
5 Commits
bc8649fac3
...
ef79ee4997
Author | SHA1 | Date | |
---|---|---|---|
ef79ee4997 | |||
63777e0db2 | |||
5dc17162d2 | |||
4763ea0ae4 | |||
9db8ef59c0 |
@ -7,6 +7,9 @@
|
|||||||
<script src="/static/feed-item.js" defer></script>
|
<script src="/static/feed-item.js" defer></script>
|
||||||
|
|
||||||
<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
|
<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/dayjs@1.9.5/plugin/relativeTime.js"></script>
|
||||||
|
<script>dayjs.extend(window.dayjs_plugin_relativeTime)</script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/hack@0.8.1/dist/hack.css">
|
<link rel="stylesheet" href="https://unpkg.com/hack@0.8.1/dist/hack.css">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/hack@0.8.1/dist/dark.css">
|
<link rel="stylesheet" href="https://unpkg.com/hack@0.8.1/dist/dark.css">
|
||||||
@ -39,8 +42,8 @@
|
|||||||
All ({{unread}})
|
All ({{unread}})
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-for="feed in feeds" :class="{strong: unreadCount(feed), 'alert': true, 'alert-success': selectedFeed == feed.FeedURL }" :data-feed="feed.FeedURL" v-on:click="loadFeed(feed.ID)">
|
<div v-for="feed in feeds" :class="{strong: unreadCounts[feed.ID], 'alert': true, 'alert-success': selectedFeed == feed.FeedURL }" :data-feed="feed.FeedURL" v-on:click="loadFeed(feed.ID)">
|
||||||
{{feed.Title}} ({{unreadCount(feed)}})
|
{{feed.Title}} ({{unreadCounts[feed.ID]}})
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
@ -78,8 +81,8 @@
|
|||||||
<div v-for="item in shownItems" :id="item.ID">
|
<div v-for="item in shownItems" :id="item.ID">
|
||||||
<div :class="{'alert': true, 'alert-info': item.Read == false, 'item-heading': true}" :data-feed="item.FeedHomepageURL" v-on:click="loadItem(item)">
|
<div :class="{'alert': true, 'alert-info': item.Read == false, 'item-heading': true}" :data-feed="item.FeedHomepageURL" v-on:click="loadItem(item)">
|
||||||
<span class="feed-title">{{item.FeedTitle}}</span>
|
<span class="feed-title">{{item.FeedTitle}}</span>
|
||||||
<span class="date" :title="item.Created">{{item.Created}}</span>
|
<span class="date" :title="item.Created">{{ dayjs(item.Created).fromNow() }}</span>
|
||||||
<h3 class="item-title"><a :href="item.URL">{{item.Title}}</a></h3>
|
<h3 class="item-title">{{item.Title}} <a :href="item.URL">↗</a></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card item-content" :data-id="item.ID" v-if="item.ID == selectedItem">
|
<div class="card item-content" :data-id="item.ID" v-if="item.ID == selectedItem">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
@ -121,6 +124,13 @@
|
|||||||
},
|
},
|
||||||
unread() {
|
unread() {
|
||||||
return this.items.filter(item => !item.Read).length;
|
return this.items.filter(item => !item.Read).length;
|
||||||
|
},
|
||||||
|
unreadCounts() {
|
||||||
|
return this.items.filter(item => !item.Read).reduce((acc, item) => {
|
||||||
|
if (!acc[item.FeedID]) acc[item.FeedID] = 0;
|
||||||
|
acc[item.FeedID]++;
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -133,9 +143,6 @@
|
|||||||
document.body.classList.toggle('dark');
|
document.body.classList.toggle('dark');
|
||||||
document.body.classList.toggle('dark-grey');
|
document.body.classList.toggle('dark-grey');
|
||||||
},
|
},
|
||||||
unreadCount(feed) {
|
|
||||||
return this.items.filter(item => item.FeedID == feed.ID).length;
|
|
||||||
},
|
|
||||||
loadFeed(feed) {
|
loadFeed(feed) {
|
||||||
this.selectedItem = undefined;
|
this.selectedItem = undefined;
|
||||||
this.selectedFeed = feed;
|
this.selectedFeed = feed;
|
||||||
@ -182,21 +189,23 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
markAllRead() {
|
markAllRead() {
|
||||||
this.setBusy(true);
|
|
||||||
let ids = this.shownItems.filter(item => !item.Read).map(item => item.ID);
|
let ids = this.shownItems.filter(item => !item.Read).map(item => item.ID);
|
||||||
fetch(
|
if (confirm(`Are you sure you want to mark ${ids.length} items as read?`)) {
|
||||||
`/api/read`,
|
this.setBusy(true);
|
||||||
{method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(ids)}
|
fetch(
|
||||||
)
|
`/api/read`,
|
||||||
.then(res => res.json())
|
{method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(ids)}
|
||||||
.then(items => this.items = items)
|
)
|
||||||
.then(() => {
|
.then(res => res.json())
|
||||||
this.setBusy(false);
|
.then(items => this.items = items)
|
||||||
})
|
.then(() => {
|
||||||
.catch(err => {
|
this.setBusy(false);
|
||||||
console.error(err);
|
})
|
||||||
this.setBusy(false);
|
.catch(err => {
|
||||||
});
|
console.error(err);
|
||||||
|
this.setBusy(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
addSite(url) {
|
addSite(url) {
|
||||||
this.setBusy(true);
|
this.setBusy(true);
|
||||||
|
@ -56,6 +56,10 @@ class FeedItem extends HTMLElement {
|
|||||||
.then(item => {
|
.then(item => {
|
||||||
template.innerHTML += item.Content || item.Description;
|
template.innerHTML += item.Content || item.Description;
|
||||||
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
||||||
|
[...this.shadowRoot.querySelectorAll('a[href^=http]')].forEach(a => {
|
||||||
|
a.setAttribute("target", "_blank");
|
||||||
|
a.setAttribute("rel", "noopener");
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user