Skip to content
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

[migrate] upgrade to MobX RESTful table v1 #188

Merged
merged 7 commits into from
Jul 12, 2023
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
18 changes: 10 additions & 8 deletions components/Activity/ActivityEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class ActivityEditor extends PureComponent<ActivityEditorProps> {
this.detailHTML = detail || '';
}

componentWillUnmount() {
activityStore.clearCurrent();
}

submitHandler = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
event.stopPropagation();
Expand All @@ -56,7 +60,7 @@ export class ActivityEditor extends PureComponent<ActivityEditorProps> {
const { name } = this.props,
data = formToJSON<ActivityFormData>(form);

data.detail = data.detail + '';
data.detail = (data.detail || '') + '';

data.banners = [data.bannerUrls ?? []].flat().map(bannerUrl => {
const name = bannerUrl.split('/').slice(-1)[0];
Expand Down Expand Up @@ -271,13 +275,11 @@ export class ActivityEditor extends PureComponent<ActivityEditorProps> {
<span className="text-danger"> *</span>
</Form.Label>
<Col sm={10}>
{detail && (
<HTMLEditor
name="detail"
defaultValue={detail}
onChange={code => (this.detailHTML = code)}
/>
)}
<HTMLEditor
name="detail"
defaultValue={detail}
onChange={code => (this.detailHTML = code)}
/>
<Form.Control
className="d-none"
isInvalid={!this.detailHTML.trim() && this.validated}
Expand Down
51 changes: 25 additions & 26 deletions components/Activity/ActivityList.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import { observer } from 'mobx-react';
import { ScrollList } from 'mobx-restful-table';
import { FC, PureComponent } from 'react';
import { Col, Row } from 'react-bootstrap';

import {
Activity,
ActivityFilter,
ActivityListType,
ActivityModel,
} from '../../models/Activity';
import platformAdmin from '../../models/PlatformAdmin';
import sessionStore from '../../models/Session';
import { i18n } from '../../models/Translation';
import { XScrollList, XScrollListProps } from '../layout/ScrollList';
import { XScrollListProps } from '../layout/ScrollList';
import { ActivityCard, ActivityCardProps } from './ActivityCard';

const { t } = i18n;

export interface ActivityListProps
export interface ActivityListLayoutProps
extends XScrollListProps<Activity>,
Pick<ActivityCardProps, 'onPublish' | 'onDelete'> {
type?: ActivityListType;
size?: 'sm' | 'lg';
userId?: string;
}

export const ActivityListLayout = ({
export const ActivityListLayout: FC<ActivityListLayoutProps> = ({
size,
type = 'online',
defaultData = [],
userId,
...props
}: ActivityListProps) => (
}) => (
<Row
className="g-4"
xs={1}
Expand All @@ -53,21 +53,13 @@ export const ActivityListLayout = ({
</Row>
);

@observer
export default class ActivityList extends XScrollList<ActivityListProps> {
store = new ActivityModel();

filter: ActivityFilter = {
userId: this.props.userId,
listType: this.props.type,
};
export type ActivityListProps = ActivityListLayoutProps;

constructor(props: ActivityListProps) {
super(props);

this.boot();
export default class ActivityList extends PureComponent<ActivityListProps> {
store = new ActivityModel();

if (props.type === 'admin' && !platformAdmin.isPlatformAdmin)
componentDidMount() {
if (this.props.type === 'admin' && !platformAdmin.isPlatformAdmin)
platformAdmin.checkAuthorization();
}

Expand All @@ -86,15 +78,22 @@ export default class ActivityList extends XScrollList<ActivityListProps> {
this.props.onDelete?.(name);
};

renderList() {
const { allItems } = this.store;
render() {
const { userId, type } = this.props;

return (
<ActivityListLayout
{...this.props}
defaultData={allItems}
onPublish={this.onPublish}
onDelete={this.onDelete}
<ScrollList
translator={i18n}
store={this.store}
filter={{ userId, listType: type }}
renderList={allItems => (
<ActivityListLayout
{...this.props}
defaultData={allItems}
onPublish={this.onPublish}
onDelete={this.onDelete}
/>
)}
/>
);
}
Expand Down
20 changes: 2 additions & 18 deletions components/Activity/ActivityLogList.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { observer } from 'mobx-react';
import { ScrollListProps } from 'mobx-restful-table';
import { Badge, ListGroup } from 'react-bootstrap';

import { Log, LogModel } from '../../models/Log';
import { XScrollList, XScrollListProps } from '../layout/ScrollList';

export interface ActivityLogListProps extends XScrollListProps<Log> {
export interface ActivityLogListProps extends ScrollListProps<Log> {
store: LogModel;
}

Expand All @@ -24,18 +23,3 @@ export const ActivityLogListLayout = ({
))}
</ListGroup>
);

@observer
export class ActivityLogList extends XScrollList<ActivityLogListProps> {
store = this.props.store;

constructor(props: ActivityLogListProps) {
super(props);

this.boot();
}

renderList() {
return <ActivityLogListLayout defaultData={this.store.allItems} />;
}
}
58 changes: 28 additions & 30 deletions components/Activity/AwardList.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { observer } from 'mobx-react';
import { ScrollList, ScrollListProps } from 'mobx-restful-table';
import { FC, PureComponent } from 'react';
import { Button, Image, Table } from 'react-bootstrap';

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

const { t } = i18n;

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

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

const awardTableHead = [
const AwardTableHead = () => [
t('quantity'),
t('type'),
t('photo'),
Expand All @@ -30,15 +30,15 @@ const awardTableHead = [
t('operation'),
];

export const AwardListLayout = ({
export const AwardListLayout: FC<AwardListLayoutProps> = ({
defaultData = [],
onEdit,
onDelete,
}: Omit<AwardListProps, 'store'>) => (
}) => (
<Table hover responsive="lg" className={styles.table}>
<thead>
<tr>
{awardTableHead.map((data, idx) => (
{AwardTableHead().map((data, idx) => (
<th key={idx}>{data}</th>
))}
</tr>
Expand All @@ -48,7 +48,7 @@ export const AwardListLayout = ({
({ quantity, target, pictures, name, description, id }) => (
<tr key={id}>
<td>{quantity}</td>
<td>{AwardTargetName[target]}</td>
<td>{AwardTargetName()[target]}</td>
<td>
{pictures! && (
<Image
Expand Down Expand Up @@ -80,36 +80,34 @@ export const AwardListLayout = ({
</Table>
);

@observer
export class AwardList extends XScrollList<AwardListProps> {
store = this.props.store;

constructor(props: AwardListProps) {
super(props);

this.boot();
}
export type AwardListProps = Pick<ScrollListProps<Award>, 'store'> &
AwardListLayoutProps;

export class AwardList extends PureComponent<AwardListProps> {
onEdit = (id: string) => {
this.props.onEdit?.(id);
this.store.getOne(id);
this.props.store.getOne(id);
};

onDelete = (id: string) => {
const { t } = i18n;

if (!confirm(t('sure_delete_this_work'))) return;

this.props.onDelete?.(id);
this.store.deleteOne(id);
this.props.store.deleteOne(id);
};

renderList() {
render() {
return (
<AwardListLayout
defaultData={this.store.allItems}
onEdit={this.onEdit}
onDelete={this.onDelete}
<ScrollList
translator={i18n}
store={this.props.store}
renderList={allItems => (
<AwardListLayout
defaultData={allItems}
onEdit={this.onEdit}
onDelete={this.onDelete}
/>
)}
/>
);
}
Expand Down
44 changes: 24 additions & 20 deletions components/Activity/EnrollmentList.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import { observer } from 'mobx-react';
import { ScrollList, ScrollListProps } from 'mobx-restful-table';
import { FC, PureComponent } from 'react';
import { Button, Form, Table } from 'react-bootstrap';

import activityStore from '../../models/Activity';
import { Enrollment, statusName } from '../../models/Enrollment';
import { i18n } from '../../models/Translation';
import styles from '../../styles/participant.module.less';
import { XScrollList, XScrollListProps } from '../layout/ScrollList';
import { XScrollListProps } from '../layout/ScrollList';

const { t } = i18n;

export interface EnrollmentListProps extends XScrollListProps<Enrollment> {
activity: string;
export interface EnrollmentListLayoutProps
extends XScrollListProps<Enrollment> {
onPopUp?: (extensions: Enrollment['extensions']) => any;
onVerify?: (userId: string, status: Enrollment['status']) => any;
}

export const EnrollmentListLayout = ({
export const EnrollmentListLayout: FC<EnrollmentListLayoutProps> = ({
defaultData = [],
onPopUp,
onVerify,
}: Pick<EnrollmentListProps, 'defaultData' | 'onPopUp' | 'onVerify'>) => (
}) => (
<Table className={styles['container-table']}>
<thead>
<tr>
Expand Down Expand Up @@ -86,28 +87,31 @@ export const EnrollmentListLayout = ({
</Table>
);

@observer
export class EnrollmentList extends XScrollList<EnrollmentListProps> {
store = activityStore.enrollmentOf(this.props.activity);

constructor(props: EnrollmentListProps) {
super(props);
export interface EnrollmentListProps extends EnrollmentListLayoutProps {
activity: string;
}

this.boot();
}
export class EnrollmentList extends PureComponent<EnrollmentListProps> {
store = activityStore.enrollmentOf(this.props.activity);

onVerify: EnrollmentListProps['onVerify'] = async (userId, status) => {
onVerify: EnrollmentListLayoutProps['onVerify'] = async (userId, status) => {
await this.store.verifyOne(userId, status);

this.props.onVerify?.(userId, status);
};

renderList() {
render() {
return (
<EnrollmentListLayout
defaultData={this.store.allItems}
onPopUp={this.props.onPopUp}
onVerify={this.onVerify}
<ScrollList
translator={i18n}
store={this.store}
renderList={allItems => (
<EnrollmentListLayout
defaultData={allItems}
onPopUp={this.props.onPopUp}
onVerify={this.onVerify}
/>
)}
/>
);
}
Expand Down
5 changes: 3 additions & 2 deletions components/Git/CardList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { text2color } from 'idea-react';
import { FC } from 'react';
import { Badge, Button, Card, Col, Form, Row } from 'react-bootstrap';

import { GitTemplate } from '../../models/TemplateRepo';
Expand All @@ -8,11 +9,11 @@ import { GitLogo } from './Logo';

const { t } = i18n;

export const CardList = ({
export const CardList: FC<XScrollListProps<GitTemplate>> = ({
defaultData = [],
selectedIds = [],
onSelect,
}: XScrollListProps<GitTemplate>) => (
}) => (
<Row as="ul" className="list-unstyled g-4" xs={1} sm={2}>
{defaultData.map(
({
Expand Down
Loading