Skip to content

Commit

Permalink
feat: add an information list for feeds that displays data such as la…
Browse files Browse the repository at this point in the history
…st or next update dates

Signed-off-by: Wolfgang <[email protected]>
  • Loading branch information
wofferl committed Jan 1, 2025
1 parent cc137f4 commit 97a46af
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ You can also check [on GitHub](https://github.com/nextcloud/news/releases), the
# Unreleased
## [25.x.x]
### Changed
- add an information list for feeds that displays data such as last or next update dates

### Fixed
- OPML import use text field for title if title field is missing (#3016)
Expand Down
10 changes: 10 additions & 0 deletions src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@
{{ t('news', 'Keyboard shortcuts') }}
</NcButton>
<HelpModal v-if="showHelp" @close="showHelp=false" />
<NcButton @click="showFeedInfoTable = true">
{{ t('news', 'Article feed information') }}
</NcButton>
<FeedInfoTable v-if="showFeedInfoTable" @close="showFeedInfoTable = false" />
<div>
<div class="select-container">
<label>
Expand Down Expand Up @@ -289,6 +293,7 @@ import MoveFeed from './MoveFeed.vue'
import SidebarFeedLinkActions from './SidebarFeedLinkActions.vue'
import HelpModal from './modals/HelpModal.vue'
import FeedInfoTable from './modals/FeedInfoTable.vue'
import { Folder } from '../types/Folder'
import { Feed } from '../types/Feed'
Expand All @@ -315,6 +320,7 @@ export default Vue.extend({
DownloadIcon,
SidebarFeedLinkActions,
HelpModal,
FeedInfoTable,
},
data: () => {
return {
Expand All @@ -323,6 +329,7 @@ export default Vue.extend({
feedToMove: undefined,
ROUTES,
showHelp: false,
showFeedInfoTable: false,
polling: null,
uploadStatus: null,
selectedFile: null,
Expand Down Expand Up @@ -475,6 +482,9 @@ export default Vue.extend({
subscribe('news:global:toggle-help-dialog', () => {
this.showHelp = !this.showHelp
})
subscribe('news:global:toggle-feed-info', () => {
this.showFeedInfoTable = !this.showFeedInfoTable
})
},
beforeDestroy() {
clearInterval(this.polling)
Expand Down
202 changes: 202 additions & 0 deletions src/components/modals/FeedInfoTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
<!--
- SPDX-FileCopyrightText: 2025 Nextcloud News
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<NcModal size="large"
@close="$emit('close')">
<div class="table-modal">
<h2>{{ t('news', 'Article feed information') }}</h2>
<table>
<thead>
<tr>
<th @click="sortBy('id')">
<span class="column-title">
ID
<SortAscIcon v-if="sortKey === 'id' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'id' && sortOrder !== 1" />
</span>
</th>
<th @click="sortBy('title')">
<span class="column-title">
{{ t('news', 'Title') }}
<SortAscIcon v-if="sortKey === 'title' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'title' && sortOrder !== 1" />
</span>
</th>
<th @click="sortBy('lastModified')">
<span class="column-title">
{{ t('news', 'Last update') }}
<SortAscIcon v-if="sortKey === 'lastModified' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'lastModified' && sortOrder !== 1" />
</span>
</th>
<th @click="sortBy('nextUpdateTime')">
<span class="column-title">
{{ t('news', 'Next update') }}
<SortAscIcon v-if="sortKey === 'nextUpdateTime' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'nextUpdateTime' && sortOrder !== 1" />
</span>
</th>
<th :title="t('news', 'Articles per update')"
@click="sortBy('articlesPerUpdate')">
<span class="column-title">
APU
<SortAscIcon v-if="sortKey === 'articlesPerUpdate' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'articlesPerUpdate' && sortOrder !== 1" />
</span>
</th>
<th :title="t('news', 'Error Count') "
@click="sortBy('updateErrorCount')">
<span class="column-title">
EC
<SortAscIcon v-if="sortKey === 'updateErrorCount' && sortOrder === 1" />
<SortDescIcon v-if="sortKey === 'updateErrorCount' && sortOrder !== 1" />
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="feed in sortedFeeds" :key="feed.id">
<td>{{ feed.id }}</td>
<td>{{ feed.title }}</td>
<td>{{ formatDate(feed.lastModified/1000) }}</td>
<td>{{ formatDate(feed.nextUpdateTime*1000) }}</td>
<td>{{ feed.articlesPerUpdate }}</td>
<td :title="feed.lastUpdateError">
{{ feed.updateErrorCount }}
</td>
</tr>
</tbody>
</table>
</div>
</NcModal>
</template>

<script>
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import SortAscIcon from 'vue-material-design-icons/SortAscending.vue'
import SortDescIcon from 'vue-material-design-icons/SortDescending.vue'
import { mapState } from 'vuex'

export default {
name: 'FeedInfoTable',
components: {
NcModal,
SortAscIcon,
SortDescIcon,
},
data() {
return {
sortKey: 'title',
sortOrder: 1,
}
},
computed: {
...mapState({
feeds: state => state.feeds.feeds,
}),
sortedFeeds() {
const sorted = this.feeds
if (this.sortKey) {
sorted.sort((a, b) => {
const valueA = a[this.sortKey]
const valueB = b[this.sortKey]
if (typeof valueA === 'string') {
return valueA.localeCompare(valueB) * this.sortOrder
} else {
return (valueA - valueB) * this.sortOrder
}
})
}
return sorted
},
},
methods: {
formatDate(timestamp) {
return new Date(timestamp).toLocaleDateString(undefined, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
},
sortBy(key) {
if (this.sortKey === key) {
this.sortOrder *= -1
} else {
this.sortKey = key
this.sortOrder = 1
}
},
},
}
</script>

<style lang="scss" scoped>
.table-modal {
width: max-content;
padding: 30px 40px 20px;

h2 {
font-weight: bold;
}
}

table {
margin-top: 24px;
border-collapse: collapse;

tbody tr {
&:hover, &:focus, &:active {
background-color: transparent !important;
}
}

thead tr {
border: none;
}

th {
cursor: pointer;
font-weight: bold;
padding: .75rem 1rem .75rem 0;
border-bottom: 2px solid var(--color-background-darker);
&:hover {
background-color: var(--color-background-hover);
}
}

td {
padding: .75rem 1rem .75rem 0;
border-top: 1px solid var(--color-background-dark);
border-bottom: unset;

&.noborder {
border-top: unset;
}

&.ellipsis_top {
padding-bottom: 0;
}

&.ellipsis {
padding-top: 0;
padding-bottom: 0;
}

&.ellipsis_bottom {
padding-top: 0;
}
}

.column-title {
display: flex;
align-items: center;
gap: 4px;
}

}
</style>

0 comments on commit 97a46af

Please sign in to comment.