|
|
import React, {Component} from 'react';
|
|
|
|
|
|
import {TPMIndexHOC} from '../TPMIndexHOC';
|
|
|
|
|
|
import {SnackbarHOC} from 'educoder';
|
|
|
|
|
|
import {Select, Radio, Input, Modal, Button, Form, Tooltip, Upload,Icon} from 'antd';
|
|
|
|
|
|
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
|
|
|
|
|
import axios from 'axios';
|
|
|
|
|
|
import {getUrl,getUploadActionUrl} from 'educoder';
|
|
|
|
|
|
import moment from 'moment';
|
|
|
|
|
|
import './css/Newshixuns.css';
|
|
|
|
|
|
import TPMMDEditor from "../challengesnew/TPMMDEditor";
|
|
|
|
|
|
let path = getUrl("/editormd/lib/");
|
|
|
|
|
|
const $ = window.$;
|
|
|
|
|
|
let timeout;
|
|
|
|
|
|
let currentValue;
|
|
|
|
|
|
const Option = Select.Option;
|
|
|
|
|
|
const RadioGroup = Radio.Group;
|
|
|
|
|
|
const confirm = Modal.confirm;
|
|
|
|
|
|
class Newshixuns extends Component {
|
|
|
constructor(props) {
|
|
|
super(props)
|
|
|
this.contentMdRef = React.createRef();
|
|
|
this.state = {
|
|
|
shixunName: undefined,
|
|
|
NAME_COUNT: 60,
|
|
|
Radiovalue: "1",
|
|
|
newshixunlist: undefined,
|
|
|
languagewrite:undefined,
|
|
|
systemenvironment:undefined,
|
|
|
testcoderunmode:undefined,
|
|
|
postapplyvisible:undefined
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
this.props.form.setFieldsValue({
|
|
|
radiogroup: `1`,
|
|
|
});
|
|
|
let newshixunUrl = `/shixuns/new.json`;
|
|
|
axios.get(newshixunUrl).then((response) => {
|
|
|
if (response.status === 200) {
|
|
|
if (response.data.message === undefined) {
|
|
|
this.setState({
|
|
|
newshixunlist: response.data
|
|
|
});
|
|
|
|
|
|
this.contentMdRef.current.setValue(!response.data.sample[0][1] ? "" : response.data.sample[0][1]);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
});
|
|
|
|
|
|
let departmentsUrl = `/shixuns/departments.json`;
|
|
|
axios.get(departmentsUrl).then((response) => {
|
|
|
if (response.status === 200) {
|
|
|
if (response.data.message === undefined) {
|
|
|
this.setState({
|
|
|
departmentslist: response.data.shools_name
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
});
|
|
|
|
|
|
// const mdContnet = this.contentMdRef.current.getValue().trim();
|
|
|
}
|
|
|
|
|
|
shixunNameInput = (e) => {
|
|
|
this.setState({
|
|
|
shixunName: e.target.value
|
|
|
})
|
|
|
|
|
|
this.props.form.setFieldsValue({
|
|
|
name: e.target.value,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
RadiovalueonChange = (e) => {
|
|
|
this.setState({
|
|
|
Radiovalue: e.target.value,
|
|
|
});
|
|
|
};
|
|
|
|
|
|
handleSubmit = e => {
|
|
|
e.preventDefault();
|
|
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
|
|
if (!err) {
|
|
|
console.log('Received values of form: ', values);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
Selectthestudent = (value) => {
|
|
|
this.props.form.setFieldsValue({
|
|
|
select: value,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
selectleft = (value) => {
|
|
|
this.props.form.setFieldsValue({
|
|
|
selectleft: value,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
selectright=(value)=>{
|
|
|
this.props.form.setFieldsValue({
|
|
|
selectright: value,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
post_apply = () => {
|
|
|
this.setState({
|
|
|
postapplyvisible: true
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sendhideModaly = () => {
|
|
|
this.setState({
|
|
|
postapplyvisible: false,
|
|
|
})
|
|
|
if(this.state.file !== undefined){
|
|
|
console.log("580");
|
|
|
// this.deleteAttachment(this.state.file);
|
|
|
this.setState({
|
|
|
file:undefined,
|
|
|
deleteisnot:true,
|
|
|
languagewrite:"",
|
|
|
systemenvironment:"",
|
|
|
testcoderunmode:"",
|
|
|
fileList:[]
|
|
|
})
|
|
|
}else {
|
|
|
this.setState({
|
|
|
file:undefined,
|
|
|
deleteisnot:true,
|
|
|
languagewrite:"",
|
|
|
systemenvironment:"",
|
|
|
testcoderunmode:"",
|
|
|
fileList:[]
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
sendsure_apply = () => {
|
|
|
let {languagewrite,systemenvironment,testcoderunmode} = this.state;
|
|
|
// console.log("点击确定")
|
|
|
// console.log("languagewrite"+languagewrite);
|
|
|
// console.log("systemenvironment"+systemenvironment);
|
|
|
// console.log("testcoderunmode"+testcoderunmode);
|
|
|
|
|
|
// let attachment_ids = undefined
|
|
|
// if (this.state.fileList) {
|
|
|
// attachment_ids = this.state.fileList.map(item => {
|
|
|
// return item.response ? item.response.id : item.id
|
|
|
// })
|
|
|
// }
|
|
|
if(languagewrite === undefined || languagewrite === "" ){
|
|
|
// this.props.showNotification(`请填写该镜像是基于什么语言`);
|
|
|
this.setState({
|
|
|
languagewritetype:true
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
if(systemenvironment === undefined || systemenvironment === ""){
|
|
|
// this.props.showNotification(`请填写该镜像是基于什么语言系统环境`);
|
|
|
this.setState({
|
|
|
systemenvironmenttype:true
|
|
|
})
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
if(testcoderunmode === undefined || testcoderunmode === "") {
|
|
|
// this.props.showNotification(`请填写该镜像中测试代码运行方式`);
|
|
|
this.setState({
|
|
|
testcoderunmodetype:true
|
|
|
})
|
|
|
return;
|
|
|
}
|
|
|
var attachment_ids=undefined;
|
|
|
if (this.state.fileList) {
|
|
|
attachment_ids = this.state.fileList.map(item => {
|
|
|
return item.response ? item.response.id : item.id
|
|
|
})
|
|
|
}
|
|
|
|
|
|
if( attachment_ids === undefined || attachment_ids.length===0){
|
|
|
|
|
|
// notification.open(
|
|
|
// {
|
|
|
// message: '提示',
|
|
|
// description:
|
|
|
// '请上传附件!',
|
|
|
//
|
|
|
// }
|
|
|
// )
|
|
|
this.setState({
|
|
|
attachmentidstype:true
|
|
|
})
|
|
|
return;
|
|
|
}
|
|
|
// console.log("attachment_ids"+attachment_ids);
|
|
|
|
|
|
// alert(languagewrite +" "+systemenvironment +" "+testcoderunmode + " "+attachment_ids);
|
|
|
|
|
|
var data={
|
|
|
language:languagewrite,
|
|
|
runtime:systemenvironment,
|
|
|
run_method:testcoderunmode,
|
|
|
attachment_id:attachment_ids[0],
|
|
|
}
|
|
|
var url =`/shixuns/apply_shixun_mirror.json`;
|
|
|
axios.post(url,data
|
|
|
).then((response) => {
|
|
|
|
|
|
try {
|
|
|
if (response.data) {
|
|
|
// const { id } = response.data;
|
|
|
// if (id) {
|
|
|
if(this.state.file !== undefined){
|
|
|
console.log("549");
|
|
|
// this.deleteAttachment(this.state.file);
|
|
|
this.setState({
|
|
|
file:undefined,
|
|
|
deleteisnot:true,
|
|
|
languagewrite:"",
|
|
|
systemenvironment:"",
|
|
|
testcoderunmode:"",
|
|
|
fileList:[]
|
|
|
})
|
|
|
}else {
|
|
|
this.setState({
|
|
|
file:undefined,
|
|
|
deleteisnot:true,
|
|
|
languagewrite:"",
|
|
|
systemenvironment:"",
|
|
|
testcoderunmode:"",
|
|
|
fileList:[]
|
|
|
})
|
|
|
}
|
|
|
// this.props.showNotification('提交成功!');
|
|
|
notification.open(
|
|
|
{
|
|
|
message: '提示',
|
|
|
description:
|
|
|
'提交成功!',
|
|
|
|
|
|
}
|
|
|
)
|
|
|
this.sendhideModaly()
|
|
|
// this.props.history.push(`/courses/${cid}/graduation_topics`);
|
|
|
// }
|
|
|
}
|
|
|
}catch (e) {
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
const {getFieldDecorator} = this.props.form;
|
|
|
const {newshixunlist,languagewrite,systemenvironment,testcoderunmode,fileList,postapplytitle,postapplyvisible} = this.state;
|
|
|
const uploadProps = {
|
|
|
width: 600,
|
|
|
fileList,
|
|
|
multiple: true,
|
|
|
// https://github.com/ant-design/ant-design/issues/15505
|
|
|
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
|
|
// showUploadList: false,
|
|
|
action: `${getUploadActionUrl()}`,
|
|
|
onChange: this.handleChange,
|
|
|
onRemove: this.onAttachmentRemove,
|
|
|
beforeUpload: (file, fileList) => {
|
|
|
|
|
|
if (this.state.fileList.length >= 1) {
|
|
|
return false
|
|
|
}
|
|
|
// console.log('beforeUpload', file.name);
|
|
|
const isLt150M = file.size / 1024 / 1024 < 50;
|
|
|
if (!isLt150M) {
|
|
|
// this.props.showNotification(`文件大小必须小于50MB`);
|
|
|
notification.open(
|
|
|
{
|
|
|
message: '提示',
|
|
|
description:
|
|
|
'文件大小必须小于50MB',
|
|
|
|
|
|
}
|
|
|
)
|
|
|
}
|
|
|
if(this.state.file !== undefined){
|
|
|
console.log("763")
|
|
|
this.setState({
|
|
|
file:file
|
|
|
})
|
|
|
}else {
|
|
|
this.setState({
|
|
|
file:file
|
|
|
})
|
|
|
}
|
|
|
|
|
|
console.log("handleChange2");
|
|
|
return isLt150M;
|
|
|
},
|
|
|
}
|
|
|
return (
|
|
|
<div className="newMain clearfix">
|
|
|
<style>
|
|
|
{
|
|
|
`
|
|
|
.newFooter{
|
|
|
display:none;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</style>
|
|
|
<div className="educontent mt20 mb60 clearfix">
|
|
|
<div className="new_shixun">
|
|
|
|
|
|
<div className="mb10 edu-back-white">
|
|
|
|
|
|
<div className="padding10-20 bor-bottom-greyE color-grey-3 clearfix">
|
|
|
<span className="fl font-18 lineh-35">新建实训项目</span>
|
|
|
{this.props.user && this.props.user.main_site === true ?
|
|
|
<a className="fr font-16 mt3 color-blue" href="/forums/2943"
|
|
|
target="_blank">实训制作指南</a> : ""}
|
|
|
</div>
|
|
|
<div className="padding10-20 color-grey-3 clearfix">
|
|
|
<Form onSubmit={this.handleSubmit}>
|
|
|
<Form.Item label="实训类型">
|
|
|
{getFieldDecorator('radiogroup')(
|
|
|
<Radio.Group onChange={this.RadiovalueonChange}>
|
|
|
<Radio value="1">普通实训</Radio>
|
|
|
<Radio value="2">Jupyter实训</Radio>
|
|
|
</Radio.Group>,
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
<Form.Item
|
|
|
label="名称"
|
|
|
className="mt15"
|
|
|
>
|
|
|
{getFieldDecorator('name', {
|
|
|
rules: [{
|
|
|
required: true, message: '请输入选题名称',
|
|
|
}, {
|
|
|
max: 60, message: '请输入名称,最大限制60个字符',
|
|
|
},{
|
|
|
whitespace:true,message:'请勿输入空格'
|
|
|
}],
|
|
|
})(
|
|
|
<Input placeholder="请输入名称,最大限制60个字符"
|
|
|
className={"input-100-45 greyInput"}
|
|
|
onInput={this.shixunNameInput} autoComplete="off"
|
|
|
addonAfter={`${String(!this.state.shixunName ? 0 : this.state.shixunName.length)}/${this.state.NAME_COUNT}`}
|
|
|
className="newViewAfter"/>
|
|
|
)}
|
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
|
label="简介"
|
|
|
style={{"borderBottom": 'none'}}
|
|
|
className="chooseDes pr"
|
|
|
>
|
|
|
<TPMMDEditor ref={this.contentMdRef} placeholder="请输入简介" mdID={'courseContentMD'}
|
|
|
refreshTimeout={1500}
|
|
|
className="courseMessageMD"
|
|
|
// initValue={this.state.description === null ? "" : this.state.description}
|
|
|
></TPMMDEditor>
|
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
|
label={"难易度"}
|
|
|
style={{"borderBottom": 'none'}}
|
|
|
className="chooseDes pr"
|
|
|
>
|
|
|
{getFieldDecorator('select', {
|
|
|
rules: [{required: true, message: '请选择难易度'}],
|
|
|
})(
|
|
|
<div className="with15 fl pr">
|
|
|
<Select placeholder="请选择难易度"
|
|
|
style={{width: 180}}
|
|
|
onChange={this.Selectthestudent}
|
|
|
>
|
|
|
<Option value={1}>初级</Option>
|
|
|
<Option value={2}>中级</Option>
|
|
|
<Option value={3}>中高级</Option>
|
|
|
<Option value={4}>高级</Option>
|
|
|
</Select>
|
|
|
|
|
|
</div>
|
|
|
)}
|
|
|
<span className="fl ml20 color-grey">(实训的难易程度)</span>
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
label={"实验环境"}
|
|
|
style={{"borderBottom": 'none','width': '18%','float': 'left'}}
|
|
|
className="chooseDes pr"
|
|
|
>
|
|
|
<div>
|
|
|
|
|
|
{getFieldDecorator('selectleft', {
|
|
|
rules: [{required: true, message: '请选择主类别'}],
|
|
|
})(
|
|
|
<div className="width100 fl mr20">
|
|
|
|
|
|
<Select placeholder="请选择主类别"
|
|
|
style={{width: 180}}
|
|
|
onChange={this.selectleft}
|
|
|
defaultOpen={false}
|
|
|
>
|
|
|
{
|
|
|
newshixunlist === undefined ? "" : newshixunlist.main_type.map((item, key) => {
|
|
|
return (
|
|
|
<Option value={item.id} key={key}>
|
|
|
<Tooltip placement="right"
|
|
|
title={item.description === "" ? "无描述" : item.description}>
|
|
|
{item.type_name}
|
|
|
</Tooltip>
|
|
|
</Option>
|
|
|
)
|
|
|
})
|
|
|
}
|
|
|
</Select>
|
|
|
<span className="fl color-grey lineh-20">
|
|
|
没有实验环境?
|
|
|
<a className="color-blue" onClick={this.post_apply}> 申请新建</a>
|
|
|
</span>
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
|
style={{"borderBottom": 'none','width': '61%','float': 'left','margin-top': '40px'}}
|
|
|
className="chooseDes pr"
|
|
|
>
|
|
|
<div className=" fl pr mr20">
|
|
|
{getFieldDecorator('selectright', {
|
|
|
rules: [{required: true, message: '请选择小类别'}],
|
|
|
})(
|
|
|
<div className=" fl pr mr20">
|
|
|
<Select placeholder="请选择小类别"
|
|
|
style={{width: 180}}
|
|
|
onChange={this.selectright}
|
|
|
defaultOpen={false}
|
|
|
>
|
|
|
{
|
|
|
newshixunlist === undefined ? "" : newshixunlist.small_type.map((item, key) => {
|
|
|
return (
|
|
|
<Option value={item.id} key={key}>
|
|
|
<Tooltip placement="right"
|
|
|
title={item.description === "" ? "无描述" : item.description}>
|
|
|
{item.type_name}
|
|
|
</Tooltip>
|
|
|
</Option>
|
|
|
)
|
|
|
})
|
|
|
}
|
|
|
</Select>
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
<span className="fl ml20 color-grey lineh-20">
|
|
|
<div>
|
|
|
<div className={"font-12"}>
|
|
|
已安装软件:hadoop3.1.0、jdk1.8;
|
|
|
</div>
|
|
|
<div className={"font-12"}>
|
|
|
说明:添加了hadoop3.1.0、jdk1.8的源码包,添加了hadoop3.1.0、jdk1.8的源码包
|
|
|
</div>
|
|
|
</div>
|
|
|
</span>
|
|
|
</div>
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
</Form>
|
|
|
|
|
|
{postapplyvisible===true?<style>
|
|
|
{
|
|
|
`
|
|
|
body{
|
|
|
overflow: hidden !important;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</style>:""}
|
|
|
|
|
|
<Modal
|
|
|
keyboard={false}
|
|
|
title="申请新建"
|
|
|
visible={postapplyvisible}
|
|
|
closable={false}
|
|
|
footer={null}
|
|
|
width={850}
|
|
|
heigth={720}
|
|
|
>
|
|
|
<div>
|
|
|
<li className="clearfix ml82" >
|
|
|
<label className="fl mt10 "><span
|
|
|
className="color-red fl mt3">*</span>语言: </label>
|
|
|
<textarea className={this.state.languagewritetype===true?"fl task-form-80 task-height-150 bor-reds":"fl task-form-80 task-height-150"}
|
|
|
style={{width:'89%',height:'100px'}}
|
|
|
onInput={this.setlanguagewrite}
|
|
|
value={languagewrite}
|
|
|
placeholder="请填写该镜像是基于什么语言:示例:Python"
|
|
|
id="demand_info"></textarea>
|
|
|
</li>
|
|
|
<div className={"color-red shixunspanred"}>{this.state.languagewritetype===true?"请填写该镜像语言":""}</div>
|
|
|
<li className="clearfix ml1">
|
|
|
<label className="panel-form-label fl ml50"><span
|
|
|
className="color-red fl mt3">*</span>系统环境: </label>
|
|
|
<textarea className={this.state.systemenvironmenttype===true?"fl task-form-80 task-height-150 bor-reds":"fl task-form-80 task-height-150"}
|
|
|
onInput={this.setsystemenvironment}
|
|
|
style={{height:'100px'}}
|
|
|
value={systemenvironment}
|
|
|
placeholder="请填写该镜像是基于什么linux系统环境,代码运行环境"
|
|
|
id="demand_info"></textarea>
|
|
|
</li>
|
|
|
<div className={"color-red shixunspanred"}>{this.state.systemenvironmenttype===true?"请填写该镜像语言系统环境":""}</div>
|
|
|
<li className="clearfix">
|
|
|
<label className="fl mt10" ><span
|
|
|
className="color-red fl mt3">*</span>测试代码运行方式: </label>
|
|
|
|
|
|
<textarea
|
|
|
className={this.state.testcoderunmodetype===true?"fl task-form-80 task-height-150 bor-reds":"fl task-form-80 task-height-150"}
|
|
|
onInput={this.settestcoderunmode}
|
|
|
value={testcoderunmode}
|
|
|
style={{height:'100px'}}
|
|
|
placeholder="请填写该镜像中测试代码运行方式"
|
|
|
id="demand_info"></textarea>
|
|
|
</li>
|
|
|
<div className={"color-red shixunspanred"}>{this.state.testcoderunmodetype===true?"请填写该镜像测试代码运行方式":""}</div>
|
|
|
<li className="clearfix ml50">
|
|
|
<label className="panel-form-label fl mt-5"><span
|
|
|
className="color-red fl">*</span>测试代码: </label>
|
|
|
<div className="mt10" style={{
|
|
|
display: "inline-block"
|
|
|
}}>
|
|
|
<Upload {...uploadProps}>
|
|
|
<Icon type="upload" className="fl mt3" > </Icon>
|
|
|
<span className="color-blue fl cdefault">上传附件</span>
|
|
|
<span className="color-grey-c fl ml10 ">(单个文件50M以内)</span>
|
|
|
|
|
|
</Upload>
|
|
|
</div>
|
|
|
|
|
|
</li>
|
|
|
<div className={"color-red shixunspanred"}>
|
|
|
{this.state.attachmentidstype===true?"请上传附件":""}
|
|
|
</div>
|
|
|
<li className="edu-txt-center clearfix ">
|
|
|
<a className="pop_close task-btn mr30"
|
|
|
onClick={() => this.sendhideModaly()}
|
|
|
>取消</a>
|
|
|
<Button type="primary" onClick={()=>this.sendsure_apply()}
|
|
|
className="task-btn task-btn-orange">确定</Button>
|
|
|
</li>
|
|
|
<div className="cl"></div>
|
|
|
</div>
|
|
|
{/*</Form>*/}
|
|
|
</Modal>
|
|
|
|
|
|
|
|
|
|
|
|
<Modal
|
|
|
keyboard={false}
|
|
|
title="提示"
|
|
|
visible={postapplytitle}
|
|
|
closable={false}
|
|
|
footer={null}
|
|
|
>
|
|
|
<div>
|
|
|
<div className="task-popup-content"><p
|
|
|
className="task-popup-text-center font-16"><span
|
|
|
className="font-17 mt10">新建申请已提交,请等待管理员的审核</span></p>
|
|
|
<li className="font-14 mt15 color-grey-6 edu-txt-center">我们将在1-2个工作日内与您联系
|
|
|
</li>
|
|
|
</div>
|
|
|
<div className="task-popup-OK clearfix">
|
|
|
<a className="task-btn task-btn-orange"
|
|
|
onClick={this.yeshidemodel}>知道啦</a>
|
|
|
</div>
|
|
|
</div>
|
|
|
</Modal>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div className="clearfix bor-bottom-greyE edu-back-white orderingbox newshixunbottombtn">
|
|
|
<div className=" edu-txt-center padding13-30">
|
|
|
<button type="button" className="ant-btn mr20 newshixunmode `backgroundFFF`" ><span>取 消</span></button>
|
|
|
<button type="button" className="ant-btn newshixunmode mr40 ant-btn-primary" type="primary" htmlType="submit" onClick={this.handleSubmit}><span>确 定</span></button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const NewshixunsNew = Form.create({name: 'newshixun'})(Newshixuns);
|
|
|
|
|
|
export default SnackbarHOC()(TPMIndexHOC(NewshixunsNew));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|