Skip to content

Commit

Permalink
[migrate] upgrade to MobX RESTful table v1 (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
TechQuery committed Jul 12, 2023
1 parent 44c9bda commit 9ebee3f
Show file tree
Hide file tree
Showing 42 changed files with 642 additions and 825 deletions.
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

1 comment on commit 9ebee3f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for open-hackathon ready!

✅ Preview
https://open-hackathon-bjcasov1k-techquery.vercel.app

Built with commit 9ebee3f.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.