diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/AddFeed.vue | 148 | ||||
-rw-r--r-- | src/components/Explore.vue | 78 | ||||
-rw-r--r-- | src/components/Sidebar.vue | 164 |
3 files changed, 390 insertions, 0 deletions
diff --git a/src/components/AddFeed.vue b/src/components/AddFeed.vue new file mode 100644 index 000000000..2adacd8ad --- /dev/null +++ b/src/components/AddFeed.vue @@ -0,0 +1,148 @@ +<template> + <Modal @close="$emit('close')"> + <div id="new-feed" news-add-feed="Navigation.feed"> + + <form ng-submit="Navigation.createFeed(Navigation.feed)" + ng-init="Navigation.feed.autoDiscover=true" + name="feedform"> + <fieldset ng-disabled="Navigation.addingFeed" style="padding: 16px"> + <input type="text" + :value="feed" + ng-model="Navigation.feed.url" + ng-class="{'ng-invalid': + !Navigation.addingFeed && + Navigation.feedUrlExists(Navigation.feed.url) + }" + :placeholder="t('news','Web address')" + name="address" + pattern="[^\s]+" + required + autofocus> + + <p class="error" + ng-show="!Navigation.addingFeed && + Navigation.feedUrlExists(Navigation.feed.url)"> + {{ t('news', 'Feed exists already!') }} + </p> + + <!-- select a folder --> + <CheckboxRadioSwitch :checked.sync="createNewFolder" type="switch"> + {{ t('news', 'New folder') }}? + </CheckboxRadioSwitch> + + <Multiselect v-if="!createNewFolder" v-model="folder" :options="folders" track-by="id" label="name"/> + + <!-- add a folder --> + <input type="text" + ng-model="Navigation.feed.newFolder" + ng-class="{'ng-invalid': + !Navigation.addingFeed && + !Navigation.addingFeed && + Navigation.showNewFolder && + Navigation.folderNameExists( + Navigation.feed.newFolder + ) + }" + :placeholder="t('news','Folder name')" + name="folderName" + v-if="createNewFolder" + style="width: 90%" + required> + + + <p class="error" ng-show="!Navigation.addingFeed && + Navigation.folderNameExists(Navigation.feed.newFolder)"> + {{ t('news', 'Folder exists already!') }} + </p> + + <!-- basic auth --> + + <CheckboxRadioSwitch :checked.sync="withBasicAuth" type="switch"> + {{ t('news', 'Credentials') }}? + </CheckboxRadioSwitch> + + <div v-if="withBasicAuth" class="add-feed-basicauth"> + <p class="warning">{{ + t('news', + 'HTTP Basic Auth credentials must be stored unencrypted! Everyone with access to the server or database will be able to access them!') + }}></p> + <input type="text" + ng-model="Navigation.feed.user" + :placeholder="t('news','Username')" + name="user" + autofocus> + + <input type="password" + ng-model="Navigation.feed.password" + :placeholder="t('news','Password')" + name="password" autocomplete="new-password"> + </div> + + <CheckboxRadioSwitch :checked.sync="autoDiscover" type="switch"> + {{ t('news', 'Auto discover Feed') }}? + </CheckboxRadioSwitch> + + <Button :wide="true" type="primary" @click="addFeed()" ng-disabled=" + Navigation.feedUrlExists(Navigation.feed.url) || + ( + Navigation.showNewFolder && + Navigation.folderNameExists(folder.name) + )"> + {{t('news','Subscribe')}} + </Button> + </fieldset> + </form> + </div> + </Modal> +</template> + +<script> +import Modal from '@nextcloud/vue/dist/Components/Modal' +import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/CheckboxRadioSwitch' +import Button from '@nextcloud/vue/dist/Components/Button' +import Multiselect from '@nextcloud/vue/dist/Components/Multiselect' + +export default { + components: { + Modal, + CheckboxRadioSwitch, + Button, + Multiselect + }, + computed: { + folders() { + return this.$store.state.folders + } + }, + methods: { + newFolder() { + this.createNewFolder = true; + }, + abortNewFolder() { + this.createNewFolder = false; + }, + addFeed() { + this.$store.dispatch('addFeed', {feedReq: { url: this.feed, folder: this.folder, autoDiscover: true}}) + } + }, + props: { + feed: '', + folder: {}, + autoDiscover: true, + withBasicAuth: false, + createNewFolder: false + }, + emits: ['close'] +} +</script> + +<style scoped> + + input { + width: 100%; + } + .multiselect { + width: 100%; + } + +</style> diff --git a/src/components/Explore.vue b/src/components/Explore.vue new file mode 100644 index 000000000..5738649cf --- /dev/null +++ b/src/components/Explore.vue @@ -0,0 +1,78 @@ +<template> + <div id="explore"> + <AddFeed v-if="showAddFeed" @close="closeShowAddFeed()" :feed="feed"></AddFeed> + <div class="grid-container"> + <div v-for="entry in explorableSites" class="explore-feed grid-item"> + <h2 class="explore-title" v-if="entry.favicon" + :style="{ backgroundImage: 'url(' + entry.favicon + ')'}"> + <a target="_blank" rel="noreferrer" :href="entry.url">{{ entry.title }}</a> + </h2> + <h2 class="icon-rss explore-title" v-if="!entry.favicon"> + {{ entry.title }} + </h2> + <div class="explore-content"> + <p>{{ entry.description }}</p> + + <div class="explore-logo"> + <img :src="entry.image"> + </div> + </div> + <Button @click="subscribe(entry.feed)"> + {{ t('news', 'Subscribe to') }} {{ entry.title }} + </Button> + </div> + </div> + </div> +</template> + +<script> +import Modal from '@nextcloud/vue/dist/Components/Modal' +import Button from '@nextcloud/vue/dist/Components/Button' +import axios from "@nextcloud/axios"; +import AddFeed from "./AddFeed"; +import {generateUrl} from "@nextcloud/router"; + +export default { + components: { + Modal, + Button, + AddFeed + }, + props: { + explorableSites: { + type: Array, + default: () => [], + required: true, + }, + showAddFeed: false, + feed: '' + }, + methods: { + async sites() { + const settings = await axios.get(generateUrl("/apps/news/settings")); + console.log(settings.data); + console.log(settings.data.settings.exploreUrl); + + const exploreUrl = settings.data.settings.exploreUrl + 'feeds.en.json'; + const explore = await axios.get(exploreUrl); + console.log(explore.data); + + Object.keys(explore.data).forEach(key => + explore.data[key].forEach(value => + this.explorableSites.push(value) + ) + ); + }, + async subscribe(feed) { + this.feed = feed; + this.showAddFeed = true; + }, + closeShowAddFeed() { + this.showAddFeed = false; + } + }, + created() { + this.sites(); + } +} +</script> diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue new file mode 100644 index 000000000..33923f89b --- /dev/null +++ b/src/components/Sidebar.vue @@ -0,0 +1,164 @@ +<template> + <AppNavigation> + <AddFeed v-if="showAddFeed" @close="closeShowAddFeed()"></AddFeed> + <AppNavigationNew + :text="t('news','Subscribe')" + button-id="new-feed-button" + button-class="icon-add" + @click="showShowAddFeed()"/> + + <ul id="locations" class="with-icon"> + + <AppNavigationNewItem :title="t('news','New folder')" + icon="icon-add-folder" + @new-item="newFolder"> + </AppNavigationNewItem> + + <AppNavigationItem :title="t('news','Unread articles')" icon="icon-rss"> + <template #actions> + <ActionButton icon="icon-checkmark" @click="alert('Edit')"> + t('news','Mark read') + </ActionButton> + </template> + <template #counter> + <CounterBubble>5</CounterBubble> + </template> + </AppNavigationItem> + <AppNavigationItem :title="t('news','All articles')" icon="icon-rss"> + <template #actions> + <ActionButton icon="icon-checkmark" @click="alert('Edit')"> + t('news','Mark read') + </ActionButton> + </template> + </AppNavigationItem> + <AppNavigationItem :title="t('news','Starred')" icon="icon-starred"> + <template #counter> + <CounterBubble>35</CounterBubble> + </template> + </AppNavigationItem> + + <AppNavigationItem v-for="folder in folders" :title="folder.name" icon="icon-folder" + :allowCollapse="true"> + <template #default> + <AppNavigationItem v-for="feed in folder.feeds" :title="feed.title" > + <template #icon> + <img :src="feed.faviconLink" v-if="feed.faviconLink" alt="feedIcon"> + <div class="icon-rss" v-if="!feed.faviconLink"></div> + </template> + <template #actions> + <ActionButton icon="icon-checkmark" @click="alert('Mark read')"> + {{ t('news', 'Mark read') }} + </ActionButton> + <ActionButton icon="icon-pinned" @click="alert('Rename')"> + {{ t('news', 'Unpin from top') }} + </ActionButton> + <ActionButton icon="icon-caret-dark" @click="deleteFolder(folder)"> + {{ t('news', 'Newest first') }} + </ActionButton> + <ActionButton icon="icon-caret-dark" @click="deleteFolder(folder)"> + {{ t('news', 'Oldest first') }} + </ActionButton> + <ActionButton icon="icon-caret-dark" @click="deleteFolder(folder)"> + {{ t('news', 'Default order') }} + </ActionButton> + <ActionButton icon="icon-full-text-disabled" @click="deleteFolder(folder)"> + {{ t('news', 'Enable full text') }} + </ActionButton> + <ActionButton icon="icon-full-text-enabled" @click="deleteFolder(folder)"> + {{ t('news', 'Disable full text') }} + </ActionButton> + <ActionButton icon="icon-updatemode-default" @click="deleteFolder(folder)"> + {{ t('news', 'Unread updated') }} + </ActionButton> + <ActionButton icon="icon-updatemode-unread" @click="deleteFolder(folder)"> + {{ t('news', 'Ignore updated') }} + </ActionButton> + <ActionButton icon="icon-icon-rss" @click="deleteFolder(folder)"> + {{ t('news', 'Open feed URL') }} + </ActionButton> + <ActionButton icon="icon-icon-rename" @click="deleteFolder(folder)"> + {{ t('news', 'Rename') }} + </ActionButton> + <ActionButton icon="icon-delete" @click="deleteFolder(folder)"> + {{ t('news', 'Delete') }} + </ActionButton> + </template> + </AppNavigationItem> + </template> + <template #counter v-if="folder.feedCount > 0"> + <CounterBubble>{{ folder.feedCount }}</CounterBubble> + </template> + <template #actions> + <ActionButton icon="icon-checkmark" @click="alert('Mark read')"> + {{ t('news', 'Mark read') }} + </ActionButton> + <ActionButton icon="icon-rename" @click="alert('Rename')"> + {{ t('news', 'Rename') }} + </ActionButton> + <ActionButton icon="icon-delete" @click="deleteFolder(folder)"> + {{ t('news', 'Delete') }} + </ActionButton> + </template> + </AppNavigationItem> + + <AppNavigationItem :title="t('news','Explore')" + icon="icon-link" + :to="{ name: 'explore' }"> + <template #counter> + <CounterBubble>35</CounterBubble> + </template> + </AppNavigationItem> + </ul> + </AppNavigation> +</template> + +<script> +import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation' +import AppNavigationNew from '@nextcloud/vue/dist/Components/AppNavigationNew' +import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem' +import AppNavigationNewItem from '@nextcloud/vue/dist/Components/AppNavigationNewItem' +import AppNavigationCounter from '@nextcloud/vue/dist/Components/AppNavigationCounter' +import CounterBubble from '@nextcloud/vue/dist/Components/CounterBubble' +import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' +import AddFeed from "./AddFeed"; + +export default { + components: { + AppNavigation, + AppNavigationNew, + AppNavigationItem, + AppNavigationNewItem, + AppNavigationCounter, + CounterBubble, + ActionButton, + AddFeed + }, + props: { + showAddFeed: false, + }, + computed: { + folders() { + return this.$store.state.folders + }, + }, + methods: { + newFolder(value) { + const folderName = value.trim(); + const folder = {name: folderName}; + this.$store.dispatch('addFolder', {folder}) + }, + deleteFolder(folder) { + this.$store.dispatch('deleteFolder', {folder}) + window.location.reload(true); + }, + showShowAddFeed() { + this.showAddFeed = true; + }, + closeShowAddFeed() { + this.showAddFeed = false; + } + }, + created() { + } +} +</script> |