Skip to content

Commit 7c95d58

Browse files
authored
Merge pull request #5503 from LibreSign/feat/return-next-scheduled-date
feat: return next scheduled date
2 parents 4b91418 + 778c6f2 commit 7c95d58

File tree

9 files changed

+111
-14
lines changed

9 files changed

+111
-14
lines changed

lib/Controller/AdminController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace OCA\Libresign\Controller;
1010

11+
use DateTimeInterface;
1112
use OCA\Libresign\AppInfo\Application;
1213
use OCA\Libresign\Exception\LibresignException;
1314
use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory;
@@ -631,6 +632,9 @@ public function updateOID(string $oid): DataResponse {
631632
#[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/admin/reminder', requirements: ['apiVersion' => '(v1)'])]
632633
public function reminderFetch(): DataResponse {
633634
$response = $this->reminderService->getSettings();
635+
if ($response['next_run'] instanceof \DateTime) {
636+
$response['next_run'] = $response['next_run']->format(DateTimeInterface::ATOM);
637+
}
634638
return new DataResponse($response);
635639
}
636640

@@ -653,6 +657,9 @@ public function reminderSave(
653657
string $sendTimer,
654658
): DataResponse {
655659
$response = $this->reminderService->save($daysBefore, $daysBetween, $max, $sendTimer);
660+
if ($response['next_run'] instanceof \DateTime) {
661+
$response['next_run'] = $response['next_run']->format(DateTimeInterface::ATOM);
662+
}
656663
return new DataResponse($response);
657664
}
658665
}

lib/ResponseDefinitions.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
* days_between: non-negative-int,
241241
* max: non-negative-int,
242242
* send_timer: string,
243+
* next_run?: string,
243244
* }
244245
* @psalm-type LibresignCapabilities = array{
245246
* features: list<string>,

lib/Service/ReminderService.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace OCA\Libresign\Service;
1010

11+
use DateTime;
1112
use OCA\Libresign\AppInfo\Application;
1213
use OCA\Libresign\BackgroundJob\Reminder;
1314
use OCA\Libresign\Db\SignRequestMapper;
@@ -29,12 +30,18 @@ public function __construct(
2930
}
3031

3132
public function getSettings(): array {
32-
return [
33+
$settings = [
3334
'days_before' => $this->appConfig->getValueInt(Application::APP_ID, 'reminder_days_before', 0),
3435
'days_between' => $this->appConfig->getValueInt(Application::APP_ID, 'reminder_days_between', 0),
3536
'max' => $this->appConfig->getValueInt(Application::APP_ID, 'reminder_max', 0),
3637
'send_timer' => $this->appConfig->getValueString(Application::APP_ID, 'reminder_send_timer', '10:00'),
38+
'next_run' => null,
3739
];
40+
foreach ($this->jobList->getJobsIterator(Reminder::class, 1, 0) as $job) {
41+
$details = $this->jobList->getDetailsById($job->getId());
42+
$settings['next_run'] = new \DateTime('@' . $details['last_checked'], new \DateTimeZone('UTC'));
43+
}
44+
return $settings;
3845
}
3946

4047
public function save(
@@ -44,7 +51,7 @@ public function save(
4451
string $sendTimer,
4552
): array {
4653
$config = $this->saveConfig($daysBefore, $daysBetween, $max, $sendTimer);
47-
$this->scheduleJob($config['send_timer']);
54+
$config['next_run'] = $this->scheduleJob($config['send_timer']);
4855
return $config;
4956
}
5057

@@ -106,20 +113,24 @@ private function setIfChangedString(string $key, string $value, string $default
106113
}
107114
}
108115

109-
protected function scheduleJob(string $startTime): void {
116+
protected function scheduleJob(string $startTime): ?DateTime {
110117
$this->jobList->remove(
111118
Reminder::class,
112119
);
113120

121+
if ($startTime === '') {
122+
return null;
123+
}
114124
$runAfter = $this->getStartTime($startTime);
115125
if (!$runAfter) {
116-
return;
126+
return null;
117127
}
118128

119129
$this->jobList->scheduleAfter(
120130
Reminder::class,
121131
$runAfter->getTimestamp(),
122132
);
133+
return $runAfter;
123134
}
124135

125136
protected function getStartTime(string $startTime): ?\DateTime {

openapi-administration.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@
225225
},
226226
"send_timer": {
227227
"type": "string"
228+
},
229+
"next_run": {
230+
"type": "string"
228231
}
229232
}
230233
},

openapi-full.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,9 @@
665665
},
666666
"send_timer": {
667667
"type": "string"
668+
},
669+
"next_run": {
670+
"type": "string"
668671
}
669672
}
670673
},

