diff --git a/.yarn/versions/6bd55107.yml b/.yarn/versions/6bd55107.yml new file mode 100644 index 0000000..85ee0e5 --- /dev/null +++ b/.yarn/versions/6bd55107.yml @@ -0,0 +1,3 @@ +releases: + "@aoi-js/frontend": patch + "@aoi-js/server": patch diff --git a/apps/frontend/src/components/problem/DataUpload.vue b/apps/frontend/src/components/problem/DataUpload.vue index 29d4fbe..5b57987 100644 --- a/apps/frontend/src/components/problem/DataUpload.vue +++ b/apps/frontend/src/components/problem/DataUpload.vue @@ -2,21 +2,29 @@ - - + + {{ t('term.config') }} {{ t('action.upload') }} + + + + {{ t('simple-mode') }} + + + {{ t('advanced-mode') }} + + @@ -48,12 +56,18 @@ const emit = defineEmits<{ const { t } = useI18n() -const { uploadFileTask, uploadInfo } = useDataUpload(props.problem._id, () => emit('updated')) +const { uploadFileTask, uploadInfo, advanced } = useDataUpload(props.problem._id, () => + emit('updated') +) en: create-data-version: Create data version + simple-mode: Simple mode + advanced-mode: Advanced mode zh-Hans: create-data-version: 创建数据版本 + simple-mode: 简单模式 + advanced-mode: 高级模式 diff --git a/apps/frontend/src/components/utils/JsonViewer.vue b/apps/frontend/src/components/utils/JsonViewer.vue index d3b876b..b1dfdb0 100644 --- a/apps/frontend/src/components/utils/JsonViewer.vue +++ b/apps/frontend/src/components/utils/JsonViewer.vue @@ -36,6 +36,7 @@ import { useI18n } from 'vue-i18n' import MonacoEditor from './MonacoEditor.vue' import AsyncState from './AsyncState.vue' import ky from 'ky' +import { watch } from 'vue' const props = defineProps<{ endpoint?: string @@ -64,6 +65,8 @@ const data = useAsyncState(async () => { const json = await ky.get(url).json() return json }, null) + +watch([() => props.endpoint, () => props.url, () => props.rawString], () => data.execute()) en: diff --git a/apps/frontend/src/components/utils/SettingsEditor.vue b/apps/frontend/src/components/utils/SettingsEditor.vue index 5d837cb..69b0b66 100644 --- a/apps/frontend/src/components/utils/SettingsEditor.vue +++ b/apps/frontend/src/components/utils/SettingsEditor.vue @@ -23,6 +23,7 @@ import { useAsyncState } from '@vueuse/core' import { useI18n } from 'vue-i18n' import AsyncState from './AsyncState.vue' import { nextTick } from 'vue' +import { watch } from 'vue' const props = defineProps<{ endpoint: string @@ -41,6 +42,12 @@ const settings = useAsyncState( null, { shallow: false } ) + +watch( + () => props.endpoint, + () => settings.execute() +) + const patchSettings = useAsyncTask(async () => { await http.patch(props.endpoint, { json: settings.state.value diff --git a/apps/frontend/src/pages/org/[orgId]/contest/[contestId]/ranklist/[ranklistKey].vue b/apps/frontend/src/pages/org/[orgId]/contest/[contestId]/ranklist/[ranklistKey].vue index 6d3844b..19e1ef9 100644 --- a/apps/frontend/src/pages/org/[orgId]/contest/[contestId]/ranklist/[ranklistKey].vue +++ b/apps/frontend/src/pages/org/[orgId]/contest/[contestId]/ranklist/[ranklistKey].vue @@ -14,6 +14,7 @@ `contest/${props.contestId}/ranklist/${encodeURIComponent(props.ranklistKey)}/url` +) + en: ranklist-settings: Ranklist Settings diff --git a/apps/frontend/src/utils/problem/data.ts b/apps/frontend/src/utils/problem/data.ts index ae008d4..cc54c2a 100644 --- a/apps/frontend/src/utils/problem/data.ts +++ b/apps/frontend/src/utils/problem/data.ts @@ -1,5 +1,5 @@ import zip from 'jszip' -import { reactive, watch } from 'vue' +import { reactive, ref, watch } from 'vue' import { computeSHA256 } from '../files' import { http } from '../http' import { useToast } from 'vue-toastification' @@ -7,6 +7,7 @@ import { useAsyncTask } from '../async' export function useDataUpload(problemId: string, updated: () => void) { const toast = useToast() + const advanced = ref(false) const uploadInfo = reactive({ file: [] as File[], @@ -33,13 +34,17 @@ export function useDataUpload(problemId: string, updated: () => void) { async function handleFile() { const file = uploadInfo.file[0] try { - uploadInfo.hash = await computeSHA256(file) - const result = await zip.loadAsync(file) - const content = await result.file('problem.json')?.async('string') - if (content) { - uploadInfo.configJson = content + if (advanced.value) { + toast.warning('Advanced mode is on, you need to manually fill in the hash and config') } else { - toast.warning('problem.json not found in zip file, please check your file') + uploadInfo.hash = await computeSHA256(file) + const result = await zip.loadAsync(file) + const content = await result.file('problem.json')?.async('string') + if (content) { + uploadInfo.configJson = content + } else { + toast.warning('problem.json not found in zip file, please check your file') + } } } catch (err) { toast.error('Failed to parse problem data, is it a zip file?') @@ -63,5 +68,5 @@ export function useDataUpload(problemId: string, updated: () => void) { updated() }) - return { uploadInfo, uploadFileTask } + return { uploadInfo, uploadFileTask, advanced } } diff --git a/apps/server/src/routes/runner/ranklist.ts b/apps/server/src/routes/runner/ranklist.ts index 8a8c114..b1e3ad8 100644 --- a/apps/server/src/routes/runner/ranklist.ts +++ b/apps/server/src/routes/runner/ranklist.ts @@ -57,19 +57,21 @@ const runnerRanklistTaskRoutes = defineRoutes(async (s) => { const { modifiedCount } = await contests.updateOne( { _id: ctx._contestId, ranklistTaskId: ctx._taskId }, - { - $addFields: { - ranklistState: { - $cond: { - if: { - $eq: ['$ranklistUpdatedAt', req.body.ranklistUpdatedAt] - }, - then: ContestRanklistState.VALID, - else: ContestRanklistState.INVALID + [ + { + $addFields: { + ranklistState: { + $cond: { + if: { + $eq: ['$ranklistUpdatedAt', req.body.ranklistUpdatedAt] + }, + then: ContestRanklistState.VALID, + else: ContestRanklistState.INVALID + } } } } - } + ] ) if (modifiedCount === 0) return rep.notFound() return {}