add cron status badge to admin setting

Display  a info card in the settings, indicating when the last news update job ran.

Signed-off-by: Benjamin Brahmer <info@b-brahmer.de>
This commit is contained in:
Benjamin Brahmer 2023-03-05 12:02:38 +01:00
parent 0d31caac83
commit ea8002e2d9
7 changed files with 5327 additions and 2746 deletions

View File

@ -5,7 +5,8 @@ The format is mostly based on [Keep a Changelog](https://keepachangelog.com/en/1
# Unreleased
## [21.x.x]
### Changed
- Remove unused background job OCA\News\Cron\Updater
- Remove unused background job OCA\News\Cron\Updater (#2137)
- Add info card to the admin settings, showing last job execution (#2141)
### Fixed
# Releases

View File

@ -16,6 +16,9 @@ namespace OCA\News\Service;
use OCA\News\AppInfo\Application;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\BackgroundJob\IJobList;
use OCP\Util;
use OCA\News\Cron\UpdaterJob;
class StatusService
{
@ -25,14 +28,18 @@ class StatusService
private $appName;
/** @var IDBConnection */
private $connection;
/** @var IJobList */
private $jobList;
public function __construct(
IConfig $settings,
IDBConnection $connection
IDBConnection $connection,
IJobList $jobList
) {
$this->settings = $settings;
$this->connection = $connection;
$this->appName = Application::NAME;
$this->jobList = $jobList;
}
/**
@ -76,4 +83,22 @@ class StatusService
]
];
}
/**
* Get last update time
*/
public function getUpdateTime(): int
{
$time = 0;
[$major, $minor, $micro] = Util::getVersion();
if ($major >= 26) {
$myJobList = $this->jobList->getJobsIterator(UpdaterJob::class, 1, 0);
$time = $myJobList->current()->getLastRun();
}
return $time;
}
}

View File

@ -3,6 +3,7 @@
namespace OCA\News\Settings;
use OCA\News\AppInfo\Application;
use OCA\News\Service\StatusService;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\Settings\ISettings;
@ -17,11 +18,14 @@ class AdminSettings implements ISettings
private $config;
/** @var IInitialState */
private $initialState;
/** @var StatusService */
private $service;
public function __construct(IConfig $config, IInitialState $initialState)
public function __construct(IConfig $config, IInitialState $initialState, StatusService $service)
{
$this->config = $config;
$this->initialState = $initialState;
$this->service = $service;
}
public function getForm()
@ -33,6 +37,14 @@ class AdminSettings implements ISettings
(string)Application::DEFAULT_SETTINGS[$setting]
));
}
if ($this->service->isCronProperlyConfigured()) {
$lastUpdate = $this->service->getUpdateTime();
} else {
$lastUpdate = 0;
}
$this->initialState->provideInitialState("lastCron", $lastUpdate);
return new TemplateResponse(Application::NAME, 'admin', []);
}

7994
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,9 +27,10 @@
"@nextcloud/dialogs": "^3.1.4",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^1.6.0",
"@nextcloud/moment": "^1.2.1",
"@nextcloud/password-confirmation": "^1.0.1",
"@nextcloud/router": "^2.0.0",
"@nextcloud/vue": "^6.0.0-beta.4",
"@nextcloud/vue": "^7.8.0",
"vue": "^2.7.0"
},
"browserslist": [

View File

@ -7,6 +7,15 @@ SPDX-Licence-Identifier: AGPL-3.0-or-later
<NcSettingsSection :title="t('news', 'News')"
class="news-settings"
doc-url="https://nextcloud.github.io/news/admin/">
<template v-if="lastCron !== 0">
<NcNoteCard v-if="oldExecution" type="error">
{{ t('news', 'Last job execution ran {relativeTime}. Something seems wrong.', {relativeTime}) }}
</NcNoteCard>
<NcNoteCard v-else type="success">
{{ t('news', 'Last job ran {relativeTime}.', {relativeTime}) }}
</NcNoteCard>
</template>
<NcCheckboxRadioSwitch type="switch"
:checked.sync="useCronUpdates"
@update:checked="update('useCronUpdates', useCronUpdates)">
@ -57,6 +66,8 @@ SPDX-Licence-Identifier: AGPL-3.0-or-later
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
import moment from '@nextcloud/moment'
import { loadState } from '@nextcloud/initial-state'
import { showError, showSuccess } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios'
@ -78,6 +89,7 @@ function debounce(func, wait) {
}
const successMessage = debounce(() => showSuccess(t('news', 'Successfully updated news configuration')), 500)
const lastCron = loadState('news', 'lastCron')
export default {
name: 'AdminSettings',
@ -85,6 +97,7 @@ export default {
NcCheckboxRadioSwitch,
NcSettingsSection,
NcTextField,
NcNoteCard,
},
data() {
return {
@ -95,8 +108,15 @@ export default {
feedFetcherTimeout: loadState('news', 'feedFetcherTimeout'),
exploreUrl: loadState('news', 'exploreUrl'),
updateInterval: loadState('news', 'updateInterval'),
relativeTime: moment(lastCron * 1000).fromNow(),
lastCron,
}
},
computed: {
oldExecution() {
return Date.now() / 1000 - this.lastCron > (parseInt(this.updateInterval) * 2) + 900
},
},
methods: {
async update(key, value) {
await confirmPassword()

View File

@ -16,6 +16,7 @@ namespace OCA\News\Tests\Unit\Service;
use OCA\News\Service\StatusService;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\BackgroundJob\IJobList;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -37,6 +38,12 @@ class StatusServiceTest extends TestCase
*/
private $service;
/**
* @var IJobList
*/
private $jobList;
public function setUp(): void
{
$this->settings = $this->getMockBuilder(IConfig::class)
@ -45,7 +52,10 @@ class StatusServiceTest extends TestCase
$this->connection = $this->getMockBuilder(IDBConnection::class)
->disableOriginalConstructor()
->getMock();
$this->service = new StatusService($this->settings, $this->connection);
$this->jobList = $this->getMockBuilder(IJobList::class)
->disableOriginalConstructor()
->getMock();
$this->service = new StatusService($this->settings, $this->connection, $this->jobList);
}
public function testGetStatus()