summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Brahmer <info@b-brahmer.de>2023-02-24 16:35:32 +0100
committerBenjamin Brahmer <info@b-brahmer.de>2023-03-01 17:23:12 +0100
commita131dd3aa27fe31cb126396d1c606a29266a27be (patch)
tree310280ed0fa654dd3b9340cc0b6e1ce4f16814fe
parent7dfa18973ad448a4aa0b18884b68fdf85d649b2b (diff)
draft first dashboarddashboard
Signed-off-by: Benjamin Brahmer <info@b-brahmer.de>
-rw-r--r--Makefile3
-rw-r--r--css/dashboard.css12
-rw-r--r--lib/AppInfo/Application.php4
-rw-r--r--lib/Dashboard/FeedWidget.php91
-rw-r--r--lib/Dashboard/ItemWidget.php93
-rw-r--r--src/components/FeedDashboard.vue53
-rw-r--r--src/components/ItemDashboard.vue50
-rw-r--r--src/dashboard-feeds.js11
-rw-r--r--src/dashboard-items.js11
-rw-r--r--src/vueBootstrap.js7
-rw-r--r--webpack.config.js2
11 files changed, 335 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index a67191f79..923259206 100644
--- a/Makefile
+++ b/Makefile
@@ -172,8 +172,7 @@ appstore:
# on macOS there is no option "--parents" for the "cp" command
mkdir -p $(appstore_sign_dir)/$(app_name)/js/build $(appstore_sign_dir)/$(app_name)/js/admin
- cp js/build/app.min.js $(appstore_sign_dir)/$(app_name)/js/build
- cp js/build/news-admin-settings.js* $(appstore_sign_dir)/$(app_name)/js/build
+ cp js/build/* $(appstore_sign_dir)/$(app_name)/js/build
# export the key and cert to a file
@if [ ! -f $(cert_dir)/$(app_name).key ] || [ ! -f $(cert_dir)/$(app_name).crt ]; then \
diff --git a/css/dashboard.css b/css/dashboard.css
new file mode 100644
index 000000000..619989506
--- /dev/null
+++ b/css/dashboard.css
@@ -0,0 +1,12 @@
+.icon-newsdashboard {
+ background-image: url('../img/app-dark.svg');
+ filter: var(--background-invert-if-dark);
+}
+
+.widget-list li {
+ list-style-type: disc;
+}
+
+#app-dashboard .panels .panel--header h2 {
+ display: flex;
+}
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index bc5e1b476..74dbdf84e 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -24,6 +24,8 @@ use OCA\News\Hooks\UserDeleteHook;
use OCA\News\Search\FeedSearchProvider;
use OCA\News\Search\FolderSearchProvider;
use OCA\News\Search\ItemSearchProvider;
+use OCA\News\Dashboard\ItemWidget;
+use OCA\News\Dashboard\FeedWidget;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
@@ -85,6 +87,8 @@ class Application extends App implements IBootstrap
$context->registerSearchProvider(FeedSearchProvider::class);
$context->registerSearchProvider(ItemSearchProvider::class);
+ $context->registerDashboardWidget(ItemWidget::class);
+ $context->registerDashboardWidget(FeedWidget::class);
$context->registerEventListener(BeforeUserDeletedEvent::class, UserDeleteHook::class);
diff --git a/lib/Dashboard/FeedWidget.php b/lib/Dashboard/FeedWidget.php
new file mode 100644
index 000000000..ae27b4053
--- /dev/null
+++ b/lib/Dashboard/FeedWidget.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace OCA\News\Dashboard;
+
+use OCA\News\Service\FeedServiceV2;
+use OCP\AppFramework\Services\IInitialState;
+use OCP\Dashboard\IAPIWidget;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+use OCP\Dashboard\Model\WidgetItem;
+
+use Psr\Log\LoggerInterface;
+
+use OCA\News\AppInfo\Application;
+use OCA\News\Db\ListType;
+use OCP\Util;
+
+class FeedWidget implements IAPIWidget
+{
+
+
+ private $l10n;
+ private $feedService;
+ private $initialStateService;
+ private $userId;
+ private $urlGenerator;
+ private $logger;
+
+ public function __construct(IL10N $l10n,
+ IURLGenerator $urlGenerator,
+ FeedServiceV2 $feedService,
+ IInitialState $initialStateService,
+ LoggerInterface $loggerInterface,
+ ?string $userId
+ ) {
+ $this->l10n = $l10n;
+ $this->feedService = $feedService;
+ $this->initialStateService = $initialStateService;
+ $this->userId = $userId;
+ $this->urlGenerator = $urlGenerator;
+ $this->logger = $loggerInterface;
+ }
+
+ public function getId(): string
+ {
+ return 'news-feed-widget';
+ }
+
+ public function getTitle(): string
+ {
+ $this->logger->debug("Requested title");
+ return $this->l10n->t('News Feed widget');
+ }
+
+ public function getOrder(): int
+ {
+ $this->logger->debug("Requested order");
+ return 20;
+ }
+
+ public function getIconClass(): string
+ {
+ return 'icon-newsdashboard';
+ $this->logger->debug("Requested icon");
+ }
+
+ public function getUrl(): ?string
+ {
+ return $this->urlGenerator->linkToRoute('news.page.index');
+ $this->logger->debug("Requested url");
+ }
+
+ public function load(): void
+ {
+ $this->logger->debug("Requested load with user: " . $this->userId);
+ if ($this->userId !== null) {
+ $items = $this->getItems($this->userId);
+ $this->initialStateService->provideInitialState('dashboard-widget-feeds', $items);
+ }
+
+ Util::addScript(Application::NAME, 'build/' . Application::NAME . '-dashboard-feeds');
+ Util::addStyle(Application::NAME, 'dashboard');
+ }
+
+ public function getItems(string $userId, ?string $since = null, int $limit = 7): array
+ {
+ $items = $this->feedService->findAllForUser($userId);
+
+ return $items;
+ }
+} \ No newline at end of file
diff --git a/lib/Dashboard/ItemWidget.php b/lib/Dashboard/ItemWidget.php
new file mode 100644
index 000000000..f10e63294
--- /dev/null
+++ b/lib/Dashboard/ItemWidget.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace OCA\News\Dashboard;
+
+use OCA\News\Service\ItemServiceV2;
+use OCP\AppFramework\Services\IInitialState;
+use OCP\Dashboard\IAPIWidget;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+//maybe this can be used to craft items with things from the feed
+use OCP\Dashboard\Model\WidgetItem;
+
+use Psr\Log\LoggerInterface;
+
+use OCA\News\AppInfo\Application;
+use OCA\News\Db\ListType;
+use OCP\Util;
+
+class ItemWidget implements IAPIWidget
+{
+
+
+ private $l10n;
+ private $itemService;
+ private $initialStateService;
+ private $userId;
+ private $urlGenerator;
+ private $logger;
+
+ public function __construct(IL10N $l10n,
+ IURLGenerator $urlGenerator,
+ ItemServiceV2 $itemService,
+ IInitialState $initialStateService,
+ LoggerInterface $loggerInterface,
+ ?string $userId
+ ) {
+ $this->l10n = $l10n;
+ $this->itemService = $itemService;
+ $this->initialStateService = $initialStateService;
+ $this->userId = $userId;
+ $this->urlGenerator = $urlGenerator;
+ $this->logger = $loggerInterface;
+ }
+
+ public function getId(): string
+ {
+ return 'news-item-widget';
+ }
+
+ public function getTitle(): string
+ {
+ $this->logger->debug("Requested title");
+ return $this->l10n->t('News Item widget');
+ }
+
+ public function getOrder(): int
+ {
+ $this->logger->debug("Requested order");
+ return 20;
+ }
+
+ public function getIconClass(): string
+ {
+ return 'icon-newsdashboard'; // TODO
+ $this->logger->debug("Requested icon");
+ }
+
+ public function getUrl(): ?string
+ {
+ return $this->urlGenerator->linkToRoute('news.page.index');
+ $this->logger->debug("Requested url");
+ }
+
+ public function load(): void
+ {
+ $this->logger->debug("Requested load with user: " . $this->userId);
+ if ($this->userId !== null) {
+ $items = $this->getItems($this->userId);
+ $this->initialStateService->provideInitialState('dashboard-widget-items', $items);
+ }
+
+ Util::addScript(Application::NAME, 'build/' . Application::NAME . '-dashboard-items');
+ Util::addStyle(Application::NAME, 'dashboard');
+ }
+
+ public function getItems(string $userId, ?string $since = null, int $limit = 7): array
+ {
+ $offset = (int) ($since ?? 0);
+ $items = $this->itemService->findAllWithFilters($userId, ListType::ALL_ITEMS, $limit, $offset, false);
+
+ return $items;
+ }
+} \ No newline at end of file
diff --git a/src/components/FeedDashboard.vue b/src/components/FeedDashboard.vue
new file mode 100644
index 000000000..f917ebf36
--- /dev/null
+++ b/src/components/FeedDashboard.vue
@@ -0,0 +1,53 @@
+<template>
+ <NcDashboardWidget :items="items">
+ <template #default="{ item }">
+ <NcDashboardWidgetItem
+ :main-text="item.mainText"
+ :sub-text="item.subText"
+ :target-url="item.targetURL"
+ :avatar-is-no-user="true"
+ :avatar-url="item.favicon">
+
+ <NcDashboardWidgetItem>
+ </template>
+ </NcDashboardWidget>
+</template>
+
+<script>
+import NcDashboardWidget from '@nextcloud/vue/dist/Components/NcDashboardWidget.js'
+import NcDashboardWidgetItem from '@nextcloud/vue/dist/Components/NcDashboardWidgetItem'
+import { loadState } from '@nextcloud/initial-state'
+import { generateUrl } from '@nextcloud/router'
+
+const newsItems = loadState('news', 'dashboard-widget-feeds')
+
+console.log(newsItems)
+
+export default {
+ name: 'NewsFeedWidget',
+ components: {
+ NcDashboardWidget,
+ NcDashboardWidgetItem,
+ },
+ props: [],
+ data() {
+ return {
+ newsItems: newsItems
+ }
+ },
+
+ computed: {
+ items() {
+ return this.newsItems.map((g) => {
+ return {
+ id: g.id,
+ mainText: g.title,
+ subText: `Unread: ${g.unreadCount}`,
+ targetURL: generateUrl(`/apps/news/#/items/feeds/${g.id}`),
+ favicon: g.faviconLink,
+ }
+ })
+ }
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/components/ItemDashboard.vue b/src/components/ItemDashboard.vue
new file mode 100644
index 000000000..a7a0f4e0c
--- /dev/null
+++ b/src/components/ItemDashboard.vue
@@ -0,0 +1,50 @@
+<template>
+ <NcDashboardWidget :items="items">
+ <template #default="{ item }">
+ <NcDashboardWidgetItem
+ :main-text="item.mainText"
+ :sub-text="item.subText"
+ :target-url="item.targetURL">
+
+ <NcDashboardWidgetItem>
+ </template>
+ </NcDashboardWidget>
+</template>
+
+<script>
+import NcDashboardWidget from '@nextcloud/vue/dist/Components/NcDashboardWidget.js'
+import NcDashboardWidgetItem from '@nextcloud/vue/dist/Components/NcDashboardWidgetItem'
+import { loadState } from '@nextcloud/initial-state'
+import { generateUrl } from '@nextcloud/router'
+
+const newsItems = loadState('news', 'dashboard-widget-items')
+
+console.log(newsItems)
+
+export default {
+ name: 'NewsItemWidget',
+ components: {
+ NcDashboardWidget,
+ NcDashboardWidgetItem,
+ },
+ props: [],
+ data() {
+ return {
+ newsItems: newsItems
+ }
+ },
+
+ computed: {
+ items() {
+ return this.newsItems.map((g) => {
+ return {
+ id: g.id,
+ mainText: g.title,
+ subText: g.intro,
+ targetURL: generateUrl(`/apps/news/#/items/feeds/${g.feedId}`)
+ }
+ })
+ }
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/dashboard-feeds.js b/src/dashboard-feeds.js
new file mode 100644
index 000000000..1ae896414
--- /dev/null
+++ b/src/dashboard-feeds.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import NewsFeedWidget from './components/FeedDashboard.vue'
+
+document.addEventListener('DOMContentLoaded', () => {
+ console.log("I'm alive")
+ OCA.Dashboard.register('news-feed-widget', (el) => {
+ console.log("Dashboard registered")
+ const View = Vue.extend(NewsFeedWidget)
+ new View().$mount(el)
+ })
+})
diff --git a/src/dashboard-items.js b/src/dashboard-items.js
new file mode 100644
index 000000000..564d10d62
--- /dev/null
+++ b/src/dashboard-items.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import NewsItemWidget from './components/ItemDashboard.vue'
+
+document.addEventListener('DOMContentLoaded', () => {
+ console.log("I'm alive")
+ OCA.Dashboard.register('news-item-widget', (el) => {
+ console.log("Dashboard registered")
+ const View = Vue.extend(NewsItemWidget)
+ new View().$mount(el)
+ })
+})
diff --git a/src/vueBootstrap.js b/src/vueBootstrap.js
new file mode 100644
index 000000000..fec6f7a09
--- /dev/null
+++ b/src/vueBootstrap.js
@@ -0,0 +1,7 @@
+import Vue from 'vue'
+import { translate, translatePlural } from '@nextcloud/l10n'
+
+Vue.prototype.t = translate
+Vue.prototype.n = translatePlural
+Vue.prototype.OC = window.OC
+Vue.prototype.OCA = window.OCA \ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index c329f79d1..2800f7bae 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -6,6 +6,8 @@ const webpackConfig = require('@nextcloud/webpack-vue-config')
webpackConfig.entry = {
'admin-settings': path.join(__dirname, 'src', 'main-admin.js'),
+ 'dashboard-items': path.join(__dirname, 'src', 'dashboard-items.js'),
+ 'dashboard-feeds': path.join(__dirname, 'src', 'dashboard-feeds.js'),
}
webpackConfig.output.path = path.resolve('./js/build/')
webpackConfig.output.publicPath = path.join('/apps/', process.env.npm_package_name, '/js/build/')