| @@ -385,6 +385,17 @@ CONN_MAX_LIFETIME = 3s | |||
| ; Database maximum number of open connections, default is 0 meaning no maximum | |||
| MAX_OPEN_CONNS = 0 | |||
| [database_statistic] | |||
| DB_TYPE = postgres | |||
| HOST = 127.0.0.1:5432 | |||
| NAME = statistic | |||
| USER = | |||
| PASSWD = | |||
| SCHEMA = | |||
| SSL_MODE = disable | |||
| CHARSET = utf8 | |||
| PATH = | |||
| [indexer] | |||
| ; Issue indexer type, currently support: bleve, db or elasticsearch, default is bleve | |||
| ISSUE_INDEXER_TYPE = bleve | |||
| @@ -464,3 +464,12 @@ func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { | |||
| } | |||
| return false | |||
| } | |||
| func GetAttachmentSizeByDatasetID(datasetID int64) (int64, error) { | |||
| total, err := x.Where("dataset_id = ?", datasetID).SumInt(&Attachment{}, "size") | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| return total, nil | |||
| } | |||
| @@ -687,7 +687,7 @@ func CanDelJob(isSigned bool, user *User, job *CloudbrainInfo) bool { | |||
| return false | |||
| } | |||
| if user.ID == job.UserID || user.IsAdmin || permission.AccessMode >= AccessModeAdmin { | |||
| if (user.ID == job.UserID && permission.AccessMode >= AccessModeWrite) || user.IsAdmin || permission.AccessMode >= AccessModeAdmin { | |||
| return true | |||
| } | |||
| return false | |||
| @@ -1016,3 +1016,19 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID | |||
| }) | |||
| return err | |||
| } | |||
| func GetCommentCountByRepoID(repoID int64) (int64, error) { | |||
| //sql := fmt.Sprintf("select count(1) from comment where issue_id in (select id from issue where repo_id = %d) and type = %d;", repoID, CommentTypeComment) | |||
| //res, err := x.Query(sql) | |||
| //if err != nil { | |||
| // return 0, err | |||
| //} | |||
| //return int64(binary.BigEndian.Uint64(res[0]["count"])), nil | |||
| total, err := x.Where("issue_id in (select id from issue where repo_id = ?) and type = ?", repoID, CommentTypeComment).Count(&Comment{}) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| return total, nil | |||
| } | |||
| @@ -136,7 +136,7 @@ func init() { | |||
| ) | |||
| tablesStatistic = append(tablesStatistic, | |||
| new(FileChunk), | |||
| new(RepoStatistic), | |||
| new(UserBusinessAnalysis), | |||
| ) | |||
| @@ -0,0 +1,60 @@ | |||
| package models | |||
| import ( | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "fmt" | |||
| ) | |||
| // RepoStatistic statistic info of all repository | |||
| type RepoStatistic struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| RepoID int64 `xorm:"unique(s) NOT NULL"` | |||
| Date string `xorm:"unique(s) NOT NULL"` | |||
| NumWatches int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumStars int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumForks int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumDownloads int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumComments int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumVisits int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumVersions int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| //develop months | |||
| NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| RepoSize int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| DatasetSize int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumModels int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumCommits int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumIssues int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumPulls int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| IssueFixedRate float32 `xorm:"NOT NULL"` | |||
| NumContributor int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0"` | |||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||
| } | |||
| func DeleteRepoStatDaily(date string) error { | |||
| sess := xStatistic.NewSession() | |||
| defer sess.Close() | |||
| if err := sess.Begin(); err != nil { | |||
| return fmt.Errorf("Begin: %v", err) | |||
| } | |||
| if _, err := sess.Where("date = ?", date).Delete(&RepoStatistic{}); err != nil { | |||
| return fmt.Errorf("Delete: %v", err) | |||
| } | |||
| if err := sess.Commit(); err != nil { | |||
| sess.Close() | |||
| return fmt.Errorf("Commit: %v", err) | |||
| } | |||
| sess.Close() | |||
| return nil | |||
| } | |||
| func InsertRepoStat(repoStat *RepoStatistic) (int64, error) { | |||
| return xStatistic.Insert(repoStat) | |||
| } | |||
| @@ -55,6 +55,15 @@ type UserBusinessAnalysis struct { | |||
| //user | |||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||
| //repo | |||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //login count, from elk | |||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //openi index | |||
| OpenIIndex int `xorm:"NOT NULL DEFAULT 0"` | |||
| //user | |||
| Email string `xorm:"NOT NULL"` | |||
| @@ -100,6 +109,7 @@ func CountData(wikiCountMap map[string]int) { | |||
| } | |||
| CommitDatasetSizeMap := queryDatasetSize(start_unix, end_unix) | |||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | |||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||
| for i, userRecord := range userList { | |||
| var dateRecord UserBusinessAnalysis | |||
| @@ -176,6 +186,12 @@ func CountData(wikiCountMap map[string]int) { | |||
| dateRecord.EncyclopediasCount = wikiCountMap[dateRecord.Name] | |||
| } | |||
| if _, ok := CreateRepoCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.CreateRepoCount = 0 | |||
| } else { | |||
| dateRecord.CreateRepoCount = CreateRepoCountMap[dateRecord.ID] | |||
| } | |||
| dateRecord.CommitModelCount = 0 | |||
| statictisSess := xStatistic.NewSession() | |||
| @@ -322,6 +338,25 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||
| } | |||
| func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| sess.Select("id,owner_id,name").Table("repository").Where(" created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix)) | |||
| repoList := make([]*Repository, 0) | |||
| sess.Find(&repoList) | |||
| resultMap := make(map[int64]int) | |||
| log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | |||
| for _, repoRecord := range repoList { | |||
| if _, ok := resultMap[repoRecord.OwnerID]; !ok { | |||
| resultMap[repoRecord.OwnerID] = 1 | |||
| } else { | |||
| resultMap[repoRecord.OwnerID] += 1 | |||
| } | |||
| } | |||
| return resultMap | |||
| } | |||
| func subMonth(t1, t2 time.Time) (month int) { | |||
| y1 := t1.Year() | |||
| y2 := t2.Year() | |||
| @@ -163,6 +163,28 @@ func registerHandleBlockChainUnSuccessCommits() { | |||
| }) | |||
| } | |||
| func registerHandleRepoStatistic() { | |||
| RegisterTaskFatal("handle_repo_statistic", &BaseConfig{ | |||
| Enabled: true, | |||
| RunAtStart: false, | |||
| Schedule: "@daily", | |||
| }, func(ctx context.Context, _ *models.User, _ Config) error { | |||
| repo.RepoStatisticAuto() | |||
| return nil | |||
| }) | |||
| } | |||
| func registerHandleUserStatistic() { | |||
| RegisterTaskFatal("handle_user_statistic", &BaseConfig{ | |||
| Enabled: true, | |||
| RunAtStart: false, | |||
| Schedule: "@daily", | |||
| }, func(ctx context.Context, _ *models.User, _ Config) error { | |||
| repo.TimingCountData() | |||
| return nil | |||
| }) | |||
| } | |||
| func initBasicTasks() { | |||
| registerUpdateMirrorTask() | |||
| registerRepoHealthCheck() | |||
| @@ -177,4 +199,7 @@ func initBasicTasks() { | |||
| registerHandleBlockChainUnSuccessRepos() | |||
| registerHandleBlockChainMergedPulls() | |||
| registerHandleBlockChainUnSuccessCommits() | |||
| registerHandleRepoStatistic() | |||
| registerHandleUserStatistic() | |||
| } | |||
| @@ -23,7 +23,7 @@ var pageSize = 10; | |||
| var tableData; | |||
| var tablePageData; | |||
| var preDictTaskData; | |||
| var modelListData; | |||
| var dataSetTaskData; | |||
| var userInfoData; | |||
| @@ -35,8 +35,8 @@ console.log("repoId=" + repoId); | |||
| function setDataSetTask(){ | |||
| dataset_task_list(); | |||
| display_createdatasetlabel(0); | |||
| //dataset_task_list(); | |||
| //display_createdatasetlabel(0); | |||
| //getUser(); | |||
| //dislpayUser(); | |||
| getLabelPropertyTask(); | |||
| @@ -121,46 +121,31 @@ function countLabel(){ | |||
| } | |||
| function display_createdatasetlabel(sindex=-1){ | |||
| var html=""; | |||
| for (var i=0;i<dataSetTaskData.length;i++){ | |||
| if (i==sindex){ | |||
| var row = "<option value=\""+dataSetTaskData[i].id+ | |||
| "\" selected=\"\">"+dataSetTaskData[i].task_name+ | |||
| "</option>"; | |||
| $("#datasetlabeltaskname").attr({value:dataSetTaskData[i].task_name + "-人工标注"}); | |||
| }else{ | |||
| var row = "<option value=\""+dataSetTaskData[i].id+ | |||
| "\">"+dataSetTaskData[i].task_name+ | |||
| "</option>"; | |||
| } | |||
| html=html+row; | |||
| } | |||
| console.log(html); | |||
| document.getElementById('dataset_list').innerHTML=html; | |||
| } | |||
| function setPredictTask(){ | |||
| pre_predict_task_list(); | |||
| display_createlabel(0); | |||
| getUser(); | |||
| dislpayUser(); | |||
| getLabelPropertyTask(); | |||
| displayLabelPropertyTask(); | |||
| //dataset_task_list(); | |||
| //display_createdatasetlabel(1); | |||
| get_model_list(); | |||
| displayModelTask(); | |||
| $(".ui.predict.modal").modal("show"); | |||
| } | |||
| function pre_predict_task_list(){ | |||
| function get_model_list(){ | |||
| $.ajax({ | |||
| type:"GET", | |||
| url:ip + "/api/pre-predict-taskforLabel/", | |||
| url:ip + "/api/queryAlgModelForAutoLabel/", | |||
| headers: { | |||
| authorization:token, | |||
| }, | |||
| dataType:"json", | |||
| async:false, | |||
| success:function(json){ | |||
| preDictTaskData = json; | |||
| modelListData = json; | |||
| console.log(json); | |||
| // return json.token; | |||
| }, | |||
| @@ -170,12 +155,26 @@ function pre_predict_task_list(){ | |||
| }); | |||
| } | |||
| function sele_Change(sele){ | |||
| var predictTaskName = $('#pre_predict_task_for_label option:selected').text(); | |||
| console.log("select predictTaskName =" + predictTaskName); | |||
| $("#labeltaskname").attr({value:predictTaskName+"-人工标注"}); | |||
| function displayModelTask(){ | |||
| var html=""; | |||
| for (var i=0;i<modelListData.length;i++){ | |||
| if (i==0){ | |||
| var row = "<option value=\""+modelListData[i].id+ | |||
| "\" selected=\"\">"+modelListData[i].model_name + | |||
| "</option>"; | |||
| }else{ | |||
| var row = "<option value=\""+modelListData[i].id+ | |||
| "\">"+modelListData[i].model_name+ | |||
| "</option>"; | |||
| } | |||
| html=html+row; | |||
| } | |||
| console.log(html); | |||
| document.getElementById('model_list').innerHTML=html; | |||
| } | |||
| function sele_export_Change(sele){ | |||
| var isNeedPicture = $('#isNeedPicture option:selected').val(); | |||
| @@ -201,27 +200,13 @@ function dataset_sele_Change(sele){ | |||
| $("#datasetlabeltaskname").attr({value:dataset_listName+"-人工标注"}); | |||
| } | |||
| function display_createlabel(sindex=-1){ | |||
| var html=""; | |||
| for (var i=0;i<preDictTaskData.length;i++){ | |||
| if (i==sindex){ | |||
| var row = "<option value=\""+preDictTaskData[i].id+ | |||
| "\" selected=\"\">"+preDictTaskData[i].task_name+ | |||
| "</option>"; | |||
| $("#labeltaskname").attr({value:preDictTaskData[i].task_name + "-人工标注"}); | |||
| }else{ | |||
| var row = "<option value=\""+preDictTaskData[i].id+ | |||
| "\">"+preDictTaskData[i].task_name+ | |||
| "</option>"; | |||
| } | |||
| html=html+row; | |||
| } | |||
| console.log(html); | |||
| document.getElementById('pre_predict_task_for_label').innerHTML=html; | |||
| function dataset_auto_sele_Change(sele){ | |||
| var dataset_listName = $('#dataset_list_auto option:selected').text(); | |||
| console.log("select dataset_list_auto =" + dataset_listName); | |||
| $("#autolabeltaskname").attr({value:dataset_listName+"-自动标注"}); | |||
| } | |||
| var createsucced; | |||
| function submit_datasettask(){ | |||
| @@ -242,7 +227,7 @@ function submit_datasettask(){ | |||
| } | |||
| var labelpropertytaskid = $('#labelpropertytask_dataset option:selected').val(); | |||
| createsucced = true; | |||
| label_task_create(task_name, relate_task_id, 2,assign_user_id,labelpropertytaskid); | |||
| label_task_create(task_name, relate_task_id, 2,assign_user_id,labelpropertytaskid,-1); | |||
| if(createsucced){ | |||
| $(".ui.dataset.modal").modal("hide"); | |||
| //$("#labelDataModal").modal('hide'); | |||
| @@ -250,25 +235,30 @@ function submit_datasettask(){ | |||
| page(0,pageSize); | |||
| } | |||
| function submit_labeltask(){ | |||
| console.log($('#labeltaskname').val()); | |||
| var task_name = $('#labeltaskname').val(); | |||
| function submit_autolabeltask(){ | |||
| console.log($('#autolabeltaskname').val()); | |||
| var task_name = $('#autolabeltaskname').val(); | |||
| if (isEmpty(task_name) || task_name.length > 32){ | |||
| alert("人工标注任务名称不能为空或者不能超过32个字符。"); | |||
| alert("自动标注任务名称不能为空或者不能超过32个字符。"); | |||
| return; | |||
| } | |||
| var relate_task_id = $('#pre_predict_task_for_label option:selected').val(); | |||
| var model_id = $('#model_list option:selected').val(); | |||
| if(isEmpty(model_id)){ | |||
| alert("标注模型不能为空。"); | |||
| return; | |||
| } | |||
| var relate_task_id = $('#dataset_list_auto option:selected').val(); | |||
| if(isEmpty(relate_task_id)){ | |||
| alert("关联的自动标注任务不能为空。"); | |||
| alert("数据集对象不能为空。"); | |||
| return; | |||
| } | |||
| var assign_user_id = $('#label_assign_user option:selected').val(); | |||
| if(isEmpty(assign_user_id)){ | |||
| assign_user_id = token; | |||
| } | |||
| var labelpropertytaskid = $('#labelpropertytask_dataset option:selected').val(); | |||
| var labelpropertytaskid = $('#labelpropertytask_auto option:selected').val(); | |||
| createsucced = true; | |||
| label_task_create(task_name, relate_task_id, 1,assign_user_id,labelpropertytaskid); | |||
| label_task_create(task_name, relate_task_id, 1,assign_user_id,labelpropertytaskid,model_id); | |||
| if(createsucced){ | |||
| $("#labelModal").modal('hide'); | |||
| } | |||
| @@ -276,10 +266,10 @@ function submit_labeltask(){ | |||
| } | |||
| function label_task_create(task_name, relate_task_id, taskType,assign_user_id,labelpropertytaskid){ | |||
| function label_task_create(task_name, relate_task_id, taskType,assign_user_id,labelpropertytaskid,model_id){ | |||
| var task_flow_type = $('#task_flow_type option:selected').val(); | |||
| var task_flow_type = $('#task_flow_type option:selected').val(); | |||
| var relate_other_label_task = []; | |||
| if(task_flow_type == 2){ | |||
| @@ -309,20 +299,21 @@ function label_task_create(task_name, relate_task_id, taskType,assign_user_id,la | |||
| 'assign_user_id':assign_user_id, | |||
| 'task_flow_type':task_flow_type, | |||
| 'relate_task_id':relate_task_id,//task id | |||
| 'relate_other_label_task': relate_other_label_task_jsonstr, | |||
| 'relate_other_label_task': relate_other_label_task_jsonstr, | |||
| "taskType": taskType, | |||
| "appid": repoId, | |||
| "createUserName":userName, | |||
| "labelPropertyTaskId":labelpropertytaskid | |||
| "appid": repoId, | |||
| "createUserName":userName, | |||
| "labelPropertyTaskId":labelpropertytaskid, | |||
| "modelId":model_id | |||
| }), | |||
| success:function(res){ | |||
| console.log(res); | |||
| if(res.code == 0){ | |||
| alert("人工标注任务创建成功!"); | |||
| alert("自动标注任务创建成功!"); | |||
| createsucced = true; | |||
| } | |||
| else{ | |||
| alert("创建人工标注任务失败," + res.message); | |||
| alert("创建自动标注任务失败," + res.message); | |||
| createsucced = false; | |||
| } | |||
| }, | |||
| @@ -433,11 +424,11 @@ function delete_labeltask(){ | |||
| return; | |||
| } | |||
| var Check = $("table[id='label_task_list'] input[type=checkbox]:checked");//在table中找input下类型为checkbox属性为选中状态的数据 | |||
| Check.each(function () {//遍历 | |||
| var row = $(this).parent("td").parent("tr");//获取选中行 | |||
| var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值 | |||
| delete_labeltask_byid(id); | |||
| }); | |||
| Check.each(function () {//遍历 | |||
| var row = $(this).parent("td").parent("tr");//获取选中行 | |||
| var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值 | |||
| delete_labeltask_byid(id); | |||
| }); | |||
| page(0,pageSize); | |||
| } | |||
| @@ -480,13 +471,13 @@ function delete_labeltask_byid(label_task_id){ | |||
| function getTaskTypeDesc(task_type){ | |||
| if(task_type == 1){ | |||
| return "自动标注结果"; | |||
| return "图片-自动标注"; | |||
| }else if(task_type == 2){ | |||
| return "原始数据集-图片"; | |||
| return "图片"; | |||
| }else if(task_type == 3){ | |||
| return "原始数据集-CT影像"; | |||
| return "CT影像"; | |||
| }else if(task_type == 4){ | |||
| return "原始数据集-视频"; | |||
| return "视频"; | |||
| } | |||
| return "其它"; | |||
| } | |||
| @@ -508,6 +499,12 @@ function getTaskSataus(task_status,task_status_desc){ | |||
| else if(task_status == -1){ | |||
| return "关联的数据集已经被删除。" | |||
| } | |||
| else if(task_status == 20){ | |||
| return "自动标注进行中:" + task_status_desc; | |||
| }else if(task_status == 21){ | |||
| return task_status_desc; | |||
| } | |||
| return ""; | |||
| } | |||
| function getVerify(task_status,id,task_type){ | |||
| @@ -522,7 +519,7 @@ function getVerify(task_status,id,task_type){ | |||
| } | |||
| function getLabel(task_status,id,task_type,task_flow_type){ | |||
| if(task_status == 0 && (userType == 1 || userType == 0)){ | |||
| if((task_status == 0 || task_status == 21) && (userType == 1 || userType == 0)){ | |||
| return "<a onclick=\"personLabel(\'" + id + "\'," + task_type + ")\"><b>" + getLabelDesc(task_flow_type) + "标注</b></a><br>"; | |||
| }else{ | |||
| return ""; | |||
| @@ -570,8 +567,59 @@ function display_list(){ | |||
| $('#label_task_list tr').find('td:eq(1)').hide(); | |||
| $('#label_task_list tr').find('th:eq(1)').hide(); | |||
| } | |||
| isNeedToRefresh = false; | |||
| taskNeedIntervalToRefresh(); | |||
| } | |||
| var isNeedToRefresh; | |||
| var refreshTimeId = []; | |||
| var refreshCount; | |||
| var refreshMaxTime; | |||
| function taskNeedIntervalToRefresh(){ | |||
| var isNeedToSetInterval = false; | |||
| refreshMaxTime= 1; | |||
| if(!isEmpty(tableData)){ | |||
| for (var i=0;i<tableData.length;i++){ | |||
| if(tableData[i].task_status == 20){ | |||
| console.log("有任务在自动标注中。需要自动刷新。"); | |||
| isNeedToRefresh = true;//有任务在进行中才刷新,否则不刷新。 | |||
| refreshMaxTime = 500; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if(!isEmpty(refreshTimeId)){ | |||
| for(var i =0; i < refreshTimeId.length ;i++){ | |||
| console.log("清除定时器。refreshTimeId=" + refreshTimeId[i]); | |||
| window.clearInterval(refreshTimeId[i]); | |||
| } | |||
| refreshTimeId = []; | |||
| } | |||
| if(isNeedToRefresh){ | |||
| refreshCount = 0; | |||
| var tmpTimeId = self.setInterval("clockRefresh('" + refreshMaxTime +"')",5000);//5秒刷新 | |||
| refreshTimeId.push(tmpTimeId); | |||
| console.log("开始刷新。tmpTimeId=" + tmpTimeId); | |||
| } | |||
| } | |||
| function clockRefresh(refreshMaxTime){ | |||
| refreshCount = refreshCount + 1; | |||
| if(refreshCount > refreshMaxTime){ | |||
| for(var i =0; i < refreshTimeId.length ;i++){ | |||
| console.log("超过刷新最大次数,清除定时器。timeId=" + refreshTimeId[i]); | |||
| window.clearInterval(refreshTimeId[i]); | |||
| } | |||
| refreshTimeId = []; | |||
| return; | |||
| } | |||
| var current = $('#displayPage1').text(); | |||
| console.log("开始刷新。current=" + current); | |||
| if(current >= 1){ | |||
| page(current - 1,pageSize); | |||
| } | |||
| } | |||
| function startToLabel(taskid, task_type){//从审核转回标注,标注人不变。 | |||
| $.ajax({ | |||
| @@ -692,12 +740,12 @@ function setMultiTaskId(){ | |||
| return; | |||
| } | |||
| var taskList = []; | |||
| Check.each(function () {//遍历 | |||
| var row = $(this).parent("td").parent("tr");//获取选中行 | |||
| var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值 | |||
| taskList.push(id); | |||
| //$('#hide_labeltaskid').val(id); | |||
| }); | |||
| Check.each(function () {//遍历 | |||
| var row = $(this).parent("td").parent("tr");//获取选中行 | |||
| var id = row.find("[id='labeltask_id']").html();//获取name='Sid'的值 | |||
| taskList.push(id); | |||
| //$('#hide_labeltaskid').val(id); | |||
| }); | |||
| setTaskId(JSON.stringify(taskList)); | |||
| } | |||
| @@ -42,7 +42,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/manager/shutdown", Shutdown) | |||
| m.Post("/manager/restart", Restart) | |||
| m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | |||
| m.Post("/cmd/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
| m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
| m.Post("/tool/repo_stat", RepoStatisticManually) | |||
| }, CheckInternalToken) | |||
| } | |||
| @@ -5,11 +5,13 @@ | |||
| package private | |||
| import ( | |||
| "gitea.com/macaron/macaron" | |||
| "net/http" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/routers/repo" | |||
| "gitea.com/macaron/macaron" | |||
| ) | |||
| func UpdateAllRepoCommitCnt(ctx *macaron.Context) { | |||
| @@ -35,3 +37,8 @@ func UpdateAllRepoCommitCnt(ctx *macaron.Context) { | |||
| "error_msg": "", | |||
| }) | |||
| } | |||
| func RepoStatisticManually(ctx *macaron.Context) { | |||
| date := ctx.Query("date") | |||
| repo.RepoStatisticDaily(date) | |||
| } | |||
| @@ -0,0 +1,122 @@ | |||
| package repo | |||
| import ( | |||
| "time" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| ) | |||
| //auto daily or manually | |||
| func RepoStatisticAuto() { | |||
| log.Info("", time.Now()) | |||
| yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") | |||
| RepoStatisticDaily(yesterday) | |||
| } | |||
| func RepoStatisticDaily(date string) { | |||
| log.Info("%s", date) | |||
| if err := models.DeleteRepoStatDaily(date); err != nil { | |||
| log.Error("DeleteRepoStatDaily failed: %v", err.Error()) | |||
| return | |||
| } | |||
| repos, err := models.GetAllRepositories() | |||
| if err != nil { | |||
| log.Error("GetAllRepositories failed: %v", err.Error()) | |||
| return | |||
| } | |||
| for _, repo := range repos { | |||
| log.Info("start statistic: %s", repo.Name) | |||
| repoGitStat, err := models.GetRepoKPIStats(repo) | |||
| if err != nil { | |||
| log.Error("GetRepoKPIStats failed: %s", repo.Name) | |||
| log.Error("failed statistic: %s", repo.Name) | |||
| continue | |||
| } | |||
| var issueFixedRate float32 | |||
| if repo.NumIssues != 0 { | |||
| issueFixedRate = float32(repo.NumClosedIssues) / float32(repo.NumIssues) | |||
| } | |||
| numVersions, err := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{}) | |||
| if err != nil { | |||
| log.Error("GetReleaseCountByRepoID failed: %s", repo.Name) | |||
| log.Error("failed statistic: %s", repo.Name) | |||
| continue | |||
| } | |||
| datasetSize, err := getDatasetSize(repo) | |||
| if err != nil { | |||
| log.Error("getDatasetSize failed: %s", repo.Name) | |||
| log.Error("failed statistic: %s", repo.Name) | |||
| continue | |||
| } | |||
| numComments, err := models.GetCommentCountByRepoID(repo.ID) | |||
| if err != nil { | |||
| log.Error("GetCommentCountByRepoID failed: %s", repo.Name) | |||
| log.Error("failed statistic: %s", repo.Name) | |||
| continue | |||
| } | |||
| //beginTime, endTime := getStatTime(date) | |||
| //numVisits := repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime) | |||
| numVisits := 0 | |||
| repoStat := models.RepoStatistic{ | |||
| RepoID: repo.ID, | |||
| Date: date, | |||
| NumWatches: int64(repo.NumWatches), | |||
| NumStars: int64(repo.NumStars), | |||
| NumDownloads: repo.CloneCnt, | |||
| NumComments: numComments, | |||
| NumVisits: int64(numVisits), | |||
| NumClosedIssues: int64(repo.NumClosedIssues), | |||
| NumVersions: numVersions, | |||
| NumDevMonths: repoGitStat.DevelopAge, | |||
| RepoSize: repo.Size, | |||
| DatasetSize: datasetSize, | |||
| NumModels: 0, | |||
| NumWikiViews: repoGitStat.WikiPages, | |||
| NumCommits: repo.NumCommit, | |||
| NumIssues: int64(repo.NumIssues), | |||
| NumPulls: int64(repo.NumPulls), | |||
| IssueFixedRate: issueFixedRate, | |||
| NumContributor: repoGitStat.Contributors, | |||
| NumKeyContributor: repoGitStat.KeyContributors, | |||
| } | |||
| if _, err = models.InsertRepoStat(&repoStat); err != nil { | |||
| log.Error("InsertRepoStat failed: %s", repo.Name) | |||
| log.Error("failed statistic: %s", repo.Name) | |||
| continue | |||
| } | |||
| log.Info("finish statistic: %s", repo.Name) | |||
| } | |||
| } | |||
| func getDatasetSize(repo *models.Repository) (int64, error) { | |||
| dataset, err := models.GetDatasetByRepo(repo) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| return models.GetAttachmentSizeByDatasetID(dataset.ID) | |||
| } | |||
| func getStatTime(timeStr string) (string, string) { | |||
| t, _ := time.Parse("2006-01-02", timeStr) | |||
| timeNumber := t.Unix() | |||
| beginTimeNumber := timeNumber - 8*60*60 | |||
| endTimeNumber := timeNumber + 16*60*60 | |||
| beginTime := time.Unix(beginTimeNumber, 0).Format(time.RFC3339) | |||
| endTime := time.Unix(endTimeNumber, 0).Format(time.RFC3339) | |||
| log.Info("%s, %s", beginTime, endTime) | |||
| return beginTime, endTime | |||
| } | |||
| @@ -8,7 +8,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/log" | |||
| ) | |||
| func TimeingCountData() { | |||
| func TimingCountData() { | |||
| //query wiki data | |||
| log.Info("start to time count data") | |||
| wikiMap := make(map[string]int) | |||
| @@ -808,10 +808,12 @@ func renderCode(ctx *context.Context) { | |||
| //base repo has the same branch, then compare between current repo branch and base repo's branch | |||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName | |||
| ctx.SetParams("*",compareUrl) | |||
| ctx.Data["UpstreamSameBranchName"] = true | |||
| }else{ | |||
| //else, compare between current repo branch and base repo's default branch | |||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch | |||
| ctx.SetParams("*",compareUrl) | |||
| ctx.Data["UpstreamSameBranchName"] = false | |||
| } | |||
| _, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx) | |||
| defer headGitRepo.Close() | |||
| @@ -318,7 +318,11 @@ | |||
| </div> | |||
| <div class="one wide column"> | |||
| <a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a> | |||
| {{if .User.Name}} | |||
| <a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a> | |||
| {{else}} | |||
| <a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a> | |||
| {{end}} | |||
| </div> | |||
| <div class="seven wide column text right"> | |||
| <div class="ui compact buttons"> | |||
| @@ -5,7 +5,7 @@ | |||
| {{range .Attachments}} | |||
| <div class="ui grid item" id="{{.UUID}}"> | |||
| <div class="row"> | |||
| <div class="eight wide column"> | |||
| <div class="eight wide column" data-tooltip="{{.Name}}"> | |||
| <span class="ui right">{{.Size | FileSize}}</span> | |||
| <a class="title" href="{{.DownloadURL}}?type={{$.Type}}"> | |||
| {{svg "octicon-cloud-download" 16}} {{.Name}} | |||
| @@ -13,7 +13,7 @@ | |||
| </div> | |||
| <div class="eight wide column right aligned"> | |||
| <div class="ui left mini icon buttons"> | |||
| <span class="ui basic button" data-tooltip='{{$.i18n.Tr "dataset.download_count"}}' data-position="bottom right">{{svg "octicon-flame" 16}} {{(.DownloadCount | PrettyNumber)}}</span> | |||
| <span class="ui basic button text left" data-tooltip='{{$.i18n.Tr "dataset.download_count"}}' data-position="bottom right" style="width: 60px; padding-left: 0;">{{svg "octicon-flame" 16}} {{(.DownloadCount | PrettyNumber)}}</span> | |||
| <span class="ui basic basic button clipboard" data-clipboard-text="{{.DownloadURL}}" data-tooltip='{{$.i18n.Tr "dataset.copy_url"}}' data-clipboard-action="copy"{{if ne $.Type 0}} style="display:none;"{{end}}>{{svg "octicon-file" 16}}</span> | |||
| <span class="ui basic basic button clipboard" data-clipboard-text="{{.FileChunk.Md5}}" data-tooltip='{{$.i18n.Tr "dataset.copy_md5"}}' data-clipboard-action="copy">{{svg "octicon-file-binary" 16}}</span> | |||
| </div> | |||
| @@ -17,9 +17,11 @@ | |||
| <div class="repository dataset dir-list view"> | |||
| {{template "repo/header" .}} | |||
| <input type="hidden" id="repoId" value="{{.repoId}}"> | |||
| <div class="ui container"> | |||
| <div class="header"> | |||
| <h3 class="modal-title">人工标注任务列表</h3> | |||
| <h3 class="modal-title">标注任务列表</h3> | |||
| </div> | |||
| <div class="ui container"> | |||
| <div class="ui container"> | |||
| @@ -45,8 +47,8 @@ | |||
| </div> | |||
| <div class="ui container" style="height: 30px;"> | |||
| <!-- <button type="button" onclick="setPredictTask();" class="ui blue button" style="float:left">新建自动标注结果图片标注</button> --> | |||
| <button type="button" onclick="setDataSetTask();" class="ui blue button" style="float:left">新建数据集图片标注</button> | |||
| <!--<button type="button" onclick="setPredictTask();" class="ui blue button" style="float:left">新建图片自动标注</button>--> | |||
| <button type="button" onclick="setDataSetTask();" class="ui blue button" style="float:left">新建图片人工标注</button> | |||
| <button type="button" onclick="setMultiTaskId();" class="ui blue button" style="float:right;margin-left:20px;">导出标注数据</button> | |||
| <button type="button" onclick="countLabel();" class="ui blue button" style="float:right;margin-left:20px;">统计所有标注数量</button> | |||
| @@ -65,7 +67,11 @@ | |||
| <div class="field"> | |||
| <label for="exampleInputPassword1">选择数据集对象<font color=red>*</font></label> | |||
| <select name="pre_predict_task" id="dataset_list" onchange="dataset_sele_Change(this)"> | |||
| <option value="" selected="">请选择</option> | |||
| {{if .Attachments}} | |||
| {{range .Attachments}} | |||
| <option value="{{.UUID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| @@ -105,44 +111,50 @@ | |||
| <div id="labelModal" class="ui predict modal"> | |||
| <div class="modal-dialog"> | |||
| <div class="modal-content"> | |||
| <div class="modal-header"> | |||
| <button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button> | |||
| <h4 class="modal-title">新建自动标注结果人工标注</h4> | |||
| </div> | |||
| <div class="modal-body"> | |||
| <div class="form-group"> | |||
| <label for="exampleInputPassword1">关联的自动标注任务<font color=red>*</font></label> | |||
| <select class="form-control" name="pre_predict_task" id="pre_predict_task_for_label" onchange="sele_Change(this)"> | |||
| <option value="" selected="">请选择</option> | |||
| </select> | |||
| <!-- <input type="" class="form-control" id="prepredtaskid" placeholder="预检任务"> --> | |||
| </div> | |||
| <div class="form-group" > | |||
| <label for="exampleInputEmail2">任务指派给</label> | |||
| <select class="form-control" name="任务指派给" id="label_assign_user"> | |||
| <option value=""> 请选择</option> | |||
| </select> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label for="exampleInputEmail1">人工标注任务名称<font color=red>*</font></label> | |||
| <input type="" class="form-control" id="labeltaskname" placeholder="校验标注任务名称,不超过32个字符" maxlength="32"> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label id = "labelInfo" for="exampleInputFile">标注类别属性,请输入符合格式Json字符串 </label> | |||
| <select class="form-control" name="labelpropertytask" id="labelpropertytask_auto"> | |||
| <option value="" selected="">请选择</option> | |||
| </select> | |||
| </div> | |||
| <i class="close icon"></i> | |||
| <div class="header"> | |||
| <h4 class="modal-title">新建自动标注任务</h4> | |||
| </div> | |||
| <div class="content"> | |||
| <div class="ui form"> | |||
| <div class="field"> | |||
| <label for="exampleInputPassword1">选择数据集对象<font color=red>*</font></label> | |||
| <select name="pre_predict_task" id="dataset_list_auto" onchange="dataset_auto_sele_Change(this)"> | |||
| {{if .Attachments}} | |||
| {{range .Attachments}} | |||
| <option value="{{.UUID}}">{{.Name}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| <div class="field"> | |||
| <label for="exampleInputPassword1">选择标注模型<font color=red>*</font></label> | |||
| <select name="pre_predict_task" id="model_list"> | |||
| <option value="" selected="">请选择</option> | |||
| </select> | |||
| </div> | |||
| <div class="field" > | |||
| <label for="exampleInputEmail1">自动标注任务名称<font color=red>*</font></label> | |||
| <input type="text" id="autolabeltaskname" placeholder="标注任务名称,不超过32个字符"> | |||
| </div> | |||
| <div class="field" style="display:none"> | |||
| <label for="exampleInputEmail2">任务指派给</label> | |||
| <select name="任务指派给" id="label_assign_user"> | |||
| <option value="">请选择</option> | |||
| </select> | |||
| </div> | |||
| <div class="field" style="display:none"> | |||
| <label id = "labelInfo" for="exampleInputFile">标注类别(也可以直接在标注界面上进行设置)</label> | |||
| <select name="labelpropertytask" id="labelpropertytask_auto" > | |||
| <option value="" selected="">请选择</option> | |||
| </select> | |||
| </div> | |||
| <button type="button" onclick="submit_labeltask();">提交</button> | |||
| </div> | |||
| <button type="button" onclick="submit_autolabeltask();">提交</button> | |||
| </div> | |||
| </div> | |||
| </div> <!-- /.box-body --> | |||
| @@ -75,7 +75,7 @@ | |||
| z-index: 11; | |||
| will-change: transform, opacity; | |||
| width: 100% !important; | |||
| -webkit-animation-iteration-count: 1; | |||
| animation-iteration-count: 1; | |||
| -webkit-animation-duration: 300ms; | |||
| @@ -86,7 +86,7 @@ | |||
| animation-fill-mode: both; | |||
| } | |||
| </style> | |||
| @@ -94,7 +94,7 @@ | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| {{template "base/alert" .}} | |||
| {{if and .Permission.IsAdmin (not .Repository.IsArchived)}} | |||
| <!-- <div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none"> | |||
| <div class="fourteen wide column"> | |||
| @@ -113,13 +113,13 @@ | |||
| data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a> | |||
| </div> | |||
| </div> --> | |||
| {{end}} | |||
| <div class="hide" id="validate_prompt"> | |||
| <span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span> | |||
| <span id="format_prompt">{{.i18n.Tr "repo.topic.format_prompt"}}</span> | |||
| </div> | |||
| <div class="ui repo-description stackable grid"> | |||
| <div class="ui repo-description stackable grid"> | |||
| {{if .RepoSearchEnabled}} | |||
| <div class="ui repo-search four wide column"> | |||
| @@ -136,7 +136,7 @@ | |||
| </div> | |||
| {{end}} | |||
| </div> | |||
| {{if .Repository.IsArchived}} | |||
| <div class="ui warning message"> | |||
| {{.i18n.Tr "repo.archive.title"}} | |||
| @@ -156,7 +156,7 @@ | |||
| </a> | |||
| {{if and .Repository.IsFork .PullRequestCtx.Allowed}} | |||
| {{if gt .FetchUpstreamCnt 0 }} | |||
| <a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}"> | |||
| <a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}"> | |||
| <button id="new-pull-request" class="ui compact basic button" title="{{$.i18n.Tr (TrN $.i18n.Lang .FetchUpstreamCnt "repo.pulls.commits_count_1" "repo.pulls.commits_count_n") .FetchUpstreamCnt}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||
| </a> | |||
| {{else if lt .FetchUpstreamCnt 0}} | |||
| @@ -164,7 +164,7 @@ | |||
| <button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_error"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||
| </a> | |||
| {{else}} | |||
| <a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}"> | |||
| <a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{if .UpstreamSameBranchName}}{{.BranchName | EscapePound}}{{else}}{{.BaseRepo.DefaultBranch | EscapePound}}{{end}}"> | |||
| <button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_up_to_date"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button> | |||
| </a> | |||
| {{end}} | |||
| @@ -254,7 +254,7 @@ | |||
| {{template "repo/view_list" .}} | |||
| {{end}} | |||
| </div> | |||
| <div class="ui six wide tablet four wide computer column"> | |||
| <div class="ui six wide tablet four wide computer column"> | |||
| <div id="repo-desc"> | |||
| <h4 id="about-desc" class="ui header">简介 | |||
| <!-- <a class="edit-icon" href="javascript:void(0)"> | |||
| @@ -267,33 +267,33 @@ | |||
| {{else}} | |||
| <span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span> | |||
| {{end}} | |||
| </p> | |||
| </div> | |||
| {{if .Repository.Website}} | |||
| <p class="ui"> | |||
| <i class="gray linkify icon"></i> | |||
| <a class="link edit-link" target="_blank" title="{{.Repository.Website}}" href="{{.Repository.Website}}">{{.Repository.Website}}</a> | |||
| </p> | |||
| {{end}} | |||
| {{end}} | |||
| <div class="ui" id="repo-topics" style="display: flex;position: relative;margin-bottom: 1.0rem;"> | |||
| <i class="grey bookmark icon"></i> | |||
| <div id="repo-topics1" style="flex: 1;"> | |||
| <!-- {{if not .Topics}} | |||
| <span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span> | |||
| {{end}} --> | |||
| {{range .Topics}} | |||
| <a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a> | |||
| <a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a> | |||
| {{end}} | |||
| </div> | |||
| <div> | |||
| @@ -301,13 +301,13 @@ | |||
| </div> | |||
| <div id="topic_edit" class="vue_menu" style="display:none"> | |||
| <div id="topic_edit1"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <p class="ui"> | |||
| <i class="grey code icon"></i> | |||
| {{range .LanguageStats}} | |||
| @@ -315,14 +315,14 @@ | |||
| {{end}} | |||
| </p> | |||
| {{if .LICENSE}} | |||
| <p class="ui"> | |||
| <i class="grey clone icon"></i> | |||
| {{.LICENSE}} | |||
| </p> | |||
| {{end}} | |||
| <div class="ui divider"></div> | |||
| @@ -338,22 +338,22 @@ | |||
| {{range .ContributorInfo}} | |||
| {{if .UserInfo}} | |||
| <a href="{{AppSubUrl}}/{{.UserInfo.Name}}"><img class="ui avatar image" src="{{.UserInfo.RelAvatarLink}}"></a> | |||
| {{else if .Email}} | |||
| {{else if .Email}} | |||
| <a href="mailto:{{.Email}}" class="circular ui button">{{.Email}}</a> | |||
| {{end}} | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <script type="text/javascript"> | |||
| $(document).ready(function(){ | |||
| $(document).ready(function(){ | |||
| $(".membersmore").click(function(){ | |||
| $("#contributorInfo > a:nth-child(n+25)").show(); | |||
| }); | |||
| @@ -12,7 +12,7 @@ | |||
| </div> | |||
| {{else}} | |||
| <div class="ui large breadcrumb"> | |||
| <a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.pulls"}}</a> | |||
| <a class="section" href="{{.RepoLink}}/pulls">{{.i18n.Tr "repo.pulls"}}</a> | |||
| <div class="divider"> / </div> | |||
| <div class="action section">{{.i18n.Tr "repo.issues_detail"}}</div> | |||
| </div> | |||
| @@ -292,7 +292,11 @@ | |||
| </div> | |||
| <div class="one wide column"> | |||
| {{if .User.Name}} | |||
| <a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a> | |||
| {{else}} | |||
| <a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a> | |||
| {{end}} | |||
| </div> | |||
| <div class="seven wide column text right"> | |||
| @@ -300,7 +304,7 @@ | |||
| <a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}"> | |||
| 查看 | |||
| </a> | |||
| <a class="ui basic {{if not .CanDebug}}disabled {{else}}blue {{end}}button" href="{{$.Link}}/{{.JobID}}/debug"> | |||
| <a class="ui basic {{if not .CanDebug}}disabled {{else}}blue {{end}}button" href="{{$.Link}}/{{.JobID}}/debug" target="_blank"> | |||
| 调试 | |||
| </a> | |||
| <form id="stopForm-{{.JobID}}" action="{{if ne .Status "RUNNING"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/stop{{end}}" method="post" style="margin-left:-1px;"> | |||
| @@ -148,29 +148,37 @@ export default { | |||
| params:this.params | |||
| }).then((res)=>{ | |||
| this.array = res.data.topics | |||
| this.array.forEach((element,index) => { | |||
| if (this.arrayTopics.indexOf(element.topic_name)>-1){ | |||
| this.showInitTopic.push(true) | |||
| }else{ | |||
| } | |||
| else{ | |||
| this.showInitTopic.push(false) | |||
| } | |||
| this.showInputValue = true | |||
| }); | |||
| let findelement = this.array.some((item)=>{ | |||
| return item.topic_name===this.input | |||
| }) | |||
| this.showInputValue = !findelement | |||
| }); | |||
| }) | |||
| this.showInputValue = true | |||
| this.showSearchTopic = true | |||
| } | |||
| this.showAddTopic = false | |||
| }, | |||
| @@ -201,6 +209,9 @@ export default { | |||
| }) | |||
| }, | |||
| postTopic(){ | |||
| if(!this.showInputValue){ | |||
| return | |||
| } | |||
| const patter = /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,34}$/ | |||
| let regexp = patter.test(this.input) | |||
| if(!regexp){ | |||
| @@ -249,7 +260,7 @@ export default { | |||
| this.Post(data,topics) | |||
| if(this.arrayTopics.length===0){ | |||
| console.log("add postTopic") | |||
| $('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>') | |||
| }else{ | |||
| $('#repo-topics1').children('span').remove() | |||
| @@ -282,7 +293,9 @@ export default { | |||
| this.input = '' | |||
| if (this.input === ''){ | |||
| this.array = this.arrayTopics | |||
| let data = [] | |||
| this.showInitTopic = [] | |||
| this.array.forEach((element,index) => { | |||
| @@ -301,6 +314,7 @@ export default { | |||
| this.showInputValue = false | |||
| this.showSearchTopic = true | |||
| this.showAddTopic = false | |||
| } | |||
| stopPropagation(e); | |||
| @@ -332,30 +346,30 @@ computed:{ | |||
| }, | |||
| watch: { | |||
| input(newValue){ | |||
| // input(newValue){ | |||
| if (newValue === ''){ | |||
| this.array = this.arrayTopics | |||
| let data = [] | |||
| this.showInitTopic = [] | |||
| this.array.forEach((element,index) => { | |||
| // if (newValue === ''){ | |||
| // this.array = this.arrayTopics | |||
| // let data = [] | |||
| // this.showInitTopic = [] | |||
| // this.array.forEach((element,index) => { | |||
| let item = {} | |||
| item.topic_name = element | |||
| // let item = {} | |||
| // item.topic_name = element | |||
| data.push(item) | |||
| this.showInitTopic.push(true) | |||
| // data.push(item) | |||
| // this.showInitTopic.push(true) | |||
| }); | |||
| // }); | |||
| this.array = data | |||
| // this.array = data | |||
| this.showInputValue = false | |||
| this.showSearchTopic = true | |||
| } | |||
| } | |||
| // this.showInputValue = false | |||
| // this.showSearchTopic = true | |||
| // } | |||
| // } | |||
| }, | |||
| mounted() { | |||
| const context = this | |||