Add dashboard app
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
parent
544fcdb549
commit
5a1874910b
|
@ -17,6 +17,7 @@
|
||||||
!/apps/cloud_federation_api
|
!/apps/cloud_federation_api
|
||||||
!/apps/comments
|
!/apps/comments
|
||||||
!/apps/contactsinteraction
|
!/apps/contactsinteraction
|
||||||
|
!/apps/dashboard
|
||||||
!/apps/dav
|
!/apps/dav
|
||||||
!/apps/files
|
!/apps/files
|
||||||
!/apps/federation
|
!/apps/federation
|
||||||
|
|
|
@ -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');
|
|
@ -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>
|
|
@ -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'],
|
||||||
|
]
|
||||||
|
];
|
|
@ -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>
|
After Width: | Height: | Size: 244 B |
|
@ -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');
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
|
@ -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),
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?php
|
||||||
|
\OC_Util::addScript('dashboard', 'dashboard');
|
||||||
|
?>
|
||||||
|
<div id="app"></div>
|
|
@ -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'
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ const { VueLoaderPlugin } = require('vue-loader')
|
||||||
const accessibility = require('./apps/accessibility/webpack')
|
const accessibility = require('./apps/accessibility/webpack')
|
||||||
const comments = require('./apps/comments/webpack')
|
const comments = require('./apps/comments/webpack')
|
||||||
const core = require('./core/webpack')
|
const core = require('./core/webpack')
|
||||||
|
const dashboard = require('./apps/dashboard/webpack')
|
||||||
const files = require('./apps/files/webpack')
|
const files = require('./apps/files/webpack')
|
||||||
const files_sharing = require('./apps/files_sharing/webpack')
|
const files_sharing = require('./apps/files_sharing/webpack')
|
||||||
const files_trashbin = require('./apps/files_trashbin/webpack')
|
const files_trashbin = require('./apps/files_trashbin/webpack')
|
||||||
|
@ -21,6 +22,7 @@ const modules = {
|
||||||
accessibility,
|
accessibility,
|
||||||
comments,
|
comments,
|
||||||
core,
|
core,
|
||||||
|
dashboard,
|
||||||
files,
|
files,
|
||||||
files_sharing,
|
files_sharing,
|
||||||
files_trashbin,
|
files_trashbin,
|
||||||
|
|
Loading…
Reference in New Issue