| @@ -51,6 +51,7 @@ type Attachment struct { | |||
| FileChunk *FileChunk `xorm:"-"` | |||
| CanDel bool `xorm:"-"` | |||
| Uploader *User `xorm:"-"` | |||
| Md5 string `xorm:"-"` | |||
| } | |||
| type AttachmentUsername struct { | |||
| @@ -389,7 +389,7 @@ type JobResultPayload struct { | |||
| AppProgress string `json:"appProgress"` | |||
| AppTrackingURL string `json:"appTrackingUrl"` | |||
| AppLaunchedTime int64 `json:"appLaunchedTime"` | |||
| AppCompletedTime int64 `json:"appCompletedTime"` | |||
| AppCompletedTime interface{} `json:"appCompletedTime"` | |||
| AppExitCode int `json:"appExitCode"` | |||
| AppExitDiagnostics string `json:"appExitDiagnostics"` | |||
| AppExitType interface{} `json:"appExitType"` | |||
| @@ -1371,6 +1371,16 @@ func getRepoCloudBrain(cb *Cloudbrain) (*Cloudbrain, error) { | |||
| return cb, nil | |||
| } | |||
| func getRepoCloudBrainWithDeleted(cb *Cloudbrain) (*Cloudbrain, error) { | |||
| has, err := x.Unscoped().Get(cb) | |||
| if err != nil { | |||
| return nil, err | |||
| } else if !has { | |||
| return nil, ErrJobNotExist{} | |||
| } | |||
| return cb, nil | |||
| } | |||
| func GetRepoCloudBrainByJobID(repoID int64, jobID string) (*Cloudbrain, error) { | |||
| cb := &Cloudbrain{JobID: jobID, RepoID: repoID} | |||
| return getRepoCloudBrain(cb) | |||
| @@ -1387,6 +1397,12 @@ func GetCloudbrainByID(id string) (*Cloudbrain, error) { | |||
| return getRepoCloudBrain(cb) | |||
| } | |||
| func GetCloudbrainByIDWithDeleted(id string) (*Cloudbrain, error) { | |||
| idInt64, _ := strconv.ParseInt(id, 10, 64) | |||
| cb := &Cloudbrain{ID: idInt64} | |||
| return getRepoCloudBrainWithDeleted(cb) | |||
| } | |||
| func GetCloudbrainByJobIDAndVersionName(jobID string, versionName string) (*Cloudbrain, error) { | |||
| cb := &Cloudbrain{JobID: jobID, VersionName: versionName} | |||
| return getRepoCloudBrain(cb) | |||
| @@ -1,6 +1,7 @@ | |||
| package models | |||
| import ( | |||
| "code.gitea.io/gitea/modules/log" | |||
| "errors" | |||
| "fmt" | |||
| "sort" | |||
| @@ -62,19 +63,20 @@ func (datasets DatasetList) loadAttributes(e Engine) error { | |||
| } | |||
| set := make(map[int64]struct{}) | |||
| userIdSet := make(map[int64]struct{}) | |||
| datasetIDs := make([]int64, len(datasets)) | |||
| for i := range datasets { | |||
| set[datasets[i].UserID] = struct{}{} | |||
| userIdSet[datasets[i].UserID] = struct{}{} | |||
| set[datasets[i].RepoID] = struct{}{} | |||
| datasetIDs[i] = datasets[i].ID | |||
| } | |||
| // Load owners. | |||
| users := make(map[int64]*User, len(set)) | |||
| users := make(map[int64]*User, len(userIdSet)) | |||
| repos := make(map[int64]*Repository, len(set)) | |||
| if err := e. | |||
| Where("id > 0"). | |||
| In("id", keysInt64(set)). | |||
| In("id", keysInt64(userIdSet)). | |||
| Find(&users); err != nil { | |||
| return fmt.Errorf("find users: %v", err) | |||
| } | |||
| @@ -139,20 +141,7 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
| var cond = builder.NewCond() | |||
| cond = cond.And(builder.Neq{"dataset.status": DatasetStatusDeleted}) | |||
| if len(opts.Keyword) > 0 { | |||
| cond = cond.And(builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword})) | |||
| } | |||
| if len(opts.Category) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.category": opts.Category}) | |||
| } | |||
| if len(opts.Task) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.task": opts.Task}) | |||
| } | |||
| if len(opts.License) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.license": opts.License}) | |||
| } | |||
| cond = generateFilterCond(opts, cond) | |||
| if opts.RepoID > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.repo_id": opts.RepoID}) | |||
| @@ -162,14 +151,12 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
| cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic}) | |||
| cond = cond.And(builder.Eq{"attachment.is_private": false}) | |||
| if opts.OwnerID > 0 { | |||
| if len(opts.Keyword) == 0 { | |||
| cond = cond.Or(builder.Eq{"repository.owner_id": opts.OwnerID}) | |||
| } else { | |||
| subCon := builder.NewCond() | |||
| subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID}, builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword})) | |||
| cond = cond.Or(subCon) | |||
| } | |||
| subCon := builder.NewCond() | |||
| subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID}) | |||
| subCon = generateFilterCond(opts, subCon) | |||
| cond = cond.Or(subCon) | |||
| } | |||
| } else if opts.OwnerID > 0 { | |||
| cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID}) | |||
| @@ -182,6 +169,25 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
| return cond | |||
| } | |||
| func generateFilterCond(opts *SearchDatasetOptions, cond builder.Cond) builder.Cond { | |||
| if len(opts.Keyword) > 0 { | |||
| cond = cond.And(builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword})) | |||
| } | |||
| if len(opts.Category) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.category": opts.Category}) | |||
| } | |||
| if len(opts.Task) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.task": opts.Task}) | |||
| } | |||
| if len(opts.License) > 0 { | |||
| cond = cond.And(builder.Eq{"dataset.license": opts.License}) | |||
| } | |||
| return cond | |||
| } | |||
| func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (DatasetList, int64, error) { | |||
| if opts.Page <= 0 { | |||
| opts.Page = 1 | |||
| @@ -292,7 +298,13 @@ func getDatasetAttachments(e Engine, typeCloudBrain int, isSigned bool, user *Us | |||
| if err != nil { | |||
| return err | |||
| } | |||
| attachment.FileChunk = fileChunks[0] | |||
| if len(fileChunks) > 0 { | |||
| attachment.Md5 = fileChunks[0].Md5 | |||
| } else { | |||
| log.Error("has attachment record, but has no file_chunk record") | |||
| attachment.Md5 = "no_record" | |||
| } | |||
| attachment.CanDel = CanDelAttachment(isSigned, user, attachment) | |||
| sortedRels.Rel[currentIndex].Attachments = append(sortedRels.Rel[currentIndex].Attachments, attachment) | |||
| } | |||
| @@ -348,7 +360,7 @@ func GetDatasetByRepo(repo *Repository) (*Dataset, error) { | |||
| if has { | |||
| return dataset, nil | |||
| } else { | |||
| return nil, errors.New("Not Found") | |||
| return nil, ErrNotExist{repo.ID} | |||
| } | |||
| } | |||
| @@ -1,4 +1,17 @@ | |||
| DELETE FROM public.dataset_es; | |||
| DROP FOREIGN TABLE public.dataset_es; | |||
| DROP TRIGGER IF EXISTS es_insert_dataset on public.dataset; | |||
| DROP FUNCTION public.insert_dataset_data(); | |||
| DROP TRIGGER IF EXISTS es_udpate_dataset_file_name on public.attachment; | |||
| DROP FUNCTION public.udpate_dataset_file_name; | |||
| DROP TRIGGER IF EXISTS es_update_dataset on public.dataset; | |||
| DROP FUNCTION public.update_dataset; | |||
| DROP TRIGGER IF EXISTS es_delete_dataset on public.dataset; | |||
| DROP FUNCTION public.delete_dataset; | |||
| CREATE FOREIGN TABLE public.dataset_es | |||
| ( | |||
| id bigint NOT NULL, | |||
| @@ -1,4 +1,15 @@ | |||
| delete from public.issue_es; | |||
| DROP FOREIGN TABLE public.issue_es; | |||
| DROP TRIGGER IF EXISTS es_insert_issue on public.issue; | |||
| DROP FUNCTION public.insert_issue_data; | |||
| DROP TRIGGER IF EXISTS es_udpate_issue_comment on public.comment; | |||
| DROP FUNCTION udpate_issue_comment; | |||
| DROP TRIGGER IF EXISTS es_update_issue on public.issue; | |||
| DROP FUNCTION public.update_issue; | |||
| DROP TRIGGER IF EXISTS es_delete_issue on public.issue; | |||
| DROP FUNCTION public.delete_issue; | |||
| CREATE FOREIGN TABLE public.issue_es | |||
| ( | |||
| id bigint NOT NULL, | |||
| @@ -182,6 +193,7 @@ $def$ | |||
| name=NEW.name, | |||
| is_closed=NEW.is_closed, | |||
| num_comments=NEW.num_comments, | |||
| updated_unix=NEW.updated_unix, | |||
| comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.id) | |||
| where id=NEW.id; | |||
| return new; | |||
| @@ -1,5 +1,18 @@ | |||
| -- 要处理项目从私有变为公有,并且从公有变成私有的情况 | |||
| DELETE FROM public.repository_es; | |||
| DROP FOREIGN table if exists public.repository_es; | |||
| DROP TRIGGER IF EXISTS es_insert_repository on public.repository; | |||
| DROP FUNCTION public.insert_repository_data; | |||
| DROP TRIGGER IF EXISTS es_update_repository on public.repository; | |||
| DROP FUNCTION public.update_repository; | |||
| DROP TRIGGER IF EXISTS es_delete_repository on public.repository; | |||
| DROP FUNCTION public.delete_repository; | |||
| DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat; | |||
| DROP FUNCTION public.udpate_repository_lang; | |||
| CREATE FOREIGN TABLE public.repository_es ( | |||
| id bigint NOT NULL, | |||
| owner_id bigint, | |||
| @@ -1,4 +1,13 @@ | |||
| DELETE FROM public.user_es; | |||
| DROP FOREIGN table if exists public.user_es; | |||
| DROP TRIGGER IF EXISTS es_insert_user on public.user; | |||
| DROP FUNCTION public.insert_user_data; | |||
| DROP TRIGGER IF EXISTS es_update_user on public.user; | |||
| DROP FUNCTION public.update_user; | |||
| DROP TRIGGER IF EXISTS es_delete_user on public.user; | |||
| DROP FUNCTION public.delete_user; | |||
| CREATE FOREIGN TABLE public.user_es | |||
| ( | |||
| id bigint NOT NULL , | |||
| @@ -138,6 +138,7 @@ func init() { | |||
| new(OfficialTag), | |||
| new(OfficialTagRepos), | |||
| new(WechatBindLog), | |||
| new(OrgStatistic), | |||
| new(SearchRecord), | |||
| ) | |||
| @@ -153,6 +154,8 @@ func init() { | |||
| new(UserBusinessAnalysisCurrentWeek), | |||
| new(UserBusinessAnalysisYesterday), | |||
| new(UserLoginLog), | |||
| new(UserMetrics), | |||
| new(UserAnalysisPara), | |||
| ) | |||
| gonicNames := []string{"SSL", "UID"} | |||
| @@ -8,6 +8,7 @@ package models | |||
| import ( | |||
| "fmt" | |||
| "os" | |||
| "strconv" | |||
| "strings" | |||
| "code.gitea.io/gitea/modules/log" | |||
| @@ -19,6 +20,17 @@ import ( | |||
| "xorm.io/xorm" | |||
| ) | |||
| type OrgStatistic struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| OrgID int64 `xorm:"UNIQUE"` | |||
| NumScore int `xorm:"INDEX NOT NULL DEFAULT 0"` | |||
| } | |||
| type OrgScore struct { | |||
| *User | |||
| Score string | |||
| } | |||
| // IsOwnedBy returns true if given user is in the owner team. | |||
| func (org *User) IsOwnedBy(uid int64) (bool, error) { | |||
| return IsOrganizationOwner(org.ID, uid) | |||
| @@ -135,6 +147,93 @@ func (org *User) RemoveOrgRepo(repoID int64) error { | |||
| return org.removeOrgRepo(x, repoID) | |||
| } | |||
| func UpdateOrgStatistics() { | |||
| ids, err := GetOrganizationsId() | |||
| if err != nil { | |||
| return | |||
| } | |||
| for _, id := range ids { | |||
| org := User{ID: id} | |||
| orgStat := &OrgStatistic{OrgID: id} | |||
| numScore, err := org.getOrgStatistics() | |||
| if err == nil { | |||
| has, _ := x.Get(orgStat) | |||
| orgStat.NumScore = numScore | |||
| if has { | |||
| x.ID(orgStat.ID).Cols("num_score").Update(&orgStat) | |||
| } else { | |||
| x.Insert(orgStat) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| func (org *User) getOrgStatistics() (int, error) { | |||
| count, err := getRepositoryCount(x, org) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| err = org.GetRepositories(ListOptions{int(count), 1}) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| var numScore = 0 | |||
| for _, repo := range org.Repos { | |||
| numScore += int(getOpenIByRepoId(repo.ID)) | |||
| } | |||
| return numScore, nil | |||
| } | |||
| func FindTopNStarsOrgs(n int) ([]*OrgScore, error) { | |||
| sql := "select a.id,sum(b.num_stars) score from \"user\" a ,repository b where a.id=b.owner_id and a.type=1 group by a.id order by score desc limit " + strconv.Itoa(n) | |||
| return findTopNOrgs(sql) | |||
| } | |||
| func FindTopNMembersOrgs(n int) ([]*OrgScore, error) { | |||
| sql := "select id, count(user_id) score from" + | |||
| " (select org_id as id, uid as user_id from org_user " + | |||
| "union select a.id,b.user_id from \"user\" a,collaboration b,repository c " + | |||
| "where a.type=1 and a.id=c.owner_id and b.repo_id=c.id) d " + | |||
| "group by id order by score desc limit " + strconv.Itoa(n) | |||
| return findTopNOrgs(sql) | |||
| } | |||
| func FindTopNOpenIOrgs(n int) ([]*OrgScore, error) { | |||
| sql := "select org_id id,num_score score from org_statistic order by num_score desc limit 10" + strconv.Itoa(n) | |||
| return findTopNOrgs(sql) | |||
| } | |||
| func findTopNOrgs(sql string) ([]*OrgScore, error) { | |||
| resutls, err := x.QueryString(sql) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| var orgScore []*OrgScore | |||
| for _, record := range resutls { | |||
| id, _ := strconv.ParseInt(record["id"], 10, 64) | |||
| user, err := getUserByID(x, id) | |||
| if err != nil { | |||
| continue | |||
| } | |||
| orgScore = append(orgScore, &OrgScore{user, record["score"]}) | |||
| } | |||
| return orgScore, nil | |||
| } | |||
| // CreateOrganization creates record of a new organization. | |||
| func CreateOrganization(org, owner *User) (err error) { | |||
| if !owner.CanCreateOrganization() { | |||
| @@ -1607,14 +1607,16 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e | |||
| } | |||
| dataset, err := GetDatasetByRepo(repo) | |||
| if err != nil { | |||
| if err != nil && !IsErrNotExist(err) { | |||
| return err | |||
| } | |||
| _, err = e.Where("dataset_id = ?", dataset.ID).Cols("is_private").Update(&Attachment{ | |||
| IsPrivate: true, | |||
| }) | |||
| if err != nil { | |||
| return err | |||
| if dataset != nil { | |||
| _, err = e.Where("dataset_id = ?", dataset.ID).Cols("is_private").Update(&Attachment{ | |||
| IsPrivate: true, | |||
| }) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| } | |||
| } else { | |||
| @@ -73,6 +73,16 @@ func (repo *RepoStatistic) DisplayName() string { | |||
| return repo.Alias | |||
| } | |||
| func getOpenIByRepoId(repoId int64) float64 { | |||
| repoStatistic := new(RepoStatistic) | |||
| has, err := xStatistic.Cols("radar_total").Where("repo_id=?", repoId).Desc("id").Limit(1).Get(repoStatistic) | |||
| if !has || err != nil { | |||
| return 0 | |||
| } | |||
| return repoStatistic.RadarTotal | |||
| } | |||
| func DeleteRepoStatDaily(date string) error { | |||
| sess := xStatistic.NewSession() | |||
| defer sess.Close() | |||
| @@ -2104,6 +2104,12 @@ func GetOrganizationsCount() (int64, error) { | |||
| } | |||
| func GetOrganizationsId() ([]int64, error) { | |||
| var ids []int64 | |||
| err := x.Table("user").Where("type=1").Cols("id").Find(&ids) | |||
| return ids, err | |||
| } | |||
| func GetBlockChainUnSuccessUsers() ([]*User, error) { | |||
| users := make([]*User, 0, 10) | |||
| err := x.Where("public_key = ''"). | |||
| @@ -6,7 +6,6 @@ import ( | |||
| "strconv" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/git" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "xorm.io/builder" | |||
| @@ -81,6 +80,19 @@ type UserBusinessAnalysisAll struct { | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| //cloudbraintask | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysis struct { | |||
| @@ -146,6 +158,18 @@ type UserBusinessAnalysis struct { | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisQueryOptions struct { | |||
| @@ -183,6 +207,29 @@ func getLastCountDate() int64 { | |||
| return pageStartTime.Unix() | |||
| } | |||
| func QueryMetrics(start int64, end int64) ([]*UserMetrics, int64) { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| userMetricsList := make([]*UserMetrics, 0) | |||
| if err := statictisSess.Table(new(UserMetrics)).Where("count_date >" + fmt.Sprint(start) + " and count_date<" + fmt.Sprint(end)).OrderBy("count_date desc"). | |||
| Find(&userMetricsList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| return userMetricsList, int64(len(userMetricsList)) | |||
| } | |||
| func QueryRankList(key string, tableName string, limit int) ([]*UserBusinessAnalysisAll, int64) { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0) | |||
| if err := statictisSess.Table(tableName).OrderBy(key+" desc,id desc").Limit(limit, 0). | |||
| Find(&userBusinessAnalysisAllList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| return userBusinessAnalysisAllList, int64(len(userBusinessAnalysisAllList)) | |||
| } | |||
| func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, queryObj interface{}, userName string) ([]*UserBusinessAnalysisAll, int64) { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| @@ -334,6 +381,7 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||
| resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||
| resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||
| resultMap[userRecord.ID].CommitDatasetNum += userRecord.CommitDatasetNum | |||
| resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||
| resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||
| resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||
| @@ -353,7 +401,7 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| return userBusinessAnalysisReturnList, count | |||
| } | |||
| func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[string]*git.UserKPIStats, tableName string, pageStartTime time.Time, pageEndTime time.Time) { | |||
| func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageStartTime time.Time, pageEndTime time.Time, userMetrics map[string]int) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| @@ -379,14 +427,15 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s | |||
| FocusRepoCountMap := queryWatch(start_unix, end_unix) | |||
| StarRepoCountMap := queryStar(start_unix, end_unix) | |||
| WatchedCountMap := queryFollow(start_unix, end_unix) | |||
| CommitDatasetSizeMap := queryDatasetSize(start_unix, end_unix) | |||
| CommitCodeSizeMap := queryCommitCodeSize(start_unix, end_unix) | |||
| CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix) | |||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | |||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||
| LoginCountMap := queryLoginCount(start_unix, end_unix) | |||
| OpenIIndexMap := queryUserRepoOpenIIndex(startTime.Unix(), end_unix) | |||
| CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | |||
| AiModelManageMap := queryUserModel(start_unix, end_unix) | |||
| DataDate := currentTimeNow.Format("2006-01-02") + " 00:01" | |||
| cond := "type != 1 and is_active=true" | |||
| @@ -395,6 +444,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s | |||
| log.Info("query user error. return.") | |||
| return | |||
| } | |||
| ParaWeight := getParaWeight() | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| insertCount := 0 | |||
| @@ -412,84 +462,22 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s | |||
| dateRecordAll.Name = userRecord.Name | |||
| dateRecordAll.GiteaAgeMonth = subMonth(currentTimeNow, userRecord.CreatedUnix.AsTime()) | |||
| dateRecordAll.DataDate = DataDate | |||
| if _, ok := CodeMergeCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.CodeMergeCount = 0 | |||
| } else { | |||
| dateRecordAll.CodeMergeCount = CodeMergeCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := CommitCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.CommitCount = 0 | |||
| } else { | |||
| dateRecordAll.CommitCount = CommitCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := IssueCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.IssueCount = 0 | |||
| } else { | |||
| dateRecordAll.IssueCount = IssueCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := CommentCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.CommentCount = 0 | |||
| } else { | |||
| dateRecordAll.CommentCount = CommentCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := FocusRepoCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.FocusRepoCount = 0 | |||
| } else { | |||
| dateRecordAll.FocusRepoCount = FocusRepoCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := StarRepoCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.StarRepoCount = 0 | |||
| } else { | |||
| dateRecordAll.StarRepoCount = StarRepoCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := WatchedCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.WatchedCount = 0 | |||
| } else { | |||
| dateRecordAll.WatchedCount = WatchedCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := CommitCodeSizeMap[dateRecordAll.Email]; !ok { | |||
| dateRecordAll.CommitCodeSize = 0 | |||
| } else { | |||
| dateRecordAll.CommitCodeSize = int(CommitCodeSizeMap[dateRecordAll.Email].CommitLines) | |||
| } | |||
| if _, ok := CommitDatasetSizeMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.CommitDatasetSize = 0 | |||
| } else { | |||
| dateRecordAll.CommitDatasetSize = CommitDatasetSizeMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := SolveIssueCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.SolveIssueCount = 0 | |||
| } else { | |||
| dateRecordAll.SolveIssueCount = SolveIssueCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := wikiCountMap[dateRecordAll.Name]; !ok { | |||
| dateRecordAll.EncyclopediasCount = 0 | |||
| } else { | |||
| dateRecordAll.EncyclopediasCount = wikiCountMap[dateRecordAll.Name] | |||
| } | |||
| if _, ok := CreateRepoCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.CreateRepoCount = 0 | |||
| } else { | |||
| dateRecordAll.CreateRepoCount = CreateRepoCountMap[dateRecordAll.ID] | |||
| } | |||
| if _, ok := LoginCountMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.LoginCount = 0 | |||
| } else { | |||
| dateRecordAll.LoginCount = LoginCountMap[dateRecordAll.ID] | |||
| } | |||
| dateRecordAll.UserLocation = userRecord.Location | |||
| dateRecordAll.CodeMergeCount = getMapValue(dateRecordAll.ID, CodeMergeCountMap) | |||
| dateRecordAll.CommitCount = getMapValue(dateRecordAll.ID, CommitCountMap) | |||
| dateRecordAll.IssueCount = getMapValue(dateRecordAll.ID, IssueCountMap) | |||
| dateRecordAll.CommentCount = getMapValue(dateRecordAll.ID, CommentCountMap) | |||
| dateRecordAll.FocusRepoCount = getMapValue(dateRecordAll.ID, FocusRepoCountMap) | |||
| dateRecordAll.StarRepoCount = getMapValue(dateRecordAll.ID, StarRepoCountMap) | |||
| dateRecordAll.WatchedCount = getMapValue(dateRecordAll.ID, WatchedCountMap) | |||
| dateRecordAll.CommitCodeSize = getMapValue(dateRecordAll.ID, CommitCodeSizeMap) | |||
| dateRecordAll.CommitDatasetSize = getMapValue(dateRecordAll.ID, CommitDatasetSizeMap) | |||
| dateRecordAll.CommitDatasetNum = getMapValue(dateRecordAll.ID, CommitDatasetNumMap) | |||
| dateRecordAll.SolveIssueCount = getMapValue(dateRecordAll.ID, SolveIssueCountMap) | |||
| dateRecordAll.EncyclopediasCount = getMapKeyStringValue(dateRecordAll.Name, wikiCountMap) | |||
| dateRecordAll.CreateRepoCount = getMapValue(dateRecordAll.ID, CreateRepoCountMap) | |||
| dateRecordAll.LoginCount = getMapValue(dateRecordAll.ID, LoginCountMap) | |||
| if _, ok := OpenIIndexMap[dateRecordAll.ID]; !ok { | |||
| dateRecordAll.OpenIIndex = 0 | |||
| @@ -497,7 +485,15 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s | |||
| dateRecordAll.OpenIIndex = OpenIIndexMap[dateRecordAll.ID] | |||
| } | |||
| dateRecordAll.CommitModelCount = 0 | |||
| dateRecordAll.CloudBrainTaskNum = getMapValue(dateRecordAll.ID, CloudBrainTaskMap) | |||
| dateRecordAll.GpuDebugJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_GpuDebugJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.NpuDebugJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_NpuDebugJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.GpuTrainJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_GpuTrainJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.NpuTrainJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_NpuTrainJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.NpuInferenceJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_NpuInferenceJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.GpuBenchMarkJob = getMapKeyStringValue(fmt.Sprint(dateRecordAll.ID)+"_GpuBenchMarkJob", CloudBrainTaskItemMap) | |||
| dateRecordAll.CommitModelCount = getMapValue(dateRecordAll.ID, AiModelManageMap) | |||
| dateRecordAll.UserIndex = getUserIndexFromAnalysisAll(dateRecordAll, ParaWeight) | |||
| dateRecordBatch = append(dateRecordBatch, dateRecordAll) | |||
| if len(dateRecordBatch) >= BATCH_INSERT_SIZE { | |||
| @@ -508,6 +504,11 @@ func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[s | |||
| } | |||
| dateRecordBatch = make([]UserBusinessAnalysisAll, 0) | |||
| } | |||
| if tableName == "user_business_analysis_all" { | |||
| if dateRecordAll.UserIndex > 0 || dateRecordAll.LoginCount > 0 { | |||
| userMetrics["TotalHasActivityUser"] = getMapKeyStringValue("TotalHasActivityUser", userMetrics) + 1 | |||
| } | |||
| } | |||
| } | |||
| indexTotal += PAGE_SIZE | |||
| if indexTotal >= count { | |||
| @@ -529,7 +530,7 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static | |||
| insertBatchSql := "INSERT INTO public." + tableName + | |||
| "(id, count_date, code_merge_count, commit_count, issue_count, comment_count, focus_repo_count, star_repo_count, watched_count, gitea_age_month, commit_code_size, commit_dataset_size, " + | |||
| "commit_model_count, solve_issue_count, encyclopedias_count, regist_date, create_repo_count, login_count, open_i_index, email, name, data_date) " + | |||
| "commit_model_count, solve_issue_count, encyclopedias_count, regist_date, create_repo_count, login_count, open_i_index, email, name, data_date,cloud_brain_task_num,gpu_debug_job,npu_debug_job,gpu_train_job,npu_train_job,npu_inference_job,gpu_bench_mark_job,cloud_brain_run_time,commit_dataset_num,user_index,user_location) " + | |||
| "VALUES" | |||
| for i, record := range dateRecords { | |||
| @@ -537,7 +538,7 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static | |||
| ", " + fmt.Sprint(record.IssueCount) + ", " + fmt.Sprint(record.CommentCount) + ", " + fmt.Sprint(record.FocusRepoCount) + ", " + fmt.Sprint(record.StarRepoCount) + | |||
| ", " + fmt.Sprint(record.WatchedCount) + ", " + fmt.Sprint(record.GiteaAgeMonth) + ", " + fmt.Sprint(record.CommitCodeSize) + ", " + fmt.Sprint(record.CommitDatasetSize) + | |||
| ", " + fmt.Sprint(record.CommitModelCount) + ", " + fmt.Sprint(record.SolveIssueCount) + ", " + fmt.Sprint(record.EncyclopediasCount) + ", " + fmt.Sprint(record.RegistDate) + | |||
| ", " + fmt.Sprint(record.CreateRepoCount) + ", " + fmt.Sprint(record.LoginCount) + ", " + fmt.Sprint(record.OpenIIndex) + ", '" + record.Email + "', '" + record.Name + "', '" + record.DataDate + "')" | |||
| ", " + fmt.Sprint(record.CreateRepoCount) + ", " + fmt.Sprint(record.LoginCount) + ", " + fmt.Sprint(record.OpenIIndex) + ", '" + record.Email + "', '" + record.Name + "', '" + record.DataDate + "'," + fmt.Sprint(record.CloudBrainTaskNum) + "," + fmt.Sprint(record.GpuDebugJob) + "," + fmt.Sprint(record.NpuDebugJob) + "," + fmt.Sprint(record.GpuTrainJob) + "," + fmt.Sprint(record.NpuTrainJob) + "," + fmt.Sprint(record.NpuInferenceJob) + "," + fmt.Sprint(record.GpuBenchMarkJob) + "," + fmt.Sprint(record.CloudBrainRunTime) + "," + fmt.Sprint(record.CommitDatasetNum) + "," + fmt.Sprint(record.UserIndex) + ",'" + record.UserLocation + "')" | |||
| if i < (len(dateRecords) - 1) { | |||
| insertBatchSql += "," | |||
| } | |||
| @@ -546,36 +547,36 @@ func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, static | |||
| statictisSess.Exec(insertBatchSql) | |||
| } | |||
| func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap map[string]*git.UserKPIStats) { | |||
| func RefreshUserStaticAllTabel(wikiCountMap map[string]int, userMetrics map[string]int) { | |||
| currentTimeNow := time.Now() | |||
| pageStartTime := time.Date(2021, 11, 5, 0, 0, 0, 0, currentTimeNow.Location()) | |||
| pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_all", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_all", pageStartTime, pageEndTime, userMetrics) | |||
| log.Info("refresh all data finished.") | |||
| pageStartTime = time.Date(currentTimeNow.Year(), 1, 1, 0, 0, 0, 0, currentTimeNow.Location()) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_year", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_current_year", pageStartTime, pageEndTime, userMetrics) | |||
| thisMonth := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 0, 0, 0, 0, currentTimeNow.Location()) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_month", thisMonth, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_current_month", thisMonth, pageEndTime, userMetrics) | |||
| offset := int(time.Monday - currentTimeNow.Weekday()) | |||
| if offset > 0 { | |||
| offset = -6 | |||
| } | |||
| pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_week", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_current_week", pageStartTime, pageEndTime, userMetrics) | |||
| pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -30) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_last30_day", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_last30_day", pageStartTime, pageEndTime, userMetrics) | |||
| pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -1) | |||
| pageEndTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_yesterday", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_yesterday", pageStartTime, pageEndTime, userMetrics) | |||
| pageStartTime = thisMonth.AddDate(0, -1, 0) | |||
| pageEndTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1) | |||
| refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_last_month", pageStartTime, pageEndTime) | |||
| refreshUserStaticTable(wikiCountMap, "user_business_analysis_last_month", pageStartTime, pageEndTime, userMetrics) | |||
| } | |||
| @@ -613,12 +614,13 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| } else { | |||
| log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) | |||
| } | |||
| CommitDatasetSizeMap := queryDatasetSize(start_unix, end_unix) | |||
| CommitDatasetSizeMap, CommitDatasetNumMap := queryDatasetSize(start_unix, end_unix) | |||
| SolveIssueCountMap := querySolveIssue(start_unix, end_unix) | |||
| CreateRepoCountMap := queryUserCreateRepo(start_unix, end_unix) | |||
| LoginCountMap := queryLoginCount(start_unix, end_unix) | |||
| OpenIIndexMap := queryUserRepoOpenIIndex(start_unix, end_unix) | |||
| CloudBrainTaskMap, CloudBrainTaskItemMap := queryCloudBrainTask(start_unix, end_unix) | |||
| AiModelManageMap := queryUserModel(start_unix, end_unix) | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| @@ -628,6 +630,9 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| log.Info("query user error. return.") | |||
| return err | |||
| } | |||
| ParaWeight := getParaWeight() | |||
| userMetrics := make(map[string]int) | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| @@ -648,47 +653,14 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| dateRecord.Name = userRecord.Name | |||
| dateRecord.GiteaAgeMonth = subMonth(currentTimeNow, userRecord.CreatedUnix.AsTime()) | |||
| dateRecord.DataDate = DataDate | |||
| if _, ok := CodeMergeCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.CodeMergeCount = 0 | |||
| } else { | |||
| dateRecord.CodeMergeCount = CodeMergeCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := CommitCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.CommitCount = 0 | |||
| } else { | |||
| dateRecord.CommitCount = CommitCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := IssueCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.IssueCount = 0 | |||
| } else { | |||
| dateRecord.IssueCount = IssueCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := CommentCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.CommentCount = 0 | |||
| } else { | |||
| dateRecord.CommentCount = CommentCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := FocusRepoCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.FocusRepoCount = 0 | |||
| } else { | |||
| dateRecord.FocusRepoCount = FocusRepoCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := StarRepoCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.StarRepoCount = 0 | |||
| } else { | |||
| dateRecord.StarRepoCount = StarRepoCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := WatchedCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.WatchedCount = 0 | |||
| } else { | |||
| dateRecord.WatchedCount = WatchedCountMap[dateRecord.ID] | |||
| } | |||
| dateRecord.CodeMergeCount = getMapValue(dateRecord.ID, CodeMergeCountMap) | |||
| dateRecord.CommitCount = getMapValue(dateRecord.ID, CommitCountMap) | |||
| dateRecord.IssueCount = getMapValue(dateRecord.ID, IssueCountMap) | |||
| dateRecord.CommentCount = getMapValue(dateRecord.ID, CommentCountMap) | |||
| dateRecord.FocusRepoCount = getMapValue(dateRecord.ID, FocusRepoCountMap) | |||
| dateRecord.StarRepoCount = getMapValue(dateRecord.ID, StarRepoCountMap) | |||
| dateRecord.WatchedCount = getMapValue(dateRecord.ID, WatchedCountMap) | |||
| if _, ok := CommitCodeSizeMap[dateRecord.Email]; !ok { | |||
| dateRecord.CommitCodeSize = 0 | |||
| @@ -696,35 +668,15 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| dateRecord.CommitCodeSize = int(CommitCodeSizeMap[dateRecord.Email].CommitLines) | |||
| } | |||
| if _, ok := CommitDatasetSizeMap[dateRecord.ID]; !ok { | |||
| dateRecord.CommitDatasetSize = 0 | |||
| } else { | |||
| dateRecord.CommitDatasetSize = CommitDatasetSizeMap[dateRecord.ID] | |||
| } | |||
| dateRecord.CommitDatasetSize = getMapValue(dateRecord.ID, CommitDatasetSizeMap) | |||
| dateRecord.CommitDatasetNum = getMapValue(dateRecord.ID, CommitDatasetNumMap) | |||
| dateRecord.SolveIssueCount = getMapValue(dateRecord.ID, SolveIssueCountMap) | |||
| if _, ok := SolveIssueCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.SolveIssueCount = 0 | |||
| } else { | |||
| dateRecord.SolveIssueCount = SolveIssueCountMap[dateRecord.ID] | |||
| } | |||
| dateRecord.EncyclopediasCount = getMapKeyStringValue(dateRecord.Name, wikiCountMap) | |||
| if _, ok := wikiCountMap[dateRecord.Name]; !ok { | |||
| dateRecord.EncyclopediasCount = 0 | |||
| } else { | |||
| dateRecord.EncyclopediasCount = wikiCountMap[dateRecord.Name] | |||
| } | |||
| dateRecord.CreateRepoCount = getMapValue(dateRecord.ID, CreateRepoCountMap) | |||
| if _, ok := CreateRepoCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.CreateRepoCount = 0 | |||
| } else { | |||
| dateRecord.CreateRepoCount = CreateRepoCountMap[dateRecord.ID] | |||
| } | |||
| if _, ok := LoginCountMap[dateRecord.ID]; !ok { | |||
| dateRecord.LoginCount = 0 | |||
| } else { | |||
| dateRecord.LoginCount = LoginCountMap[dateRecord.ID] | |||
| } | |||
| dateRecord.LoginCount = getMapValue(dateRecord.ID, LoginCountMap) | |||
| if _, ok := OpenIIndexMap[dateRecord.ID]; !ok { | |||
| dateRecord.OpenIIndex = 0 | |||
| @@ -732,8 +684,17 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| dateRecord.OpenIIndex = OpenIIndexMap[dateRecord.ID] | |||
| } | |||
| dateRecord.CommitModelCount = 0 | |||
| dateRecord.CloudBrainTaskNum = getMapValue(dateRecord.ID, CloudBrainTaskMap) | |||
| dateRecord.GpuDebugJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_GpuDebugJob", CloudBrainTaskItemMap) | |||
| dateRecord.NpuDebugJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_NpuDebugJob", CloudBrainTaskItemMap) | |||
| dateRecord.GpuTrainJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_GpuTrainJob", CloudBrainTaskItemMap) | |||
| dateRecord.NpuTrainJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_NpuTrainJob", CloudBrainTaskItemMap) | |||
| dateRecord.NpuInferenceJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_NpuInferenceJob", CloudBrainTaskItemMap) | |||
| dateRecord.GpuBenchMarkJob = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_GpuBenchMarkJob", CloudBrainTaskItemMap) | |||
| dateRecord.CloudBrainRunTime = getMapKeyStringValue(fmt.Sprint(dateRecord.ID)+"_CloudBrainRunTime", CloudBrainTaskItemMap) | |||
| dateRecord.CommitModelCount = getMapValue(dateRecord.ID, AiModelManageMap) | |||
| dateRecord.UserIndex = getUserIndex(dateRecord, ParaWeight) | |||
| setUserMetrics(userMetrics, userRecord, start_unix, end_unix, dateRecord) | |||
| _, err = statictisSess.Insert(&dateRecord) | |||
| if err != nil { | |||
| log.Info("insert daterecord failed." + err.Error()) | |||
| @@ -747,11 +708,142 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| } | |||
| } | |||
| RefreshUserStaticAllTabel(wikiCountMap, CommitCodeSizeMap) | |||
| RefreshUserStaticAllTabel(wikiCountMap, userMetrics) | |||
| //insert userMetrics table | |||
| var useMetrics UserMetrics | |||
| useMetrics.CountDate = CountDate.Unix() | |||
| statictisSess.Delete(&useMetrics) | |||
| useMetrics.ActivateRegistUser = getMapKeyStringValue("ActivateRegistUser", userMetrics) | |||
| useMetrics.HasActivityUser = getMapKeyStringValue("HasActivityUser", userMetrics) | |||
| useMetrics.NotActivateRegistUser = getMapKeyStringValue("NotActivateRegistUser", userMetrics) | |||
| useMetrics.TotalActivateRegistUser = getMapKeyStringValue("TotalActivateRegistUser", userMetrics) | |||
| useMetrics.TotalHasActivityUser = getMapKeyStringValue("TotalHasActivityUser", userMetrics) | |||
| statictisSess.Insert(&useMetrics) | |||
| return nil | |||
| } | |||
| func setUserMetrics(userMetrics map[string]int, user *User, start_time int64, end_time int64, dateRecord UserBusinessAnalysis) { | |||
| //ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| //NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| //HasActivityUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| //TotalActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| //TotalHasActivityUser | |||
| regist_time := user.CreatedUnix.AsTime().Unix() | |||
| if regist_time >= start_time && regist_time <= end_time { | |||
| if user.IsActive { | |||
| userMetrics["ActivateRegistUser"] = getMapKeyStringValue("ActivateRegistUser", userMetrics) + 1 | |||
| } else { | |||
| userMetrics["NotActivateRegistUser"] = getMapKeyStringValue("NotActivateRegistUser", userMetrics) + 1 | |||
| } | |||
| } | |||
| if user.IsActive { | |||
| userMetrics["TotalActivateRegistUser"] = getMapKeyStringValue("TotalActivateRegistUser", userMetrics) + 1 | |||
| } | |||
| if dateRecord.UserIndex > 0 || dateRecord.LoginCount > 0 { | |||
| userMetrics["HasActivityUser"] = getMapKeyStringValue("HasActivityUser", userMetrics) + 1 | |||
| } | |||
| } | |||
| func getParaWeight() map[string]float64 { | |||
| result := make(map[string]float64) | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| statictisSess.Select("*").Table(new(UserAnalysisPara)) | |||
| paraList := make([]*UserAnalysisPara, 0) | |||
| statictisSess.Find(¶List) | |||
| for _, paraRecord := range paraList { | |||
| result[paraRecord.Key] = paraRecord.Value | |||
| } | |||
| return result | |||
| } | |||
| func getUserIndexFromAnalysisAll(dateRecord UserBusinessAnalysisAll, ParaWeight map[string]float64) float64 { | |||
| var result float64 | |||
| // PR数 0.20 | |||
| // commit数 0.20 | |||
| // 提出任务数 0.20 | |||
| // 评论数 0.20 | |||
| // 关注项目数 0.10 | |||
| // 点赞项目数 0.10 | |||
| // 登录次数 0.10 | |||
| result = float64(dateRecord.CodeMergeCount) * getParaWeightValue("CodeMergeCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.CommitCount) * getParaWeightValue("CommitCount", ParaWeight, 0.2) | |||
| log.Info("1 result=" + fmt.Sprint(result)) | |||
| result += float64(dateRecord.IssueCount) * getParaWeightValue("IssueCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.CommentCount) * getParaWeightValue("CommentCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.FocusRepoCount) * getParaWeightValue("FocusRepoCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.StarRepoCount) * getParaWeightValue("StarRepoCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.LoginCount) * getParaWeightValue("LoginCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.WatchedCount) * getParaWeightValue("WatchedCount", ParaWeight, 0.3) | |||
| result += float64(dateRecord.CommitCodeSize) * getParaWeightValue("CommitCodeSize", ParaWeight, 0.1) | |||
| result += float64(dateRecord.SolveIssueCount) * getParaWeightValue("SolveIssueCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.EncyclopediasCount) * getParaWeightValue("EncyclopediasCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.CreateRepoCount) * getParaWeightValue("CreateRepoCount", ParaWeight, 0.05) | |||
| result += float64(dateRecord.CloudBrainTaskNum) * getParaWeightValue("CloudBrainTaskNum", ParaWeight, 0.3) | |||
| result += float64(dateRecord.CommitModelCount) * getParaWeightValue("CommitModelCount", ParaWeight, 0.2) | |||
| result += dateRecord.OpenIIndex * getParaWeightValue("OpenIIndex", ParaWeight, 0.1) | |||
| return result | |||
| } | |||
| func getUserIndex(dateRecord UserBusinessAnalysis, ParaWeight map[string]float64) float64 { | |||
| var result float64 | |||
| // PR数 0.20 | |||
| // commit数 0.20 | |||
| // 提出任务数 0.20 | |||
| // 评论数 0.20 | |||
| // 关注项目数 0.10 | |||
| // 点赞项目数 0.10 | |||
| // 登录次数 0.10 | |||
| result = float64(dateRecord.CodeMergeCount) * getParaWeightValue("CodeMergeCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.CommitCount) * getParaWeightValue("CommitCount", ParaWeight, 0.2) | |||
| log.Info("2 result=" + fmt.Sprint(result)) | |||
| result += float64(dateRecord.IssueCount) * getParaWeightValue("IssueCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.CommentCount) * getParaWeightValue("CommentCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.FocusRepoCount) * getParaWeightValue("FocusRepoCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.StarRepoCount) * getParaWeightValue("StarRepoCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.LoginCount) * getParaWeightValue("LoginCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.WatchedCount) * getParaWeightValue("WatchedCount", ParaWeight, 0.3) | |||
| result += float64(dateRecord.CommitCodeSize) * getParaWeightValue("CommitCodeSize", ParaWeight, 0.1) | |||
| result += float64(dateRecord.SolveIssueCount) * getParaWeightValue("SolveIssueCount", ParaWeight, 0.2) | |||
| result += float64(dateRecord.EncyclopediasCount) * getParaWeightValue("EncyclopediasCount", ParaWeight, 0.1) | |||
| result += float64(dateRecord.CreateRepoCount) * getParaWeightValue("CreateRepoCount", ParaWeight, 0.05) | |||
| result += float64(dateRecord.CloudBrainTaskNum) * getParaWeightValue("CloudBrainTaskNum", ParaWeight, 0.3) | |||
| result += float64(dateRecord.CommitModelCount) * getParaWeightValue("CommitModelCount", ParaWeight, 0.2) | |||
| result += dateRecord.OpenIIndex * getParaWeightValue("OpenIIndex", ParaWeight, 0.1) | |||
| return result | |||
| } | |||
| func getParaWeightValue(key string, valueMap map[string]float64, defaultValue float64) float64 { | |||
| if _, ok := valueMap[key]; !ok { | |||
| return defaultValue | |||
| } else { | |||
| return valueMap[key] | |||
| } | |||
| } | |||
| func getMapKeyStringValue(key string, valueMap map[string]int) int { | |||
| if _, ok := valueMap[key]; !ok { | |||
| return 0 | |||
| } else { | |||
| return valueMap[key] | |||
| } | |||
| } | |||
| func getMapValue(userId int64, valueMap map[int64]int) int { | |||
| if _, ok := valueMap[userId]; !ok { | |||
| return 0 | |||
| } else { | |||
| return valueMap[userId] | |||
| } | |||
| } | |||
| func getInt(str string) int { | |||
| re, err := strconv.ParseInt(str, 10, 32) | |||
| if err != nil { | |||
| @@ -1052,16 +1144,17 @@ func queryFollow(start_unix int64, end_unix int64) map[int64]int { | |||
| return resultMap | |||
| } | |||
| func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||
| func queryDatasetSize(start_unix int64, end_unix int64) (map[int64]int, map[int64]int) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| resultMap := make(map[int64]int) | |||
| resultSizeMap := make(map[int64]int) | |||
| resultNumMap := make(map[int64]int) | |||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||
| count, err := sess.Where(cond).Count(new(Attachment)) | |||
| if err != nil { | |||
| log.Info("query attachment error. return.") | |||
| return resultMap | |||
| return resultSizeMap, resultNumMap | |||
| } | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| @@ -1072,10 +1165,12 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||
| log.Info("query Attachment size=" + fmt.Sprint(len(attachmentList))) | |||
| for _, attachRecord := range attachmentList { | |||
| if _, ok := resultMap[attachRecord.UploaderID]; !ok { | |||
| resultMap[attachRecord.UploaderID] = int(attachRecord.Size / (1024 * 1024)) //MB | |||
| if _, ok := resultSizeMap[attachRecord.UploaderID]; !ok { | |||
| resultSizeMap[attachRecord.UploaderID] = int(attachRecord.Size / (1024 * 1024)) //MB | |||
| resultNumMap[attachRecord.UploaderID] = 1 | |||
| } else { | |||
| resultMap[attachRecord.UploaderID] += int(attachRecord.Size / (1024 * 1024)) //MB | |||
| resultSizeMap[attachRecord.UploaderID] += int(attachRecord.Size / (1024 * 1024)) //MB | |||
| resultNumMap[attachRecord.UploaderID] += 1 | |||
| } | |||
| } | |||
| @@ -1085,7 +1180,7 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||
| } | |||
| } | |||
| return resultMap | |||
| return resultSizeMap, resultNumMap | |||
| } | |||
| func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||
| @@ -1212,6 +1307,133 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { | |||
| return resultMap | |||
| } | |||
| func queryCommitCodeSize(start_unix int64, end_unix int64) map[int64]int { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| resultMap := make(map[int64]int) | |||
| cond := "count_date>=" + fmt.Sprint(start_unix) + " and count_date<=" + fmt.Sprint(end_unix) | |||
| count, err := statictisSess.Where(cond).Count(new(UserBusinessAnalysis)) | |||
| if err != nil { | |||
| log.Info("query commit code size error. return.") | |||
| return resultMap | |||
| } | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| statictisSess.Select("id,commit_code_size").Table("user_business_analysis").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||
| userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0) | |||
| statictisSess.Find(&userBusinessAnalysisList) | |||
| log.Info("query user login size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| for _, analysisRecord := range userBusinessAnalysisList { | |||
| if _, ok := resultMap[analysisRecord.ID]; !ok { | |||
| resultMap[analysisRecord.ID] = analysisRecord.CommitCodeSize | |||
| } else { | |||
| resultMap[analysisRecord.ID] += analysisRecord.CommitCodeSize | |||
| } | |||
| } | |||
| indexTotal += PAGE_SIZE | |||
| if indexTotal >= count { | |||
| break | |||
| } | |||
| } | |||
| log.Info("user commit code size=" + fmt.Sprint(len(resultMap))) | |||
| return resultMap | |||
| } | |||
| func queryUserModel(start_unix int64, end_unix int64) map[int64]int { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| resultMap := make(map[int64]int) | |||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||
| count, err := sess.Where(cond).Count(new(AiModelManage)) | |||
| if err != nil { | |||
| log.Info("query AiModelManage error. return.") | |||
| return resultMap | |||
| } | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,user_id").Table("ai_model_manage").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||
| aiModelList := make([]*AiModelManage, 0) | |||
| sess.Find(&aiModelList) | |||
| log.Info("query AiModelManage size=" + fmt.Sprint(len(aiModelList))) | |||
| for _, aiModelRecord := range aiModelList { | |||
| if _, ok := resultMap[aiModelRecord.UserId]; !ok { | |||
| resultMap[aiModelRecord.UserId] = 1 | |||
| } else { | |||
| resultMap[aiModelRecord.UserId] += 1 | |||
| } | |||
| } | |||
| indexTotal += PAGE_SIZE | |||
| if indexTotal >= count { | |||
| break | |||
| } | |||
| } | |||
| return resultMap | |||
| } | |||
| func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[string]int) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| resultMap := make(map[int64]int) | |||
| resultItemMap := make(map[string]int) | |||
| cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) | |||
| count, err := sess.Where(cond).Count(new(Cloudbrain)) | |||
| if err != nil { | |||
| log.Info("query cloudbrain error. return.") | |||
| return resultMap, resultItemMap | |||
| } | |||
| var indexTotal int64 | |||
| indexTotal = 0 | |||
| for { | |||
| sess.Select("id,job_type,user_id,duration,train_job_duration,type").Table("cloudbrain").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||
| cloudTaskList := make([]*Cloudbrain, 0) | |||
| sess.Find(&cloudTaskList) | |||
| log.Info("query cloudbrain size=" + fmt.Sprint(len(cloudTaskList))) | |||
| for _, cloudTaskRecord := range cloudTaskList { | |||
| if _, ok := resultMap[cloudTaskRecord.UserID]; !ok { | |||
| resultMap[cloudTaskRecord.UserID] = 1 | |||
| } else { | |||
| resultMap[cloudTaskRecord.UserID] += 1 | |||
| } | |||
| setMapKey("CloudBrainRunTime", cloudTaskRecord.UserID, int(cloudTaskRecord.Duration), resultItemMap) | |||
| if cloudTaskRecord.Type == 1 { //npu | |||
| if cloudTaskRecord.JobType == "TRAIN" { | |||
| setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } else if cloudTaskRecord.JobType == "INFERENCE" { | |||
| setMapKey("NpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } else { | |||
| setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } | |||
| } else { //type=0 gpu | |||
| if cloudTaskRecord.JobType == "TRAIN" { | |||
| setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } else if cloudTaskRecord.JobType == "BENCHMARK" { | |||
| setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } else { | |||
| setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap) | |||
| } | |||
| } | |||
| } | |||
| indexTotal += PAGE_SIZE | |||
| if indexTotal >= count { | |||
| break | |||
| } | |||
| } | |||
| return resultMap, resultItemMap | |||
| } | |||
| func setMapKey(key string, userId int64, value int, resultItemMap map[string]int) { | |||
| newKey := fmt.Sprint(userId) + "_" + key | |||
| if _, ok := resultItemMap[newKey]; !ok { | |||
| resultItemMap[newKey] = value | |||
| } else { | |||
| resultItemMap[newKey] += value | |||
| } | |||
| } | |||
| func subMonth(t1, t2 time.Time) (month int) { | |||
| y1 := t1.Year() | |||
| y2 := t2.Year() | |||
| @@ -44,6 +44,18 @@ type UserBusinessAnalysisCurrentYear struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisLast30Day struct { | |||
| @@ -88,6 +100,18 @@ type UserBusinessAnalysisLast30Day struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisLastMonth struct { | |||
| @@ -132,6 +156,18 @@ type UserBusinessAnalysisLastMonth struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisCurrentMonth struct { | |||
| @@ -176,6 +212,18 @@ type UserBusinessAnalysisCurrentMonth struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisCurrentWeek struct { | |||
| @@ -220,6 +268,18 @@ type UserBusinessAnalysisCurrentWeek struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysisYesterday struct { | |||
| @@ -264,4 +324,30 @@ type UserBusinessAnalysisYesterday struct { | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| CloudBrainTaskNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuDebugJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuTrainJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| NpuInferenceJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| GpuBenchMarkJob int `xorm:"NOT NULL DEFAULT 0"` | |||
| CloudBrainRunTime int `xorm:"NOT NULL DEFAULT 0"` | |||
| CommitDatasetNum int `xorm:"NOT NULL DEFAULT 0"` | |||
| UserIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| UserLocation string `xorm:"NULL"` | |||
| } | |||
| type UserAnalysisPara struct { | |||
| Key string `xorm:"NOT NULL"` | |||
| Value float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| } | |||
| type UserMetrics struct { | |||
| CountDate int64 `xorm:"pk"` | |||
| ActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| NotActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| HasActivityUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| TotalActivateRegistUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| TotalHasActivityUser int `xorm:"NOT NULL DEFAULT 0"` | |||
| } | |||
| @@ -185,6 +185,17 @@ func registerHandleSummaryStatistic() { | |||
| }) | |||
| } | |||
| func registerHandleOrgStatistic() { | |||
| RegisterTaskFatal("handle_org_statistic", &BaseConfig{ | |||
| Enabled: true, | |||
| RunAtStart: false, | |||
| Schedule: "0 0 2 * * ?", | |||
| }, func(ctx context.Context, _ *models.User, _ Config) error { | |||
| models.UpdateOrgStatistics() | |||
| return nil | |||
| }) | |||
| } | |||
| func registerSyncCloudbrainStatus() { | |||
| RegisterTaskFatal("sync_cloudbrain_status", &BaseConfig{ | |||
| Enabled: true, | |||
| @@ -215,4 +226,5 @@ func initBasicTasks() { | |||
| registerHandleSummaryStatistic() | |||
| registerSyncCloudbrainStatus() | |||
| registerHandleOrgStatistic() | |||
| } | |||
| @@ -280,6 +280,7 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| JobID: jobResult.ID, | |||
| JobName: jobName, | |||
| FlavorCode: flavor, | |||
| DisplayJobName: displayJobName, | |||
| JobType: string(models.JobTypeDebug), | |||
| Type: models.TypeCloudBrainTwo, | |||
| @@ -40,6 +40,7 @@ var ( | |||
| DisabledRepoUnits []string | |||
| DefaultRepoUnits []string | |||
| PrefixArchiveFiles bool | |||
| RepoMaxSize int64 | |||
| // Repository editor settings | |||
| Editor struct { | |||
| @@ -54,6 +55,7 @@ var ( | |||
| AllowedTypes []string `delim:"|"` | |||
| FileMaxSize int64 | |||
| MaxFiles int | |||
| TotalMaxSize int64 | |||
| } `ini:"-"` | |||
| // Repository local settings | |||
| @@ -104,6 +106,7 @@ var ( | |||
| DisabledRepoUnits: []string{}, | |||
| DefaultRepoUnits: []string{}, | |||
| PrefixArchiveFiles: true, | |||
| RepoMaxSize: 1024, | |||
| // Repository editor settings | |||
| Editor: struct { | |||
| @@ -121,12 +124,14 @@ var ( | |||
| AllowedTypes []string `delim:"|"` | |||
| FileMaxSize int64 | |||
| MaxFiles int | |||
| TotalMaxSize int64 | |||
| }{ | |||
| Enabled: true, | |||
| TempPath: "data/tmp/uploads", | |||
| AllowedTypes: []string{}, | |||
| FileMaxSize: 3, | |||
| MaxFiles: 5, | |||
| FileMaxSize: 30, | |||
| MaxFiles: 10, | |||
| TotalMaxSize: 1024, | |||
| }, | |||
| // Repository local settings | |||
| @@ -493,6 +493,11 @@ static.encyclopediascount=Encyclopedias Count | |||
| static.createrepocount=Create Repo Count | |||
| static.openiindex=OpenI Index | |||
| static.registdate=Regist Date | |||
| static.CloudBrainTaskNum=CloudBrain Task Count | |||
| static.CloudBrainRunTime=CloudBrain Run Time | |||
| static.CommitDatasetNum=Commit Dataset Count | |||
| static.CommitModelCount=Commit Model Count | |||
| static.UserIndex=User Index | |||
| static.countdate=Count Date | |||
| static.all=All | |||
| static.public.user_business_analysis_current_month=Current_Month | |||
| @@ -911,7 +916,13 @@ language_other = Other | |||
| datasets = Datasets | |||
| datasets.desc = Enable Dataset | |||
| cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. | |||
| cloudbrain.exitinfo=Exit Information | |||
| cloudbrain.platform=Platform | |||
| cloudbrain.endtime=End Time | |||
| cloudbrain.runinfo=Task Runtime Information | |||
| cloudbrain.time.starttime=Start run time | |||
| cloudbrain.time.endtime=End run time | |||
| cloudbrain.datasetdownload=Dataset download url | |||
| model_manager = Model | |||
| model_noright=No right | |||
| model_rename=Duplicate model name, please modify model name. | |||
| @@ -1250,6 +1261,10 @@ editor.cannot_commit_to_protected_branch = Cannot commit to protected branch '%s | |||
| editor.no_commit_to_branch = Unable to commit directly to branch because: | |||
| editor.user_no_push_to_branch = User cannot push to branch | |||
| editor.require_signed_commit = Branch requires a signed commit | |||
| editor.repo_too_large = Repository can not exceed %d MB | |||
| editor.repo_file_invalid = Upload files are invalid | |||
| editor.upload_file_too_much = Can not upload more than %d files at a time | |||
| commits.desc = Browse source code change history. | |||
| commits.commits = Commits | |||
| @@ -2192,6 +2207,16 @@ customize = Customize | |||
| selected_project=Selected Projects | |||
| fold = Fold | |||
| unfold = Unfold | |||
| org_member = Member | |||
| org_members = Members | |||
| org_team = Team | |||
| org_teams = Teams | |||
| org_repository = Repository | |||
| org_repositories = Repositories | |||
| star = Star Top10 | |||
| member = Members Top10 | |||
| active = Active Top10 | |||
| form.name_reserved = The organization name '%s' is reserved. | |||
| form.name_pattern_not_allowed = The pattern '%s' is not allowed in an organization name. | |||
| @@ -2847,6 +2872,8 @@ uploading = Uploading | |||
| upload_complete = Uploading complete | |||
| failed = Upload Failed | |||
| enable_minio_support = Enable minio support to use the dataset service | |||
| max_file_tooltips= Upload a maximum of ? files at a time, each file does not exceed ? MB. | |||
| max_size_tooltips= You can only upload a maximum of ? files at a time. The upload limit has been reached, please do not add more files. | |||
| [notification] | |||
| notifications = Notifications | |||
| @@ -496,6 +496,11 @@ static.encyclopediascount=百科页面贡献次数 | |||
| static.createrepocount=创建项目数 | |||
| static.openiindex=OpenI指数 | |||
| static.registdate=用户注册时间 | |||
| static.CloudBrainTaskNum=云脑任务数 | |||
| static.CloudBrainRunTime=云脑运行时间(小时) | |||
| static.CommitDatasetNum=上传(提交)数据集文件数 | |||
| static.CommitModelCount=提交模型数 | |||
| static.UserIndex=用户指数 | |||
| static.countdate=系统统计时间 | |||
| static.all=所有 | |||
| static.public.user_business_analysis_current_month=本月 | |||
| @@ -959,7 +964,13 @@ cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字 | |||
| cloudbrain_query_fail=查询云脑任务失败。 | |||
| cloudbrain.mirror_tag = 镜像标签 | |||
| cloudbrain.mirror_description = 镜像描述 | |||
| cloudbrain.exitinfo=退出信息 | |||
| cloudbrain.platform=平台 | |||
| cloudbrain.endtime=结束时间 | |||
| cloudbrain.runinfo=任务运行简况 | |||
| cloudbrain.time.starttime=开始运行时间 | |||
| cloudbrain.time.endtime=结束运行时间 | |||
| cloudbrain.datasetdownload=数据集下载地址 | |||
| record_begintime_get_err=无法获取统计开始时间。 | |||
| parameter_is_wrong=输入参数错误,请检查输入参数。 | |||
| total_count_get_error=查询总页数失败。 | |||
| @@ -1257,6 +1268,9 @@ editor.cannot_commit_to_protected_branch=不可以提交到受保护的分支 '% | |||
| editor.no_commit_to_branch=无法直接提交分支,因为: | |||
| editor.user_no_push_to_branch=用户不能推送到分支 | |||
| editor.require_signed_commit=分支需要签名提交 | |||
| editor.repo_too_large = 代码仓总大小不能超过%dMB | |||
| editor.repo_file_invalid = 提交的文件非法 | |||
| editor.upload_file_too_much = 不能同时提交超过%d个文件 | |||
| commits.desc=浏览代码修改历史 | |||
| commits.commits=次代码提交 | |||
| @@ -2197,6 +2211,16 @@ customize = 自定义 | |||
| selected_project=精选项目 | |||
| fold = 收起 | |||
| unfold = 展开 | |||
| org_member = 成员 | |||
| org_members = 成员 | |||
| org_team = 团队 | |||
| org_teams = 团队 | |||
| org_repository = 项目 | |||
| org_repositories = 项目 | |||
| star = 点赞榜 | |||
| member = 成员榜 | |||
| active = 活跃榜 | |||
| form.name_reserved=组织名称 '%s' 是被保留的。 | |||
| form.name_pattern_not_allowed=组织名称中不允许使用 "%s"。 | |||
| @@ -2853,6 +2877,8 @@ uploading=正在上传 | |||
| upload_complete=上传完成 | |||
| failed=上传失败 | |||
| enable_minio_support=启用minio支持以使用数据集服务 | |||
| max_file_tooltips=单次最多上传?个文件,每个文件不超过? MB。 | |||
| max_size_tooltips=一次最多只能上传?个文件, 上传已达到上限,请勿再添加文件。 | |||
| [notification] | |||
| notifications=通知 | |||
| @@ -108,8 +108,9 @@ function searchItem(type,sortType){ | |||
| currentSearchSortBy = sortBy[sortType]; | |||
| currentSearchAscending = sortAscending[sortType]; | |||
| OnlySearchLabel =false; | |||
| page(currentPage); | |||
| }else{ | |||
| emptySearch(); | |||
| } | |||
| } | |||
| @@ -121,49 +122,31 @@ function search(){ | |||
| if(!isEmpty(currentSearchKeyword)){ | |||
| currentSearchKeyword = currentSearchKeyword.trim(); | |||
| } | |||
| $('#searchForm').addClass("hiddenSearch"); | |||
| initPageInfo(); | |||
| if(!isEmpty(currentSearchKeyword)){ | |||
| document.getElementById("find_id").innerHTML=getLabel(isZh,"search_finded"); | |||
| currentSearchSortBy = sortBy[10]; | |||
| currentSearchAscending = "false"; | |||
| OnlySearchLabel =false; | |||
| page(currentPage); | |||
| if(currentSearchTableName != "repository"){ | |||
| doSearch("repository",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "issue"){ | |||
| doSearch("issue",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "user"){ | |||
| doSearch("user",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "org"){ | |||
| doSearch("org",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "dataset"){ | |||
| doSearch("dataset",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "pr"){ | |||
| doSearch("pr",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| doSpcifySearch(currentSearchTableName,currentSearchKeyword,sortBy[10],"false"); | |||
| }else{ | |||
| initDiv(false); | |||
| document.getElementById("find_id").innerHTML=getLabel(isZh,"search_empty"); | |||
| $('#find_title').html(""); | |||
| document.getElementById("sort_type").innerHTML=""; | |||
| document.getElementById("child_search_item").innerHTML=""; | |||
| document.getElementById("page_menu").innerHTML=""; | |||
| $('#repo_total').text(""); | |||
| $('#pr_total').text(""); | |||
| $('#issue_total').text(""); | |||
| $('#dataset_total').text(""); | |||
| $('#user_total').text(""); | |||
| $('#org_total').text(""); | |||
| setActivate(null); | |||
| emptySearch(); | |||
| } | |||
| } | |||
| function emptySearch(){ | |||
| initDiv(false); | |||
| initPageInfo(); | |||
| $('#searchForm').addClass("hiddenSearch"); | |||
| document.getElementById("find_id").innerHTML=getLabel(isZh,"search_empty"); | |||
| $('#find_title').html(""); | |||
| document.getElementById("sort_type").innerHTML=""; | |||
| document.getElementById("child_search_item").innerHTML=""; | |||
| document.getElementById("page_menu").innerHTML=""; | |||
| $('#repo_total').text(""); | |||
| $('#pr_total').text(""); | |||
| $('#issue_total').text(""); | |||
| $('#dataset_total').text(""); | |||
| $('#user_total').text(""); | |||
| $('#org_total').text(""); | |||
| setActivate(null); | |||
| } | |||
| function initDiv(isSearchLabel=false){ | |||
| if(isSearchLabel){ | |||
| document.getElementById("search_div").style.display="none"; | |||
| @@ -174,7 +157,6 @@ function initDiv(isSearchLabel=false){ | |||
| document.getElementById("user_item").style.display="none"; | |||
| document.getElementById("org_item").style.display="none"; | |||
| document.getElementById("find_id").innerHTML=""; | |||
| }else{ | |||
| document.getElementById("search_div").style.display="block"; | |||
| document.getElementById("search_label_div").style.display="none"; | |||
| @@ -187,6 +169,39 @@ function initDiv(isSearchLabel=false){ | |||
| } | |||
| } | |||
| function doSpcifySearch(tableName,keyword,sortBy="",ascending="false"){ | |||
| initDiv(false); | |||
| $('#searchForm').addClass("hiddenSearch"); | |||
| document.getElementById("find_id").innerHTML=getLabel(isZh,"search_finded"); | |||
| currentSearchKeyword = keyword; | |||
| initPageInfo(); | |||
| currentSearchTableName = tableName; | |||
| currentSearchSortBy = sortBy; | |||
| currentSearchAscending = ascending; | |||
| OnlySearchLabel =false; | |||
| page(currentPage); | |||
| if(currentSearchTableName != "repository"){ | |||
| doSearch("repository",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "issue"){ | |||
| doSearch("issue",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "user"){ | |||
| doSearch("user",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "org"){ | |||
| doSearch("org",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "dataset"){ | |||
| doSearch("dataset",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| if(currentSearchTableName != "pr"){ | |||
| doSearch("pr",currentSearchKeyword,1,pageSize,true,"",false); | |||
| } | |||
| } | |||
| function doSearchLabel(tableName,keyword,sortBy="",ascending="false"){ | |||
| initDiv(true); | |||
| //document.getElementById("search_div").style.display="none"; | |||
| @@ -1272,8 +1287,17 @@ var zhCN={ | |||
| sessionStorage.removeItem("searchLabel"); | |||
| doSearchLabel(sessionStorage.getItem("tableName"),sessionStorage.getItem("keyword"),sessionStorage.getItem("sortBy"),sessionStorage.getItem("ascending")); | |||
| }else{ | |||
| console.log("normal search...."); | |||
| search(); | |||
| var specifySearch = sessionStorage.getItem("specifySearch"); | |||
| if(specifySearch){ | |||
| sessionStorage.removeItem("specifySearch"); | |||
| console.log("search sepcial keyword=...." + sessionStorage.getItem("keyword")); | |||
| document.getElementById("keyword_input").value = sessionStorage.getItem("keyword"); | |||
| doSpcifySearch(sessionStorage.getItem("tableName"),sessionStorage.getItem("keyword"),sessionStorage.getItem("sortBy"),sessionStorage.getItem("ascending")); | |||
| }else{ | |||
| console.log("normal search...."); | |||
| search(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -547,6 +547,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }) | |||
| }, operationReq) | |||
| m.Get("/query_user_metrics", operationReq, repo_ext.QueryMetrics) | |||
| m.Get("/query_user_rank_list", operationReq, repo_ext.QueryRankingList) | |||
| m.Get("/query_user_static_page", operationReq, repo_ext.QueryUserStaticDataPage) | |||
| m.Get("/query_user_current_month", operationReq, repo_ext.QueryUserStaticCurrentMonth) | |||
| m.Get("/query_user_current_week", operationReq, repo_ext.QueryUserStaticCurrentWeek) | |||
| @@ -49,7 +49,7 @@ func Home(ctx *context.Context) { | |||
| ctx.HTML(200, tplHome) | |||
| } | |||
| func setRecommendURL(ctx *context.Context) { | |||
| func setRecommendURLOnly(ctx *context.Context) { | |||
| addr := setting.RecommentRepoAddr[10:] | |||
| start := strings.Index(addr, "/") | |||
| end := strings.Index(addr, "raw") | |||
| @@ -58,7 +58,10 @@ func setRecommendURL(ctx *context.Context) { | |||
| } else { | |||
| ctx.Data["RecommendURL"] = setting.RecommentRepoAddr | |||
| } | |||
| } | |||
| func setRecommendURL(ctx *context.Context) { | |||
| setRecommendURLOnly(ctx) | |||
| ctx.Data["page_title"] = ctx.Tr("home.page_title") | |||
| ctx.Data["page_small_title"] = ctx.Tr("home.page_small_title") | |||
| ctx.Data["page_description"] = ctx.Tr("home.page_description") | |||
| @@ -441,17 +444,39 @@ func ExploreOrganizations(ctx *context.Context) { | |||
| ctx.Data["PageIsExploreOrganizations"] = true | |||
| ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | |||
| visibleTypes := []structs.VisibleType{structs.VisibleTypePublic} | |||
| if ctx.User != nil { | |||
| visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate) | |||
| N := 10 | |||
| starInfo, err := models.FindTopNStarsOrgs(N) | |||
| if err != nil { | |||
| log.Error("GetStarOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| ctx.ServerError("GetStarOrgInfos", err) | |||
| return | |||
| } | |||
| memberInfo, err := models.FindTopNMembersOrgs(N) | |||
| if err != nil { | |||
| log.Error("GetMemberOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| ctx.ServerError("GetMemberOrgInfos", err) | |||
| return | |||
| } | |||
| openIInfo, err := models.FindTopNOpenIOrgs(N) | |||
| if err != nil { | |||
| log.Error("GetOpenIOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| ctx.ServerError("GetOpenIOrgInfos", err) | |||
| return | |||
| } | |||
| RenderUserSearch(ctx, &models.SearchUserOptions{ | |||
| Actor: ctx.User, | |||
| Type: models.UserTypeOrganization, | |||
| ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, | |||
| Visible: visibleTypes, | |||
| }, tplExploreOrganizations) | |||
| recommendOrgs, err := GetRecommendOrg() | |||
| if err != nil { | |||
| log.Error("GetRecommendOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| ctx.ServerError("GetRecommendOrgInfos", err) | |||
| return | |||
| } | |||
| setRecommendURLOnly(ctx) | |||
| ctx.Data["RecommendOrgs"] = recommendOrgs | |||
| ctx.Data["StarOrgs"] = starInfo | |||
| ctx.Data["MemberOrgs"] = memberInfo | |||
| ctx.Data["ActiveOrgs"] = openIInfo | |||
| ctx.HTML(http.StatusOK, tplExploreOrganizations) | |||
| } | |||
| // ExploreCode render explore code page | |||
| @@ -583,12 +608,12 @@ func NotFound(ctx *context.Context) { | |||
| ctx.NotFound("home.NotFound", nil) | |||
| } | |||
| func RecommendOrgFromPromote(ctx *context.Context) { | |||
| func GetRecommendOrg() ([]map[string]interface{}, error) { | |||
| url := setting.RecommentRepoAddr + "organizations" | |||
| result, err := repository.RecommendFromPromote(url) | |||
| if err != nil { | |||
| ctx.ServerError("500", err) | |||
| return | |||
| return nil, err | |||
| } | |||
| resultOrg := make([]map[string]interface{}, 0) | |||
| for _, userName := range result { | |||
| @@ -598,6 +623,7 @@ func RecommendOrgFromPromote(ctx *context.Context) { | |||
| userMap["Name"] = user.Name | |||
| userMap["Description"] = user.Description | |||
| userMap["FullName"] = user.FullName | |||
| userMap["HomeLink"] = user.HomeLink() | |||
| userMap["ID"] = user.ID | |||
| userMap["Avatar"] = user.RelAvatarLink() | |||
| userMap["NumRepos"] = user.NumRepos | |||
| @@ -608,7 +634,15 @@ func RecommendOrgFromPromote(ctx *context.Context) { | |||
| log.Info("query user error," + err.Error()) | |||
| } | |||
| } | |||
| return resultOrg, nil | |||
| } | |||
| func RecommendOrgFromPromote(ctx *context.Context) { | |||
| resultOrg, err := GetRecommendOrg() | |||
| if err != nil { | |||
| ctx.ServerError("500", err) | |||
| return | |||
| } | |||
| ctx.JSON(200, resultOrg) | |||
| } | |||
| @@ -45,6 +45,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | |||
| m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
| m.Post("/tool/repo_stat/:date", RepoStatisticManually) | |||
| m.Get("/tool/org_stat", OrgStatisticManually) | |||
| m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | |||
| m.Post("/task/history_handle/duration", repo.HandleTaskWithNoDuration) | |||
| @@ -45,6 +45,10 @@ func RepoStatisticManually(ctx *macaron.Context) { | |||
| repo.TimingCountDataByDate(date) | |||
| } | |||
| func OrgStatisticManually() { | |||
| models.UpdateOrgStatistics() | |||
| } | |||
| func UpdateRepoVisit(ctx *macaron.Context) { | |||
| date := ctx.Params("date") | |||
| log.Info("date(%s)", date) | |||
| @@ -2,11 +2,9 @@ package repo | |||
| import ( | |||
| "bufio" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "github.com/unknwon/i18n" | |||
| "io" | |||
| "net/http" | |||
| "os" | |||
| @@ -16,6 +14,9 @@ import ( | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "github.com/unknwon/i18n" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/base" | |||
| @@ -345,6 +346,24 @@ func CloudBrainRestart(ctx *context.Context) { | |||
| break | |||
| } | |||
| var hasSameResource bool | |||
| if gpuInfos == nil { | |||
| json.Unmarshal([]byte(setting.GpuTypes), &gpuInfos) | |||
| } | |||
| for _, resourceType := range gpuInfos.GpuInfo { | |||
| if resourceType.Queue == task.GpuQueue { | |||
| hasSameResource = true | |||
| continue | |||
| } | |||
| } | |||
| if !hasSameResource { | |||
| log.Error("has no same resource, can not restart", ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "the job's version is too old and can not be restarted" | |||
| break | |||
| } | |||
| count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, string(models.JobTypeDebug)) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| @@ -400,18 +419,34 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| if jobType == models.JobTypeTrain { | |||
| task, err = models.GetCloudbrainByJobID(ctx.Params(":jobid")) | |||
| } else { | |||
| task, err = models.GetCloudbrainByID(ctx.Params(":id")) | |||
| task, err = models.GetCloudbrainByIDWithDeleted(ctx.Params(":id")) | |||
| } | |||
| if err != nil { | |||
| log.Info("error:" + err.Error()) | |||
| ctx.Data["error"] = err.Error() | |||
| return | |||
| } | |||
| result, err := cloudbrain.GetJob(task.JobID) | |||
| if err != nil { | |||
| log.Info("error:" + err.Error()) | |||
| ctx.Data["error"] = err.Error() | |||
| return | |||
| } | |||
| if cloudbrain.ResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &cloudbrain.ResourceSpecs) | |||
| } | |||
| for _, tmp := range cloudbrain.ResourceSpecs.ResourceSpec { | |||
| if tmp.Id == task.ResourceSpecId { | |||
| ctx.Data["GpuNum"] = tmp.GpuNum | |||
| ctx.Data["CpuNum"] = tmp.CpuNum | |||
| ctx.Data["MemMiB"] = tmp.MemMiB | |||
| ctx.Data["ShareMemMiB"] = tmp.ShareMemMiB | |||
| } | |||
| } | |||
| if result != nil { | |||
| jobRes, _ := models.ConvertToJobResultPayload(result.Payload) | |||
| jobRes.Resource.Memory = strings.ReplaceAll(jobRes.Resource.Memory, "Mi", "MB") | |||
| @@ -426,6 +461,15 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| ctx.Data["resource_type"] = resourceType.Value | |||
| } | |||
| } | |||
| } else { | |||
| if gpuInfos == nil { | |||
| json.Unmarshal([]byte(setting.GpuTypes), &gpuInfos) | |||
| } | |||
| for _, resourceType := range gpuInfos.GpuInfo { | |||
| if resourceType.Queue == jobRes.Config.GpuType { | |||
| ctx.Data["resource_type"] = resourceType.Value | |||
| } | |||
| } | |||
| } | |||
| taskRoles := jobRes.TaskRoles | |||
| if jobRes.JobStatus.State != string(models.JobFailed) { | |||
| @@ -436,9 +480,15 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| task.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
| task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
| models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| if task.DeletedAt.IsZero() { //normal record | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| return | |||
| } | |||
| } else { //deleted record | |||
| } | |||
| } else { | |||
| task.Status = jobRes.JobStatus.State | |||
| @@ -455,7 +505,9 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| ctx.Data["result"] = jobRes | |||
| } else { | |||
| log.Info("error:" + err.Error()) | |||
| return | |||
| } | |||
| user, err := models.GetUserByID(task.UserID) | |||
| if err == nil { | |||
| task.User = user | |||
| @@ -510,6 +562,12 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| } | |||
| } | |||
| attachment, err := models.GetAttachmentByUUID(task.Uuid) | |||
| if err == nil { | |||
| ctx.Data["datasetname"] = attachment.Name | |||
| } else { | |||
| ctx.Data["datasetname"] = "" | |||
| } | |||
| ctx.Data["task"] = task | |||
| ctx.Data["jobName"] = task.JobName | |||
| @@ -518,7 +576,10 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo | |||
| version_list_task = append(version_list_task, task) | |||
| ctx.Data["version_list_task"] = version_list_task | |||
| ctx.Data["debugListType"] = debugListType | |||
| ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, task) | |||
| ctx.Data["code_path"] = cloudbrain.CodeMountPath | |||
| ctx.Data["dataset_path"] = cloudbrain.DataSetMountPath | |||
| ctx.Data["model_path"] = cloudbrain.ModelMountPath | |||
| ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task) | |||
| ctx.HTML(200, tpName) | |||
| } | |||
| @@ -5,6 +5,7 @@ | |||
| package repo | |||
| import ( | |||
| repo_service "code.gitea.io/gitea/services/repository" | |||
| "encoding/json" | |||
| "fmt" | |||
| "io/ioutil" | |||
| @@ -614,6 +615,19 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) { | |||
| message += "\n\n" + form.CommitMessage | |||
| } | |||
| if err := repo_service.CheckPushSizeLimit4Web(ctx.Repo.Repository, form.Files); err != nil { | |||
| if repo_service.IsRepoTooLargeErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.repo_too_large", setting.Repository.RepoMaxSize), tplUploadFile, &form) | |||
| } else if repo_service.IsUploadFileInvalidErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.repo_file_invalid"), tplUploadFile, &form) | |||
| } else if repo_service.IsUploadFileTooMuchErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_too_much", setting.Repository.Upload.MaxFiles), tplUploadFile, &form) | |||
| } else { | |||
| ctx.RenderWithErr(err.Error(), tplUploadFile, &form) | |||
| } | |||
| return | |||
| } | |||
| if err := repofiles.UploadRepoFiles(ctx.Repo.Repository, ctx.User, &repofiles.UploadRepoFileOptions{ | |||
| LastCommitID: ctx.Repo.CommitID, | |||
| OldBranch: oldBranchName, | |||
| @@ -2,10 +2,9 @@ package repo | |||
| import ( | |||
| "archive/zip" | |||
| "code.gitea.io/gitea/modules/notification" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "io" | |||
| "io/ioutil" | |||
| "net/http" | |||
| @@ -16,6 +15,9 @@ import ( | |||
| "time" | |||
| "unicode/utf8" | |||
| "code.gitea.io/gitea/modules/notification" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/base" | |||
| @@ -247,7 +249,7 @@ func NotebookShow(ctx *context.Context) { | |||
| debugListType := ctx.Query("debugListType") | |||
| var ID = ctx.Params(":id") | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| task, err := models.GetCloudbrainByIDWithDeleted(ID) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookShow, nil) | |||
| @@ -262,16 +264,19 @@ func NotebookShow(ctx *context.Context) { | |||
| } | |||
| if result != nil { | |||
| task.Status = result.Status | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookShow, nil) | |||
| return | |||
| } | |||
| if task.DeletedAt.IsZero() { //normal record | |||
| if task.Status != result.Status { | |||
| task.Status = result.Status | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsNotebookShow, nil) | |||
| return | |||
| } | |||
| } | |||
| } else { //deleted record | |||
| result.CreateTime = time.Unix(int64(result.CreateAt/1000), 0).Format("2006-01-02 15:04:05") | |||
| result.LatestUpdateTime = time.Unix(int64(result.UpdateAt/1000), 0).Format("2006-01-02 15:04:05") | |||
| } | |||
| } | |||
| datasetDownloadLink := "-" | |||
| @@ -279,16 +284,44 @@ func NotebookShow(ctx *context.Context) { | |||
| if task.Uuid != "" && task.UserID == ctx.User.ID { | |||
| attachment, err := models.GetAttachmentByUUID(task.Uuid) | |||
| if err == nil { | |||
| task.DatasetName = attachment.Name | |||
| datasetDownloadLink = attachment.S3DownloadURL() | |||
| } | |||
| } | |||
| } | |||
| user, err := models.GetUserByID(task.UserID) | |||
| if err == nil { | |||
| task.User = user | |||
| } | |||
| if modelarts.FlavorInfos == nil { | |||
| json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | |||
| } | |||
| if modelarts.FlavorInfos != nil { | |||
| ctx.Data["resource_spec"] = modelarts.FlavorInfos.FlavorInfo[0].Desc | |||
| for _, f := range modelarts.FlavorInfos.FlavorInfo { | |||
| if fmt.Sprint(f.Value) == task.FlavorCode { | |||
| ctx.Data["resource_spec"] = f.Desc | |||
| break | |||
| } | |||
| } | |||
| } | |||
| if task.TrainJobDuration == "" { | |||
| if task.Duration == 0 { | |||
| var duration int64 | |||
| if task.Status == string(models.JobRunning) { | |||
| duration = time.Now().Unix() - int64(task.CreatedUnix) | |||
| } else { | |||
| duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | |||
| } | |||
| task.Duration = duration | |||
| } | |||
| task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
| } | |||
| ctx.Data["duration"] = task.TrainJobDuration | |||
| ctx.Data["datasetDownloadLink"] = datasetDownloadLink | |||
| ctx.Data["task"] = task | |||
| ctx.Data["ID"] = ID | |||
| ctx.Data["jobName"] = task.JobName | |||
| ctx.Data["result"] = result | |||
| ctx.Data["debugListType"] = debugListType | |||
| ctx.HTML(200, tplModelArtsNotebookShow) | |||
| } | |||
| @@ -1553,7 +1586,7 @@ func TrainJobShow(ctx *context.Context) { | |||
| ctx.Data["displayJobName"] = VersionListTasks[0].DisplayJobName | |||
| ctx.Data["version_list_task"] = VersionListTasks | |||
| ctx.Data["version_list_count"] = VersionListCount | |||
| ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, &VersionListTasks[0].Cloudbrain) | |||
| ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, &VersionListTasks[0].Cloudbrain) | |||
| ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow) | |||
| } | |||
| @@ -2184,7 +2217,7 @@ func InferenceJobShow(ctx *context.Context) { | |||
| ctx.Data["jobName"] = task.JobName | |||
| ctx.Data["displayJobName"] = task.DisplayJobName | |||
| ctx.Data["task"] = task | |||
| ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, task) | |||
| ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task) | |||
| tempUids := []int64{} | |||
| tempUids = append(tempUids, task.UserID) | |||
| @@ -54,7 +54,12 @@ func queryUserDataPage(ctx *context.Context, tableName string, queryObj interfac | |||
| "N1": ctx.Tr("user.static.createrepocount"), | |||
| "O1": ctx.Tr("user.static.openiindex"), | |||
| "P1": ctx.Tr("user.static.registdate"), | |||
| "Q1": ctx.Tr("user.static.countdate"), | |||
| "Q1": ctx.Tr("user.static.CloudBrainTaskNum"), | |||
| "R1": ctx.Tr("user.static.CloudBrainRunTime"), | |||
| "S1": ctx.Tr("user.static.CommitDatasetNum"), | |||
| "T1": ctx.Tr("user.static.CommitModelCount"), | |||
| "U1": ctx.Tr("user.static.UserIndex"), | |||
| "V1": ctx.Tr("user.static.countdate"), | |||
| } | |||
| for k, v := range dataHeader { | |||
| //设置单元格的值 | |||
| @@ -89,8 +94,14 @@ func queryUserDataPage(ctx *context.Context, tableName string, queryObj interfac | |||
| formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05") | |||
| xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3]) | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, userRecord.CloudBrainTaskNum) | |||
| xlsx.SetCellValue(sheetName, "R"+rows, fmt.Sprintf("%.2f", float64(userRecord.CloudBrainRunTime)/3600)) | |||
| xlsx.SetCellValue(sheetName, "S"+rows, userRecord.CommitDatasetNum) | |||
| xlsx.SetCellValue(sheetName, "T"+rows, userRecord.CommitModelCount) | |||
| xlsx.SetCellValue(sheetName, "U"+rows, fmt.Sprintf("%.2f", userRecord.UserIndex)) | |||
| formatTime = userRecord.DataDate | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, formatTime) | |||
| xlsx.SetCellValue(sheetName, "V"+rows, formatTime) | |||
| } | |||
| indexTotal += PAGE_SIZE | |||
| @@ -115,6 +126,30 @@ func queryUserDataPage(ctx *context.Context, tableName string, queryObj interfac | |||
| } | |||
| } | |||
| func QueryMetrics(ctx *context.Context) { | |||
| startDate := ctx.Query("startDate") | |||
| endDate := ctx.Query("endDate") | |||
| startTime, _ := time.ParseInLocation("2006-01-02", startDate, time.Local) | |||
| endTime, _ := time.ParseInLocation("2006-01-02", endDate, time.Local) | |||
| result, count := models.QueryMetrics(startTime.Unix(), endTime.Unix()) | |||
| mapInterface := make(map[string]interface{}) | |||
| mapInterface["data"] = result | |||
| mapInterface["count"] = count | |||
| ctx.JSON(http.StatusOK, mapInterface) | |||
| } | |||
| func QueryRankingList(ctx *context.Context) { | |||
| key := ctx.Query("key") | |||
| tableName := ctx.Query("tableName") | |||
| limit := ctx.QueryInt("limit") | |||
| result, count := models.QueryRankList(key, tableName, limit) | |||
| mapInterface := make(map[string]interface{}) | |||
| mapInterface["data"] = result | |||
| mapInterface["count"] = count | |||
| ctx.JSON(http.StatusOK, mapInterface) | |||
| } | |||
| func QueryUserStaticCurrentMonth(ctx *context.Context) { | |||
| queryUserDataPage(ctx, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth)) | |||
| } | |||
| @@ -221,7 +256,12 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| "N1": ctx.Tr("user.static.createrepocount"), | |||
| "O1": ctx.Tr("user.static.openiindex"), | |||
| "P1": ctx.Tr("user.static.registdate"), | |||
| "Q1": ctx.Tr("user.static.countdate"), | |||
| "Q1": ctx.Tr("user.static.CloudBrainTaskNum"), | |||
| "R1": ctx.Tr("user.static.CloudBrainRunTime"), | |||
| "S1": ctx.Tr("user.static.CommitDatasetNum"), | |||
| "T1": ctx.Tr("user.static.CommitModelCount"), | |||
| "U1": ctx.Tr("user.static.UserIndex"), | |||
| "V1": ctx.Tr("user.static.countdate"), | |||
| } | |||
| for k, v := range dataHeader { | |||
| //设置单元格的值 | |||
| @@ -249,9 +289,13 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05") | |||
| xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3]) | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, userRecord.CloudBrainTaskNum) | |||
| xlsx.SetCellValue(sheetName, "R"+rows, fmt.Sprintf("%.2f", float64(userRecord.CloudBrainRunTime)/3600)) | |||
| xlsx.SetCellValue(sheetName, "S"+rows, userRecord.CommitDatasetNum) | |||
| xlsx.SetCellValue(sheetName, "T"+rows, userRecord.CommitModelCount) | |||
| xlsx.SetCellValue(sheetName, "U"+rows, fmt.Sprintf("%.2f", userRecord.UserIndex)) | |||
| formatTime = userRecord.DataDate | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, formatTime+" 00:01") | |||
| xlsx.SetCellValue(sheetName, "V"+rows, formatTime) | |||
| } | |||
| //设置默认打开的表单 | |||
| @@ -247,7 +247,11 @@ func renderDirectory(ctx *context.Context, treeLink string) { | |||
| ctx.Data["ReadmeInList"] = true | |||
| ctx.Data["ReadmeExist"] = true | |||
| ctx.Data["FileIsSymlink"] = readmeFile.isSymlink | |||
| ctx.Data["ReadmeName"] = readmeFile.name | |||
| if ctx.Repo.TreePath == "" { | |||
| ctx.Data["ReadmeRelativePath"] = readmeFile.name | |||
| } else { | |||
| ctx.Data["ReadmeRelativePath"] = ctx.Repo.TreePath + "/" + readmeFile.name | |||
| } | |||
| if ctx.Repo.CanEnableEditor() { | |||
| ctx.Data["CanEditFile"] = true | |||
| @@ -579,11 +583,11 @@ func safeURL(address string) string { | |||
| } | |||
| type ContributorInfo struct { | |||
| UserInfo *models.User // nil for contributor who is not a registered user | |||
| RelAvatarLink string `json:"rel_avatar_link"` | |||
| UserName string `json:"user_name"` | |||
| Email string `json:"email"` | |||
| CommitCnt int `json:"commit_cnt"` | |||
| UserInfo *models.User // nil for contributor who is not a registered user | |||
| RelAvatarLink string `json:"rel_avatar_link"` | |||
| UserName string `json:"user_name"` | |||
| Email string `json:"email"` | |||
| CommitCnt int `json:"commit_cnt"` | |||
| } | |||
| type GetContributorsInfo struct { | |||
| @@ -642,7 +646,7 @@ func Home(ctx *context.Context) { | |||
| existedContributorInfo.CommitCnt += c.CommitCnt | |||
| } else { | |||
| var newContributor = &ContributorInfo{ | |||
| user, "", "",c.Email, c.CommitCnt, | |||
| user, "", "", c.Email, c.CommitCnt, | |||
| } | |||
| count++ | |||
| contributorInfos = append(contributorInfos, newContributor) | |||
| @@ -839,7 +843,7 @@ func renderCode(ctx *context.Context) { | |||
| compareInfo, err = baseGitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), ctx.Repo.BranchName, ctx.Repo.Repository.BaseRepo.DefaultBranch) | |||
| ctx.Data["UpstreamSameBranchName"] = false | |||
| } | |||
| if err==nil && compareInfo != nil { | |||
| if err == nil && compareInfo != nil { | |||
| if compareInfo.Commits != nil { | |||
| log.Info("compareInfoCommits数量:%d", compareInfo.Commits.Len()) | |||
| ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len() | |||
| @@ -950,7 +954,7 @@ func ContributorsAPI(ctx *context.Context) { | |||
| } else { | |||
| // new committer info | |||
| var newContributor = &ContributorInfo{ | |||
| user, user.RelAvatarLink(),user.Name, user.Email,c.CommitCnt, | |||
| user, user.RelAvatarLink(), user.Name, user.Email, c.CommitCnt, | |||
| } | |||
| count++ | |||
| contributorInfos = append(contributorInfos, newContributor) | |||
| @@ -963,7 +967,7 @@ func ContributorsAPI(ctx *context.Context) { | |||
| existedContributorInfo.CommitCnt += c.CommitCnt | |||
| } else { | |||
| var newContributor = &ContributorInfo{ | |||
| user, "", "",c.Email,c.CommitCnt, | |||
| user, "", "", c.Email, c.CommitCnt, | |||
| } | |||
| count++ | |||
| contributorInfos = append(contributorInfos, newContributor) | |||
| @@ -573,7 +573,8 @@ func trimFontHtml(text []rune) string { | |||
| startRune := rune('<') | |||
| endRune := rune('>') | |||
| count := 0 | |||
| for i := 0; i < len(text); i++ { | |||
| i := 0 | |||
| for ; i < len(text); i++ { | |||
| if text[i] == startRune { //start < | |||
| re := false | |||
| j := i + 1 | |||
| @@ -592,11 +593,14 @@ func trimFontHtml(text []rune) string { | |||
| } else { | |||
| return string(text[0:i]) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return string(text) | |||
| if count%2 == 1 { | |||
| return string(text[0:i]) + "</font>" | |||
| } else { | |||
| return string(text[0:i]) | |||
| } | |||
| } | |||
| func trimHrefHtml(result string) string { | |||
| @@ -1125,7 +1129,7 @@ func makePrivateIssueOrPr(issues []*models.Issue, res *SearchRes, Key string, la | |||
| record["num_comments"] = issue.NumComments | |||
| record["is_closed"] = issue.IsClosed | |||
| record["updated_unix"] = issue.UpdatedUnix | |||
| record["updated_html"] = timeutil.TimeSinceUnix(repo.UpdatedUnix, language) | |||
| record["updated_html"] = timeutil.TimeSinceUnix(issue.UpdatedUnix, language) | |||
| res.Result = append(res.Result, record) | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ import ( | |||
| "fmt" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "os" | |||
| "strings" | |||
| "code.gitea.io/gitea/models" | |||
| @@ -172,3 +173,137 @@ func RecommendFromPromote(url string) ([]string, error) { | |||
| } | |||
| return result, nil | |||
| } | |||
| func CheckPushSizeLimit4Web(repo *models.Repository, fileIds []string) error { | |||
| if err := CheckRepoNumOnceLimit(len(fileIds)); err != nil { | |||
| return err | |||
| } | |||
| totalSize, err := CountUploadFileSizeByIds(fileIds) | |||
| if err != nil { | |||
| return UploadFileInvalidErr{} | |||
| } | |||
| if err := CheckRepoTotalSizeLimit(repo, totalSize); err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| func CheckPushSizeLimit4Http(repo *models.Repository, uploadFileSize int64) error { | |||
| if err := CheckRepoOnceTotalSizeLimit(uploadFileSize); err != nil { | |||
| return err | |||
| } | |||
| if err := CheckRepoTotalSizeLimit(repo, uploadFileSize); err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| func CheckRepoTotalSizeLimit(repo *models.Repository, uploadFileSize int64) error { | |||
| if repo.Size+uploadFileSize > setting.Repository.RepoMaxSize*1024*1024 { | |||
| return RepoTooLargeErr{} | |||
| } | |||
| return nil | |||
| } | |||
| func CheckRepoOnceTotalSizeLimit(uploadFileSize int64) error { | |||
| if uploadFileSize > setting.Repository.Upload.TotalMaxSize*1024*1024 { | |||
| return UploadFileTooLargeErr{} | |||
| } | |||
| return nil | |||
| } | |||
| func CheckRepoNumOnceLimit(uploadFileNum int) error { | |||
| if uploadFileNum > setting.Repository.Upload.MaxFiles { | |||
| return UploadFileTooMuchErr{} | |||
| } | |||
| return nil | |||
| } | |||
| func CountUploadFileSizeByIds(fileIds []string) (int64, error) { | |||
| if len(fileIds) == 0 { | |||
| return 0, nil | |||
| } | |||
| uploads, err := models.GetUploadsByUUIDs(fileIds) | |||
| if err != nil { | |||
| return 0, fmt.Errorf("CountUploadFileSizeByIds error [uuids: %v]: %v", fileIds, err) | |||
| } | |||
| var totalSize int64 | |||
| for _, upload := range uploads { | |||
| size, err := GetUploadFileSize(upload) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| totalSize += size | |||
| } | |||
| return totalSize, nil | |||
| } | |||
| func GetUploadFileSize(upload *models.Upload) (int64, error) { | |||
| info, err := os.Lstat(upload.LocalPath()) | |||
| if err != nil { | |||
| return 0, err | |||
| } | |||
| return info.Size(), nil | |||
| } | |||
| type RepoTooLargeErr struct { | |||
| } | |||
| func (RepoTooLargeErr) Error() string { | |||
| return fmt.Sprintf("Repository can not exceed %d MB. Please remove some unnecessary files and try again", setting.Repository.RepoMaxSize) | |||
| } | |||
| func IsRepoTooLargeErr(err error) bool { | |||
| _, ok := err.(RepoTooLargeErr) | |||
| return ok | |||
| } | |||
| type UploadFileTooLargeErr struct { | |||
| } | |||
| func (UploadFileTooLargeErr) Error() string { | |||
| return fmt.Sprintf("Upload files can not exceed %d MB at a time", setting.Repository.Upload.TotalMaxSize) | |||
| } | |||
| func IsUploadFileTooLargeErr(err error) bool { | |||
| _, ok := err.(UploadFileTooLargeErr) | |||
| return ok | |||
| } | |||
| type RepoFileTooLargeErr struct { | |||
| } | |||
| func (RepoFileTooLargeErr) Error() string { | |||
| return "repository file is too large" | |||
| } | |||
| func IsRepoFileTooLargeErr(err error) bool { | |||
| _, ok := err.(RepoFileTooLargeErr) | |||
| return ok | |||
| } | |||
| type UploadFileTooMuchErr struct { | |||
| } | |||
| func (UploadFileTooMuchErr) Error() string { | |||
| return "upload files are too lmuch" | |||
| } | |||
| func IsUploadFileTooMuchErr(err error) bool { | |||
| _, ok := err.(UploadFileTooMuchErr) | |||
| return ok | |||
| } | |||
| type UploadFileInvalidErr struct { | |||
| } | |||
| func (UploadFileInvalidErr) Error() string { | |||
| return "upload files are invalid" | |||
| } | |||
| func IsUploadFileInvalidErr(err error) bool { | |||
| _, ok := err.(UploadFileInvalidErr) | |||
| return ok | |||
| } | |||
| @@ -81,7 +81,7 @@ | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "TRAIN"}} | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/train-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <a class="title" href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts{{end}}/train-job/{{$JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| {{else if eq .JobType "BENCHMARK"}} | |||
| @@ -155,13 +155,13 @@ | |||
| </a> | |||
| </form> | |||
| {{else}} | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" > | |||
| <a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED"}}disabled {{else}} blue {{end}}button" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain/train-job{{else}}/modelarts/{{if eq .JobType "INFERENCE"}}inference-job{{else}}train-job{{end}}{{end}}" data-jobid="{{$JobID}}" data-version="{{.VersionName}}" > | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{end}} | |||
| </div> | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}/modelarts/train-job{{end}}/{{$JobID}}/del?isadminpage=true' method="post"> | |||
| <form class="ui compact buttons" id="delForm-{{$JobID}}" action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if eq .JobType "DEBUG"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .ComputeResource "NPU"}}/modelarts/notebook{{else}}/cloudbrain{{end}}/train-job{{end}}/{{$JobID}}/del?isadminpage=true' method="post"> | |||
| {{$.CsrfTokenHtml}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}" data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true" data-version="{{.VersionName}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| {{$.i18n.Tr "repo.delete"}} | |||
| @@ -135,4 +135,4 @@ | |||
| </el-dialog> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1,134 @@ | |||
| <div class="dataset-repolink" id="dataset-repolink-init" style="display: none;" data-repolink="{{.RepoLink}}" data-cloudranin-type="{{.cloudbraintype}}"></div> | |||
| <div class="inline required unite min_title field" id="dataset-base" style="margin-bottom: 0 !important;"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "dataset.dataset"}}</label> | |||
| <input type="hidden" name="attachment" :value="dataset_uuid"> | |||
| <input class="disabled" type="text" :value="dataset_name" required onfocus="this.blur();" style="width: 35.5%;"> | |||
| <el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;"> {{.i18n.Tr "dataset.select_dataset"}}</el-button> | |||
| <el-dialog | |||
| title="{{.i18n.Tr "dataset.select_dataset"}}" | |||
| :visible.sync="dialogVisible" | |||
| width="50%" | |||
| > | |||
| <div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;"> | |||
| <i class="search icon" style="cursor: pointer;pointer-events:auto" @click="searchDataset()"></i> | |||
| <input type="text" placeholder="{{.i18n.Tr "dataset.search_dataset"}}" v-model="searchDataItem" @keyup.enter="searchDataset()"> | |||
| </div> | |||
| <el-tabs v-model="activeName" @tab-click="handleClick('{{.RepoLink}}',activeName,{{.cloudbraintype}})"> | |||
| <el-tab-pane label="{{.i18n.Tr "dataset.current_project"}}" name="first"> | |||
| <div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in currentRepoDataset" :key="index"> | |||
| <div style="width: 90%;"> | |||
| <div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias} </span><span class="panel_dataset_name">${dataset.Name} </span></div> | |||
| <div style="margin-top: 8px;display: flex;"> | |||
| <a :title="dataset.UserName" style="cursor: default;"> | |||
| <img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
| </a> | |||
| <span class="panel_datset_desc">${dataset.Description}</span> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
| <span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
| <i class="CREATING"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
| </span> | |||
| <span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
| <i class="FAILED"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </el-tab-pane> | |||
| <el-tab-pane label="{{.i18n.Tr "dataset.owner_dataset"}}" name="second"> | |||
| <div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in myDataset" :key="index"> | |||
| <div style="width: 90%;"> | |||
| <div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
| <div style="margin-top: 8px;display: flex;"> | |||
| <a :title="dataset.UserName" style="cursor: default;"> | |||
| <img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
| </a> | |||
| <span class="panel_datset_desc">${dataset.Description}</span> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
| <span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
| <i class="CREATING"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
| </span> | |||
| <span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
| <i class="FAILED"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </el-tab-pane> | |||
| <el-tab-pane label="{{.i18n.Tr "dataset.public_dataset"}}" name="third"> | |||
| <div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in publicDataset" :key="index"> | |||
| <div style="width: 90%;"> | |||
| <div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
| <div style="margin-top: 8px;display: flex;"> | |||
| <a :title="dataset.UserName" style="cursor: default;"> | |||
| <img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
| </a> | |||
| <span class="panel_datset_desc">${dataset.Description}</span> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
| <span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
| <i class="CREATING"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
| </span> | |||
| <span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
| <i class="FAILED"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </el-tab-pane> | |||
| <el-tab-pane label="{{.i18n.Tr "dataset.I_liked"}}" name="fourth"> | |||
| <div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in myFavoriteDataset" :key="index"> | |||
| <div style="width: 90%;"> | |||
| <div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
| <div style="margin-top: 8px;display: flex;"> | |||
| <a :title="dataset.UserName" style="cursor: default;"> | |||
| <img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
| </a> | |||
| <span class="panel_datset_desc">${dataset.Description}</span> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| <button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
| <span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
| <i class="CREATING"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
| </span> | |||
| <span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
| <i class="FAILED"></i> | |||
| <span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </el-tab-pane> | |||
| </el-tabs> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-size="5" | |||
| layout="total,prev, pager, next" | |||
| :total="totalnums"> | |||
| </el-pagination> | |||
| </div> | |||
| </el-dialog> | |||
| </div> | |||
| @@ -121,10 +121,10 @@ | |||
| <i class="dropdown icon"></i> | |||
| </span> | |||
| <div class="menu"> | |||
| <a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
| <a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
| <a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||
| <a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||
| <a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
| <a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
| <a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||
| <a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$.License}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||
| <!-- <a class="{{if eq .SortType "downloadtimes"}}active{{end}} item" href="{{$.Link}}?sort=downloadtimes&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.downloadtimes"}}</a> --> | |||
| </div> | |||
| </div> | |||
| @@ -184,9 +184,15 @@ | |||
| </div> | |||
| <div class="extra content" style="border-top: none !important;"> | |||
| <div style="display: flex;align-items: center;"> | |||
| {{if eq .UserID 0}} | |||
| <a href="{{AppSubUrl}}/{{.Repo.OwnerName}}" title="{{.Repo.OwnerName}}"> | |||
| <img class="ui avatar image" style="width: 22px;height:22px;" src="/user/avatar/{{.Repo.OwnerName}}/-1"> | |||
| </a> | |||
| {{else}} | |||
| <a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"> | |||
| <img class="ui avatar image" style="width: 22px;height:22px;" src="/user/avatar/{{.User.Name}}/-1"> | |||
| </a> | |||
| {{end}} | |||
| <span style="color: #999999;font-size: 14px;;">创建于:{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
| </div> | |||
| </div> | |||
| @@ -215,4 +221,4 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| {{template "base/footer" .}} | |||
| @@ -1,68 +1,251 @@ | |||
| <link rel="stylesheet" href="/swiper/swiper-bundle.min.css"> | |||
| <link rel="stylesheet" href="/css/git.openi.css"> | |||
| <script src="/swiper/swiper-bundle.min.js"></script> | |||
| <script src="/self/js/jquery.min.js" type="text/javascript"></script> | |||
| {{template "base/head" .}} | |||
| <div class="explore users"> | |||
| {{template "explore/search" .}} | |||
| <div class="ui container"> | |||
| <div class="ui grid"> | |||
| {{template "explore/navbar" .}} | |||
| <div class="sixteen wide mobile ten wide tablet ten wide computer column"> | |||
| <h2 class="ui left floated medium header"> | |||
| {{.i18n.Tr "explore.organizations"}} | |||
| </h2> | |||
| <div class="ui right floated secondary filter menu"> | |||
| <!-- Sort --> | |||
| <div class="ui right dropdown type jump item"> | |||
| <span class="text"> | |||
| {{.i18n.Tr "repo.issues.filter_sort"}} | |||
| <i class="dropdown icon"></i> | |||
| </span> | |||
| <div class="menu"> | |||
| <a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
| <a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
| <a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||
| <a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||
| <a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||
| <a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||
| </div> | |||
| <!-- {{template "explore/search" .}} --> | |||
| <div class="repos--seach"> | |||
| <div class="ui container"> | |||
| <div class="ui two column centered grid"> | |||
| <div class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" > | |||
| <div class="ui fluid action input" id="search_all"> | |||
| <input id = 'value_s' name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." onkeydown="if(event.keyCode==13){all_search();}" autofocus> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <button class="ui green button" onclick="all_search()">{{.i18n.Tr "explore.search"}}</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="ui clearing divider"></div> | |||
| <div class="ui user list"> | |||
| {{range .Users}} | |||
| <div class="item"> | |||
| <img class="ui avatar image" src="{{.RelAvatarLink}}"> | |||
| <div class="content"> | |||
| <span class="header"> | |||
| <a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}} | |||
| {{if .Visibility.IsPrivate}} | |||
| <span class="text gold">{{svg "octicon-lock" 16}}</span> | |||
| {{end}} | |||
| </span> | |||
| <div class="description"> | |||
| {{if .Location}} | |||
| {{svg "octicon-location" 16}} {{.Location}} | |||
| {{end}} | |||
| {{if and .Website}} | |||
| {{svg "octicon-link" 16}} | |||
| <a href="{{.Website}}" rel="nofollow">{{.Website}}</a> | |||
| {{end}} | |||
| {{svg "octicon-clock" 16}} {{$.i18n.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}} | |||
| </div> | |||
| </div> | |||
| <div class="ui container homeorg"> | |||
| <div class="ui center aligned header"> | |||
| <h1 class="title_re"> | |||
| {{$.i18n.Tr "home.page_recommend_org"}} | |||
| </h1> | |||
| <p class="re_con"> {{$.i18n.Tr "home.page_recommend_org_desc"}}<a href="{{.RecommendURL}}"> {{$.i18n.Tr "home.page_recommend_org_commit"}}</a></p> | |||
| </div> | |||
| <div class="sixteen wide tablet sixteen wide computer column"> | |||
| <div class="homeorg-list" > | |||
| <div class="swiper-wrapper" id="recommendorg" style="height:auto"> | |||
| {{range .RecommendOrgs}} | |||
| <div class="swiper-slide"> | |||
| <a href="{{.HomeLink}}" class= "ui fluid card"> | |||
| <div class="content"> | |||
| <div class= "ui small header"> | |||
| <img class="ui image" src="{{.Avatar}}" > | |||
| <div class="content nowrap"> | |||
| <span class="ui blue"> {{.Name}} </span> {{.FullName}} | |||
| <div class="sub header"> | |||
| <span> | |||
| {{.NumRepos}} | |||
| {{if le .NumRepos 1}} | |||
| {{$.i18n.Tr "org.org_repository"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "org.org_repositories"}} | |||
| {{end}} | |||
| </span> | |||
| . <span> | |||
| {{.NumMembers}} | |||
| {{if le .NumRepos 1}} | |||
| {{$.i18n.Tr "org.org_member"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "org.org_members"}} | |||
| {{end}} | |||
| </span> | |||
| .<span> | |||
| {{.NumTeams}} | |||
| {{if le .NumRepos 1}} | |||
| {{$.i18n.Tr "org.org_team"}} | |||
| {{else}} | |||
| {{$.i18n.Tr "org.org_teams"}} | |||
| {{end}} | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </a> | |||
| </div> | |||
| {{else}} | |||
| <div>{{$.i18n.Tr "explore.org_no_results"}}</div> | |||
| {{end}} | |||
| </div> | |||
| {{template "base/paginate" .}} | |||
| <div class="swiper-pagination"></div> | |||
| </div> | |||
| <div class="sixteen wide mobile six wide tablet three wide computer column"> | |||
| {{template "explore/repo_right" .}} | |||
| </div> | |||
| </div> | |||
| <div class="ui container homeorg"> | |||
| <div class="content_top10"> | |||
| <div class="ui three doubling cards"> | |||
| <div class="card_list" > | |||
| <div class="list_title star_title"> | |||
| <p class="p_text"> <i class="ri-star-line"> </i>{{$.i18n.Tr "org.star"}}</p> | |||
| </div> | |||
| <li style="list-style:none"> | |||
| {{ range $i,$user :=.StarOrgs}} | |||
| <ul class="orgs" style="display: flex;"> | |||
| {{if eq $i 0}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><defs><path id="rank1_svg__a" d="M13.69 20V9.616h-1.598l-3.139 2.61 1.027 1.218 1.95-1.804V20z"></path></defs><g fill="none" fill-rule="evenodd"><path d="M0 0h32v32H0z"></path><g transform="translate(4 2.667)"><path fill="#D16C11" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#F7C049" cx="12" cy="14.667" r="12"></circle><circle fill="#FEE6AD" cx="12" cy="14.667" r="9.333"></circle><g fill-rule="nonzero"><use fill="#FFF" xlink:href="#rank1_svg__a"></use><use fill="#D74D03" xlink:href="#rank1_svg__a"></use></g></g></g></svg> | |||
| </div> | |||
| {{else if eq $i 1}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#305269" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#BDD8F0" cx="12" cy="14.667" r="12"></circle><circle fill="#E1E9FC" cx="12" cy="14.667" r="9.333"></circle><path d="M15.817 20v-1.584h-4.81l3.212-2.977c.469-.43.853-.883 1.151-1.357.298-.474.447-1.039.447-1.694 0-.499-.088-.934-.264-1.305a2.525 2.525 0 00-.718-.917 3.169 3.169 0 00-1.064-.543 4.531 4.531 0 00-1.312-.183c-.47 0-.905.064-1.306.19-.4.128-.753.314-1.056.558-.303.244-.55.55-.74.917-.191.366-.306.79-.345 1.268l1.848.147c.059-.43.23-.772.513-1.027.284-.254.646-.381 1.086-.381.205 0 .398.032.579.095.18.064.34.154.477.272a1.262 1.262 0 01.455.997c0 .176-.035.345-.103.506a2.52 2.52 0 01-.257.462 3.476 3.476 0 01-.345.418c-.127.132-.249.257-.366.374l-4.034 3.901V20h6.952z" fill="#305269" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else if eq $i 2}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#865B45" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#E7C5AC" cx="12" cy="14.667" r="12"></circle><circle fill="#FEDDC7" cx="12" cy="14.667" r="9.333"></circle><path d="M12.239 20.176c.46 0 .902-.066 1.327-.198.425-.132.8-.328 1.122-.587.323-.259.58-.579.77-.96.19-.382.286-.822.286-1.32 0-.646-.171-1.203-.513-1.672-.343-.47-.846-.753-1.511-.851v-.03c.557-.136.992-.422 1.305-.857.313-.435.47-.932.47-1.489 0-.46-.09-.863-.272-1.21a2.547 2.547 0 00-.726-.865 3.232 3.232 0 00-1.056-.521 4.521 4.521 0 00-1.276-.176 4.52 4.52 0 00-1.1.132 3.404 3.404 0 00-.968.403 2.79 2.79 0 00-.762.697 3.181 3.181 0 00-.499.997l1.863.499c.127-.362.33-.643.608-.843.279-.2.594-.301.946-.301.44 0 .797.127 1.071.381.274.255.41.582.41.983 0 .313-.058.562-.175.748a1.17 1.17 0 01-.462.425 1.903 1.903 0 01-.646.191 6.09 6.09 0 01-.74.044h-.455v1.584h.425c.264 0 .533.02.807.059.274.039.52.115.74.227.22.112.402.274.543.484.142.21.213.482.213.814a1.533 1.533 0 01-.52 1.18 1.772 1.772 0 01-.558.33 1.88 1.88 0 01-.667.118c-.47 0-.841-.117-1.115-.352s-.464-.567-.572-.997l-1.877.498c.117.43.288.8.513 1.108.225.308.491.56.8.755.307.196.652.34 1.033.433a5.13 5.13 0 001.218.139z" fill="#865B45" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else }} | |||
| <div class="org_icon org_icon_num" > | |||
| {{Add $i 1}} | |||
| </div> | |||
| {{end}} | |||
| <li class="li_avatar"> | |||
| <img class="ui avatar image" src="{{$user.RelAvatarLink}}" > | |||
| </li> | |||
| <li class="li_name"> | |||
| <p class="org_line_hight">{{$user.Name}}</p> | |||
| </li> | |||
| <ul> | |||
| <li class="li_score" > | |||
| <i class="ri-star-line org_line_hight org_icon_color"></i> <p class="p_score">{{$user.Score}}</p> | |||
| </li> | |||
| </ul> | |||
| </ul> | |||
| {{end}} | |||
| </li> | |||
| </div> | |||
| <div class="card_list" > | |||
| <div class="list_title star_title"> | |||
| <p class="p_text"> <i class="ri-user-2-line"> </i>{{$.i18n.Tr "org.member"}}</p> | |||
| </div> | |||
| <li style="list-style:none"> | |||
| {{ range $i,$user :=.StarOrgs}} | |||
| <ul class="orgs" style="display: flex;"> | |||
| {{if eq $i 0}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><defs><path id="rank1_svg__a" d="M13.69 20V9.616h-1.598l-3.139 2.61 1.027 1.218 1.95-1.804V20z"></path></defs><g fill="none" fill-rule="evenodd"><path d="M0 0h32v32H0z"></path><g transform="translate(4 2.667)"><path fill="#D16C11" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#F7C049" cx="12" cy="14.667" r="12"></circle><circle fill="#FEE6AD" cx="12" cy="14.667" r="9.333"></circle><g fill-rule="nonzero"><use fill="#FFF" xlink:href="#rank1_svg__a"></use><use fill="#D74D03" xlink:href="#rank1_svg__a"></use></g></g></g></svg> | |||
| </div> | |||
| {{else if eq $i 1}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#305269" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#BDD8F0" cx="12" cy="14.667" r="12"></circle><circle fill="#E1E9FC" cx="12" cy="14.667" r="9.333"></circle><path d="M15.817 20v-1.584h-4.81l3.212-2.977c.469-.43.853-.883 1.151-1.357.298-.474.447-1.039.447-1.694 0-.499-.088-.934-.264-1.305a2.525 2.525 0 00-.718-.917 3.169 3.169 0 00-1.064-.543 4.531 4.531 0 00-1.312-.183c-.47 0-.905.064-1.306.19-.4.128-.753.314-1.056.558-.303.244-.55.55-.74.917-.191.366-.306.79-.345 1.268l1.848.147c.059-.43.23-.772.513-1.027.284-.254.646-.381 1.086-.381.205 0 .398.032.579.095.18.064.34.154.477.272a1.262 1.262 0 01.455.997c0 .176-.035.345-.103.506a2.52 2.52 0 01-.257.462 3.476 3.476 0 01-.345.418c-.127.132-.249.257-.366.374l-4.034 3.901V20h6.952z" fill="#305269" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else if eq $i 2}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#865B45" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#E7C5AC" cx="12" cy="14.667" r="12"></circle><circle fill="#FEDDC7" cx="12" cy="14.667" r="9.333"></circle><path d="M12.239 20.176c.46 0 .902-.066 1.327-.198.425-.132.8-.328 1.122-.587.323-.259.58-.579.77-.96.19-.382.286-.822.286-1.32 0-.646-.171-1.203-.513-1.672-.343-.47-.846-.753-1.511-.851v-.03c.557-.136.992-.422 1.305-.857.313-.435.47-.932.47-1.489 0-.46-.09-.863-.272-1.21a2.547 2.547 0 00-.726-.865 3.232 3.232 0 00-1.056-.521 4.521 4.521 0 00-1.276-.176 4.52 4.52 0 00-1.1.132 3.404 3.404 0 00-.968.403 2.79 2.79 0 00-.762.697 3.181 3.181 0 00-.499.997l1.863.499c.127-.362.33-.643.608-.843.279-.2.594-.301.946-.301.44 0 .797.127 1.071.381.274.255.41.582.41.983 0 .313-.058.562-.175.748a1.17 1.17 0 01-.462.425 1.903 1.903 0 01-.646.191 6.09 6.09 0 01-.74.044h-.455v1.584h.425c.264 0 .533.02.807.059.274.039.52.115.74.227.22.112.402.274.543.484.142.21.213.482.213.814a1.533 1.533 0 01-.52 1.18 1.772 1.772 0 01-.558.33 1.88 1.88 0 01-.667.118c-.47 0-.841-.117-1.115-.352s-.464-.567-.572-.997l-1.877.498c.117.43.288.8.513 1.108.225.308.491.56.8.755.307.196.652.34 1.033.433a5.13 5.13 0 001.218.139z" fill="#865B45" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else }} | |||
| <div class="org_icon org_icon_num" > | |||
| {{Add $i 1}} | |||
| </div> | |||
| {{end}} | |||
| <li class="li_avatar"> | |||
| <img class="ui avatar image" src="{{$user.RelAvatarLink}}" > | |||
| </li> | |||
| <li class="li_name"> | |||
| <p class="org_line_hight">{{$user.Name}}</p> | |||
| </li> | |||
| <ul> | |||
| <li class="li_score"> | |||
| <i class="ri-user-2-line org_line_hight org_icon_color"></i> <p class="p_score">{{$user.Score}}</p> | |||
| </li> | |||
| </ul> | |||
| </ul> | |||
| {{end}} | |||
| </li> | |||
| </div> | |||
| <div class="card_list" > | |||
| <div class="list_title star_title"> | |||
| <p class="p_text"> <i class="ri-blaze-fill"> </i>{{$.i18n.Tr "org.active"}}</p> | |||
| </div> | |||
| <li style="list-style:none"> | |||
| {{ range $i,$user :=.StarOrgs}} | |||
| <ul class="orgs" style="display: flex;"> | |||
| {{if eq $i 0}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><defs><path id="rank1_svg__a" d="M13.69 20V9.616h-1.598l-3.139 2.61 1.027 1.218 1.95-1.804V20z"></path></defs><g fill="none" fill-rule="evenodd"><path d="M0 0h32v32H0z"></path><g transform="translate(4 2.667)"><path fill="#D16C11" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#F7C049" cx="12" cy="14.667" r="12"></circle><circle fill="#FEE6AD" cx="12" cy="14.667" r="9.333"></circle><g fill-rule="nonzero"><use fill="#FFF" xlink:href="#rank1_svg__a"></use><use fill="#D74D03" xlink:href="#rank1_svg__a"></use></g></g></g></svg> | |||
| </div> | |||
| {{else if eq $i 1}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#305269" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#BDD8F0" cx="12" cy="14.667" r="12"></circle><circle fill="#E1E9FC" cx="12" cy="14.667" r="9.333"></circle><path d="M15.817 20v-1.584h-4.81l3.212-2.977c.469-.43.853-.883 1.151-1.357.298-.474.447-1.039.447-1.694 0-.499-.088-.934-.264-1.305a2.525 2.525 0 00-.718-.917 3.169 3.169 0 00-1.064-.543 4.531 4.531 0 00-1.312-.183c-.47 0-.905.064-1.306.19-.4.128-.753.314-1.056.558-.303.244-.55.55-.74.917-.191.366-.306.79-.345 1.268l1.848.147c.059-.43.23-.772.513-1.027.284-.254.646-.381 1.086-.381.205 0 .398.032.579.095.18.064.34.154.477.272a1.262 1.262 0 01.455.997c0 .176-.035.345-.103.506a2.52 2.52 0 01-.257.462 3.476 3.476 0 01-.345.418c-.127.132-.249.257-.366.374l-4.034 3.901V20h6.952z" fill="#305269" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else if eq $i 2}} | |||
| <div class="org_icon"> | |||
| <svg width="1em" height="1em" viewBox="0 0 32 32" class="contribution-item-img__2-fih"><g transform="translate(4 2.667)" fill="none" fill-rule="evenodd"><path fill="#865B45" d="M0 0h6.976l5.49 7.642L17.063 0H24L12 16z"></path><circle fill="#E7C5AC" cx="12" cy="14.667" r="12"></circle><circle fill="#FEDDC7" cx="12" cy="14.667" r="9.333"></circle><path d="M12.239 20.176c.46 0 .902-.066 1.327-.198.425-.132.8-.328 1.122-.587.323-.259.58-.579.77-.96.19-.382.286-.822.286-1.32 0-.646-.171-1.203-.513-1.672-.343-.47-.846-.753-1.511-.851v-.03c.557-.136.992-.422 1.305-.857.313-.435.47-.932.47-1.489 0-.46-.09-.863-.272-1.21a2.547 2.547 0 00-.726-.865 3.232 3.232 0 00-1.056-.521 4.521 4.521 0 00-1.276-.176 4.52 4.52 0 00-1.1.132 3.404 3.404 0 00-.968.403 2.79 2.79 0 00-.762.697 3.181 3.181 0 00-.499.997l1.863.499c.127-.362.33-.643.608-.843.279-.2.594-.301.946-.301.44 0 .797.127 1.071.381.274.255.41.582.41.983 0 .313-.058.562-.175.748a1.17 1.17 0 01-.462.425 1.903 1.903 0 01-.646.191 6.09 6.09 0 01-.74.044h-.455v1.584h.425c.264 0 .533.02.807.059.274.039.52.115.74.227.22.112.402.274.543.484.142.21.213.482.213.814a1.533 1.533 0 01-.52 1.18 1.772 1.772 0 01-.558.33 1.88 1.88 0 01-.667.118c-.47 0-.841-.117-1.115-.352s-.464-.567-.572-.997l-1.877.498c.117.43.288.8.513 1.108.225.308.491.56.8.755.307.196.652.34 1.033.433a5.13 5.13 0 001.218.139z" fill="#865B45" fill-rule="nonzero"></path></g></svg> | |||
| </div> | |||
| {{else }} | |||
| <div class="org_icon org_icon_num" > | |||
| {{Add $i 1}} | |||
| </div> | |||
| {{end}} | |||
| <li class="li_avatar"> | |||
| <img class="ui avatar image" src="{{$user.RelAvatarLink}}" > | |||
| </li> | |||
| <li class="li_name"> | |||
| <p class="org_line_hight">{{$user.Name}}</p> | |||
| </li> | |||
| </ul> | |||
| {{end}} | |||
| </li> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| function all_search(){ | |||
| var inputValue = document.getElementById("value_s").value; | |||
| console.log("Keyword",inputValue) | |||
| sessionStorage.setItem("keyword",inputValue); | |||
| sessionStorage.setItem("tableName","org"); | |||
| sessionStorage.setItem("specifySearch",true); | |||
| sessionStorage.setItem("sortBy","default"); | |||
| sessionStorage.setItem("ascending","false"); | |||
| window.open("/all/search/"); | |||
| } | |||
| window.onload = function() { | |||
| var swiperOrg = new Swiper(".homeorg-list", { | |||
| slidesPerView: 1, | |||
| slidesPerColumn: 3, | |||
| slidesPerColumnFill:'row', | |||
| spaceBetween: 15, | |||
| pagination: { | |||
| el: ".swiper-pagination", | |||
| clickable: true, | |||
| }, | |||
| autoplay: { | |||
| delay: 4500, | |||
| disableOnInteraction: false, | |||
| }, | |||
| breakpoints: { | |||
| 768: { | |||
| slidesPerView: 3, | |||
| }, | |||
| 1024: { | |||
| slidesPerView: 4, | |||
| }, | |||
| }, | |||
| }); | |||
| } | |||
| </script> | |||
| @@ -42,18 +42,15 @@ | |||
| .active{ | |||
| color:#0366D6 !important; | |||
| } | |||
| .mleft{ | |||
| margin-left: 30% !important; | |||
| } | |||
| .mbom{ | |||
| margin-bottom: 10px !important; | |||
| } | |||
| </style> | |||
| <div class="row"> | |||
| <div class="ui secondary pointing tabular top attached borderless menu navbar mbom"> | |||
| <div class="ui secondary tiny pointing borderless menu center aligned grid mbom"> | |||
| {{with .Org}} | |||
| <a class="{{if $.PageIsOrgHome}}active{{end}} item mleft" href="{{.HomeLink}}"> | |||
| <a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | |||
| {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||
| </a> | |||
| {{end}} | |||
| @@ -83,47 +83,36 @@ | |||
| {{ range .tags}} | |||
| {{if eq .TagName "精选项目"}} | |||
| <div class="ui three cards" style="margin-bottom: 10px;"> | |||
| <div class="ui three stackable cards" style="margin-bottom: 10px;"> | |||
| {{ range .RepoList}} | |||
| <div class="card" > | |||
| <div class="ui raised card"> | |||
| <div class="extra full_height cor" > | |||
| <div class=" header header_card omit" > | |||
| <a class="header_card image poping up " href="{{.Link}}" data-content="{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}" data-position="top left" data-variation="tiny inverted">{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}</a> | |||
| <div class="content" style="padding-bottom: 0;"> | |||
| <div class="header" > | |||
| <a href="{{.Link}}">{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}</a> | |||
| </div> | |||
| <div class='content descript_height nowrap-2'> | |||
| <div class="description"> | |||
| <p class="nowrap-2"> | |||
| {{.Description}} | |||
| </div> | |||
| <div class="content " > | |||
| </p> | |||
| {{if .Topics }} | |||
| <div class=" tags " style="position: relative;"> | |||
| {{range .Topics}} | |||
| {{if ne . "" }}<a style="max-width:100%;display:inline-flex;" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}" ><span class="ui small label topic omit" >{{.}}</span></a>{{end}} | |||
| {{end}} | |||
| </div> | |||
| {{end}} | |||
| <p> | |||
| {{range .Topics}} | |||
| {{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}" class="ui small label topic omit" >{{.}}</a>{{end}} | |||
| {{end}} | |||
| </p> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| <div class=" extra " style="color:#888888;border-top: none !important;padding-top: 0"> | |||
| <div class="ui mini right compact marg" > | |||
| <a class="item marg "> | |||
| {{svg "octicon-eye" 16}} {{.NumWatches}} | |||
| </a> | |||
| <a class="item marg"> | |||
| {{svg "octicon-star" 16}} {{.NumStars}} | |||
| </a> | |||
| <a class="item marg"> | |||
| {{svg "octicon-git-branch" 16}} {{.NumForks}} | |||
| </a> | |||
| </div> | |||
| <div class="extra content"> | |||
| <span class="right floated date"> | |||
| {{svg "octicon-eye" 16}} {{.NumWatches}}     | |||
| {{svg "octicon-star" 16}} {{.NumStars}}     | |||
| {{svg "octicon-git-branch" 16}} {{.NumForks}} | |||
| </span> | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| </div> | |||
| @@ -281,7 +281,7 @@ td, th { | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 镜像 | |||
| {{.i18n.Tr "cloudbrain.mirror"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -292,7 +292,8 @@ td, th { | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 类型 | |||
| {{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -313,7 +314,7 @@ td, th { | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 训练程序 | |||
| {{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -324,7 +325,7 @@ td, th { | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 测试程序 | |||
| {{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_test"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -360,7 +361,7 @@ td, th { | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 创建者 | |||
| {{$.i18n.Tr "repo.cloudbrain_creator"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -371,7 +372,7 @@ td, th { | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| 子类型 | |||
| {{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_child_type"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| @@ -1,108 +1,511 @@ | |||
| {{template "base/head" .}} | |||
| <style> | |||
| .according-panel-heading{ | |||
| box-sizing: border-box; | |||
| padding: 8px 16px; | |||
| color: #252b3a; | |||
| background-color: #f2f5fc; | |||
| line-height: 1.5; | |||
| cursor: pointer; | |||
| -moz-user-select: none; | |||
| -webkit-user-select: none; | |||
| -ms-user-select: none; | |||
| -khtml-user-select: none; | |||
| user-select: none; | |||
| } | |||
| .accordion-panel-title { | |||
| margin-top: 0; | |||
| margin-bottom: 0; | |||
| color: #252b3a; | |||
| } | |||
| .accordion-panel-title-content{ | |||
| vertical-align: middle; | |||
| display: inline-block; | |||
| width: calc(100% - 32px); | |||
| cursor: default; | |||
| } | |||
| .acc-margin-bottom { | |||
| margin-bottom: 5px; | |||
| } | |||
| .title_text { | |||
| font-size: 12px; | |||
| } | |||
| .ac-display-inblock { | |||
| display: inline-block; | |||
| } | |||
| .cti-mgRight-sm { | |||
| margin-right: 8px; | |||
| } | |||
| .ac-text-normal { | |||
| font-size: 14px; | |||
| color: #575d6c; | |||
| } | |||
| .uc-accordionTitle-black { | |||
| color: #333; | |||
| } | |||
| .accordion-border{ | |||
| border:1px solid #cce2ff; | |||
| } | |||
| .padding0{ | |||
| padding: 0 !important; | |||
| } | |||
| .content-pad{ | |||
| padding: 15px 35px; | |||
| } | |||
| .content-margin{ | |||
| margin:10px 5px ; | |||
| } | |||
| .tab_2_content { | |||
| min-height: 380px; | |||
| margin-left: 10px; | |||
| } | |||
| .ac-grid { | |||
| display: block; | |||
| *zoom: 1; | |||
| } | |||
| .ac-grid-col { | |||
| float: left; | |||
| width: 100%; | |||
| } | |||
| .ac-grid-col2 .ac-grid-col { | |||
| width: 50%; | |||
| } | |||
| .ti-form { | |||
| text-align: left; | |||
| max-width: 100%; | |||
| vertical-align: middle; | |||
| } | |||
| .ti-form>tbody { | |||
| font-size: 12px; | |||
| } | |||
| .ti-form>tbody, .ti-form>tbody>tr { | |||
| vertical-align: inherit; | |||
| } | |||
| .info_text { | |||
| padding-bottom: 20px; | |||
| padding-right: 20px; | |||
| font-size: 12px; | |||
| } | |||
| .ti-text-form-label { | |||
| padding-bottom: 20px; | |||
| padding-right: 20px; | |||
| color: #8a8e99; | |||
| font-size: 12px; | |||
| white-space: nowrap !important; | |||
| width: 80px; | |||
| line-height: 30px; | |||
| } | |||
| .ti-text-form-content{ | |||
| line-height: 30px; | |||
| padding-bottom: 20px; | |||
| } | |||
| .ti-form>tbody>tr>td { | |||
| vertical-align: top; | |||
| white-space: normal; | |||
| } | |||
| td, th { | |||
| padding: 0; | |||
| } | |||
| .ac-grid-col .text-span { | |||
| width: 450px; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| } | |||
| .redo-color{ | |||
| color: #3291F8; | |||
| } | |||
| .ti-action-menu-item:not(:last-child){ | |||
| margin-right: 10px; | |||
| padding-right: 11px; | |||
| text-decoration: none!important; | |||
| color: #526ecc; | |||
| cursor: pointer; | |||
| display: inline-block; | |||
| -moz-user-select: none; | |||
| -webkit-user-select: none; | |||
| -ms-user-select: none; | |||
| -khtml-user-select: none; | |||
| user-select: none; | |||
| position: relative; | |||
| } | |||
| .ti-action-menu-item:not(:last-child):after { | |||
| content: ""; | |||
| display: inline-block; | |||
| position: absolute; | |||
| height: 12px; | |||
| right: 0; | |||
| top: 50%; | |||
| -webkit-transform: translateY(-6px); | |||
| -ms-transform: translateY(-6px); | |||
| -o-transform: translateY(-6px); | |||
| transform: translateY(-6px); | |||
| border-right: 1px solid #dfe1e6; | |||
| } | |||
| .text-width80{ | |||
| width: 100px; | |||
| line-height: 30px; | |||
| } | |||
| .border-according{ | |||
| border: 1px solid #dfe1e6; | |||
| } | |||
| .disabled { | |||
| cursor: default; | |||
| pointer-events: none; | |||
| color: rgba(0,0,0,.6) !important; | |||
| opacity: .45 !important; | |||
| } | |||
| .pad20{ | |||
| border:0px !important; | |||
| } | |||
| .model_file_bread{ | |||
| margin-bottom: -0.5rem !important; | |||
| padding-left: 1rem; | |||
| padding-top: 0.5rem ; | |||
| } | |||
| </style> | |||
| <div id="mask"> | |||
| <div id="loadingPage"> | |||
| <div class="rect1"></div> | |||
| <div class="rect2"></div> | |||
| <div class="rect3"></div> | |||
| <div class="rect4"></div> | |||
| <div class="rect5"></div> | |||
| </div> | |||
| </div> | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="repository new repo ui middle very relaxed page grid"> | |||
| <div class="column"> | |||
| {{template "base/alert" .}} | |||
| <div class="ui container"> | |||
| <h4 class="ui header" id="vertical-segment"> | |||
| <div class="ui breadcrumb"> | |||
| <a class="section" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section backTodeBug" href="{{.RepoLink}}/debugjob?debugListType={{if eq $.debugListType "NPU"}}NPU{{else if eq $.debugListType "CPU/GPU"}}CPU/GPU{{else}}all{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.notebook"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| {{with .task}} | |||
| <div class="active section">{{.DisplayJobName}}</div> | |||
| {{end}} | |||
| </div> | |||
| <div class="ui breadcrumb"> | |||
| <a class="section" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section backTodeBug" href="{{.RepoLink}}/debugjob?debugListType={{if eq $.debugListType "NPU"}}NPU{{else if eq $.debugListType "CPU/GPU"}}CPU/GPU{{else}}all{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.notebook"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <div class="active section">{{.displayJobName}}</div> | |||
| </div> | |||
| </h4> | |||
| <div> | |||
| <div class="ui yellow segment"> | |||
| {{with .task}} | |||
| <p>任务名称: {{.DisplayJobName}}</p> | |||
| {{end}} | |||
| </div> | |||
| <div class="ui green segment"> | |||
| <p>任务结果:</p> | |||
| {{with .taskRes}} | |||
| {{range .TaskStatuses}} | |||
| <table class="ui celled striped table"> | |||
| <tbody> | |||
| <tr> | |||
| <td class="four wide"> 状态 </td> | |||
| <td> {{.State}} </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| {{end}} | |||
| {{end}} | |||
| </div> | |||
| <div class="ui blue segment"> | |||
| {{with .result}} | |||
| <table class="ui celled striped table"> | |||
| <thead> | |||
| <tr> <th colspan="2"> 硬件信息 </th> </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr> | |||
| <td class="four wide"> CPU </td> | |||
| <td>{{.Resource.CPU}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> Memory </td> | |||
| <td>{{.Resource.Memory}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> NvidiaComGpu </td> | |||
| <td>{{.Resource.NvidiaComGpu}}</td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| <table class="ui celled striped table"> | |||
| <thead> | |||
| <tr> <th colspan="2"> 调试信息 </th> </tr> | |||
| </thead> | |||
| <tbody> | |||
| <tr> | |||
| <td class="four wide"> 平台 </td> | |||
| <td> {{.Platform}} </td> | |||
| </tr> | |||
| <tr> | |||
| <td> 开始时间 </td> | |||
| {{if not (eq $.task.StartTime 0)}} | |||
| <td>{{TimeSinceUnix1 $.task.StartTime}}</td> | |||
| {{else}} | |||
| <td>无<td> | |||
| {{end}} | |||
| </tr> | |||
| <tr> | |||
| <td> 结束时间 </td> | |||
| {{if not (eq $.task.EndTime 0)}} | |||
| <td>{{TimeSinceUnix1 $.task.EndTime}}</td> | |||
| {{else}} | |||
| <td>无<td> | |||
| {{end}} | |||
| </tr> | |||
| <tr> | |||
| <td> ExitCode </td> | |||
| <td>{{.JobStatus.AppExitCode}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 退出信息 </td> | |||
| <td>{{.JobStatus.AppExitDiagnostics | nl2br}}</td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| {{end}} | |||
| </div> | |||
| {{range $k ,$v := .version_list_task}} | |||
| <div class="ui accordion border-according" id="accordion{{.VersionName}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
| <input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}"> | |||
| <div class="{{if eq $k 0}}active{{end}} title padding0"> | |||
| <div class="according-panel-heading"> | |||
| <div class="accordion-panel-title"> | |||
| <!--<i class="dropdown icon"></i> --> | |||
| <span class="accordion-panel-title-content"> | |||
| <span> | |||
| <div class="ac-display-inblock title_text acc-margin-bottom"> | |||
| <span class="cti-mgRight-sm"> | |||
| {{if not (eq .StartTime 0)}} | |||
| <td>{{TimeSinceUnix1 .StartTime}}</td> | |||
| {{else}} | |||
| <td>{{TimeSinceUnix1 .CreatedUnix}}<td> | |||
| {{end}} | |||
| </span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
| <span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span> | |||
| <span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span> | |||
| </div> | |||
| </span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="{{if eq $k 0}}active{{end}} content"> | |||
| <div class="content-pad"> | |||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||
| <a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||
| <a class="item" data-tab="second{{$k}}" onclick="javascript:parseLog()">{{$.i18n.Tr "repo.cloudbrain.runinfo"}}</a> | |||
| </div> | |||
| <div class="ui tab active" data-tab="first{{$k}}"> | |||
| <div style="padding-top: 10px;"> | |||
| <div class="tab_2_content"> | |||
| <div class="ac-grid ac-grid-col2"> | |||
| <div class="ac-grid-col"> | |||
| <table class="ti-form"> | |||
| <tbody class="ti-text-form"> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain_task"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.DisplayJobName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.status"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-status"> | |||
| {{.Status}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain_creator"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-mirror"> | |||
| {{.User.Name}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.computing_resources"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-computeresource"> | |||
| {{.ComputeResource}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.task_type"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-computeresource"> | |||
| {{.JobType}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.gpu_type"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{$.resource_type}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain.time.starttime"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-startTime"> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| -- | |||
| {{end}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain.time.endtime"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-EndTime"> | |||
| {{if not (eq .EndTime 0)}} | |||
| {{TimeSinceUnix1 .EndTime}} | |||
| {{else}} | |||
| -- | |||
| {{end}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| <div class="ac-grid-col"> | |||
| <table class="ti-form"> | |||
| <tbody class="ti-text-form"> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.mirror"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-mirror"> | |||
| {{.Image}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.dataset"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName"> | |||
| {{$.datasetname}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.standard"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{$.i18n.Tr "cloudbrain.gpu_num"}}:{{$.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{$.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{$.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{$.ShareMemMiB}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.dataset_storage_path"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="dataset_storage_path"> | |||
| {{$.dataset_path}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.model_storage_path"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="model_storage_path"> | |||
| {{$.model_path}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.code_storage_path"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="code_storage_path"> | |||
| {{$.code_path}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-duration"> | |||
| {{$.duration}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="ui tab" data-tab="second{{$k}}"> | |||
| <div> | |||
| <div class="ui message message{{.VersionName}}" style="display: none;"> | |||
| <div id="header"></div> | |||
| </div> | |||
| <div class="ui attached log" id="log{{.VersionName}}" style="height: 390px !important; overflow: auto;"> | |||
| <input type="hidden" id="json_value" value="{{$.result.JobStatus.AppExitDiagnostics}}"> | |||
| <span id="info_display" class="info_text"> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} {{template "base/paginate" .}} | |||
| </div> | |||
| <!-- 确认模态框 --> | |||
| <div id="deletemodel"> | |||
| <div class="ui basic modal"> | |||
| <div class="ui icon header"> | |||
| <i class="trash icon"></i> {{.i18n.Tr "cloudbrain.delete_task"}} | |||
| </div> | |||
| <div class="content"> | |||
| <p>{{.i18n.Tr "cloudbrain.task_delete_confirm"}}</p> | |||
| </div> | |||
| <div class="actions"> | |||
| <div class="ui red basic inverted cancel button"> | |||
| <i class="remove icon"></i> {{.i18n.Tr "cloudbrain.operate_cancel"}} | |||
| </div> | |||
| <div class="ui green basic inverted ok button"> | |||
| <i class="checkmark icon"></i> {{.i18n.Tr "cloudbrain.operate_confirm"}} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| $('.menu .item').tab() | |||
| $(document).ready(function(){ | |||
| $('.ui.accordion').accordion({selector:{trigger:'.icon'}}); | |||
| }); | |||
| $(document).ready(function(){ | |||
| $('.secondary.menu .item').tab(); | |||
| }); | |||
| function parseLog(){ | |||
| let jsonValue = document.getElementById("json_value").value; | |||
| let jsonObj = JSON.parse(jsonValue); | |||
| let podRoleName = jsonObj["podRoleName"]; | |||
| let html = ""; | |||
| if (podRoleName != null){ | |||
| let task0 = podRoleName["task1-0"]; | |||
| let podEvents = jsonObj["podEvents"]; | |||
| let podEventArray = podEvents[task0]; | |||
| if(podEventArray != null){ | |||
| for(var i=0; i < podEventArray.length;i++){ | |||
| html +="<p><b>[" +podEventArray[i]["reason"] + "]</b></p>"; | |||
| html +="<p>" +podEventArray[i]["message"] + "</p>"; | |||
| html +="<p>" +podEventArray[i]["action"] + "</p>"; | |||
| } | |||
| } | |||
| let extras= jsonObj["extras"]; | |||
| if(extras != null){ | |||
| for(var i=0; i < extras.length;i++){ | |||
| html +="<p><b>[" +extras[i]["reason"] + "]</b></p>"; | |||
| html +="<p>" +extras[i]["message"] + "</p>"; | |||
| html +="<p>" +extras[i]["action"] + "</p>"; | |||
| } | |||
| } | |||
| } | |||
| document.getElementById("info_display").innerHTML=html; | |||
| } | |||
| </script> | |||
| @@ -169,9 +169,9 @@ | |||
| <div class="inline unite min_title field required"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
| {{if .bootFile}} | |||
| <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| <input style="width: 35.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| {{else}} | |||
| <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" > | |||
| <input style="width: 35.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" > | |||
| {{end}} | |||
| <span> | |||
| <i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i> | |||
| @@ -179,17 +179,9 @@ | |||
| <a href="https://git.openi.org.cn/OpenIOSSG/MNIST_PytorchExample_GPU" target="_blank">查看样例</a> | |||
| </div> | |||
| <div class="required unite min_title inline field" style="position: relative;"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
| <select id="cloudbrain_dataset" class="ui search dropdown width80" placeholder="选择数据集" style='width:385px' name="attachment" required> | |||
| {{range .attachments}} | |||
| <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
| {{end}} | |||
| </select> | |||
| <span class="tooltips">训练脚本存储在/code中,数据集存储在/dataset中,训练输出请存储在/model中以供后续下载。</span> | |||
| </div> | |||
| {{template "custom/select_dataset_train" .}} | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">训练脚本存储在/code中,数据集存储在/dataset中,训练输出请存储在/model中以供后续下载。</span> | |||
| <div class="inline unite min_title field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| @@ -199,7 +199,7 @@ | |||
| </div> | |||
| </div> | |||
| {{range $k, $v :=.Attachments}} | |||
| <div class="ui grid stackable item" id="{{.FileChunk.UUID}}"> | |||
| <div class="ui grid stackable item" id="{{.UUID}}"> | |||
| <div class="row"> | |||
| <!-- 数据集名称 --> | |||
| @@ -266,8 +266,8 @@ | |||
| <a class="ui basic blue button" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{$.i18n.Tr "preview"}}</a> | |||
| {{end}} | |||
| {{if and (.CanDel) (not $.Repository.IsPrivate)}} | |||
| <span class="ui basic blue button" style="color: #13c28d !important;" @click="setPrivate('{{.FileChunk.UUID}}',false,{{$k}})" v-if="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_public"}}</span> | |||
| <span class="ui basic blue button" style="color: #fa8c16 !important;" @click="setPrivate('{{.FileChunk.UUID}}',true,{{$k}})" v-else="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_private"}}</span> | |||
| <span class="ui basic blue button" style="color: #13c28d !important;" @click="setPrivate('{{.UUID}}',false,{{$k}})" v-if="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_public"}}</span> | |||
| <span class="ui basic blue button" style="color: #fa8c16 !important;" @click="setPrivate('{{.UUID}}',true,{{$k}})" v-else="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_private"}}</span> | |||
| {{end}} | |||
| <!-- {{if $.CanRead}} | |||
| <a class="ui basic blue button" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'>标注</a> | |||
| @@ -281,13 +281,13 @@ | |||
| </span> | |||
| <el-dropdown-menu slot="dropdown"> | |||
| <el-dropdown-item class="clipboard" data-clipboard-text="{{.DownloadURL}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_url"}}</el-dropdown-item> | |||
| <el-dropdown-item class="clipboard" data-clipboard-text="{{.FileChunk.Md5}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_md5"}}</el-dropdown-item> | |||
| <el-dropdown-item class="clipboard" data-clipboard-text="{{.Md5}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_md5"}}</el-dropdown-item> | |||
| {{if and ($.CanWrite) (eq .DecompressState 1) }} | |||
| <el-dropdown-item @click.native="gotoAnnotate('{{$.RepoLink}}','{{.UUID}}',{{.Type}})">{{$.i18n.Tr "dataset.annotation"}}</el-dropdown-item> | |||
| {{end}} | |||
| {{if .CanDel}} | |||
| <el-dropdown-item @click.native="gotoDatasetEidt('{{$.RepoLink}}',{{.ID}})">{{$.i18n.Tr "dataset.modify_description"}}</el-dropdown-item> | |||
| <el-dropdown-item style="color: red;" @click.native="delDataset('{{.FileChunk.UUID}}')">{{$.i18n.Tr "dataset.delete"}}</el-dropdown-item> | |||
| <el-dropdown-item style="color: red;" @click.native="delDataset('{{.UUID}}')">{{$.i18n.Tr "dataset.delete"}}</el-dropdown-item> | |||
| {{end}} | |||
| </el-dropdown-menu> | |||
| </el-dropdown> | |||
| @@ -27,10 +27,10 @@ | |||
| </div> | |||
| <div class="field"> | |||
| <div class="files"></div> | |||
| <div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div> | |||
| <div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}" data-max-file-tooltips="{{.i18n.Tr "dropzone.max_file_tooltips"}}" data-max-size-tooltips="{{.i18n.Tr "dropzone.max_size_tooltips"}}"><div class="maxfilesize ui red message" style="display: none;margin: 2.5rem;"></div></div> | |||
| </div> | |||
| {{template "repo/editor/commit_form" .}} | |||
| </form> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| {{template "base/footer" .}} | |||
| @@ -169,24 +169,10 @@ | |||
| </select> | |||
| </div> | |||
| <!-- 数据集 --> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
| <select class="ui dropdown width35" id="trainjob_datasets" name="attachment" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}" required> | |||
| {{if $.uuid}} | |||
| <option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option> | |||
| {{end}} | |||
| {{range .attachments}} | |||
| <option value="">{{$.i18n.Tr "cloudbrain.select_dataset"}}</option> | |||
| <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
| {{end}} | |||
| </select> | |||
| <span> | |||
| <i class="question circle icon" data-content="{{.i18n.Tr "cloudbrain.dataset_path_rule"}}" data-position="top center" data-variation="inverted mini"></i> | |||
| </span> | |||
| </div> | |||
| <!-- 启动文件 --> | |||
| {{template "custom/select_dataset_train" .}} | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||
| <div class="inline unite min_title field required"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
| {{if .bootFile}} | |||
| <input style="width: 35.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| {{else}} | |||
| @@ -1,68 +1,470 @@ | |||
| {{template "base/head" .}} | |||
| <style> | |||
| .according-panel-heading{ | |||
| box-sizing: border-box; | |||
| padding: 8px 16px; | |||
| color: #252b3a; | |||
| background-color: #f2f5fc; | |||
| line-height: 1.5; | |||
| cursor: pointer; | |||
| -moz-user-select: none; | |||
| -webkit-user-select: none; | |||
| -ms-user-select: none; | |||
| -khtml-user-select: none; | |||
| user-select: none; | |||
| } | |||
| .accordion-panel-title { | |||
| margin-top: 0; | |||
| margin-bottom: 0; | |||
| color: #252b3a; | |||
| } | |||
| .accordion-panel-title-content{ | |||
| vertical-align: middle; | |||
| display: inline-block; | |||
| width: calc(100% - 32px); | |||
| cursor: default; | |||
| } | |||
| .acc-margin-bottom { | |||
| margin-bottom: 5px; | |||
| } | |||
| .title_text { | |||
| font-size: 12px; | |||
| } | |||
| .ac-display-inblock { | |||
| display: inline-block; | |||
| } | |||
| .cti-mgRight-sm { | |||
| margin-right: 8px; | |||
| } | |||
| .ac-text-normal { | |||
| font-size: 14px; | |||
| color: #575d6c; | |||
| } | |||
| .uc-accordionTitle-black { | |||
| color: #333; | |||
| } | |||
| .accordion-border{ | |||
| border:1px solid #cce2ff; | |||
| } | |||
| .padding0{ | |||
| padding: 0 !important; | |||
| } | |||
| .content-pad{ | |||
| padding: 15px 35px; | |||
| } | |||
| .content-margin{ | |||
| margin:10px 5px ; | |||
| } | |||
| .tab_2_content { | |||
| min-height: 460px; | |||
| margin-left: 10px; | |||
| } | |||
| .ac-grid { | |||
| display: block; | |||
| *zoom: 1; | |||
| } | |||
| .ac-grid-col { | |||
| float: left; | |||
| width: 100%; | |||
| } | |||
| .ac-grid-col2 .ac-grid-col { | |||
| width: 50%; | |||
| } | |||
| .ti-form { | |||
| text-align: left; | |||
| max-width: 100%; | |||
| vertical-align: middle; | |||
| } | |||
| .ti-form>tbody { | |||
| font-size: 12px; | |||
| } | |||
| .ti-form>tbody, .ti-form>tbody>tr { | |||
| vertical-align: inherit; | |||
| } | |||
| .info_text { | |||
| padding-bottom: 20px; | |||
| padding-right: 20px; | |||
| font-size: 12px; | |||
| } | |||
| .ti-text-form-label { | |||
| padding-bottom: 20px; | |||
| padding-right: 20px; | |||
| color: #8a8e99; | |||
| font-size: 12px; | |||
| white-space: nowrap !important; | |||
| width: 80px; | |||
| line-height: 30px; | |||
| } | |||
| .ti-text-form-content{ | |||
| line-height: 30px; | |||
| padding-bottom: 20px; | |||
| } | |||
| .ti-form>tbody>tr>td { | |||
| vertical-align: top; | |||
| white-space: normal; | |||
| } | |||
| td, th { | |||
| padding: 0; | |||
| } | |||
| .ac-grid-col .text-span { | |||
| width: 450px; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| } | |||
| .text-span-new { | |||
| width: 800px; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| height: 80px; | |||
| word-break: break-all; | |||
| } | |||
| .redo-color{ | |||
| color: #3291F8; | |||
| } | |||
| .ti-action-menu-item:not(:last-child){ | |||
| margin-right: 10px; | |||
| padding-right: 11px; | |||
| text-decoration: none!important; | |||
| color: #526ecc; | |||
| cursor: pointer; | |||
| display: inline-block; | |||
| -moz-user-select: none; | |||
| -webkit-user-select: none; | |||
| -ms-user-select: none; | |||
| -khtml-user-select: none; | |||
| user-select: none; | |||
| position: relative; | |||
| } | |||
| .ti-action-menu-item:not(:last-child):after { | |||
| content: ""; | |||
| display: inline-block; | |||
| position: absolute; | |||
| height: 12px; | |||
| right: 0; | |||
| top: 50%; | |||
| -webkit-transform: translateY(-6px); | |||
| -ms-transform: translateY(-6px); | |||
| -o-transform: translateY(-6px); | |||
| transform: translateY(-6px); | |||
| border-right: 1px solid #dfe1e6; | |||
| } | |||
| .text-width80{ | |||
| width: 100px; | |||
| line-height: 30px; | |||
| } | |||
| .border-according{ | |||
| border: 1px solid #dfe1e6; | |||
| } | |||
| .disabled { | |||
| cursor: default; | |||
| pointer-events: none; | |||
| color: rgba(0,0,0,.6) !important; | |||
| opacity: .45 !important; | |||
| } | |||
| .pad20{ | |||
| border:0px !important; | |||
| } | |||
| .model_file_bread{ | |||
| margin-bottom: -0.5rem !important; | |||
| padding-left: 1rem; | |||
| padding-top: 0.5rem ; | |||
| } | |||
| </style> | |||
| <div id="mask"> | |||
| <div id="loadingPage"> | |||
| <div class="rect1"></div> | |||
| <div class="rect2"></div> | |||
| <div class="rect3"></div> | |||
| <div class="rect4"></div> | |||
| <div class="rect5"></div> | |||
| </div> | |||
| </div> | |||
| <div class="repository"> | |||
| {{template "repo/header" .}} | |||
| <div class="repository new repo ui middle very relaxed page grid"> | |||
| <div class="column"> | |||
| {{template "base/alert" .}} | |||
| <div class="ui container"> | |||
| <h4 class="ui header" id="vertical-segment"> | |||
| <div class="ui breadcrumb"> | |||
| <a class="section" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section backTodeBug" href="{{.RepoLink}}/debugjob?debugListType={{if eq $.debugListType "NPU"}}NPU{{else if eq $.debugListType "CPU/GPU"}}CPU/GPU{{else}}all{{end}}"> | |||
| <a class="section" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section backTodeBug" href="{{.RepoLink}}/debugjob?debugListType={{if eq $.debugListType "NPU"}}NPU{{else if eq $.debugListType "CPU/GPU"}}CPU/GPU{{else}}all{{end}}"> | |||
| {{$.i18n.Tr "repo.modelarts.notebook"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| {{with .task}} | |||
| <div class="active section">{{.DisplayJobName}}</div> | |||
| {{end}} | |||
| </div> | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| {{with .task}} | |||
| <div class="active section">{{.DisplayJobName}}</div> | |||
| {{end}} | |||
| </div> | |||
| </h4> | |||
| <div> | |||
| <div class="ui yellow segment"> | |||
| {{with .task}} | |||
| <p>任务名称: {{.DisplayJobName}}</p> | |||
| {{end}} | |||
| </div> | |||
| <div class="ui green segment"> | |||
| <p>任务详情:</p> | |||
| {{with .result}} | |||
| <table class="ui celled striped table"> | |||
| <tbody> | |||
| <tr> | |||
| <td class="four wide"> 状态 </td> | |||
| <td> {{.Status}} </td> | |||
| </tr> | |||
| <tr> | |||
| <td> 描述 </td> | |||
| <td style="max-width: 480px; word-wrap:break-word">{{$.task.Description}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 镜像名称 </td> | |||
| <td>{{$.task.Image}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 数据集下载地址 </td> | |||
| <td style="max-width: 480px; word-wrap:break-word">{{$.datasetDownloadLink}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 开始时间 </td> | |||
| <td>{{.CreateTime}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 最后更新时间 </td> | |||
| <td>{{.LatestUpdateTime}}</td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| {{end}} | |||
| </div> | |||
| {{with .task}} | |||
| <div class="ui accordion border-according" id="accordion" data-repopath="" data-jobid="" data-version=""> | |||
| <div class="active title padding0"> | |||
| <div class="according-panel-heading"> | |||
| <div class="accordion-panel-title"> | |||
| <i class="dropdown icon"></i> | |||
| <span class="accordion-panel-title-content"> | |||
| <span> | |||
| <div class="ac-display-inblock title_text acc-margin-bottom"> | |||
| <span class="cti-mgRight-sm"> | |||
| {{if not (eq .StartTime 0)}} | |||
| <td>{{TimeSinceUnix1 .StartTime}}</td> | |||
| {{else}} | |||
| <td>{{TimeSinceUnix1 .CreatedUnix}}<td> | |||
| {{end}} | |||
| </span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
| <span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span> | |||
| <span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span> | |||
| </div> | |||
| </span> | |||
| </span> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="active content"> | |||
| <div class="content-pad"> | |||
| <div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||
| <a class="active item" data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||
| </div> | |||
| <div class="ui tab active" data-tab="first"> | |||
| <div style="padding-top: 10px;"> | |||
| <div class="tab_2_content"> | |||
| <div class="ac-grid ac-grid-col2"> | |||
| <div class="ac-grid-col"> | |||
| <table class="ti-form"> | |||
| <tbody class="ti-text-form"> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain_task"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.DisplayJobName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.status"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-status"> | |||
| {{.Status}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain_creator"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-mirror"> | |||
| {{.User.Name}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.computing_resources"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-computeresource"> | |||
| {{.ComputeResource}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-duration"> | |||
| {{$.duration}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain.datasetdownload"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span-new" id="model_description"> | |||
| {{$.datasetDownloadLink}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.description"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span-new" id="model_description"> | |||
| {{.Description}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| <div class="ac-grid-col"> | |||
| <table class="ti-form"> | |||
| <tbody class="ti-text-form"> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "cloudbrain.mirror"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-mirror"> | |||
| {{.Image}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.dataset"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName"> | |||
| {{.DatasetName}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.standard"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{$.resource_spec}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job.start_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-startTime"> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| -- | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "repo.cloudbrain.time.endtime"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-EndTime"> | |||
| {{if not (eq .EndTime 0)}} | |||
| {{TimeSinceUnix1 .EndTime}} | |||
| {{else}} | |||
| -- | |||
| {{end}} | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| {{template "base/paginate" .}} | |||
| </div> | |||
| <!-- 确认模态框 --> | |||
| <div id="deletemodel"> | |||
| <div class="ui basic modal"> | |||
| <div class="ui icon header"> | |||
| <i class="trash icon"></i> {{.i18n.Tr "cloudbrain.delete_task"}} | |||
| </div> | |||
| <div class="content"> | |||
| <p>{{.i18n.Tr "cloudbrain.task_delete_confirm"}}</p> | |||
| </div> | |||
| <div class="actions"> | |||
| <div class="ui red basic inverted cancel button"> | |||
| <i class="remove icon"></i> {{.i18n.Tr "cloudbrain.operate_cancel"}} | |||
| </div> | |||
| <div class="ui green basic inverted ok button"> | |||
| <i class="checkmark icon"></i> {{.i18n.Tr "cloudbrain.operate_confirm"}} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| $('.menu .item').tab() | |||
| $(document).ready(function(){ | |||
| $('.ui.accordion').accordion({selector:{trigger:'.icon'}}); | |||
| }); | |||
| $(document).ready(function(){ | |||
| $('.secondary.menu .item').tab(); | |||
| }); | |||
| let userName | |||
| let repoPath | |||
| let jobName | |||
| $(document).ready(function(){ | |||
| let url = window.location.href; | |||
| let urlArr = url.split('/') | |||
| userName = urlArr.slice(-5)[0] | |||
| repoPath = urlArr.slice(-4)[0] | |||
| jobName = urlArr.slice(-1)[0] | |||
| }) | |||
| </script> | |||
| @@ -158,29 +158,18 @@ | |||
| <div class="inline unite min_title field required"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
| {{if .bootFile}} | |||
| <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| <input style="width: 35.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| {{else}} | |||
| <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" > | |||
| <input style="width: 35.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" > | |||
| {{end}} | |||
| <span> | |||
| <i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i> | |||
| </span> | |||
| <a href="https://git.openi.org.cn/OpenIOSSG/MINIST_Example" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | |||
| </div> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
| <select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}"> | |||
| {{if $.uuid}} | |||
| <option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option> | |||
| {{end}} | |||
| {{range .attachments}} | |||
| <option value="">{{$.i18n.Tr "cloudbrain.select_dataset"}}</option> | |||
| <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
| {{end}} | |||
| </select> | |||
| <span class="tooltips">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||
| </div> | |||
| {{template "custom/select_dataset_train" .}} | |||
| <span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||
| <div class="inline unite min_title field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
| <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
| @@ -40,7 +40,7 @@ | |||
| <div class="ui right file-actions"> | |||
| {{if .Repository.CanEnableEditor}} | |||
| {{if .CanEditFile}} | |||
| <a href="{{.RepoLink}}/_edit/{{EscapePound .BranchName}}/{{EscapePound .ReadmeName}}"><span class="btn-octicon poping up" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil" 16}}</span></a> | |||
| <a href="{{.RepoLink}}/_edit/{{EscapePound .BranchName}}/{{EscapePound .ReadmeRelativePath}}"><span class="btn-octicon poping up" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil" 16}}</span></a> | |||
| {{else}} | |||
| <span class="btn-octicon poping up disabled" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil" 16}}</span> | |||
| {{end}} | |||
| @@ -48,7 +48,7 @@ | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| {{if not .ReadmeInList}} | |||
| <div class="file-header-right"> | |||
| <div class="ui right file-actions"> | |||
| @@ -133,7 +133,43 @@ | |||
| <template slot-scope="scope"> | |||
| {{scope.row.RegistDate | transformTimestamp}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="CloudBrainTaskNum" | |||
| label="云脑任务数" | |||
| width="120px" | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="CloudBrainRunTime" | |||
| label="云脑运行时间(小时)" | |||
| width="120px" | |||
| align="center"> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.CloudBrainRunTime | roundingToHour}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="CommitDatasetNum" | |||
| label="上传(提交)数据集文件数" | |||
| width="120px" | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="CommitModelCount" | |||
| label="提交模型数" | |||
| width="120px" | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="UserIndex" | |||
| label="用户指数" | |||
| width="120px" | |||
| align="center"> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.UserIndex | rounding}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="DataDate" | |||
| label="系统统计时间" | |||
| @@ -178,7 +214,7 @@ | |||
| value_time: '', | |||
| search:'', | |||
| data:'', | |||
| columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CodeMergeCount'},{title: 'commit数',key:'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'用户注册时间',key:'RegistDate'},{title:'系统统计时间',key:'CountDate'}], | |||
| columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CodeMergeCount'},{title: 'commit数',key:'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'用户注册时间',key:'RegistDate'},{title:'云脑任务数',key:'CloudBrainTaskNum'},{title:'云脑运行时间(小时)',key:'CloudBrainRunTime'},{title:'上传(提交)数据集文件数',key:'CommitDatasetNum'},{title:'提交模型数',key:'CommitModelCount'},{title:'用户指数',key:'UserIndex'},{title:'系统统计时间',key:'CountDate'}], | |||
| blob:'', | |||
| fileName:'', | |||
| dynamic:7, | |||
| @@ -351,6 +387,12 @@ | |||
| }, | |||
| filters:{ | |||
| rounding (value) { | |||
| return Number(value).toFixed(2) | |||
| }, | |||
| roundingToHour (value) { | |||
| return (Number(value)/3600).toFixed(2) | |||
| }, | |||
| transformTimestamp(timestamp){ | |||
| let a = new Date(timestamp*1000); | |||
| const date = new Date(a); | |||
| @@ -2751,9 +2751,23 @@ $(document).ready(async () => { | |||
| $('td[data-href]').click(function () { | |||
| window.location = $(this).data('href'); | |||
| }); | |||
| // 在String原型对象上添加format方法 | |||
| String.prototype.format = function(){ | |||
| let str = this; | |||
| if(arguments.length == 0){ | |||
| return str; | |||
| }else{ | |||
| Object.keys(arguments).forEach((item,index)=>{ | |||
| str = str.replace(/\?/,arguments[item]) | |||
| }) | |||
| return str | |||
| } | |||
| } | |||
| // Dropzone | |||
| const $dropzone = $('#dropzone'); | |||
| let maxFileTooltips=$dropzone.data('max-file-tooltips').format($dropzone.data('max-file'),$dropzone.data('max-size')) | |||
| let maxSizeTooltips=$dropzone.data('max-size-tooltips').format($dropzone.data('max-file')) | |||
| if ($dropzone.length > 0) { | |||
| const filenameDict = {}; | |||
| @@ -2788,6 +2802,22 @@ $(document).ready(async () => { | |||
| }); | |||
| } | |||
| }); | |||
| this.on('addedfile',(file)=>{ | |||
| if(file.size/(1000*1000)>$dropzone.data('max-size')){ | |||
| this.removeFile(file) | |||
| $('.maxfilesize.ui.red.message').text(maxFileTooltips) | |||
| $('.maxfilesize.ui.red.message').css('display','block') | |||
| }else{ | |||
| $('.maxfilesize.ui.red.message').css('display','none') | |||
| } | |||
| }); | |||
| this.on('maxfilesexceeded',(file)=>{ | |||
| this.removeFile(file) | |||
| $('.maxfilesize.ui.red.message').text(maxSizeTooltips) | |||
| $('.maxfilesize.ui.red.message').css('display','block') | |||
| }) | |||
| } | |||
| }); | |||
| } | |||
| @@ -12,6 +12,11 @@ a { | |||
| .ui .text.yellow a:hover { | |||
| color: #f2711c!important | |||
| } | |||
| .ui.small.label.topic{ | |||
| margin-bottom: 0; | |||
| font-weight: 400; | |||
| } | |||
| .mb-1 { | |||
| margin-bottom: 8px !important; | |||
| } | |||
| @@ -142,6 +147,11 @@ footer { | |||
| width:auto; | |||
| margin:10px auto; | |||
| } | |||
| .ui.card>.extra, .ui.cards>.card>.extra{ | |||
| border-top:none !important; | |||
| padding: .5em .5em 1em; | |||
| } | |||
| #index-project .ui.card>.content, #index-project.ui.cards>.card>.content{ | |||
| padding: 0.5em 0.2em; | |||
| } | |||
| @@ -811,6 +821,89 @@ display: block; | |||
| box-shadow: -15px 0px 10px #fff; | |||
| } | |||
| .content_top10{ | |||
| padding:10px; | |||
| padding-top:0px; | |||
| } | |||
| .re_con{ | |||
| color: rgba(136, 136, 136, 100); | |||
| font-size: 14px; | |||
| text-align: center; | |||
| font-family: SourceHanSansSC-light; | |||
| } | |||
| .title_re{ | |||
| margin-top: 50px !important; | |||
| } | |||
| .card_list { | |||
| width: calc(33.33333333333333% - 2em); | |||
| margin-left: 1em; | |||
| margin-right: 1em | |||
| } | |||
| .list_title{ | |||
| height: 52px; | |||
| text-align: center | |||
| } | |||
| .star_title{ | |||
| background-color: #3291F8; | |||
| } | |||
| .memb_title{ | |||
| background-color: #706FE3; | |||
| } | |||
| .act_title{ | |||
| background-color: #13C28D; | |||
| } | |||
| .p_text{ | |||
| line-height: 50px; | |||
| text-align:left; | |||
| padding-left:15px; | |||
| font-size:18px; | |||
| color:#FFFFFF; | |||
| } | |||
| .orgs { | |||
| display: flex; | |||
| flex-flow: row wrap; | |||
| padding: 0; | |||
| margin-top:20px | |||
| } | |||
| .orgs li { | |||
| display: flex; | |||
| border-bottom: 0!important; | |||
| padding: 3px!important; | |||
| } | |||
| .p_score{ | |||
| line-height: 28px; | |||
| width: 100%; | |||
| /* padding-right: 20px; */ | |||
| text-align: right; | |||
| } | |||
| .org_line_hight{ | |||
| line-height: 28px; | |||
| } | |||
| .org_icon{ | |||
| margin-top: 10px; | |||
| margin-right: 10px; | |||
| padding-left: 15px; | |||
| } | |||
| .org_icon_num{ | |||
| margin-left: 2px; | |||
| margin-right: 13px; | |||
| } | |||
| .org_icon_color{ | |||
| color: #FA8C16; | |||
| } | |||
| .li_name{ | |||
| list-style:none; | |||
| width: 55%; | |||
| } | |||
| .li_avatar{ | |||
| list-style: none; | |||
| width: 10%; | |||
| } | |||
| .li_score{ | |||
| list-style:none; | |||
| margin-left: 2px; | |||
| } | |||
| /**seach**/ | |||
| /**搜索导航条适配窄屏**/ | |||
| .seachnav{ | |||
| @@ -851,6 +944,7 @@ display: block; | |||
| .highlight{ | |||
| color: red; | |||
| } | |||
| .ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content { | |||
| width: calc(100% - 4.0em); | |||
| margin-left: 0; | |||