@xcpcio/board-app 0.23.0 → 0.24.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/about.html +2 -2
  2. package/dist/assets/DataSourceInput.vue_vue_type_script_setup_true_lang-bdd603c5.js +1 -0
  3. package/dist/assets/TheInput.vue_vue_type_script_setup_true_lang-19d39372.js +1 -0
  4. package/dist/assets/{_...all_-bca664b6.css → _...all_-65bba7d0.css} +1 -1
  5. package/dist/assets/_...all_-76798627.js +3 -0
  6. package/dist/assets/_name_-82a33e88.js +1 -0
  7. package/dist/assets/{about-caa3031e.js → about-6cc32222.js} +2 -2
  8. package/dist/assets/{app-dacf61f3.js → app-a6c41ce5.js} +52 -52
  9. package/dist/assets/{board-layout-127eb0a9.js → board-layout-a5587489.js} +1 -1
  10. package/dist/assets/headless-13d3a223.js +1 -0
  11. package/dist/assets/{home-c816ad74.js → home-6560de4b.js} +1 -1
  12. package/dist/assets/index-4ddb0930.js +1 -0
  13. package/dist/assets/{index-517541e1.css → index-da8e69bb.css} +2 -2
  14. package/dist/assets/{index-layout-650bba92.js → index-layout-f4d3ebfe.js} +1 -1
  15. package/dist/assets/test-4090a9c4.js +1 -0
  16. package/dist/assets/{user-5e7a1733.js → user-5e01721a.js} +1 -1
  17. package/dist/assets/{virtual_pwa-register-54c5c068.js → virtual_pwa-register-af30bbb9.js} +1 -1
  18. package/dist/balloon.html +1 -0
  19. package/dist/index.html +1 -1
  20. package/dist/sitemap.xml +1 -1
  21. package/dist/ssr-manifest.json +181 -163
  22. package/dist/sw.js +1 -1
  23. package/dist/test.html +1 -1
  24. package/package.json +3 -3
  25. package/src/auto-imports.d.ts +12 -0
  26. package/src/components/Balloon.vue +99 -0
  27. package/src/components/BalloonBlock.vue +85 -0
  28. package/src/components/{ContestIndex.vue → ContestIndexUI.vue} +3 -3
  29. package/src/components/CustomBalloon.vue +25 -0
  30. package/src/components/CustomBoard.vue +15 -0
  31. package/src/components/{board/CustomBoard.vue → DataSourceInput.vue} +8 -20
  32. package/src/components/board/Board.vue +3 -2
  33. package/src/components/board/TeamUI.vue +4 -1
  34. package/src/components/board/Utility.vue +23 -1
  35. package/src/components.d.ts +6 -3
  36. package/src/composables/constant.ts +3 -0
  37. package/src/composables/query.ts +9 -0
  38. package/src/layouts/headless.vue +7 -0
  39. package/src/pages/balloon/index.vue +10 -0
  40. package/src/pages/index.vue +4 -1
  41. package/src/styles/color.css +8 -0
  42. package/src/styles/main.css +1 -0
  43. package/src/styles/resolver.css +8 -0
  44. package/uno.config.ts +11 -0
  45. package/dist/assets/TheInput.vue_vue_type_script_setup_true_lang-7e223c40.js +0 -1
  46. package/dist/assets/_...all_-f4969270.js +0 -3
  47. package/dist/assets/_name_-8f131dce.js +0 -1
  48. package/dist/assets/test-a2803908.js +0 -1
  49. package/src/components/board/Balloon.vue +0 -5
  50. /package/src/{components → composables}/logo/ccpc.ts +0 -0
  51. /package/src/{components → composables}/logo/hunan-cpc.ts +0 -0
  52. /package/src/{components → composables}/logo/icpc.ts +0 -0
  53. /package/src/{components → composables}/logo/index.ts +0 -0
