Implement dashboard
Signed-off-by: Jakob Röhrl <jakob.roehrl@web.de>
This commit is contained in:
parent
1e938f3831
commit
1c4ea0e28b
3
Makefile
3
Makefile
|
@ -91,6 +91,9 @@ clean:
|
|||
rm -f ./js/tasks-main.js
|
||||
rm -f ./js/tasks-main.js.map
|
||||
rm -f ./js/tasks-main.js.LICENSE.txt
|
||||
rm -f ./js/tasks-dashboard.js
|
||||
rm -f ./js/tasks-dashboard.js.map
|
||||
rm -f ./js/tasks-dashboard.js.LICENSE.txt
|
||||
rm -rf $(build_directory)
|
||||
|
||||
# Same as clean but also removes dependencies installed by npm
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="32px" height="32px" enable-background="new 0 0 32 32" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m14.383 26.764s0.259-0.716 0.563-1.367c4.908-10.57 11.212-17.53 14.008-20.69 2.264-2.559 1.378-2.156 0.375-1.503-4.09 2.659-11.742 11.206-14.668 14.169-0.542 0.545-1.769 1.833-2.045 1.833-0.313 0-1.358-0.481-1.955-0.833-2.282-1.338-4.464-2.643-5.834-3.136-2.917-1.049-2.092-0.052-1.926 0.281 0.521 1.042 7.566 6.689 9.899 9.356 0.722 0.824 1.583 1.89 1.583 1.89z" fill="#000" stroke="#000" stroke-miterlimit="10" stroke-width=".75"/>
|
||||
</svg>
|
After Width: | Height: | Size: 662 B |
|
@ -22,14 +22,28 @@
|
|||
|
||||
namespace OCA\Tasks\AppInfo;
|
||||
|
||||
use OCA\Tasks\Dashboard\TasksWidget;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||
|
||||
class Application extends App {
|
||||
class Application extends App implements IBootstrap {
|
||||
|
||||
/** @var string */
|
||||
public const APP_ID = 'tasks';
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(array $params=[]) {
|
||||
parent::__construct('tasks', $params);
|
||||
parent::__construct(self::APP_ID, $params);
|
||||
}
|
||||
|
||||
public function register(IRegistrationContext $context): void {
|
||||
$context->registerDashboardWidget(TasksWidget::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @author Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @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\Tasks\Dashboard;
|
||||
|
||||
use OCA\Tasks\AppInfo\Application;
|
||||
use OCP\Dashboard\IWidget;
|
||||
use OCP\IL10N;
|
||||
|
||||
class TasksWidget implements IWidget {
|
||||
|
||||
/**
|
||||
* @var IL10N
|
||||
*/
|
||||
private $l10n;
|
||||
|
||||
/**
|
||||
* TasksWidget constructor.
|
||||
* @param IL10N $l10n
|
||||
*/
|
||||
public function __construct(IL10N $l10n) {
|
||||
$this->l10n = $l10n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getId(): string {
|
||||
return Application::APP_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getTitle(): string {
|
||||
return $this->l10n->t('Upcoming tasks');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getOrder(): int {
|
||||
return 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIconClass(): string {
|
||||
return 'icon-tasks';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getUrl(): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function load(): void {
|
||||
\OCP\Util::addScript('tasks', 'tasks-dashboard');
|
||||
}
|
||||
}
|
|
@ -8,13 +8,16 @@
|
|||
"version": "0.13.6",
|
||||
"license": "AGPLv3",
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^1.3.0",
|
||||
"@nextcloud/axios": "^1.6.0",
|
||||
"@nextcloud/dialogs": "^3.1.2",
|
||||
"@nextcloud/event-bus": "^2.0.0",
|
||||
"@nextcloud/initial-state": "1.2.0",
|
||||
"@nextcloud/l10n": "^1.4.1",
|
||||
"@nextcloud/moment": "^1.1.1",
|
||||
"@nextcloud/router": "^2.0.0",
|
||||
"@nextcloud/vue": "^4.0.2",
|
||||
"@nextcloud/vue-dashboard": "^2.0.1",
|
||||
"@vue/test-utils": "^1.2.1",
|
||||
"cdav-library": "github:nextcloud/cdav-library",
|
||||
"color-convert": "^2.0.1",
|
||||
|
@ -2792,6 +2795,128 @@
|
|||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/vue-dashboard/-/vue-dashboard-2.0.1.tgz",
|
||||
"integrity": "sha512-eLzdK8Ey5rrs3D6i2OAA5jkZ6lklrAbfnRgL40tZLIJ+MEKvRuPOjwrzhJKxHgVp3rU1rEgkaaPvSNXRVGS1mQ==",
|
||||
"dependencies": {
|
||||
"@nextcloud/vue": "^3.1.1",
|
||||
"core-js": "^3.6.4",
|
||||
"vue": "^2.6.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nextcloud/vue": "^3.1.1",
|
||||
"vue": "^2.6.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/@nextcloud/event-bus": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-1.3.0.tgz",
|
||||
"integrity": "sha512-+U5MnCvfnNWvf0lvdqJg8F+Nm8wN+s9ayuBjtiEQxTAcootv7lOnlMgfreqF3l2T0Wet2uZh4JbFVUWf8l3w7g==",
|
||||
"dependencies": {
|
||||
"@types/semver": "^7.3.5",
|
||||
"core-js": "^3.11.2",
|
||||
"semver": "^7.3.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/@nextcloud/router": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-1.2.0.tgz",
|
||||
"integrity": "sha512-kn9QsL9LuhkIMaSSgdiqRL3SZ6PatuAjXUiyq343BbSnI99Oc5eJH8kU6cT2AHije7wKy/tK8Xe3VQuVO32SZQ==",
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/@nextcloud/vue": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-3.10.1.tgz",
|
||||
"integrity": "sha512-DdnnEFxt5FuZOtAD1x7hSDFVQF9KVVgQtFKwzs2ySNbyIx8rfRfc6noC7JbMAPR1LyPegCst0bVwQIfqsASGog==",
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^1.2.3",
|
||||
"@nextcloud/axios": "^1.3.2",
|
||||
"@nextcloud/browser-storage": "^0.1.1",
|
||||
"@nextcloud/capabilities": "^1.0.2",
|
||||
"@nextcloud/dialogs": "^3.0.0",
|
||||
"@nextcloud/event-bus": "^1.1.4",
|
||||
"@nextcloud/l10n": "^1.2.3",
|
||||
"@nextcloud/router": "^1.0.2",
|
||||
"core-js": "^3.6.5",
|
||||
"debounce": "1.2.1",
|
||||
"emoji-mart-vue-fast": "^7.0.7",
|
||||
"escape-html": "^1.0.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"linkifyjs": "~2.1.9",
|
||||
"md5": "^2.2.1",
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"string-length": "^4.0.1",
|
||||
"striptags": "^3.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"tributejs": "^5.1.3",
|
||||
"v-click-outside": "^3.0.1",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-color": "^2.7.1",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vue-visible": "^1.0.2",
|
||||
"vue2-datepicker": "^3.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/string-length": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
|
||||
"integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
|
||||
"dependencies": {
|
||||
"char-regex": "^1.0.2",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextcloud/vue-dashboard/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/@nextcloud/webpack-vue-config": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/webpack-vue-config/-/webpack-vue-config-4.0.3.tgz",
|
||||
|
@ -3480,7 +3605,6 @@
|
|||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -7502,6 +7626,7 @@
|
|||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
@ -14595,7 +14720,6 @@
|
|||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
},
|
||||
|
@ -18850,6 +18974,105 @@
|
|||
"vue2-datepicker": "^3.6.3"
|
||||
}
|
||||
},
|
||||
"@nextcloud/vue-dashboard": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/vue-dashboard/-/vue-dashboard-2.0.1.tgz",
|
||||
"integrity": "sha512-eLzdK8Ey5rrs3D6i2OAA5jkZ6lklrAbfnRgL40tZLIJ+MEKvRuPOjwrzhJKxHgVp3rU1rEgkaaPvSNXRVGS1mQ==",
|
||||
"requires": {
|
||||
"@nextcloud/vue": "^3.1.1",
|
||||
"core-js": "^3.6.4",
|
||||
"vue": "^2.6.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/event-bus": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-1.3.0.tgz",
|
||||
"integrity": "sha512-+U5MnCvfnNWvf0lvdqJg8F+Nm8wN+s9ayuBjtiEQxTAcootv7lOnlMgfreqF3l2T0Wet2uZh4JbFVUWf8l3w7g==",
|
||||
"requires": {
|
||||
"@types/semver": "^7.3.5",
|
||||
"core-js": "^3.11.2",
|
||||
"semver": "^7.3.5"
|
||||
}
|
||||
},
|
||||
"@nextcloud/router": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-1.2.0.tgz",
|
||||
"integrity": "sha512-kn9QsL9LuhkIMaSSgdiqRL3SZ6PatuAjXUiyq343BbSnI99Oc5eJH8kU6cT2AHije7wKy/tK8Xe3VQuVO32SZQ==",
|
||||
"requires": {
|
||||
"core-js": "^3.6.4"
|
||||
}
|
||||
},
|
||||
"@nextcloud/vue": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-3.10.1.tgz",
|
||||
"integrity": "sha512-DdnnEFxt5FuZOtAD1x7hSDFVQF9KVVgQtFKwzs2ySNbyIx8rfRfc6noC7JbMAPR1LyPegCst0bVwQIfqsASGog==",
|
||||
"requires": {
|
||||
"@nextcloud/auth": "^1.2.3",
|
||||
"@nextcloud/axios": "^1.3.2",
|
||||
"@nextcloud/browser-storage": "^0.1.1",
|
||||
"@nextcloud/capabilities": "^1.0.2",
|
||||
"@nextcloud/dialogs": "^3.0.0",
|
||||
"@nextcloud/event-bus": "^1.1.4",
|
||||
"@nextcloud/l10n": "^1.2.3",
|
||||
"@nextcloud/router": "^1.0.2",
|
||||
"core-js": "^3.6.5",
|
||||
"debounce": "1.2.1",
|
||||
"emoji-mart-vue-fast": "^7.0.7",
|
||||
"escape-html": "^1.0.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"linkifyjs": "~2.1.9",
|
||||
"md5": "^2.2.1",
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"string-length": "^4.0.1",
|
||||
"striptags": "^3.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"tributejs": "^5.1.3",
|
||||
"v-click-outside": "^3.0.1",
|
||||
"v-tooltip": "^2.0.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-color": "^2.7.1",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vue-visible": "^1.0.2",
|
||||
"vue2-datepicker": "^3.6.3"
|
||||
}
|
||||
},
|
||||
"char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"string-length": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
|
||||
"integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
|
||||
"requires": {
|
||||
"char-regex": "^1.0.2",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nextcloud/webpack-vue-config": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/webpack-vue-config/-/webpack-vue-config-4.0.3.tgz",
|
||||
|
@ -19451,8 +19674,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
|
@ -20357,7 +20579,7 @@
|
|||
"cdav-library": {
|
||||
"version": "git+ssh://git@github.com/nextcloud/cdav-library.git#a8e1b3fa505ee2e457b2318b16de3795cbca06c3",
|
||||
"integrity": "sha512-BNN7nU2t60dyUCidZ97QjsmZNIvDaWHVET27OQP4X5Zbgq0aIENXlZMdJidEwNYQqQ1DWMtBr5tiOriNeI5ArA==",
|
||||
"from": "cdav-library@github:nextcloud/cdav-library#a8e1b3fa505ee2e457b2318b16de3795cbca06c3",
|
||||
"from": "cdav-library@github:nextcloud/cdav-library",
|
||||
"requires": {
|
||||
"core-js": "^3.14.0",
|
||||
"regenerator-runtime": "^0.13.7"
|
||||
|
@ -22634,6 +22856,7 @@
|
|||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
|
@ -28044,7 +28267,6 @@
|
|||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
|
|
|
@ -26,13 +26,16 @@
|
|||
"bugs": "https://github.com/nextcloud/tasks/issues",
|
||||
"contributors": [],
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^1.3.0",
|
||||
"@nextcloud/axios": "^1.6.0",
|
||||
"@nextcloud/dialogs": "^3.1.2",
|
||||
"@nextcloud/event-bus": "^2.0.0",
|
||||
"@nextcloud/initial-state": "1.2.0",
|
||||
"@nextcloud/l10n": "^1.4.1",
|
||||
"@nextcloud/moment": "^1.1.1",
|
||||
"@nextcloud/router": "^2.0.0",
|
||||
"@nextcloud/vue": "^4.0.2",
|
||||
"@nextcloud/vue-dashboard": "^2.0.1",
|
||||
"@vue/test-utils": "^1.2.1",
|
||||
"cdav-library": "github:nextcloud/cdav-library",
|
||||
"color-convert": "^2.0.1",
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.icon-tasks {
|
||||
background-image: url(./../../img/tasks-dark.svg);
|
||||
}
|
||||
|
||||
body.dark .icon-tasks {
|
||||
background-image: url(./../../img/tasks.svg);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @author Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import Dashboard from './views/Dashboard'
|
||||
import store from './store/store.js'
|
||||
|
||||
import './css/dashboard.scss'
|
||||
|
||||
import { generateFilePath } from '@nextcloud/router'
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
// eslint-disable-next-line
|
||||
__webpack_nonce__ = btoa(getRequestToken())
|
||||
|
||||
// eslint-disable-next-line
|
||||
__webpack_public_path__ = generateFilePath('tasks', '', 'js/')
|
||||
|
||||
Vue.prototype.t = translate
|
||||
Vue.prototype.n = translatePlural
|
||||
Vue.prototype.OC = OC
|
||||
Vue.prototype.OCA = OCA
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
OCA.Dashboard.register('tasks', (el) => {
|
||||
const View = Vue.extend(Dashboard)
|
||||
const vm = new View({
|
||||
propsData: {},
|
||||
store,
|
||||
}).$mount(el)
|
||||
return vm
|
||||
})
|
||||
})
|
|
@ -0,0 +1,180 @@
|
|||
<!--
|
||||
Nextcloud - Tasks
|
||||
|
||||
@author Jakob Röhrl
|
||||
@copyright 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
|
||||
@author Raimund Schlüßler
|
||||
@copyright 2021 Raimund Schlüßler <raimund.schluessler@mailbox.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or any later version.
|
||||
|
||||
This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
<template>
|
||||
<DashboardWidget
|
||||
id="tasks_panel"
|
||||
:items="tasks"
|
||||
empty-content-icon="icon-tasks"
|
||||
:empty-content-message="t('tasks', 'No upcoming tasks')"
|
||||
:show-more-text="t('tasks', 'upcoming tasks')"
|
||||
:loading="loading"
|
||||
:show-items-and-empty-content="!hasTaskToday"
|
||||
:half-empty-content-message="t('tasks', 'No tasks today')">
|
||||
<template #default="{ item }">
|
||||
<DashboardWidgetItem
|
||||
:main-text="item.summary"
|
||||
:sub-text="formatSubtext(item)"
|
||||
:target-url="getTasksAppUrl(item)">
|
||||
<template #avatar>
|
||||
<div
|
||||
class="calendar-dot"
|
||||
:style="{'background-color': item.calendar.color}"
|
||||
:title="item.calendar.displayName" />
|
||||
</template>
|
||||
</DashboardWidgetItem>
|
||||
</template>
|
||||
</DashboardWidget>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { sort, isTaskInList } from '../store/storeHelper.js'
|
||||
import client from '../services/cdav.js'
|
||||
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { DashboardWidget, DashboardWidgetItem } from '@nextcloud/vue-dashboard'
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
DashboardWidget,
|
||||
DashboardWidgetItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
tasks: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
calendars: state => state.calendars.calendars,
|
||||
}),
|
||||
hasTaskToday() {
|
||||
return this.tasks.some(task => isTaskInList(task, 'today'))
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initializeEnvironment()
|
||||
},
|
||||
methods: {
|
||||
async initializeEnvironment() {
|
||||
await client.connect({ enableCalDAV: true })
|
||||
await this.$store.dispatch('fetchCurrentUserPrincipal')
|
||||
const calendars = await this.$store.dispatch('getCalendars')
|
||||
const owners = []
|
||||
calendars.forEach((calendar) => {
|
||||
if (owners.indexOf(calendar.owner) === -1) {
|
||||
owners.push(calendar.owner)
|
||||
}
|
||||
})
|
||||
owners.forEach((owner) => {
|
||||
this.$store.dispatch('fetchPrincipalByUrl', {
|
||||
url: owner,
|
||||
})
|
||||
})
|
||||
// No calendars? Create a new one!
|
||||
if (calendars.length === 0) {
|
||||
let color = '#0082C9'
|
||||
if (this.$OCA.Theming) {
|
||||
color = this.$OCA.Theming.color
|
||||
}
|
||||
await this.$store.dispatch('appendCalendar', { displayName: translate('tasks', 'Tasks'), color })
|
||||
this.fetchTasks()
|
||||
// else, let's get those tasks!
|
||||
} else {
|
||||
this.fetchTasks()
|
||||
}
|
||||
},
|
||||
fetchTasks() {
|
||||
Promise.all(this.calendars.map(calendar =>
|
||||
this.$store.dispatch('getTasksFromCalendar', { calendar, completed: false, related: null })
|
||||
)).then(results => {
|
||||
this.tasks = sort([...results.flat().filter(task => !task.closed)])
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/**
|
||||
* @param {Object} task The task to format
|
||||
* @returns {String}
|
||||
*/
|
||||
formatSubtext(task) {
|
||||
if (!task.dueMoment.isValid()) {
|
||||
return translate('tasks', 'No due date assigned')
|
||||
}
|
||||
if (task.allDay) {
|
||||
return task.dueMoment.calendar(null, {
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
lastDay: translate('tasks', '[Due yesterday]'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
sameDay: translate('tasks', '[Due today]'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
nextDay: translate('tasks', '[Due tomorrow]'),
|
||||
lastWeek: translate('tasks', '[Due] L'),
|
||||
nextWeek: translate('tasks', '[Due] L'),
|
||||
sameElse: translate('tasks', '[Due] L'),
|
||||
})
|
||||
} else {
|
||||
return task.dueMoment.calendar(null, {
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
lastDay: translate('tasks', '[Due yesterday at] LT'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
sameDay: translate('tasks', '[Due today at] LT'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
nextDay: translate('tasks', '[Due tomorrow at] LT'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
lastWeek: translate('tasks', '[Due] L [at] LT'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
nextWeek: translate('tasks', '[Due] L [at] LT'),
|
||||
// TRANSLATORS This is a string for moment.js. The square brackets escape the string from moment.js. Please translate the string and keep the brackets.
|
||||
sameElse: translate('tasks', '[Due] L [at] LT'),
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {Object} task The task to generate the URL for
|
||||
* @returns {string}
|
||||
*/
|
||||
getTasksAppUrl(task) {
|
||||
return generateUrl('apps/tasks') + `/#/calendars/${task.calendar.id}/tasks/${task.uri}`
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#tasks_panel {
|
||||
.calendar-dot {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
margin-top: .2rem;
|
||||
border-radius: 50%;
|
||||
min-width: 1rem;
|
||||
min-height: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,3 +1,9 @@
|
|||
const webpackConfig = require('@nextcloud/webpack-vue-config')
|
||||
const path = require('path')
|
||||
|
||||
webpackConfig.entry = {
|
||||
...webpackConfig.entry,
|
||||
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
|
Loading…
Reference in New Issue