-
Notifications
You must be signed in to change notification settings - Fork 6
[add] model & card component of Open Source Project #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import { FC } from 'react'; | ||
|
|
||
| import { Project } from '../../models/Project'; | ||
| import { GitCard } from '../Git/Card'; | ||
|
|
||
| export const ProjectCard: FC<Project> = ({ name, sourceLink, link, languages, tags, summary }) => ( | ||
| <GitCard | ||
| full_name={name as string} | ||
| html_url={sourceLink as string} | ||
| homepage={link as string} | ||
| languages={languages as string[]} | ||
| topics={tags as string[]} | ||
| description={summary as string} | ||
| /> | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { BiDataQueryOptions, BiDataTable, BiSearch, TableCellValue } from 'mobx-lark'; | ||
|
|
||
| import { larkClient } from './Base'; | ||
| import { AwardTableId, LarkBitableId } from './configuration'; | ||
|
|
||
| export type Award = Record< | ||
| | 'awardName' | ||
| | `nominee${'Name' | 'Desc'}` | ||
| | 'videoUrl' | ||
| | 'reason' | ||
| | 'nominator' | ||
| | 'createdAt' | ||
| | 'votes', | ||
| TableCellValue | ||
| >; | ||
|
|
||
| export class AwardModel extends BiDataTable<Award>() { | ||
| client = larkClient; | ||
|
|
||
| queryOptions: BiDataQueryOptions = { text_field_as_array: false }; | ||
|
|
||
| constructor(appId = LarkBitableId, tableId = AwardTableId) { | ||
| super(appId, tableId); | ||
| } | ||
| } | ||
|
|
||
| export class SearchAwardModel extends BiSearch<Award>(AwardModel) { | ||
| searchKeys = ['awardName', 'nomineeName', 'nomineeDesc', 'reason', 'nominator']; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,66 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BiDataQueryOptions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BiDataTable, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BiSearch, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableCellLink, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableCellValue, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableRecord, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from 'mobx-lark'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { LarkBase, larkClient } from './Base'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { LarkBitableId, ProjectTableId } from './configuration'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export type Project = LarkBase & | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Record< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'name' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'type' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'sourceLink' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'link' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'license' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'languages' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'tags' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'summary' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'logo' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'status' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | 'reason', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableCellValue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class ProjectModel extends BiDataTable<Project>() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client = larkClient; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| queryOptions: BiDataQueryOptions = { text_field_as_array: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constructor(appId = LarkBitableId, tableId = ProjectTableId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super(appId, tableId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| extractFields({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fields: { sourceLink, link, languages, tags, ...fields }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...meta | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }: TableRecord<Project>) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...meta, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...fields, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sourceLink: (sourceLink as TableCellLink)?.link, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| link: (link as TableCellLink)?.link, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| languages: languages?.toString().split(/\s*,\s*/) || [], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tags: tags?.toString().split(/\s*,\s*/) || [], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 修复字段提取逻辑中的运行时错误风险。 关键问题(第 47-48 行): 次要问题(第 45-46 行): 🔧 建议的修复方案 extractFields({
fields: { sourceLink, link, languages, tags, ...fields },
...meta
}: TableRecord<Project>) {
return {
...meta,
...fields,
- sourceLink: (sourceLink as TableCellLink)?.link,
- link: (link as TableCellLink)?.link,
- languages: languages?.toString().split(/\s*,\s*/) || [],
- tags: tags?.toString().split(/\s*,\s*/) || [],
+ sourceLink: (sourceLink as TableCellLink | undefined)?.link,
+ link: (link as TableCellLink | undefined)?.link,
+ languages: (languages?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
+ tags: (tags?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
};
}或使用更简洁的写法: - languages: languages?.toString().split(/\s*,\s*/) || [],
- tags: tags?.toString().split(/\s*,\s*/) || [],
+ languages: languages ? String(languages).split(/\s*,\s*/) : [],
+ tags: tags ? String(tags).split(/\s*,\s*/) : [],📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class SearchProjectModel extends BiSearch<Project>(ProjectModel) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| searchKeys = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'name', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'type', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'sourceLink', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'link', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'license', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'languages', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'tags', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'summary', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'status', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'reason', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,4 +35,6 @@ export const LarkWikiDomain = hostname; | |
| export const LarkWikiId = pathname.split('/').pop()!; | ||
|
|
||
| export const LarkBitableId = process.env.NEXT_PUBLIC_LARK_BITABLE_ID!, | ||
| ActivityTableId = process.env.NEXT_PUBLIC_ACTIVITY_TABLE_ID!; | ||
| ActivityTableId = process.env.NEXT_PUBLIC_ACTIVITY_TABLE_ID!, | ||
| ProjectTableId = process.env.NEXT_PUBLIC_PROJECT_TABLE_ID!, | ||
| AwardTableId = process.env.NEXT_PUBLIC_AWARD_TABLE_ID!; | ||
|
Comment on lines
+38
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Step 1: Check if .env.example exists and its contents
echo "=== Looking for environment configuration files ==="
fd -t f '\.(env|example)' | head -20
echo ""
echo "=== Checking .env.example for the mentioned variables ==="
if [ -f ".env.example" ]; then
grep -n "ACTIVITY_TABLE_ID\|PROJECT_TABLE_ID\|AWARD_TABLE_ID" .env.example || echo "Variables not found in .env.example"
else
echo ".env.example not found"
fi
echo ""
echo "=== Checking README files ==="
fd -t f 'README' -i | head -10Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io Length of output: 255 🏁 Script executed: #!/bin/bash
# Step 2: Read models/configuration.ts to understand the context
echo "=== Reading models/configuration.ts ==="
wc -l models/configuration.ts
echo ""
echo "=== Content around lines 38-40 ==="
sed -n '30,50p' models/configuration.tsRepository: Open-Source-Bazaar/Open-Source-Bazaar.github.io Length of output: 667 🏁 Script executed: #!/bin/bash
# Step 3: Search for usage of these table IDs in the codebase
echo "=== Searching for usage of AwardTableId ==="
rg "AwardTableId" -A 2 -B 2 | head -30
echo ""
echo "=== Searching for usage of ProjectTableId ==="
rg "ProjectTableId" -A 2 -B 2 | head -30
echo ""
echo "=== Searching for usage of ActivityTableId ==="
rg "ActivityTableId" -A 2 -B 2 | head -30Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io Length of output: 2683 🏁 Script executed: #!/bin/bash
# Step 4: Check Award.ts and Project.ts for context
echo "=== Checking Award.ts ==="
fd -name "Award.ts" | head -5
echo ""
echo "=== Checking Project.ts ==="
fd -name "Project.ts" | head -5
# Read Award.ts if it exists
if [ -f "models/Award.ts" ]; then
echo "=== First 50 lines of models/Award.ts ==="
head -50 models/Award.ts
fiRepository: Open-Source-Bazaar/Open-Source-Bazaar.github.io Length of output: 1424 需要在项目中补充环境变量文档。
建议创建或更新 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { cache, compose, errorLogger } from 'next-ssr-middleware'; | ||
| import { FC } from 'react'; | ||
|
|
||
| import { Award, AwardModel } from '../../models/Award'; | ||
|
|
||
| export const getServerSideProps = compose(cache(), errorLogger, async () => { | ||
| const awards = await new AwardModel().getAll(); | ||
|
|
||
| return { props: { awards } }; | ||
| }); | ||
|
|
||
| const AwardPage: FC<{ awards: Award[] }> = ({ awards }) => { | ||
| return <></>; | ||
| }; | ||
|
|
||
| export default AwardPage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
类型断言存在安全隐患,且缺少 MobX observer 包装。
此组件存在两个问题:
类型安全问题(关键):所有属性都使用
as string或as string[]强制类型转换。根据models/Project.ts的定义,这些字段的类型是TableCellValue,它可能是多种类型(number、boolean、array 等)。强制转换会绕过 TypeScript 的类型检查,可能导致运行时错误。缺少 MobX observer:参考
ActivityCard和OrganizationCard,卡片组件应该用observer()包装以响应数据变化。如果 Project 数据是可观察的(observable),当前实现将无法正确更新 UI。🔧 建议的修复方案
方案 1(推荐):类型守卫 + observer 包装
方案 2:在 Project 模型层添加类型转换
如果 TableCellValue 总是返回正确类型,可在
models/Project.ts中添加类型断言辅助函数,然后在组件中使用这些安全的转换。🤖 Prompt for AI Agents