@adminforth/background-jobs 1.8.1 → 1.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.woodpecker/release.yml +4 -4
- package/README.md +31 -0
- package/build.log +3 -2
- package/custom/GlobalJobApi.vue +27 -39
- package/custom/JobInfoPopup.vue +2 -2
- package/custom/JobsList.vue +2 -2
- package/custom/NavbarJobs.vue +1 -1
- package/custom/useBackgroundJobApi.ts +55 -0
- package/dist/custom/GlobalJobApi.vue +27 -39
- package/dist/custom/JobInfoPopup.vue +2 -2
- package/dist/custom/JobsList.vue +2 -2
- package/dist/custom/NavbarJobs.vue +1 -1
- package/dist/custom/useBackgroundJobApi.ts +55 -0
- package/dist/index.js +1 -1
- package/index.ts +2 -2
- package/package.json +36 -6
- package/types.ts +2 -1
package/.woodpecker/release.yml
CHANGED
|
@@ -17,18 +17,18 @@ steps:
|
|
|
17
17
|
- infisical export --domain https://vault.devforth.io/api --format=dotenv-export --env="prod" > /woodpecker/deploy.vault.env
|
|
18
18
|
|
|
19
19
|
build:
|
|
20
|
-
image:
|
|
20
|
+
image: devforth/node20-pnpm:latest
|
|
21
21
|
when:
|
|
22
22
|
- event: push
|
|
23
23
|
commands:
|
|
24
24
|
- apt update && apt install -y rsync
|
|
25
25
|
- . /woodpecker/deploy.vault.env
|
|
26
|
-
-
|
|
26
|
+
- pnpm install
|
|
27
27
|
- /bin/bash ./.woodpecker/buildRelease.sh
|
|
28
28
|
- npm audit signatures
|
|
29
29
|
|
|
30
30
|
release:
|
|
31
|
-
image:
|
|
31
|
+
image: devforth/node20-pnpm:latest
|
|
32
32
|
when:
|
|
33
33
|
- event:
|
|
34
34
|
- push
|
|
@@ -36,7 +36,7 @@ steps:
|
|
|
36
36
|
- main
|
|
37
37
|
commands:
|
|
38
38
|
- . /woodpecker/deploy.vault.env
|
|
39
|
-
-
|
|
39
|
+
- pnpm exec semantic-release
|
|
40
40
|
|
|
41
41
|
slack-on-failure:
|
|
42
42
|
image: curlimages/curl
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# AdminForth Background Jobs Plugin
|
|
2
|
+
|
|
3
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT" /> <img src="https://woodpecker.devforth.io/api/badges/3848/status.svg" alt="Build Status" /> <a href="https://www.npmjs.com/package/@adminforth/background-jobs"><img src="https://img.shields.io/npm/dm/@adminforth/background-jobs" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/@adminforth/background-jobs"><img src="https://img.shields.io/npm/v/@adminforth/background-jobs" alt="npm version" /></a>
|
|
4
|
+
|
|
5
|
+
[](https://tluma.ai/ask-ai/devforth/adminforth)
|
|
6
|
+
|
|
7
|
+
Lets you run and manage background jobs from AdminForth resources.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Run long tasks outside the request-response cycle.
|
|
12
|
+
- Manage background work directly from AdminForth resources.
|
|
13
|
+
- Keep admin operations responsive during heavy processing.
|
|
14
|
+
- Support repeatable job-based back-office workflows.
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
17
|
+
|
|
18
|
+
Full setup and configuration guide:
|
|
19
|
+
|
|
20
|
+
[AdminForth Background Jobs Documentation](https://adminforth.dev/docs/tutorial/Plugins/background-jobs/)
|
|
21
|
+
|
|
22
|
+
## About AdminForth
|
|
23
|
+
|
|
24
|
+
AdminForth is an open-source, agent-first admin framework for building robust admin panels and back-office applications faster.
|
|
25
|
+
|
|
26
|
+
## Related links
|
|
27
|
+
|
|
28
|
+
- [AdminForth website](https://adminforth.dev)
|
|
29
|
+
- [npm package](https://www.npmjs.com/package/@adminforth/background-jobs)
|
|
30
|
+
- [More AdminForth plugins](https://adminforth.dev/docs/tutorial/ListOfPlugins/)
|
|
31
|
+
- [Built by DevForth](https://devforth.io)
|
package/build.log
CHANGED
|
@@ -10,7 +10,8 @@ custom/JobsList.vue
|
|
|
10
10
|
custom/NavbarJobs.vue
|
|
11
11
|
custom/StateToIcon.vue
|
|
12
12
|
custom/tsconfig.json
|
|
13
|
+
custom/useBackgroundJobApi.ts
|
|
13
14
|
custom/utils.ts
|
|
14
15
|
|
|
15
|
-
sent
|
|
16
|
-
total size is
|
|
16
|
+
sent 18,463 bytes received 172 bytes 37,270.00 bytes/sec
|
|
17
|
+
total size is 17,830 speedup is 0.96
|
package/custom/GlobalJobApi.vue
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
ref="dialogRef"
|
|
6
6
|
removeFromDomOnClose
|
|
7
7
|
class="p-4"
|
|
8
|
-
:beforeCloseFunction="() => {
|
|
8
|
+
:beforeCloseFunction="() => { jobStore.clearCurrentJob(); jobStore.setIsOpened(false); }"
|
|
9
9
|
>
|
|
10
10
|
<JobInfoPopup
|
|
11
|
-
v-if="currentJob"
|
|
12
|
-
:job="currentJob"
|
|
11
|
+
v-if="jobStore.currentJob"
|
|
12
|
+
:job="jobStore.currentJob"
|
|
13
13
|
:meta="meta"
|
|
14
14
|
:closeModal="closeModal"
|
|
15
15
|
/>
|
|
@@ -18,14 +18,15 @@
|
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup lang="ts">
|
|
21
|
-
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
|
22
|
-
import { callAdminForthApi } from '@/utils';
|
|
23
|
-
import { useAdminforth } from '@/adminforth';
|
|
21
|
+
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
|
|
24
22
|
import { Modal } from '@/afcl';
|
|
25
23
|
import JobInfoPopup from './JobInfoPopup.vue';
|
|
26
24
|
import websocket from '@/websocket';
|
|
25
|
+
import { useBackgroundJobApi } from './useBackgroundJobApi';
|
|
27
26
|
|
|
28
|
-
const
|
|
27
|
+
const jobStore = useBackgroundJobApi();
|
|
28
|
+
|
|
29
|
+
const dialogRef = ref<any>(null);
|
|
29
30
|
|
|
30
31
|
const props = defineProps<{
|
|
31
32
|
meta: {
|
|
@@ -33,45 +34,35 @@ const props = defineProps<{
|
|
|
33
34
|
}
|
|
34
35
|
}>();
|
|
35
36
|
|
|
36
|
-
const dialogRef = ref<any>(null);
|
|
37
|
-
const currentJob = ref<any>(null);
|
|
38
37
|
|
|
39
38
|
function closeModal() {
|
|
40
39
|
if (!dialogRef.value) return;
|
|
41
40
|
if (typeof dialogRef.value.close === 'function') {
|
|
42
41
|
dialogRef.value.close();
|
|
42
|
+
jobStore.clearCurrentJob();
|
|
43
|
+
jobStore.setIsOpened(false);
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
if (typeof dialogRef.value.hide === 'function') {
|
|
47
|
+
jobStore.clearCurrentJob();
|
|
48
|
+
jobStore.setIsOpened(false);
|
|
46
49
|
dialogRef.value.hide();
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
method: 'POST',
|
|
56
|
-
body: { jobId },
|
|
57
|
-
});
|
|
58
|
-
if (res && res.ok) {
|
|
59
|
-
currentJob.value = res.job;
|
|
60
|
-
// open dialog
|
|
61
|
-
if (dialogRef.value && typeof dialogRef.value.open === 'function') {
|
|
62
|
-
dialogRef.value.open();
|
|
63
|
-
} else if (dialogRef.value && typeof dialogRef.value.show === 'function') {
|
|
64
|
-
dialogRef.value.show();
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
adminforth.alert({ variant: 'danger', message: res?.message || 'Failed to load job info' });
|
|
68
|
-
}
|
|
69
|
-
} catch (e) {
|
|
70
|
-
console.error('OpenJobInfoPopup error', e);
|
|
71
|
-
adminforth.alert({ variant: 'danger', message: 'Failed to load job info' });
|
|
53
|
+
watch(() => jobStore.isOpened, (newVal) => {
|
|
54
|
+
if (newVal) {
|
|
55
|
+
dialogRef.value?.open?.();
|
|
56
|
+
} else {
|
|
57
|
+
dialogRef.value?.close?.();
|
|
72
58
|
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
async function openJobInfo(jobId: string) {
|
|
62
|
+
jobStore.openJobInfoPopup(jobId);
|
|
73
63
|
}
|
|
74
64
|
|
|
65
|
+
|
|
75
66
|
onMounted(() => {
|
|
76
67
|
// expose global function
|
|
77
68
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -79,21 +70,18 @@ onMounted(() => {
|
|
|
79
70
|
window.OpenJobInfoPopup = openJobInfo;
|
|
80
71
|
|
|
81
72
|
websocket.subscribe('/background-jobs', (data) => {
|
|
82
|
-
if (data.jobId === currentJob
|
|
73
|
+
if (data.jobId === jobStore.currentJob?.id) {
|
|
83
74
|
if (data.status) {
|
|
84
|
-
|
|
75
|
+
jobStore.updateCurrentJob({ status: data.status });
|
|
85
76
|
}
|
|
86
77
|
if (data.progress !== undefined) {
|
|
87
|
-
|
|
78
|
+
jobStore.updateCurrentJob({ progress: data.progress });
|
|
88
79
|
}
|
|
89
80
|
if (data.finishedAt) {
|
|
90
|
-
|
|
81
|
+
jobStore.updateCurrentJob({ finishedAt: data.finishedAt });
|
|
91
82
|
}
|
|
92
83
|
if (data.state) {
|
|
93
|
-
|
|
94
|
-
...currentJob.value.state,
|
|
95
|
-
...data.state,
|
|
96
|
-
};
|
|
84
|
+
jobStore.updateCurrentJob({ state: { ...jobStore.currentJob?.state, ...data.state } });
|
|
97
85
|
}
|
|
98
86
|
}
|
|
99
87
|
});
|
package/custom/JobInfoPopup.vue
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
</Tooltip>
|
|
34
34
|
</div>
|
|
35
35
|
</div>
|
|
36
|
-
<div class="flex items-center gap-4 w-full">
|
|
36
|
+
<div class="flex items-center gap-4 w-full mt-4">
|
|
37
37
|
<ProgressBar
|
|
38
38
|
:current-value="job.progress"
|
|
39
39
|
:max-value="100"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
:showLabels="false"
|
|
43
43
|
:showValues="false"
|
|
44
44
|
:show-progress="false"
|
|
45
|
-
:height="
|
|
45
|
+
:height="3"
|
|
46
46
|
/>
|
|
47
47
|
<Button class="h-8" v-if="job.status === 'IN_PROGRESS'" @click="cancelJob"> {{ t('Cancel') }} </Button>
|
|
48
48
|
</div>
|
package/custom/JobsList.vue
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
ref="modalRef"
|
|
5
5
|
class="p-4"
|
|
6
6
|
v-for="job in props.jobs" :key="job.id"
|
|
7
|
-
:beforeCloseFunction="
|
|
8
|
-
:beforeOpenFunction="
|
|
7
|
+
:beforeCloseFunction="onBeforeClose"
|
|
8
|
+
:beforeOpenFunction="onBeforeOpen"
|
|
9
9
|
removeFromDomOnClose
|
|
10
10
|
>
|
|
11
11
|
<template #trigger>
|
package/custom/NavbarJobs.vue
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="cursor-pointer hover:scale-110 transition-transform" @click="isDropdownOpen = !isDropdownOpen">
|
|
4
4
|
<div class="relative flex items-center justify-center" v-if="jobs.length > 0">
|
|
5
5
|
<Tooltip>
|
|
6
|
-
<IconBriefcaseSolid class="w-7 h-7 text-
|
|
6
|
+
<IconBriefcaseSolid class="w-7 h-7 text-lightNavbarIcons dark:text-darkNavbarIcons" />
|
|
7
7
|
<template #tooltip>
|
|
8
8
|
{{ t('All jobs completed') }}
|
|
9
9
|
</template>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
import { callAdminForthApi } from '@/utils';
|
|
3
|
+
import { useAdminforth } from '@/adminforth';
|
|
4
|
+
import { defineStore } from 'pinia'
|
|
5
|
+
|
|
6
|
+
export const useBackgroundJobApi = defineStore('jobInfo', () => {
|
|
7
|
+
const currentJob = ref<any>(null);
|
|
8
|
+
const isOpened = ref(false);
|
|
9
|
+
const adminforth = useAdminforth();
|
|
10
|
+
|
|
11
|
+
async function openJobInfoPopup(jobId: string) {
|
|
12
|
+
if (!jobId) return null;
|
|
13
|
+
try {
|
|
14
|
+
const res = await callAdminForthApi({
|
|
15
|
+
path: `/plugin/get-background-job-info`,
|
|
16
|
+
method: 'POST',
|
|
17
|
+
body: { jobId },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (res && res.ok) {
|
|
21
|
+
currentJob.value = res.job;
|
|
22
|
+
isOpened.value = true;
|
|
23
|
+
return res.job;
|
|
24
|
+
} else {
|
|
25
|
+
adminforth.alert({ variant: 'danger', message: res?.message || 'Failed to load job info' });
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error('OpenJobInfoPopup error', e);
|
|
30
|
+
adminforth.alert({ variant: 'danger', message: 'Failed to load job info' });
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function setIsOpened(value: boolean) {
|
|
36
|
+
isOpened.value = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function clearCurrentJob() {
|
|
40
|
+
currentJob.value = null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function updateCurrentJob(jobData: any) {
|
|
44
|
+
currentJob.value = { ...currentJob.value, ...jobData };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
currentJob,
|
|
49
|
+
isOpened,
|
|
50
|
+
openJobInfoPopup,
|
|
51
|
+
setIsOpened,
|
|
52
|
+
clearCurrentJob,
|
|
53
|
+
updateCurrentJob
|
|
54
|
+
};
|
|
55
|
+
});
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
ref="dialogRef"
|
|
6
6
|
removeFromDomOnClose
|
|
7
7
|
class="p-4"
|
|
8
|
-
:beforeCloseFunction="() => {
|
|
8
|
+
:beforeCloseFunction="() => { jobStore.clearCurrentJob(); jobStore.setIsOpened(false); }"
|
|
9
9
|
>
|
|
10
10
|
<JobInfoPopup
|
|
11
|
-
v-if="currentJob"
|
|
12
|
-
:job="currentJob"
|
|
11
|
+
v-if="jobStore.currentJob"
|
|
12
|
+
:job="jobStore.currentJob"
|
|
13
13
|
:meta="meta"
|
|
14
14
|
:closeModal="closeModal"
|
|
15
15
|
/>
|
|
@@ -18,14 +18,15 @@
|
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup lang="ts">
|
|
21
|
-
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
|
22
|
-
import { callAdminForthApi } from '@/utils';
|
|
23
|
-
import { useAdminforth } from '@/adminforth';
|
|
21
|
+
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
|
|
24
22
|
import { Modal } from '@/afcl';
|
|
25
23
|
import JobInfoPopup from './JobInfoPopup.vue';
|
|
26
24
|
import websocket from '@/websocket';
|
|
25
|
+
import { useBackgroundJobApi } from './useBackgroundJobApi';
|
|
27
26
|
|
|
28
|
-
const
|
|
27
|
+
const jobStore = useBackgroundJobApi();
|
|
28
|
+
|
|
29
|
+
const dialogRef = ref<any>(null);
|
|
29
30
|
|
|
30
31
|
const props = defineProps<{
|
|
31
32
|
meta: {
|
|
@@ -33,45 +34,35 @@ const props = defineProps<{
|
|
|
33
34
|
}
|
|
34
35
|
}>();
|
|
35
36
|
|
|
36
|
-
const dialogRef = ref<any>(null);
|
|
37
|
-
const currentJob = ref<any>(null);
|
|
38
37
|
|
|
39
38
|
function closeModal() {
|
|
40
39
|
if (!dialogRef.value) return;
|
|
41
40
|
if (typeof dialogRef.value.close === 'function') {
|
|
42
41
|
dialogRef.value.close();
|
|
42
|
+
jobStore.clearCurrentJob();
|
|
43
|
+
jobStore.setIsOpened(false);
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
if (typeof dialogRef.value.hide === 'function') {
|
|
47
|
+
jobStore.clearCurrentJob();
|
|
48
|
+
jobStore.setIsOpened(false);
|
|
46
49
|
dialogRef.value.hide();
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
method: 'POST',
|
|
56
|
-
body: { jobId },
|
|
57
|
-
});
|
|
58
|
-
if (res && res.ok) {
|
|
59
|
-
currentJob.value = res.job;
|
|
60
|
-
// open dialog
|
|
61
|
-
if (dialogRef.value && typeof dialogRef.value.open === 'function') {
|
|
62
|
-
dialogRef.value.open();
|
|
63
|
-
} else if (dialogRef.value && typeof dialogRef.value.show === 'function') {
|
|
64
|
-
dialogRef.value.show();
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
adminforth.alert({ variant: 'danger', message: res?.message || 'Failed to load job info' });
|
|
68
|
-
}
|
|
69
|
-
} catch (e) {
|
|
70
|
-
console.error('OpenJobInfoPopup error', e);
|
|
71
|
-
adminforth.alert({ variant: 'danger', message: 'Failed to load job info' });
|
|
53
|
+
watch(() => jobStore.isOpened, (newVal) => {
|
|
54
|
+
if (newVal) {
|
|
55
|
+
dialogRef.value?.open?.();
|
|
56
|
+
} else {
|
|
57
|
+
dialogRef.value?.close?.();
|
|
72
58
|
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
async function openJobInfo(jobId: string) {
|
|
62
|
+
jobStore.openJobInfoPopup(jobId);
|
|
73
63
|
}
|
|
74
64
|
|
|
65
|
+
|
|
75
66
|
onMounted(() => {
|
|
76
67
|
// expose global function
|
|
77
68
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -79,21 +70,18 @@ onMounted(() => {
|
|
|
79
70
|
window.OpenJobInfoPopup = openJobInfo;
|
|
80
71
|
|
|
81
72
|
websocket.subscribe('/background-jobs', (data) => {
|
|
82
|
-
if (data.jobId === currentJob
|
|
73
|
+
if (data.jobId === jobStore.currentJob?.id) {
|
|
83
74
|
if (data.status) {
|
|
84
|
-
|
|
75
|
+
jobStore.updateCurrentJob({ status: data.status });
|
|
85
76
|
}
|
|
86
77
|
if (data.progress !== undefined) {
|
|
87
|
-
|
|
78
|
+
jobStore.updateCurrentJob({ progress: data.progress });
|
|
88
79
|
}
|
|
89
80
|
if (data.finishedAt) {
|
|
90
|
-
|
|
81
|
+
jobStore.updateCurrentJob({ finishedAt: data.finishedAt });
|
|
91
82
|
}
|
|
92
83
|
if (data.state) {
|
|
93
|
-
|
|
94
|
-
...currentJob.value.state,
|
|
95
|
-
...data.state,
|
|
96
|
-
};
|
|
84
|
+
jobStore.updateCurrentJob({ state: { ...jobStore.currentJob?.state, ...data.state } });
|
|
97
85
|
}
|
|
98
86
|
}
|
|
99
87
|
});
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
</Tooltip>
|
|
34
34
|
</div>
|
|
35
35
|
</div>
|
|
36
|
-
<div class="flex items-center gap-4 w-full">
|
|
36
|
+
<div class="flex items-center gap-4 w-full mt-4">
|
|
37
37
|
<ProgressBar
|
|
38
38
|
:current-value="job.progress"
|
|
39
39
|
:max-value="100"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
:showLabels="false"
|
|
43
43
|
:showValues="false"
|
|
44
44
|
:show-progress="false"
|
|
45
|
-
:height="
|
|
45
|
+
:height="3"
|
|
46
46
|
/>
|
|
47
47
|
<Button class="h-8" v-if="job.status === 'IN_PROGRESS'" @click="cancelJob"> {{ t('Cancel') }} </Button>
|
|
48
48
|
</div>
|
package/dist/custom/JobsList.vue
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
ref="modalRef"
|
|
5
5
|
class="p-4"
|
|
6
6
|
v-for="job in props.jobs" :key="job.id"
|
|
7
|
-
:beforeCloseFunction="
|
|
8
|
-
:beforeOpenFunction="
|
|
7
|
+
:beforeCloseFunction="onBeforeClose"
|
|
8
|
+
:beforeOpenFunction="onBeforeOpen"
|
|
9
9
|
removeFromDomOnClose
|
|
10
10
|
>
|
|
11
11
|
<template #trigger>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="cursor-pointer hover:scale-110 transition-transform" @click="isDropdownOpen = !isDropdownOpen">
|
|
4
4
|
<div class="relative flex items-center justify-center" v-if="jobs.length > 0">
|
|
5
5
|
<Tooltip>
|
|
6
|
-
<IconBriefcaseSolid class="w-7 h-7 text-
|
|
6
|
+
<IconBriefcaseSolid class="w-7 h-7 text-lightNavbarIcons dark:text-darkNavbarIcons" />
|
|
7
7
|
<template #tooltip>
|
|
8
8
|
{{ t('All jobs completed') }}
|
|
9
9
|
</template>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
import { callAdminForthApi } from '@/utils';
|
|
3
|
+
import { useAdminforth } from '@/adminforth';
|
|
4
|
+
import { defineStore } from 'pinia'
|
|
5
|
+
|
|
6
|
+
export const useBackgroundJobApi = defineStore('jobInfo', () => {
|
|
7
|
+
const currentJob = ref<any>(null);
|
|
8
|
+
const isOpened = ref(false);
|
|
9
|
+
const adminforth = useAdminforth();
|
|
10
|
+
|
|
11
|
+
async function openJobInfoPopup(jobId: string) {
|
|
12
|
+
if (!jobId) return null;
|
|
13
|
+
try {
|
|
14
|
+
const res = await callAdminForthApi({
|
|
15
|
+
path: `/plugin/get-background-job-info`,
|
|
16
|
+
method: 'POST',
|
|
17
|
+
body: { jobId },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (res && res.ok) {
|
|
21
|
+
currentJob.value = res.job;
|
|
22
|
+
isOpened.value = true;
|
|
23
|
+
return res.job;
|
|
24
|
+
} else {
|
|
25
|
+
adminforth.alert({ variant: 'danger', message: res?.message || 'Failed to load job info' });
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error('OpenJobInfoPopup error', e);
|
|
30
|
+
adminforth.alert({ variant: 'danger', message: 'Failed to load job info' });
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function setIsOpened(value: boolean) {
|
|
36
|
+
isOpened.value = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function clearCurrentJob() {
|
|
40
|
+
currentJob.value = null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function updateCurrentJob(jobData: any) {
|
|
44
|
+
currentJob.value = { ...currentJob.value, ...jobData };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
currentJob,
|
|
49
|
+
isOpened,
|
|
50
|
+
openJobInfoPopup,
|
|
51
|
+
setIsOpened,
|
|
52
|
+
clearCurrentJob,
|
|
53
|
+
updateCurrentJob
|
|
54
|
+
};
|
|
55
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -449,7 +449,7 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
449
449
|
});
|
|
450
450
|
server.endpoint({
|
|
451
451
|
method: 'POST',
|
|
452
|
-
path: `/plugin
|
|
452
|
+
path: `/plugin/get-background-job-info`,
|
|
453
453
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ adminUser, body }) {
|
|
454
454
|
const jobId = body.jobId;
|
|
455
455
|
const job = yield this.adminforth.resource(this.resourceConfig.resourceId).get(Filters.EQ(this.getResourcePk(), jobId));
|
package/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ type taskType = {
|
|
|
15
15
|
skip?: boolean;
|
|
16
16
|
state: Record<string, any>;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
20
20
|
options: PluginOptions;
|
|
21
21
|
private taskHandlers: Record<string, taskHandlerType> = {};
|
|
@@ -485,7 +485,7 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
485
485
|
|
|
486
486
|
server.endpoint({
|
|
487
487
|
method: 'POST',
|
|
488
|
-
path: `/plugin
|
|
488
|
+
path: `/plugin/get-background-job-info`,
|
|
489
489
|
handler: async ({ adminUser, body }) => {
|
|
490
490
|
const jobId = body.jobId;
|
|
491
491
|
|
package/package.json
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/background-jobs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"homepage": "https://adminforth.dev/docs/tutorial/Plugins/background-jobs/",
|
|
7
8
|
"publishConfig": {
|
|
8
9
|
"access": "public"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
|
|
12
13
|
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
"keywords": [
|
|
15
|
+
"adminforth",
|
|
16
|
+
"background-jobs",
|
|
17
|
+
"async-processing",
|
|
18
|
+
"task-runner",
|
|
19
|
+
"job-management",
|
|
20
|
+
"progress-tracking",
|
|
21
|
+
"long-running-tasks"
|
|
22
|
+
],
|
|
23
|
+
"author": "DevForth (https://devforth.io)",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"description": "Background jobs plugin for AdminForth to run and manage long tasks from resources",
|
|
17
26
|
"devDependencies": {
|
|
18
27
|
"@types/node": "latest",
|
|
28
|
+
"adminforth": "^2.42.0",
|
|
29
|
+
"semantic-release": "^24.2.1",
|
|
30
|
+
"semantic-release-slack-bot": "^4.0.2",
|
|
19
31
|
"typescript": "^5.7.3"
|
|
20
32
|
},
|
|
33
|
+
"release": {
|
|
34
|
+
"plugins": [
|
|
35
|
+
"@semantic-release/commit-analyzer",
|
|
36
|
+
"@semantic-release/release-notes-generator",
|
|
37
|
+
"@semantic-release/npm",
|
|
38
|
+
"@semantic-release/github",
|
|
39
|
+
[
|
|
40
|
+
"semantic-release-slack-bot",
|
|
41
|
+
{
|
|
42
|
+
"packageName": "@adminforth/background-jobs",
|
|
43
|
+
"notifyOnSuccess": true,
|
|
44
|
+
"notifyOnFail": true,
|
|
45
|
+
"slackIcon": ":package:",
|
|
46
|
+
"markdownReleaseNotes": true
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
]
|
|
50
|
+
},
|
|
21
51
|
"dependencies": {
|
|
22
52
|
"@vueuse/core": "^14.2.1",
|
|
23
53
|
"async-mutex": "^0.5.0",
|
|
@@ -25,6 +55,6 @@
|
|
|
25
55
|
"p-limit": "^7.3.0"
|
|
26
56
|
},
|
|
27
57
|
"peerDependencies": {
|
|
28
|
-
"adminforth": "
|
|
58
|
+
"adminforth": "^2.42.0"
|
|
29
59
|
}
|
|
30
60
|
}
|