Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Vue Rewrite] Routes: Folder and All Articles Components and Routes #2346

Merged
merged 3 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ export default Vue.extend({
async created() {
await this.$store.dispatch(ACTIONS.FETCH_FOLDERS)
await this.$store.dispatch(ACTIONS.FETCH_FEEDS)
await this.$store.dispatch(ACTIONS.FETCH_STARRED)
},
})
</script>

<style>
.material-design-icon {
color: var(--color-text-lighter)
}
</style>
50 changes: 40 additions & 10 deletions src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,43 @@
<NcAppNavigationNew :text="t('news', 'Subscribe')"
button-id="new-feed-button"
button-class="icon-add"
@click="showShowAddFeed()" />
:icon="true"
@click="showShowAddFeed()">
<template #icon>
<PlusIcon />
</template>
</NcAppNavigationNew>
<template #list>
<NcAppNavigationNewItem :title="t('news', 'New folder')"
icon="icon-add-folder"
@new-item="newFolder" />
:icon="true"
@new-item="newFolder">
<template #icon>
<FolderPlusIcon />
</template>
</NcAppNavigationNewItem>

<NcAppNavigationItem :title="t('news', 'Unread articles')" icon="icon-rss" :to="{ name: ROUTES.UNREAD }">
<template #actions>
<NcActionButton icon="icon-checkmark" @click="alert('TODO: Mark Read')">
t('news','Mark read')
</NcActionButton>
</template>
<template #icon>
<EyeIcon />
</template>
<template #counter>
<NcCounterBubble>{{ items.unreadCount }}</NcCounterBubble>
</template>
</NcAppNavigationItem>
<NcAppNavigationItem :title="t('news', 'All articles')" icon="icon-rss">
<NcAppNavigationItem :title="t('news', 'All articles')" icon="icon-rss" :to="{ name: ROUTES.ALL }">
<template #actions>
<ActionButton icon="icon-checkmark" @click="alert('TODO: Edit')">
t('news','Mark read')
</ActionButton>
</template>
<template #icon>
<RssIcon />
</template>
</NcAppNavigationItem>
<NcAppNavigationItem :title="t('news', 'Starred')" icon="icon-starred" :to="{ name: ROUTES.STARRED }">
<template #counter>
Expand All @@ -36,18 +51,20 @@
<NcAppNavigationItem v-for="topLevelItem in topLevelNav"
:key="topLevelItem.name || topLevelItem.title"
:title="topLevelItem.name || topLevelItem.title"
:icon="isFolder(topLevelItem) ? 'icon-folder': ''"
:to="isFolder(topLevelItem) ? {} : { name: ROUTES.FEED, params: { feedId: topLevelItem.id.toString() } }"
:icon="true"
:to="isFolder(topLevelItem) ? { name: ROUTES.FOLDER, params: { folderId: topLevelItem.id.toString() }} : { name: ROUTES.FEED, params: { feedId: topLevelItem.id.toString() } }"
:allow-collapse="true">
<template #default>
<NcAppNavigationItem v-for="feed in topLevelItem.feeds"
:key="feed.name"
:title="feed.title"
:to="{ name: ROUTES.FEED, props: { feedId: feed.id } }">
:icon="true"
:to="{ name: ROUTES.FEED, params: { feedId: feed.id } }">
<template #icon>
<RssIcon v-if="!feed.faviconLink" />
<span v-if="feed.faviconLink" style="width: 24px; background-size: contain;" :style="{ 'backgroundImage': 'url(' + feed.faviconLink + ')' }" />
<span v-if="feed.faviconLink" style="width: 16px; height: 16px; background-size: contain;" :style="{ 'backgroundImage': 'url(' + feed.faviconLink + ')' }" />
</template>

