Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/refactor-problem-create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"algohub": patch:refactor
---

Refactored problem creation page.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dtolnay",
"emptydirs",
"farmfe",
"Gridlines",
"icns",
"ICPC",
"jbolda",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions src/components/MonacoEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ onUnmounted(disposeEditor)
onBeforeUnmount(disposeEditor)
onBeforeRouteLeave(disposeEditor)

console.log(Language)
console.log(Object.values(Language))
console.log(Object.keys(Language))
console.log(Object.entries(Language))

const languageOptions = Object.entries(Language).map(([name, value]) => ({ name, value }))

const onChangeLanguage = (value: SelectChangeEvent) => {
Expand Down
57 changes: 43 additions & 14 deletions src/components/ProblemEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ onMounted(async () => {
samples.splice(0, samples.length);
data.samples.forEach(sample => samples.push({ input: sample.input, output: sample.output }));
hint.value = data.hint || '';
testCases.splice(0, testCases.length);
data.test_cases?.forEach(tc => testCases.push({ input: tc.input, output: tc.output }));
loading.value = false;
}
})
Expand All @@ -38,7 +40,8 @@ const input = ref<string>('');
const output = ref<string>('');
const samples = reactive<Sample[]>([{ input: '', output: '' }]);
const hint = ref<string>('');
const isPrivate = ref(false);
const owner = ref<string>(accountStore.account.id!);
const visibility = ref<ProblemVisibility>(ProblemVisibility.Public);
const testCases = reactive<TestCase[]>([]);

const timeLimit = ref<number>(1000);
Expand All @@ -57,7 +60,7 @@ interface ProblemForm<T, N> {
owner: RecordId,
categories: string[];
tags: string[];
private: boolean;
visibility: ProblemVisibility;
}

