├── lib.js ├── components ├── katex │ ├── katex.styl │ └── katex.page.js ├── scratchpad │ ├── var.inc.styl │ ├── Panel.page.styl │ ├── Editor.page.styl │ ├── reducers │ │ ├── index.js │ │ ├── editor.js │ │ ├── pretest.js │ │ └── records.js │ ├── PanelButton.page.styl │ ├── DataInput.page.styl │ ├── PanelButtonComponent.jsx │ ├── PanelComponent.jsx │ ├── DataInputComponent.jsx │ ├── scratchpad.page.styl │ └── Toolbar.page.styl ├── nprogress │ └── index.js ├── header │ ├── header-logo.png │ ├── header-logo@2x.png │ ├── header-background.png │ ├── header-logo-summer.png │ ├── header-background@2x.png │ └── header-logo-summer@2x.png ├── problem │ ├── rp.page.styl │ └── tag.page.styl ├── profile │ ├── backgrounds │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ ├── 7.jpg │ │ ├── 8.jpg │ │ ├── 9.jpg │ │ ├── 10.jpg │ │ ├── 11.jpg │ │ ├── 12.jpg │ │ ├── 13.jpg │ │ ├── 14.jpg │ │ ├── 15.jpg │ │ ├── 16.jpg │ │ ├── 17.jpg │ │ ├── 18.jpg │ │ ├── 19.jpg │ │ ├── 20.jpg │ │ ├── 21.jpg │ │ ├── thumbnail │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ ├── 9.jpg │ │ │ ├── 10.jpg │ │ │ ├── 11.jpg │ │ │ ├── 12.jpg │ │ │ ├── 13.jpg │ │ │ ├── 14.jpg │ │ │ ├── 15.jpg │ │ │ ├── 16.jpg │ │ │ ├── 17.jpg │ │ │ ├── 18.jpg │ │ │ ├── 19.jpg │ │ │ ├── 20.jpg │ │ │ └── 21.jpg │ │ └── gen_thumbnails.sh │ └── profile.page.styl ├── contest │ ├── problem-contest-bg.png │ ├── problem-contest-bg@2x.png │ ├── contest_sidebar.page.styl │ └── contest.page.styl ├── navigation │ ├── nav-logo-small_dark.png │ ├── nav-logo-small_light.png │ ├── nav-logo-small@2x_dark.png │ └── nav-logo-small@2x_light.png ├── tab │ ├── var.inc.styl │ └── tab.page.js ├── emoji │ ├── emoji.page.styl │ └── emojify.page.js ├── autocomplete │ ├── userselectautocomplete.page.styl │ ├── domainselectautocomplete.page.styl │ └── autocomplete.page.styl ├── react-splitpane │ ├── SplitPaneFillOverlay.page.styl │ ├── SplitPaneFillOverlayComponent.jsx │ └── splitpane.page.styl ├── marker │ ├── marker.page.js │ └── marker.page.styl ├── dropdown │ ├── dropdown.page.js │ └── dropdown.page.styl ├── table │ └── styledTable.page.js ├── form │ ├── var.inc.styl │ ├── form.page.js │ ├── textbox.page.js │ └── select.page.styl ├── messagepad │ ├── reducers │ │ ├── index.js │ │ ├── inputs.js │ │ ├── activeId.js │ │ ├── isPosting.js │ │ └── dialogues.js │ ├── DialogueListItem.page.styl │ ├── MessageComponent.jsx │ └── DialogueListItemComponent.jsx ├── star │ ├── star.page.styl │ └── star.page.js ├── rotator │ └── rotator.page.styl ├── discussion │ └── discussion.page.styl ├── react │ ├── IconComponent.jsx │ └── DomComponent.jsx ├── highlighter │ ├── highlighter.page.js │ ├── codemirror.page.styl │ └── meta.js ├── menu │ ├── menu.page.js │ └── menu-heading.page.js ├── cmeditor │ ├── cmeditor.page.js │ └── textareaHandler.js ├── loader │ └── loader.page.styl ├── datepicker │ └── datepicker.page.js ├── record │ └── record.page.styl ├── training │ └── training.page.styl ├── dialog │ └── dialog.page.styl ├── tooltip │ ├── tooltip.page.js │ └── Tooltip.js ├── pager │ └── pager.page.styl ├── hitokoto │ └── index.page.js ├── footer │ └── footer.page.js ├── message │ └── index.page.js ├── notification │ └── notification.page.styl ├── vote │ └── vote.page.js └── drop │ └── drop.page.styl ├── .vscode ├── settings.json └── extensions.json ├── constant ├── message.js ├── util │ └── objectMeta.js ├── setting.js ├── model.js └── domain.js ├── breakpoints.json ├── static ├── favicon.ico ├── img │ ├── avatar.png │ └── team_avatar.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon-96x96.png ├── mstile-144x144.png ├── android-chrome-192x192.png ├── apple-touch-icon-180x180.png └── manifest.json ├── postcss.config.js ├── .gitignore ├── misc ├── immersive-background.jpg ├── immersive-background@2x.jpg ├── icons │ ├── send.svg │ ├── add.svg │ ├── check.svg │ ├── flag.svg │ ├── chevron_left.svg │ ├── chevron_right.svg │ ├── expand_less.svg │ ├── expand_more.svg │ ├── italic.svg │ ├── upload.svg │ ├── download.svg │ ├── formula.svg │ ├── statistics.svg │ ├── warning.svg │ ├── star.svg │ ├── code.svg │ ├── quote.svg │ ├── close.svg │ ├── reply.svg │ ├── delete.svg │ ├── logout.svg │ ├── play.svg │ ├── hourglass.svg │ ├── info--circle.svg │ ├── check--circle.svg │ ├── edit.svg │ ├── platform--windows.svg │ ├── user.svg │ ├── security.svg │ ├── heart.svg │ ├── link--external.svg │ ├── copy.svg │ ├── stack.svg │ ├── vote--up.svg │ ├── calendar.svg │ ├── template │ │ ├── webicon.inc.styl │ │ └── webicon.styl │ ├── close--circle.svg │ ├── star--outline.svg │ ├── lab.svg │ ├── vote--down.svg │ ├── facebook.svg │ ├── mail.svg │ ├── insert--image.svg │ ├── ordered_list.svg │ ├── platform--mobile.svg │ ├── shrink.svg │ ├── enlarge.svg │ ├── refresh.svg │ ├── schedule--fill.svg │ ├── info.svg │ ├── tag.svg │ ├── comment--text.svg │ ├── crown.svg │ ├── account--circle.svg │ ├── comment--multiple.svg │ ├── google_plus.svg │ ├── help2.svg │ ├── erase.svg │ ├── linkedin.svg │ ├── bold.svg │ ├── user--multiple.svg │ ├── global.svg │ ├── heart--outline.svg │ ├── search.svg │ ├── platform--unknown.svg │ ├── filter.svg │ ├── block.svg │ ├── platform--ios.svg │ ├── schedule.svg │ ├── insert--link.svg │ ├── award.svg │ ├── debug.svg │ ├── homework.svg │ ├── sliders.svg │ ├── twitter.svg │ ├── qq.svg │ ├── platform--chromeos.svg │ ├── file.svg │ ├── preview.svg │ ├── wrench.svg │ ├── feeling-lucky.svg │ ├── unordered_list.svg │ ├── github.svg │ ├── settings.svg │ ├── wechat.svg │ ├── help.svg │ ├── web.svg │ ├── platform--android.svg │ ├── platform--mac.svg │ ├── link.svg │ └── platform--linux.svg ├── textalign.styl ├── float.styl ├── nothing.styl ├── immersive.styl ├── slideout.styl └── PageLoader.js ├── pages ├── discussion_node_bg │ ├── nodes_qa.png │ ├── nodes@2x_qa.png │ ├── nodes_advice.png │ ├── nodes_share.png │ ├── nodes_vijos.png │ ├── nodes@2x_share.png │ ├── nodes@2x_vijos.png │ ├── nodes_solution.png │ ├── nodes@2x_advice.png │ └── nodes@2x_solution.png ├── domain_role.page.styl ├── problem_files.page.styl ├── problem_import.page.js ├── domain_user.page.styl ├── home_account.page.styl ├── domain_join.page.styl ├── problem_submit.page.styl ├── status.page.styl ├── contest_detail.page.styl ├── homework_detail.page.styl ├── contest_main.page.js ├── ranking.page.styl ├── problem_submit.page.js ├── discussion_node.page.js ├── homework_main.page.styl ├── problem_solution.page.js ├── discussion_detail.page.js ├── home_domain.page.styl ├── domain_permission.page.styl ├── discussion_detail.page.styl ├── homework_scoreboard.page.styl ├── record_detail.page.styl ├── contest_scoreboard.page.styl ├── home_security.page.styl ├── record_detail.page.js ├── domain_join_applications.page.js ├── training_detail.page.styl ├── user_detail.page.js ├── training_edit.page.js ├── manage_user_import.page.js ├── manage_script.page.js ├── error.page.styl ├── discussion_main.page.styl ├── training_main.page.styl ├── record_main.page.styl ├── record_main.page.js ├── manage_dashboard.page.js └── homework_main.page.js ├── templates ├── layout │ ├── simple.html │ ├── home_base.html │ ├── wiki_base.html │ ├── basic.html │ └── immersive.html ├── partials │ ├── homework_default_penalty_rules.yaml │ ├── problem_stat.html │ ├── hamburger.html │ ├── header.html │ ├── training_default.json │ ├── header_mobile.html │ ├── problem_lucky.html │ ├── problem_default.md │ ├── problem_sidebar.html │ ├── discussion_nodes_widget.html │ ├── path.html │ └── category.html ├── domain_edit.html ├── manage_setting.html ├── components │ ├── nothing.html │ ├── contest.html │ ├── homework.html │ ├── noscript_note.html │ ├── sidemenu.html │ ├── record.html │ ├── home.html │ └── paginator.html ├── home_settings.html ├── user_register_mail_sent.html ├── user_changemail_mail_sent.html ├── user_lostpass_mail_sent.html ├── user_register_mail.html ├── user_lostpass_mail.html ├── user_changemail_mail.html ├── user_delete_pending.html ├── problem_submit_tr.html ├── user_logout.html ├── problem_statistics.html ├── record_detail_summary.html ├── error.html ├── home_messages.html ├── manage_user_import.html ├── problem_upload.html ├── user_lostpass.html ├── user_register.html ├── manage_base.html ├── fs_upload.html ├── problem_import.html ├── user_lostpass_with_code.html ├── contest_boardcast.html ├── domain_dashboard.html ├── manage_dashboard.html ├── discussion_create.html ├── contest_scoreboard_download_html.html ├── user_register_with_code.html ├── discussion_edit.html ├── domain_join.html └── domain_base.html ├── entry.js ├── .npmignore ├── common ├── rem.inc.styl ├── functions.inc.styl ├── color.inc.styl └── common.inc.styl ├── utils ├── delay.js ├── zIndexManager.js ├── i18n.js ├── substitute.js ├── zip.js ├── parseQueryString.js ├── mediaQuery.js ├── mongoId.js ├── emulateAnchorClick.js ├── tpl.js ├── pipeStream.js └── loadReactRedux.js ├── jsconfig.json ├── .gitpod.yml ├── README.md ├── modules.js ├── .github └── workflows │ └── build.yml ├── theme └── default.js └── babel.config.js /lib.js: -------------------------------------------------------------------------------- 1 | require('./backendlib/template'); 2 | -------------------------------------------------------------------------------- /components/katex/katex.styl: -------------------------------------------------------------------------------- 1 | .katex 2 | font-size: 1.2em 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.eol": "\n", 3 | "editor.tabSize": 2 4 | } -------------------------------------------------------------------------------- /constant/message.js: -------------------------------------------------------------------------------- 1 | export const FLAG_UNREAD = 1; 2 | export const FLAG_ALERT = 2; 3 | -------------------------------------------------------------------------------- /breakpoints.json: -------------------------------------------------------------------------------- 1 | { 2 | "mobile": 600, 3 | "desktop": 1000, 4 | "hd": 1250 5 | } 6 | -------------------------------------------------------------------------------- /components/scratchpad/var.inc.styl: -------------------------------------------------------------------------------- 1 | $panel-header-height = 34px 2 | $tab-color = #fff170 3 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /static/img/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/img/avatar.png -------------------------------------------------------------------------------- /components/nprogress/index.js: -------------------------------------------------------------------------------- 1 | import NProgress from 'nprogress'; 2 | 3 | export default NProgress; 4 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | *.log 3 | node_modules/ 4 | public/ 5 | __* 6 | misc/.iconfont 7 | static/locale 8 | -------------------------------------------------------------------------------- /static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/favicon-96x96.png -------------------------------------------------------------------------------- /static/img/team_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/img/team_avatar.png -------------------------------------------------------------------------------- /static/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/mstile-144x144.png -------------------------------------------------------------------------------- /misc/immersive-background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/misc/immersive-background.jpg -------------------------------------------------------------------------------- /components/header/header-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-logo.png -------------------------------------------------------------------------------- /components/problem/rp.page.styl: -------------------------------------------------------------------------------- 1 | .problem__rp-tag 2 | font-size: 0.8em 3 | padding: rem(0 5px) 4 | color: #AAA 5 | -------------------------------------------------------------------------------- /misc/immersive-background@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/misc/immersive-background@2x.jpg -------------------------------------------------------------------------------- /static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /components/header/header-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-logo@2x.png -------------------------------------------------------------------------------- /components/profile/backgrounds/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/1.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/2.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/3.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/4.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/5.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/6.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/7.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/8.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/9.jpg -------------------------------------------------------------------------------- /static/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/static/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /components/profile/backgrounds/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/10.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/11.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/12.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/13.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/14.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/15.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/16.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/17.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/18.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/19.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/20.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/21.jpg -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes_qa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes_qa.png -------------------------------------------------------------------------------- /components/contest/problem-contest-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/contest/problem-contest-bg.png -------------------------------------------------------------------------------- /components/header/header-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-background.png -------------------------------------------------------------------------------- /components/header/header-logo-summer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-logo-summer.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes@2x_qa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes@2x_qa.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes_advice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes_advice.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes_share.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes_vijos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes_vijos.png -------------------------------------------------------------------------------- /pages/domain_role.page.styl: -------------------------------------------------------------------------------- 1 | .page--domain_role 2 | .col--checkbox 3 | width: 60px 4 | 5 | .col--users 6 | width: 100px 7 | -------------------------------------------------------------------------------- /pages/problem_files.page.styl: -------------------------------------------------------------------------------- 1 | .page--problem_files 2 | .col--checkbox 3 | width: 60px 4 | 5 | .col--size 6 | width: 120px 7 | -------------------------------------------------------------------------------- /components/header/header-background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-background@2x.png -------------------------------------------------------------------------------- /components/header/header-logo-summer@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/header/header-logo-summer@2x.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes@2x_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes@2x_share.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes@2x_vijos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes@2x_vijos.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes_solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes_solution.png -------------------------------------------------------------------------------- /templates/layout/simple.html: -------------------------------------------------------------------------------- 1 | {% set layout_name = "basic" %} 2 | {% extends "layout/html5.html" %} 3 | {% block body %} 4 | {% endblock %} 5 | -------------------------------------------------------------------------------- /templates/partials/homework_default_penalty_rules.yaml: -------------------------------------------------------------------------------- 1 | # Format: 2 | # hours: coefficient 3 | 1: 0.9 4 | 3: 0.8 5 | 12: 0.75 6 | 9999: 0.5 7 | -------------------------------------------------------------------------------- /components/contest/problem-contest-bg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/contest/problem-contest-bg@2x.png -------------------------------------------------------------------------------- /components/navigation/nav-logo-small_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/navigation/nav-logo-small_dark.png -------------------------------------------------------------------------------- /components/navigation/nav-logo-small_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/navigation/nav-logo-small_light.png -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/1.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/2.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/3.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/4.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/5.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/6.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/7.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/8.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/9.jpg -------------------------------------------------------------------------------- /misc/icons/send.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes@2x_advice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes@2x_advice.png -------------------------------------------------------------------------------- /pages/discussion_node_bg/nodes@2x_solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/pages/discussion_node_bg/nodes@2x_solution.png -------------------------------------------------------------------------------- /components/navigation/nav-logo-small@2x_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/navigation/nav-logo-small@2x_dark.png -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/10.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/11.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/12.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/13.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/14.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/15.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/16.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/17.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/18.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/19.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/20.jpg -------------------------------------------------------------------------------- /components/profile/backgrounds/thumbnail/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/profile/backgrounds/thumbnail/21.jpg -------------------------------------------------------------------------------- /entry.js: -------------------------------------------------------------------------------- 1 | window.Hydro = { 2 | extraPages: [], 3 | components: {}, 4 | utils: {}, 5 | node_modules: {}, 6 | }; 7 | 8 | import('./hydro'); 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ 3 | build/ 4 | common/ 5 | components/ 6 | constant/ 7 | misc/ 8 | pages/ 9 | static/ 10 | utils/ 11 | __* 12 | -------------------------------------------------------------------------------- /common/rem.inc.styl: -------------------------------------------------------------------------------- 1 | rem() { 2 | ret = (); 3 | for arg in arguments { 4 | push(ret, unit(arg / $font-size, 'rem')); 5 | } 6 | return ret; 7 | } 8 | -------------------------------------------------------------------------------- /components/navigation/nav-logo-small@2x_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hydro-dev/ui-default/HEAD/components/navigation/nav-logo-small@2x_light.png -------------------------------------------------------------------------------- /components/tab/var.inc.styl: -------------------------------------------------------------------------------- 1 | $tab-item-height = 35px 2 | $tab-item-shadow-size = 10px 3 | $tab-item-height-mobile = 32px // 32 * (13 / 16) is an integer 4 | -------------------------------------------------------------------------------- /misc/icons/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/check.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/flag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/problem_stat.html: -------------------------------------------------------------------------------- 1 |
2 |