package/dist/test.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en" data-critters-container><head><meta charset="UTF-8"><!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> --><link rel="apple-touch-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.23.0/dist/balloon-192x192.png"><link rel="mask-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.23.0/dist/balloon-512x512.svg" color="#00aba9"><meta name="msapplication-TileColor" content="#00aba9"><script>function normalizePath(_){for(;_.endsWith("/");)_=_.slice(0,-1);return _+"/"}{let _="__CDN_HOST__";_=normalizePath(_),window.CDN_HOST=_}try{let _=__DATA_HOST__;_=normalizePath(_),window.DATA_HOST=_}catch(_){window.DATA_HOST="/data/"}try{let _=__DATA_REGION__;window.DATA_REGION=_}catch(_){window.DATA_REGION="CN"}</script><script>!function(){var e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,t=localStorage.getItem("vueuse-color-scheme")||"auto";("dark"===t||e&&"light"!==t)&&document.documentElement.classList.toggle("dark",!0)}()</script><script type="module" async crossorigin src="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.23.0/dist/assets/app-dacf61f3.js"></script><link rel="manifest" href="/manifest.webmanifest"><style></style><link rel="modulepreload" crossorigin href="/assets/home-c816ad74.js"><link rel="modulepreload" crossorigin href="/assets/test-a2803908.js"><title>Board - XCPCIO</title><meta name="description" content="XCPCIO-Board 主要收录 *CPC 系列竞赛的榜单。"><meta name="keywords" content="icpc, ccpc, rank, board, standings"><meta name="theme-color" content="#ffffff"><link rel="icon" type="image/svg+xml" href="/favicon.svg"></head><body class="font-sans"><div id="app" data-server-rendered="true"><main px-4 py-10 text="center gray-700 dark:gray-200"><div flex flex-col justify-center items-center><div text-4xl><div i-carbon-campsite></div></div><p><a rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank">Vitesse</a></p><p><em text-sm opacity-75>Opinionated Vite Starter Template</em></p><div py-4></div><div w-48><input id="input" value type="text" placeholder="What's your name?" autocomplete="false" p="x-4 y-2" w-full text="center" bg="transparent" border="~ rounded gray-200 dark:gray-700" outline="none active:none"><label class="hidden" for="input">What's your name?</label></div><div><button m-3 text-sm btn disabled="disabled">GO</button></div></div><footer mt-8 py-4 md:py-8 lg:py-10 w-full flex justify-center items-center><div text-center w-full><a href="/" class flex items-center justify-center text-2xl font-semibold text-gray-900 dark:text-white><div i-ion-balloon-sharp mr-4 h-8></div>Get more balloons</a><p my-6 text-gray-500 dark:text-gray-400 w-full flex justify-center>Open-source project of ICPC/CCPC Standings.</p><ul mb-6 w-full flex flex-wrap items-center justify-center text-gray-900 dark:text-white><li><a href="/" class mr-4 md:mr-6 hover:underline>Home</a></li><li><div class="v-popper v-popper--theme-tooltip" w-inherit><!--[--><!--[--><a href="https://github.com/xcpcio/xcpcio" class="mr-4 md:mr-6 hover:underline" rel="noreferrer" target="_blank" title="GitHub">GitHub</a><!--]--><div id="popper_jbmicdwq_v1wzmy" class="v-popper__popper v-popper--theme-tooltip v-popper__popper--hidden v-popper__popper--hide-to" style="position:absolute;transform:translate3d(0,0,0)" aria-hidden="true" data-popper-placement><div class="v-popper__backdrop"></div><div class="v-popper__wrapper" style><div class="v-popper__inner"><!----></div><div class="v-popper__arrow-container" style="left:0;top:0"><div class="v-popper__arrow-outer"></div><div class="v-popper__arrow-inner"></div></div></div></div><!--]--></div></li><li><div class="v-popper v-popper--theme-tooltip" w-inherit><!--[--><!--[--><a href="mailto:hi@dup4.com" mr-4 md:mr-6 hover:underline>Contact</a><!--]--><div id="popper_1f59ji65_v1wzmz" class="v-popper__popper v-popper--theme-tooltip v-popper__popper--hidden v-popper__popper--hide-to" style="position:absolute;transform:translate3d(0,0,0)" aria-hidden="true" data-popper-placement><div class="v-popper__backdrop"></div><div class="v-popper__wrapper" style><div class="v-popper__inner"><!----></div><div class="v-popper__arrow-container" style="left:0;top:0"><div class="v-popper__arrow-outer"></div><div class="v-popper__arrow-inner"></div></div></div></div><!--]--></div></li></ul><span text-sm text-gray-500 sm:text-center dark:text-gray-400 w-full>© 2020-PRESENT <a href="/" class hover:underline>XCPCIO™</a>. All Rights Reserved.</span></div></footer><div mx-auto mt-5 text-center text-sm opacity-50>[Home Layout]</div></main></div><script>window.__INITIAL_STATE__='{"pinia":{"user":{"savedName":""}}}'</script><noscript>This website requires JavaScript to function properly. Please enable JavaScript to continue.</noscript><script>try{var umamiJSUrl=__UMAMI_JS_URL__,umamiWebsiteId=__UMAMI_WEBSITE_ID__;!function(){var e=document.createElement("script"),t=(e.src=umamiJSUrl,e.defer=!0,e.setAttribute("data-website-id",umamiWebsiteId),document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var plausibleJSUrl=__PLAUSIBLE_JS_URL__,plausibleDataDomain=__PLAUSIBLE_DATA_DOMAIN__;!function(){var e=document.createElement("script"),t=(e.src=plausibleJSUrl,e.defer=!0,e.setAttribute("data-domain",plausibleDataDomain),document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var baiduAnalyticsId=__BAIDU_ANALYTICS_ID__,_hmt=_hmt||[];!function(){var e=document.createElement("script"),t=(e.src="https://hm.baidu.com/hm.js?"+baiduAnalyticsId,document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var googleAnalyticsId=__GOOGLE_ANALYTICS_ID__;!function(){var e,t,a,r;location.port||(e=window,r=document,t="script",a="ga",e.GoogleAnalyticsObject=a,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=+new Date,a=r.createElement(t),r=r.getElementsByTagName(t)[0],a.async=1,a.src="//www.google-analytics.com/analytics.js",r.parentNode.insertBefore(a,r),ga("create",""+googleAnalyticsId,"auto"),ga("send","pageview"))}()}catch(e){}</script></body></html>
1
+ <!DOCTYPE html><html lang="en" data-critters-container><head><meta charset="UTF-8"><!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> --><link rel="apple-touch-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.24.3/dist/balloon-192x192.png"><link rel="mask-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.24.3/dist/balloon-512x512.svg" color="#00aba9"><meta name="msapplication-TileColor" content="#00aba9"><script>function normalizePath(_){for(;_.endsWith("/");)_=_.slice(0,-1);return _+"/"}{let _="__CDN_HOST__";_=normalizePath(_),window.CDN_HOST=_}try{let _=__DATA_HOST__;_=normalizePath(_),window.DATA_HOST=_}catch(_){window.DATA_HOST="/data/"}try{let _=__DATA_REGION__;window.DATA_REGION=_}catch(_){window.DATA_REGION="CN"}</script><script>!function(){var e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,t=localStorage.getItem("vueuse-color-scheme")||"auto";("dark"===t||e&&"light"!==t)&&document.documentElement.classList.toggle("dark",!0)}()</script><script type="module" async crossorigin src="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.24.3/dist/assets/app-a6c41ce5.js"></script><link rel="manifest" href="/manifest.webmanifest"><style></style><link rel="modulepreload" crossorigin href="/assets/home-6560de4b.js"><link rel="modulepreload" crossorigin href="/assets/test-4090a9c4.js"><title>Board - XCPCIO</title><meta name="description" content="XCPCIO-Board 主要收录 *CPC 系列竞赛的榜单。"><meta name="keywords" content="icpc, ccpc, rank, board, standings"><meta name="theme-color" content="#ffffff"><link rel="icon" type="image/svg+xml" href="/favicon.svg"></head><body class="font-sans"><div id="app" data-server-rendered="true"><main px-4 py-10 text="center gray-700 dark:gray-200"><div flex flex-col justify-center items-center><div text-4xl><div i-carbon-campsite></div></div><p><a rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank">Vitesse</a></p><p><em text-sm opacity-75>Opinionated Vite Starter Template</em></p><div py-4></div><div w-48><input id="input" value type="text" placeholder="What's your name?" autocomplete="false" p="x-4 y-2" w-full text="center" bg="transparent" border="~ rounded gray-200 dark:gray-700" outline="none active:none"><label class="hidden" for="input">What's your name?</label></div><div><button m-3 text-sm btn disabled="disabled">GO</button></div></div><footer mt-8 py-4 md:py-8 lg:py-10 w-full flex justify-center items-center><div text-center w-full><a href="/" class flex items-center justify-center text-2xl font-semibold text-gray-900 dark:text-white><div i-ion-balloon-sharp mr-4 h-8></div>Get more balloons</a><p my-6 text-gray-500 dark:text-gray-400 w-full flex justify-center>Open-source project of ICPC/CCPC Standings.</p><ul mb-6 w-full flex flex-wrap items-center justify-center text-gray-900 dark:text-white><li><a href="/" class mr-4 md:mr-6 hover:underline>Home</a></li><li><div class="v-popper v-popper--theme-tooltip" w-inherit><!--[--><!--[--><a href="https://github.com/xcpcio/xcpcio" class="mr-4 md:mr-6 hover:underline" rel="noreferrer" target="_blank" title="GitHub">GitHub</a><!--]--><div id="popper_1vvkpjor_17h6rl" class="v-popper__popper v-popper--theme-tooltip v-popper__popper--hidden v-popper__popper--hide-to" style="position:absolute;transform:translate3d(0,0,0)" aria-hidden="true" data-popper-placement><div class="v-popper__backdrop"></div><div class="v-popper__wrapper" style><div class="v-popper__inner"><!----></div><div class="v-popper__arrow-container" style="left:0;top:0"><div class="v-popper__arrow-outer"></div><div class="v-popper__arrow-inner"></div></div></div></div><!--]--></div></li><li><div class="v-popper v-popper--theme-tooltip" w-inherit><!--[--><!--[--><a href="mailto:hi@dup4.com" mr-4 md:mr-6 hover:underline>Contact</a><!--]--><div id="popper_5she32xz_17h6rl" class="v-popper__popper v-popper--theme-tooltip v-popper__popper--hidden v-popper__popper--hide-to" style="position:absolute;transform:translate3d(0,0,0)" aria-hidden="true" data-popper-placement><div class="v-popper__backdrop"></div><div class="v-popper__wrapper" style><div class="v-popper__inner"><!----></div><div class="v-popper__arrow-container" style="left:0;top:0"><div class="v-popper__arrow-outer"></div><div class="v-popper__arrow-inner"></div></div></div></div><!--]--></div></li></ul><span text-sm text-gray-500 sm:text-center dark:text-gray-400 w-full>© 2020-PRESENT <a href="/" class hover:underline>XCPCIO™</a>. All Rights Reserved.</span></div></footer><div mx-auto mt-5 text-center text-sm opacity-50>[Home Layout]</div></main></div><script>window.__INITIAL_STATE__='{"pinia":{"user":{"savedName":""}}}'</script><noscript>This website requires JavaScript to function properly. Please enable JavaScript to continue.</noscript><script>try{var umamiJSUrl=__UMAMI_JS_URL__,umamiWebsiteId=__UMAMI_WEBSITE_ID__;!function(){var e=document.createElement("script"),t=(e.src=umamiJSUrl,e.defer=!0,e.setAttribute("data-website-id",umamiWebsiteId),document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var plausibleJSUrl=__PLAUSIBLE_JS_URL__,plausibleDataDomain=__PLAUSIBLE_DATA_DOMAIN__;!function(){var e=document.createElement("script"),t=(e.src=plausibleJSUrl,e.defer=!0,e.setAttribute("data-domain",plausibleDataDomain),document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var baiduAnalyticsId=__BAIDU_ANALYTICS_ID__,_hmt=_hmt||[];!function(){var e=document.createElement("script"),t=(e.src="https://hm.baidu.com/hm.js?"+baiduAnalyticsId,document.getElementsByTagName("script")[0]);t.parentNode.insertBefore(e,t)}()}catch(e){}try{var googleAnalyticsId=__GOOGLE_ANALYTICS_ID__;!function(){var e,t,a,r;location.port||(e=window,r=document,t="script",a="ga",e.GoogleAnalyticsObject=a,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=+new Date,a=r.createElement(t),r=r.getElementsByTagName(t)[0],a.async=1,a.src="//www.google-analytics.com/analytics.js",r.parentNode.insertBefore(a,r),ga("create",""+googleAnalyticsId,"auto"),ga("send","pageview"))}()}catch(e){}</script></body></html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xcpcio/board-app",
3
3
  "type": "module",
4
- "version": "0.23.0",
4
+ "version": "0.24.3",
5
5
  "description": "XCPCIO Board App",
6
6
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
7
7
  "license": "MIT",
@@ -53,8 +53,8 @@
53
53
  "vue-router": "^4.2.4",
54
54
  "vue-search-select": "^3.1.2",
55
55
  "vue-toast-notification": "^3",
56
- "@xcpcio/core": "0.23.0",
57
- "@xcpcio/types": "0.23.0"
56
+ "@xcpcio/core": "0.24.3",
57
+ "@xcpcio/types": "0.24.3"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@antfu/eslint-config": "^0.39.8",
@@ -5,8 +5,11 @@
5
5
  // Generated by unplugin-auto-import
6
6
  export {}
7
7
  declare global {
8
+ const BALLOON_TITLE_SUFFIX: typeof import('./composables/constant')['BALLOON_TITLE_SUFFIX']
8
9
  const EffectScope: typeof import('vue')['EffectScope']
9
10
  const Pagination: typeof import('./composables/pagination')['Pagination']
11
+ const RESOLVER_TITLE_SUFFIX: typeof import('./composables/constant')['RESOLVER_TITLE_SUFFIX']
12
+ const TITLE_SUFFIX: typeof import('./composables/constant')['TITLE_SUFFIX']
10
13
  const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
11
14
  const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
12
15
  const class_pagination_ix: typeof import('./composables/pagination')['class_pagination_ix']
@@ -40,6 +43,7 @@ declare global {
40
43
  const extendRef: typeof import('@vueuse/core')['extendRef']
41
44
  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
42
45
  const getCurrentScope: typeof import('vue')['getCurrentScope']
46
+ const getDataSourceUrl: typeof import('./composables/query')['getDataSourceUrl']
43
47
  const getLocalStorageKeyForFilterOrganizations: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']
44
48
  const getLocalStorageKeyForFilterTeams: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']
45
49
  const getProblemChart: typeof import('./composables/statistics')['getProblemChart']
@@ -315,8 +319,11 @@ declare global {
315
319
  import { UnwrapRef } from 'vue'
316
320
  declare module 'vue' {
317
321
  interface ComponentCustomProperties {
322
+ readonly BALLOON_TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['BALLOON_TITLE_SUFFIX']>
318
323
  readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
319
324
  readonly Pagination: UnwrapRef<typeof import('./composables/pagination')['Pagination']>
325
+ readonly RESOLVER_TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['RESOLVER_TITLE_SUFFIX']>
326
+ readonly TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['TITLE_SUFFIX']>
320
327
  readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
321
328
  readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
322
329
  readonly computed: UnwrapRef<typeof import('vue')['computed']>
@@ -345,6 +352,7 @@ declare module 'vue' {
345
352
  readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
346
353
  readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
347
354
  readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
355
+ readonly getDataSourceUrl: UnwrapRef<typeof import('./composables/query')['getDataSourceUrl']>
348
356
  readonly getLocalStorageKeyForFilterOrganizations: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']>
349
357
  readonly getLocalStorageKeyForFilterTeams: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']>
350
358
  readonly getProblemChart: UnwrapRef<typeof import('./composables/statistics')['getProblemChart']>
@@ -611,8 +619,11 @@ declare module 'vue' {
611
619
  }
612
620
  declare module '@vue/runtime-core' {
613
621
  interface ComponentCustomProperties {
622
+ readonly BALLOON_TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['BALLOON_TITLE_SUFFIX']>
614
623
  readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
615
624
  readonly Pagination: UnwrapRef<typeof import('./composables/pagination')['Pagination']>
625
+ readonly RESOLVER_TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['RESOLVER_TITLE_SUFFIX']>
626
+ readonly TITLE_SUFFIX: UnwrapRef<typeof import('./composables/constant')['TITLE_SUFFIX']>
616
627
  readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
617
628
  readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
618
629
  readonly computed: UnwrapRef<typeof import('vue')['computed']>
@@ -641,6 +652,7 @@ declare module '@vue/runtime-core' {
641
652
  readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
642
653
  readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
643
654
  readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
655
+ readonly getDataSourceUrl: UnwrapRef<typeof import('./composables/query')['getDataSourceUrl']>
644
656
  readonly getLocalStorageKeyForFilterOrganizations: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']>
645
657
  readonly getLocalStorageKeyForFilterTeams: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']>
646
658
  readonly getProblemChart: UnwrapRef<typeof import('./composables/statistics')['getProblemChart']>
@@ -0,0 +1,99 @@
1
+ <script setup lang="ts">
2
+ import { Rank, createContest, createSubmissions, createTeams } from "@xcpcio/core";
3
+ import type { Contest, Submissions, Teams } from "@xcpcio/core";
4
+ import type { Contest as IContest, Submissions as ISubmissions, Teams as ITeams } from "@xcpcio/types";
5
+
6
+ import { BALLOON_TITLE_SUFFIX } from "~/composables/constant";
7
+
8
+ const props = defineProps<{
9
+ dataSourceUrl: string,
10
+ }>();
11
+
12
+ const title = useTitle(BALLOON_TITLE_SUFFIX);
13
+ const { t } = useI18n();
14
+
15
+ const firstLoaded = ref(false);
16
+ const contestData = ref({} as Contest);
17
+ const teamsData = ref([] as Teams);
18
+ const submissionsData = ref([] as Submissions);
19
+ const rank = ref({} as Rank);
20
+ const now = ref(new Date());
21
+
22
+ function reBuildBalloons() {
23
+ const newRank = new Rank(contestData.value, teamsData.value, submissionsData.value);
24
+ newRank.buildBalloons();
25
+ rank.value = newRank;
26
+ }
27
+
28
+ const { data, isError, error } = useQueryBoardData(props.dataSourceUrl, now);
29
+ watch(data, async () => {
30
+ if (data.value === null || data.value === undefined) {
31
+ return;
32
+ }
33
+
34
+ contestData.value = createContest(data.value?.contest as IContest);
35
+ title.value = `${contestData.value.name} | ${BALLOON_TITLE_SUFFIX}`;
36
+
37
+ teamsData.value = createTeams(data.value?.teams as ITeams);
38
+ submissionsData.value = createSubmissions(data.value?.submissions as ISubmissions);
39
+
40
+ reBuildBalloons();
41
+
42
+ firstLoaded.value = true;
43
+ });
44
+
45
+ const balloons = computed(() => {
46
+ return rank.value.balloons;
47
+ });
48
+
49
+ const setNowIntervalId = setInterval(() => {
50
+ now.value = new Date();
51
+ }, 1000);
52
+
53
+ onUnmounted(() => {
54
+ clearInterval(setNowIntervalId);
55
+ });
56
+ </script>
57
+
58
+ <template>
59
+ <div
60
+ class="bg-[#323443]"
61
+ text-gray-200
62
+ >
63
+ <div v-if="!firstLoaded">
64
+ <div
65
+ flex flex-col
66
+ justify-center items-center
67
+ w-screen
68
+ h-screen
69
+ text-xl italic
70
+ >
71
+ <div>
72
+ {{ t("common.loading") }}...
73
+ </div>
74
+
75
+ <div v-if="isError">
76
+ {{ error }}
77
+ </div>
78
+ </div>
79
+ </div>
80
+
81
+ <div
82
+ v-else
83
+ >
84
+ <div
85
+ flex flex-col justify-between
86
+ >
87
+ <template
88
+ v-for="(b, ix) in balloons"
89
+ :key="b.key"
90
+ >
91
+ <BalloonBlock
92
+ :index="ix"
93
+ :balloon="b"
94
+ />
95
+ </template>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </template>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ import type { Balloon, Team } from "@xcpcio/core";
3
+ import type { ThemeColor } from "@xcpcio/types";
4
+
5
+ const props = defineProps<{
6
+ index: number;
7
+ balloon: Balloon,
8
+ }>();
9
+
10
+ const balloon = computed(() => {
11
+ return props.balloon;
12
+ });
13
+
14
+ const el = ref(null);
15
+ const isVisible = useElementVisibility(el);
16
+
17
+ function showTeamName(team: Team) {
18
+ const sections = [team.location, team.organization, team.name];
19
+ return sections.filter(s => s).join(" - ");
20
+ }
21
+
22
+ function getColor(c: ThemeColor): string {
23
+ if (typeof c === "string") {
24
+ return c;
25
+ }
26
+
27
+ if (isDark && c?.dark) {
28
+ return c.dark;
29
+ }
30
+
31
+ return c.light;
32
+ }
33
+ </script>
34
+
35
+ <template>
36
+ <div
37
+ ref="el"
38
+ h-24
39
+ >
40
+ <div
41
+ v-if="isVisible"
42
+ h-24
43
+ flex flex-row gap-x-4
44
+ font-mono text-4xl
45
+ :class="[props.index % 2 === 0 ? 'bg-resolver-bg-zero' : 'bg-resolver-bg-one']"
46
+ >
47
+ <div
48
+ w-20
49
+ flex flex-shrink-0 justify-center items-center
50
+ :style="{
51
+ backgroundColor: getColor(balloon.problem!.balloonColor!.background_color),
52
+ }"
53
+ >
54
+ <div
55
+ :style="{
56
+ color: getColor(balloon.problem!.balloonColor!.color),
57
+ }"
58
+ >
59
+ {{ balloon.problem.label }}
60
+ </div>
61
+ </div>
62
+
63
+ <div
64
+ flex flex-1 flex-col justify-center items-start
65
+ >
66
+ <div
67
+ class="resolver-team-name"
68
+ truncate overflow-hidden
69
+ >
70
+ {{ showTeamName(balloon.team) }}
71
+ </div>
72
+ <div
73
+ flex flex-row text-sm items-start gap-x-2
74
+ />
75
+ </div>
76
+
77
+ <div
78
+ w-32
79
+ flex flex-shrink-0 flex-row justify-start items-center
80
+ >
81
+ {{ balloon.submission.timestampToMinute }}
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </template>
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
+ import { useElementVisibility } from "@vueuse/core";
3
+
2
4
  import type { ContestIndex } from "@xcpcio/core";
3
5
  import { getImageSource } from "@xcpcio/core";
4
6
 
5
- import { useElementVisibility } from "@vueuse/core";
6
-
7
- import { getLogoFromPreset } from "./logo";
7
+ import { getLogoFromPreset } from "~/composables/logo";
8
8
 
9
9
  const props = defineProps<{
10
10
  data: ContestIndex
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { getDataSourceUrl } from "~/composables/query";
3
+
4
+ const dataSourceUrl = getDataSourceUrl();
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-if="dataSourceUrl.length === 0"
10
+ >
11
+ <div
12
+ mt-20
13
+ >
14
+ <DataSourceInput />
15
+ </div>
16
+ </div>
17
+
18
+ <div
19
+ v-if="dataSourceUrl.length > 0"
20
+ >
21
+ <Balloon
22
+ :data-source-url="dataSourceUrl"
23
+ />
24
+ </div>
25
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import { getDataSourceUrl } from "~/composables/query";
3
+
4
+ const dataSourceUrl = getDataSourceUrl();
5
+ </script>
6
+
7
+ <template>
8
+ <DataSourceInput />
9
+
10
+ <div v-if="dataSourceUrl.length > 0">
11
+ <Board
12
+ :data-source-url="dataSourceUrl"
13
+ />
14
+ </div>
15
+ </template>
@@ -1,35 +1,29 @@
1
1
  <script setup lang="ts">
2
- import { useRouteQuery } from "@vueuse/router";
3
-
4
- const dataSourceUrlFromRouteQuery = useRouteQuery(
5
- "data-source",
6
- "",
7
- { transform: String },
8
- );
2
+ import { getDataSourceUrl } from "~/composables/query";
9
3
 
10
4
  const { t } = useI18n();
11
5
 
12
- const dataSourceUrl = ref("");
6
+ const dataSourceUrl = getDataSourceUrl();
13
7
  const dataSourceUrlText = "Data Source URL";
8
+ const dataSourceUrlInput = ref(dataSourceUrl.value);
14
9
 
10
+ const route = useRoute();
15
11
  const router = useRouter();
16
12
  function go() {
17
- if (dataSourceUrl.value) {
18
- router.push(`/board/?data-source=${dataSourceUrl.value.trim()}`);
19
- }
13
+ router.push(`${route.fullPath}/?data-source=${dataSourceUrlInput.value.trim()}`);
20
14
  }
21
15
  </script>
22
16
 
23
17
  <template>
24
18
  <div
25
- v-if="dataSourceUrlFromRouteQuery.length === 0"
19
+ v-if="dataSourceUrl.length === 0"
26
20
  class="flex flex-col items-center"
27
21
  >
28
22
  <div
29
23
  w-128
30
24
  >
31
25
  <TheInput
32
- v-model="dataSourceUrl"
26
+ v-model="dataSourceUrlInput"
33
27
  w-full
34
28
  :placeholder="dataSourceUrlText"
35
29
  autocomplete="false"
@@ -45,17 +39,11 @@ function go() {
45
39
  <div>
46
40
  <button
47
41
  m-3 text-sm btn
48
- :disabled="!dataSourceUrl"
42
+ :disabled="dataSourceUrlInput.length === 0"
49
43
  @click="go"
50
44
  >
51
45
  {{ t('button.go') }}
52
46
  </button>
53
47
  </div>
54
48
  </div>
55
-
56
- <div v-else>
57
- <Board
58
- :data-source-url="dataSourceUrlFromRouteQuery"
59
- />
60
- </div>
61
49
  </template>
@@ -7,6 +7,7 @@ import { Rank, RankOptions, createContest, createSubmissions, createTeams, getTi
7
7
  import type { Contest, Submissions, Teams } from "@xcpcio/core";
8
8
  import { ContestState, type Contest as IContest, type Submissions as ISubmissions, type Teams as ITeams } from "@xcpcio/types";
9
9
 
10
+ import { TITLE_SUFFIX } from "~/composables/constant";
10
11
  import type { Item } from "~/components/board/SecondLevelMenu.vue";
11
12
 
12
13
  const props = defineProps<{
@@ -14,7 +15,7 @@ const props = defineProps<{
14
15
  }>();
15
16
 
16
17
  const route = useRoute();
17
- const title = useTitle();
18
+ const title = useTitle(TITLE_SUFFIX);
18
19
  const { t } = useI18n();
19
20
 
20
21
  const firstLoaded = ref(false);
@@ -77,7 +78,7 @@ watch(data, async () => {
77
78
  }
78
79
 
79
80
  contestData.value = createContest(data.value?.contest as IContest);
80
- title.value = `${contestData.value.name} - XCPCIO Board`;
81
+ title.value = `${contestData.value.name} | ${TITLE_SUFFIX}`;
81
82
 
82
83
  teamsData.value = createTeams(data.value?.teams as ITeams);
83
84
  submissionsData.value = createSubmissions(data.value?.submissions as ISubmissions);
@@ -43,7 +43,10 @@ function getStandClassName(t: Team, isRankField = false): string {
43
43
  }
44
44
  }
45
45
 
46
- return `stand${(rank.value.rankStatistics.maxSolvedProblems - t.solvedProblemNum) % 2}${(t.rank - 1) % 2}`;
46
+ const solvedProblemIndex = (rank.value.rankStatistics.getTeamSolvedNumIndex(t.solvedProblemNum) - 1) % 2;
47
+ const rankIndex = (t.rank - 1) % 2;
48
+
49
+ return `stand${solvedProblemIndex}${rankIndex}`;
47
50
  }
48
51
 
49
52
  function isRenderByVisible() {
@@ -6,15 +6,21 @@
6
6
  const { t } = useI18n();
7
7
 
8
8
  const route = useRoute();
9
+ const router = useRouter();
9
10
 
10
11
  const resolverUrl = computed(() => {
11
12
  return `https://resolver.xcpcio.com/resolver?xcpcio-data-source=${route.path}`;
12
13
  });
14
+
15
+ function goBalloon() {
16
+ router.push(`/balloon/?data-source=${route.path}`);
17
+ }
13
18
  </script>
14
19
 
15
20
  <template>
16
21
  <div
17
- flex w-full mt-4
22
+ w-full
23
+ flex mt-4 gap-4
18
24
  >
19
25
  <a
20
26
  btn
@@ -24,5 +30,21 @@ const resolverUrl = computed(() => {
24
30
  >
25
31
  {{ t("type_menu.resolver") }}
26
32
  </a>
33
+
34
+ <button
35
+ btn
36
+ title="Balloon"
37
+ @click="goBalloon"
38
+ >
39
+ {{ t('type_menu.balloon') }}
40
+ </button>
41
+
42
+ <button
43
+ btn
44
+ title="Submissions"
45
+ disabled="true"
46
+ >
47
+ {{ t('type_menu.submissions') }}
48
+ </button>
27
49
  </div>
28
50
  </template>
@@ -8,12 +8,15 @@ export {}
8
8
  declare module 'vue' {
9
9
  export interface GlobalComponents {
10
10
  Badge: typeof import('./components/board/Badge.vue')['default']
11
- Balloon: typeof import('./components/board/Balloon.vue')['default']
11
+ Balloon: typeof import('./components/Balloon.vue')['default']
12
+ BalloonBlock: typeof import('./components/BalloonBlock.vue')['default']
12
13
  Board: typeof import('./components/board/Board.vue')['default']
13
14
  BottomStatistics: typeof import('./components/board/BottomStatistics.vue')['default']
14
- ContestIndex: typeof import('./components/ContestIndex.vue')['default']
15
+ ContestIndexUI: typeof import('./components/ContestIndexUI.vue')['default']
15
16
  ContestStateBadge: typeof import('./components/board/ContestStateBadge.vue')['default']
16
- CustomBoard: typeof import('./components/board/CustomBoard.vue')['default']
17
+ CustomBalloon: typeof import('./components/CustomBalloon.vue')['default']
18
+ CustomBoard: typeof import('./components/CustomBoard.vue')['default']
19
+ DataSourceInput: typeof import('./components/DataSourceInput.vue')['default']
17
20
  Export: typeof import('./components/board/Export.vue')['default']
18
21
  Footer: typeof import('./components/Footer.vue')['default']
19
22
  GirlIcon: typeof import('./components/icon/GirlIcon.vue')['default']
@@ -0,0 +1,3 @@
1
+ export const TITLE_SUFFIX = "Board - XCPCIO";
2
+ export const BALLOON_TITLE_SUFFIX = "Balloon - XCPCIO";
3
+ export const RESOLVER_TITLE_SUFFIX = "Resolver - XCPCIO";
@@ -0,0 +1,9 @@
1
+ import { useRouteQuery } from "@vueuse/router";
2
+
3
+ export function getDataSourceUrl() {
4
+ return useRouteQuery(
5
+ "data-source",
6
+ "",
7
+ { transform: String },
8
+ );
9
+ }
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <main
3
+ text-gray-700 dark:text-gray-200
4
+ >
5
+ <RouterView />
6
+ </main>
7
+ </template>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <div>
3
+ <CustomBalloon />
4
+ </div>
5
+ </template>
6
+
7
+ <route lang="yaml">
8
+ meta:
9
+ layout: headless
10
+ </route>
@@ -5,9 +5,12 @@ import { useRouteQuery } from "@vueuse/router";
5
5
  import { createContestIndexList } from "@xcpcio/core";
6
6
  import type { ContestIndexList } from "@xcpcio/core";
7
7
 
8
+ import { TITLE_SUFFIX } from "~/composables/constant";
8
9
  import SearchInput from "~/components/SearchInput.vue";
10
+ import ContestIndexUI from "~/components/ContestIndexUI.vue";
9
11
 
10
12
  const { t } = useI18n();
13
+ useTitle(TITLE_SUFFIX);
11
14
 
12
15
  const now = ref(new Date());
13
16
  const url = ref(`${window.DATA_HOST}index/contest_list.json?t=${now.value.getTime()}`);
@@ -106,7 +109,7 @@ watch(searchText, () => {
106
109
  v-for="item in contestIndexList"
107
110
  :key="item.boardLink"
108
111
  >
109
- <ContestIndex
112
+ <ContestIndexUI
110
113
  :data="item"
111
114
  />
112
115
  </template>
@@ -22,6 +22,14 @@ html {
22
22
  --theme-status-skipped: #78909C;
23
23
  --theme-status-unknown: #000;
24
24
  --theme-status-undefined: var(--theme-status-unknown);
25
+
26
+ --theme-resolver-ac: #5eb95e;
27
+ --theme-resolver-wa: #dd514c;
28
+ --theme-resolver-pending: #607D8B;
29
+ --theme-resolver-untouched: #1f1f1f;
30
+ --theme-resolver-selected: #406b82;
31
+ --theme-resolver-bg-0: #3e3e3e;
32
+ --theme-resolver-bg-1: #030712;
25
33
  }
26
34
 
27
35
  html.dark {
@@ -1,5 +1,6 @@
1
1
  @import './markdown.css';
2
2
  @import './color.css';
3
+ @import './resolver.css';
3
4
 
4
5
  html,
5
6
  body,
@@ -0,0 +1,8 @@
1
+ .resolver-uncover {
2
+ animation: flashing 300ms infinite;
3
+ -webkit-animation: flashing 30ms infinite; /*Safari and Chrome*/
4
+ }
5
+
6
+ .resolver-team-name {
7
+ max-width: calc(100vw - 80px - 192px - 112px);
8
+ }
package/uno.config.ts CHANGED
@@ -25,6 +25,17 @@ export default defineConfig({
25
25
  900: "#1e3a8a",
26
26
  950: "#172554",
27
27
  },
28
+ resolver: {
29
+ ac: "var(--theme-resolver-ac)",
30
+ wa: "var(--theme-resolver-wa)",
31
+ pending: "var(--theme-resolver-pending)",
32
+ untouched: "var(--theme-resolver-untouched)",
33
+ selected: "var(--theme-resolver-selected)",
34
+ bg: {
35
+ zero: "var(--theme-resolver-bg-0)",
36
+ one: "var(--theme-resolver-bg-1)",
37
+ },
38
+ },
28
39
  },
29
40
  },
30
41
  shortcuts: [
@@ -1 +0,0 @@
1
- import{g as o,az as l,$ as r,a0 as s,j as u,o as p,c as d,aA as i,k as m}from"./app-dacf61f3.js";const f=o({__name:"TheInput",props:{modelValue:null},emits:["update:modelValue"],setup(_){const{modelValue:e}=l("modelValue");return(a,t)=>r((p(),d("input",i({id:"input","onUpdate:modelValue":t[0]||(t[0]=n=>m(e)?e.value=n:null),type:"text"},a.$attrs,{p:"x-4 y-2","w-full":"",text:"center",bg:"transparent",border:"~ rounded gray-200 dark:gray-700",outline:"none active:none"}),null,16)),[[s,u(e)]])}});export{f as _};