✨ Challenges Modification
This commit is contained in:
parent
3f5654efb4
commit
ffa7f097af
@ -1,11 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<client-only>
|
||||||
|
<vue-monaco-editor
|
||||||
|
:options="options"
|
||||||
|
:language="answers.language ?? 'text'"
|
||||||
|
v-model:value="answers.code"
|
||||||
|
class="min-h-[360px] code-editor"
|
||||||
|
/>
|
||||||
|
</client-only>
|
||||||
|
|
||||||
|
<n-divider class="mx-[-24px] w-[calc(100%+48px)] divider-below-code" />
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<n-space>
|
||||||
|
<n-select
|
||||||
|
:options="languages"
|
||||||
|
v-model:value="answers.language"
|
||||||
|
placeholder="Programming Language"
|
||||||
|
class="w-120"
|
||||||
|
/>
|
||||||
|
</n-space>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { NDivider, NSpace, NSelect } from "naive-ui";
|
||||||
|
import { VueMonacoEditor } from "@guolao/vue-monaco-editor";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
challenge: any,
|
||||||
|
problem: any,
|
||||||
|
answers: any,
|
||||||
|
}>();
|
||||||
|
const emits = defineEmits(["update:answers"]);
|
||||||
|
|
||||||
|
const answers = ref(props.challenge?.answers ?? {});
|
||||||
|
|
||||||
|
watch(answers, (v) => {
|
||||||
|
emits("update:answers", v);
|
||||||
|
});
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
minimap: { enabled: false }
|
||||||
|
};
|
||||||
|
|
||||||
|
const languageWhitelist: string[] = props.problem?.languageWhitelist ?? [];
|
||||||
|
const languageBlacklist: string[] = props.problem?.languageBlacklist ?? [];
|
||||||
|
|
||||||
|
const languages = [
|
||||||
|
{ label: "C", value: "c" },
|
||||||
|
{ label: "C++", value: "cpp" },
|
||||||
|
{ label: "JSON", value: "json" }, // Huh?
|
||||||
|
].filter((item) => {
|
||||||
|
return languageWhitelist.filter((x) => new RegExp(x, item.value)).length > 0 ||
|
||||||
|
!(languageBlacklist.filter((x) => new RegExp(x, item.value)).length > 0);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.code-editor {
|
||||||
|
min-width: calc(100% + 48px);
|
||||||
|
margin-top: -20px;
|
||||||
|
margin-left: -24px;
|
||||||
|
margin-right: -24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider-below-code {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -12,15 +12,14 @@
|
|||||||
</n-page-header>
|
</n-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<client-only>
|
<section>
|
||||||
<vue-monaco-editor
|
<problem-solution-program
|
||||||
:options="options"
|
v-if="problem.type === 'programming'"
|
||||||
v-model:value="answer.code"
|
v-model:answers="answers"
|
||||||
class="min-h-[360px] code-editor"
|
:challenge="challenge"
|
||||||
|
:problem="problem"
|
||||||
/>
|
/>
|
||||||
</client-only>
|
</section>
|
||||||
|
|
||||||
<n-divider class="mx-[-24px] w-[calc(100%+48px)] divider-below-code" />
|
|
||||||
|
|
||||||
<template #action>
|
<template #action>
|
||||||
<div class="w-full flex justify-between">
|
<div class="w-full flex justify-between">
|
||||||
@ -42,8 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { NButton, NCard, NDivider, NPageHeader, NTag, NIcon, useDialog, useMessage } from "naive-ui";
|
import { NButton, NCard, NPageHeader, NTag, NIcon, useDialog, useMessage } from "naive-ui";
|
||||||
import { VueMonacoEditor } from "@guolao/vue-monaco-editor";
|
|
||||||
import { Save } from "@vicons/carbon";
|
import { Save } from "@vicons/carbon";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -51,10 +49,6 @@ const client = useSupabaseClient();
|
|||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
|
|
||||||
const options = {
|
|
||||||
minimap: { enabled: false }
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitting = ref(false);
|
const submitting = ref(false);
|
||||||
|
|
||||||
const { data: challenge } = await client
|
const { data: challenge } = await client
|
||||||
@ -63,16 +57,48 @@ const { data: challenge } = await client
|
|||||||
.eq("id", route.params.id)
|
.eq("id", route.params.id)
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
|
const { data: problem } = await client
|
||||||
|
.from("problems")
|
||||||
|
.select<any, any>("*")
|
||||||
|
.eq("id", challenge?.problem)
|
||||||
|
.single();
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: challenge ? `挑战 #${challenge.id}` : "挑战 #404"
|
title: challenge ? `挑战 #${challenge.id}` : "挑战 #404"
|
||||||
});
|
});
|
||||||
|
|
||||||
const answer = ref(challenge?.answer ?? {});
|
const answers = ref(challenge?.answers ?? {});
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
|
submitting.value = true;
|
||||||
|
const instance = message.loading("正在保存,请稍后……");
|
||||||
|
|
||||||
|
const { error } = await client
|
||||||
|
.from("challenges")
|
||||||
|
// @ts-ignore
|
||||||
|
.update<any>({
|
||||||
|
answers: answers.value
|
||||||
|
})
|
||||||
|
.eq("id", challenge.id);
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
message.error(`Something went wrong... ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.destroy();
|
||||||
|
submitting.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
const prefixKey = navigator.platform.indexOf("Mac") == 0 ? event.metaKey : event.ctrlKey;
|
||||||
|
if (prefixKey && event.key == "s") {
|
||||||
|
event.preventDefault();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function abandon() {
|
function abandon() {
|
||||||
const instance = dialog.warning({
|
const instance = dialog.warning({
|
||||||
title: "警告",
|
title: "警告",
|
||||||
@ -88,7 +114,7 @@ function abandon() {
|
|||||||
|
|
||||||
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
|
||||||
|
|
||||||
instance.loading = true
|
instance.loading = true;
|
||||||
message.info("已放弃挑战该题");
|
message.info("已放弃挑战该题");
|
||||||
|
|
||||||
await delay(1850);
|
await delay(1850);
|
||||||
@ -101,16 +127,3 @@ async function submit() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.code-editor {
|
|
||||||
min-width: calc(100% + 48px);
|
|
||||||
margin-top: -20px;
|
|
||||||
margin-left: -24px;
|
|
||||||
margin-right: -24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider-below-code {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -32,5 +32,5 @@ policy "Enable update access for users' own items" on "public"."challenges"
|
|||||||
as permissive for
|
as permissive for
|
||||||
update
|
update
|
||||||
to public
|
to public
|
||||||
using (author = auth.uid())
|
using (author = auth.uid() and status = 'in-progress')
|
||||||
with check (author = auth.uid())
|
with check (author = auth.uid())
|
Loading…
Reference in New Issue
Block a user