{{ _('{0} problems').format(pcount) }}

3 |
-------------------------------------------------------------------------------- /misc/icons/chevron_left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/chevron_right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/expand_less.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/expand_more.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/emoji/emoji.page.styl: -------------------------------------------------------------------------------- 1 | .emoji 2 | width: 1em 3 | height: 1em 4 | display: inline-block 5 | background-size: contain 6 | vertical-align: baseline 7 | -------------------------------------------------------------------------------- /misc/icons/italic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /utils/delay.js: -------------------------------------------------------------------------------- 1 | export default function delay(ms) { 2 | return new Promise((resolve) => setTimeout(resolve, ms)); 3 | } 4 | 5 | window.Hydro.utils.delay = delay; 6 | -------------------------------------------------------------------------------- /misc/icons/upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/formula.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/statistics.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/warning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/problem_import.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('problem_import', async () => { 4 | }); 5 | 6 | export default page; 7 | -------------------------------------------------------------------------------- /misc/icons/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/domain_user.page.styl: -------------------------------------------------------------------------------- 1 | .page--domain_user 2 | .col--checkbox 3 | width: 60px 4 | 5 | .col--uid 6 | width: 100px 7 | 8 | .col--role 9 | width: 160px 10 | -------------------------------------------------------------------------------- /misc/icons/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/quote.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/domain_edit.html: -------------------------------------------------------------------------------- 1 | {% extends "domain_base.html" %} 2 | {% block domain_content %} 3 |
4 | {% include "partials/setting.html" %} 5 |
6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /templates/manage_setting.html: -------------------------------------------------------------------------------- 1 | {% extends "manage_base.html" %} 2 | {% block manage_content %} 3 |
4 | {% include "partials/setting.html" %} 5 |
6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /components/autocomplete/userselectautocomplete.page.styl: -------------------------------------------------------------------------------- 1 | .menu.user-select 2 | width: rem(200px) 3 | 4 | .user-select__uid 5 | font-size: rem($font-size-small) 6 | color: $userselect-uid-color 7 | -------------------------------------------------------------------------------- /misc/icons/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/reply.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/home_account.page.styl: -------------------------------------------------------------------------------- 1 | .page--home_account 2 | [name="form_item_background_img"] .radiobox__image 3 | width: rem(100px) 4 | height: rem(62px) 5 | background-size: rem(100px 62px) 6 | -------------------------------------------------------------------------------- /components/autocomplete/domainselectautocomplete.page.styl: -------------------------------------------------------------------------------- 1 | .menu.domain-select 2 | width: rem(200px) 3 | 4 | .domain-select__id 5 | font-size: rem($font-size-small) 6 | color: $userselect-uid-color 7 | -------------------------------------------------------------------------------- /misc/icons/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/logout.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "gruntfuggly.todo-tree", 5 | "ronnidc.nunjucks", 6 | "sysoev.language-stylus" 7 | ] 8 | } -------------------------------------------------------------------------------- /misc/textalign.styl: -------------------------------------------------------------------------------- 1 | .text-center 2 | text-align: center 3 | 4 | .text-right 5 | text-align: right 6 | 7 | .text-left 8 | text-align: left 9 | 10 | .text-justify 11 | text-align: justify 12 | -------------------------------------------------------------------------------- /misc/icons/hourglass.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hydro", 3 | "icons": [ 4 | { 5 | "src": "\/android-chrome-192x192.png", 6 | "sizes": "192x192", 7 | "type": "image\/png", 8 | "density": 4 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /misc/icons/info--circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/check--circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/platform--windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/profile/backgrounds/gen_thumbnails.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for f in *.jpg 4 | do 5 | echo "$f..." 6 | convert "$f" -strip -interlace Plane -quality 92 -resize 200x124^ -gravity center -extent 200x124 "thumbnail/$f" 7 | done 8 | -------------------------------------------------------------------------------- /components/react-splitpane/SplitPaneFillOverlay.page.styl: -------------------------------------------------------------------------------- 1 | .splitpane-fill 2 | display: flex 3 | position: absolute 4 | overflow: hidden 5 | left: 0 6 | width: 100% 7 | top: 0 8 | height: 100% 9 | user-select: none 10 | -------------------------------------------------------------------------------- /templates/components/nothing.html: -------------------------------------------------------------------------------- 1 | {% macro render(text, compact=false) %} 2 |
3 |
4 | {{ _(text) }} 5 |
6 | {% endmacro %} 7 | -------------------------------------------------------------------------------- /misc/icons/security.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /constant/util/objectMeta.js: -------------------------------------------------------------------------------- 1 | export default function attachObjectMeta(obj, key, value) { 2 | Object.defineProperty(obj, `__${key}`, { 3 | value, 4 | enumerable: false, 5 | configurable: false, 6 | writable: false, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /misc/icons/heart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/link--external.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/domain_join.page.styl: -------------------------------------------------------------------------------- 1 | .page--domain_join 2 | .domain_join__container 3 | +above(rupture.mobile-cutoff) 4 | width: rem(500px) 5 | margin: rem(50px) auto 6 | 7 | +above(rupture.desktop-cutoff) 8 | width: rem(700px) 9 | -------------------------------------------------------------------------------- /templates/home_settings.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/home_base.html" %} 2 | {% block home_content %} 3 |
4 | {% include "partials/setting.html" %} 5 |
6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /components/scratchpad/Panel.page.styl: -------------------------------------------------------------------------------- 1 | @import './var.inc.styl' 2 | 3 | .scratchpad__panel-title 4 | background: $primary-color 5 | line-height: rem($panel-header-height) 6 | padding: rem(0 5px) 7 | font-size: rem($font-size-small) 8 | color: #FFF 9 | -------------------------------------------------------------------------------- /misc/float.styl: -------------------------------------------------------------------------------- 1 | .float-left 2 | float: left 3 | 4 | .float-right 5 | float: right 6 | 7 | .clearfix:after 8 | visibility: hidden 9 | display: block 10 | font-size: 0 11 | content: ' ' 12 | clear: both 13 | height: 0 14 | zoom: 1 15 | -------------------------------------------------------------------------------- /misc/icons/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/hamburger.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /common/functions.inc.styl: -------------------------------------------------------------------------------- 1 | word-wrap() 2 | overflow-wrap: break-word 3 | word-wrap: break-word 4 | -ms-word-break: break-all 5 | word-break: break-word 6 | -ms-hyphens: auto 7 | -moz-hyphens: auto 8 | -webkit-hyphens: auto 9 | hyphens: auto 10 | -------------------------------------------------------------------------------- /components/tab/tab.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import Tab from './Tab'; 3 | 4 | const tabPage = new AutoloadPage('tabPage', () => { 5 | Tab.initAll(); 6 | Tab.initEventListeners(); 7 | }); 8 | 9 | export default tabPage; 10 | -------------------------------------------------------------------------------- /misc/icons/stack.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/vote--up.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/marker/marker.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import MarkerReactive from './MarkerReactive'; 3 | 4 | const markerPage = new AutoloadPage('markerPage', () => { 5 | MarkerReactive.initAll(); 6 | }); 7 | 8 | export default markerPage; 9 | -------------------------------------------------------------------------------- /misc/icons/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/template/webicon.inc.styl: -------------------------------------------------------------------------------- 1 | $icon-font-name = '{{ options.fontName }}' 2 | 3 | {% for icon in glyphs %} 4 | $icon-{{ icon.name }} = '\{{ icon.unicode[0].charCodeAt(0).toString(16)|upper }}' 5 | $icon-{{ icon.name }}-file = '{{ icon.name }}.svg' 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /components/dropdown/dropdown.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import Dropdown from './Dropdown'; 3 | 4 | const dropdownPage = new AutoloadPage('dropdownPage', () => { 5 | Dropdown.registerLifeCycleHooks(); 6 | }); 7 | 8 | export default dropdownPage; 9 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "allowSyntheticDefaultImports": true, 5 | "target": "ES6", 6 | "baseUrl": ".", 7 | "paths": { 8 | "vj/*": [ 9 | "./*" 10 | ] 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /misc/icons/close--circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/star--outline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/problem_submit.page.styl: -------------------------------------------------------------------------------- 1 | .page--problem_submit 2 | .col--status 3 | width: rem(150px) 4 | 5 | .col--submit-at 6 | width: rem(160px) 7 | text-align: center 8 | 9 | +mobile() 10 | .col--memory, 11 | .col--time 12 | display: none 13 | -------------------------------------------------------------------------------- /misc/icons/lab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/vote--down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/table/styledTable.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import StyledTable from './StyledTable'; 3 | 4 | const styledTablePage = new AutoloadPage('styledTablePage', () => { 5 | StyledTable.registerLifeCycleHooks(); 6 | }); 7 | 8 | export default styledTablePage; 9 | -------------------------------------------------------------------------------- /pages/status.page.styl: -------------------------------------------------------------------------------- 1 | .page--status 2 | .col--id 3 | width: 70px 4 | 5 | .col--status 6 | width: 100px 7 | 8 | .col--memory 9 | width: 150px 10 | 11 | .col--request 12 | width: 100px 13 | 14 | +mobile() 15 | .col--os 16 | .col--cpu 17 | display: none -------------------------------------------------------------------------------- /utils/zIndexManager.js: -------------------------------------------------------------------------------- 1 | let zIndexCurrent = 1000; 2 | 3 | const manager = { 4 | getCurrent() { 5 | return zIndexCurrent; 6 | }, 7 | getNext() { 8 | return ++zIndexCurrent; 9 | }, 10 | }; 11 | 12 | export default manager; 13 | window.Hydro.utils.zIndexManager = manager; 14 | -------------------------------------------------------------------------------- /misc/icons/insert--image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/header.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | {% include "partials/path.html" %} 6 |
7 | -------------------------------------------------------------------------------- /misc/icons/ordered_list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/contest_detail.page.styl: -------------------------------------------------------------------------------- 1 | .page--contest_detail 2 | .col--status 3 | width: rem(150px) 4 | 5 | .col--submit-at 6 | width: rem(150px) 7 | 8 | .col--problem 9 | border-left: 1px solid $table-border-color 10 | 11 | +mobile() 12 | .col--submit-at 13 | display: none 14 | -------------------------------------------------------------------------------- /pages/homework_detail.page.styl: -------------------------------------------------------------------------------- 1 | .page--homework_detail 2 | .col--status 3 | width: rem(150px) 4 | 5 | .col--submit-at 6 | width: rem(150px) 7 | 8 | .col--problem 9 | border-left: 1px solid $table-border-color 10 | 11 | +mobile() 12 | .col--submit-at 13 | display: none -------------------------------------------------------------------------------- /misc/icons/platform--mobile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/shrink.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-mongodb 2 | tasks: 3 | - init: yarn && yarn build 4 | vscode: 5 | extensions: 6 | - dbaeumer.vscode-eslint@2.1.3:1NRvj3UKNTNwmYjptmUmIw== 7 | - vscode-icons-team.vscode-icons@10.2.0:DrQUJPtFm0woSFiyitha8Q== 8 | - samuelcolvin.jinjahtml@0.12.0:lFI6zKplznEZPdWvFvRHwg== 9 | -------------------------------------------------------------------------------- /components/autocomplete/autocomplete.page.styl: -------------------------------------------------------------------------------- 1 | .drop-element.autocomplete 2 | max-width: rem(250px) 3 | 4 | .empty-row 5 | color: $autocomplete-empty-row-color 6 | font-size: $(font-size-small) 7 | padding: rem(10px) 8 | 9 | .menu 10 | max-height: rem(250px) 11 | overflow: auto 12 | -------------------------------------------------------------------------------- /misc/icons/enlarge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/schedule--fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/contest_main.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('contest_main', () => { 4 | // Contest Filter 5 | $('[name="filter-form"] [name="rule"]').change(() => { 6 | $('[name="filter-form"]').submit(); 7 | }); 8 | }); 9 | 10 | export default page; 11 | -------------------------------------------------------------------------------- /utils/i18n.js: -------------------------------------------------------------------------------- 1 | import substitute from './substitute'; 2 | 3 | export default function i18n(str, ...params) { 4 | if (window.LOCALES && window.LOCALES[str]) { 5 | return substitute(window.LOCALES[str], params); 6 | } 7 | return substitute(str, params); 8 | } 9 | 10 | window.Hydro.utils.i18n = i18n; 11 | -------------------------------------------------------------------------------- /utils/substitute.js: -------------------------------------------------------------------------------- 1 | export default function substitute(str, obj) { 2 | return str.replace(/\{([^{}]+)\}/g, (match, key) => { 3 | if (obj[key] !== undefined) { 4 | return String(obj[key]); 5 | } 6 | return `{${key}}`; 7 | }); 8 | } 9 | 10 | window.Hydro.utils.substitute = substitute; 11 | -------------------------------------------------------------------------------- /misc/icons/info.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/tag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /utils/zip.js: -------------------------------------------------------------------------------- 1 | import 'streamsaver/examples/zip-stream'; 2 | 3 | export const createZipStream = window.ZIP; 4 | 5 | export async function createZipBlob(underlyingSource) { 6 | return new Response(createZipStream(underlyingSource)).blob(); 7 | } 8 | 9 | window.Hydro.utils.zip = { createZipStream, createZipBlob }; 10 | -------------------------------------------------------------------------------- /pages/ranking.page.styl: -------------------------------------------------------------------------------- 1 | .page--ranking 2 | .col--rank 3 | width: rem(70px) 4 | position: relative 5 | 6 | .col--user 7 | width: rem(200px) 8 | text-align: center 9 | 10 | .col--rp 11 | width: rem(80px) 12 | text-align: right 13 | 14 | +mobile() 15 | .col--bio 16 | display: none 17 | -------------------------------------------------------------------------------- /templates/partials/training_default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "_id": 1, 4 | "title": "最初的最初 - A+B Problem", 5 | "requireNids": [], 6 | "pids": [1000, "56c52ade2fefd90539000005"] 7 | }, 8 | { 9 | "_id": 2, 10 | "title": "最初的进阶", 11 | "requireNids": [1], 12 | "pids": [1001, 1002] 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /misc/icons/comment--text.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/crown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/user_register_mail_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |

{{ _('Sign Up') }}

5 |
6 | {{ _('Sign up mail has been sent to your email.') }} 7 |
8 |
9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /misc/icons/account--circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/comment--multiple.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/user_changemail_mail_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |

{{ _('New Email') }}

5 |
6 | {{ _('Confirmation mail has been sent to your new email.') }} 7 |
8 |
9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /templates/user_lostpass_mail_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |

{{ _('Lost Password') }}

5 |
6 | {{ _('Password reset mail has been sent to your email.') }} 7 |
8 |
9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /components/scratchpad/Editor.page.styl: -------------------------------------------------------------------------------- 1 | .ScratchpadMonacoEditor 2 | flex: 1 3 | position: relative 4 | overflow: hidden 5 | 6 | .cm-s-vjcm 7 | position: absolute 8 | left: 0 9 | top: 0 10 | width: 100% 11 | height: 100% 12 | font-family: $code-font-family 13 | font-size: rem($font-size-secondary) 14 | line-height: 1.2 15 | -------------------------------------------------------------------------------- /misc/icons/google_plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/nothing.styl: -------------------------------------------------------------------------------- 1 | .nothing-placeholder 2 | padding: rem(80px 0) 3 | text-align: center 4 | font-size: rem($font-size-title) 5 | color: #AAA 6 | 7 | &.compact 8 | padding: rem(20px 0) 9 | 10 | .nothing-icon 11 | background: url(./puzzled_twd2.svg) no-repeat center center 12 | height: 184px 13 | margin-bottom: rem(20px) 14 | -------------------------------------------------------------------------------- /templates/user_register_mail.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/mail.html" %} 2 | {% block title %}{{ _('Sign Up') }}{% endblock %} 3 | {% block content %} 4 |

{{ _('Hello! You can click following link to sign up your Hydro account:') }}

5 |

{{ url_prefix|safe }}{{ path|safe }}

6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /templates/components/contest.html: -------------------------------------------------------------------------------- 1 | {% import "components/user.html" as user with context %} 2 | {% macro render_time(tdoc_time) %} 3 | {{ datetimeSpan(tdoc_time, false, '%Y-%m-%d %H:%M')|safe }} 4 | {% endmacro %} 5 | 6 | {% macro render_duration(tdoc) %} 7 | {{ ((tdoc.endAt.getTime() - tdoc.beginAt.getTime()) /1000 / 3600)|round(1) }} 8 | {% endmacro %} 9 | -------------------------------------------------------------------------------- /components/scratchpad/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import ui from './ui'; 3 | import editor from './editor'; 4 | import pretest from './pretest'; 5 | import records from './records'; 6 | 7 | const reducer = combineReducers({ 8 | ui, 9 | editor, 10 | pretest, 11 | records, 12 | }); 13 | 14 | export default reducer; 15 | -------------------------------------------------------------------------------- /misc/icons/help2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/components/homework.html: -------------------------------------------------------------------------------- 1 | {% import "components/user.html" as user with context %} 2 | {% macro render_time(tdoc_time) %} 3 | {{ datetimeSpan(tdoc_time, false, '%Y-%m-%d %H:%M')|safe }} 4 | {% endmacro %} 5 | 6 | {% macro render_extension(tdoc) %} 7 | {{ ((tdoc['endAt'].getTime() - tdoc['penaltySince'].getTime())/ 1000 / 3600)|round(1) }} 8 | {% endmacro %} 9 | -------------------------------------------------------------------------------- /templates/user_lostpass_mail.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/mail.html" %} 2 | {% block title %}{{ _('Lost Password') }}{% endblock %} 3 | {% block content %} 4 |

{{ _('Hello, {0}! You can click following link to reset the password of your Hydro account:').format(uname) }}

5 |

{{ url_prefix }}{{ url }}

6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /pages/problem_submit.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('problem_submit', async () => { 4 | $(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => { 5 | $(ev.currentTarget).hide(); 6 | $('[name="problem-sidebar__categories"]').show(); 7 | }); 8 | }); 9 | 10 | export default page; 11 | -------------------------------------------------------------------------------- /templates/user_changemail_mail.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/mail.html" %} 2 | {% block title %}{{ _('Change Email') }}{% endblock %} 3 | {% block content %} 4 |

{{ _('Hello, {0}! You can click following link to active your new email of your Hydro account:').format(uname) }}

5 |

{{ url_prefix }}{{ url }}

6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /components/form/var.inc.styl: -------------------------------------------------------------------------------- 1 | form-styles() 2 | appearance: none 3 | display: block 4 | width: 100% 5 | font-size: rem($font-size-secondary) 6 | margin: $input-margin 7 | height: rem($form-control-height) 8 | line-height: 1.2 9 | padding: rem(5px) 10 | border: $input-border 11 | 12 | &.inline 13 | display: inline-block 14 | width: auto 15 | -------------------------------------------------------------------------------- /misc/icons/erase.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/discussion_node.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('discussion_node', async () => { 4 | $(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => { 5 | $(ev.currentTarget).hide(); 6 | $('[name="problem-sidebar__categories"]').show(); 7 | }); 8 | }); 9 | 10 | export default page; 11 | -------------------------------------------------------------------------------- /pages/homework_main.page.styl: -------------------------------------------------------------------------------- 1 | $highlight-button-color = #F6DF45 2 | 3 | .page--homework_main 4 | .homework__title 5 | line-height: 1.2em 6 | margin-bottom: rem(10px) 7 | font-size: rem($font-size-title) 8 | 9 | .homework__info-attended 10 | color: $success-color 11 | 12 | .homework__date 13 | margin-right: rem(10px) 14 | white-space: nowrap -------------------------------------------------------------------------------- /pages/problem_solution.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('problem_solution', async () => { 4 | $(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => { 5 | $(ev.currentTarget).hide(); 6 | $('[name="problem-sidebar__categories"]').show(); 7 | }); 8 | }); 9 | 10 | export default page; 11 | -------------------------------------------------------------------------------- /pages/discussion_detail.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('discussion_detail', async () => { 4 | $(document).on('click', '[name="problem-sidebar__show-category"]', (ev) => { 5 | $(ev.currentTarget).hide(); 6 | $('[name="problem-sidebar__categories"]').show(); 7 | }); 8 | }); 9 | 10 | export default page; 11 | -------------------------------------------------------------------------------- /components/scratchpad/PanelButton.page.styl: -------------------------------------------------------------------------------- 1 | @import './var.inc.styl' 2 | 3 | .scratchpad__panel-button 4 | background: none 5 | border: 0 6 | line-height: rem($panel-header-height) 7 | margin: 0 8 | color: #FFF 9 | padding: rem(0 5px) 10 | cursor: pointer 11 | font-size: rem($font-size-small) 12 | outline: 0 13 | 14 | &:hover 15 | color: $tab-color 16 | -------------------------------------------------------------------------------- /misc/icons/linkedin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/user_delete_pending.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |

{{ _('Done') }}

5 |
6 | {{ _('Your account will be deleted in 7 days.') }} 7 | {{ _('You can cancel this at user setting page.') }} 8 |
9 |
10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /components/messagepad/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import activeId from './activeId'; 3 | import dialogues from './dialogues'; 4 | import inputs from './inputs'; 5 | import isPosting from './isPosting'; 6 | 7 | const reducer = combineReducers({ 8 | activeId, 9 | dialogues, 10 | inputs, 11 | isPosting, 12 | }); 13 | 14 | export default reducer; 15 | -------------------------------------------------------------------------------- /misc/icons/bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/user--multiple.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/home_domain.page.styl: -------------------------------------------------------------------------------- 1 | .page--home_domain 2 | .col--icon 3 | width: 60px 4 | line-height: 1 5 | 6 | img 7 | border-radius: 50% 8 | 9 | .col--role 10 | width: rem(160px) 11 | border-left: 1px solid $table-border-color 12 | 13 | .col--action 14 | width: rem(135px) 15 | 16 | +mobile() 17 | .col--icon, .col--role 18 | display: none 19 | -------------------------------------------------------------------------------- /components/star/star.page.styl: -------------------------------------------------------------------------------- 1 | .star 2 | border: 0 3 | background: none 4 | outline: 0 5 | padding: 0 6 | margin: 0 7 | color: gray 8 | 9 | .starred--show 10 | display: none 11 | .starred--hide 12 | display: block 13 | 14 | &.activated 15 | color: orange 16 | .starred--show 17 | display: block 18 | .starred--hide 19 | display: none 20 | 21 | -------------------------------------------------------------------------------- /misc/icons/global.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/heart--outline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /common/color.inc.styl: -------------------------------------------------------------------------------- 1 | aqua = #7FDBFF 2 | blue = #0074D9 3 | navy = #001F3F 4 | teal = #39CCCC 5 | green = #2ECC40 6 | olive = #3D9970 7 | lime = #01FF70 8 | yellow = #FFDC00 9 | orange = #FF851B 10 | red = #FF4136 11 | fuchsia = #F012BE 12 | purple = #B10DC9 13 | maroon = #85144B 14 | white = #ffffff 15 | silver = #dddddd 16 | gray = #aaaaaa 17 | black = #111111 18 | -------------------------------------------------------------------------------- /misc/icons/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/platform--unknown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/filter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/block.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/platform--ios.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /utils/parseQueryString.js: -------------------------------------------------------------------------------- 1 | export default function parseQueryString(str) { 2 | const obj = {}; 3 | (str || document.location.search) 4 | .replace(/(^\?)/, '') 5 | .split('&') 6 | .forEach((n) => { 7 | const [key, value] = n.split('=').map((v) => decodeURIComponent(v)); 8 | obj[key] = value; 9 | }); 10 | return obj; 11 | } 12 | 13 | window.Hydro.utils.parseQueryString = parseQueryString; 14 | -------------------------------------------------------------------------------- /misc/icons/schedule.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/domain_permission.page.styl: -------------------------------------------------------------------------------- 1 | .page--domain_permission 2 | .col--p 3 | width: 80px 4 | text-align: center 5 | border-left: 1px solid $table-border-color 6 | 7 | td.col--description 8 | padding-left: rem(30px) !important 9 | 10 | .col--family 11 | line-height: 2 12 | color: #FFF 13 | background: lighten(saturate($primary-color, 70%), 30%) 14 | border-top: 2px solid $primary-color 15 | -------------------------------------------------------------------------------- /misc/icons/insert--link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/header_mobile.html: -------------------------------------------------------------------------------- 1 | {% if no_path_section %} 2 |
3 |
4 |
5 |   6 |
7 |
8 | {% include "partials/hamburger.html" %} 9 |
10 |
11 |
12 | {% endif %} 13 | -------------------------------------------------------------------------------- /templates/problem_submit_tr.html: -------------------------------------------------------------------------------- 1 | {% import "components/record.html" as record with context %} 2 | 3 | {{ record.render_status_td(rdoc) }} 4 | 5 | {{ (rdoc.memory / 1000)|round(0, 'ceil')|int }} MB 6 | 7 | 8 | {{ rdoc.time|round|int }}ms 9 | 10 | {{ datetimeSpan(rdoc._id)|safe }} 11 | 12 | -------------------------------------------------------------------------------- /misc/icons/award.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/debug.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/homework.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/sliders.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/qq.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/rotator/rotator.page.styl: -------------------------------------------------------------------------------- 1 | .rotator 2 | position: relative 3 | height: 1em 4 | 5 | .rotator__item 6 | position: absolute 7 | left: 0 8 | top: 0 9 | width: 100% 10 | height: 100% 11 | transition: transform .2s, opacity .2s 12 | transition-timing-function: ease-out-cubic 13 | 14 | &.pos--above 15 | transform: translateY(-100%) 16 | opacity: 0 17 | 18 | &.pos--below 19 | transform: translateY(100%) 20 | opacity: 0 21 | -------------------------------------------------------------------------------- /templates/partials/problem_lucky.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | 4 | {{ _('Lucky') }} 5 | 6 |

7 |
8 |

{{ _('Pick a problem randomly based on current filter') }}

9 |
10 |
11 | -------------------------------------------------------------------------------- /misc/icons/platform--chromeos.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/layout/home_base.html: -------------------------------------------------------------------------------- 1 | {% import "components/home.html" as home with context %} 2 | {% extends "layout/basic.html" %} 3 | {% block content %} 4 |
5 |
6 | {% block home_content %}{% endblock %} 7 |
8 |
9 | {{ home.render_sidebar() }} 10 | {% block home_sidebar %}{% endblock %} 11 |
12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /misc/icons/preview.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/wrench.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/problem_default.md: -------------------------------------------------------------------------------- 1 | # Background 2 | Special for beginners, ^_^ 3 | 4 | # Description 5 | Given two integers x and y, print the sum. 6 | 7 | # Format 8 | 9 | ## Input 10 | Two integers x and y, satisfying $0\leq x,y\leq 32767$ . 11 | 12 | ## Output 13 | One integer, the sum of x and y. 14 | 15 | # Sample 1 16 | 17 | ## Input 18 | 19 | ``` 20 | 123 500 21 | ``` 22 | 23 | ## Output 24 | 25 | ``` 26 | 623 27 | ``` 28 | 29 | # Limitation 30 | 1s, 1024KiB for each test case. 31 | -------------------------------------------------------------------------------- /utils/mediaQuery.js: -------------------------------------------------------------------------------- 1 | export function isAbove(width) { 2 | if (window.matchMedia) { 3 | return window.matchMedia(`(min-width: ${width}px)`).matches; 4 | } 5 | return window.innerWidth >= width; 6 | } 7 | 8 | export function isBelow(width) { 9 | if (window.matchMedia) { 10 | return window.matchMedia(`(max-width: ${width}px)`).matches; 11 | } 12 | return window.innerWidth <= width; 13 | } 14 | 15 | window.Hydro.utils.isAbove = isAbove; 16 | window.Hydro.utils.isBelow = isBelow; 17 | -------------------------------------------------------------------------------- /components/discussion/discussion.page.styl: -------------------------------------------------------------------------------- 1 | .discussion-node-tag 2 | font-size: rem($font-size-small) 3 | display: inline-block 4 | line-height: rem(22px) 5 | padding: rem(0 10px) 6 | vertical-align: middle 7 | border-radius: rem(12px) 8 | border: 1px solid $supplementary-border-color 9 | 10 | &:hover 11 | background: $primary-color 12 | color: #FFF !important 13 | text-decoration: none 14 | border-color: $primary-color 15 | 16 | .icon 17 | margin-right: rem(5px) 18 | -------------------------------------------------------------------------------- /components/react/IconComponent.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import classNames from 'classnames'; 3 | 4 | export default function IconComponent(props) { 5 | const { 6 | name, 7 | className, 8 | ...rest 9 | } = props; 10 | const cn = classNames(className, `icon icon-${name}`); 11 | return ( 12 | 13 | ); 14 | } 15 | 16 | IconComponent.propTypes = { 17 | name: PropTypes.string.isRequired, 18 | className: PropTypes.string, 19 | }; 20 | -------------------------------------------------------------------------------- /common/common.inc.styl: -------------------------------------------------------------------------------- 1 | // This file is imported in all stylus source code 2 | breakpoints = json('../breakpoints.json', { hash: true }) 3 | rupture.mobile-cutoff = unit(breakpoints.mobile, 'px') 4 | rupture.desktop-cutoff = unit(breakpoints.desktop, 'px') 5 | rupture.hd-cutoff = unit(breakpoints.hd, 'px') 6 | 7 | @import '~vj/misc/.iconfont/webicon.inc.styl' 8 | @import 'color.inc.styl' 9 | @import 'variables.inc.styl' 10 | @import 'easing.inc.styl' 11 | @import 'rem.inc.styl' 12 | @import 'functions.inc.styl' 13 | -------------------------------------------------------------------------------- /components/katex/katex.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | 3 | const katexPage = new AutoloadPage('katexPage', () => { 4 | import('katex/dist/contrib/auto-render.min.js').then(({ default: katex }) => { 5 | function runKatex($containers) { 6 | $containers.get().forEach((container) => katex(container)); 7 | } 8 | runKatex($('.typo')); 9 | $(document).on('vjContentNew', (e) => runKatex($(e.target).find('.typo'))); 10 | }); 11 | }); 12 | 13 | export default katexPage; 14 | -------------------------------------------------------------------------------- /components/scratchpad/DataInput.page.styl: -------------------------------------------------------------------------------- 1 | .scratchpad__data-input 2 | border: 0 3 | border-left: 3px solid #E0E0E0 4 | background: #F8F8F8 5 | padding: rem(8px 4px) 6 | font-family: $code-font-family 7 | font-size: rem($font-size-secondary) 8 | outline: 0 9 | resize: none 10 | color: #666 11 | height: 100% 12 | width: 100% 13 | transition: background-color .2s linear, border-color .2s linear 14 | 15 | &:focus 16 | background: #FFF 17 | border-color: lighten($primary-color, 70%) 18 | -------------------------------------------------------------------------------- /pages/discussion_detail.page.styl: -------------------------------------------------------------------------------- 1 | .page--discussion_detail 2 | 3 | .topic__content 4 | margin: rem(20px 0) 5 | 6 | .profile__bg 7 | background-size: cover 8 | background-position: center center 9 | height: rem(60px) 10 | margin-bottom: rem(-32px) 11 | 12 | .sidebar-user-profile 13 | .media__body 14 | padding-left: rem(10px) 15 | padding-top: rem(20px) 16 | 17 | .user-profile-name 18 | font-size: 1.2rem 19 | color: #444 20 | vertical-align: middle 21 | -------------------------------------------------------------------------------- /components/highlighter/highlighter.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | 3 | const highlighterPage = new AutoloadPage('highlighterPage', () => { 4 | import('./prismjs').then((module) => { 5 | const prismjs = module.default; 6 | function runHighlight($container) { 7 | prismjs.highlightBlocks($container); 8 | } 9 | runHighlight($('body')); 10 | $(document).on('vjContentNew', (e) => runHighlight($(e.target))); 11 | }); 12 | }); 13 | 14 | export default highlighterPage; 15 | -------------------------------------------------------------------------------- /components/scratchpad/reducers/editor.js: -------------------------------------------------------------------------------- 1 | export default function reducer(state = { 2 | lang: Context.codeLang, 3 | code: Context.codeTemplate, 4 | }, action) { 5 | switch (action.type) { 6 | case 'SCRATCHPAD_EDITOR_UPDATE_CODE': { 7 | return { 8 | ...state, 9 | code: action.payload, 10 | }; 11 | } 12 | case 'SCRATCHPAD_EDITOR_SET_LANG': { 13 | return { 14 | ...state, 15 | lang: action.payload, 16 | }; 17 | } 18 | default: 19 | return state; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /misc/icons/feeling-lucky.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/unordered_list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/icons/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/components/noscript_note.html: -------------------------------------------------------------------------------- 1 | {% macro render() %} 2 | {% if not isIE(handler.request.headers['user-agent']) %} 3 | 8 | {% else %} 9 |
10 |
11 |

{{ _('This page needs JavaScript to work.') }}

12 |
13 |
14 | {% endif %} 15 | {% endmacro %} 16 | -------------------------------------------------------------------------------- /components/form/form.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | 3 | const formPage = new AutoloadPage('formPage', () => { 4 | $(document).on('vjFormDisableUpdate', 'input, select, textarea', (ev) => { 5 | const $input = $(ev.currentTarget); 6 | const $formItem = $input.closest('.form__item'); 7 | if ($input.prop('disabled')) { 8 | $formItem.addClass('is--disabled'); 9 | } else { 10 | $formItem.removeClass('is--disabled'); 11 | } 12 | }); 13 | }); 14 | 15 | export default formPage; 16 | -------------------------------------------------------------------------------- /components/menu/menu.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import { slideDown } from 'vj/utils/slide'; 3 | import delay from 'vj/utils/delay'; 4 | 5 | function expandMenu($menu) { 6 | slideDown($menu, 500, { opacity: 0 }, { opacity: 1 }); 7 | } 8 | 9 | async function expandAllMenus() { 10 | await delay(200); 11 | $('.menu.collapsed').get().forEach((menu) => expandMenu($(menu))); 12 | } 13 | 14 | const menuPage = new AutoloadPage('menuPage', () => { 15 | expandAllMenus(); 16 | }); 17 | 18 | export default menuPage; 19 | -------------------------------------------------------------------------------- /templates/layout/wiki_base.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/basic.html" %} 2 | {% block content %} 3 |
4 |
5 | {% block wiki_content %}{% endblock %} 6 |
7 |
8 |
9 | 13 |
14 |
15 |
16 | {% endblock %} -------------------------------------------------------------------------------- /components/scratchpad/PanelButtonComponent.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import classNames from 'classnames'; 3 | 4 | export default function PanelButtonComponent(props) { 5 | const { 6 | className, 7 | children, 8 | ...rest 9 | } = props; 10 | const cn = classNames(className, 'scratchpad__panel-button'); 11 | return ( 12 | 13 | ); 14 | } 15 | 16 | PanelButtonComponent.propTypes = { 17 | className: PropTypes.string, 18 | children: PropTypes.node, 19 | }; 20 | -------------------------------------------------------------------------------- /templates/user_logout.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |
5 |

{{ _('Logout') }}

6 |
7 | 8 |
9 | 10 |
11 |
12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /utils/mongoId.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // https://github.com/andrasq/node-mongoid-js/blob/master/mongoid.js 3 | 4 | export function parse(idstring) { 5 | if (typeof idstring !== 'string') { 6 | idstring = String(idstring); 7 | } 8 | return { 9 | timestamp: parseInt(idstring.slice( 0, 0+8), 16), 10 | machineid: parseInt(idstring.slice( 8, 8+6), 16), 11 | pid: parseInt(idstring.slice(14, 14+4), 16), 12 | sequence: parseInt(idstring.slice(18, 18+6), 16), 13 | }; 14 | } 15 | 16 | window.Hydro.utils.mongoId = parse; 17 | -------------------------------------------------------------------------------- /pages/homework_scoreboard.page.styl: -------------------------------------------------------------------------------- 1 | .page--homework_scoreboard 2 | .col--rank 3 | width: rem(70px) 4 | border-right: 1px solid $table-border-color 5 | 6 | .col--user 7 | width: rem(140px) 8 | 9 | .col--total_score, .col--total_time_str, .col--solved_problems 10 | width: rem(100px) 11 | text-align: center 12 | 13 | .col--problem_detail 14 | border-left: 1px solid $table-border-color 15 | text-align: center 16 | 17 | +mobile() 18 | .col--user 19 | width: auto 20 | 21 | .col--problem_detail 22 | display: none -------------------------------------------------------------------------------- /pages/record_detail.page.styl: -------------------------------------------------------------------------------- 1 | .page--record_detail 2 | 3 | .compiler-text 4 | padding: rem(20px 0) 5 | font-size: rem($font-size-small) 6 | &:empty 7 | display: none 8 | 9 | .col--case 10 | width: rem(70px) 11 | 12 | .col--memory, .col--time 13 | width: rem(120px) 14 | 15 | .col--case, .col--status 16 | border-right: 1px solid $table-border-color 17 | 18 | +mobile() 19 | .col--case 20 | display: none 21 | 22 | .col--time 23 | width: rem(70px) 24 | 25 | .col--memory 26 | width: rem(100px) 27 | -------------------------------------------------------------------------------- /templates/layout/basic.html: -------------------------------------------------------------------------------- 1 | {% set layout_name = "basic" %} 2 | {% extends "layout/html5.html" %} 3 | {% block body %} 4 | 5 | {% include "partials/nav.html" %} 6 | 7 |
8 |
9 | {% include "partials/header_mobile.html" %} 10 | {% include "partials/header.html" %} 11 |
12 | {% block content %}{% endblock %} 13 |
14 | {% include "partials/footer.html" %} 15 |
16 | 17 | {% include "partials/login_dialog.html" %} 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /components/react-splitpane/SplitPaneFillOverlayComponent.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import classNames from 'classnames'; 3 | 4 | export default function SplitPaneFillOverlayComponent(props) { 5 | const { 6 | className, 7 | children, 8 | ...rest 9 | } = props; 10 | const cn = classNames(className, 'splitpane-fill'); 11 | return ( 12 |
{children}
13 | ); 14 | } 15 | 16 | SplitPaneFillOverlayComponent.propTypes = { 17 | className: PropTypes.string, 18 | children: PropTypes.node, 19 | }; 20 | -------------------------------------------------------------------------------- /constant/setting.js: -------------------------------------------------------------------------------- 1 | import attachObjectMeta from './util/objectMeta'; 2 | 3 | export const PRIVACY_PUBLIC = 0; 4 | export const PRIVACY_REGISTERED_ONLY = 1; 5 | export const PRIVACY_SECRET = 2; 6 | export const PRIVACY_RANGE = { 7 | [PRIVACY_PUBLIC]: 'Public', 8 | [PRIVACY_REGISTERED_ONLY]: 'Visible to registered users', 9 | [PRIVACY_SECRET]: 'Secret', 10 | }; 11 | attachObjectMeta(PRIVACY_RANGE, 'intKey', true); 12 | 13 | export const FUNCTION_RANGE = { 14 | 0: 'Disabled', 15 | 1: 'Enabled', 16 | }; 17 | attachObjectMeta(FUNCTION_RANGE, 'intKey', true); 18 | -------------------------------------------------------------------------------- /pages/contest_scoreboard.page.styl: -------------------------------------------------------------------------------- 1 | .page--contest_scoreboard 2 | .col--rank 3 | width: rem(70px) 4 | border-right: 1px solid $table-border-color 5 | 6 | .col--user 7 | width: rem(140px) 8 | 9 | .col--total_score, .col--total_time_str, .col--solved_problems 10 | width: rem(100px) 11 | text-align: center 12 | 13 | .col--problem_detail 14 | border-left: 1px solid $table-border-color 15 | text-align: center 16 | 17 | +mobile() 18 | .col--user 19 | width: auto 20 | 21 | .col--problem_detail 22 | display: none 23 | -------------------------------------------------------------------------------- /templates/components/sidemenu.html: -------------------------------------------------------------------------------- 1 | {% macro render_item(icon_name, page_name, args={}, label=none) %} 2 | {% set target_url = url(page_name, args) if page_name else '#' %} 3 | 15 | {% endmacro %} 16 | -------------------------------------------------------------------------------- /components/dropdown/dropdown.page.styl: -------------------------------------------------------------------------------- 1 | .dropdown-target 2 | display: none 3 | 4 | .drop .dropdown-target 5 | display: block 6 | 7 | .dropdown 8 | .menu 9 | min-width: rem(150px) 10 | box-shadow: $menu-drop-shadow 11 | background: $menu-drop-bg-color 12 | font-size: rem($font-size-small) 13 | 14 | .menu__link 15 | padding: rem(8px 10px) 16 | 17 | .dropdown 18 | .drop-content 19 | transition: transform .1s ease-in-out 20 | transform: scale(0.9) translateZ(0) 21 | 22 | &.drop-after-open 23 | .drop-content 24 | transform: scale(1) translateZ(0) 25 | -------------------------------------------------------------------------------- /components/contest/contest_sidebar.page.styl: -------------------------------------------------------------------------------- 1 | .contest-sidebar__bg 2 | display: block 3 | background: #67AABB url(problem-contest-bg.png) right top no-repeat 4 | color: #FFF !important 5 | font-size: rem($font-size) 6 | padding: rem(20px 0) 7 | 8 | +retina() 9 | background-image: url(problem-contest-bg@2x.png) 10 | background-size: 131px 150px 11 | 12 | h1 13 | font-size: rem($font-size-title) 14 | color: #FFF 15 | text-shadow: 0 1px 3px rgba(#000, 0.5) 16 | 17 | &:hover 18 | text-decoration: none 19 | 20 | .contest-sidebar__status 21 | margin-top: rem(20px) 22 | -------------------------------------------------------------------------------- /components/highlighter/codemirror.page.styl: -------------------------------------------------------------------------------- 1 | @css { 2 | span.cm-comment { color: #008000; } 3 | span.cm-keyword, span.cm-variable-3 { line-height: 1em; color: #00f; } 4 | span.cm-string { color: #a31515; } 5 | span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; } 6 | span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; } 7 | span.cm-variable { color: black; } 8 | span.cm-meta { color: #2b91af; } 9 | span.cm-link { color: #3a3; } 10 | .CodeMirror-activeline-background { background: #e8f2ff; } 11 | .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; } 12 | } 13 | -------------------------------------------------------------------------------- /misc/immersive.styl: -------------------------------------------------------------------------------- 1 | .layout--immersive 2 | #panel 3 | background: #80b2d5 url('immersive-background.jpg') no-repeat 4 | background-size: 1920px 1080px 5 | background-size: cover 6 | +retina() 7 | background-image: url('immersive-background@2x.jpg') 8 | 9 | .immersive--content 10 | color: $immersive-text-color 11 | 12 | h1, h2, h3, h4, h5, h6 13 | color: $immersive-header-color 14 | 15 | +above(rupture.mobile-cutoff) 16 | .immersive--center 17 | width: 200px 18 | margin: 0 auto 19 | 20 | .immersive--center 21 | h1 22 | text-align: center 23 | margin: 2em 0 24 | -------------------------------------------------------------------------------- /misc/icons/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/partials/problem_sidebar.html: -------------------------------------------------------------------------------- 1 | {% if tdoc %} 2 | {% if tdoc.docType == 60 %} 3 | {% include "partials/problem_sidebar_homework.html" %} 4 | {% if not owner_udoc %} 5 | {% set owner_udoc = udoc %} 6 | {% endif %} 7 | {% include "partials/homework_sidebar.html" %} 8 | {% else %} 9 | {% include "partials/problem_sidebar_contest.html" %} 10 | {% if not owner_udoc %} 11 | {% set owner_udoc = udoc %} 12 | {% endif %} 13 | {% include "partials/contest_sidebar.html" %} 14 | {% endif %} 15 | {% else %} 16 | {% include "partials/problem_sidebar_normal.html" %} 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /misc/icons/wechat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/problem_statistics.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/basic.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |
7 |

{{ _('Submission Statistics') }}

8 |
9 |
10 | {{ _('Swx Template') }} 11 |
12 |
13 |
14 |
15 | {% set owner_udoc = udoc %} 16 | {% include "partials/problem_sidebar.html" %} 17 | {% endwith %} 18 |
19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /utils/emulateAnchorClick.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Event} ev 3 | * @param {String} targetUrl 4 | * @param {Boolean} alwaysOpenInNewWindow 5 | */ 6 | export default function emulateAnchorClick(ev, targetUrl, alwaysOpenInNewWindow = false) { 7 | let openInNewWindow; 8 | if (alwaysOpenInNewWindow) { 9 | openInNewWindow = true; 10 | } else { 11 | openInNewWindow = (ev.ctrlKey || ev.shiftKey || ev.metaKey); 12 | } 13 | if (openInNewWindow) { 14 | window.open(targetUrl); 15 | } else { 16 | window.location.href = targetUrl; 17 | } 18 | } 19 | 20 | window.Hydro.utils.emulateAnchorClick = emulateAnchorClick; 21 | -------------------------------------------------------------------------------- /utils/tpl.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | export default function tpl(pieces, ...substitutions) { 4 | let result = pieces[0]; 5 | for (let i = 0; i < substitutions.length; ++i) { 6 | const subst = substitutions[i]; 7 | let substHtml; 8 | if (typeof subst === 'object' && subst.templateRaw) { 9 | substHtml = subst.html; 10 | } else substHtml = _.escape(String(subst)); 11 | result += substHtml + pieces[i + 1]; 12 | } 13 | return result; 14 | } 15 | 16 | export function rawHtml(html) { 17 | return { 18 | templateRaw: true, 19 | html, 20 | }; 21 | } 22 | 23 | global.Hydro.utils.tpl = tpl; 24 | -------------------------------------------------------------------------------- /components/react/DomComponent.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class DomComponent extends React.PureComponent { 5 | componentDidMount() { 6 | this.refs.dom.appendChild(this.props.childDom); 7 | } 8 | 9 | componentWillUnmount() { 10 | $(this.refs.dom).empty(); 11 | } 12 | 13 | render() { 14 | const { 15 | childDom, 16 | ...rest 17 | } = this.props; 18 | return ( 19 |
20 | ); 21 | } 22 | } 23 | 24 | DomComponent.propTypes = { 25 | childDom: PropTypes.instanceOf(HTMLElement).isRequired, 26 | }; 27 | -------------------------------------------------------------------------------- /misc/icons/help.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/layout/immersive.html: -------------------------------------------------------------------------------- 1 | {% set layout_name = "immersive" %} 2 | {% set no_path_section = true %} 3 | {% extends "layout/html5.html" %} 4 | {% block body %} 5 | 6 | {% include "partials/nav.html" %} 7 | 8 |
9 |
10 | {% include "partials/header_mobile.html" %} 11 | 12 |
13 | {% block content %}{% endblock %} 14 |
15 | 16 | {% set show_topics = false %} 17 | {% include "partials/footer.html" %} 18 |
19 | 20 | {% include "partials/login_dialog.html" %} 21 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /components/cmeditor/cmeditor.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | import delay from 'vj/utils/delay'; 3 | import CmEditor from '.'; 4 | 5 | function runSubstitute($container) { 6 | const selector = ['textarea[data-markdown]']; 7 | $container.find(selector.join(', ')).get().forEach((element) => { 8 | CmEditor.getOrConstruct($(element)); 9 | }); 10 | } 11 | 12 | const cmEditorPage = new AutoloadPage('cmEditorPage', () => { 13 | runSubstitute($('body')); 14 | $(document).on('vjContentNew', async (e) => { 15 | await delay(0); 16 | runSubstitute($(e.target)); 17 | }); 18 | }); 19 | 20 | export default cmEditorPage; 21 | -------------------------------------------------------------------------------- /components/loader/loader.page.styl: -------------------------------------------------------------------------------- 1 | .loader-container 2 | position: absolute 3 | left: 0 4 | width: 100% 5 | top: 0 6 | height: 100% 7 | 8 | .loader 9 | text-indent: -9999em 10 | border: rem(5px) solid rgba($primary-color, .2) 11 | border-left: rem(5px) solid $primary-color 12 | animation: load8 1.1s infinite linear 13 | border-radius: 50% 14 | width: rem(50px) 15 | height: rem(50px) 16 | margin-left: rem(-25px) 17 | margin-top: rem(-25px) 18 | left: 50% 19 | top: 50% 20 | position: absolute 21 | 22 | @keyframes load8 23 | 0% 24 | transform: rotate(0deg) 25 | 26 | 100% 27 | transform: rotate(360deg) 28 | 29 | 30 | -------------------------------------------------------------------------------- /components/profile/profile.page.styl: -------------------------------------------------------------------------------- 1 | .user-profile-avatar 2 | border-radius: 50% 3 | 4 | .user-profile-badge 5 | display: inline-block 6 | font-size: rem(12px) 7 | padding: rem(3px 4px) 8 | line-height: 1 9 | 10 | &:hover 11 | text-decoration: none 12 | 13 | for n in (1..21) 14 | .user-profile-bg--{n} 15 | background-image: url('backgrounds/' + n + '.jpg') 16 | 17 | .user-profile-bg--thumbnail-{n} 18 | background-image: url('backgrounds/thumbnail/' + n + '.jpg') 19 | 20 | for key, _ in $badge-bg-color 21 | .badge--{key} 22 | background-color: $badge-bg-color[key] !important 23 | color: $badge-text-color[key] !important 24 | -------------------------------------------------------------------------------- /components/datepicker/datepicker.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | 3 | const datepickerPage = new AutoloadPage('datepickerPage', async () => { 4 | if ($('[data-pick-date]').length > 0) { 5 | await import('pickadate/lib/picker.date'); 6 | $('[data-pick-date]').pickadate({ 7 | format: 'yyyy-m-d', 8 | clear: false, 9 | }); 10 | } 11 | if ($('[data-pick-time]').length > 0) { 12 | await import('pickadate/lib/picker.time'); 13 | $('[data-pick-time]').pickatime({ 14 | format: 'H:i', 15 | interval: 15, 16 | clear: false, 17 | }); 18 | } 19 | }); 20 | 21 | export default datepickerPage; 22 | -------------------------------------------------------------------------------- /misc/icons/web.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/highlighter/meta.js: -------------------------------------------------------------------------------- 1 | // The following content is extracted from: 2 | // https://github.com/codemirror/CodeMirror/blob/master/mode/meta.js 3 | 4 | export default [ 5 | { name: 'C', ext: ['c', 'h'] }, 6 | { name: 'C++', ext: ['cpp', 'c++', 'cc', 'cxx', 'hpp', 'h++', 'hh', 'hxx'] }, 7 | { name: 'Go', ext: ['go'] }, 8 | { name: 'Haskell', ext: ['hs'] }, 9 | { name: 'Java', ext: ['java'] }, 10 | { name: 'JavaScript', ext: ['js'] }, 11 | { name: 'Pascal', ext: ['p', 'pas'] }, 12 | { name: 'PHP', ext: ['php', 'php3', 'php4', 'php5', 'php7', 'phtml'] }, 13 | { name: 'Python', ext: ['BUILD', 'bzl', 'py', 'pyw'] }, 14 | { name: 'Rust', ext: ['rs'] }, 15 | ]; 16 | -------------------------------------------------------------------------------- /templates/record_detail_summary.html: -------------------------------------------------------------------------------- 1 |
2 |
{{ _('Score') }}
3 |
{{ rdoc['score'] }}
4 |
{{ _('Total Time') }}
5 |
{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.time|round|int }}ms
6 |
{{ _('Peak Memory') }}
7 |
{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ size(rdoc.memory, 1024) }}
8 |
9 | -------------------------------------------------------------------------------- /components/emoji/emojify.page.js: -------------------------------------------------------------------------------- 1 | import emojify from 'emojify.js'; 2 | 3 | import { AutoloadPage } from 'vj/misc/Page'; 4 | 5 | function runEmojify($container) { 6 | if ($container.is('[data-emoji-enabled]')) { 7 | emojify.run($container[0]); 8 | return; 9 | } 10 | $container.find('[data-emoji-enabled]').get().forEach((element) => emojify.run(element)); 11 | } 12 | 13 | const emojifyPage = new AutoloadPage('emojifyPage', () => { 14 | emojify.setConfig({ 15 | img_dir: `${UiContext.cdn_prefix}img/emoji`, 16 | }); 17 | runEmojify($('body')); 18 | $(document).on('vjContentNew', (e) => runEmojify($(e.target))); 19 | }); 20 | 21 | export default emojifyPage; 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moved to https://github.com/hydro-dev/Hydro/blob/master/packages/ui-default 2 | 3 | # Hydro-UI-Default 4 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhydro-dev%2Fui-default.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhydro-dev%2Fui-default?ref=badge_shield) 5 | 6 | 7 | Based on Vijos-UI-Framework 8 | 9 | See [vijos/vj4/vj4/ui/README.md](https://github.com/vijos/vj4/blob/master/vj4/ui/README.md) 10 | 11 | 12 | ## License 13 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhydro-dev%2Fui-default.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhydro-dev%2Fui-default?ref=badge_large) 14 | -------------------------------------------------------------------------------- /components/form/textbox.page.js: -------------------------------------------------------------------------------- 1 | import { AutoloadPage } from 'vj/misc/Page'; 2 | 3 | const textboxPage = new AutoloadPage('textboxPage', () => { 4 | $(document).on('focusin', '.textbox.material input', (ev) => { 5 | $(ev.currentTarget).parent().addClass('focus'); 6 | }); 7 | 8 | $(document).on('focusout', '.textbox.material input', (ev) => { 9 | $(ev.currentTarget).parent().removeClass('focus'); 10 | }); 11 | 12 | const $focusElement = $(document.activeElement); 13 | if ($focusElement.prop('tagName') === 'INPUT' 14 | && $focusElement.parent().is('.textbox.material') 15 | ) { 16 | $focusElement.focusin(); 17 | } 18 | }); 19 | 20 | export default textboxPage; 21 | -------------------------------------------------------------------------------- /constant/model.js: -------------------------------------------------------------------------------- 1 | import attachObjectMeta from './util/objectMeta'; 2 | 3 | export const USER_GENDER_MALE = 0; 4 | export const USER_GENDER_FEMALE = 1; 5 | export const USER_GENDER_OTHER = 2; 6 | export const USER_GENDERS = [USER_GENDER_MALE, USER_GENDER_FEMALE, USER_GENDER_OTHER]; 7 | export const USER_GENDER_RANGE = { 8 | [USER_GENDER_MALE]: 'Boy ♂', 9 | [USER_GENDER_FEMALE]: 'Girl ♀', 10 | [USER_GENDER_OTHER]: 'Other', 11 | }; 12 | attachObjectMeta(USER_GENDER_RANGE, 'intKey', true); 13 | export const USER_GENDER_ICONS = { 14 | [USER_GENDER_MALE]: '♂', 15 | [USER_GENDER_FEMALE]: '♀', 16 | [USER_GENDER_OTHER]: '?', 17 | }; 18 | attachObjectMeta(USER_GENDER_ICONS, 'intKey', true); 19 | -------------------------------------------------------------------------------- /misc/icons/platform--android.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/record/record.page.styl: -------------------------------------------------------------------------------- 1 | .record-status--text 2 | for key, value in $record-status-color 3 | &.{key} 4 | color: value !important 5 | 6 | .record-status--icon 7 | display: inline-block 8 | width: 1.15em 9 | for key, value in $record-status-icon 10 | &.{key}:before 11 | content: value 12 | color: $record-status-color[key] 13 | 14 | .record-status--border 15 | border-left: rem(3px) solid transparent 16 | for key, value in $record-status-color 17 | &.{key} 18 | border-left: rem(3px) solid lighten(value, 10%) 19 | 20 | .record-status--background 21 | color: #FFF 22 | 23 | for key, value in $record-status-color 24 | &.{key} 25 | background: value 26 | 27 | -------------------------------------------------------------------------------- /pages/home_security.page.styl: -------------------------------------------------------------------------------- 1 | .page--home_security 2 | 3 | .sessionlist 4 | font-size: rem($font-size-secondary) 5 | 6 | .sessionlist__icon 7 | font-size: rem(30px) 8 | color: #888 9 | margin: rem(0 20px) 10 | 11 | .sessionlist__item 12 | margin: rem(10px 0) 13 | padding: rem(10px 0) 14 | border-bottom: 1px solid #DDD 15 | 16 | input 17 | margin: 0 18 | 19 | .sessionlist__current-session 20 | line-height: rem($form-control-height) 21 | color: green 22 | 23 | +mobile() 24 | .sessionlist__item 25 | .media__left 26 | display: none 27 | 28 | .media__body, .media__right 29 | display: block 30 | padding: 0 31 | margin: 0 32 | -------------------------------------------------------------------------------- /templates/error.html: -------------------------------------------------------------------------------- 1 | {% set no_path_section = true %} 2 | {% extends "layout/basic.html" %} 3 | {% block content %} 4 |
5 |
6 |
7 |
8 |
9 |

{{ _('Oops!') }}

10 |

{{ _(error.message).formatFromArray(error.params) }}

11 |

{{ _('Technical Information') }}:

12 |

{{ _('Type') }}: {{ error.code }}

13 |

{{ _('Arguments') }}: 14 |

    15 | {%- for param in error.params -%} 16 |
  1. {{ param }}
  2. 17 | {%- endfor -%} 18 |
19 |

20 |
21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /components/training/training.page.styl: -------------------------------------------------------------------------------- 1 | .training-status--icon 2 | display: inline-block 3 | width: 1.15em 4 | for key, value in $training-status-icon 5 | &.{key}:before 6 | content: value 7 | color: $training-status-color[key] 8 | 9 | .training-status--text 10 | for key, value in $training-status-color 11 | &.{key} 12 | color: value 13 | 14 | .training-section-status--icon 15 | display: inline-block 16 | width: 1.15em 17 | for key, value in $training-section-status-icon 18 | &.{key}:before 19 | content: value 20 | color: $training-status-color[key] 21 | 22 | .training-section-status--text 23 | for key, value in $training-section-status-color 24 | &.{key} 25 | color: value 26 | -------------------------------------------------------------------------------- /misc/icons/platform--mac.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | import _ from 'lodash'; 3 | 4 | import './utils/delay'; 5 | import './utils/emulateAnchorClick'; 6 | import './utils/i18n'; 7 | import './utils/loadReactRedux'; 8 | import './utils/mediaQuery'; 9 | import './utils/mongoId'; 10 | import './utils/parseQueryString'; 11 | import './utils/pipeStream'; 12 | import './utils/pjax'; 13 | import './utils/request'; 14 | import './utils/slide'; 15 | import './utils/substitute'; 16 | import './utils/tpl'; 17 | import './utils/zIndexManager'; 18 | import './utils/zip'; 19 | 20 | import './components/autocomplete'; 21 | import './components/dialog'; 22 | import './components/notification'; 23 | import './components/nprogress'; 24 | 25 | window.node_modules = { _, $ }; 26 | -------------------------------------------------------------------------------- /templates/home_messages.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/home_base.html" %} 2 | {% block home_content %} 3 | 18 |
19 |
20 | {{ noscript_note.render() }} 21 |
22 |
23 |
24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /templates/partials/discussion_nodes_widget.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

{{ _('Discussion Nodes') }}

4 |
5 |
    6 | {%- for category, nodes in vnodes|groupby('content') -%} 7 |
  • 8 |

    {{ category }}

    9 |
      10 | {%- for node in nodes -%} 11 |
    1. {{ node.docId }}
    2. 12 | {%- endfor -%} 13 |
    14 |
  • 15 | {%- endfor -%} 16 |
17 |
-------------------------------------------------------------------------------- /pages/record_detail.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | 3 | const page = new NamedPage('record_detail', async () => { 4 | const { default: SockJs } = await import('../components/socket'); 5 | const { DiffDOM } = await import('diff-dom'); 6 | 7 | const sock = new SockJs(Context.socketUrl); 8 | const dd = new DiffDOM(); 9 | sock.onmessage = (message) => { 10 | const msg = JSON.parse(message.data); 11 | const newStatus = $(msg.status_html); 12 | const oldStatus = $('#status'); 13 | dd.apply(oldStatus[0], dd.diff(oldStatus[0], newStatus[0])); 14 | const newSummary = $(msg.summary_html); 15 | const oldSummary = $('#summary'); 16 | dd.apply(oldSummary[0], dd.diff(oldSummary[0], newSummary[0])); 17 | }; 18 | }); 19 | 20 | export default page; 21 | -------------------------------------------------------------------------------- /components/scratchpad/reducers/pretest.js: -------------------------------------------------------------------------------- 1 | export default function reducer(state = { 2 | input: '', 3 | output: '', 4 | rid: null, 5 | }, action) { 6 | if (action.type === 'SCRATCHPAD_PRETEST_DATA_CHANGE') { 7 | const { type, value } = action.payload; 8 | return { 9 | ...state, 10 | [type]: value, 11 | }; 12 | } 13 | if (action.type === 'SCRATCHPAD_RECORDS_PUSH') { 14 | const { rdoc } = action.payload; 15 | if (rdoc._id === state.rid && rdoc.testCases[0]) { 16 | return { 17 | ...state, 18 | output: rdoc.testCases[0].message, 19 | }; 20 | } 21 | } 22 | if (action.type === 'SCRATCHPAD_POST_PRETEST_FULFILLED') { 23 | return { 24 | ...state, 25 | rid: action.payload.rid, 26 | }; 27 | } 28 | return state; 29 | } 30 | -------------------------------------------------------------------------------- /templates/components/record.html: -------------------------------------------------------------------------------- 1 | {% macro render_status_td(rdoc, rid_key='_id') %} 2 | 3 |
4 | 5 | 6 | {{ model.builtin.STATUS_TEXTS[rdoc.status] }} 7 | 8 |
9 | {% if rdoc.status == STATUS.STATUS_JUDGING %} 10 |
11 |
12 |
13 | {% endif %} 14 | 15 | {% endmacro %} 16 | -------------------------------------------------------------------------------- /templates/manage_user_import.html: -------------------------------------------------------------------------------- 1 | {% import "components/user.html" as user %} 2 | {% extends "manage_base.html" %} 3 | {% block manage_content %} 4 |
5 |
6 |

{{ _('Import User') }}

7 |
8 |
9 | {{ noscript_note.render() }} 10 |

11 | {{ form.form_textarea({ 12 | columns:null, 13 | label:'Users', 14 | name:'users' 15 | }) }} 16 |
17 | 18 | 19 |
20 |
21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /utils/pipeStream.js: -------------------------------------------------------------------------------- 1 | export default async function pipeStream(read, write, abort) { 2 | if (window.WritableStream && read.pipeTo) { 3 | const abortController = new AbortController(); 4 | if (abort) abort.abort = abortController.abort.bind(abortController); 5 | await read.pipeTo(write, abortController); 6 | } else { 7 | const writer = write.getWriter(); 8 | if (abort) abort.abort = writer.abort.bind(writer); 9 | const reader = read.getReader(); 10 | // eslint-disable-next-line no-constant-condition 11 | while (1) { 12 | const readResult = await reader.read(); 13 | if (readResult.done) { 14 | writer.close(); 15 | break; 16 | } else writer.write(readResult.value); 17 | } 18 | } 19 | } 20 | 21 | window.Hydro.utils.pipeStream = pipeStream; 22 | -------------------------------------------------------------------------------- /templates/partials/path.html: -------------------------------------------------------------------------------- 1 |
2 | {% if not no_path_section %} 3 |
4 |
5 |
6 |
7 | {%- for c in path -%} 8 | / {% if loop.index < path.length %}{{ c[0] if c[3] else _(c[0]) }}{% endif %} 9 | {%- endfor %} 10 |
11 |

{{ path[path.length - 1][0] if path[path.length - 1][3] else _(path[path.length - 1][0]) }}

12 |
13 |
14 | {% include "partials/hamburger.html" %} 15 |
16 |
17 |
18 | {% endif %} 19 |
20 | -------------------------------------------------------------------------------- /templates/problem_upload.html: -------------------------------------------------------------------------------- 1 | {% extends 'layout/simple.html' %} 2 | {% block body %} 3 |
4 | {% if (typeof(pdoc.data) == 'string') %} 5 |

{{ _('Current dataset comes from') }} {{ pdoc.data.split('from:')[1] }}

6 | {% else %} 7 |

{{ _('Current dataset: {0}').format((pdoc['data'] or _('(None)')).toString()) }}

8 |

{{ _('MD5') }}: {{ md5|default(_('(None)')) }}

9 | {% endif %} 10 |

{{ _('New dataset') }}: 11 | 12 | 13 | 14 |

15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /components/messagepad/DialogueListItem.page.styl: -------------------------------------------------------------------------------- 1 | $stripe-width = 2px 2 | 3 | .messagepad__list-item 4 | display: block 5 | padding: rem(20px $section-gap-h 20px ($section-gap-h - $stripe-width)) 6 | border-left: $stripe-width solid transparent 7 | cursor: pointer 8 | transition: border-color .1s linear, background-color .1s linear 9 | overflow: hidden 10 | text-overflow: ellipsis 11 | 12 | &:hover 13 | border-color: #DDD 14 | background: #F4F4F4 15 | text-decoration: none 16 | 17 | &.active 18 | border-color: $secondary-color 19 | background: rgba($secondary-color, 0.07) 20 | 21 | .messagepad__desc 22 | font-size: rem($font-size-small) 23 | color: #888 24 | max-height: 2em 25 | margin-top: rem(5px) 26 | overflow: hidden 27 | text-overflow: ellipsis 28 | word-wrap() 29 | -------------------------------------------------------------------------------- /components/react-splitpane/splitpane.page.styl: -------------------------------------------------------------------------------- 1 | $resizer-extend = 4px 2 | $resizer-extend-color = rgba($primary-color, 0.3) 3 | 4 | .Resizer 5 | background: #000 6 | opacity: .2 7 | z-index: 1 8 | box-sizing: border-box 9 | background-clip: padding-box 10 | 11 | .Resizer.horizontal 12 | height: ($resizer-extend * 2 + 1px) 13 | margin: -($resizer-extend) 0 14 | border-top: $resizer-extend solid transparent 15 | border-bottom: $resizer-extend solid transparent 16 | cursor: row-resize 17 | width: 100% 18 | 19 | .Resizer.vertical 20 | width: ($resizer-extend * 2 + 1px) 21 | margin: 0 -($resizer-extend) 22 | border-left: $resizer-extend solid transparent 23 | border-right: $resizer-extend solid transparent 24 | cursor: col-resize 25 | 26 | .Resizer:hover 27 | border-color: $resizer-extend-color 28 | -------------------------------------------------------------------------------- /components/contest/contest.page.styl: -------------------------------------------------------------------------------- 1 | .contest-type-tag 2 | .contest-tag 3 | font-size: rem($font-size-small) 4 | display: inline-block 5 | line-height: rem(22px) 6 | padding: rem(0 10px) 7 | vertical-align: middle 8 | border-radius: rem(12px) 9 | 10 | &:hover 11 | text-decoration: none 12 | color: #FFF !important 13 | 14 | .contest-type-tag 15 | &, &:visited 16 | &, .supplementary & 17 | color: #FFF 18 | 19 | .icon 20 | margin-right: rem(5px) 21 | 22 | for key, value in $contest-color 23 | .contest-type--{key} .contest-type-tag 24 | background: value 25 | 26 | &:hover 27 | background: lighten(value, 20%) 28 | 29 | .contest-tag 30 | border: 1px solid $supplementary-border-color 31 | 32 | &:hover 33 | background: $primary-color 34 | border-color: $primary-color 35 | -------------------------------------------------------------------------------- /templates/partials/category.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/scratchpad/PanelComponent.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent'; 5 | 6 | export default function PanelComponent(props) { 7 | const { 8 | title, 9 | className, 10 | children, 11 | ...rest 12 | } = props; 13 | const cn = classNames(className, 'flex-col'); 14 | return ( 15 | 16 |
{title}
17 |
{children}
18 |
19 | ); 20 | } 21 | 22 | PanelComponent.propTypes = { 23 | title: PropTypes.node, 24 | className: PropTypes.string, 25 | children: PropTypes.node, 26 | }; 27 | -------------------------------------------------------------------------------- /misc/icons/template/webicon.styl: -------------------------------------------------------------------------------- 1 | @font-face 2 | font-family: $icon-font-name 3 | src: url('./{{ options.fontName }}.eot') 4 | src: url('./{{ options.fontName }}.eot#iefix') format('embedded-opentype'), 5 | url('./{{ options.fontName }}.woff2') format('woff2'), 6 | url('./{{ options.fontName }}.woff') format('woff'), 7 | url('./{{ options.fontName }}.ttf') format('truetype') 8 | font-weight: normal 9 | font-style: normal 10 | 11 | .icon 12 | font-family: $icon-font-name !important 13 | speak: none 14 | font-style: normal 15 | font-weight: normal 16 | font-variant: normal 17 | text-transform: none 18 | line-height: 1 19 | -webkit-font-smoothing: antialiased 20 | -moz-osx-font-smoothing: grayscale 21 | 22 | {% for icon in glyphs %} 23 | .icon-{{ icon.name }}:before 24 | content: $icon-{{ icon.name }} 25 | {% endfor %} 26 | -------------------------------------------------------------------------------- /components/cmeditor/textareaHandler.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import DOMAttachedObject from 'vj/components/DOMAttachedObject'; 3 | import CmEditor from '.'; 4 | 5 | export default class TextareaHandler extends DOMAttachedObject { 6 | static DOMAttachKey = 'vjTextareaHandlerInstance'; 7 | 8 | getCmEditor() { 9 | return CmEditor.get(this.$dom); 10 | } 11 | 12 | isCmEditor() { 13 | const editor = this.getCmEditor(); 14 | return (editor !== undefined && editor.isValid()); 15 | } 16 | 17 | val(...argv) { 18 | if (this.isCmEditor()) { 19 | return this.getCmEditor().value(...argv); 20 | } 21 | return this.$dom.val(...argv); 22 | } 23 | 24 | focus() { 25 | if (this.isCmEditor()) { 26 | this.getCmEditor().focus(); 27 | } 28 | this.$dom.focus(); 29 | } 30 | } 31 | 32 | _.assign(TextareaHandler, DOMAttachedObject); 33 | -------------------------------------------------------------------------------- /pages/domain_join_applications.page.js: -------------------------------------------------------------------------------- 1 | import { NamedPage } from 'vj/misc/Page'; 2 | import * as domainEnum from 'vj/constant/domain'; 3 | 4 | const page = new NamedPage('domain_join_applications', () => { 5 | const $role = $('[name="role"]'); 6 | const $expire = $('[name="expire"]'); 7 | const $code = $('[name="invitationCode"]'); 8 | function updateFormState() { 9 | const method = parseInt($('[name="method"]').val(), 10); 10 | $role.prop('disabled', method === domainEnum.JOIN_METHOD_NONE).trigger('vjFormDisableUpdate'); 11 | $expire.prop('disabled', method === domainEnum.JOIN_METHOD_NONE).trigger('vjFormDisableUpdate'); 12 | $code.prop('disabled', method !== domainEnum.JOIN_METHOD_CODE).trigger('vjFormDisableUpdate'); 13 | } 14 | updateFormState(); 15 | $('[name="method"]').change(() => updateFormState()); 16 | }); 17 | 18 | export default page; 19 | -------------------------------------------------------------------------------- /templates/components/home.html: -------------------------------------------------------------------------------- 1 | {% import "components/sidemenu.html" as sidemenu with context %} 2 | {% macro render_sidebar() %} 3 |
4 | 14 |
15 | {% endmacro %} 16 | -------------------------------------------------------------------------------- /templates/user_lostpass.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/immersive.html" %} 2 | {% block content %} 3 |
4 |
5 |

{{ _('Lost Password') }}

6 |
7 |
8 | 12 |
13 |
14 |
15 | 16 | 17 |
18 |
19 |
20 |
21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /pages/training_detail.page.styl: -------------------------------------------------------------------------------- 1 | .page--training_detail 2 | .col--status 3 | width: rem(150px) 4 | position: relative 5 | 6 | .col--submit_n, .col--ac_rate, .col--difficulty 7 | width: rem(70px) 8 | text-align: center 9 | 10 | .col--status 11 | border-right: 1px solid $table-border-color 12 | 13 | .col--submit_n, .col--difficulty 14 | border-left: 1px solid $table-border-color 15 | 16 | +mobile() 17 | .col--status, 18 | .col--submit_n, 19 | .col--difficulty 20 | display: none 21 | 22 | .col--ac_rate 23 | border-left: 1px solid $table-border-color 24 | 25 | .training__section 26 | &.invalid 27 | .training__problems 28 | opacity: 0.6 29 | 30 | &.collapsed .collapsed--hidden, 31 | &.expanded .expanded--hidden 32 | display: none 33 | 34 | &.collapsed .training__section__detail 35 | display: none 36 | -------------------------------------------------------------------------------- /components/scratchpad/DataInputComponent.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import classNames from 'classnames'; 3 | 4 | export default function DataInputComponent(props) { 5 | const { 6 | title, 7 | value, 8 | onChange, 9 | className, 10 | ...rest 11 | } = props; 12 | const cn = classNames(className, 'flex-col flex-fill'); 13 | return ( 14 |
15 |