-
-
Notifications
You must be signed in to change notification settings - Fork 10
✨ Enable to show task table for ABC212 - (#1611) #1614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
ca6c8ac
✨ Add task table tab for ABC212 - (#1611)
KATO-Hiro 15f9e7d
✨ Select ABC212 - tasks (#1611)
KATO-Hiro abd8767
♻️ Rename (#1611)
KATO-Hiro 4416a23
:bug: Fix conflict (#1611)
KATO-Hiro 630892e
:books: Add future tasks to comment (#1611)
KATO-Hiro 04f6fe7
:books: Add future tasks to comment (#1611)
KATO-Hiro 013db18
✨ Show task title in task table (#1611)
KATO-Hiro 9f14afe
:art: Show external links and add styles (#1611)
KATO-Hiro 2063e77
:art: Add components and styles (#1611)
KATO-Hiro 09b753b
Merge branch 'staging' of github.com:KATO-Hiro/AtCoderNoviceProblemsS…
KATO-Hiro 9403c08
✨ Add textOverflow and iconSize (#1611)
KATO-Hiro dec29c5
:art: Add and update styles (#1611)
KATO-Hiro fd9d7f0
:art: Enable to hide icon (#1611)
KATO-Hiro 2f36609
:art: Add submission status icon and colors (#1611)
KATO-Hiro a7218b9
✨ Add helper method (#1611)
KATO-Hiro 2969d75
:art: Add and update styles (#1611)
KATO-Hiro 1213b78
Merge branch 'staging' of github.com:KATO-Hiro/AtCoderNoviceProblemsS…
KATO-Hiro f654aea
:art: Fix title position and size (#1611)
KATO-Hiro 026409a
:art: Fix icon size (#1611)
KATO-Hiro 4f96b9d
♻️ Split image and text (#1611)
KATO-Hiro 47aff4b
:art: Fix layout (#1611)
KATO-Hiro 6923c67
✨ Enable to update submission status from task table (#1611)
KATO-Hiro a34c7d5
♻️ Extract component (#1611)
KATO-Hiro dd7c19a
:art: Improve layout (#1611)
KATO-Hiro 0fb55e0
:bug: Fix lint error (#1611)
KATO-Hiro c05abd8
:art: Improve accessibility (#1611)
KATO-Hiro a40715d
♻️ Extract method (#1611)
KATO-Hiro d45bd4d
:art: Improve styles (#1611)
KATO-Hiro a88893a
📖 Add docs (#1611)
KATO-Hiro 0ea88fb
🚨 Add tests for task table header name (#1611)
KATO-Hiro cc8845c
📖 Add and update docs (#1611)
KATO-Hiro 37c1018
♻️ Extract method (#1611)
KATO-Hiro da519fa
📖 Update docs (#1611)
KATO-Hiro f6f55ba
:art: Add accessibility attributes (#1611)
KATO-Hiro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/lib/components/SubmissionStatus/IconForUpdating.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| <script lang="ts"> | ||
| // @ts-ignore | ||
| import ChevronDownOutline from 'flowbite-svelte-icons/ChevronDownOutline.svelte'; | ||
|
|
||
| export let isLoggedIn: boolean; | ||
| </script> | ||
|
|
||
| <!-- HACK: 以下のコンポーネントと類似しているが、差分が大きいため別コンポーネントとして用意 --> | ||
| <!-- src/lib/components/SubmissionStatus/SubmissionStatusImage.svelte --> | ||
| {#if isLoggedIn} | ||
| <div class="flex items-center justify-center text-sm"> | ||
| <div class="dark:text-gray-300"> | ||
| {'更新'} | ||
| </div> | ||
|
|
||
| <ChevronDownOutline class="w-4 h-4 text-primary-600 dark:text-gray-300 inline" /> | ||
| </div> | ||
| {/if} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| <script lang="ts"> | ||
| import { | ||
| Heading, | ||
| ButtonGroup, | ||
| Button, | ||
| Table, | ||
| TableBody, | ||
| TableBodyCell, | ||
| TableBodyRow, | ||
| TableHead, | ||
| TableHeadCell, | ||
| } from 'flowbite-svelte'; | ||
|
|
||
| import type { TaskResults, TaskResult } from '$lib/types/task'; | ||
| import { ContestType } from '$lib/types/contest'; | ||
|
|
||
| import UpdatingModal from '$lib/components/SubmissionStatus/UpdatingModal.svelte'; | ||
| import TaskTableBodyCell from '$lib/components/TaskTables/TaskTableBodyCell.svelte'; | ||
|
|
||
| import { classifyContest, getContestNameLabel } from '$lib/utils/contest'; | ||
| import { getTaskTableHeaderName } from '$lib/utils/task'; | ||
| import { getBackgroundColorFrom } from '$lib/services/submission_status'; | ||
|
|
||
| export let taskResults: TaskResults; | ||
| export let isLoggedIn: boolean; | ||
|
|
||
| let selectedTaskResults: TaskResults; | ||
| let contestIds: Array<string>; | ||
| let taskTableIndices: Array<string>; | ||
| let taskTable: Record<string, Record<string, TaskResult>>; | ||
| let updatingModal: UpdatingModal; | ||
|
|
||
| // TODO: 任意のコンテスト種別に拡張 | ||
| $: selectedTaskResults = filterTaskResultsByContestType(taskResults, fromABC212_Onwards); | ||
| $: contestIds = getContestIds(selectedTaskResults); | ||
| $: taskTableIndices = getTaskTableIndices(selectedTaskResults, ContestType.ABC); | ||
| $: taskTable = prepareTaskTable(selectedTaskResults, ContestType.ABC); | ||
|
|
||
| function filterTaskResultsByContestType( | ||
| taskResults: TaskResults, | ||
| condition: (taskResult: TaskResult) => boolean, | ||
| ): TaskResults { | ||
| return taskResults.filter(condition); | ||
| } | ||
|
|
||
| // Note: | ||
| // Before and from ABC212 onwards, the number and tendency of tasks are very different. | ||
| const fromABC212_Onwards = (taskResult: TaskResult) => | ||
| classifyContest(taskResult.contest_id) === ContestType.ABC && taskResult.contest_id >= 'abc212'; | ||
|
|
||
| function getContestIds(selectedTaskResults: TaskResults): Array<string> { | ||
| const contestList = selectedTaskResults.map((taskResult: TaskResult) => taskResult.contest_id); | ||
| return Array.from(new Set(contestList)).sort().reverse(); | ||
| } | ||
|
|
||
| function getTaskTableIndices( | ||
| selectedTaskResults: TaskResults, | ||
| selectedContestType: ContestType, | ||
| ): Array<string> { | ||
| const headerList = selectedTaskResults.map((taskResult: TaskResult) => | ||
| getTaskTableHeaderName(selectedContestType, taskResult), | ||
| ); | ||
| return Array.from(new Set(headerList)).sort(); | ||
| } | ||
|
|
||
| /** | ||
| * Prepare a table for task and submission statuses. | ||
| * | ||
| * Computational complexity of preparation table: O(N), where N is the number of task results. | ||
| * Computational complexity of accessing table: O(1). | ||
| * | ||
| * @param selectedTaskResults Task results to be shown in the table. | ||
| * @param selectedContestType Contest type of the task results. | ||
| * @returns A table for task and submission statuses. | ||
| */ | ||
| function prepareTaskTable( | ||
| selectedTaskResults: TaskResults, | ||
| selectedContestType: ContestType, | ||
| ): Record<string, Record<string, TaskResult>> { | ||
| const table: Record<string, Record<string, TaskResult>> = {}; | ||
|
|
||
| selectedTaskResults.forEach((taskResult: TaskResult) => { | ||
| const contestId = taskResult.contest_id; | ||
| const taskTableIndex = getTaskTableHeaderName(selectedContestType, taskResult); | ||
|
|
||
| if (!table[contestId]) { | ||
| table[contestId] = {}; | ||
| } | ||
|
|
||
| table[contestId][taskTableIndex] = taskResult; | ||
| }); | ||
|
|
||
| return table; | ||
| } | ||
|
|
||
| function getContestNameLabelForTaskTable(contestId: string): string { | ||
| let contestNameLabel = getContestNameLabel(contestId); | ||
| const contestType = classifyContest(contestId); | ||
|
|
||
| switch (contestType) { | ||
| case ContestType.ABC: | ||
| return contestNameLabel.replace('ABC ', ''); | ||
| // TODO: Add cases for other contest types. | ||
| default: | ||
| return contestNameLabel; | ||
| } | ||
| } | ||
|
|
||
| function getBodyCellClasses(contestId: string, taskIndex: string): string { | ||
| const baseClasses = 'w-1/2 xs:w-1/3 sm:w-1/4 md:w-1/5 lg:w-1/6 px-1 py-1 border'; | ||
| const backgroundColor = getBackgroundColor(taskTable[contestId][taskIndex]); | ||
|
|
||
| return `${baseClasses} ${backgroundColor}`; | ||
| } | ||
|
|
||
| function getBackgroundColor(taskResult: TaskResult): string { | ||
| const statusName = taskResult?.status_name; | ||
|
|
||
| if (taskResult && statusName !== 'ns') { | ||
| return getBackgroundColorFrom(statusName); | ||
| } | ||
|
|
||
| return ''; | ||
| } | ||
| </script> | ||
|
|
||
| <!-- TODO: コンテスト種別のボタンの並び順を決める --> | ||
| <!-- See: --> | ||
| <!-- https://flowbite-svelte.com/docs/components/button-group --> | ||
| <ButtonGroup class="m-4 contents-center" aria-label="Contest filter options"> | ||
| <Button | ||
| on:click={() => filterTaskResultsByContestType(taskResults, fromABC212_Onwards)} | ||
| aria-label="Filter contests from ABC212 onwards" | ||
| > | ||
| ABC212〜 | ||
| </Button> | ||
| </ButtonGroup> | ||
|
|
||
| <!-- TODO: コンテスト種別に応じて動的に変更できるようにする --> | ||
| <Heading tag="h2" class="text-2xl pb-3 text-gray-900 dark:text-white"> | ||
| {'AtCoder Beginners Contest 212 〜'} | ||
| </Heading> | ||
|
|
||
| <!-- TODO: ページネーションを実装 --> | ||
| <!-- TODO: ページネーションライブラリを導入するには、Svelte v4 から v5 へのアップデートが必要 --> | ||
| <!-- See: --> | ||
| <!-- https://github.com/kenkoooo/AtCoderProblems/blob/master/atcoder-problems-frontend/src/pages/TablePage/AtCoderRegularTable.tsx --> | ||
| <!-- https://github.com/birdou/atcoder-blogs/blob/main/app/atcoder-blogs-frontend/src/pages/BlogTablePage/BlogTablePage.tsx --> | ||
| <div class="container w-full overflow-auto border rounded-md"> | ||
| <Table shadow id="task-table" class="text-md table-fixed" aria-label="Task table"> | ||
| <TableHead class="text-sm bg-gray-100"> | ||
| <TableHeadCell class="w-full xl:w-16 px-2 text-center border" scope="col">Round</TableHeadCell | ||
| > | ||
|
|
||
| {#if taskTableIndices.length} | ||
| {#each taskTableIndices as taskTableIndex} | ||
| <TableHeadCell class="text-center border" scope="col">{taskTableIndex}</TableHeadCell> | ||
| {/each} | ||
| {/if} | ||
| </TableHead> | ||
|
|
||
| <TableBody tableBodyClass="divide-y"> | ||
| {#if contestIds.length && taskTableIndices.length} | ||
| {#each contestIds as contestId} | ||
| <TableBodyRow class="flex flex-wrap xl:table-row"> | ||
| <TableBodyCell class="w-full xl:w-16 truncate px-2 py-2 text-center border"> | ||
| <!-- FIXME: コンテスト種別に合わせて修正できるようにする --> | ||
| {getContestNameLabelForTaskTable(contestId)} | ||
| </TableBodyCell> | ||
|
|
||
| {#each taskTableIndices as taskIndex} | ||
| <TableBodyCell | ||
| key={contestId + '-' + taskIndex} | ||
| class={getBodyCellClasses(contestId, taskIndex)} | ||
| > | ||
| {#if taskTable[contestId][taskIndex]} | ||
| <TaskTableBodyCell | ||
| taskResult={taskTable[contestId][taskIndex]} | ||
| {isLoggedIn} | ||
| {updatingModal} | ||
| /> | ||
| {/if} | ||
| </TableBodyCell> | ||
| {/each} | ||
| </TableBodyRow> | ||
| {/each} | ||
| {/if} | ||
| </TableBody> | ||
| </Table> | ||
| </div> | ||
|
|
||
| <UpdatingModal bind:this={updatingModal} {isLoggedIn} /> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <script lang="ts"> | ||
| import type { TaskResult } from '$lib/types/task'; | ||
|
|
||
| import ExternalLinkWrapper from '$lib/components/ExternalLinkWrapper.svelte'; | ||
| import GradeLabel from '$lib/components/GradeLabel.svelte'; | ||
| import IconForUpdating from '$lib/components/SubmissionStatus/IconForUpdating.svelte'; | ||
| import UpdatingModal from '$lib/components/SubmissionStatus/UpdatingModal.svelte'; | ||
|
|
||
| import { getTaskUrl } from '$lib/utils/task'; | ||
|
|
||
| export let taskResult: TaskResult; | ||
| export let isLoggedIn: boolean; | ||
| export let updatingModal: UpdatingModal; | ||
| </script> | ||
|
|
||
| <!-- Task title and an external link --> | ||
| <div class="text-left text-md sm:text-lg"> | ||
| <ExternalLinkWrapper | ||
| url={getTaskUrl(taskResult.contest_id, taskResult.task_id)} | ||
| description={taskResult.title} | ||
| textSize="xs:text-md" | ||
| textColorInDarkMode="dark:text-gray-300" | ||
| textOverflow="min-w-[60px] max-w-[120px]" | ||
| iconSize={0} | ||
| /> | ||
| </div> | ||
|
|
||
| <div class="flex items-center justify-between py-1"> | ||
| <!-- Task grade --> | ||
| <GradeLabel taskGrade={taskResult.grade} defaultPadding={0.25} defaultWidth={8} /> | ||
|
|
||
| <!-- Submission updater and links of task detail page --> | ||
| <button | ||
| type="button" | ||
| class="mx-2 w-8 text-center" | ||
| on:click={() => updatingModal.openModal(taskResult)} | ||
| aria-label="Update submission for {taskResult.title}" | ||
| > | ||
| <IconForUpdating {isLoggedIn} /> | ||
| </button> | ||
|
|
||
| <!-- TODO: Add link of detailed page. --> | ||
| <div class="flex-1 text-center text-sm dark:text-gray-300 max-w-[32px]"> | ||
| {'詳細'} | ||
| </div> | ||
KATO-Hiro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </div> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.