Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_aliyun_beta
杨树林 5 years ago
commit 3afcd6eedf

@ -1,14 +1,22 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-message-modal');
var $submitBtn = $modal.find('.submit-btn');
if ($modal.length > 0) {
$modal.on('hide.bs.modal', function(){
$modal.find('.modal-body').html('');
$submitBtn.unbind();
});
}
});
function showMessageModal(html) {
function showMessageModal(html, callback) {
var $modal = $('.modal.admin-message-modal');
var $submitBtn = $modal.find('.submit-btn');
$submitBtn.unbind();
if(callback !== undefined && typeof callback === 'function'){
$submitBtn.on('click', callback);
}
$modal.find('.modal-body').html(html);
$modal.modal('show');
}

@ -0,0 +1,78 @@
$(document).on('turbolinks:load', function() {
var $modal = $('.modal.admin-import-course-member-modal');
if ($modal.length > 0) {
var $form = $modal.find('form.admin-import-course-member-form');
var resetFileInputFunc = function(file){
file.after(file.clone().val(""));
file.remove();
}
$modal.on('show.bs.modal', function(){
$modal.find('.file-names').html('选择文件');
$modal.find('.upload-file-input').trigger('click');
});
$modal.on('hide.bs.modal', function(){
resetFileInputFunc($modal.find('.upload-file-input'));
});
$modal.on('change', '.upload-file-input', function(e){
var file = $(this)[0].files[0];
$modal.find('.file-names').html(file ? file.name : '请选择文件');
})
var importFormValid = function(){
if($form.find('input[name="file"]').val() == undefined || $form.find('input[name="file"]').val().length == 0){
$form.find('.error').html('请选择文件');
return false;
}
return true;
};
var buildResultMessage = function(data){
var messageHtml = "<div>导入结果:成功" + data.success + "条,失败"+ data.fail.length + "条</div>";
if(data.fail.length > 0){
messageHtml += '<table class="table"><thead class="thead-light"><tr><th>数据</th><th>失败原因</th></tr></thead><tbody>';
data.fail.forEach(function(item){
messageHtml += '<tr><td>' + item.data + '</td><td>' + item.message + '</td></tr>';
});
messageHtml += '</tbody></table>'
}
return messageHtml;
}
$modal.on('click', '.submit-btn', function(){
$form.find('.error').html('');
if (importFormValid()) {
$('body').mLoading({ text: '正在导入...' });
$.ajax({
method: 'POST',
dataType: 'json',
url: '/admins/import_course_members',
data: new FormData($form[0]),
processData: false,
contentType: false,
success: function(data){
$('body').mLoading('destroy');
$modal.modal('hide');
showMessageModal(buildResultMessage(data), function(){
window.location.reload();
});
},
error: function(res){
$('body').mLoading('destroy');
var data = res.responseJSON;
$form.find('.error').html(data.message);
}
});
}
});
}
});

@ -122,14 +122,18 @@ $(document).on('turbolinks:load', function(){
// 导入学生
var $importUserModal = $('.modal.admin-import-user-modal');
var $importUserForm = $importUserModal.find('form.admin-import-user-form')
var resetFileInputFunc = function(file){
file.after(file.clone().val(""));
file.remove();
}
$importUserModal.on('show.bs.modal', function(){
resetFileInputFunc($importUserModal.find('.upload-file-input'));
$importUserModal.find('.file-names').html('选择文件');
$importUserModal.find('.upload-file-input').trigger('click');
});
$importUserModal.find('.upload-file-input').on('change', function(e){
$importUserModal.on('change', '.upload-file-input', function(e){
var file = $(this)[0].files[0];
$importUserModal.find('.file-names').html(file ? file.name : '请选择文件');
})
@ -175,7 +179,9 @@ $(document).on('turbolinks:load', function(){
$('body').mLoading('destroy');
$importUserModal.modal('hide');
showMessageModal(buildResultMessage(data));
showMessageModal(buildResultMessage(data), function(){
window.location.reload();
});
},
error: function(res){
$('body').mLoading('destroy');

@ -212,7 +212,7 @@ class CoursesController < ApplicationController
@course.update_attributes!(course_params.merge(extra_params))
@course.update_course_modules(params[:course_module_types])
Rails.logger.info("###############course_update_end")
normal_status(0, "成功")
rescue => e
uid_logger_error(e.message)
@ -1484,8 +1484,10 @@ class CoursesController < ApplicationController
shixun_titles = shixun_homeworks.pluck(:name) + ["总得分"]
# 更新实训作业成绩
shixun_homeworks.includes(:homework_challenge_settings, :published_settings, :homework_commons_shixun).each do |homework|
homework.update_homework_work_score
unless course.is_end
shixun_homeworks.includes(:homework_challenge_settings, :published_settings, :homework_commons_shixun).each do |homework|
homework.update_homework_work_score
end
end
shixun_homeworks = shixun_homeworks&.includes(score_student_works: :user)

@ -916,7 +916,8 @@ class GamesController < ApplicationController
# 更新关卡状态和一些学习进度
def update_game_parameter game
game.update_attribute(:status, 0) if game.status == 1
game.update_attributes(status: 0, open_time: Time.now) if game.status == 3
# 第一次进入关卡更新时间
game.update_attributes(status: 0, open_time: Time.now) if game.open_time.blank? || game.status == 3
# 开启实训更新myshixuns的时间方便跟踪用于的学习进度。
game.myshixun.update_column(:updated_at, Time.now)
end

@ -601,7 +601,7 @@ class ShixunsController < ApplicationController
challenges.each_with_index do |challenge, index|
status = (index == 0 ? 0 : 3)
game_identifier = generate_identifier(Game, 12)
worker.add(base_attr.merge(challenge_id: challenge.id, status: status, open_time: Time.now,
worker.add(base_attr.merge(challenge_id: challenge.id, status: status,
identifier: game_identifier, modify_time: challenge.modify_time))
end
end

@ -1,7 +1,10 @@
class Wechats::JsSdkSignaturesController < ApplicationController
def create
signature = Util::Wechat.js_sdk_signature(params[:url], params[:noncestr], params[:timestamp])
render_ok(signature: signature)
timestamp = (Time.now.to_f * 1000).to_i
noncestr = ('A'..'z').to_a.sample(8).join
signature = Util::Wechat.js_sdk_signature(params[:url], noncestr, timestamp)
render_ok(appid: Util::Wechat.appid, timestamp: timestamp, noncestr: noncestr, signature: signature)
rescue Util::Wechat::Error => ex
render_error(ex.message)
end

@ -0,0 +1,30 @@
<div class="modal fade admin-import-course-member-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">导入课堂成员</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="admin-import-course-member-form" enctype="multipart/form-data">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">文件</span>
</div>
<div class="custom-file">
<input type="file" name="file" id="import-course-member-input" class="upload-file-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label class="custom-file-label file-names" for="import-course-member-input">选择文件</label>
</div>
</div>
<div class="error text-danger"></div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary submit-btn">确认</button>
</div>
</div>
</div>
</div>

@ -11,7 +11,7 @@
保存成功
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">确认</button>
<button type="button" class="btn btn-primary submit-btn" data-dismiss="modal">确认</button>
</div>
</div>
</div>

@ -28,6 +28,7 @@
<% end %>
<%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %>
<%= javascript_void_link '导入课堂成员', class: 'btn btn-secondary btn-sm ml-2', data: { toggle: 'modal', target: '.admin-import-course-member-modal'} %>
</div>
<div class="box users-list-container">
@ -35,4 +36,7 @@
</div>
<%= render partial: 'admins/users/shared/reward_grade_modal' %>
<%= render partial: 'admins/users/shared/import_user_modal' %>
<%= render partial: 'admins/users/shared/import_user_modal' %>
<!-- TODO: move to course list page -->
<%= render partial: 'admins/courses/shared/import_course_member_modal' %>

@ -14,8 +14,8 @@
<span class="input-group-text">文件</span>
</div>
<div class="custom-file">
<input type="file" name="file" class="upload-file-input" id="upload-file-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label class="custom-file-label file-names" for="upload-file-input">选择文件</label>
<input type="file" name="file" class="upload-file-input" id="import-user-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<label class="custom-file-label file-names" for="import-user-input">选择文件</label>
</div>
</div>
<div class="error text-danger"></div>

@ -20,6 +20,7 @@ if @course
json.group_info @course.teacher_group(@user.id) if @course_identity < Course::STUDENT
end
json.first_category_url module_url(@course.none_hidden_course_modules.first, @course)
json.course_is_end @course.is_end
end
if params[:school]

@ -776,6 +776,10 @@ Rails.application.routes.draw do
end
post 'callbacks/aliyun_vod', to: 'callbacks/aliyun_vods#create'
namespace :wechats do
resource :js_sdk_signature, only: [:create]
end
end
namespace :admins do
@ -884,10 +888,6 @@ Rails.application.routes.draw do
end
end
namespace :wechats do
resource :js_sdk_signature, only: [:create]
end
#git 认证回调
match 'gitauth/*url', to: 'gits#auth', via: :all

Binary file not shown.

@ -383,12 +383,12 @@ class Comments extends Component {
{/* <span className="ml5 mr5 color-grey-8">|</span>*/}
<a href={`javascript:void(0)`} className="color-grey-8"
{(this.props.showReply == undefined || this.props.showReply == true) && <a href={`javascript:void(0)`} className="color-grey-8"
onClick={() => this.initReply(item) } >
<Tooltip title={ "回复" }>
<i className="iconfont icon-huifu1 mr5"></i>
</Tooltip>
</a>
</a>}
{/* <span className="ml5 mr5 color-grey-8">|</span>*/}

@ -527,6 +527,7 @@ class TopicDetail extends Component {
// TODO 图片上传地址
const courseId=this.props.match.params.coursesId;
const boardId = this.props.match.params.boardId
const isCourseEnd = this.props.isCourseEnd()
return (
<div className="edu-back-white edu-class-container edu-position course-message topicDetail" id="yslforum_index_list"> {/* fl with100 */}
<style>{`
@ -678,8 +679,8 @@ class TopicDetail extends Component {
}
</div>
<MemoDetailMDEditor ref="editor" memo={memo} usingMockInput={true} placeholder="说点什么"
height={160} showError={true} buttonText={'发表'} className={comments && comments.length && 'borderBottom'}></MemoDetailMDEditor>
{!isCourseEnd && <MemoDetailMDEditor ref="editor" memo={memo} usingMockInput={true} placeholder="说点什么"
height={160} showError={true} buttonText={'发表'} className={comments && comments.length && 'borderBottom'}></MemoDetailMDEditor>}
{/* onClick={ this.createNewComment }
enableReplyTo={true}
@ -704,6 +705,7 @@ class TopicDetail extends Component {
loadMoreChildComments={this.loadMoreChildComments}
initReply={this.initReply}
showRewardButton={false}
showReply={!isCourseEnd}
onlySuperAdminCouldHide={true}
></Comments>
@ -720,7 +722,7 @@ class TopicDetail extends Component {
{ total_count > REPLY_PAGE_COUNT &&
<Pagination showQuickJumper onChange={this.onPaginationChange} current={pageCount} total={total_count} pageSize={10}/>
}
<div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>
{!isCourseEnd && <div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>}
</div>
</div>

@ -327,6 +327,7 @@ class Boards extends Component{
}
render(){
const isAdmin = this.props.isAdmin()
const isCourseEnd = this.props.isCourseEnd()
const isAdminOrStudent = this.props.isAdminOrStudent()
let { boardName, searchValue, boards, messages, checkBoxValues,
checkAllValue, pagination, sort_type, parent_id } = this.state;
@ -350,9 +351,9 @@ class Boards extends Component{
searchPlaceholder={ '请输入帖子名称进行搜索' }
firstRowRight={
<React.Fragment>
{ isAdmin && !parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>添加目录</WordsBtn> }
{ !isCourseEnd && isAdmin && !parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>添加目录</WordsBtn> }
{ isAdmin && !!parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>目录重命名</WordsBtn> }
{ isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> }
{ !isCourseEnd && isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> }
</React.Fragment>
}
secondRowLeft={

@ -646,7 +646,7 @@ render(){
{/*<span className="color-grey-9 ml3 mr3">&gt;</span>*/}
{/*</WordsBtn>*/}
<span>{`${current_user ? current_user.username : ''} ${ this.isEdit ? '编辑' : '提交'}作品` }</span>
<span>{`${current_user ? current_user.real_name : ''} ${ this.isEdit ? '编辑' : '提交'}作品` }</span>
</p>
<div style={{ width:'100%',height:'75px'}} >

@ -426,7 +426,7 @@ class CoursesBanner extends Component {
render() {
let { Addcoursestypes, coursedata,excellent, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,is_guide,AccountProfiletype} = this.state;
const isCourseEnd = this.props.isCourseEnd()
return (
<div>
{
@ -714,24 +714,24 @@ class CoursesBanner extends Component {
position: "relative"
}}
>
<li className={"mt7 mr10im"}>
{!isCourseEnd && <li className={"mt7 mr10im"}>
<a onClick={()=>this.addTeacher(true)}>
<span className="color-white fl font-16 bannerurli width100f">添加老师</span>
</a>
</li>
</li>}
<li className={"mt7 mr10im"}>
{!isCourseEnd && <li className={"mt7 mr10im"}>
<a onClick={()=>this.addTeacher(false)}>
<span className="color-white fl font-16 bannerurli width100f">添加助教</span>
</a>
</li>
</li>}
<li className={"mt7 mr10im"}>
{!isCourseEnd && <li className={"mt7 mr10im"}>
<a onClick={()=>this.addStudent()}>
<span className={"color-white fl font-16 bannerurli width100f"}>添加学生</span>
</a>
</li>
</li>}
{excellent===false?
<li className={"mt7 mr10im ml10"} style={{overflow:"hidden"}}>
<a>

@ -619,7 +619,7 @@ class GraduationTasksSubmitedit extends Component{
{/*<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id} className="color-grey-6">{workslist&&workslist.task_name}</Link>*/}
{/*<span className="color-grey-9 ml3 mr3">&gt;</span>*/}
{/*</WordsBtn>*/}
<span>{this.props.user&&this.props.user.username} 修改作品</span>
<span>{this.props.current_user&&this.props.current_user.real_name} 修改作品</span>
</p>
<div style={{ width:'100%',height:'75px'}} >

@ -552,7 +552,7 @@ render(){
},
};
// console.log(this.props)
console.log(this.props)
@ -601,7 +601,7 @@ render(){
{/*<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id} className="color-grey-6">{workslist&&workslist.task_name}</Link>*/}
{/*<span className="color-grey-9 ml3 mr3">&gt;</span>*/}
{/*</WordsBtn>*/}
<span>{this.props.user&&this.props.user.username} 提交作品</span>
<span>{this.props.current_user&&this.props.current_user.real_name} 提交作品</span>
</p>
<div style={{ width:'100%',height:'75px'}} >

@ -497,6 +497,7 @@ class studentsList extends Component{
render(){
const isAdmin = this.props.isAdmin()
const isSuperAdmin = this.props.isSuperAdmin()
const isCourseEnd = this.props.isCourseEnd()
let {
page,
@ -591,7 +592,7 @@ class studentsList extends Component{
></CreateGroupByImportModal>
<WordsBtn style="blue" className="mr30" onClick={()=> this.refs['createGroupByImportModal'].setVisible(true)}>导入创建分班</WordsBtn>
</React.Fragment> }
{ isAdmin && isParent && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>添加分班</WordsBtn> }
{ !isCourseEnd && isAdmin && isParent && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>添加分班</WordsBtn> }
{ isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={()=>this.deleteDir()}>删除分班</WordsBtn> }
{ isAdmin && !isParent && course_group_id != 0 && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>分班重命名</WordsBtn> }
<style>{`

@ -2499,6 +2499,8 @@ class Listofworksstudentone extends Component {
// console.log(data);
// console.log(datas);
// console.log(this.props.isAdmin());
let course_is_end = this.props.current_user&&this.props.current_user.course_is_end;
return (
this.props.isAdmin() === true ?
(
@ -2639,7 +2641,7 @@ class Listofworksstudentone extends Component {
<ul className="clearfix" style={{padding: '20px 15px 10px 20px'}}>
<li className="clearfix ">
<span className="fl mr10 color-grey-6 ">计算成绩时间{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}</span>
<span>
{course_is_end===true?<span>
{teacherdata&&teacherdata.publish_immediately===false&&computeTimetype===true?
(this.props.isNotMember()===false?<div className={"computeTime font-13"} onClick={this.setComputeTimet}>
计算成绩
@ -2649,7 +2651,7 @@ class Listofworksstudentone extends Component {
计算成绩
</div>:"")
}
</span>
</span>:""}
<div className="fr mr5 search-newysl" style={{marginBottom: '1px'}}>
<Search
@ -2944,7 +2946,7 @@ class Listofworksstudentone extends Component {
<div className="fr">
<span className="fl mr10 color-grey-6 ">计算成绩时间{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}</span>
{teacherdata&&teacherdata.task_operation[0]==="开启挑战"?"":<span>
{ course_is_end===true?"":teacherdata&&teacherdata.task_operation[0]==="开启挑战"?"":<span>
{computeTimetype===true?
(this.props.isNotMember()===false?
<div className={"computeTime font-13"} onClick={this.setComputeTime}>
@ -3154,7 +3156,7 @@ class Listofworksstudentone extends Component {
<div className="fr">
<span className="fl mr10 color-grey-6 ">计算成绩时间{teacherdata&&teacherdata.calculation_time==null?"--": moment(teacherdata&&teacherdata.calculation_time).format('YYYY-MM-DD HH:mm')}</span>
{teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":<span>
{ course_is_end===true?"":teacherdata&&teacherdata.task_operation&&teacherdata.task_operation[0]==="开启挑战"?"":<span>
{computeTimetype===true?
(this.props.isNotMember()===false?<div className={"computeTime font-13"} onClick={this.setComputeTime}>
计算成绩

@ -244,6 +244,10 @@ export function TPMIndexHOC(WrappedComponent) {
return this.state.coursedata&&this.state.coursedata.course_identity >= 6
}
isCourseEnd = () => {
return this.state.current_user ? this.state.current_user.course_is_end : false
}
// setTrialapplication = ()=>{
// this.setState({
// isRenders:true
@ -411,6 +415,8 @@ export function TPMIndexHOC(WrappedComponent) {
isStudent: this.isStudent,
isAdminOrStudent: this.isAdminOrStudent,
isNotMember: this.isNotMember,
isCourseEnd: this.isCourseEnd,
isUserid:this.state.coursedata&&this.state.coursedata.userid,
fetchUser: this.fetchUser,

@ -15,7 +15,7 @@ import axios from 'axios';
import './css/TPMsettings.css';
import { getImageUrl, toPath, getUrl ,appendFileSizeToUploadFileAll} from 'educoder';
import { getImageUrl, toPath, getUrl ,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder';
let origin = getUrl();
@ -1372,15 +1372,18 @@ export default class TPMsettings extends Component {
})
}
handleChange = (info) => {
let {fileList}=this.state;
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
console.log("handleChange1");
let {fileList}=this.state;
if(fileList.length===0){
// if(fileList.length===0){
let fileLists = info.fileList;
this.setState({ fileList:fileLists,
deleteisnot:false});
}
// }
}
}
@ -1497,10 +1500,13 @@ export default class TPMsettings extends Component {
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
action: `${getUploadActionUrl()}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
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) {

@ -561,7 +561,8 @@ export default class TPMevaluation extends Component {
if(type==="sr"){
newevaluationlist[key].input=e.target.value
}else if(type==="yq"){
newevaluationlist[key].output=e.target.value
// 统一转成\r\n
newevaluationlist[key].output= e.target.value ? e.target.value.replace(/\r?\n/g, "\r\n") : e.target.value
}
this.setevaluationlist(newevaluationlist);
}

@ -2,7 +2,7 @@ import React, {Component} from 'react';
import {TPMIndexHOC} from '../TPMIndexHOC';
import {SnackbarHOC,appendFileSizeToUploadFileAll} from 'educoder';
import {SnackbarHOC,appendFileSizeToUploadFileAll, getUploadActionUrl} from 'educoder';
import {Input, Select, Radio, Checkbox, Modal, Icon, DatePicker,Upload,Button,message,Form,notification,Tooltip} from 'antd';
@ -757,19 +757,19 @@ class Newshixuns extends Component {
})
}
// 附件相关 START
handleChange = (info) => {
let {fileList}=this.state;
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let {fileList}=this.state;
console.log("handleChange1");
if(fileList.length===0){
// if(fileList.length===0){
let fileLists = info.fileList;
this.setState({
// fileList:appendFileSizeToUploadFileAll(fileList),
fileList:fileLists,
deleteisnot:false});
}
// }
}
}
@ -872,10 +872,14 @@ class Newshixuns extends Component {
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
action: `${getUploadActionUrl()}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
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) {

Loading…
Cancel
Save