src/types/openapi/openapi-administration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ export type components = {
351351
/** Format: int64 */
352352
max: number;
353353
send_timer: string;
354+
next_run?: string;
354355
};
355356
RootCertificate: {
356357
commonName: string;

src/types/openapi/openapi-full.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,7 @@ export type components = {
14251425
/** Format: int64 */
14261426
max: number;
14271427
send_timer: string;
1428+
next_run?: string;
14281429
};
14291430
RootCertificate: {
14301431
commonName: string;

src/views/Settings/Reminders.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
class="settings-section__loading-icon"
1515
:size="20" />
1616
<div v-if="reminderState">
17+
{{ t('libresign', 'Next job execution: {date}', {date: nextRunFormatted}) }}
1718
<NcTextField :value.sync="reminderDaysBefore"
1819
:label="t('libresign', 'First reminder after (days)')"
1920
:placeholder="t('libresign', 'First reminder after (days)')"
@@ -61,6 +62,7 @@ import debounce from 'debounce'
6162
6263
import axios from '@nextcloud/axios'
6364
import { translate as t } from '@nextcloud/l10n'
65+
import Moment from '@nextcloud/moment'
6466
import { generateOcsUrl } from '@nextcloud/router'
6567
6668
import { NcDateTimePickerNative } from '@nextcloud/vue'
@@ -100,6 +102,7 @@ export default {
100102
previousReminderMax: 0,
101103
displaySuccessReminderMax: false,
102104
reminderState: false,
105+
nextRun: null,
103106
loading: false,
104107
}
105108
},
@@ -111,6 +114,13 @@ export default {
111114
reminderState: this.reminderState ? t('libresign', 'off') : t('libresign', 'on'),
112115
})
113116
},
117+
nextRunFormatted() {
118+
if (this.nextRun) {
119+
return this.dateFromSqlAnsi(this.nextRun)
120+
}
121+
// TRANSLATORS No next reminder job to signers is scheduled
122+
return t('libresign', 'Not scheduled')
123+
},
114124
},
115125
watch: {
116126
reminderState(reminderState) {
@@ -128,6 +138,9 @@ export default {
128138
this.getData()
129139
},
130140
methods: {
141+
dateFromSqlAnsi(date) {
142+
return Moment(Date.parse(date)).format('LL LTS')
143+
},
131144
async getData() {
132145
this.loading = true
133146
@@ -148,6 +161,7 @@ export default {
148161
this.reminderState = this.reminderDaysBefore > 0
149162
|| this.reminderDaysBetween > 0
150163
|| this.max > 0
164+
this.nextRun = response.next_run
151165
})
152166
.finally(() => {
153167
this.loading = false
@@ -194,6 +208,7 @@ export default {
194208
this.displaySuccessReminderSendTimer = true
195209
setTimeout(() => { this.displaySuccessReminderSendTimer = false }, 2000)
196210
}
211+
this.nextRun = response.next_run
197212
})
198213
}, 1000),
199214
formatHourMinute(date) {

tests/php/Unit/Service/ReminderServiceTest.php

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,42 +347,97 @@ public function testSave(
347347
}
348348

349349
public static function providerSave(): array {
350+
$now = (new DateTime());
350351
return [
351352
[
352353
'daysBefore' => 0, 'daysBetween' => 0, 'max' => 0, 'sendTimer' => '',
353-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
354+
'expected' => [
355+
'days_before' => 0,
356+
'days_between' => 0,
357+
'max' => 0,
358+
'next_run' => null,
359+
'send_timer' => '',
360+
],
354361
],
355362
[
356363
'daysBefore' => 0, 'daysBetween' => 0, 'max' => 1, 'sendTimer' => '',
357-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
364+
'expected' => [
365+
'days_before' => 0,
366+
'days_between' => 0,
367+
'max' => 0,
368+
'next_run' => null,
369+
'send_timer' => '',
370+
],
358371
],
359372
[
360373
'daysBefore' => 0, 'daysBetween' => 1, 'max' => 0, 'sendTimer' => '',
361-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
374+
'expected' => [
375+
'days_before' => 0,
376+
'days_between' => 0,
377+
'max' => 0,
378+
'next_run' => null,
379+
'send_timer' => '',
380+
],
362381
],
363382
[
364383
'daysBefore' => 0, 'daysBetween' => 1, 'max' => 1, 'sendTimer' => '',
365-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
384+
'expected' => [
385+
'days_before' => 0,
386+
'days_between' => 0,
387+
'max' => 0,
388+
'next_run' => null,
389+
'send_timer' => '',
390+
],
366391
],
367392
[
368393
'daysBefore' => 1, 'daysBetween' => 0, 'max' => 0, 'sendTimer' => '',
369-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
394+
'expected' => [
395+
'days_before' => 0,
396+
'days_between' => 0,
397+
'max' => 0,
398+
'next_run' => null,
399+
'send_timer' => '',
400+
],
370401
],
371402
[
372403
'daysBefore' => 1, 'daysBetween' => 1, 'max' => 0, 'sendTimer' => '',
373-
'expected' => ['days_before' => 0, 'days_between' => 0, 'max' => 0, 'send_timer' => ''],
404+
'expected' => [
405+
'days_before' => 0,
406+
'days_between' => 0,
407+
'max' => 0,
408+
'next_run' => null,
409+
'send_timer' => '',
410+
],
374411
],
375412
[
376413
'daysBefore' => 1, 'daysBetween' => 1, 'max' => 1, 'sendTimer' => '',
377-
'expected' => ['days_before' => 1, 'days_between' => 1, 'max' => 1, 'send_timer' => '10:00'],
414+
'expected' => [
415+
'days_before' => 1,
416+
'days_between' => 1,
417+
'max' => 1,
418+
'next_run' => (clone $now)->modify('+1 day')->setTime(10, 0),
419+
'send_timer' => '10:00',
420+
],
378421
],
379422
[
380-
'daysBefore' => 1, 'daysBetween' => 1, 'max' => 1, 'sendTimer' => '11:05:00',
381-
'expected' => ['days_before' => 1, 'days_between' => 1, 'max' => 1, 'send_timer' => '10:00'],
423+
'daysBefore' => 1, 'daysBetween' => 1, 'max' => 1, 'sendTimer' => '11:05:00', // Invalid timer, need to be HH:mm
424+
'expected' => [
425+
'days_before' => 1,
426+
'days_between' => 1,
427+
'max' => 1,
428+
'next_run' => (clone $now)->modify('+1 day')->setTime(10, 0),
429+
'send_timer' => '10:00',
430+
],
382431
],
383432
[
384433
'daysBefore' => 1, 'daysBetween' => 1, 'max' => 1, 'sendTimer' => '11:05',
385-
'expected' => ['days_before' => 1, 'days_between' => 1, 'max' => 1, 'send_timer' => '11:05'],
434+
'expected' => [
435+
'days_before' => 1,
436+
'days_between' => 1,
437+
'max' => 1,
438+
'next_run' => (clone $now)->modify('+1 day')->setTime(11, 5),
439+
'send_timer' => '11:05',
440+
],
386441
],
387442
];
388443
}

0 commit comments

Comments
 (0)