diff --git a/apps/frontend/package.json b/apps/frontend/package.json index c3b53219a..fff029a85 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -41,10 +41,12 @@ "@modrinth/ui": "workspace:*", "@modrinth/utils": "workspace:*", "@pinia/nuxt": "^0.5.1", + "@types/three": "^0.172.0", "@vintl/vintl": "^4.4.1", "@vueuse/core": "^11.1.0", "ace-builds": "^1.36.2", "ansi-to-html": "^0.7.2", + "cronstrue": "^2.61.0", "dayjs": "^1.11.7", "dompurify": "^3.1.7", "floating-vue": "^5.2.2", @@ -59,7 +61,6 @@ "qrcode.vue": "^3.4.0", "semver": "^7.5.4", "three": "^0.172.0", - "@types/three": "^0.172.0", "vue-multiselect": "3.0.0-alpha.2", "vue-typed-virtual-list": "^1.0.10", "vue3-ace-editor": "^2.2.4", diff --git a/apps/frontend/src/composables/servers/modules/scheduling.ts b/apps/frontend/src/composables/servers/modules/scheduling.ts index 8f49aa12f..491869e7d 100644 --- a/apps/frontend/src/composables/servers/modules/scheduling.ts +++ b/apps/frontend/src/composables/servers/modules/scheduling.ts @@ -1,45 +1,45 @@ -import type { ScheduledTask } from "@modrinth/utils"; +import type { Schedule, ServerSchedule } from "@modrinth/utils"; import { useServersFetch } from "../servers-fetch.ts"; import { ServerModule } from "./base.ts"; export class SchedulingModule extends ServerModule { - tasks: ScheduledTask[] = []; + tasks: ServerSchedule[] = []; async fetch(): Promise { - // this.tasks = await useServersFetch( - // `servers/${this.serverId}/options/schedules`, - // { version: 1 }, - // ); + const response = await useServersFetch<{ items: ServerSchedule[] }>( + `servers/${this.serverId}/options/schedules`, + { version: 1 }, + ); + this.tasks = response.items; } - async deleteTask(task: ScheduledTask): Promise { - // await useServersFetch(`servers/${this.serverId}/options/schedules`, { - // method: "DELETE", - // body: { title: task.title }, - // version: 1, - // }); - // this.tasks = this.tasks.filter((t) => t.title !== task.title); + async deleteTask(task: ServerSchedule): Promise { + await useServersFetch(`servers/${this.serverId}/options/schedules/${task.id}`, { + method: "DELETE", + version: 1, + }); + this.tasks = this.tasks.filter((t) => t.id !== task.id); } - async createTask(task: ScheduledTask): Promise { - // await useServersFetch(`servers/${this.serverId}/options/schedules`, { - // method: "POST", - // body: task, - // version: 1, - // }); - // this.tasks.push(task); - // return this.tasks.length; + async createTask(task: Schedule): Promise { + const response = await useServersFetch<{ id: number }>( + `servers/${this.serverId}/options/schedules`, + { + method: "POST", + body: task, + version: 1, + }, + ); + await this.fetch(); + return response.id; } - async editTask(taskTitle: string, updatedTask: Partial): Promise { - // await useServersFetch(`servers/${this.serverId}/options/schedules`, { - // method: "PATCH", - // body: { title: taskTitle, ...updatedTask }, - // version: 1, - // }); - // const index = this.tasks.findIndex((t) => t.title === taskTitle); - // if (index !== -1) { - // this.tasks[index] = { ...this.tasks[index], ...updatedTask }; - // } + async editTask(taskId: number, updatedTask: Partial): Promise { + await useServersFetch(`servers/${this.serverId}/options/schedules/${taskId}`, { + method: "PATCH", + body: updatedTask, + version: 1, + }); + await this.fetch(); } } diff --git a/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/[taskId].vue b/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/[taskId].vue new file mode 100644 index 000000000..fa8dbf2e7 --- /dev/null +++ b/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/[taskId].vue @@ -0,0 +1,413 @@ + + + diff --git a/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/index.vue b/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/index.vue index 9ffc14b97..7c305d061 100644 --- a/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/index.vue +++ b/apps/frontend/src/pages/servers/manage/[id]/options/scheduling/index.vue @@ -1,164 +1,165 @@ @@ -178,7 +179,7 @@ import { } from "@modrinth/assets"; import { Toggle, Checkbox, RaisedBadge, ButtonStyled } from "@modrinth/ui"; import cronstrue from "cronstrue"; -import type { ScheduledTask } from "@modrinth/utils"; +import type { ServerSchedule } from "@modrinth/utils"; import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts"; const props = defineProps<{ @@ -191,11 +192,11 @@ onBeforeMount(async () => { await props.server.scheduling.fetch(); }); -const selectedTasks = ref([]); +const selectedTasks = ref([]); const sortBy = ref("Name"); const descending = ref(false); -const tasks = computed(() => props.server.scheduling.tasks); +const tasks = computed(() => props.server.scheduling.tasks as ServerSchedule[]); const sortedTasks = computed(() => { const sorted = [...tasks.value]; @@ -225,7 +226,7 @@ function handleSelectAll(selected: boolean): void { selectedTasks.value = selected ? [...tasks.value] : []; } -function handleTaskSelect(task: ScheduledTask, selected: boolean): void { +function handleTaskSelect(task: ServerSchedule, selected: boolean): void { if (selected) { selectedTasks.value.push(task); } else { @@ -233,17 +234,17 @@ function handleTaskSelect(task: ScheduledTask, selected: boolean): void { } } -async function handleTaskToggle(task: ScheduledTask, enabled: boolean): Promise { +async function handleTaskToggle(task: ServerSchedule, enabled: boolean): Promise { try { - await props.server.scheduling.editTask(task.title, { enabled }); - console.log("Toggle task:", task.title, enabled); + await props.server.scheduling.editTask(task.id, { enabled }); + console.log("Toggle task:", task.id, enabled); } catch (error) { console.error("Failed to toggle task:", error); task.enabled = !enabled; } } -async function handleTaskDelete(task: ScheduledTask): Promise { +async function handleTaskDelete(task: ServerSchedule): Promise { if (confirm(`Are you sure you want to delete "${task.title}"?`)) { try { await props.server.scheduling.deleteTask(task); @@ -262,7 +263,7 @@ async function handleBulkToggle(): Promise { try { await Promise.all( selectedTasks.value.map((task) => - props.server.scheduling.editTask(task.title, { enabled: shouldEnable }), + props.server.scheduling.editTask(task.id, { enabled: shouldEnable }), ), ); console.log("Bulk toggle tasks:", selectedTasks.value.length, "to", shouldEnable); diff --git a/packages/utils/servers/types/scheduling.ts b/packages/utils/servers/types/scheduling.ts index 3712142da..4f8ae68f1 100644 --- a/packages/utils/servers/types/scheduling.ts +++ b/packages/utils/servers/types/scheduling.ts @@ -1,10 +1,19 @@ -export interface ScheduledTask { - id?: number +export type ActionKind = 'game-command' | 'restart' + +export type ScheduleOptions = { command: string } | Record + +export interface Schedule { title: string - action_kind: 'game-command' | 'restart' - options: { command?: string } - enabled: boolean - warn_msg?: string - warn_intervals: number[] every: string + action_kind: ActionKind + options: ScheduleOptions + enabled: boolean + warn_msg: string + warn_intervals: number[] +} + +export interface ServerSchedule extends Schedule { + id: number + server_id: string + added_on: string } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e9e5cd820..034dce853 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -233,6 +233,9 @@ importers: ansi-to-html: specifier: ^0.7.2 version: 0.7.2 + cronstrue: + specifier: ^2.61.0 + version: 2.61.0 dayjs: specifier: ^1.11.7 version: 1.11.11 @@ -3606,10 +3609,6 @@ packages: resolution: {integrity: sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==} engines: {node: '>=18.0'} - cronstrue@2.52.0: - resolution: {integrity: sha512-NKgHbWkSZXJUcaBHSsyzC8eegD6bBd4O0oCI6XMIJ+y4Bq3v4w7sY3wfWoKPuVlq9pQHRB6od0lmKpIqi8TlKA==} - hasBin: true - cronstrue@2.61.0: resolution: {integrity: sha512-ootN5bvXbIQI9rW94+QsXN5eROtXWwew6NkdGxIRpS/UFWRggL0G5Al7a9GTBFEsuvVhJ2K3CntIIVt7L2ILhA==} hasBin: true @@ -9305,7 +9304,7 @@ snapshots: '@vue/devtools-kit': 7.6.4 birpc: 0.2.19 consola: 3.2.3 - cronstrue: 2.52.0 + cronstrue: 2.61.0 destr: 2.0.3 error-stack-parser-es: 0.1.5 execa: 7.2.0 @@ -11723,8 +11722,6 @@ snapshots: croner@9.0.0: {} - cronstrue@2.52.0: {} - cronstrue@2.61.0: {} cross-spawn@6.0.6: