| @@ -1,529 +0,0 @@ | |||||
| import React, {Component} from 'react'; | |||||
| import logo from './logo.svg'; | |||||
| import './App.css'; | |||||
| import {LocaleProvider} from 'antd' | |||||
| import zhCN from 'antd/lib/locale-provider/zh_CN'; | |||||
| import { | |||||
| BrowserRouter as Router, | |||||
| Route, | |||||
| Switch | |||||
| } from 'react-router-dom'; | |||||
| import axios from 'axios'; | |||||
| import '@icedesign/base/dist/ICEDesignBase.css'; | |||||
| import '@icedesign/base/index.scss'; | |||||
| import LoginDialog from './modules/login/LoginDialog'; | |||||
| import Notcompletedysl from './modules/user/Notcompletedysl'; | |||||
| import Trialapplicationysl from './modules/login/Trialapplicationysl'; | |||||
| import Trialapplicationreview from './modules/user/Trialapplicationreview'; | |||||
| import Addcourses from "./modules/courses/coursesPublic/Addcourses"; | |||||
| import AccountProfile from"./modules/user/AccountProfile"; | |||||
| import Trialapplication from './modules/login/Trialapplication' | |||||
| import NotFoundPage from './NotFoundPage' | |||||
| import Loading from './Loading' | |||||
| import Loadable from 'react-loadable'; | |||||
| import moment from 'moment' | |||||
| import {MuiThemeProvider, createMuiTheme} from 'material-ui/styles'; | |||||
| // import './AppConfig' | |||||
| import history from './history'; | |||||
| import {SnackbarHOC} from 'educoder' | |||||
| import {initAxiosInterceptors} from './AppConfig' | |||||
| // !!!tpi需要这个来加载css | |||||
| import {TPMIndexHOC} from './modules/tpm/TPMIndexHOC'; | |||||
| const theme = createMuiTheme({ | |||||
| palette: { | |||||
| primary: { | |||||
| main: '#4CACFF', | |||||
| contrastText: 'rgba(255, 255, 255, 0.87)' | |||||
| }, | |||||
| secondary: {main: '#4CACFF'}, // #11cb5f This is just green.A700 as hex. | |||||
| }, | |||||
| }); | |||||
| // | |||||
| // const Trialapplication= Loadable({ | |||||
| // loader: () =>import('./modules/login/Trialapplication'), | |||||
| // loading:Loading, | |||||
| // }) | |||||
| //登入 | |||||
| const EducoderLogin = Loadable({ | |||||
| loader: () => import('./modules/login/EducoderLogin'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TestIndex = Loadable({ | |||||
| loader: () => import('./modules/test'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const IndexWrapperComponent = Loadable({ | |||||
| loader: () => import('./modules/page/IndexWrapper'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const CommentComponent = Loadable({ | |||||
| loader: () => import('./modules/comment/CommentContainer'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TestMaterialDesignComponent = Loadable({ | |||||
| loader: () => import('./modules/test/md/TestMaterialDesign'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TestCodeMirrorComponent = Loadable({ | |||||
| loader: () => import('./modules/test/codemirror/TestCodeMirror'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TestComponent = Loadable({ | |||||
| loader: () => import('./modules/test/TestRC'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TestUrlQueryComponent = Loadable({ | |||||
| loader: () => import('./modules/test/urlquery/TestUrlQuery'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TPMIndexComponent = Loadable({ | |||||
| loader: () => import('./modules/tpm/TPMIndex'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const TPMShixunsIndexComponent = Loadable({ | |||||
| loader: () => import('./modules/tpm/shixuns/ShixunsIndex'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //实训课程(原实训路径) | |||||
| const ShixunPaths = Loadable({ | |||||
| loader: () => import('./modules/paths/Index'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //在线课堂 | |||||
| const CoursesIndex = Loadable({ | |||||
| loader: () => import('./modules/courses/Index'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const SearchPage = Loadable({ | |||||
| loader: () => import('./search/SearchPage'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //教学案例 | |||||
| const MoopCases = Loadable({ | |||||
| loader: () => import('./modules/moop_cases/index'), | |||||
| loading: Loading, | |||||
| }) | |||||
| // 课堂讨论 | |||||
| // const BoardIndex = Loadable({ | |||||
| // loader: () => import('./modules/courses/boards/BoardIndex'), | |||||
| // loading:Loading, | |||||
| // }) | |||||
| // //课堂普通作业&分组作业 | |||||
| // const CoursesWorkIndex = Loadable({ | |||||
| // loader: () => import('./modules/courses/busyWork/Index'), | |||||
| // loading:Loading, | |||||
| // }) | |||||
| // | |||||
| // const TPMShixunchildIndexComponent = Loadable({ | |||||
| // loader: () => import('./modules/tpm/shixunchild/ShixunChildIndex'), | |||||
| // loading: Loading, | |||||
| // }) | |||||
| // const TPMshixunfork_listIndexComponent = Loadable({ | |||||
| // loader: () => import('./modules/tpm/shixunchild/Shixunfork_list'), | |||||
| // loading: Loading, | |||||
| // }) | |||||
| const ForumsIndexComponent = Loadable({ | |||||
| loader: () => import('./modules/forums/ForumsIndex'), | |||||
| loading: Loading, | |||||
| }) | |||||
| // trustie plus forum | |||||
| // const TPForumsIndexComponent = Loadable({ | |||||
| // loader: () => import('./modules/tp-forums/TPForumsIndex'), | |||||
| // loading: Loading, | |||||
| // }) | |||||
| // const TestPageComponent = Loadable({ | |||||
| // loader: () => import('./modules/page/Index'), | |||||
| // loading: Loading, | |||||
| // }) | |||||
| //新建实训 | |||||
| const Newshixuns = Loadable({ | |||||
| loader: () => import('./modules/tpm/newshixuns/Newshixuns'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //实训首页 | |||||
| const ShixunsHome = Loadable({ | |||||
| loader: () => import('./modules/home/shixunsHome'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const CompatibilityPageLoadable = Loadable({ | |||||
| loader: () => import('./modules/common/CompatibilityPage'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //403页面 | |||||
| const Shixunauthority = Loadable({ | |||||
| loader: () => import('./modules/403/Shixunauthority'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //404页面 | |||||
| const Shixunnopage = Loadable({ | |||||
| loader: () => import('./modules/404/Shixunnopage'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //500页面 | |||||
| const http500 = Loadable({ | |||||
| loader: () => import('./modules/500/http500'), | |||||
| loading: Loading, | |||||
| }) | |||||
| // 登录注册 | |||||
| const LoginRegisterPage = Loadable({ | |||||
| loader: () => import('./modules/user/LoginRegisterPage'), | |||||
| loading: Loading, | |||||
| }) | |||||
| const AccountPage = Loadable({ | |||||
| loader: () => import('./modules/user/AccountPage'), | |||||
| loading: Loading, | |||||
| }) | |||||
| // 个人主页 | |||||
| const UsersInfo = Loadable({ | |||||
| loader: () => import('./modules/user/usersInfo/Infos'), | |||||
| loading: Loading, | |||||
| }) | |||||
| // 兴趣页面 | |||||
| const Interestpage = Loadable({ | |||||
| loader: () => import('./modules/login/EducoderInteresse'), | |||||
| loading: Loading, | |||||
| }) | |||||
| //众包创新 | |||||
| const ProjectPackages=Loadable({ | |||||
| loader: () => import('./modules/projectPackages/ProjectPackageIndex'), | |||||
| loading: Loading, | |||||
| }) | |||||
| class App extends Component { | |||||
| constructor(props) { | |||||
| super(props) | |||||
| // this.state = { | |||||
| // isRenders:false, | |||||
| // } | |||||
| } | |||||
| componentDidMount() { | |||||
| // force an update if the URL changes | |||||
| history.listen(() => { | |||||
| this.forceUpdate() | |||||
| const $ = window.$ | |||||
| // https://www.trustie.net/issues/21919 可能会有问题 | |||||
| $("html").animate({ scrollTop: $('html').scrollTop() - 0 }) | |||||
| }); | |||||
| initAxiosInterceptors(this.props) | |||||
| // | |||||
| // axios.interceptors.response.use((response) => { | |||||
| // // console.log("response"+response); | |||||
| // if(response!=undefined) | |||||
| // // console.log("response"+response.data.statu); | |||||
| // if (response&&response.data.status === 407) { | |||||
| // this.setState({ | |||||
| // isRenders: true, | |||||
| // }) | |||||
| // } | |||||
| // return response; | |||||
| // }, (error) => { | |||||
| // //TODO 这里如果样式变了会出现css不加载的情况 | |||||
| // }); | |||||
| } | |||||
| //修改登录方法 | |||||
| Modifyloginvalue=()=>{ | |||||
| this.setState({ | |||||
| isRender:false, | |||||
| }) | |||||
| } | |||||
| render() { | |||||
| return ( | |||||
| <LocaleProvider locale={zhCN}> | |||||
| <MuiThemeProvider theme={theme}> | |||||
| <LoginDialog {...this.props} {...this.state} Modifyloginvalue={()=>this.Modifyloginvalue()}></LoginDialog> | |||||
| <Notcompletedysl {...this.props} {...this.state}></Notcompletedysl> | |||||
| <Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl> | |||||
| <Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview> | |||||
| <Addcourses {...this.props} {...this.state}/> | |||||
| <AccountProfile {...this.props} {...this.state}/> | |||||
| {/*{*/} | |||||
| {/* isRender === true?*/} | |||||
| {/* <LoginDialog></LoginDialog> : ""*/} | |||||
| {/*}*/} | |||||
| {/*{*/} | |||||
| {/* isRenders === true?*/} | |||||
| {/*<Trialapplication></Trialapplication>*/} | |||||
| {/*:""*/} | |||||
| {/*}*/} | |||||
| <Router> | |||||
| <Switch> | |||||
| {/*<Route path="/login" component={LoginRegisterPage}/>*/} | |||||
| {/*众包创新*/} | |||||
| <Route path={"/crowdsourcings"} component={ProjectPackages}/> | |||||
| {/*认证*/} | |||||
| <Route path="/account" component={AccountPage}/> | |||||
| {/*403*/} | |||||
| <Route path="/403" component={Shixunauthority}/> | |||||
| <Route path="/500" component={http500}/> | |||||
| {/*404*/} | |||||
| <Route path="/nopage" component={Shixunnopage}/> | |||||
| <Route path="/compatibility" component={CompatibilityPageLoadable}/> | |||||
| <Route | |||||
| path="/login" component={EducoderLogin} | |||||
| /> | |||||
| <Route | |||||
| path="/register" component={EducoderLogin} | |||||
| /> | |||||
| <Route path="/users/:username" | |||||
| render={ | |||||
| (props) => (<UsersInfo {...this.props} {...props} {...this.state} />) | |||||
| }></Route> | |||||
| {/*<Route*/} | |||||
| {/* path="/trialapplication" component={Trialapplication}*/} | |||||
| {/*/>*/} | |||||
| <Route | |||||
| path="/changepassword" component={EducoderLogin} | |||||
| /> | |||||
| <Route | |||||
| path="/interesse" component={Interestpage} | |||||
| /> | |||||
| <Route path="/shixuns/new" component={Newshixuns}> | |||||
| </Route> | |||||
| <Route path="/tasks/:stageId" component={IndexWrapperComponent}/> | |||||
| <Route path="/shixuns/:shixunId" component={TPMIndexComponent}> | |||||
| </Route> | |||||
| {/*列表页*/} | |||||
| <Route path="/shixuns" component={TPMShixunsIndexComponent}/> | |||||
| {/* <Route path="/shixunchild" component={TPMShixunchildIndexComponent}> | |||||
| </Route> | |||||
| <Route path="/fork_list" component={TPMshixunfork_listIndexComponent}> | |||||
| </Route> */} | |||||
| {/*<Route path="/forums" component={ForumsIndexComponent}>*/} | |||||
| {/*</Route>*/} | |||||
| {/*实训课程(原实训路径)*/} | |||||
| <Route path="/paths" component={ShixunPaths}></Route> | |||||
| <Route path="/search" | |||||
| render={ | |||||
| (props)=>(<SearchPage {...this.props} {...props} {...this.state}></SearchPage>) | |||||
| } | |||||
| ></Route> | |||||
| {/*课堂*/} | |||||
| <Route path="/courses" component={CoursesIndex} {...this.props}></Route> | |||||
| {/* 课堂讨论 */} | |||||
| {/* <Route path="/board" component = {BoardIndex} {...this.props}></Route> */} | |||||
| {/* <Route path="/tpforums" component={TPForumsIndexComponent}> | |||||
| </Route> */} | |||||
| {/* <Route path="/myshixuns/:shixunId/stages/:stageId" component={Index}/> */} | |||||
| {/* 兴趣页面*/} | |||||
| {/*<Route path="/interest" component={Interestpage}/>*/} | |||||
| <Route path="/comment" component={CommentComponent}/> | |||||
| <Route path="/testMaterial" component={TestMaterialDesignComponent}/> | |||||
| <Route path="/test" component={TestIndex}/> | |||||
| <Route path="/testCodeMirror" component={TestCodeMirrorComponent}/> | |||||
| <Route path="/testRCComponent" component={TestComponent}/> | |||||
| <Route path="/testUrlQuery" component={TestUrlQueryComponent}/> | |||||
| {/* 教学案例 */} | |||||
| <Route path="/moop_cases"render={ | |||||
| (props) => (<MoopCases {...this.props} {...props} {...this.state} />) | |||||
| }/> | |||||
| {/* <Route component={NotFoundPage}/> */} | |||||
| {/*列表页*/} | |||||
| {/*<Route component={TPMShixunsIndexComponent}/>*/} | |||||
| {/*首页*/} | |||||
| <Route exact path="/" component={ShixunsHome}/> | |||||
| <Route component={Shixunnopage}/> | |||||
| {/*<Route component={ShixunsHome}/>*/} | |||||
| </Switch> | |||||
| </Router> | |||||
| </MuiThemeProvider> | |||||
| </LocaleProvider> | |||||
| ); | |||||
| } | |||||
| } | |||||
| // moment国际化,设置为中文 | |||||
| moment.defineLocale('zh-cn', { | |||||
| months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), | |||||
| monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), | |||||
| weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), | |||||
| weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'), | |||||
| weekdaysMin: '日_一_二_三_四_五_六'.split('_'), | |||||
| longDateFormat: { | |||||
| LT: 'Ah点mm分', | |||||
| LTS: 'Ah点m分s秒', | |||||
| L: 'YYYY-MM-DD', | |||||
| LL: 'YYYY年MMMD日', | |||||
| LLL: 'YYYY年MMMD日Ah点mm分', | |||||
| LLLL: 'YYYY年MMMD日ddddAh点mm分', | |||||
| l: 'YYYY-MM-DD', | |||||
| ll: 'YYYY年MMMD日', | |||||
| lll: 'YYYY年MMMD日Ah点mm分', | |||||
| llll: 'YYYY年MMMD日ddddAh点mm分' | |||||
| }, | |||||
| meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, | |||||
| meridiemHour: function (hour, meridiem) { | |||||
| if (hour === 12) { | |||||
| hour = 0; | |||||
| } | |||||
| if (meridiem === '凌晨' || meridiem === '早上' || | |||||
| meridiem === '上午') { | |||||
| return hour; | |||||
| } else if (meridiem === '下午' || meridiem === '晚上') { | |||||
| return hour + 12; | |||||
| } else { | |||||
| // '中午' | |||||
| return hour >= 11 ? hour : hour + 12; | |||||
| } | |||||
| }, | |||||
| meridiem: function (hour, minute, isLower) { | |||||
| var hm = hour * 100 + minute; | |||||
| if (hm < 600) { | |||||
| return '凌晨'; | |||||
| } else if (hm < 900) { | |||||
| return '早上'; | |||||
| } else if (hm < 1130) { | |||||
| return '上午'; | |||||
| } else if (hm < 1230) { | |||||
| return '中午'; | |||||
| } else if (hm < 1800) { | |||||
| return '下午'; | |||||
| } else { | |||||
| return '晚上'; | |||||
| } | |||||
| }, | |||||
| calendar: { | |||||
| sameDay: function () { | |||||
| return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; | |||||
| }, | |||||
| nextDay: function () { | |||||
| return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; | |||||
| }, | |||||
| lastDay: function () { | |||||
| return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; | |||||
| }, | |||||
| nextWeek: function () { | |||||
| var startOfWeek, prefix; | |||||
| startOfWeek = moment().startOf('week'); | |||||
| prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; | |||||
| return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; | |||||
| }, | |||||
| lastWeek: function () { | |||||
| var startOfWeek, prefix; | |||||
| startOfWeek = moment().startOf('week'); | |||||
| prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; | |||||
| return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; | |||||
| }, | |||||
| sameElse: 'LL' | |||||
| }, | |||||
| ordinalParse: /\d{1,2}(日|月|周)/, | |||||
| ordinal: function (number, period) { | |||||
| switch (period) { | |||||
| case 'd': | |||||
| case 'D': | |||||
| case 'DDD': | |||||
| return number + '日'; | |||||
| case 'M': | |||||
| return number + '月'; | |||||
| case 'w': | |||||
| case 'W': | |||||
| return number + '周'; | |||||
| default: | |||||
| return number; | |||||
| } | |||||
| }, | |||||
| relativeTime: { | |||||
| future: '%s内', | |||||
| past: '%s前', | |||||
| s: '几秒', | |||||
| m: '1分钟', | |||||
| mm: '%d分钟', | |||||
| h: '1小时', | |||||
| hh: '%d小时', | |||||
| d: '1天', | |||||
| dd: '%d天', | |||||
| M: '1个月', | |||||
| MM: '%d个月', | |||||
| y: '1年', | |||||
| yy: '%d年' | |||||
| }, | |||||
| week: { | |||||
| // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 | |||||
| dow: 1, // Monday is the first day of the week. | |||||
| doy: 4 // The week that contains Jan 4th is the first week of the year. | |||||
| } | |||||
| }); | |||||
| export default SnackbarHOC()(App); | |||||
| @@ -338,10 +338,10 @@ http://localhost:3000/api/projects/ | jq | |||||
| |-|-|-|-| | |-|-|-|-| | ||||
| |user_id |是|int |用户id或者组织id | | |user_id |是|int |用户id或者组织id | | ||||
| |name |是|string |项目名称 | | |name |是|string |项目名称 | | ||||
| |description |是|string |项目描述 | | |||||
| |description |否|string |项目描述 | | |||||
| |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | ||||
| |project_category_id|是|int |项目类别id | | |||||
| |project_language_id|是|int |项目语言id | | |||||
| |project_category_id|否|int |项目类别id | | |||||
| |project_language_id|否|int |项目语言id | | |||||
| |ignore_id |否|int |gitignore相关id | | |ignore_id |否|int |gitignore相关id | | ||||
| |license_id |否|int |开源许可证id | | |license_id |否|int |开源许可证id | | ||||
| |private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | | |private |否|boolean|项目是否私有, true:为私有,false: 公开,默认为公开 | | ||||
| @@ -374,9 +374,7 @@ curl -X POST \ | |||||
| -d "user_id=36408" \ | -d "user_id=36408" \ | ||||
| -d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ | -d "clone_addr=https://gitea.com/mx8090alex/golden.git" \ | ||||
| -d "name=golden_mirror1" \ | -d "name=golden_mirror1" \ | ||||
| -d "description=golden_mirror" \ | |||||
| -d "project_category_id=1" \ | |||||
| -d "project_language_id=2" \ | |||||
| -d "repository_name=golden_mirror1" \ | |||||
| http://localhost:3000/api/projects/migrate.json | jq | http://localhost:3000/api/projects/migrate.json | jq | ||||
| ``` | ``` | ||||
| *请求参数说明:* | *请求参数说明:* | ||||
| @@ -388,8 +386,8 @@ http://localhost:3000/api/projects/migrate.json | jq | |||||
| |clone_addr |是|string |镜像项目clone地址 | | |clone_addr |是|string |镜像项目clone地址 | | ||||
| |description |否|string |项目描述 | | |description |否|string |项目描述 | | ||||
| |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | |repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 | | ||||
| |project_category_id|是|int |项目类别id | | |||||
| |project_language_id|是|int |项目语言id | | |||||
| |project_category_id|否|int |项目类别id | | |||||
| |project_language_id|否|int |项目语言id | | |||||
| |is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | | |is_mirror |否|boolean|是否设置为镜像, true:是, false:否,默认为否 | | ||||
| |auth_username |否|string|镜像源仓库的登录用户名 | | |auth_username |否|string|镜像源仓库的登录用户名 | | ||||
| |auth_password |否|string|镜像源仓库的登录秘密 | | |auth_password |否|string|镜像源仓库的登录秘密 | | ||||
| @@ -0,0 +1,55 @@ | |||||
| class Admins::EduSettingsController < Admins::BaseController | |||||
| before_action :find_setting, only: [:edit,:update, :destroy] | |||||
| def index | |||||
| default_sort('id', 'desc') | |||||
| edu_settings = Admins::EduSettingQuery.call(params) | |||||
| @edu_settings = paginate edu_settings | |||||
| end | |||||
| def new | |||||
| @edu_setting = EduSetting.new | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def create | |||||
| @edu_setting = EduSetting.new(edu_setting_params) | |||||
| if @edu_setting.save | |||||
| redirect_to admins_edu_settings_path | |||||
| flash[:success] = '创建成功' | |||||
| else | |||||
| redirect_to admins_edu_settings_path | |||||
| flash[:danger] = @edu_setting.errors.full_messages.join(",") | |||||
| end | |||||
| end | |||||
| def update | |||||
| if @edu_setting.update!(edu_setting_params) | |||||
| flash[:success] = '更新成功' | |||||
| else | |||||
| flash[:danger] = @edu_setting.errors.full_messages.join(",") | |||||
| end | |||||
| redirect_to admins_edu_settings_path | |||||
| end | |||||
| def destroy | |||||
| if @edu_setting.destroy! | |||||
| flash[:success] = '删除成功' | |||||
| else | |||||
| lash[:danger] = '删除失败' | |||||
| end | |||||
| redirect_to admins_edu_settings_path | |||||
| end | |||||
| private | |||||
| def find_setting | |||||
| @edu_setting ||= EduSetting.find(params[:id]) | |||||
| end | |||||
| def edu_setting_params | |||||
| params.require(:edu_setting).permit(:name, :value, :description) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,56 @@ | |||||
| class Admins::SitesController < Admins::BaseController | |||||
| before_action :find_site, only: [:edit,:update, :destroy] | |||||
| def index | |||||
| default_sort('id', 'desc') | |||||
| sites = Admins::SiteQuery.call(params) | |||||
| @sites = paginate sites | |||||
| end | |||||
| def new | |||||
| @site = Site.new | |||||
| end | |||||
| def edit | |||||
| end | |||||
| def create | |||||
| @site = Site.new(site_params) | |||||
| if @site.save | |||||
| redirect_to admins_sites_path | |||||
| flash[:success] = '创建成功' | |||||
| else | |||||
| redirect_to admins_sites_path | |||||
| flash[:danger] = @site.errors.full_messages.join(",") | |||||
| end | |||||
| end | |||||
| def update | |||||
| if @site.update!(site_params) | |||||
| flash[:success] = '更新成功' | |||||
| else | |||||
| flash[:danger] = @site.errors.full_messages.join(",") | |||||
| end | |||||
| redirect_to admins_sites_path | |||||
| end | |||||
| def destroy | |||||
| if @site.destroy! | |||||
| flash[:success] = '删除成功' | |||||
| else | |||||
| lash[:danger] = '删除失败' | |||||
| end | |||||
| redirect_to admins_sites_path | |||||
| end | |||||
| private | |||||
| def find_site | |||||
| @site ||= Site.find(params[:id]) | |||||
| end | |||||
| def site_params | |||||
| params.require(:site).permit(:name, :url, :key, :site_type) | |||||
| end | |||||
| end | |||||
| @@ -41,7 +41,7 @@ module LaboratoryHelper | |||||
| my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist", | my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist", | ||||
| my_projects: "/users/#{current_user.try(:login)}/projects", | my_projects: "/users/#{current_user.try(:login)}/projects", | ||||
| my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations", | my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations", | ||||
| default_url: "https://www.trustie.net/", | |||||
| default_url: Rails.application.config_for(:configuration)['platform_url'], | |||||
| tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages", | tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages", | ||||
| register_url: "https://www.trustie.net/login?login=false" | register_url: "https://www.trustie.net/login?login=false" | ||||
| } | } | ||||
| @@ -29,10 +29,8 @@ class EduSettingsController < ApplicationController | |||||
| respond_to do |format| | respond_to do |format| | ||||
| if @edu_setting.save | if @edu_setting.save | ||||
| format.html { redirect_to @edu_setting, notice: 'Edu setting was successfully created.' } | |||||
| format.json { render :show, status: :created, location: @edu_setting } | format.json { render :show, status: :created, location: @edu_setting } | ||||
| else | else | ||||
| format.html { render :new } | |||||
| format.json { render json: @edu_setting.errors, status: :unprocessable_entity } | format.json { render json: @edu_setting.errors, status: :unprocessable_entity } | ||||
| end | end | ||||
| end | end | ||||
| @@ -43,10 +41,8 @@ class EduSettingsController < ApplicationController | |||||
| def update | def update | ||||
| respond_to do |format| | respond_to do |format| | ||||
| if @edu_setting.update(edu_setting_params) | if @edu_setting.update(edu_setting_params) | ||||
| format.html { redirect_to @edu_setting, notice: 'Edu setting was successfully updated.' } | |||||
| format.json { render :show, status: :ok, location: @edu_setting } | format.json { render :show, status: :ok, location: @edu_setting } | ||||
| else | else | ||||
| format.html { render :edit } | |||||
| format.json { render json: @edu_setting.errors, status: :unprocessable_entity } | format.json { render json: @edu_setting.errors, status: :unprocessable_entity } | ||||
| end | end | ||||
| end | end | ||||
| @@ -57,7 +53,6 @@ class EduSettingsController < ApplicationController | |||||
| def destroy | def destroy | ||||
| @edu_setting.destroy | @edu_setting.destroy | ||||
| respond_to do |format| | respond_to do |format| | ||||
| format.html { redirect_to edu_settings_url, notice: 'Edu setting was successfully destroyed.' } | |||||
| format.json { head :no_content } | format.json { head :no_content } | ||||
| end | end | ||||
| end | end | ||||
| @@ -46,7 +46,6 @@ class ProjectsController < ApplicationController | |||||
| def create | def create | ||||
| ActiveRecord::Base.transaction do | ActiveRecord::Base.transaction do | ||||
| tip_exception("无法使用以下关键词:#{project_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(project_params[:repository_name]).present? | |||||
| Projects::CreateForm.new(project_params).validate! | Projects::CreateForm.new(project_params).validate! | ||||
| @project = Projects::CreateService.new(current_user, project_params).call | @project = Projects::CreateService.new(current_user, project_params).call | ||||
| @@ -57,7 +56,6 @@ class ProjectsController < ApplicationController | |||||
| end | end | ||||
| def migrate | def migrate | ||||
| tip_exception("无法使用以下关键词:#{mirror_params[:repository_name]},请重新命名") if ReversedKeyword.is_reversed(mirror_params[:repository_name]).present? | |||||
| Projects::MigrateForm.new(mirror_params).validate! | Projects::MigrateForm.new(mirror_params).validate! | ||||
| @project = | @project = | ||||
| @@ -2,18 +2,24 @@ class BaseForm | |||||
| include ActiveModel::Model | include ActiveModel::Model | ||||
| def check_project_category(project_category_id) | def check_project_category(project_category_id) | ||||
| raise "project_category_id参数值无效." if (ProjectCategory.find_by_id project_category_id).blank? | |||||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||||
| end | end | ||||
| def check_project_language(project_language_id) | def check_project_language(project_language_id) | ||||
| raise "project_language_id参数值无效." if (ProjectLanguage.find_by_id project_language_id).blank? | |||||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||||
| end | end | ||||
| def check_repository_name(user_id, repository_name) | def check_repository_name(user_id, repository_name) | ||||
| raise "仓库名称已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists? | |||||
| check_reversed_keyword(repository_name) | |||||
| raise "项目标识已被使用." if Repository.where(user_id: user_id, identifier: repository_name.strip).exists? | |||||
| end | end | ||||
| def check_project_name(user_id, project_name) | def check_project_name(user_id, project_name) | ||||
| raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists? | raise "项目名称已被使用." if Project.where(user_id: user_id, name: project_name.strip).exists? | ||||
| end | end | ||||
| def check_reversed_keyword(repository_name) | |||||
| raise "项目标识已被占用." if ReversedKeyword.is_reversed(repository_name).exists? | |||||
| end | |||||
| end | end | ||||
| @@ -1,11 +1,9 @@ | |||||
| class Projects::CreateForm < BaseForm | class Projects::CreateForm < BaseForm | ||||
| REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 | |||||
| attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, | attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, | ||||
| :project_language_id, :ignore_id, :license_id, :private, :owner | :project_language_id, :ignore_id, :license_id, :private, :owner | ||||
| validates :user_id, :name, :description,:repository_name, | |||||
| :project_category_id, :project_language_id, presence: true | |||||
| validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :user_id, :name, :repository_name, presence: true | |||||
| validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :name, length: { maximum: 50 } | validates :name, length: { maximum: 50 } | ||||
| validates :repository_name, length: { maximum: 100 } | validates :repository_name, length: { maximum: 100 } | ||||
| @@ -1,12 +1,13 @@ | |||||
| class Projects::MigrateForm < BaseForm | class Projects::MigrateForm < BaseForm | ||||
| REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 | |||||
| URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i | |||||
| attr_accessor :user_id, :name, :repository_name, :project_category_id, :description, | |||||
| :project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner | |||||
| attr_accessor :user_id, :name, :description, :repository_name, :project_category_id, :project_language_id, :clone_addr, :private, :is_mirror, :auth_username, :auth_password, :owner | |||||
| validates :user_id, :name, :description,:repository_name, :project_category_id, :project_language_id, presence: true | |||||
| validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :clone_addr, format: { with: URL_REGEX, multiline: true, message: "地址格式不正确" } | |||||
| validates :user_id, :name, :repository_name, :clone_addr, presence: true | |||||
| validates :repository_name, format: { with: CustomRegexp::REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" } | |||||
| validates :clone_addr, format: { with: CustomRegexp::URL_REGEX, multiline: true, message: "地址格式不正确" } | |||||
| validates :name, length: { maximum: 50 } | |||||
| validates :repository_name, length: { maximum: 100 } | |||||
| validates :description, length: { maximum: 200 } | |||||
| validate do | validate do | ||||
| check_project_name(user_id, name) unless name.blank? | check_project_name(user_id, name) unless name.blank? | ||||
| check_repository_name(user_id, repository_name) unless repository_name.blank? | check_repository_name(user_id, repository_name) unless repository_name.blank? | ||||
| @@ -6,4 +6,8 @@ module CustomRegexp | |||||
| PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ | PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/ | ||||
| URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/ | URL = /\Ahttps?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]\z/ | ||||
| IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ | IP = /^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/ | ||||
| URL_REGEX = /\A(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?\z/i | |||||
| REPOSITORY_NAME_REGEX = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾 | |||||
| end | end | ||||
| @@ -24,4 +24,12 @@ class ApplicationRecord < ActiveRecord::Base | |||||
| def reset_platform_cache_async_job | def reset_platform_cache_async_job | ||||
| ResetPlatformCacheJob.perform_later | ResetPlatformCacheJob.perform_later | ||||
| end | end | ||||
| def self.strip_param(key) | |||||
| key.to_s.strip.presence | |||||
| end | |||||
| def strip_param(key) | |||||
| key.to_s.strip.presence | |||||
| end | |||||
| end | end | ||||
| @@ -1,22 +1,24 @@ | |||||
| # == Schema Information | |||||
| # | |||||
| # Table name: edu_settings | |||||
| # | |||||
| # id :integer not null, primary key | |||||
| # name :string(255) | |||||
| # value :string(255) | |||||
| # created_at :datetime not null | |||||
| # updated_at :datetime not null | |||||
| # description :string(255) | |||||
| # | |||||
| # Indexes | |||||
| # | |||||
| # index_edu_settings_on_name (name) UNIQUE | |||||
| # | |||||
| # == Schema Information | |||||
| # | |||||
| # Table name: edu_settings | |||||
| # | |||||
| # id :integer not null, primary key | |||||
| # name :string(255) | |||||
| # value :string(255) | |||||
| # created_at :datetime not null | |||||
| # updated_at :datetime not null | |||||
| # description :string(255) | |||||
| # | |||||
| # Indexes | |||||
| # | |||||
| # index_edu_settings_on_name (name) UNIQUE | |||||
| # | |||||
| class EduSetting < ApplicationRecord | class EduSetting < ApplicationRecord | ||||
| after_commit :expire_value_cache | after_commit :expire_value_cache | ||||
| scope :by_search, -> (keyword){ where("name LIKE :keyword OR value LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? } | |||||
| def value_cache_key | def value_cache_key | ||||
| self.class.value_cache_key(name) | self.class.value_cache_key(name) | ||||
| end | end | ||||
| @@ -17,6 +17,9 @@ class Site < ApplicationRecord | |||||
| # common: 普通链接 | # common: 普通链接 | ||||
| enum site_type: { add: 0, personal: 1, common: 2 } | enum site_type: { add: 0, personal: 1, common: 2 } | ||||
| scope :by_search, -> (keyword){ where("name LIKE :keyword OR url LIKE :keyword", keyword: "%#{strip_param(keyword)}%") unless strip_param(keyword).blank? } | |||||
| scope :by_site_type, -> (site_type){ where(site_type: strip_param(site_type)) unless strip_param(site_type).blank? } | |||||
| def self.set_default_menu | def self.set_default_menu | ||||
| set_add_menu! | set_add_menu! | ||||
| set_personal_menu! | set_personal_menu! | ||||
| @@ -26,8 +29,8 @@ class Site < ApplicationRecord | |||||
| private | private | ||||
| def self.set_add_menu! | def self.set_add_menu! | ||||
| adds= [ | adds= [ | ||||
| {name: '新建镜像项目', key: 'add_mirror_project', url: '/projects/mirror/new'}, | |||||
| {name: '新建托管项目', key: 'add_common', url: '/projects/deposit/new'}, | |||||
| {name: '新建项目', key: 'add_mirror_project', url: '/projects/mirror/new'}, | |||||
| {name: '导入项目', key: 'add_common', url: '/projects/deposit/new'}, | |||||
| {name: '新建组织', key: 'add_r', url: '/organize/new'}] | {name: '新建组织', key: 'add_r', url: '/organize/new'}] | ||||
| adds.each { |ele| | adds.each { |ele| | ||||
| @@ -0,0 +1,28 @@ | |||||
| class Admins::EduSettingQuery < ApplicationQuery | |||||
| include CustomSortable | |||||
| attr_reader :params | |||||
| sort_columns :id, default_by: :id, default_direction: :desc | |||||
| def initialize(params) | |||||
| @params = params | |||||
| end | |||||
| def call | |||||
| collection = EduSetting.all | |||||
| collection = filter_settings(collection) | |||||
| custom_sort collection, params[:sort_by], params[:sort_direction] | |||||
| end | |||||
| def filter_settings(collection) | |||||
| by_search(collection) | |||||
| end | |||||
| def by_search(collection) | |||||
| keyword = strip_param(:search) | |||||
| collection.by_search(keyword) | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,35 @@ | |||||
| class Admins::SiteQuery < ApplicationQuery | |||||
| include CustomSortable | |||||
| attr_reader :params | |||||
| sort_columns :id, default_by: :id, default_direction: :desc | |||||
| def initialize(params) | |||||
| @params = params | |||||
| end | |||||
| def call | |||||
| collection = Site.all | |||||
| collection = filter_sites(collection) | |||||
| custom_sort collection, params[:sort_by], params[:sort_direction] | |||||
| end | |||||
| def filter_sites(collection) | |||||
| collection = by_search(collection) | |||||
| collection = by_stie_type(collection) | |||||
| collection | |||||
| end | |||||
| def by_search(collection) | |||||
| keyword = strip_param(:search) | |||||
| collection.by_search(keyword) | |||||
| end | |||||
| def by_stie_type(collection) | |||||
| site_type = strip_param(:site_type) | |||||
| collection.by_site_type(site_type) | |||||
| end | |||||
| end | |||||
| @@ -15,8 +15,8 @@ class Gitea::Organization::Repository::CreateService < Gitea::ClientService | |||||
| private | private | ||||
| def request_params | def request_params | ||||
| create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: create_params) | |||||
| # create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: params) | |||||
| end | end | ||||
| def url | def url | ||||
| @@ -25,8 +25,8 @@ class Gitea::Repository::CreateService < Gitea::ClientService | |||||
| private | private | ||||
| def request_params | def request_params | ||||
| create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: create_params) | |||||
| # create_params = params.merge(readme: "readme") | |||||
| Hash.new.merge(token: token, data: params) | |||||
| end | end | ||||
| def url | def url | ||||
| @@ -43,7 +43,7 @@ class Projects::CreateService < ApplicationService | |||||
| ignore_id: params[:ignore_id], | ignore_id: params[:ignore_id], | ||||
| license_id: params[:license_id], | license_id: params[:license_id], | ||||
| website: params[:website], | website: params[:website], | ||||
| identifier: params[:repository_name] #新增,hs | |||||
| identifier: params[:repository_name] | |||||
| } | } | ||||
| end | end | ||||
| @@ -32,7 +32,7 @@ class Repositories::MigrateService < ApplicationService | |||||
| private: params[:hidden], | private: params[:hidden], | ||||
| mirror: wrapper_mirror || false, | mirror: wrapper_mirror || false, | ||||
| auth_username: params[:login], | auth_username: params[:login], | ||||
| auth_password: Base64.decode64(params[:password]) | |||||
| auth_password: Base64.decode64(params[:password] || "") | |||||
| } | } | ||||
| end | end | ||||
| @@ -0,0 +1,38 @@ | |||||
| <div class="modal fade edu_setting-change-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"><%= type == "create" ? "新增" : "编辑" %></h5> | |||||
| <button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |||||
| <span aria-hidden="true">×</span> | |||||
| </button> | |||||
| </div> | |||||
| <%= form_for @edu_setting, url: {controller: "edu_settings", action: "#{type}"} do |p| %> | |||||
| <div class="modal-body"> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 变量名 <span class="ml10 color-orange mr20">*</span> | |||||
| </label> | |||||
| <%= p.text_field :name, class: "form-control input-lg",required: true%> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 变量值 <span class="ml10 color-orange mr20">*</span> | |||||
| </label> | |||||
| <%= p.text_field :value, class: "form-control input-lg",required: true%> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 备注说明 | |||||
| </label> | |||||
| <%= p.text_area :description, class: "form-control", placeholder: ""%> | |||||
| </div> | |||||
| </div> | |||||
| <div class="modal-footer"> | |||||
| <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> | |||||
| <%= p.submit "确认", class: "btn btn-primary submit-btn" %> | |||||
| </div> | |||||
| <% end %> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| @@ -0,0 +1,36 @@ | |||||
| <table class="table table-hover text-center subject-list-table"> | |||||
| <thead class="thead-light"> | |||||
| <tr> | |||||
| <th width="5%">序号</th> | |||||
| <th width="15%">变量名</th> | |||||
| <th width="35%">变量值</th> | |||||
| <th width="20%">备注说明</th> | |||||
| <th width="10%"><%= sort_tag('创建时间', name: 'created_at', path: admins_edu_settings_path) %></th> | |||||
| <th width="10%">操作</th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| <% if edu_settings.present? %> | |||||
| <% edu_settings.each_with_index do |edu_setting, index| %> | |||||
| <tr class="edu_setting-item-<%= edu_setting.id %>"> | |||||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | |||||
| <td> | |||||
| <%= edu_setting.name %> | |||||
| </td> | |||||
| <td><%= edu_setting.value %></td> | |||||
| <td><%= overflow_hidden_span display_text(edu_setting.description), width: 200 %></td> | |||||
| <td><%= edu_setting.created_at&.strftime('%Y-%m-%d %H:%M') %></td> | |||||
| <td class="action-container"> | |||||
| <%= link_to "编辑", edit_admins_edu_setting_path(edu_setting), remote: true, class: "action" %> | |||||
| <%= link_to "删除", admins_edu_setting_path(edu_setting), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> | |||||
| </td> | |||||
| </tr> | |||||
| <% end %> | |||||
| <% else %> | |||||
| <%= render 'admins/shared/no_data_for_table' %> | |||||
| <% end %> | |||||
| </tbody> | |||||
| </table> | |||||
| <%= render partial: 'admins/shared/paginate', locals: { objects: edu_settings } %> | |||||
| @@ -0,0 +1,2 @@ | |||||
| $("#edu_setting-modals").html("<%= j render(partial: 'admins/edu_settings/form', locals: {type: 'update'}) %>") | |||||
| $(".edu_setting-change-modal").modal('show'); | |||||
| @@ -0,0 +1,22 @@ | |||||
| <% define_admin_breadcrumbs do %> | |||||
| <% add_admin_breadcrumb('全局变量配置') %> | |||||
| <% end %> | |||||
| <div class="box search-form-container edu_settings-list-form"> | |||||
| <%= form_tag(admins_edu_settings_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> | |||||
| <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '关键字检索') %> | |||||
| <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | |||||
| <input type="reset" class="btn btn-secondary clear-btn" value="清空"/> | |||||
| <% end %> | |||||
| <%= link_to "新增", new_admins_edu_setting_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> | |||||
| </div> | |||||
| <div class="box py-0 pt-4 pl-4 daily-school-statistic-title"> | |||||
| 说明:该界面适用于存储全局变量. | |||||
| </div> | |||||
| <div class="box admin-list-container edu_settings-list-container"> | |||||
| <%= render partial: 'admins/edu_settings/list', locals: { edu_settings: @edu_settings } %> | |||||
| </div> | |||||
| <div id="edu_setting-modals"> | |||||
| </div> | |||||
| @@ -0,0 +1 @@ | |||||
| $('.edu_settings-list-container').html("<%= j( render partial: 'admins/edu_settings/list', locals: { edu_settings: @edu_settings } ) %>"); | |||||
| @@ -0,0 +1,2 @@ | |||||
| $("#edu_setting-modals").html("<%= j render(partial: 'admins/edu_settings/form', locals: {type: 'create'}) %>") | |||||
| $(".edu_setting-change-modal").modal('show'); | |||||
| @@ -4,7 +4,7 @@ | |||||
| <div class="box search-form-container laboratory-list-form"> | <div class="box search-form-container laboratory-list-form"> | ||||
| <%= form_tag(admins_laboratories_path(unsafe_params), method: :get, class: 'form-inline search-form flex-1', remote: true) do %> | <%= form_tag(admins_laboratories_path(unsafe_params), method: :get, class: 'form-inline search-form flex-1', remote: true) do %> | ||||
| <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-6 col-md-4 ml-3', placeholder: '学校名称/二级域名前缀检索') %> | |||||
| <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-6 col-md-4 ml-3', placeholder: '单位名称/二级域名前缀检索') %> | |||||
| <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | ||||
| <% end %> | <% end %> | ||||
| @@ -1,6 +1,6 @@ | |||||
| <% school = laboratory&.school %> | <% school = laboratory&.school %> | ||||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | ||||
| <td class="text-left"><%= school&.name || 'Trustie主站' %></td> | |||||
| <td class="text-left"><%= school&.name || '主站' %></td> | |||||
| <td class="text-left"> | <td class="text-left"> | ||||
| <% if laboratory.identifier %> | <% if laboratory.identifier %> | ||||
| <%= link_to laboratory.site, "https://#{laboratory.site}", target: '_blank' %> | <%= link_to laboratory.site, "https://#{laboratory.site}", target: '_blank' %> | ||||
| @@ -29,40 +29,10 @@ | |||||
| </div> | </div> | ||||
| </td> | </td> | ||||
| <td><%= laboratory.created_at.strftime('%Y-%m-%d %H:%M') %></td> | <td><%= laboratory.created_at.strftime('%Y-%m-%d %H:%M') %></td> | ||||
| <td> | |||||
| <% if school.present? && laboratory.id != 1 %> | |||||
| <%= check_box_tag :sync_course,!laboratory.sync_course,laboratory.sync_course,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> | |||||
| <% end %> | |||||
| </td> | |||||
| <td> | |||||
| <% if school.present? && laboratory.id != 1 %> | |||||
| <%= check_box_tag :sync_subject,!laboratory.sync_subject,laboratory.sync_subject,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> | |||||
| <% end %> | |||||
| </td> | |||||
| <td> | |||||
| <% if school.present? && laboratory.id != 1 %> | |||||
| <%= check_box_tag :sync_shixun,!laboratory.sync_shixun,laboratory.sync_shixun,remote:true,data:{id:laboratory.id},class:"laboratory-sync-form" %> | |||||
| <% end %> | |||||
| </td> | |||||
| <td class="action-container"> | <td class="action-container"> | ||||
| <%= link_to '定制', admins_laboratory_laboratory_setting_path(laboratory), class: 'action' %> | |||||
| <%= link_to '设置', admins_laboratory_laboratory_setting_path(laboratory), class: 'action' %> | |||||
| <% if school.present? && laboratory.id != 1 %> | <% if school.present? && laboratory.id != 1 %> | ||||
| <%= javascript_void_link '添加管理员', class: 'action', data: { laboratory_id: laboratory.id, toggle: 'modal', target: '.admin-add-laboratory-user-modal' } %> | |||||
| <%= link_to '同步用户', synchronize_user_admins_laboratory_path(laboratory), remote: true, data: { confirm: '确认同步该单位下的所有用户到云上实验室吗?' }, class: 'action' %> | |||||
| <% end %> | |||||
| <div class="d-inline"> | |||||
| <%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %> | |||||
| <div class="dropdown-menu more-action-dropdown"> | |||||
| <%= link_to '轮播图', admins_laboratory_carousels_path(laboratory), class: 'dropdown-item' %> | |||||
| <%= link_to '查看实训项目', admins_laboratory_laboratory_shixuns_path(laboratory), class: 'dropdown-item' %> | |||||
| <%= link_to '查看实践课程', admins_laboratory_laboratory_subjects_path(laboratory), class: 'dropdown-item' %> | |||||
| <% if school.present? && laboratory.id != 1 %> | |||||
| <%= delete_link '删除', admins_laboratory_path(laboratory, element: ".laboratory-item-#{laboratory.id}"), class: 'dropdown-item delete-laboratory-action' %> | |||||
| <% end %> | |||||
| </div> | |||||
| </div> | |||||
| <%= delete_link '删除', admins_laboratory_path(laboratory, element: ".laboratory-item-#{laboratory.id}"), class: 'action' %> | |||||
| <% end %> | |||||
| </td> | </td> | ||||
| @@ -7,9 +7,6 @@ | |||||
| <th width="6%">统计链接</th> | <th width="6%">统计链接</th> | ||||
| <th width="22%">管理员</th> | <th width="22%">管理员</th> | ||||
| <th width="10%"><%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %></th> | <th width="10%"><%= sort_tag('创建时间', name: 'id', path: admins_laboratories_path) %></th> | ||||
| <th width="4%" title="同步显示主站下该单位的课堂">同步课堂</th> | |||||
| <th width="4%" title="同步显示主站下该单位用户创建的实践课程">同步实践课程</th> | |||||
| <th width="4%" title="同步显示主站下该单位用户创建的实训">同步实训</th> | |||||
| <th width="16%">操作</th> | <th width="16%">操作</th> | ||||
| </tr> | </tr> | ||||
| </thead> | </thead> | ||||
| @@ -86,7 +86,9 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="form-group px-2 setting-item"> | |||||
| <% | |||||
| =begin%> | |||||
| <div class="form-group px-2 setting-item"> | |||||
| <div class="setting-item-head"><h6>Banner设置</h6></div> | <div class="setting-item-head"><h6>Banner设置</h6></div> | ||||
| <div class="dropdown-divider"></div> | <div class="dropdown-divider"></div> | ||||
| <div class="pl-0 py-3 row setting-item-body"> | <div class="pl-0 py-3 row setting-item-body"> | ||||
| @@ -140,7 +142,9 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | |||||
| </div> | |||||
| <% | |||||
| =end%> | |||||
| <div class="form-group px-2 setting-item"> | <div class="form-group px-2 setting-item"> | ||||
| <div class="setting-item-head"> | <div class="setting-item-head"> | ||||
| @@ -11,6 +11,10 @@ | |||||
| <%= link_to "新增", new_admins_reversed_keyword_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> | <%= link_to "新增", new_admins_reversed_keyword_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> | ||||
| </div> | </div> | ||||
| <div class="box py-0 pt-4 pl-4 daily-school-statistic-title"> | |||||
| 旨在为特殊用户群体、特殊场景、路由而保留的关键词,如:Gitlink、Trustie等;目前主要在用户注册、创建组织、创建项目等场景下做关键词的验证. | |||||
| </div> | |||||
| <div class="box admin-list-container reversed-keyword-list-container"> | <div class="box admin-list-container reversed-keyword-list-container"> | ||||
| <%= render partial: 'admins/reversed_keywords/list', locals: { keywords: @keywords } %> | <%= render partial: 'admins/reversed_keywords/list', locals: { keywords: @keywords } %> | ||||
| </div> | </div> | ||||
| @@ -26,10 +26,11 @@ | |||||
| <li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories') %></li> | <li><%= sidebar_item(admins_project_categories_path, '分类列表', icon: 'sitemap', controller: 'admins-project_categories') %></li> | ||||
| <li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses') %></li> | <li><%= sidebar_item(admins_project_licenses_path, '开源许可证', icon: 'file-text-o', controller: 'admins-project_licenses') %></li> | ||||
| <li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li> | <li><%= sidebar_item(admins_project_ignores_path, '忽略文件', icon: 'git', controller: 'admins-project_ignores') %></li> | ||||
| <li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li> | |||||
| <% end %> | <% end %> | ||||
| </li> | </li> | ||||
| <li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li> | |||||
| <li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li> | <li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li> | ||||
| <li> | <li> | ||||
| @@ -42,6 +43,12 @@ | |||||
| <li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li> | <li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li> | ||||
| <% end %> | <% end %> | ||||
| </li> | </li> | ||||
| <li> | |||||
| <%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %> | |||||
| <li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li> | |||||
| <li><%= sidebar_item(admins_edu_settings_path, '全局变量配置', icon: 'pencil-square', controller: 'admins-edu_settings') %></li> | |||||
| <% end %> | |||||
| </li> | |||||
| <li> | <li> | ||||
| <%= sidebar_item('/admins/sidekiq', '定时任务', icon: 'bell', controller: 'root') %> | <%= sidebar_item('/admins/sidekiq', '定时任务', icon: 'bell', controller: 'root') %> | ||||
| </li> | </li> | ||||
| @@ -0,0 +1,42 @@ | |||||
| <div class="modal fade site-change-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"><%= type == "create" ? "新增" : "编辑" %></h5> | |||||
| <button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |||||
| <span aria-hidden="true">×</span> | |||||
| </button> | |||||
| </div> | |||||
| <%= form_for @site, url: {controller: "sites", action: "#{type}"} do |p| %> | |||||
| <div class="modal-body"> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 名称 <span class="ml10 color-orange mr20">*</span> | |||||
| </label> | |||||
| <%= p.text_field :name, class: "form-control input-lg",required: true%> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 路由 <span class="ml10 color-orange mr20">*</span> | |||||
| </label> | |||||
| <%= p.text_field :url, class: "form-control input-lg",required: true%> | |||||
| </div> | |||||
| <div class="form-group"> | |||||
| <label> | |||||
| 标识 <span class="ml10 color-orange mr20">*</span> | |||||
| </label> | |||||
| <%= p.text_field :key, class: "form-control input-lg",required: true%> | |||||
| </div> | |||||
| <div class="form-group "> | |||||
| <label for="status">类型:</label> | |||||
| <%= p.select :site_type, options_for_select(Site.site_types.map { |key, value| [key.humanize, key] }), {}, class: "form-control" %> | |||||
| </div> | |||||
| </div> | |||||
| <div class="modal-footer"> | |||||
| <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> | |||||
| <%= p.submit "确认", class: "btn btn-primary submit-btn" %> | |||||
| </div> | |||||
| <% end %> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| @@ -0,0 +1,38 @@ | |||||
| <table class="table table-hover text-center subject-list-table"> | |||||
| <thead class="thead-light"> | |||||
| <tr> | |||||
| <th width="5%">序号</th> | |||||
| <th width="15%">名称</th> | |||||
| <th width="30%">路由</th> | |||||
| <th width="20%">标识</th> | |||||
| <th width="10%">类型</th> | |||||
| <th width="20%"><%= sort_tag('创建时间', name: 'created_at', path: admins_sites_path) %></th> | |||||
| <th width="25%">操作</th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| <% if sites.present? %> | |||||
| <% sites.each_with_index do |site, index| %> | |||||
| <tr class="site-item-<%= site.id %>"> | |||||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | |||||
| <td> | |||||
| <%= overflow_hidden_span display_text(site.name), width: 150 %> | |||||
| </td> | |||||
| <td><%= site.url %></td> | |||||
| <td><%= overflow_hidden_span display_text(site.key), width: 150 %></td> | |||||
| <td><%= site.site_type.humanize %></td> | |||||
| <td><%= site.created_at&.strftime('%Y-%m-%d %H:%M') %></td> | |||||
| <td class="action-container"> | |||||
| <%= link_to "编辑", edit_admins_site_path(site), remote: true, class: "action" %> | |||||
| <%= link_to "删除", admins_site_path(site), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %> | |||||
| </td> | |||||
| </tr> | |||||
| <% end %> | |||||
| <% else %> | |||||
| <%= render 'admins/shared/no_data_for_table' %> | |||||
| <% end %> | |||||
| </tbody> | |||||
| </table> | |||||
| <%= render partial: 'admins/shared/paginate', locals: { objects: sites } %> | |||||
| @@ -0,0 +1,2 @@ | |||||
| $("#site-modals").html("<%= j render(partial: 'admins/sites/form', locals: {type: 'update'}) %>") | |||||
| $(".site-change-modal").modal('show'); | |||||
| @@ -0,0 +1,24 @@ | |||||
| <% define_admin_breadcrumbs do %> | |||||
| <% add_admin_breadcrumb('Setting接口配置') %> | |||||
| <% end %> | |||||
| <div class="box search-form-container sites-list-form"> | |||||
| <%= form_tag(admins_sites_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %> | |||||
| <div class="form-group mr-2"> | |||||
| <label for="status">类型:</label> | |||||
| <% type_options = [['全部', ''], ['Add', Site.site_types[:add]], ['Personal', Site.site_types[:personal]], ['Common', Site.site_types[:common]]] %> | |||||
| <%= select_tag(:site_type, options_for_select(type_options), class: 'form-control') %> | |||||
| </div> | |||||
| <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '关键字检索') %> | |||||
| <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | |||||
| <input type="reset" class="btn btn-secondary clear-btn" value="清空"/> | |||||
| <% end %> | |||||
| <%= link_to "新增", new_admins_site_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %> | |||||
| </div> | |||||
| <div class="box admin-list-container sites-list-container"> | |||||
| <%= render partial: 'admins/sites/list', locals: { sites: @sites } %> | |||||
| </div> | |||||
| <div id="site-modals"> | |||||
| </div> | |||||
| @@ -0,0 +1 @@ | |||||
| $('.sites-list-container').html("<%= j( render partial: 'admins/sites/list', locals: { sites: @sites } ) %>"); | |||||
| @@ -0,0 +1,2 @@ | |||||
| $("#site-modals").html("<%= j render(partial: 'admins/sites/form', locals: {type: 'create'}) %>") | |||||
| $(".site-change-modal").modal('show'); | |||||
| @@ -1,27 +0,0 @@ | |||||
| <%= form_with(model: edu_setting, local: true) do |form| %> | |||||
| <% if edu_setting.errors.any? %> | |||||
| <div id="error_explanation"> | |||||
| <h2><%= pluralize(edu_setting.errors.count, "error") %> prohibited this edu_setting from being saved:</h2> | |||||
| <ul> | |||||
| <% edu_setting.errors.full_messages.each do |message| %> | |||||
| <li><%= message %></li> | |||||
| <% end %> | |||||
| </ul> | |||||
| </div> | |||||
| <% end %> | |||||
| <div class="field"> | |||||
| <%= form.label :name %> | |||||
| <%= form.text_field :name %> | |||||
| </div> | |||||
| <div class="field"> | |||||
| <%= form.label :value %> | |||||
| <%= form.text_field :value %> | |||||
| </div> | |||||
| <div class="actions"> | |||||
| <%= form.submit %> | |||||
| </div> | |||||
| <% end %> | |||||
| @@ -1,6 +0,0 @@ | |||||
| <h1>Editing Edu Setting</h1> | |||||
| <%= render 'form', edu_setting: @edu_setting %> | |||||
| <%= link_to 'Show', @edu_setting %> | | |||||
| <%= link_to 'Back', edu_settings_path %> | |||||
| @@ -1,30 +0,0 @@ | |||||
| <p id="notice"><%= notice %></p> | |||||
| <h1>EduCoder公共配置</h1> | |||||
| <p>说明:该界面适用于存储全局变量</p> | |||||
| <table> | |||||
| <thead> | |||||
| <tr> | |||||
| <th>变量名</th> | |||||
| <th>变量值</th> | |||||
| <th colspan="3"></th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| <% @edu_settings.each do |edu_setting| %> | |||||
| <tr> | |||||
| <td><%= edu_setting.name %></td> | |||||
| <td><%= edu_setting.value %></td> | |||||
| <td><%= link_to 'Show', edu_setting %></td> | |||||
| <td><%= link_to 'Edit', edit_edu_setting_path(edu_setting) %></td> | |||||
| <td><%= link_to 'Destroy', edu_setting, method: :delete, data: { confirm: 'Are you sure?' } %></td> | |||||
| </tr> | |||||
| <% end %> | |||||
| </tbody> | |||||
| </table> | |||||
| <br> | |||||
| <%= link_to 'New Edu Setting', new_edu_setting_path %> | |||||
| @@ -1,5 +0,0 @@ | |||||
| <h1>New Edu Setting</h1> | |||||
| <%= render 'form', edu_setting: @edu_setting %> | |||||
| <%= link_to 'Back', edu_settings_path %> | |||||
| @@ -1,14 +0,0 @@ | |||||
| <p id="notice"><%= notice %></p> | |||||
| <p> | |||||
| <strong>Name:</strong> | |||||
| <%= @edu_setting.name %> | |||||
| </p> | |||||
| <p> | |||||
| <strong>Value:</strong> | |||||
| <%= @edu_setting.value %> | |||||
| </p> | |||||
| <%= link_to 'Edit', edit_edu_setting_path(@edu_setting) %> | | |||||
| <%= link_to 'Back', edu_settings_path %> | |||||
| @@ -3,18 +3,18 @@ json.login @user.login | |||||
| json.name @user.full_name | json.name @user.full_name | ||||
| json.location @user.location | json.location @user.location | ||||
| json.image_url url_to_avatar(@user) | json.image_url url_to_avatar(@user) | ||||
| json.url "#{request.base_url }/users/#{@user.login}" | |||||
| json.url "#{request.base_url }/#{@user.login}" | |||||
| json.followers_count @user.followers_count | json.followers_count @user.followers_count | ||||
| json.followers_url "#{base_url}/users/#{@user.login}/fan_users" | |||||
| json.followers_url "#{base_url}/#{@user.login}/fan_users" | |||||
| json.following_count @user.following_count | json.following_count @user.following_count | ||||
| json.following_url "#{base_url}/users/#{@user.login}/watchers" | |||||
| json.following_url "#{base_url}/#{@user.login}/watchers" | |||||
| json.projects_count @user.projects_count | json.projects_count @user.projects_count | ||||
| json.projects_url "#{base_url}/users/#{@user.login}" | |||||
| json.projects_url "#{base_url}/#{@user.login}" | |||||
| json.projects_count @user.projects_count | json.projects_count @user.projects_count | ||||
| json.is_watch current_user&.watched?(@user) | json.is_watch current_user&.watched?(@user) | ||||
| json.organizations @user.organizations do |organization| | json.organizations @user.organizations do |organization| | ||||
| json.login organization.login | json.login organization.login | ||||
| json.name organization.real_name | json.name organization.real_name | ||||
| json.image_url url_to_avatar(organization) | json.image_url url_to_avatar(organization) | ||||
| json.url "#{base_url}/organize/#{organization.login}" | |||||
| json.url "#{base_url}/#{organization.login}" | |||||
| end | end | ||||
| @@ -651,6 +651,8 @@ Rails.application.routes.draw do | |||||
| get :visits_static | get :visits_static | ||||
| end | end | ||||
| end | end | ||||
| resources :sites | |||||
| resources :edu_settings | |||||
| resources :project_languages | resources :project_languages | ||||
| resources :project_categories | resources :project_categories | ||||
| resources :project_licenses | resources :project_licenses | ||||
| @@ -1,51 +0,0 @@ | |||||
| # 新版Git测试说明 | |||||
| 统一: | |||||
| 参考实训:http://47.96.87.25:48080/shixuns/ca9fvobr/repository | |||||
| 请求方式:POST | |||||
| 参数{repo_path: "educoder/ca9fvobr.git"} | |||||
| 公共方法: | |||||
| ['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', | |||||
| 'file_content', 'commits'] | |||||
| 1、仓库目录接口 | |||||
| 测试方法:模拟1000个用户同时去访问接口,访问方式 | |||||
| http://121.199.19.206:9000/api/file_tree | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", path: ''} // 如:{path: 'step1'} | |||||
| 2、创建版本库 | |||||
| 访问地址:http://121.199.19.206:9000/api/add_repository | |||||
| 参数: | |||||
| {repo_path: 比如:"Hjqreturn/aaass1.git"} | |||||
| 3、fork版本库 | |||||
| http://121.199.19.206:9000/api/fork_repository | |||||
| 参数: | |||||
| {repo_path: 'Hjqreturn/aaass1.git', fork_repository_path: 'educoder/ca9fvobr.git'} | |||||
| 说明:fork_repository_path是新项目的repo_path, repo_path是源项目的 | |||||
| 4、更新文件 | |||||
| 测试方法: | |||||
| 1、更新同一个文件,并发量可以不用很大,可以用同一个用户并发10-100 | |||||
| 2、更新不同的文件:可以依据创建的版本库去更新 | |||||
| 访问地址:http://121.199.19.206:9000/api/update_file | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", | |||||
| file_path: 'step1/main.py', | |||||
| message: 'commit by test', | |||||
| content: 'afdjadsjfj1111', | |||||
| author_name: 'guange', | |||||
| author_email: '8863824@gmil.com'} | |||||
| 5、获取文件内容 | |||||
| 访问地址:http://121.199.19.206:9000/api/file_content | |||||
| 参数: | |||||
| {repo_path: "educoder/ca9fvobr.git", path: 'step1/main.py',} | |||||
| 6、获取提交记录 | |||||
| 访问地址:http://121.199.19.206:9000/api/commits | |||||
| 参数: | |||||
| {repo_path: 比如:"educoder/ca9fvobr.git"} | |||||
| @@ -1,72 +0,0 @@ | |||||
| mbtclufr | |||||
| 9op3hs4j | |||||
| 96ctv7yr | |||||
| rtmzxfke | |||||
| ofqxthrf | |||||
| czu9w4gj | |||||
| 9fpzj6et | |||||
| pwhc865b | |||||
| maozpx4l | |||||
| y5wh2ofx | |||||
| b5rzhpf3 | |||||
| bs243nrl | |||||
| 47fn2yfb | |||||
| kwotfxey | |||||
| w5468sbp | |||||
| fyekprio | |||||
| q6ze5fih | |||||
| b5hjq9zm | |||||
| ky8pbqux | |||||
| 53phc7nq | |||||
| b9j2yuix | |||||
| 9t3uphwk | |||||
| iokm8ah2 | |||||
| qlsy6xb4 | |||||
| 345bqhfi | |||||
| v728fqia | |||||
| 4euftvf2 | |||||
| f23sef5m | |||||
| nhqis8m9 | |||||
| qp72tb5x | |||||
| gt3anszw | |||||
| tng6heyf | |||||
| nb9keawo | |||||
| elgnbkp9 | |||||
| 4neslomg | |||||
| lh35s6ma | |||||
| xmc4rpay | |||||
| qrpaxi6b | |||||
| 9fla2zry | |||||
| efuibzrm | |||||
| fzp3iu4w | |||||
| pligsyn8 | |||||
| glbksr29 | |||||
| kfm7ghyc | |||||
| p6hk3svf | |||||
| p539gjhm | |||||
| am5o73er | |||||
| 4x3qwrbe | |||||
| fqosyl8g | |||||
| of5z3fci | |||||
| tb7hw62n | |||||
| ie6zxg7r | |||||
| 4q2bmy9h | |||||
| fpm3u5yb | |||||
| nikx3ojt | |||||
| vt82s9bq | |||||
| ma59fefo | |||||
| lxa39tfq | |||||
| 4gnockxf | |||||
| nxwg84ey | |||||
| fmie8nzb | |||||
| w5nsr24v | |||||
| 4hn3efwc | |||||
| h9ljfbq7 | |||||
| nuv54t8b | |||||
| 2te9fmfq | |||||
| vihnsayz | |||||
| qhlyn82s | |||||
| vw74kmfr | |||||
| vcta36bz | |||||
| henz425l | |||||
| g529v38z | |||||
| @@ -0,0 +1,47 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe Admins::EduSettingsController, type: :controller do | |||||
| describe "GET #index" do | |||||
| it "returns http success" do | |||||
| get :index | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| describe "GET #new" do | |||||
| it "returns http success" do | |||||
| get :new | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| describe "GET #update" do | |||||
| it "returns http success" do | |||||
| get :update | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| describe "GET #edit" do | |||||
| it "returns http success" do | |||||
| get :edit | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| describe "GET #create" do | |||||
| it "returns http success" do | |||||
| get :create | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| describe "GET #destroy" do | |||||
| it "returns http success" do | |||||
| get :destroy | |||||
| expect(response).to have_http_status(:success) | |||||
| end | |||||
| end | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe Admins::SitesController, type: :controller do | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/create.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/destroy.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/edit.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/index.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/new.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||
| @@ -0,0 +1,5 @@ | |||||
| require 'rails_helper' | |||||
| RSpec.describe "edu_settings/update.html.erb", type: :view do | |||||
| pending "add some examples to (or delete) #{__FILE__}" | |||||
| end | |||||