diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | apps/dashboard/appinfo/app.php | 24 | ||||
-rw-r--r-- | apps/dashboard/appinfo/info.xml | 30 | ||||
-rw-r--r-- | apps/dashboard/appinfo/routes.php | 28 | ||||
-rw-r--r-- | apps/dashboard/img/dashboard.svg | 1 | ||||
-rw-r--r-- | apps/dashboard/lib/Controller/DashboardController.php | 79 | ||||
-rw-r--r-- | apps/dashboard/src/App.vue | 119 | ||||
-rw-r--r-- | apps/dashboard/src/main.js | 9 | ||||
-rw-r--r-- | apps/dashboard/templates/index.php | 4 | ||||
-rw-r--r-- | apps/dashboard/webpack.js | 11 | ||||
-rw-r--r-- | webpack.common.js | 2 |
11 files changed, 308 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 680bd19c8ee..0b6eeaec463 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ !/apps/cloud_federation_api !/apps/comments !/apps/contactsinteraction +!/apps/dashboard !/apps/dav !/apps/files !/apps/federation diff --git a/apps/dashboard/appinfo/app.php b/apps/dashboard/appinfo/app.php new file mode 100644 index 00000000000..3edd53762fd --- /dev/null +++ b/apps/dashboard/appinfo/app.php @@ -0,0 +1,24 @@ +<?php +/** + * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net> + * + * @author Julius Härtl <jus@bitgrid.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +$app = new \OCP\AppFramework\App('dashboard'); diff --git a/apps/dashboard/appinfo/info.xml b/apps/dashboard/appinfo/info.xml new file mode 100644 index 00000000000..9d3b7fc8418 --- /dev/null +++ b/apps/dashboard/appinfo/info.xml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd"> + <id>dashboard</id> + <name>Dashboard</name> + <summary>Dashboard app</summary> + <description><![CDATA[Show something]]></description> + <version>7.0.0</version> + <licence>agpl</licence> + <author>Julius Härtl</author> + <namespace>Dashboard</namespace> + <default_enable/> + + <category>customization</category> + + <bugs>https://github.com/nextcloud/server/issues</bugs> + + <dependencies> + <nextcloud min-version="20" max-version="20"/> + </dependencies> + + <navigations> + <navigation> + <name>Dashboard</name> + <route>dashboard.dashboard.index</route> + <icon>dashboard.svg</icon> + <order>-1</order> + </navigation> + </navigations> +</info> diff --git a/apps/dashboard/appinfo/routes.php b/apps/dashboard/appinfo/routes.php new file mode 100644 index 00000000000..5ad8e9073d0 --- /dev/null +++ b/apps/dashboard/appinfo/routes.php @@ -0,0 +1,28 @@ +<?php +/** + * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net> + * + * @author Julius Härtl <jus@bitgrid.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +return [ + 'routes' => [ + ['name' => 'dashboard#index', 'url' => '/', 'verb' => 'GET'], + ] +]; diff --git a/apps/dashboard/img/dashboard.svg b/apps/dashboard/img/dashboard.svg new file mode 100644 index 00000000000..a942dfc4a50 --- /dev/null +++ b/apps/dashboard/img/dashboard.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><g stroke-width=".905" fill="#fff" paint-order="stroke fill markers"><path d="M2.096 2.902h3.26v10.046h-3.26zM6.49 2.85h3.26v10.046H6.49zM11.052 2.824h3.26V12.87h-3.26z"/></g></svg>
\ No newline at end of file diff --git a/apps/dashboard/lib/Controller/DashboardController.php b/apps/dashboard/lib/Controller/DashboardController.php new file mode 100644 index 00000000000..75a34727c8e --- /dev/null +++ b/apps/dashboard/lib/Controller/DashboardController.php @@ -0,0 +1,79 @@ +<?php +/** + * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net> + * + * @author Julius Härtl <jus@bitgrid.net> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Dashboard\Controller; + +use OCA\Viewer\Event\LoadViewer; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\Dashboard\IManager; +use OCP\Dashboard\IPanel; +use OCP\Dashboard\IRegisterPanelEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IInitialStateService; +use OCP\IRequest; + +class DashboardController extends Controller { + + /** @var IInitialStateService */ + private $inititalStateService; + /** @var IEventDispatcher */ + private $eventDispatcher; + /** @var IManager */ + private $dashboardManager; + + public function __construct($appName, IRequest $request, IInitialStateService $initialStateService, IEventDispatcher $eventDispatcher, IManager $dashboardManager) { + parent::__construct($appName, $request); + + $this->inititalStateService = $initialStateService; + $this->eventDispatcher = $eventDispatcher; + $this->dashboardManager = $dashboardManager; + } + + /** + * @NoCSRFRequired + * @NoAdminRequired + * @return TemplateResponse + */ + public function index(): TemplateResponse { + $this->eventDispatcher->dispatchTyped(new IRegisterPanelEvent($this->dashboardManager)); + + $dashboardManager = $this->dashboardManager; + $this->inititalStateService->provideLazyInitialState('dashboard', 'panels', function () use ($dashboardManager) { + return array_map(function (IPanel $panel) { + return [ + 'id' => $panel->getId(), + 'title' => $panel->getTitle(), + 'iconClass' => $panel->getIconClass(), + 'url' => $panel->getUrl() + ]; + }, $dashboardManager->getPanels()); + }); + + if (class_exists(LoadViewer::class)) { + $this->eventDispatcher->dispatchTyped(new LoadViewer()); + } + + return new TemplateResponse('dashboard', 'index'); + } +} diff --git a/apps/dashboard/src/App.vue b/apps/dashboard/src/App.vue new file mode 100644 index 00000000000..9f8598de216 --- /dev/null +++ b/apps/dashboard/src/App.vue @@ -0,0 +1,119 @@ +<template> + <div id="app-dashboard"> + <h2>{{ greeting }}, {{ name }}</h2> + + <div class="panels"> + <div v-for="panel in panels" :key="panel.id" class="panel"> + <a :href="panel.url"> + <h3 :class="panel.iconClass"> + {{ panel.title }} + </h3> + </a> + <div :ref="panel.id" :data-id="panel.id" /> + </div> + </div> + </div> +</template> + +<script> +import Vue from 'vue' +import { loadState } from '@nextcloud/initial-state' +import { getCurrentUser } from '@nextcloud/auth' + +const panels = loadState('dashboard', 'panels') + +console.debug('Loading dashboard panels', panels) + +export default { + name: 'App', + data() { + return { + timer: new Date(), + callbacks: {}, + panels, + name: getCurrentUser()?.displayName, + } + }, + computed: { + greeting() { + const time = this.timer.getHours() + + if (time > 18) { + return t('dashboard', '🌙 Good evening') + } + if (time > 12) { + return t('dashboard', '☀ Good afternoon') + } + if (time === 12) { + return t('dashboard', '🍽 Time for lunch') + } + return t('dashboard', '🌄 Good morning') + }, + }, + watch: { + callbacks() { + for (const app in this.callbacks) { + const element = this.$refs[app] + if (this.panels[app].mounted) { + return + } + + if (element) { + this.callbacks[app](element[0]) + Vue.set(this.panels[app], 'mounted', true) + } else { + console.error('Failed to register panel in the frontend as no backend data was provided for ' + app) + } + } + }, + }, + mounted() { + setInterval(() => { + this.timer = new Date() + }, 30000) + }, + methods: { + register(app, callback) { + Vue.set(this.callbacks, app, callback) + }, + }, +} +</script> + +<style lang="scss" scoped> + #app-dashboard { + width: 100%; + padding-left: 50px; + padding-right: 50px; + } + h2 { + text-align: center; + padding: 40px; + } + + .panels { + width: 100%; + display: flex; + justify-content: center; + } + + .panel { + width: 250px; + margin: 0 30px 30px 0; + + &:first-child { + margin-left: 30px; + } + + h3 { + position: sticky; + top: 50px; + margin-top: 0; + background-position: 10px 32px; + padding: 30px 12px 12px 35px; + background-color: var(--color-main-background); + } + + } + +</style> diff --git a/apps/dashboard/src/main.js b/apps/dashboard/src/main.js new file mode 100644 index 00000000000..998f538356b --- /dev/null +++ b/apps/dashboard/src/main.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import App from './App.vue' + +const Dashboard = Vue.extend(App) +const Instance = new Dashboard({}).$mount('#app') + +window.OCA.Dashboard = { + register: (app, callback) => Instance.register(app, callback), +} diff --git a/apps/dashboard/templates/index.php b/apps/dashboard/templates/index.php new file mode 100644 index 00000000000..b9e614b0f1c --- /dev/null +++ b/apps/dashboard/templates/index.php @@ -0,0 +1,4 @@ +<?php + \OC_Util::addScript('dashboard', 'dashboard'); +?> +<div id="app"></div> diff --git a/apps/dashboard/webpack.js b/apps/dashboard/webpack.js new file mode 100644 index 00000000000..ac455498920 --- /dev/null +++ b/apps/dashboard/webpack.js @@ -0,0 +1,11 @@ +const path = require('path') + +module.exports = { + entry: path.join(__dirname, 'src', 'main.js'), + output: { + path: path.resolve(__dirname, './js'), + publicPath: '/js/', + filename: 'dashboard.js', + jsonpFunction: 'webpackJsonpDashboard' + } +} diff --git a/webpack.common.js b/webpack.common.js index ee8db43e728..249647c3146 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -6,6 +6,7 @@ const { VueLoaderPlugin } = require('vue-loader') const accessibility = require('./apps/accessibility/webpack') const comments = require('./apps/comments/webpack') const core = require('./core/webpack') +const dashboard = require('./apps/dashboard/webpack') const files = require('./apps/files/webpack') const files_sharing = require('./apps/files_sharing/webpack') const files_trashbin = require('./apps/files_trashbin/webpack') @@ -21,6 +22,7 @@ const modules = { accessibility, comments, core, + dashboard, files, files_sharing, files_trashbin, |