mirror of
https://github.com/chylex/Nextcloud-News.git
synced 2025-02-22 20:46:04 +01:00
[Vue Rewrite] Enable Typescript Vue Components (#1831)
* compiling typescript with webpack Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * working typescript component Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * clean up indentation and linting Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * remove calendar-js Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * revert indentation and remove commented out lines Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * clean up warning Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * cleanup + add comments Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * fix warnings and add more comments Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * cleanup unecessary changes to webpack and add comments Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * fix package Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * update changelog and fix comment Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * cleanup Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * remove unecessary line Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * remove vue-class-component library + others Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * clean up babel-loader Signed-off-by: Devlin Junker <devlin.junker@gmail.com> * remove fork-ts-checker plugin Signed-off-by: Devlin Junker <devlin.junker@gmail.com>
This commit is contained in:
parent
40d9c352ab
commit
f1668df03f
32
.eslintrc.js
32
.eslintrc.js
@ -1,10 +1,26 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'@nextcloud',
|
||||
],
|
||||
rules: {
|
||||
'jsdoc/check-alignment': 'off',
|
||||
'vue/html-indent': 'off',
|
||||
'indent': ['error', 4]
|
||||
},
|
||||
root: true,
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: {
|
||||
ts: '@typescript-eslint/parser',
|
||||
},
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/base',
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard',
|
||||
'@vue/typescript/recommended',
|
||||
'@nextcloud',
|
||||
],
|
||||
ignorePatterns: ['*.d.ts'],
|
||||
rules: {
|
||||
'node/no-unpublished-import': 'off', // necessary for vue-property-decorator (not published?)
|
||||
|
||||
// TODO: remove these indentation rules during reformat (expects tab char \t but right now code base uses spaces)
|
||||
'vue/html-indent': 'off',
|
||||
indent: ['error', 4],
|
||||
},
|
||||
}
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -47,6 +47,9 @@ RCS/*
|
||||
# netbeans
|
||||
nbproject
|
||||
|
||||
# vscode
|
||||
.vscode
|
||||
|
||||
# phpStorm
|
||||
.idea
|
||||
|
||||
|
@ -6,6 +6,7 @@ The format is mostly based on [Keep a Changelog](https://keepachangelog.com/en/1
|
||||
## [19.x.x]
|
||||
### Changed
|
||||
- Vue Rewrite
|
||||
- Add Typescript
|
||||
|
||||
## [18.x.x]
|
||||
### Changed
|
||||
|
@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
],
|
||||
presets: ['@babel/preset-env'],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
],
|
||||
presets: ['@babel/preset-env'],
|
||||
}
|
||||
|
11218
package-lock.json
generated
11218
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
47
package.json
47
package.json
@ -38,35 +38,46 @@
|
||||
},
|
||||
"private": true,
|
||||
"homepage": "https://github.com/nextcloud/news",
|
||||
"dependencies": {
|
||||
"@nextcloud/axios": "^1.10.0",
|
||||
"@nextcloud/dialogs": "^3.1.2",
|
||||
"@nextcloud/router": "^2.0.0",
|
||||
"@nextcloud/vue": "^5.3.1",
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.3",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.1",
|
||||
"@babel/eslint-parser": "^7.17.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@nextcloud/babel-config": "^1.0.0",
|
||||
"@nextcloud/browserslist-config": "^2.2.0",
|
||||
"@nextcloud/eslint-config": "^6.1.2",
|
||||
"@nextcloud/eslint-config": "^8.0.0",
|
||||
"@nextcloud/eslint-plugin": "^2.0.0",
|
||||
"@nextcloud/stylelint-config": "^2.1.2",
|
||||
"@nextcloud/webpack-vue-config": "^5.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"@types/webpack-env": "^1.17.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.1",
|
||||
"@typescript-eslint/parser": "^5.27.1",
|
||||
"@vue/eslint-config-standard": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-import-resolver-webpack": "^0.12.2",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-jsdoc": "^37.9.7",
|
||||
"eslint-plugin-jsdoc": "^39.2.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.2.0",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"eslint-plugin-vue": "^7.20.0",
|
||||
"eslint-plugin-vue": "^8.7.1",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"file-loader": "^6.0.0",
|
||||
"jasmine-core": "^3.5.0",
|
||||
"jquery": "^3.5.1",
|
||||
"jshint": "^2.11.1",
|
||||
"karma": "^5.0.9",
|
||||
"karma": "^6.4.0",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-coverage": "^2.0.2",
|
||||
"karma-firefox-launcher": "^1.3.0",
|
||||
@ -84,19 +95,13 @@
|
||||
"stylelint-config-recommended-scss": "^5.0.2",
|
||||
"stylelint-config-recommended-vue": "^1.4.0",
|
||||
"stylelint-webpack-plugin": "^2.1.0",
|
||||
"ts-loader": "^9.3.0",
|
||||
"typescript": "^4.7.2",
|
||||
"url-loader": "^4.1.0",
|
||||
"vue-loader": "^15.9.3",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"vue-eslint-parser": "^9.0.2",
|
||||
"vue-loader": "^15.9.8",
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"webpack": "^5.72.1",
|
||||
"webpack-cli": "^4.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/axios": "^1.10.0",
|
||||
"@nextcloud/dialogs": "^3.1.2",
|
||||
"@nextcloud/router": "^2.0.0",
|
||||
"@nextcloud/vue": "^5.3.1",
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.3",
|
||||
"vuex": "^3.6.2"
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,5 @@ export default {
|
||||
created() {
|
||||
this.$store.dispatch('loadFolder')
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
@ -2,15 +2,15 @@
|
||||
<div id="explore">
|
||||
<AddFeed v-if="showAddFeed" :feed="feed" @close="closeShowAddFeed()" />
|
||||
<div class="grid-container">
|
||||
<div v-for="entry in explorableSites"
|
||||
<div v-for="entry in exploreSites"
|
||||
:key="entry.title"
|
||||
class="explore-feed grid-item">
|
||||
<h2 v-if="entry.favicon"
|
||||
class="explore-title"
|
||||
:style="{ backgroundImage: 'url(' + entry.favicon + ')' }">
|
||||
<a target="_blank" rel="noreferrer" :href="entry.url">{{
|
||||
entry.title
|
||||
}}</a>
|
||||
<a target="_blank" rel="noreferrer" :href="entry.url">
|
||||
{{ entry.title }}
|
||||
</a>
|
||||
</h2>
|
||||
<h2 v-if="!entry.favicon" class="icon-rss explore-title">
|
||||
{{ entry.title }}
|
||||
@ -30,58 +30,56 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* eslint-disable vue/require-prop-type-constructor */
|
||||
|
||||
// import Modal from '@nextcloud/vue/dist/Components/Modal'
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import Button from '@nextcloud/vue/dist/Components/Button'
|
||||
import axios from '@nextcloud/axios'
|
||||
import AddFeed from './AddFeed'
|
||||
import AddFeed from './AddFeed.vue'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
export default {
|
||||
const ExploreComponent = Vue.extend({
|
||||
components: {
|
||||
// Modal,
|
||||
Button,
|
||||
AddFeed,
|
||||
},
|
||||
props: {
|
||||
feed: '',
|
||||
},
|
||||
data() {
|
||||
data: () => {
|
||||
const exploreSites: any[] = []
|
||||
const feed: any = {}
|
||||
const showAddFeed = false
|
||||
|
||||
return {
|
||||
explorableSites: [],
|
||||
showAddFeed: false,
|
||||
exploreSites,
|
||||
feed,
|
||||
showAddFeed,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.sites()
|
||||
},
|
||||
|
||||
methods: {
|
||||
async sites() {
|
||||
const settings = await axios.get(
|
||||
generateUrl('/apps/news/settings')
|
||||
)
|
||||
// console.log(settings.data)
|
||||
// console.log(settings.data.settings.exploreUrl)
|
||||
const settings = await axios.get(generateUrl('/apps/news/settings'))
|
||||
|
||||
const exploreUrl
|
||||
= settings.data.settings.exploreUrl + 'feeds.en.json'
|
||||
const exploreUrl = settings.data.settings.exploreUrl + 'feeds.en.json'
|
||||
const explore = await axios.get(exploreUrl)
|
||||
|
||||
Object.keys(explore.data).forEach((key) =>
|
||||
explore.data[key].forEach((value) =>
|
||||
this.explorableSites.push(value)
|
||||
)
|
||||
explore.data[key].forEach((value: any) =>
|
||||
this.exploreSites.push(value),
|
||||
),
|
||||
)
|
||||
},
|
||||
async subscribe(feed) {
|
||||
// this.feed = feed
|
||||
async subscribe(feed: any) {
|
||||
this.feed = feed
|
||||
this.showAddFeed = true
|
||||
},
|
||||
closeShowAddFeed() {
|
||||
this.showAddFeed = false
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
export default ExploreComponent
|
||||
|
||||
</script>
|
||||
|
@ -11,8 +11,7 @@
|
||||
icon="icon-add-folder"
|
||||
@new-item="newFolder" />
|
||||
|
||||
<AppNavigationItem :title="t('news', 'Unread articles')"
|
||||
icon="icon-rss">
|
||||
<AppNavigationItem :title="t('news', 'Unread articles')" icon="icon-rss">
|
||||
<template #actions>
|
||||
<ActionButton icon="icon-checkmark" @click="alert('Edit')">
|
||||
t('news','Mark read')
|
||||
@ -22,16 +21,14 @@
|
||||
<CounterBubble>5</CounterBubble>
|
||||
</template>
|
||||
</AppNavigationItem>
|
||||
<AppNavigationItem :title="t('news', 'All articles')"
|
||||
icon="icon-rss">
|
||||
<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">
|
||||
<AppNavigationItem :title="t('news', 'Starred')" icon="icon-starred">
|
||||
<template #counter>
|
||||
<CounterBubble>35</CounterBubble>
|
||||
</template>
|
||||
@ -53,12 +50,10 @@
|
||||
<div v-if="!feed.faviconLink" class="icon-rss" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<ActionButton icon="icon-checkmark"
|
||||
@click="alert('Mark read')">
|
||||
<ActionButton icon="icon-checkmark" @click="alert('Mark read')">
|
||||
{{ t("news", "Mark read") }}
|
||||
</ActionButton>
|
||||
<ActionButton icon="icon-pinned"
|
||||
@click="alert('Rename')">
|
||||
<ActionButton icon="icon-pinned" @click="alert('Rename')">
|
||||
{{ t("news", "Unpin from top") }}
|
||||
</ActionButton>
|
||||
<ActionButton icon="icon-caret-dark"
|
||||
@ -89,16 +84,14 @@
|
||||
@click="deleteFolder(folder)">
|
||||
{{ t("news", "Ignore updated") }}
|
||||
</ActionButton>
|
||||
<ActionButton icon="icon-icon-rss"
|
||||
@click="deleteFolder(folder)">
|
||||
<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)">
|
||||
<ActionButton icon="icon-delete" @click="deleteFolder(folder)">
|
||||
{{ t("news", "Delete") }}
|
||||
</ActionButton>
|
||||
</template>
|
||||
@ -108,15 +101,13 @@
|
||||
<CounterBubble>{{ folder.feedCount }}</CounterBubble>
|
||||
</template>
|
||||
<template #actions>
|
||||
<ActionButton icon="icon-checkmark"
|
||||
@click="alert('Mark read')">
|
||||
<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)">
|
||||
<ActionButton icon="icon-delete" @click="deleteFolder(folder)">
|
||||
{{ t("news", "Delete") }}
|
||||
</ActionButton>
|
||||
</template>
|
||||
@ -142,7 +133,7 @@ import AppNavigationNewItem from '@nextcloud/vue/dist/Components/AppNavigationNe
|
||||
// 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'
|
||||
import AddFeed from './AddFeed.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -155,7 +146,7 @@ export default {
|
||||
ActionButton,
|
||||
AddFeed,
|
||||
},
|
||||
data() {
|
||||
data: () => {
|
||||
return {
|
||||
showAddFeed: false,
|
||||
}
|
||||
@ -165,7 +156,9 @@ export default {
|
||||
return this.$store.state.folders
|
||||
},
|
||||
},
|
||||
created() {},
|
||||
created() {
|
||||
// TODO?
|
||||
},
|
||||
methods: {
|
||||
newFolder(value) {
|
||||
const folderName = value.trim()
|
||||
@ -182,6 +175,9 @@ export default {
|
||||
closeShowAddFeed() {
|
||||
this.showAddFeed = false
|
||||
},
|
||||
alert(msg) {
|
||||
window.alert(msg)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
21
src/main.js
21
src/main.js
@ -1,10 +1,10 @@
|
||||
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import App from './App.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Explore from './components/Explore'
|
||||
import Explore from './components/Explore.vue'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import Vuex from 'vuex'
|
||||
import Vuex, { Store } from 'vuex'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
import { Tooltip } from '@nextcloud/vue'
|
||||
@ -36,7 +36,7 @@ const router = new VueRouter({
|
||||
routes,
|
||||
})
|
||||
|
||||
const store = new Vuex.Store({
|
||||
const store = new Store({
|
||||
state: {
|
||||
folders: [],
|
||||
feeds: [],
|
||||
@ -52,10 +52,12 @@ const store = new Vuex.Store({
|
||||
feeds.forEach((it) => {
|
||||
state.feeds.push(it)
|
||||
const folder = state.folders.find(
|
||||
(folder) => folder.id === it.folderId
|
||||
(folder) => folder.id === it.folderId,
|
||||
)
|
||||
folder.feeds.push(it)
|
||||
folder.feedCount += it.unreadCount
|
||||
if (folder) {
|
||||
folder.feeds.push(it)
|
||||
folder.feedCount += it.unreadCount
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
@ -64,7 +66,7 @@ const store = new Vuex.Store({
|
||||
axios
|
||||
.post(folderUrl, { folderName: folder.name })
|
||||
.then((response) =>
|
||||
commit('addFolders', response.data.folders)
|
||||
commit('addFolders', response.data.folders),
|
||||
)
|
||||
},
|
||||
deleteFolder({ commit }, { folder }) {
|
||||
@ -72,7 +74,6 @@ const store = new Vuex.Store({
|
||||
this.getByFolderId(folderId).forEach(function (feed) {
|
||||
promises.push(self.reversiblyDelete(feed.id, false, true));
|
||||
});
|
||||
|
||||
this.updateUnreadCache();
|
||||
*/
|
||||
axios.delete(folderUrl + '/' + folder.id).then()
|
||||
@ -83,7 +84,7 @@ const store = new Vuex.Store({
|
||||
axios
|
||||
.get(feedUrl)
|
||||
.then((response) =>
|
||||
commit('addFeeds', response.data.feeds)
|
||||
commit('addFeeds', response.data.feeds),
|
||||
)
|
||||
})
|
||||
},
|
||||
|
18
src/shims-tsx.d.ts
vendored
Normal file
18
src/shims-tsx.d.ts
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Initially copied from typescript+vue2 project generated by @vue/cli-plugin v5.0.0
|
||||
*/
|
||||
import Vue, { VNode } from "vue";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface Element extends VNode { }
|
||||
interface ElementClass extends Vue { }
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any;
|
||||
}
|
||||
}
|
||||
t;
|
||||
n;
|
||||
OC;
|
||||
OCA;
|
||||
};
|
11
src/shims-vue.d.ts
vendored
Normal file
11
src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Initially copied from typescript+vue2 project generated by @vue/cli-plugin v5.0.0
|
||||
*/
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue';
|
||||
export default Vue;
|
||||
};
|
||||
|
||||
declare module '@nextcloud/vue/dist/Components/Button' {
|
||||
|
||||
};
|
48
tsconfig.json
Normal file
48
tsconfig.json
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Initially copied from typescript+vue2 project generated by @vue/cli-plugin v5.0.0
|
||||
*/
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"useDefineForClassFields": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env",
|
||||
// TODO: Add these back when we add unit testing
|
||||
// "mocha",
|
||||
// "chai"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
17
webpack.js
17
webpack.js
@ -1,3 +1,20 @@
|
||||
const webpackConfig = require('@nextcloud/webpack-vue-config')
|
||||
|
||||
// Add TS Loader for processing typescript in vue templates
|
||||
webpackConfig.module.rules.push({
|
||||
test: /.ts$/,
|
||||
exclude: [/node_modules/],
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
appendTsSuffixTo: [
|
||||
'\\.vue$',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
Loading…
Reference in New Issue
Block a user