Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
373 changes: 133 additions & 240 deletions components/Activity/ActivityEditor.tsx

Large diffs are not rendered by default.

120 changes: 39 additions & 81 deletions components/Activity/AwardList.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,58 @@
import { faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Loading } from 'idea-react';
import { computed } from 'mobx';
import { observer } from 'mobx-react';
import { ScrollList, ScrollListProps } from 'mobx-restful-table';
import { FC, PureComponent, useContext } from 'react';
import { Button, Image, Table } from 'react-bootstrap';
import { ObservedComponent } from 'mobx-react-helper';
import { Column, RestTable } from 'mobx-restful-table';
import { Image } from 'react-bootstrap';

import { Award } from '../../models/Activity/Award';
import { Award, AwardModel } from '../../models/Activity/Award';
import { i18n, I18nContext } from '../../models/Base/Translation';
import styles from '../../styles/Table.module.less';
import { XScrollListProps } from '../layout/ScrollList';

export interface AwardListLayoutProps extends XScrollListProps<Award> {
onEdit?: (id: number) => any;
onDelete?: (id: number) => any;
}

export const AwardTargetName = ({ t }: typeof i18n) => ({
individual: t('personal'),
team: t('team'),
});

const AwardTableHead = ({ t }: typeof i18n) => [
t('quantity'),
t('type'),
t('photo'),
t('name'),
t('description'),
t('operation'),
];
@observer
export class AwardList extends ObservedComponent<{ store: AwardModel }, typeof i18n> {
static contextType = I18nContext;

export const AwardListLayout: FC<AwardListLayoutProps> = observer(
({ defaultData = [], onEdit, onDelete }) => {
const i18n = useContext(I18nContext);
@computed
get columns(): Column<Award>[] {
const i18n = this.observedContext;
const { t } = i18n;

return (
<Table hover responsive="lg" className={styles.table}>
<thead>
<tr>
{AwardTableHead(i18n).map((data, idx) => (
<th key={idx}>{data}</th>
))}
</tr>
</thead>
<tbody>
{defaultData.map(({ quantity, target, pictures, name, description, id }) => (
<tr key={id}>
<td>{quantity}</td>
<td>{AwardTargetName(i18n)[target]}</td>
<td>
{pictures! && <Image src={pictures?.[0].uri} alt={pictures?.[0].description} />}
</td>
<td>
<Button variant="link" onClick={() => onEdit?.(id!)}>
{name}
</Button>
</td>
<td>{description}</td>
<td>
<Button variant="danger" size="sm" onClick={() => onDelete?.(id!)}>
<FontAwesomeIcon icon={faTrash} className="me-2" />
{t('delete')}
</Button>
</td>
</tr>
))}
</tbody>
</Table>
);
},
);

export type AwardListProps = Pick<ScrollListProps<Award>, 'store'> & AwardListLayoutProps;

export class AwardList extends PureComponent<AwardListProps> {
onEdit = (id: number) => {
this.props.onEdit?.(id);
this.props.store.getOne(id);
};
return [
{ key: 'quantity', renderHead: t('quantity') },
{
key: 'target',
renderHead: t('type'),
renderBody: ({ target }) => AwardTargetName(i18n)[target],
},
{
key: 'pictures',
renderHead: t('photo'),
renderBody: ({ pictures }) =>
pictures && <Image src={pictures?.[0].uri} alt={pictures?.[0].description} />,
},
{ key: 'name', renderHead: t('name') },
{ key: 'description', renderHead: t('description') },
];
}

onDelete = (id: number) => {
if (!confirm(i18n.t('sure_delete_this_work'))) return;
render() {
const i18n = this.observedContext,
{ store } = this.props;
const { downloading, uploading } = store;

this.props.onDelete?.(id);
this.props.store.deleteOne(id);
};
const loading = downloading > 0 || uploading > 0;

render() {
return (
<ScrollList
translator={i18n}
store={this.props.store}
renderList={allItems => (
<AwardListLayout defaultData={allItems} onEdit={this.onEdit} onDelete={this.onDelete} />
)}
/>
<>
<RestTable translator={i18n} store={store} columns={this.columns} editable deletable />

{loading && <Loading />}
</>
);
}
}
6 changes: 4 additions & 2 deletions components/DateTimeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ChangeEvent } from 'react';
import { Col, Form, InputGroup, Row } from 'react-bootstrap';
import { formatDate } from 'web-utility';

import { i18n } from '../models/Base/Translation';
import { i18n, I18nContext } from '../models/Base/Translation';

export interface DateTimeInputProps {
id?: string;
Expand All @@ -18,6 +18,8 @@ export interface DateTimeInputProps {

@observer
export class DateTimeInput extends ObservedComponent<DateTimeInputProps, typeof i18n> {
static contextType = I18nContext;

@observable
accessor start = '';

Expand All @@ -43,7 +45,7 @@ export class DateTimeInput extends ObservedComponent<DateTimeInputProps, typeof
{ isInvalid } = this;

return (
<Form.Group as={Row} className="mb-3" controlId={id}>
<Form.Group as={Row} controlId={id}>
<Form.Label column sm={2}>
{label}
<span className="text-danger"> *</span>
Expand Down
22 changes: 6 additions & 16 deletions components/Git/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GitTemplate, HackathonBase } from '@kaiyuanshe/openhackathon-service';
import { text2color } from 'idea-react';
import { observer } from 'mobx-react';
import { BadgeBar } from 'mobx-restful-table';
import { FC, ReactNode, useContext } from 'react';
import { Badge, Button, Card, Col, Form, Row } from 'react-bootstrap';
import { Button, Card, Col, Form, Row } from 'react-bootstrap';

import { I18nContext } from '../../models/Base/Translation';
import { GitLogo } from './Logo';
Expand Down Expand Up @@ -37,20 +37,10 @@ export const GitCard: FC<GitCardProps> = observer(
</a>
</Card.Title>

<nav className="flex-fill">
{topics?.map(topic => (
<Badge
key={topic}
className="me-1"
bg={text2color(topic, ['light'])}
as="a"
target="_blank"
href={`https://github.com/topics/${topic}`}
>
{topic}
</Badge>
))}
</nav>
<BadgeBar
className="flex-fill"
list={(topics || []).map(text => ({ text, link: `https://github.com/topics/${text}` }))}
/>
<Row as="ul" className="list-unstyled g-4" xs={4}>
{languages &&
Object.keys(languages).map(language => (
Expand Down
25 changes: 9 additions & 16 deletions components/Git/CardList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GitTemplate } from '@kaiyuanshe/openhackathon-service';
import { text2color } from 'idea-react';
import { observer } from 'mobx-react';
import { BadgeBar } from 'mobx-restful-table';
import { FC, useContext } from 'react';
import { Badge, Button, Card, Col, Form, Row } from 'react-bootstrap';
import { Button, Card, Col, Form, Row } from 'react-bootstrap';

import { I18nContext } from '../../models/Base/Translation';
import { XScrollListProps } from '../layout/ScrollList';
Expand Down Expand Up @@ -32,20 +32,13 @@ export const CardList: FC<XScrollListProps<GitTemplate>> = observer(
</a>
</Card.Title>

<nav className="flex-fill">
{topics?.map(topic => (
<Badge
key={topic}
className="me-1"
bg={text2color(topic, ['light'])}
as="a"
target="_blank"
href={`https://github.com/topics/${topic}`}
>
{topic}
</Badge>
))}
</nav>
<BadgeBar
className="flex-fill"
list={(topics || []).map(text => ({
text,
link: `https://github.com/topics/${text}`,
}))}
/>
<Row as="ul" className="list-unstyled g-4" xs={4}>
{languages &&
Object.keys(languages).map(language => (
Expand Down
22 changes: 6 additions & 16 deletions components/Git/GitTeamCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GitTemplate } from '@kaiyuanshe/openhackathon-service';
import { text2color } from 'idea-react';
import { observer } from 'mobx-react';
import { BadgeBar } from 'mobx-restful-table';
import { FC, ReactNode, useContext } from 'react';
import { Badge, Card, Col, Form, Row } from 'react-bootstrap';
import { Card, Col, Form, Row } from 'react-bootstrap';

import { I18nContext } from '../../models/Base/Translation';
import { GitLogo } from './Logo';
Expand Down Expand Up @@ -34,20 +34,10 @@ export const GitTeamCard: FC<GitTeamCardProps> = observer(
</a>
</Card.Title>

<nav className="flex-fill">
{topics?.map(topic => (
<Badge
key={topic}
className="me-1"
bg={text2color(topic, ['light'])}
as="a"
target="_blank"
href={`https://github.com/topics/${topic}`}
>
{topic}
</Badge>
))}
</nav>
<BadgeBar
className="flex-fill"
list={(topics || []).map(text => ({ text, link: `https://github.com/topics/${text}` }))}
/>
<Row as="ul" className="list-unstyled g-4" xs={4}>
{languages.map(language => (
<Col key={language} as="li">
Expand Down
15 changes: 7 additions & 8 deletions components/HTMLEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FC } from 'react';
import {
AudioTool,
CopyMarkdownTool,
Editor,
EditorProps,
IFrameTool,
Expand All @@ -12,16 +13,14 @@ import { Constructor, uniqueID } from 'web-utility';

import fileStore from '../models/Base/File';

ImageTool.prototype.save = blob =>
fileStore.upload(new File([blob], uniqueID()));
ImageTool.prototype.save = blob => fileStore.upload(new File([blob], uniqueID()));

const ExcludeTools = [IFrameTool, AudioTool, VideoTool];

const CustomTools = OriginalTools.filter(
Tool => !ExcludeTools.includes(Tool as Constructor<IFrameTool>),
);
export const CustomTools = [
...OriginalTools.filter(Tool => !ExcludeTools.includes(Tool as Constructor<IFrameTool>)),
CopyMarkdownTool,
];
const HTMLEditor: FC<EditorProps> = props => <Editor tools={CustomTools} {...props} />;

const HTMLEditor: FC<EditorProps> = props => (
<Editor tools={CustomTools} {...props} />
);
export default HTMLEditor;
Loading