Skip to content

Commit

Permalink
Merge pull request #21346 from nextcloud/enh/20930/dashboard
Browse files Browse the repository at this point in the history
Dashboard API
  • Loading branch information
rullzer authored Jul 15, 2020
2 parents 24ec4a8 + 6b2bb32 commit f04f932
Show file tree
Hide file tree
Showing 32 changed files with 743 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
!/apps/cloud_federation_api
!/apps/comments
!/apps/contactsinteraction
!/apps/dashboard
!/apps/dav
!/apps/files
!/apps/federation
Expand Down
30 changes: 30 additions & 0 deletions apps/dashboard/appinfo/info.xml
Original file line number Diff line number Diff line change
@@ -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>
31 changes: 31 additions & 0 deletions apps/dashboard/appinfo/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

/**
* @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'],
]
];
1 change: 1 addition & 0 deletions apps/dashboard/img/dashboard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions apps/dashboard/js/dashboard.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/dashboard/js/dashboard.js.map

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions apps/dashboard/lib/Controller/DashboardController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

/**
* @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\RegisterPanelEvent;
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(
string $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 RegisterPanelEvent($this->dashboardManager));

$dashboardManager = $this->dashboardManager;
$panels = array_map(function (IPanel $panel) {
return [
'id' => $panel->getId(),
'title' => $panel->getTitle(),
'iconClass' => $panel->getIconClass(),
'url' => $panel->getUrl()
];
}, $dashboardManager->getPanels());
$this->inititalStateService->provideInitialState('dashboard', 'panels', $panels);

if (class_exists(LoadViewer::class)) {
$this->eventDispatcher->dispatchTyped(new LoadViewer());
}

return new TemplateResponse('dashboard', 'index');
}
}
126 changes: 126 additions & 0 deletions apps/dashboard/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<template>
<div id="app-dashboard">
<h2>{{ greeting.icon }} {{ greeting.text }}</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')
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 { icon: '🌙', text: t('dashboard', 'Good evening, {name}', { name: this.name }) }
}
if (time > 12) {
return { icon: '', text: t('dashboard', 'Good afternoon, {name}', { name: this.name }) }
}
if (time === 12) {
return { icon: '🍽', text: t('dashboard', 'Time for lunch, {name}', { name: this.name }) }
}
if (time > 5) {
return { icon: '🌄', text: t('dashboard', 'Good morning, {name}', { name: this.name }) }
}
return { icon: '🦉', text: t('dashboard', 'Have a night owl, {name}', { name: this.name }) }
},
},
watch: {
callbacks() {
for (const app in this.callbacks) {
const element = this.$refs[app]
if (this.panels[app].mounted) {
continue
}
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%;
}
h2 {
text-align: center;
font-size: 32px;
line-height: 130%;
padding: 80px 16px 32px;
}
.panels {
width: 100%;
display: flex;
justify-content: center;
flex-direction: row;
align-items: flex-start;
flex-wrap: wrap;
}
.panel {
width: 250px;
margin: 16px;
& > a {
position: sticky;
top: 50px;
display: block;
background: linear-gradient(var(--color-main-background-translucent), var(--color-main-background-translucent) 80%, rgba(255, 255, 255, 0));
backdrop-filter: blur(4px);
h3 {
margin: 0;
font-size: 20px;
font-weight: bold;
background-size: 32px;
background-position: 10px 10px;
padding: 16px 8px 16px 52px;
}
}
}
</style>
9 changes: 9 additions & 0 deletions apps/dashboard/src/main.js
Original file line number Diff line number Diff line change
@@ -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),
}
4 changes: 4 additions & 0 deletions apps/dashboard/templates/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php
\OCP\Util::addScript('dashboard', 'dashboard');
?>
<div id="app"></div>
11 changes: 11 additions & 0 deletions apps/dashboard/webpack.js
Original file line number Diff line number Diff line change
@@ -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'
}
}
4 changes: 4 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,14 @@
'OCP\\Dashboard\\Exceptions\\DashboardAppNotAvailableException' => $baseDir . '/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php',
'OCP\\Dashboard\\IDashboardManager' => $baseDir . '/lib/public/Dashboard/IDashboardManager.php',
'OCP\\Dashboard\\IDashboardWidget' => $baseDir . '/lib/public/Dashboard/IDashboardWidget.php',
'OCP\\Dashboard\\IManager' => $baseDir . '/lib/public/Dashboard/IManager.php',
'OCP\\Dashboard\\IPanel' => $baseDir . '/lib/public/Dashboard/IPanel.php',
'OCP\\Dashboard\\Model\\IWidgetConfig' => $baseDir . '/lib/public/Dashboard/Model/IWidgetConfig.php',
'OCP\\Dashboard\\Model\\IWidgetRequest' => $baseDir . '/lib/public/Dashboard/Model/IWidgetRequest.php',
'OCP\\Dashboard\\Model\\WidgetSetting' => $baseDir . '/lib/public/Dashboard/Model/WidgetSetting.php',
'OCP\\Dashboard\\Model\\WidgetSetup' => $baseDir . '/lib/public/Dashboard/Model/WidgetSetup.php',
'OCP\\Dashboard\\Model\\WidgetTemplate' => $baseDir . '/lib/public/Dashboard/Model/WidgetTemplate.php',
'OCP\\Dashboard\\RegisterPanelEvent' => $baseDir . '/lib/public/Dashboard/RegisterPanelEvent.php',
'OCP\\Dashboard\\Service\\IEventsService' => $baseDir . '/lib/public/Dashboard/Service/IEventsService.php',
'OCP\\Dashboard\\Service\\IWidgetsService' => $baseDir . '/lib/public/Dashboard/Service/IWidgetsService.php',
'OCP\\Defaults' => $baseDir . '/lib/public/Defaults.php',
Expand Down Expand Up @@ -942,6 +945,7 @@
'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\SetTransactionIsolationLevel' => $baseDir . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\Dashboard\\DashboardManager' => $baseDir . '/lib/private/Dashboard/DashboardManager.php',
'OC\\Dashboard\\Manager' => $baseDir . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => $baseDir . '/lib/private/DatabaseException.php',
'OC\\DatabaseSetupException' => $baseDir . '/lib/private/DatabaseSetupException.php',
'OC\\DateTimeFormatter' => $baseDir . '/lib/private/DateTimeFormatter.php',
Expand Down
4 changes: 4 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,14 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Dashboard\\Exceptions\\DashboardAppNotAvailableException' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Exceptions/DashboardAppNotAvailableException.php',
'OCP\\Dashboard\\IDashboardManager' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IDashboardManager.php',
'OCP\\Dashboard\\IDashboardWidget' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IDashboardWidget.php',
'OCP\\Dashboard\\IManager' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IManager.php',
'OCP\\Dashboard\\IPanel' => __DIR__ . '/../../..' . '/lib/public/Dashboard/IPanel.php',
'OCP\\Dashboard\\Model\\IWidgetConfig' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/IWidgetConfig.php',
'OCP\\Dashboard\\Model\\IWidgetRequest' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/IWidgetRequest.php',
'OCP\\Dashboard\\Model\\WidgetSetting' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetSetting.php',
'OCP\\Dashboard\\Model\\WidgetSetup' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetSetup.php',
'OCP\\Dashboard\\Model\\WidgetTemplate' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Model/WidgetTemplate.php',
'OCP\\Dashboard\\RegisterPanelEvent' => __DIR__ . '/../../..' . '/lib/public/Dashboard/RegisterPanelEvent.php',
'OCP\\Dashboard\\Service\\IEventsService' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Service/IEventsService.php',
'OCP\\Dashboard\\Service\\IWidgetsService' => __DIR__ . '/../../..' . '/lib/public/Dashboard/Service/IWidgetsService.php',
'OCP\\Defaults' => __DIR__ . '/../../..' . '/lib/public/Defaults.php',
Expand Down Expand Up @@ -971,6 +974,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php',
'OC\\DB\\SetTransactionIsolationLevel' => __DIR__ . '/../../..' . '/lib/private/DB/SetTransactionIsolationLevel.php',
'OC\\Dashboard\\DashboardManager' => __DIR__ . '/../../..' . '/lib/private/Dashboard/DashboardManager.php',
'OC\\Dashboard\\Manager' => __DIR__ . '/../../..' . '/lib/private/Dashboard/Manager.php',
'OC\\DatabaseException' => __DIR__ . '/../../..' . '/lib/private/DatabaseException.php',
'OC\\DatabaseSetupException' => __DIR__ . '/../../..' . '/lib/private/DatabaseSetupException.php',
'OC\\DateTimeFormatter' => __DIR__ . '/../../..' . '/lib/private/DateTimeFormatter.php',
Expand Down
7 changes: 7 additions & 0 deletions lib/private/AppFramework/Bootstrap/Coordinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\QueryException;
use OCP\Dashboard\IManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
use OCP\IServerContainer;
Expand All @@ -47,6 +48,9 @@ class Coordinator {
/** @var Registry */
private $registry;

/** @var IManager */
private $dashboardManager;

/** @var IEventDispatcher */
private $eventDispatcher;

Expand All @@ -58,10 +62,12 @@ class Coordinator {

public function __construct(IServerContainer $container,
Registry $registry,
IManager $dashboardManager,
IEventDispatcher $eventListener,
ILogger $logger) {
$this->serverContainer = $container;
$this->registry = $registry;
$this->dashboardManager = $dashboardManager;
$this->eventDispatcher = $eventListener;
$this->logger = $logger;
}
Expand Down Expand Up @@ -117,6 +123,7 @@ public function runRegistration(): void {
*/
$this->registrationContext->delegateCapabilityRegistrations($apps);
$this->registrationContext->delegateCrashReporterRegistrations($apps, $this->registry);
$this->registrationContext->delegateDashboardPanelRegistrations($apps, $this->dashboardManager);
$this->registrationContext->delegateEventListenerRegistrations($this->eventDispatcher);
$this->registrationContext->delegateContainerRegistrations($apps);
$this->registrationContext->delegateMiddlewareRegistrations($apps);
Expand Down
Loading

0 comments on commit f04f932

Please sign in to comment.