diff --git a/.gitignore b/.gitignore index 419695e..d9c9a0d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ package-lock.json yarn.lock dist/ .parcel-cache/ -.husky/ .idea/ .vscode/ .DS_Store diff --git a/.husky/pre-commit b/.husky/pre-commit index 06c2b40..72c4429 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1 @@ -#!/bin/sh - -. "$(dirname "$0")/_/husky.sh" - npm test diff --git a/.husky/pre-push b/.husky/pre-push index 952f7e3..d6cb288 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,5 +1 @@ -#!/bin/sh - -. "$(dirname "$0")/_/husky.sh" - npm run build diff --git a/package.json b/package.json index 6d3ab26..9c2a10f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "url": "https://github.com/FreeCodeCamp-Chengdu/Web-Conf/issues" }, "scripts": { - "prepare": "husky install", + "prepare": "husky", "test": "lint-staged", "clean": "rm -rf dist/ .parcel-cache/", "start": "npm run clean && parcel source/index.html --open", @@ -32,7 +32,7 @@ "*.{html,md,css,less,js,ts,tsx,json}": "prettier --write" }, "dependencies": { - "boot-cell": "^2.0.0-beta.9", + "boot-cell": "^2.0.0-beta.10", "browser-unhandled-rejection": "^1.0.2", "cell-router": "^3.0.0-rc.5", "classnames": "^2.5.1", @@ -40,7 +40,7 @@ "html-to-image": "^1.11.11", "koajax": "^0.9.6", "lodash.groupby": "^4.6.0", - "marked": "^11.1.1", + "marked": "^11.2.0", "mobx": "^6.12.0", "mobx-i18n": "^0.5.0", "web-cell": "^3.0.0-rc.8", @@ -53,12 +53,12 @@ "@parcel/transformer-typescript-tsc": "~2.11.0", "@parcel/transformer-webmanifest": "~2.11.0", "@types/lodash.groupby": "^4.6.9", - "@types/node": "^18.19.8", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", + "@types/node": "^18.19.10", + "@typescript-eslint/eslint-plugin": "^6.20.0", + "@typescript-eslint/parser": "^6.20.0", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "husky": "^8.0.3", + "husky": "^9.0.7", "lint-staged": "^15.2.0", "parcel": "~2.11.0", "postcss": "^8.4.33", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b2f2bc..7fddbde 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: boot-cell: - specifier: ^2.0.0-beta.9 - version: 2.0.0-beta.9(typescript@5.3.3) + specifier: ^2.0.0-beta.10 + version: 2.0.0-beta.10(typescript@5.3.3) browser-unhandled-rejection: specifier: ^1.0.2 version: 1.0.2 @@ -30,8 +30,8 @@ dependencies: specifier: ^4.6.0 version: 4.6.0 marked: - specifier: ^11.1.1 - version: 11.1.1 + specifier: ^11.2.0 + version: 11.2.0 mobx: specifier: ^6.12.0 version: 6.12.0 @@ -65,14 +65,14 @@ devDependencies: specifier: ^4.6.9 version: 4.6.9 '@types/node': - specifier: ^18.19.8 - version: 18.19.8 + specifier: ^18.19.10 + version: 18.19.10 '@typescript-eslint/eslint-plugin': - specifier: ^6.19.0 - version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.20.0 + version: 6.20.0(@typescript-eslint/parser@6.20.0)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.19.0 - version: 6.19.0(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.20.0 + version: 6.20.0(eslint@8.56.0)(typescript@5.3.3) eslint: specifier: ^8.56.0 version: 8.56.0 @@ -80,8 +80,8 @@ devDependencies: specifier: ^9.1.0 version: 9.1.0(eslint@8.56.0) husky: - specifier: ^8.0.3 - version: 8.0.3 + specifier: ^9.0.7 + version: 9.0.7 lint-staged: specifier: ^15.2.0 version: 15.2.0 @@ -2630,7 +2630,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.19.8 + '@types/node': 18.19.10 dev: true /@types/lodash.groupby@4.6.9: @@ -2647,8 +2647,8 @@ packages: resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} dev: true - /@types/node@18.19.8: - resolution: {integrity: sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==} + /@types/node@18.19.10: + resolution: {integrity: sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==} dependencies: undici-types: 5.26.5 dev: true @@ -2660,13 +2660,13 @@ packages: /@types/resolve@1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 18.19.8 + '@types/node': 18.19.10 dev: true /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: - '@types/node': 18.19.8 + '@types/node': 18.19.10 dev: true /@types/semver@7.5.6: @@ -2677,8 +2677,8 @@ packages: resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} dev: true - /@typescript-eslint/eslint-plugin@6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==} + /@typescript-eslint/eslint-plugin@6.20.0(@typescript-eslint/parser@6.20.0)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -2689,11 +2689,11 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.19.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.19.0 - '@typescript-eslint/type-utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/parser': 6.20.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.20.0 + '@typescript-eslint/type-utils': 6.20.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.20.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.20.0 debug: 4.3.4 eslint: 8.56.0 graphemer: 1.4.0 @@ -2706,8 +2706,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.19.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==} + /@typescript-eslint/parser@6.20.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2716,10 +2716,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.19.0 - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/scope-manager': 6.20.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/typescript-estree': 6.20.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.20.0 debug: 4.3.4 eslint: 8.56.0 typescript: 5.3.3 @@ -2727,16 +2727,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.19.0: - resolution: {integrity: sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==} + /@typescript-eslint/scope-manager@6.20.0: + resolution: {integrity: sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/visitor-keys': 6.20.0 dev: true - /@typescript-eslint/type-utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==} + /@typescript-eslint/type-utils@6.20.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2745,8 +2745,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.20.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.20.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.56.0 ts-api-utils: 1.0.3(typescript@5.3.3) @@ -2755,13 +2755,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.19.0: - resolution: {integrity: sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==} + /@typescript-eslint/types@6.20.0: + resolution: {integrity: sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.19.0(typescript@5.3.3): - resolution: {integrity: sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==} + /@typescript-eslint/typescript-estree@6.20.0(typescript@5.3.3): + resolution: {integrity: sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -2769,8 +2769,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/visitor-keys': 6.19.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/visitor-keys': 6.20.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -2782,8 +2782,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.19.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==} + /@typescript-eslint/utils@6.20.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -2791,9 +2791,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.19.0 - '@typescript-eslint/types': 6.19.0 - '@typescript-eslint/typescript-estree': 6.19.0(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.20.0 + '@typescript-eslint/types': 6.20.0 + '@typescript-eslint/typescript-estree': 6.20.0(typescript@5.3.3) eslint: 8.56.0 semver: 7.5.4 transitivePeerDependencies: @@ -2801,11 +2801,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@6.19.0: - resolution: {integrity: sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==} + /@typescript-eslint/visitor-keys@6.20.0: + resolution: {integrity: sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.0 + '@typescript-eslint/types': 6.20.0 eslint-visitor-keys: 3.4.3 dev: true @@ -3021,8 +3021,8 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true - /boot-cell@2.0.0-beta.9(typescript@5.3.3): - resolution: {integrity: sha512-RLxcNLyH0lH2J59ibOHJeE4NMye/qeos4TlMyD8o84efzgUQ7ZsnGj0aNAp3uYEn8uWLtmbG3kSjqSKhJvTSxg==} + /boot-cell@2.0.0-beta.10(typescript@5.3.3): + resolution: {integrity: sha512-a5/tBFKWfTJsOjDAQINDQGY5Qbzh9uyQo3tPo60QCLUtEt6vNDXxeOJHDdhrPN0GxZNLIiykYZESmLFcPb9fqA==} peerDependencies: '@fortawesome/fontawesome-free': ^6 '@nuintun/qrcode': ^3 @@ -4270,9 +4270,9 @@ packages: engines: {node: '>=16.17.0'} dev: true - /husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} + /husky@9.0.7: + resolution: {integrity: sha512-vWdusw+y12DUEeoZqW1kplOFqk3tedGV8qlga8/SF6a3lOiWLqGZZQvfWvY0fQYdfiRi/u1DFNpudTSV9l1aCg==} + engines: {node: '>=18'} hasBin: true dev: true @@ -4648,7 +4648,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.19.8 + '@types/node': 18.19.10 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -5065,8 +5065,8 @@ packages: engines: {node: '>=8'} dev: true - /marked@11.1.1: - resolution: {integrity: sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==} + /marked@11.2.0: + resolution: {integrity: sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==} engines: {node: '>= 18'} hasBin: true dev: false diff --git a/source/component/Carousel.tsx b/source/component/Carousel.tsx new file mode 100644 index 0000000..4305d95 --- /dev/null +++ b/source/component/Carousel.tsx @@ -0,0 +1,30 @@ +import { FC, WebCellProps } from 'web-cell'; + +export interface CarouselItemProps extends WebCellProps { + interval?: number; +} + +export const CarouselItem: FC = ({ + className = '', + interval, + children, + ...props +}) => ( +
+ {children} +
+); + +export const CarouselCaption: FC> = ({ + className = '', + children, + ...props +}) => ( +
+ {children} +
+); diff --git a/source/component/SessionBox.tsx b/source/component/SessionBox.tsx index 5694369..a7454cd 100644 --- a/source/component/SessionBox.tsx +++ b/source/component/SessionBox.tsx @@ -1,15 +1,17 @@ -import { attribute, component, observer } from 'web-cell'; +import { WebCell, attribute, component, observer } from 'web-cell'; import { observable } from 'mobx'; import { InputGroup, FormControl, Button } from 'boot-cell'; import { session } from '../model'; +export interface SessionBox extends WebCell {} + @component({ tagName: 'session-box', mode: 'open' }) @observer -export class SessionBox extends HTMLElement { +export class SessionBox extends HTMLElement implements WebCell { @attribute @observable accessor countDown = 0; diff --git a/source/page/2018-Code4City/GuestCard.tsx b/source/page/2018-Code4City/GuestCard.tsx index bfa5c28..7ce7642 100644 --- a/source/page/2018-Code4City/GuestCard.tsx +++ b/source/page/2018-Code4City/GuestCard.tsx @@ -1,31 +1,26 @@ -import { createCell } from 'web-cell'; -import { Image } from 'boot-cell/source/Media/Image'; +import { FC } from 'web-cell'; +import { Image } from 'boot-cell'; -import style from './index.less'; +import * as style from './index.module.less'; import { vips } from './data'; -export function GuestCard({ +export const GuestCard: FC<(typeof vips)[0]> = ({ avatar, name, role, identity, describe -}: typeof vips[0]) { - return ( -
-
- -
-
{name}
- {role} -
{identity}
-
-
{describe}
+}) => ( +
+
+ + +
+
{name}
+ {role} +
{identity}
+
{describe}
- ); -} +
+); diff --git a/source/page/2018-Code4City/index.less b/source/page/2018-Code4City/index.module.less similarity index 100% rename from source/page/2018-Code4City/index.less rename to source/page/2018-Code4City/index.module.less diff --git a/source/page/2018-Code4City/index.tsx b/source/page/2018-Code4City/index.tsx index 5b4ecae..5ffbf41 100644 --- a/source/page/2018-Code4City/index.tsx +++ b/source/page/2018-Code4City/index.tsx @@ -1,193 +1,199 @@ -import { createCell, Fragment } from 'web-cell'; -import { Image } from 'boot-cell/source/Media/Image'; -import { Button } from 'boot-cell/source/Form/Button'; -import { CarouselView, CarouselItem } from 'boot-cell/source/Media/Carousel'; +import { FC } from 'web-cell'; +import { Image, Button } from 'boot-cell'; +import { CarouselCaption, CarouselItem } from '../../component/Carousel'; import { GuestCard } from './GuestCard'; -import style from './index.less'; +import * as style from './index.module.less'; import BG_mountain from './image/BG-mountain.png'; import BG_points from './image/BG-points.png'; import { review, awards, vips, sponsors } from './data'; -export function Code4City() { - return ( - <> - -
-
-
-

- 2018 黑客松大赛 -

-

Code for City

+export const Code4City: FC = () => ( + <> +
+
+
+
+

+ 2018 黑客松大赛 +

+

Code for City

- + -
    -
  • - 线上预赛:2018 年 1 月 12 日 20:00 ~ 2018 年 - 1 月 14 日 20:00 -
  • -
  • - 决赛日期:2018 年 1 月 20 日 9:00 ~ 19:00 -
  • -
  • - 决赛地址:高新天府五街 200 号菁蓉国际广场 7 - 栋 1 号菁蓉汇主会场 -
  • -
-
+
    +
  • + 线上预赛:2018 年 1 月 12 日 20:00 ~ 2018 年 1 + 月 14 日 20:00 +
  • +
  • 决赛日期:2018 年 1 月 20 日 9:00 ~ 19:00
  • +
  • + 决赛地址:高新天府五街 200 号菁蓉国际广场 7 栋 1 + 号菁蓉汇主会场 +
  • +
+
-
- - {review.map(({ imageURL, title }) => ( - + + {review.map(({ imageURL, title }) => ( + + - ))} - -
-
-

- 大赛宗旨 -

-
    -
  • - 关注城市生活:以“Code For - City”为主题,旨在用实际编程行动改变城市生活,让城市更美好 -
  • -
  • - 鼓励技术创新:创意与实践相互结合,想象与行动二者并重,是本次大赛的重要评判标准之一 -
  • -
  • - 提升行业氛围:创造有价值的产品,挖掘有潜力的团队,加强高新区对人才、企业资本的吸引力 -
  • -
  • - 展现成都风采:打造一个广泛聚焦的舞台,一展成都程序员风采,彰显成都IT新一线的城市风貌 -
  • -
-
-
-

- 品牌理念 -

-

- Code for City 是 freeCodeCamp China - 的品牌活动,通过联合企业、高校、技术社区、公益组织等机构,以编程工作坊或黑客松等形式,赋能青年人为社会问题设计解决方案,旨在推动编程的普及,用技术影响世界。 -

-
-
-

- 大赛奖项 -

-
- {awards.map(({ title, detail }) => ( - <> -

{title}

-

{detail}

- - ))} -
-
-

- 所有奖项以现金或同等价值奖品发放 -

-
-
+ +
{title}
+
+ + ))} +
-
- - -
-
-
+

- 大赛参赛队伍规模及规则 + 大赛宗旨

- - 海选期:不限 - 决赛日:6支 - -
    -
  1. 参赛队长通过官方链接或者官方微信群报名
  2. +
    • - 队长在获得官方授予的权限之后,拉队员进入自己的Team(GitHub - 对应的 team、repository 自动创建) + 关注城市生活:以“Code For + City”为主题,旨在用实际编程行动改变城市生活,让城市更美好
    • - 参赛队成员在比赛开始时才被赋予代码库 push - 权限,在评选阶段暂时失去 push 权限,赛后会取得 - admin 权限以便继续开发 + 鼓励技术创新:创意与实践相互结合,想象与行动二者并重,是本次大赛的重要评判标准之一
    • -
-
-
+
  • + 提升行业氛围:创造有价值的产品,挖掘有潜力的团队,加强高新区对人才、企业资本的吸引力 +
  • +
  • + 展现成都风采:打造一个广泛聚焦的舞台,一展成都程序员风采,彰显成都IT新一线的城市风貌 +
  • + +
    +

    - 嘉宾评委介绍 + 品牌理念

    +

    + Code for City 是 freeCodeCamp China + 的品牌活动,通过联合企业、高校、技术社区、公益组织等机构,以编程工作坊或黑客松等形式,赋能青年人为社会问题设计解决方案,旨在推动编程的普及,用技术影响世界。 +

    +
    +
    +

    + 大赛奖项 +

    +
    + {awards.map(({ title, detail }) => ( + <> +

    {title}

    +

    {detail}

    + + ))} +
    +
    +

    + 所有奖项以现金或同等价值奖品发放 +

    +
    +
    +
    +
    +
    + +
    +
    +
    +

    + 大赛参赛队伍规模及规则 +

    + + 海选期:不限 + 决赛日:6支 + +
      +
    1. 参赛队长通过官方链接或者官方微信群报名
    2. +
    3. + 队长在获得官方授予的权限之后,拉队员进入自己的Team(GitHub + 对应的 team、repository 自动创建) +
    4. +
    5. + 参赛队成员在比赛开始时才被赋予代码库 push + 权限,在评选阶段暂时失去 push 权限,赛后会取得 admin + 权限以便继续开发 +
    6. +
    +
    +
    +

    + 嘉宾评委介绍 +

    + + 按首字母排序 - 按首字母排序 +
    + {vips.map(GuestCard)} +
    +
    +
    +
    +

    + 合作单位 +

    +
    + {sponsors.map(({ title, list }) => ( +
    +
    {title}
    -
    - {vips.map(GuestCard)} +
      + {list.map(({ title }) => ( +
    • {title}
    • + ))} +
    +
    + ))}
    - -
    -

    - 合作单位 -

    -
    - {sponsors.map(({ title, list }) => ( -
    -
    {title}
    - -
      - {list.map(({ title }) => ( -
    • {title}
    • - ))} -
    -
    - ))} -
    -
    - -
      - {sponsors.map(({ list }) => - list.map(({ imageURL, title }) => ( -
    • - {title} -
    • - )) - )} -
    +
      + {sponsors.map(({ list }) => + list.map(({ imageURL, title }) => ( +
    • + {title} +
    • + )) + )} +
    - - ); -} +
    + +); diff --git a/source/page/2019/InvitationCard.less b/source/page/2019/InvitationCard.module.less similarity index 100% rename from source/page/2019/InvitationCard.less rename to source/page/2019/InvitationCard.module.less diff --git a/source/page/2019/InvitationCard.tsx b/source/page/2019/InvitationCard.tsx index f417516..936436c 100644 --- a/source/page/2019/InvitationCard.tsx +++ b/source/page/2019/InvitationCard.tsx @@ -1,32 +1,26 @@ -import { createCell, component, mixin } from 'web-cell'; -import { observer } from 'mobx-web-cell'; +import { component, observer } from 'web-cell'; +import { observable } from 'mobx'; import { toPng } from 'html-to-image'; import { session } from '../../model'; import { SessionBox } from '../../component'; -import style from './InvitationCard.less'; +import * as style from './InvitationCard.module.less'; import banner from './data/banner.jpg'; import BuyCode from './data/BuyCode.png'; -interface InvitationCardState { - imageURI: string; -} - +@component({ tagName: 'invitation-card' }) @observer -@component({ - tagName: 'invitation-card', - renderTarget: 'children' -}) -export class InvitationCard extends mixin<{}, InvitationCardState>() { - state = { imageURI: '' }; +export class InvitationCard extends HTMLElement { + @observable + accessor imageURI = ''; showImage = async () => { - if (this.state.imageURI) return; + if (this.imageURI) return; const box = this.querySelector('main'); - if (box) this.setState({ imageURI: await toPng(box) }); + if (box) this.imageURI = await toPng(box); }; renderCard() { @@ -60,7 +54,9 @@ export class InvitationCard extends mixin<{}, InvitationCardState>() { ); } - render(_, { imageURI }: InvitationCardState) { + render() { + const { imageURI } = this; + return ( {session.user && this.renderCard()} diff --git a/source/page/2019/PageAccount.tsx b/source/page/2019/PageAccount.tsx index 0939697..64b6a1f 100644 --- a/source/page/2019/PageAccount.tsx +++ b/source/page/2019/PageAccount.tsx @@ -1,80 +1,98 @@ -import { createCell } from 'web-cell'; -import { parseTextTable } from 'web-utility/source/data'; -import { Table, TableRow } from 'boot-cell/source/Content/Table'; +import { component, observer } from 'web-cell'; +import { CustomElement, parseTextTable } from 'web-utility'; +import { Table } from 'boot-cell'; +import { computed, observable } from 'mobx'; import { PageFrame } from './PageFrame'; -import data from './data/account.csv'; -interface Account { - item: string; - price: number; - count: number; - manager: string; - date: string; - remark: string; -} +type Account = Record<'item' | 'manager' | 'date' | 'remark', string> & + Record<'price' | 'count', number>; -const list = parseTextTable(data, true) as Account[]; +@component({ tagName: 'account-page' }) +@observer +export class AccountPage extends HTMLElement implements CustomElement { + @observable + accessor list: Account[] = []; -const expenditure = list.reduce( - (sum, { price, count, date }) => - price < 0 && date ? sum + price * count : sum, - 0 -); + @computed + get expenditure() { + return this.list.reduce( + (sum, { price, count, date }) => + price < 0 && date ? sum + price * count : sum, + 0 + ); + } -const revenue = list.reduce( - (sum, { price, count, date }) => - price > 0 && date ? sum + price * count : sum, - 0 -); + @computed + get revenue() { + return this.list.reduce( + (sum, { price, count, date }) => + price > 0 && date ? sum + price * count : sum, + 0 + ); + } -export function PageAccount() { - return ( - -

    收支账目

    + async connectedCallback() { + const data = await ( + await fetch(new URL('./data/account.csv', import.meta.url)) + ).text(); - - - - - - - - - - + this.list = parseTextTable(data, true) as Account[]; + } - {list.map( - ({ item, price, count, manager, date, remark }, index) => ( - - - - - - - - - - ) + renderRow = ( + { item, price, count, manager, date, remark }: Account, + index: number + ) => ( + + + + + + - - - - - - -
    #事项单价(人民币¥)数量经办日期备注{++index}{item}{price}{count} - {manager && ( - - @{manager} - - )} - {date}{remark}
    {++index}{item}{price}{count} + {manager && ( + + @{manager} + )} - - 总支出(人民币¥){expenditure.toFixed(2)}总收入(人民币¥){revenue.toFixed(2)}总结余(人民币¥){(revenue + expenditure).toFixed(2)}
    -
    + + {date} + {remark} + ); + + render() { + const { list, expenditure, revenue } = this; + + return ( + +

    收支账目

    + + + + + + + + + + + + + + {list.map(this.renderRow)} + + + + + + + + + + +
    #事项单价(人民币¥)数量经办日期备注
    总支出(人民币¥){expenditure.toFixed(2)}总收入(人民币¥){revenue.toFixed(2)}总结余(人民币¥){(revenue + expenditure).toFixed(2)}
    +
    + ); + } } diff --git a/source/page/2019/PageFrame.tsx b/source/page/2019/PageFrame.tsx index 9cdb736..1b54c4c 100644 --- a/source/page/2019/PageFrame.tsx +++ b/source/page/2019/PageFrame.tsx @@ -1,18 +1,12 @@ -import { WebCellProps, createCell, Fragment } from 'web-cell'; +import { FC, PropsWithChildren } from 'web-cell'; import { TopNavBar } from '../../component'; import { title, menu } from './data/index.json'; -export function PageFrame({ defaultSlot }: WebCellProps) { - return ( - <> - -
    {defaultSlot}
    - - ); -} +export const PageFrame: FC = ({ children }) => ( + <> + + +
    {children}
    + +); diff --git a/source/page/2019/PartnerGroup.tsx b/source/page/2019/PartnerGroup.tsx index 30581ba..bac24cf 100644 --- a/source/page/2019/PartnerGroup.tsx +++ b/source/page/2019/PartnerGroup.tsx @@ -1,41 +1,36 @@ -import { createCell, Fragment } from 'web-cell'; +import { FC } from 'web-cell'; -interface Partner { - title: string; - name: string; +interface Partner extends Record<'title' | 'name', string> { logo?: string; } -export function PartnerGroup({ - title, - list -}: { +export interface PartnerGroupProps { title: string; list: Partner[]; -}) { - return ( - <> -

    {title}

    - -
      - {list.map(({ name, logo }) => ( -
    • - {logo ? ( - {name} - ) : ( - name - )} -
    • - ))} -
    - - ); } + +export const PartnerGroup: FC = ({ title, list }) => ( + <> +

    {title}

    + +
      + {list.map(({ name, logo }) => ( +
    • + {logo ? ( + {name} + ) : ( + name + )} +
    • + ))} +
    + +); diff --git a/source/page/2019/TopicGroup.less b/source/page/2019/TopicGroup.module.less similarity index 100% rename from source/page/2019/TopicGroup.less rename to source/page/2019/TopicGroup.module.less diff --git a/source/page/2019/TopicGroup.tsx b/source/page/2019/TopicGroup.tsx index 43cbcf9..be89acc 100644 --- a/source/page/2019/TopicGroup.tsx +++ b/source/page/2019/TopicGroup.tsx @@ -1,62 +1,51 @@ -import { createCell } from 'web-cell'; -import { Card } from 'boot-cell/source/Content/Card'; +import { FC } from 'web-cell'; +import { Card, CardBody, CardImg, CardTitle } from 'boot-cell'; -import style from './TopicGroup.less'; +import * as style from './TopicGroup.module.less'; -interface Mentor { +interface Mentor extends Record<'name' | 'GitHub', string> { id: number; - name: string; - GitHub: string; } -export interface Topic { - type: string; - title: string; - date: string; +export interface Topic + extends Record<'type' | 'title' | 'date' | 'image', string> { time: string[]; - image: string; mentorId?: number; slideshow?: string; } -export function TopicGroup({ - topics, - mentors -}: { +export interface TopicGroupProps { topics: Topic[]; mentors: Mentor[]; -}) { - topics.sort((A, B) => A.time[0].localeCompare(B.time[0])); +} - return ( -
    - {topics.map(({ title, image, mentorId, slideshow, time }) => { +export const TopicGroup: FC = ({ topics, mentors }) => ( +
    + {[...topics] + .sort((A, B) => A.time[0].localeCompare(B.time[0])) + .map(({ title, image, mentorId, slideshow, time }) => { const mentor = mentorId && mentors.find(({ id }) => id === mentorId)!; return ( - + + + {title} + {mentor && ( {mentor.name} - ) - } - > -
    - - {slideshow && ( - - 演示文稿 - )} -
    +
    + + {slideshow && ( + + 演示文稿 + + )} +
    +
    ); })} -
    - ); -} +
    +); diff --git a/source/page/2019/index.tsx b/source/page/2019/index.tsx index 72e3a92..bdaa290 100644 --- a/source/page/2019/index.tsx +++ b/source/page/2019/index.tsx @@ -1,12 +1,15 @@ import groupBy from 'lodash.groupby'; -import { createCell, Fragment } from 'web-cell'; -import { Jumbotron } from 'boot-cell/source/Content/Jumbotron'; -import { Button } from 'boot-cell/source/Form/Button'; -import { Card } from 'boot-cell/source/Content/Card'; -import { CountDown } from 'boot-cell/source/Calendar/CountDown'; -import { TabView, TabPanel } from 'boot-cell/source/Content/TabView'; -import { NavLink } from 'boot-cell/source/Navigator/Nav'; -import { Embed } from 'boot-cell/source/Media/Embed'; +import { FC } from 'web-cell'; +import { + Jumbotron, + Button, + Card, + CardBody, + CardImg, + CardTitle, + NavLink, + Ratio +} from 'boot-cell'; import { PageFrame } from './PageFrame'; import { TopicGroup, Topic } from './TopicGroup'; @@ -22,70 +25,64 @@ const topicGroups = Object.entries( A[1][0].date.localeCompare(B[1][0].date) || B[1][0].place.localeCompare(A[1][0].place) ); - const partnerGroups = Object.entries(groupBy(data.partners, 'title')); -export function Page2019() { - return ( - - -
  • 2019 年 11 月 16 ~ 17 日
  • -
  • {data.address}
  • - - } +export const Page2019: FC = () => ( + + +
  • 2019 年 11 月 16 ~ 17 日
  • +
  • {data.address}
  • + + } + > + + -
    + 即刻报名 + +
    -

    - 大会议程 -

    - - {topicGroups.map(([title, list]) => ( - <> - {title} - - - - - ))} - -
    +

    + 大会议程 +

    + + {topicGroups.map(([title, list]) => ( + <> + {title} + + + + + ))} + +
    -

    - 大咖讲师 -

    -

    (排名不分先后)

    +

    + 大咖讲师 +

    +

    (排名不分先后)

    -
    - {data.mentors.map( - ({ name, avatar, organization, title, GitHub }) => ( - +
    + {data.mentors.map( + ({ name, avatar, organization, title, GitHub }) => ( + + + + {name} + {organization + ? `${organization} - ${title}` + : title} @{GitHub} - - ) - )} -
    -
    + +
    + ) + )} +
    +
    -

    - 共创伙伴 -

    -
    - {partnerGroups.map(([title, list]) => ( - - ))} -
    -
    +

    + 共创伙伴 +

    +
    + {partnerGroups.map(([title, list]) => ( + + ))} +
    +
    -

    - 会场交通 -

    -

    {data.address}

    - + 会场交通 + +

    {data.address}

    + +