368 lines
19 KiB
TypeScript
368 lines
19 KiB
TypeScript
|
|
import React from 'react';
|
||
|
|
import cx from 'classnames';
|
||
|
|
import { isAfter, isBefore, parse } from 'date-fns';
|
||
|
|
import { getVariable, isEffectiveApi, OptionsControlProps, Payload, OptionsControl, Select } from 'amis';
|
||
|
|
|
||
|
|
@OptionsControl({
|
||
|
|
test: /(^|\/)course\-list$/,
|
||
|
|
name: 'course-list',
|
||
|
|
})
|
||
|
|
export class CourseListRenderer extends React.Component<
|
||
|
|
OptionsControlProps,
|
||
|
|
{
|
||
|
|
options: Array<any>;
|
||
|
|
selectedOptions: Array<any>;
|
||
|
|
selectedProjects: Array<any>;
|
||
|
|
selectedClasses: Array<any>;
|
||
|
|
}
|
||
|
|
> {
|
||
|
|
constructor(props: OptionsControlProps) {
|
||
|
|
super(props);
|
||
|
|
this.state = {
|
||
|
|
options: [],
|
||
|
|
selectedOptions: [],
|
||
|
|
selectedProjects: [],
|
||
|
|
selectedClasses: [],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
componentDidMount() {
|
||
|
|
const { data, value, env, source } = this.props;
|
||
|
|
const dateRange = getVariable(data, 'date');
|
||
|
|
const startDate = parse(
|
||
|
|
dateRange.split(',')[0],
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
);
|
||
|
|
const endDate = parse(
|
||
|
|
dateRange.split(',')[1],
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
);
|
||
|
|
let selectedOptions: Array<any> = [];
|
||
|
|
if (value) {
|
||
|
|
selectedOptions = value.map((item: any) => {
|
||
|
|
return {
|
||
|
|
id: item.id,
|
||
|
|
name: item.name,
|
||
|
|
value: item.id,
|
||
|
|
label: item.name,
|
||
|
|
subjectList: item.subjectList.map((sub: any) => {
|
||
|
|
return {
|
||
|
|
value: sub.id,
|
||
|
|
label: sub.name,
|
||
|
|
id: sub.id,
|
||
|
|
name: sub.name,
|
||
|
|
validRoomList: sub.validRoomList
|
||
|
|
? sub.validRoomList.map((room: any) => {
|
||
|
|
return {
|
||
|
|
id: room.id,
|
||
|
|
name: room.name,
|
||
|
|
timeslotList: room.timeslotlist
|
||
|
|
? room.timeslotlist
|
||
|
|
.filter(
|
||
|
|
(t: any) =>
|
||
|
|
!isBefore(
|
||
|
|
parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
),
|
||
|
|
startDate
|
||
|
|
) &&
|
||
|
|
!isAfter(
|
||
|
|
parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
),
|
||
|
|
endDate
|
||
|
|
)
|
||
|
|
)
|
||
|
|
.map((t: any) => {
|
||
|
|
return {
|
||
|
|
id: t.id,
|
||
|
|
date: t.date,
|
||
|
|
period: {
|
||
|
|
id: t.period.id,
|
||
|
|
name: t.period
|
||
|
|
.name,
|
||
|
|
startTime:
|
||
|
|
t.period
|
||
|
|
.start_time,
|
||
|
|
endTime:
|
||
|
|
t.period
|
||
|
|
.end_time,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
})
|
||
|
|
: [],
|
||
|
|
};
|
||
|
|
})
|
||
|
|
: [],
|
||
|
|
preSubjectList: sub.preSubjectList
|
||
|
|
? sub.preSubjectList
|
||
|
|
: [],
|
||
|
|
};
|
||
|
|
}),
|
||
|
|
studentGroupList: item.studentGroupList.map((sub: any) => {
|
||
|
|
return {
|
||
|
|
value: sub.id,
|
||
|
|
label: sub.name,
|
||
|
|
id: sub.id,
|
||
|
|
name: sub.name,
|
||
|
|
validTimeslotList: sub.validTimeslotList
|
||
|
|
? sub.validTimeslotList.filter((t: any) => {
|
||
|
|
let tDate = parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
);
|
||
|
|
return (
|
||
|
|
!isBefore(tDate, startDate) &&
|
||
|
|
!isAfter(tDate, endDate)
|
||
|
|
);
|
||
|
|
})
|
||
|
|
: [],
|
||
|
|
};
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (isEffectiveApi(source)) {
|
||
|
|
env.fetcher(source, data).then((payload: Payload) => {
|
||
|
|
this.setState({
|
||
|
|
options: payload.data.items.map((item: any) => {
|
||
|
|
return {
|
||
|
|
id: item.id,
|
||
|
|
name: item.name,
|
||
|
|
value: item.id,
|
||
|
|
label: item.name,
|
||
|
|
subjectList: item.course2projects.map(
|
||
|
|
(sub: any) => {
|
||
|
|
return {
|
||
|
|
id: sub.projects.id,
|
||
|
|
name: sub.projects.name,
|
||
|
|
validRoomList: sub.projects
|
||
|
|
.validRoomList
|
||
|
|
? sub.projects.validRoomList.map(
|
||
|
|
(room: any) => {
|
||
|
|
return {
|
||
|
|
id: room.id,
|
||
|
|
name: room.name,
|
||
|
|
timeslotList:
|
||
|
|
room.timeslotlist
|
||
|
|
? room.timeslotlist
|
||
|
|
.filter(
|
||
|
|
(
|
||
|
|
t: any
|
||
|
|
) =>
|
||
|
|
!isBefore(
|
||
|
|
parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
),
|
||
|
|
startDate
|
||
|
|
) &&
|
||
|
|
!isAfter(
|
||
|
|
parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
),
|
||
|
|
endDate
|
||
|
|
)
|
||
|
|
)
|
||
|
|
.map(
|
||
|
|
(
|
||
|
|
t: any
|
||
|
|
) => {
|
||
|
|
return {
|
||
|
|
id: t.id,
|
||
|
|
date: t.date,
|
||
|
|
period: {
|
||
|
|
id: t
|
||
|
|
.period
|
||
|
|
.id,
|
||
|
|
name: t
|
||
|
|
.period
|
||
|
|
.name,
|
||
|
|
startTime:
|
||
|
|
t
|
||
|
|
.period
|
||
|
|
.start_time,
|
||
|
|
endTime:
|
||
|
|
t
|
||
|
|
.period
|
||
|
|
.end_time,
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
)
|
||
|
|
: [],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
)
|
||
|
|
: [],
|
||
|
|
preSubjectList: sub.projects
|
||
|
|
.preSubjectList
|
||
|
|
? sub.projects.preSubjectList
|
||
|
|
: [],
|
||
|
|
value: sub.projects.id,
|
||
|
|
label: sub.projects.name,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
),
|
||
|
|
studentGroupList: item.course2orgs.map(
|
||
|
|
(sub: any) => {
|
||
|
|
return {
|
||
|
|
id: sub.orgs.id,
|
||
|
|
name: sub.orgs.name,
|
||
|
|
validTimeslotList: sub.orgs
|
||
|
|
.validTimeslotList
|
||
|
|
? sub.orgs.validTimeslotList.filter(
|
||
|
|
(t: any) => {
|
||
|
|
let tDate = parse(
|
||
|
|
t.date,
|
||
|
|
'yyyy-MM-dd',
|
||
|
|
new Date()
|
||
|
|
);
|
||
|
|
return (
|
||
|
|
!isBefore(
|
||
|
|
tDate,
|
||
|
|
startDate
|
||
|
|
) &&
|
||
|
|
!isAfter(
|
||
|
|
tDate,
|
||
|
|
endDate
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
)
|
||
|
|
: [],
|
||
|
|
value: sub.orgs.id,
|
||
|
|
label: sub.orgs.name,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
),
|
||
|
|
};
|
||
|
|
}),
|
||
|
|
selectedOptions: selectedOptions,
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
handleClick(option: any, e: React.MouseEvent<HTMLElement>) {
|
||
|
|
if (e.target && (e.target as HTMLElement).closest('a,button')) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const { onChange } = this.props;
|
||
|
|
let index = this.state.selectedOptions.findIndex(
|
||
|
|
(item: any) => item.value === option.value
|
||
|
|
);
|
||
|
|
let newOptions = Object.assign([], this.state.selectedOptions);
|
||
|
|
if (index === -1) {
|
||
|
|
newOptions.push(option);
|
||
|
|
this.setState({
|
||
|
|
selectedOptions: newOptions,
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
newOptions.splice(index, 1);
|
||
|
|
this.setState({
|
||
|
|
selectedOptions: newOptions,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
onChange(newOptions);
|
||
|
|
}
|
||
|
|
|
||
|
|
render() {
|
||
|
|
const { placeholder, className, onChange } = this.props;
|
||
|
|
|
||
|
|
const { options, selectedOptions } = this.state;
|
||
|
|
|
||
|
|
let body: JSX.Element | null = null;
|
||
|
|
if (options && options.length) {
|
||
|
|
body = (
|
||
|
|
<div>
|
||
|
|
<div className={cx('a-ListControl-items')}>
|
||
|
|
{options.map((option, key) => (
|
||
|
|
<div
|
||
|
|
key={key}
|
||
|
|
className={cx(`a-ListControl-item`, 'w-full', {
|
||
|
|
'is-active':
|
||
|
|
selectedOptions.findIndex(
|
||
|
|
(o: any) => o.value === option.value
|
||
|
|
) !== -1,
|
||
|
|
'is-disabled': option.disabled,
|
||
|
|
})}
|
||
|
|
style={{ maxWidth: '100%' }}
|
||
|
|
onClick={this.handleClick.bind(this, option)}
|
||
|
|
>
|
||
|
|
{option.label}
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
<div className={`m-t-md`}>
|
||
|
|
{selectedOptions.map((option, key) => {
|
||
|
|
let optionData = options.find(
|
||
|
|
(item: any) => item.value === option.value
|
||
|
|
);
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
key={key}
|
||
|
|
className={cx('w-full', 'm-t-xs')}
|
||
|
|
>
|
||
|
|
<div>{optionData.label}</div>
|
||
|
|
<Select
|
||
|
|
multiple
|
||
|
|
clearable={false}
|
||
|
|
joinValues
|
||
|
|
defaultCheckAll
|
||
|
|
className={`w-full m-xs`}
|
||
|
|
options={optionData.subjectList}
|
||
|
|
onChange={(value: any) => {
|
||
|
|
option.subjectList = value;
|
||
|
|
onChange(
|
||
|
|
this.state.selectedOptions
|
||
|
|
);
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<Select
|
||
|
|
multiple
|
||
|
|
clearable={false}
|
||
|
|
joinValues
|
||
|
|
defaultCheckAll
|
||
|
|
className={`w-full m-xs`}
|
||
|
|
options={optionData.studentGroupList}
|
||
|
|
onChange={(value: any) => {
|
||
|
|
option.studentGroupList = value;
|
||
|
|
onChange(
|
||
|
|
this.state.selectedOptions
|
||
|
|
);
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className={cx('a-ListControl', className)}>
|
||
|
|
{body ? (
|
||
|
|
body
|
||
|
|
) : (
|
||
|
|
<span className={cx('a-ListControl-placeholder')}>
|
||
|
|
{placeholder}
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|