Skip to content

Commit

Permalink
fix: ranklist & problem data ux (#28)
Browse files Browse the repository at this point in the history
* fix: ranker api

* fix: ranklist route

* feat: support advanced data uploader

* chore: bump versions
  • Loading branch information
thezzisu authored Jan 20, 2024
1 parent cf2c653 commit 9fae951
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 24 deletions.
3 changes: 3 additions & 0 deletions .yarn/versions/6bd55107.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
releases:
"@aoi-js/frontend": patch
"@aoi-js/server": patch
24 changes: 19 additions & 5 deletions apps/frontend/src/components/problem/DataUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@
<VCard :title="t('create-data-version')" variant="flat">
<VCardText>
<VFileInput v-model="uploadInfo.file" />
<VTextField :model-value="uploadInfo.hash" readonly label="SHA256 Hash" />
<VTextField :label="t('term.description')" v-model="uploadInfo.description" />
<VTextField v-model="uploadInfo.hash" :readonly="!advanced" label="SHA256 Hash" />
<VTextField v-model="uploadInfo.description" :label="t('term.description')" />
<VCardSubtitle>{{ t('term.config') }}</VCardSubtitle>
<MonacoEditor v-model="uploadInfo.configJson" language="json" />
</VCardText>
<VCardActions>
<VBtn
prepend-icon="mdi-upload"
rounded="none"
class="my-auto"
variant="tonal"
@click="uploadFileTask.execute()"
:loading="uploadFileTask.isLoading.value"
>
{{ t('action.upload') }}
</VBtn>
<VSpacer />
<VBtnToggle v-model="advanced" mandatory>
<VBtn :value="false">
{{ t('simple-mode') }}
</VBtn>
<VBtn :value="true">
{{ t('advanced-mode') }}
</VBtn>
</VBtnToggle>
</VCardActions>
</VCard>
</template>
Expand Down Expand Up @@ -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')
)
</script>

<i18n>
en:
create-data-version: Create data version
simple-mode: Simple mode
advanced-mode: Advanced mode
zh-Hans:
create-data-version: 创建数据版本
simple-mode: 简单模式
advanced-mode: 高级模式
</i18n>
3 changes: 3 additions & 0 deletions apps/frontend/src/components/utils/JsonViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -64,6 +65,8 @@ const data = useAsyncState(async () => {
const json = await ky.get(url).json<T>()
return json
}, null)
watch([() => props.endpoint, () => props.url, () => props.rawString], () => data.execute())
</script>
<i18n>
en:
Expand Down
7 changes: 7 additions & 0 deletions apps/frontend/src/components/utils/SettingsEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</VWindowItem>
<VWindowItem value="settings">
<RanklistSettings
:key="props.ranklistKey"
:ranklist-key="props.ranklistKey"
:org-id="props.orgId"
:contest-id="props.contestId"
Expand All @@ -31,6 +32,7 @@ import RanklistSettings from '@/components/contest/RanklistSettings.vue'
import { ref } from 'vue'
import RanklistViewer from '@/components/utils/RanklistViewer.vue'
import { useContestCapability } from '@/utils/contest/inject'
import { computed } from 'vue'
const props = defineProps<{
orgId: string
Expand All @@ -48,8 +50,11 @@ const { t } = useI18n()
const currentTab = ref()
const admin = useContestCapability('admin')
const endpoint = `contest/${props.contestId}/ranklist/${encodeURIComponent(props.ranklistKey)}/url`
const endpoint = computed(
() => `contest/${props.contestId}/ranklist/${encodeURIComponent(props.ranklistKey)}/url`
)
</script>

<i18n>
en:
ranklist-settings: Ranklist Settings
Expand Down
21 changes: 13 additions & 8 deletions apps/frontend/src/utils/problem/data.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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'
import { useAsyncTask } from '../async'

export function useDataUpload(problemId: string, updated: () => void) {
const toast = useToast()
const advanced = ref(false)

const uploadInfo = reactive({
file: [] as File[],
Expand All @@ -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?')
Expand All @@ -63,5 +68,5 @@ export function useDataUpload(problemId: string, updated: () => void) {
updated()
})

return { uploadInfo, uploadFileTask }
return { uploadInfo, uploadFileTask, advanced }
}
22 changes: 12 additions & 10 deletions apps/server/src/routes/runner/ranklist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down

0 comments on commit 9fae951

Please sign in to comment.