Skip to content

Commit c48a229

Browse files
committed
feat: start on modal
1 parent 39a3709 commit c48a229

File tree

8 files changed

+873
-53
lines changed

8 files changed

+873
-53
lines changed

apps/frontend/src/composables/servers/modrinth-servers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
WSModule,
1212
FSModule,
1313
} from "./modules/index.ts";
14-
import { ScheudlingModule } from "./modules/scheduling.ts";
14+
import { SchedulingModule } from "./modules/scheduling.ts";
1515

1616
export function handleError(err: any) {
1717
if (err instanceof ModrinthServerError && err.v1Error) {
@@ -41,7 +41,7 @@ export class ModrinthServer {
4141
readonly startup: StartupModule;
4242
readonly ws: WSModule;
4343
readonly fs: FSModule;
44-
readonly scheduling: ScheudlingModule;
44+
readonly scheduling: SchedulingModule;
4545

4646
constructor(serverId: string) {
4747
this.serverId = serverId;
@@ -53,7 +53,7 @@ export class ModrinthServer {
5353
this.startup = new StartupModule(this);
5454
this.ws = new WSModule(this);
5555
this.fs = new FSModule(this);
56-
this.scheduling = new ScheudlingModule(this);
56+
this.scheduling = new SchedulingModule(this);
5757
}
5858

5959
async createMissingFolders(path: string): Promise<void> {

apps/frontend/src/composables/servers/modules/scheduling.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ScheduledTask } from "@modrinth/utils";
22
import { useServersFetch } from "../servers-fetch.ts";
33
import { ServerModule } from "./base.ts";
44

5-
export class ScheudlingModule extends ServerModule {
5+
export class SchedulingModule extends ServerModule {
66
tasks: ScheduledTask[] = [];
77

88
async fetch(): Promise<void> {
@@ -12,15 +12,34 @@ export class ScheudlingModule extends ServerModule {
1212
);
1313
}
1414

15-
async deleteTask(_task: ScheduledTask): Promise<void> {
16-
// ...
15+
async deleteTask(task: ScheduledTask): Promise<void> {
16+
await useServersFetch(`servers/${this.serverId}/options/schedules`, {
17+
method: "DELETE",
18+
body: { title: task.title },
19+
version: 1,
20+
});
21+
this.tasks = this.tasks.filter((t) => t.title !== task.title);
1722
}
1823

19-
async createTask(_task: ScheduledTask): Promise<number> {
20-
return await 1;
24+
async createTask(task: ScheduledTask): Promise<number> {
25+
await useServersFetch(`servers/${this.serverId}/options/schedules`, {
26+
method: "POST",
27+
body: task,
28+
version: 1,
29+
});
30+
this.tasks.push(task);
31+
return this.tasks.length;
2132
}
2233

23-
async editTask(_taskID: number, _task: Partial<ScheduledTask>) {
24-
// ...
34+
async editTask(taskTitle: string, updatedTask: Partial<ScheduledTask>): Promise<void> {
35+
await useServersFetch(`servers/${this.serverId}/options/schedules`, {
36+
method: "PATCH",
37+
body: { title: taskTitle, ...updatedTask },
38+
version: 1,
39+
});
40+
const index = this.tasks.findIndex((t) => t.title === taskTitle);
41+
if (index !== -1) {
42+
this.tasks[index] = { ...this.tasks[index], ...updatedTask };
43+
}
2544
}
2645
}

apps/frontend/src/pages/servers/manage/[id]/options/scheduling.vue

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,13 @@
154154
</section>
155155
</div>
156156
</div>
157+
158+
<ScheduleTaskModal ref="scheduleModal" @save="handleTaskSave" />
157159
</div>
158160
</template>
159161

160162
<script setup lang="ts">
161-
import { ref, computed, defineProps } from "vue";
163+
import { ref, computed } from "vue";
162164
import { Multiselect } from "vue-multiselect";
163165
import {
164166
PlusIcon,
@@ -170,7 +172,7 @@ import {
170172
SortAscendingIcon as AscendingIcon,
171173
SortDescendingIcon as DescendingIcon,
172174
} from "@modrinth/assets";
173-
import { Toggle, Checkbox, RaisedBadge, ButtonStyled } from "@modrinth/ui";
175+
import { Toggle, Checkbox, RaisedBadge, ButtonStyled, ScheduleTaskModal } from "@modrinth/ui";
174176
import cronstrue from "cronstrue";
175177
import type { ScheduledTask } from "@modrinth/utils";
176178
import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts";
@@ -179,10 +181,16 @@ const props = defineProps<{
179181
server: ModrinthServer;
180182
}>();
181183
182-
const tasks = ref<ScheduledTask[]>(props.server.scheduling.tasks);
184+
onBeforeMount(async () => {
185+
await props.server.scheduling.fetch();
186+
});
187+
183188
const selectedTasks = ref<ScheduledTask[]>([]);
184189
const sortBy = ref("Name");
185190
const descending = ref(false);
191+
const scheduleModal = ref();
192+
193+
const tasks = computed(() => props.server.scheduling.tasks);
186194
187195
const sortedTasks = computed(() => {
188196
const sorted = [...tasks.value];
@@ -208,88 +216,112 @@ const sortedTasks = computed(() => {
208216
return descending.value ? sorted.reverse() : sorted;
209217
});
210218
211-
const handleSelectAll = (selected: boolean) => {
219+
function handleSelectAll(selected: boolean): void {
212220
selectedTasks.value = selected ? [...tasks.value] : [];
213-
};
221+
}
214222
215-
const handleTaskSelect = (task: ScheduledTask, selected: boolean) => {
223+
function handleTaskSelect(task: ScheduledTask, selected: boolean): void {
216224
if (selected) {
217225
selectedTasks.value.push(task);
218226
} else {
219227
selectedTasks.value = selectedTasks.value.filter((t) => t !== task);
220228
}
221-
};
229+
}
222230
223-
const handleTaskToggle = async (task: ScheduledTask, enabled: boolean) => {
231+
async function handleTaskToggle(task: ScheduledTask, enabled: boolean): Promise<void> {
224232
try {
225-
task.enabled = enabled;
233+
await props.server.scheduling.editTask(task.title, { enabled });
226234
console.log("Toggle task:", task.title, enabled);
227235
} catch (error) {
228236
console.error("Failed to toggle task:", error);
229237
task.enabled = !enabled;
230238
}
231-
};
239+
}
232240
233-
const handleTaskEdit = (task: ScheduledTask) => {
234-
console.log("Edit task:", task.title);
235-
};
241+
function handleTaskEdit(task: ScheduledTask): void {
242+
scheduleModal.value?.show(task);
243+
}
236244
237-
const handleTaskDelete = async (task: ScheduledTask) => {
245+
async function handleTaskDelete(task: ScheduledTask): Promise<void> {
238246
if (confirm(`Are you sure you want to delete "${task.title}"?`)) {
239247
try {
240-
const index = tasks.value.indexOf(task);
241-
if (index > -1) {
242-
tasks.value.splice(index, 1);
243-
}
248+
await props.server.scheduling.deleteTask(task);
244249
selectedTasks.value = selectedTasks.value.filter((t) => t !== task);
245250
console.log("Delete task:", task.title);
246251
} catch (error) {
247252
console.error("Failed to delete task:", error);
248253
}
249254
}
250-
};
255+
}
251256
252-
const handleCreateTask = () => {
253-
console.log("Create new task");
254-
};
257+
function handleCreateTask(): void {
258+
scheduleModal.value?.showNew();
259+
}
255260
256-
const handleBulkToggle = async () => {
261+
async function handleBulkToggle(): Promise<void> {
257262
const enabledCount = selectedTasks.value.filter((t) => t.enabled).length;
258263
const shouldEnable = enabledCount < selectedTasks.value.length / 2;
259264
260265
try {
261-
selectedTasks.value.forEach((task: ScheduledTask) => {
262-
task.enabled = shouldEnable;
263-
});
266+
await Promise.all(
267+
selectedTasks.value.map((task) =>
268+
props.server.scheduling.editTask(task.title, { enabled: shouldEnable }),
269+
),
270+
);
264271
console.log("Bulk toggle tasks:", selectedTasks.value.length, "to", shouldEnable);
265272
} catch (error) {
266273
console.error("Failed to bulk toggle tasks:", error);
267274
}
268-
};
275+
}
269276
270-
const handleBulkDelete = async () => {
271-
// TODO: Confirm delete modal.
272-
// `Are you sure you want to delete ${selectedTasks.value.length} selected tasks?`
273-
};
277+
async function handleBulkDelete(): Promise<void> {
278+
if (confirm(`Are you sure you want to delete ${selectedTasks.value.length} selected tasks?`)) {
279+
try {
280+
await Promise.all(
281+
selectedTasks.value.map((task) => props.server.scheduling.deleteTask(task)),
282+
);
283+
selectedTasks.value = [];
284+
console.log("Bulk delete completed");
285+
} catch (error) {
286+
console.error("Failed to bulk delete tasks:", error);
287+
}
288+
}
289+
}
274290
275-
const updateSort = () => {
276-
// Trigger reactivity for sortedTasks somehow.
277-
};
291+
async function handleTaskSave(data: ScheduledTask): Promise<void> {
292+
try {
293+
if (scheduleModal.value?.mode === "edit") {
294+
await props.server.scheduling.editTask(
295+
scheduleModal.value.originalData?.title || data.title,
296+
data,
297+
);
298+
console.log("Updated task:", data.title);
299+
} else {
300+
await props.server.scheduling.createTask(data);
301+
console.log("Created task:", data.title);
302+
}
303+
} catch (error) {
304+
console.error("Failed to save task:", error);
305+
}
306+
}
307+
308+
function updateSort(): void {
309+
// Trigger reactivity for sortedTasks
310+
}
278311
279-
const updateDescending = () => {
312+
function updateDescending(): void {
280313
descending.value = !descending.value;
281-
};
314+
}
282315
283-
const getHumanReadableCron = (cronExpression: string) => {
316+
function getHumanReadableCron(cronExpression: string): string {
284317
try {
285-
// eslint-disable-next-line import/no-named-as-default-member
286318
return cronstrue.toString(cronExpression);
287319
} catch {
288320
return cronExpression;
289321
}
290-
};
322+
}
291323
292-
const formatWarningIntervals = (intervals: number[]) => {
324+
function formatWarningIntervals(intervals: number[]): string {
293325
return intervals
294326
.sort((a, b) => b - a)
295327
.map((seconds) => {
@@ -298,7 +330,7 @@ const formatWarningIntervals = (intervals: number[]) => {
298330
return `${seconds}s`;
299331
})
300332
.join(", ");
301-
};
333+
}
302334
</script>
303335

304336
<style lang="scss" scoped>
@@ -321,12 +353,10 @@ const formatWarningIntervals = (intervals: number[]) => {
321353
justify-content: center;
322354
padding: var(--spacing-card-sm);
323355
324-
// Left edge of table
325356
&:first-child {
326357
padding-left: var(--spacing-card-bg);
327358
}
328359
329-
// Right edge of table
330360
&:last-child {
331361
padding-right: var(--spacing-card-bg);
332362
}

packages/assets/icons/clock.svg

Lines changed: 1 addition & 0 deletions
Loading

packages/assets/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import _ChevronRightIcon from './icons/chevron-right.svg?component'
6666
import _ClearIcon from './icons/clear.svg?component'
6767
import _ClientIcon from './icons/client.svg?component'
6868
import _ClipboardCopyIcon from './icons/clipboard-copy.svg?component'
69+
import _ClockIcon from './icons/clock.svg?component'
6970
import _CodeIcon from './icons/code.svg?component'
7071
import _CoffeeIcon from './icons/coffee.svg?component'
7172
import _CoinsIcon from './icons/coins.svg?component'
@@ -287,6 +288,7 @@ export const ChevronRightIcon = _ChevronRightIcon
287288
export const ClearIcon = _ClearIcon
288289
export const ClientIcon = _ClientIcon
289290
export const ClipboardCopyIcon = _ClipboardCopyIcon
291+
export const ClockIcon = _ClockIcon
290292
export const CodeIcon = _CodeIcon
291293
export const CoffeeIcon = _CoffeeIcon
292294
export const CoinsIcon = _CoinsIcon

0 commit comments

Comments
 (0)