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] Add Feed Component #2306

Merged
merged 13 commits into from
Aug 11, 2023
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@
],
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/src/$1",
"^Components/(.*)$": "<rootDir>/src/components/$1"
"^Components/(.*)$": "<rootDir>/src/components/$1",
"^.+\\.(css|less)$": "<rootDir>/tests/javascript/helpers/CSSStub.js"
},
"testEnvironment": "jsdom",
"transform": {
Expand Down
224 changes: 122 additions & 102 deletions src/components/AddFeed.vue
Original file line number Diff line number Diff line change
@@ -1,87 +1,82 @@
<template>
<NcModal @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)
}"
<div id="new-feed">
<form name="feedform">
<fieldset style="padding: 16px">
<input v-model="feedUrl"
type="text"
:placeholder="t('news', 'Web address')"
:class="{ 'invalid': feedUrlExists() }"
name="address"
pattern="[^\s]+"
required
autofocus>
autofocus
style="width: 90%;">

<p class="error"
ng-show="!Navigation.addingFeed &&
Navigation.feedUrlExists(Navigation.feed.url)">
<p v-if="feedUrlExists()" class="error">
{{ t("news", "Feed exists already!") }}
</p>

<!-- select a folder -->
<NcCheckboxRadioSwitch :checked.sync="createNewFolder" type="switch">
{{ t("news", "New folder") }}?
</NcCheckboxRadioSwitch>

<NcMultiselect v-if="!createNewFolder && folders"
v-model="folder"
:options="folders"
track-by="id"
label="name" />
<div style="display:flex;">
<NcSelect v-if="!createNewFolder && folders"
v-model="folder"
:options="folders"
:placeholder="'-- ' + t('news', 'No folder') + ' --'"
track-by="id"
label="name"
style="flex-grow: 1;" />

<!-- add a folder -->
<input v-if="createNewFolder"
v-model="newFolderName"
type="text"
:class="{ 'invalid': folderNameExists() }"
:placeholder="t('news', 'Folder name')"
name="folderName"
style="flex-grow: 1; padding: 22px 12px; margin: 0px;"
required>

<NcCheckboxRadioSwitch :checked.sync="createNewFolder" type="switch">
{{ t("news", "New folder") }}?
</NcCheckboxRadioSwitch>
</div>

<!-- add a folder -->
<input v-if="createNewFolder"
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"
style="width: 90%"
required>

<p class="error"
ng-show="!Navigation.addingFeed &&
Navigation.folderNameExists(Navigation.feed.newFolder)">
<p v-if="folderNameExists()"
class="error">
{{ t("news", "Folder exists already!") }}
</p>

<!-- basic auth -->
<p v-if="withBasicAuth" 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>

<NcCheckboxRadioSwitch :checked.sync="withBasicAuth" type="switch">
{{ t("news", "Credentials") }}?
</NcCheckboxRadioSwitch>

<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 style="display: flex">
<NcCheckboxRadioSwitch :checked.sync="withBasicAuth" type="switch" style="flex-grow: 1;">
{{ t("news", "Credentials") }}?
</NcCheckboxRadioSwitch>

<div v-if="withBasicAuth" class="add-feed-basicauth" style="flex-grow: 1; display: flex;">
<input v-model="feedUser"
type="text"
:placeholder="t('news', 'Username')"
name="user"
autofocus
style="flex-grow: 1">

<input v-model="feedPassword"
type="password"
:placeholder="t('news', 'Password')"
name="password"
autocomplete="new-password"
style="flex-grow: 1">
</div>
</div>

<NcCheckboxRadioSwitch :checked.sync="autoDiscover" type="switch">
Expand All @@ -90,11 +85,7 @@

<NcButton :wide="true"
type="primary"
ng-disabled="Navigation.feedUrlExists(Navigation.feed.url) ||
(
Navigation.showNewFolder &&
Navigation.folderNameExists(folder.name)
)"
:disabled="disableAddFeed"
@click="addFeed()">
{{ t("news", "Subscribe") }}
</NcButton>
Expand All @@ -111,75 +102,104 @@ import Vue from 'vue'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'

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

type AddFeedState = {
folder: Folder;
folder?: Folder;
newFolderName: string;

autoDiscover: boolean;
createNewFolder: boolean;
withBasicAuth: boolean;

// from props
feed?: Feed;
feedUrl?: string;
feedUser?: string;
feedPassword?: string;
};

export default Vue.extend({
components: {
NcModal,
NcCheckboxRadioSwitch,
NcButton,
NcMultiselect,
},
props: {
feed: {
type: String,
default: '',
},
NcSelect,
},
data: (): AddFeedState => {
return {
folder: { name: '' } as Folder,
folder: undefined,
newFolderName: '',

autoDiscover: true,
createNewFolder: false,
withBasicAuth: false,

feedUrl: '',
feedUser: '',
feedPassword: '',
}
},
computed: {
folders(): Folder[] {
return this.$store.state.folders
return this.$store.state.folders.folders
},
disableAddFeed(): boolean {
return (this.feedUrl === ''
|| this.feedUrlExists()
|| (this.createNewFolder && (this.newFolderName === '' || this.folderNameExists())))
},
},
methods: {
newFolder() {
this.createNewFolder = true
},
abortNewFolder() {
this.createNewFolder = false
},
addFeed() {
/**
* Adds a New Feed via the Vuex Store
*/
async addFeed() {
this.$store.dispatch(ACTIONS.ADD_FEED, {
feedReq: {
url: this.feed,
folder: this.folder,
autoDiscover: true,
url: this.feedUrl,
folder: this.createNewFolder ? { name: this.newFolderName } : this.folder,
autoDiscover: this.autoDiscover,
user: this.feedUser === '' ? undefined : this.feedUser,
password: this.feedPassword === '' ? undefined : this.feedPassword,
},
})

this.$emit('close')
},
/**
* Checks if Feed Url exists in Vuex Store Feeds
*/
feedUrlExists(): boolean {
for (const feed of this.$store.state.feeds.feeds) {
if (feed.url === this.feedUrl) {
return true
}
}

return false
},
/**
* Check if Folder Name exists in Vuex Store Folders
*/
folderNameExists(): boolean {
if (this.createNewFolder) {
for (const folder of this.$store.state.folders.folders) {
if (folder.name === this.newFolderName) {
return true
}
}
}
return false
},
},
})

</script>

<style scoped>
input {
width: 100%
}

.multiselect {
width: 100%
.invalid {
border: 1px solid rgb(251, 72, 72) !important;
}
</style>
8 changes: 4 additions & 4 deletions src/components/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
</NcAppNavigationItem>

<NcAppNavigationItem v-for="topLevelItem in topLevelNav"
:key="topLevelItem.name"
:title="topLevelItem.name"
icon="icon-folder"
:key="topLevelItem.name || topLevelItem.title"
:title="topLevelItem.name || topLevelItem.title"
:icon="topLevelItem.name !== undefined ? 'icon-folder': ''"
:allow-collapse="true">
<template #default>
<NcAppNavigationItem v-for="feed in topLevelItem.feeds"
Expand Down Expand Up @@ -101,7 +101,7 @@
</NcAppNavigationItem>
</template>
<template v-if="topLevelItem.feedCount > 0" #counter>
<CounterBubble>{{ topLevelItem.feedCount }}</CounterBubble>
<NcCounterBubble>{{ topLevelItem.feedCount }}</NcCounterBubble>
</template>
<template #actions>
<NcActionButton icon="icon-checkmark" @click="alert('TODO: Mark read')">
Expand Down
Loading
Loading