<template #actions>
<NcActionButton icon="icon-checkmark"
@click="alert('TODO: Mark read')">
Expand Down Expand Up @@ -101,6 +118,7 @@
</NcAppNavigationItem>
</template>
<template #icon>
<FolderIcon v-if="topLevelItem.feedCount !== undefined" style="width:22px" />
<RssIcon v-if="topLevelItem.feedCount === undefined && !topLevelItem.faviconLink" />
<span v-if="topLevelItem.feedCount === undefined && topLevelItem.faviconLink" style="height: 16px; width: 16px; background-size: contain;" :style="{ 'backgroundImage': 'url(' + topLevelItem.faviconLink + ')' }" />
</template>
Expand All @@ -126,11 +144,14 @@
</NcAppNavigationItem>

<NcAppNavigationItem :title="t('news', 'Explore')"
icon="icon-link"
icon="true"
:to="{ name: ROUTES.EXPLORE }">
<template #counter>
<NcCounterBubble>35</NcCounterBubble>
</template>
<template #icon>
<EarthIcon />
</template>
</NcAppNavigationItem>
</template>
</NcAppNavigation>
Expand All @@ -150,6 +171,11 @@ import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'

import RssIcon from 'vue-material-design-icons/Rss.vue'
import FolderIcon from 'vue-material-design-icons/Folder.vue'
import EyeIcon from 'vue-material-design-icons/Eye.vue'
import EarthIcon from 'vue-material-design-icons/Earth.vue'
import FolderPlusIcon from 'vue-material-design-icons/FolderPlus.vue'
import PlusIcon from 'vue-material-design-icons/Plus.vue'