const validate = (form: ProblemForm<string, number>): boolean => {
Expand Down Expand Up @@ -92,11 +95,11 @@ const onCreateProblem = async () => {
test_cases: testCases.map(tc => ({ input: tc.input, output: tc.output })),
owner: {
tb: "account",
id: accountStore.account.id!
id: owner.value
},
categories: [],
tags: [],
private: isPrivate.value
visibility: visibility.value,
}
const valid = validate(problem);
if (!valid) return;
Expand All @@ -106,7 +109,6 @@ const onCreateProblem = async () => {
const res = await api.createProblem({
id: accountStore.account.id!,
token: accountStore.account.token!,
visibility: ProblemVisibility.Public,
...problem,
});
if (!res.success) {
Expand Down Expand Up @@ -236,16 +238,32 @@ const formatSize = (bytes: number) => {

return `${formattedSize} ${sizes[i]}`;
};

const onRemoveTestCases = async (testCase: TestCase) => {
const removeInput = await api.removeAsset(testCase.input, accountStore.auth!);
const removeOutput = await api.removeAsset(testCase.output, accountStore.auth!);
if (!removeInput.success || !removeOutput.success) {
return toast.add({ severity: 'error', summary: 'Error', detail: removeInput.message || removeOutput.message, life: 3000 });
}
const index = testCases.indexOf(testCase);
if (index !== -1) {
testCases.splice(index, 1);
}
}
</script>

<template>
<div class="max-w-full md:max-w-[768px] mx-auto">
<Panel v-if="!loading" class="mt-10">
<div class="flex flex-col gap-8">
<div class="mt-10 text-center">
<div v-if="!props.id" class="mt-10 text-center">
<span class="text-gray-500 mb-4">Share your algorithm problem with the community</span>
<h1 class="text-3xl font-bold mb-4">Create a new algorithm problem</h1>
</div>
<div v-else class="mt-10 text-center">
<span class="text-gray-500 mb-4">Edit your algorithm problem</span>
<h1 class="text-3xl font-bold mb-4">Edit Problem</h1>
</div>
<div class="flex flex-col gap-8">
<div class="flex flex-col gap-1">
<InputText v-model="title" type="text" name="title" placeholder="Problem Title" fluid>
Expand Down Expand Up @@ -292,7 +310,16 @@ const formatSize = (bytes: number) => {
<InputGroupAddon>
<i class="pi pi-building"></i>
</InputGroupAddon>
<Select placeholder="Owner" disabled></Select>
<Select
:options="[{ label: accountStore.account.username, value: accountStore.account.id }]"
optionLabel="label" optionValue="value" placeholder="Owner" v-model="owner"></Select>
</InputGroup>
<InputGroup>
<InputGroupAddon>
<i class="pi pi-eye"></i>
</InputGroupAddon>
<Select :options="Object.values(ProblemVisibility)" placeholder="Visibility"
v-model="visibility"></Select>
</InputGroup>
</div>
<FileUpload customUpload :multiple="true" accept=".in,.out" :maxFileSize="12 * 1024 * 1024"
Expand Down Expand Up @@ -362,14 +389,16 @@ const formatSize = (bytes: number) => {
</div>
</template>
</FileUpload>
<DataTable :value="testCases" tableStyle="min-width: 50rem">
<Column field="input" header="Code"></Column>
<Column field="output" header="Name"></Column>
<DataTable v-if="testCases.length > 0" :value="testCases" tableStyle="w-full" showGridlines>
<Column field="input" header="Input"></Column>
<Column field="output" header="Output"></Column>
<Column :exportable="false" style="min-width: 12rem">
<template #body="slotProps">
<Button icon="pi pi-trash" outlined rounded severity="danger"
@click="onRemoveTestCases(slotProps.data)"></Button>
</template>
</Column>
</DataTable>
<div class="flex items-center gap-2">
<Checkbox name="private" v-model="isPrivate" binary></Checkbox>
<span>Mark as private</span>
</div>
<Button @click="onCreateProblem" type="submit" label="Save Changes"></Button>
</div>
</div>
Expand Down
17 changes: 14 additions & 3 deletions src/scripts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ export const uploadContent = async (form: CreateAsset) => {
}
};

export const removeAsset = async (id: string, auth: Credentials) => {
try {
const response = await axios.delete(`/asset/delete/${id}`, {
data: auth,
});
return response.data as Response<undefined>;
} catch (error) {
return handleAxiosError(AxiosError.from(error));
}
};

interface ProfileForm {
id: string;
token: string;
Expand Down Expand Up @@ -160,9 +171,9 @@ interface Submission {
lang: Language;
problem: RecordId;
code: string;
status: 'in_queue' | 'judging' | 'ready';
judge_details: { status: any, timeUsed: number, memoryUsed: number }[],
judge_result: { status: any, timeUsed: number, memoryUsed: number },
status: "in_queue" | "judging" | "ready";
judge_details: { status: any; timeUsed: number; memoryUsed: number }[];
judge_result: { status: any; timeUsed: number; memoryUsed: number };
// contest
}

Expand Down
1 change: 1 addition & 0 deletions src/scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface CreateAsset {

export interface UserContent {
id: string;
name: string;
}

export enum ProblemVisibility {
Expand Down
6 changes: 4 additions & 2 deletions src/views/problem/[id].vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import * as api from '@/scripts/api';
import { useAccountStore, useThemeStore } from '@/scripts/store';
import { useToast } from 'primevue';
Expand All @@ -9,6 +9,7 @@ import { MdPreview } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

const route = useRoute();
const router = useRouter();
const id = route.params.id as string;

const toast = useToast();
Expand Down Expand Up @@ -100,7 +101,8 @@ onUnmounted(() => {
<div class="p-3 flex flex-wrap flex-row items-center justify-between w-full">
<Button size="small" icon="pi pi-arrow-left" plain outlined></Button>
<div class="inline-flex items-center gap-1">
<Button icon="pi pi-pencil" size="small" plain outlined></Button>
<Button @click="router.push(`/problem/edit/${id}`)" icon="pi pi-pencil" size="small" plain
outlined></Button>
<Button size="small" severity="danger" icon="pi pi-trash" outlined></Button>
</div>
</div>
Expand Down
16 changes: 16 additions & 0 deletions src/views/problem/edit/[id].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
import { useRoute } from 'vue-router';

const route = useRoute();
const id = route.params.id as string;

const path = [{ label: 'New problem' }];
</script>

<template>
<div class="flex-1 flex flex-col">
<UniversalToolBar :path></UniversalToolBar>
<ProblemEditor :id></ProblemEditor>
<UniversalFooter></UniversalFooter>
</div>
</template>
Loading