import { ROUTES } from '../routes'
import { ACTIONS, AppState } from '../store'
Expand Down Expand Up @@ -177,11 +203,15 @@ export default Vue.extend({
NcAppNavigationNew,
NcAppNavigationItem,
NcAppNavigationNewItem,
// AppNavigationCounter,
NcCounterBubble,
NcActionButton,
AddFeed,
RssIcon,
FolderIcon,
EyeIcon,
EarthIcon,
FolderPlusIcon,
PlusIcon,
},
data: () => {
return {
Expand Down
18 changes: 17 additions & 1 deletion src/components/feed-display/FeedItemDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export default Vue.extend({

</script>

<style scoped>
<style>
.feed-item-display {
max-height: 100%;
overflow-y: hidden;
Expand All @@ -210,6 +210,22 @@ export default Vue.extend({
color: #3a84e4
}

.article .body ul {
margin: 7px 0;
padding-left: 14px;
list-style-type: disc;
}

.article .body ul li {
cursor: default;
line-height: 21px;
}

.article .body p {
line-height: 1.5;
margin: 7px 0 14px 0;
}

.article .subtitle {
color: var(--color-text-lighter);
font-size: 15px;
Expand Down
16 changes: 14 additions & 2 deletions src/components/feed-display/FeedItemDisplayList.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div>
<div style="justify-content: right; display: flex">
<div class="feed-item-display-list">
<div class="header">
<NcActions class="filter-container" :force-menu="true">
<template #icon>
<FilterIcon />
Expand Down Expand Up @@ -180,6 +180,12 @@ export default Vue.extend({
</script>

<style scoped>
.feed-item-display-list {
height: 100%;
display: flex;
flex-direction: column;
}

.virtual-scroll {
border-top: 1px solid var(--color-border);
width: 100%;
Expand All @@ -193,6 +199,12 @@ export default Vue.extend({
.feed-item-container {
max-width: 50%;
overflow-y: hidden;
height: calc(100vh - 50px - 50px - 10px)
}

.header {
justify-content: right;
display: flex;
}

.filter-container {
Expand Down
63 changes: 63 additions & 0 deletions src/components/routes/All.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<template>
<div class="route-container">
<div class="header">
{{ t('news', 'All Articles') }}
</div>

<FeedItemDisplayList :items="allItems"
:fetch-key="'all'"
@load-more="fetchMore()" />
</div>
</template>

<script lang="ts">
import Vue from 'vue'
import { mapState } from 'vuex'

import FeedItemDisplayList from '../feed-display/FeedItemDisplayList.vue'

import { FeedItem } from '../../types/FeedItem'
import { ACTIONS, MUTATIONS } from '../../store'

export default Vue.extend({
components: {
FeedItemDisplayList,
},
computed: {
...mapState(['items']),

allItems(): FeedItem[] {
return this.$store.getters.allItems
},
},
created() {
this.$store.commit(MUTATIONS.SET_SELECTED_ITEM, { id: undefined })
},
methods: {
async fetchMore() {
if (!this.$store.state.items.fetchingItems.all) {
this.$store.dispatch(ACTIONS.FETCH_ITEMS)
}
},
},
})
</script>

<style scoped>
.route-container {
height: 100%;
}

.header {
padding-left: 50px;
position: absolute;
top: 1em;
font-weight: 700;
}

.counter-bubble {
display: inline-block;
vertical-align: sub;
margin-left: 10px;
}
</style>
94 changes: 94 additions & 0 deletions src/components/routes/Folder.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<div class="route-container">
<div class="header">
{{ folder ? folder.name : '' }}
<NcCounterBubble v-if="folder" class="counter-bubble">
{{ unreadCount }}
</NcCounterBubble>
</div>

<FeedItemDisplayList :items="items" :fetch-key="'folder-'+folderId" @load-more="fetchMore()" />
</div>
</template>

<script lang="ts">
import Vue from 'vue'
import { mapState } from 'vuex'

import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js'

import FeedItemDisplayList from '../feed-display/FeedItemDisplayList.vue'

import { FeedItem } from '../../types/FeedItem'
import { ACTIONS, MUTATIONS } from '../../store'
import { Feed } from '../../types/Feed'
import { Folder } from '../../types/Folder'

export default Vue.extend({
components: {
NcCounterBubble,
FeedItemDisplayList,
},
props: {
folderId: {
type: String,
required: true,
},
},
computed: {
...mapState(['items', 'feeds', 'folders']),
folder(): Folder {
return this.$store.getters.folders.find((folder: Folder) => folder.id === this.id)
},
items(): FeedItem[] {
const feeds: Array<number> = this.$store.getters.feeds.filter((feed: Feed) => feed.folderId === this.id).map((feed: Feed) => feed.id)

return this.$store.state.items.allItems.filter((item: FeedItem) => {
return feeds.includes(item.feedId)
}) || []
},
id(): number {
return Number(this.folderId)
},
unreadCount(): number {
const totalUnread = this.$store.getters.feeds
.filter((feed: Feed) => feed.folderId === this.id)
.reduce((acc: number, feed: Feed) => { acc += feed.unreadCount; return acc }, 0)

return totalUnread
},
},
created() {
this.$store.commit(MUTATIONS.SET_SELECTED_ITEM, { id: undefined })
this.fetchMore()
this.$watch(() => this.$route.params, this.fetchMore)
},
methods: {
async fetchMore() {
if (!this.$store.state.items.fetchingItems['folder-' + this.folderId]) {
this.$store.dispatch(ACTIONS.FETCH_FOLDER_FEED_ITEMS, { folderId: this.id })
}
},
},
})
</script>

<style scoped>
.route-container {
height: 100%;
}

.header {
padding-left: 50px;
position: absolute;
top: 1em;
font-weight: 700;
}

.counter-bubble {
display: inline-block;
vertical-align: sub;
margin-left: 10px;
}

</style>
2 changes: 1 addition & 1 deletion src/components/routes/Starred.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="route-container">
<div class="header">
Starred
{{ t('news', 'Starred') }}
<NcCounterBubble class="counter-bubble">
{{ items.starredCount }}
</NcCounterBubble>
Expand Down
2 changes: 1 addition & 1 deletion src/components/routes/Unread.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="route-container">
<div class="header">
Unread
{{ t('news', 'Unread Articles') }}
<NcCounterBubble class="counter-bubble">
{{ items.unreadCount }}
</NcCounterBubble>
Expand Down
Loading