# Conflicts: # templates/repo/editor/upload.tmpltags/v1.22.4.1^2
| @@ -44,12 +44,6 @@ | |||
| -webkit-line-clamp: 2; | |||
| -webkit-box-orient: vertical; | |||
| } | |||
| .ui.label{ | |||
| font-weight: normal; | |||
| } | |||
| .active { | |||
| color: #0366D6 !important; | |||
| } | |||
| .opacity5{ opacity:0.5;} | |||
| .radius15{ border-radius:1.5rem !important; } | |||
| @@ -287,70 +281,6 @@ | |||
| position: relative; | |||
| } | |||
| /**seach**/ | |||
| /**搜索导航条适配窄屏**/ | |||
| .seachnav{ | |||
| overflow-x: auto; | |||
| overflow-y: hidden; | |||
| scrollbar-width: none; /* firefox */ | |||
| -ms-overflow-style: none; /* IE 10+ */ | |||
| } | |||
| .seachnav::-webkit-scrollbar { | |||
| display: none; /* Chrome Safari */ | |||
| } | |||
| .ui.green.button, .ui.green.buttons .button{ | |||
| background-color: #5BB973; | |||
| } | |||
| .seach .repos--seach{ | |||
| padding-bottom: 0; | |||
| border-bottom: none; | |||
| } | |||
| .seach .ui.secondary.pointing.menu{ | |||
| border-bottom: none; | |||
| } | |||
| .seach .ui.secondary.pointing.menu .item > i{ | |||
| margin-right: 5px; | |||
| } | |||
| .seach .ui.secondary.pointing.menu .active.item{ | |||
| border-bottom-width: 2px; | |||
| margin: 0 0 -1px; | |||
| } | |||
| .seach .ui.menu .active.item>.label { | |||
| background: #1684FC; | |||
| color: #FFF; | |||
| } | |||
| .seach .ui.menu .item>.label:not(.active.item>.label) { | |||
| background: #e8e8e8; | |||
| color: rgba(0,0,0,.6); | |||
| } | |||
| .highlight{ | |||
| color: red; | |||
| } | |||
| .ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content { | |||
| width: calc(100% - 3.0em); | |||
| margin-left: 0; | |||
| } | |||
| .seach .ui.list .list>.item .header, .seach .ui.list>.item .header{ | |||
| margin-bottom: 0.5em; | |||
| font-size: 1.4rem !important; | |||
| font-weight: normal; | |||
| } | |||
| .seach .time, .seach .time a{ | |||
| font-size: 12px; | |||
| color: grey; | |||
| } | |||
| .seach .list .item.members .ui.avatar.image { | |||
| width: 3.2em; | |||
| height: 3.2em; | |||
| } | |||
| .ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content { | |||
| width: calc(100% - 4.0em); | |||
| margin-left: 0; | |||
| } | |||
| @media only screen and (max-width: 767px) { | |||
| .am-mt-30{ margin-top: 1.5rem !important;} | |||
| .ui.secondary.hometop.segment{ | |||
| @@ -57,6 +57,7 @@ const ( | |||
| ActionCreateInferenceTask // 28 | |||
| ActionCreateBenchMarkTask //29 | |||
| ActionCreateNewModelTask //30 | |||
| ActionCreateGPUTrainTask //31 | |||
| ) | |||
| // Action represents user operation type and other information to | |||
| @@ -51,6 +51,7 @@ type Attachment struct { | |||
| FileChunk *FileChunk `xorm:"-"` | |||
| CanDel bool `xorm:"-"` | |||
| Uploader *User `xorm:"-"` | |||
| Md5 string `xorm:"-"` | |||
| } | |||
| type AttachmentUsername struct { | |||
| @@ -20,9 +20,17 @@ type CloudbrainStatus string | |||
| type JobType string | |||
| type ModelArtsJobStatus string | |||
| const ( | |||
| TypeCloudBrainOne int = iota | |||
| TypeCloudBrainTwo | |||
| TypeCloudBrainAll = -1 | |||
| ) | |||
| const ( | |||
| NPUResource = "NPU" | |||
| GPUResource = "CPU/GPU" | |||
| AllResource = "all" | |||
| //notebook storage category | |||
| EVSCategory = "EVS" | |||
| @@ -87,6 +95,8 @@ const ( | |||
| ModelArtsTrainJobCheckRunning ModelArtsJobStatus = "CHECK_RUNNING" //审核作业正在运行中 | |||
| ModelArtsTrainJobCheckRunningCompleted ModelArtsJobStatus = "CHECK_RUNNING_COMPLETED" //审核作业已经完成 | |||
| ModelArtsTrainJobCheckFailed ModelArtsJobStatus = "CHECK_FAILED" //审核作业失败 | |||
| DURATION_STR_ZERO = "00:00:00" | |||
| ) | |||
| type Cloudbrain struct { | |||
| @@ -160,7 +170,9 @@ func (task *Cloudbrain) ComputeAndSetDuration() { | |||
| if task.StartTime == 0 { | |||
| d = 0 | |||
| } else if task.EndTime == 0 { | |||
| d = time.Now().Unix() - task.StartTime.AsTime().Unix() | |||
| if !task.IsTerminal() { | |||
| d = time.Now().Unix() - task.StartTime.AsTime().Unix() | |||
| } | |||
| } else { | |||
| d = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | |||
| } | |||
| @@ -172,9 +184,14 @@ func (task *Cloudbrain) ComputeAndSetDuration() { | |||
| task.TrainJobDuration = ConvertDurationToStr(d) | |||
| } | |||
| func (task *Cloudbrain) IsTerminal() bool { | |||
| status := task.Status | |||
| return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) || status == string(ModelArtsStopped) || status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded) | |||
| } | |||
| func ConvertDurationToStr(duration int64) string { | |||
| if duration == 0 { | |||
| return "00:00:00" | |||
| return DURATION_STR_ZERO | |||
| } | |||
| return util.AddZero(duration/3600) + ":" + util.AddZero(duration%3600/60) + ":" + util.AddZero(duration%60) | |||
| } | |||
| @@ -191,6 +208,19 @@ func IsCloudBrainOneDebugJobTerminal(status string) bool { | |||
| return status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded) | |||
| } | |||
| func ParseAndSetDurationFromCloudBrainOne(result JobResultPayload, task *Cloudbrain) { | |||
| isActivated := result.JobStatus.CreatedTime > 0 | |||
| if task.StartTime == 0 && isActivated { | |||
| task.StartTime = timeutil.TimeStamp(result.JobStatus.CreatedTime / 1000) | |||
| } | |||
| if task.EndTime == 0 && IsCloudBrainOneDebugJobTerminal(task.Status) && isActivated { | |||
| if result.JobStatus.CompletedTime > 0 { | |||
| task.EndTime = timeutil.TimeStamp(result.JobStatus.CompletedTime / 1000) | |||
| } | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| } | |||
| type CloudbrainInfo struct { | |||
| Cloudbrain `xorm:"extends"` | |||
| User `xorm:"extends"` | |||
| @@ -1323,6 +1353,7 @@ func CloudbrainsVersionList(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int, e | |||
| } | |||
| func CreateCloudbrain(cloudbrain *Cloudbrain) (err error) { | |||
| cloudbrain.TrainJobDuration = DURATION_STR_ZERO | |||
| if _, err = x.Insert(cloudbrain); err != nil { | |||
| return err | |||
| } | |||
| @@ -1339,6 +1370,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) | |||
| @@ -1355,6 +1396,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) | |||
| @@ -1467,6 +1514,15 @@ func GetCloudBrainUnStoppedJob() ([]*Cloudbrain, error) { | |||
| Find(&cloudbrains) | |||
| } | |||
| func GetStoppedJobWithNoDurationJob() ([]*Cloudbrain, error) { | |||
| cloudbrains := make([]*Cloudbrain, 0) | |||
| return cloudbrains, x. | |||
| In("status", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded). | |||
| Where("train_job_duration is null or train_job_duration = '' "). | |||
| Limit(100). | |||
| Find(&cloudbrains) | |||
| } | |||
| func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) { | |||
| count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeCloudBrainOne).Count(new(Cloudbrain)) | |||
| return int(count), err | |||
| @@ -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} | |||
| } | |||
| } | |||
| @@ -0,0 +1,199 @@ | |||
| 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, | |||
| title character varying(255), | |||
| status integer, | |||
| category character varying(255), | |||
| description text, | |||
| download_times bigint, | |||
| license character varying(255), | |||
| task character varying(255), | |||
| release_id bigint, | |||
| user_id bigint, | |||
| repo_id bigint, | |||
| created_unix bigint, | |||
| updated_unix bigint, | |||
| file_name text, | |||
| file_desc text | |||
| )SERVER multicorn_es | |||
| OPTIONS | |||
| ( | |||
| host '192.168.207.94', | |||
| port '9200', | |||
| index 'dataset-es-index', | |||
| rowid_column 'id', | |||
| default_sort '_id' | |||
| ) | |||
| ; | |||
| DELETE FROM public.dataset_es; | |||
| INSERT INTO public.dataset_es( | |||
| id, | |||
| title, | |||
| status, | |||
| category, | |||
| description, | |||
| download_times, | |||
| license, task, | |||
| release_id, | |||
| user_id, | |||
| repo_id, | |||
| created_unix, | |||
| updated_unix, | |||
| file_name, | |||
| file_desc | |||
| ) | |||
| SELECT | |||
| b.id, | |||
| b.title, | |||
| b.status, | |||
| b.category, | |||
| b.description, | |||
| b.download_times, | |||
| b.license, | |||
| b.task, | |||
| b.release_id, | |||
| b.user_id, | |||
| b.repo_id, | |||
| b.created_unix, | |||
| b.updated_unix, | |||
| (select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false), | |||
| (select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false) | |||
| FROM public.dataset b,public.repository c where b.repo_id=c.id and c.is_private=false; | |||
| DROP TRIGGER IF EXISTS es_insert_dataset on public.dataset; | |||
| CREATE OR REPLACE FUNCTION public.insert_dataset_data() RETURNS trigger AS | |||
| $def$ | |||
| DECLARE | |||
| privateValue boolean=false; | |||
| BEGIN | |||
| select into privateValue is_private from public.repository where id=NEW.repo_id; | |||
| if not privateValue then | |||
| INSERT INTO public.dataset_es( | |||
| id, | |||
| title, | |||
| status, | |||
| category, | |||
| description, | |||
| download_times, | |||
| license, | |||
| task, | |||
| release_id, | |||
| user_id, | |||
| repo_id, | |||
| created_unix, | |||
| updated_unix) | |||
| VALUES ( | |||
| NEW.id, | |||
| NEW.title, | |||
| NEW.status, | |||
| NEW.category, | |||
| NEW.description, | |||
| NEW.download_times, | |||
| NEW.license, | |||
| NEW.task, | |||
| NEW.release_id, | |||
| NEW.user_id, | |||
| NEW.repo_id, | |||
| NEW.created_unix, | |||
| NEW.updated_unix | |||
| ); | |||
| end if; | |||
| RETURN NEW; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_insert_dataset | |||
| AFTER INSERT ON public.dataset | |||
| FOR EACH ROW EXECUTE PROCEDURE insert_dataset_data(); | |||
| ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_insert_dataset; | |||
| DROP TRIGGER IF EXISTS es_udpate_dataset_file_name on public.attachment; | |||
| CREATE OR REPLACE FUNCTION public.udpate_dataset_file_name() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| if (TG_OP = 'UPDATE') then | |||
| update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id; | |||
| elsif (TG_OP = 'INSERT') then | |||
| update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id; | |||
| elsif (TG_OP = 'DELETE') then | |||
| update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id; | |||
| update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id; | |||
| end if; | |||
| return NEW; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_udpate_dataset_file_name | |||
| AFTER INSERT OR UPDATE OR DELETE ON public.attachment | |||
| FOR EACH ROW EXECUTE PROCEDURE udpate_dataset_file_name(); | |||
| ALTER TABLE public.attachment ENABLE ALWAYS TRIGGER es_udpate_dataset_file_name; | |||
| DROP TRIGGER IF EXISTS es_update_dataset on public.dataset; | |||
| CREATE OR REPLACE FUNCTION public.update_dataset() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| UPDATE public.dataset_es | |||
| SET description=NEW.description, | |||
| title=NEW.title, | |||
| category=NEW.category, | |||
| task=NEW.task, | |||
| download_times=NEW.download_times, | |||
| updated_unix=NEW.updated_unix, | |||
| file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false), | |||
| file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false) | |||
| where id=NEW.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_update_dataset | |||
| AFTER UPDATE ON public.dataset | |||
| FOR EACH ROW EXECUTE PROCEDURE update_dataset(); | |||
| ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_update_dataset; | |||
| DROP TRIGGER IF EXISTS es_delete_dataset on public.dataset; | |||
| CREATE OR REPLACE FUNCTION public.delete_dataset() RETURNS trigger AS | |||
| $def$ | |||
| declare | |||
| BEGIN | |||
| DELETE FROM public.dataset_es where id=OLD.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_delete_dataset | |||
| AFTER DELETE ON public.dataset | |||
| FOR EACH ROW EXECUTE PROCEDURE delete_dataset(); | |||
| ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_delete_dataset; | |||
| @@ -0,0 +1,227 @@ | |||
| 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, | |||
| repo_id bigint, | |||
| index bigint, | |||
| poster_id bigint, | |||
| original_author character varying(255), | |||
| original_author_id bigint, | |||
| name character varying(255) , | |||
| content text, | |||
| comment text, | |||
| milestone_id bigint, | |||
| priority integer, | |||
| is_closed boolean, | |||
| is_pull boolean, | |||
| pr_id bigint, | |||
| num_comments integer, | |||
| ref character varying(255), | |||
| deadline_unix bigint, | |||
| created_unix bigint, | |||
| updated_unix bigint, | |||
| closed_unix bigint, | |||
| is_locked boolean NOT NULL, | |||
| amount bigint, | |||
| is_transformed boolean NOT NULL | |||
| )SERVER multicorn_es | |||
| OPTIONS | |||
| ( | |||
| host '192.168.207.94', | |||
| port '9200', | |||
| index 'issue-es-index', | |||
| rowid_column 'id', | |||
| default_sort '_id' | |||
| ) | |||
| ; | |||
| delete from public.issue_es; | |||
| INSERT INTO public.issue_es( | |||
| id, | |||
| repo_id, | |||
| index, | |||
| poster_id, | |||
| original_author, | |||
| original_author_id, | |||
| name, | |||
| content, | |||
| milestone_id, | |||
| priority, | |||
| is_closed, | |||
| is_pull, | |||
| num_comments, | |||
| ref, | |||
| deadline_unix, | |||
| created_unix, | |||
| updated_unix, | |||
| closed_unix, | |||
| is_locked, | |||
| amount, | |||
| is_transformed,comment,pr_id) | |||
| SELECT | |||
| b.id, | |||
| b.repo_id, | |||
| b.index, | |||
| b.poster_id, | |||
| b.original_author, | |||
| b.original_author_id, | |||
| b.name, | |||
| b.content, | |||
| b.milestone_id, | |||
| b.priority, | |||
| b.is_closed, | |||
| b.is_pull, | |||
| b.num_comments, | |||
| b.ref, | |||
| b.deadline_unix, | |||
| b.created_unix, | |||
| b.updated_unix, | |||
| b.closed_unix, | |||
| b.is_locked, | |||
| b.amount, | |||
| b.is_transformed, | |||
| (select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id), | |||
| (select id from public.pull_request d where b.id=d.issue_id and b.is_pull=true) | |||
| FROM public.issue b,public.repository c where b.repo_id=c.id and c.is_private=false; | |||
| CREATE OR REPLACE FUNCTION public.insert_issue_data() RETURNS trigger AS | |||
| $def$ | |||
| DECLARE | |||
| privateValue boolean=false; | |||
| BEGIN | |||
| select into privateValue is_private from public.repository where id=NEW.repo_id; | |||
| if not privateValue then | |||
| INSERT INTO public.issue_es( | |||
| id, | |||
| repo_id, | |||
| index, | |||
| poster_id, | |||
| original_author, | |||
| original_author_id, | |||
| name, | |||
| content, | |||
| milestone_id, | |||
| priority, | |||
| is_closed, | |||
| is_pull, | |||
| num_comments, | |||
| ref, | |||
| deadline_unix, | |||
| created_unix, | |||
| updated_unix, | |||
| closed_unix, | |||
| is_locked, | |||
| amount, | |||
| is_transformed) | |||
| VALUES ( | |||
| NEW.id, | |||
| NEW.repo_id, | |||
| NEW.index, | |||
| NEW.poster_id, | |||
| NEW.original_author, | |||
| NEW.original_author_id, | |||
| NEW.name, | |||
| NEW.content, | |||
| NEW.milestone_id, | |||
| NEW.priority, | |||
| NEW.is_closed, | |||
| NEW.is_pull, | |||
| NEW.num_comments, | |||
| NEW.ref, | |||
| NEW.deadline_unix, | |||
| NEW.created_unix, | |||
| NEW.updated_unix, | |||
| NEW.closed_unix, | |||
| NEW.is_locked, | |||
| NEW.amount, | |||
| NEW.is_transformed | |||
| ); | |||
| end if; | |||
| RETURN NEW; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| DROP TRIGGER IF EXISTS es_insert_issue on public.issue; | |||
| CREATE TRIGGER es_insert_issue | |||
| AFTER INSERT ON public.issue | |||
| FOR EACH ROW EXECUTE PROCEDURE insert_issue_data(); | |||
| ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_insert_issue; | |||
| CREATE OR REPLACE FUNCTION public.udpate_issue_comment() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| if (TG_OP = 'DELETE') then | |||
| update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=OLD.issue_id) where id=OLD.issue_id; | |||
| elsif (TG_OP = 'UPDATE') then | |||
| update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.issue_id) where id=NEW.issue_id; | |||
| end if; | |||
| return null; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| DROP TRIGGER IF EXISTS es_udpate_issue_comment on public.comment; | |||
| CREATE TRIGGER es_udpate_issue_comment | |||
| AFTER DELETE OR UPDATE ON public.comment | |||
| FOR EACH ROW EXECUTE PROCEDURE udpate_issue_comment(); | |||
| ALTER TABLE public.comment ENABLE ALWAYS TRIGGER es_udpate_issue_comment; | |||
| CREATE OR REPLACE FUNCTION public.update_issue() RETURNS trigger AS | |||
| $def$ | |||
| declare | |||
| BEGIN | |||
| UPDATE public.issue_es | |||
| SET content=NEW.content, | |||
| 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; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| DROP TRIGGER IF EXISTS es_update_issue on public.issue; | |||
| CREATE TRIGGER es_update_issue | |||
| AFTER UPDATE ON public.issue | |||
| FOR EACH ROW EXECUTE PROCEDURE update_issue(); | |||
| ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_update_issue; | |||
| CREATE OR REPLACE FUNCTION public.delete_issue() RETURNS trigger AS | |||
| $def$ | |||
| declare | |||
| BEGIN | |||
| DELETE FROM public.issue_es where id=OLD.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| DROP TRIGGER IF EXISTS es_delete_issue on public.issue; | |||
| CREATE TRIGGER es_delete_issue | |||
| AFTER DELETE ON public.issue | |||
| FOR EACH ROW EXECUTE PROCEDURE delete_issue(); | |||
| ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_delete_issue; | |||
| @@ -0,0 +1,545 @@ | |||
| -- 要处理项目从私有变为公有,并且从公有变成私有的情况 | |||
| 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, | |||
| owner_name character varying(255), | |||
| lower_name character varying(255) NOT NULL, | |||
| name character varying(255) NOT NULL, | |||
| description text, | |||
| website character varying(2048), | |||
| original_service_type integer, | |||
| original_url character varying(2048), | |||
| default_branch character varying(255), | |||
| num_watches integer, | |||
| num_stars integer, | |||
| num_forks integer, | |||
| num_issues integer, | |||
| num_closed_issues integer, | |||
| num_pulls integer, | |||
| num_closed_pulls integer, | |||
| num_milestones integer DEFAULT 0 NOT NULL, | |||
| num_closed_milestones integer DEFAULT 0 NOT NULL, | |||
| is_private boolean, | |||
| is_empty boolean, | |||
| is_archived boolean, | |||
| is_mirror boolean, | |||
| status integer DEFAULT 0 NOT NULL, | |||
| is_fork boolean DEFAULT false NOT NULL, | |||
| fork_id bigint, | |||
| is_template boolean DEFAULT false NOT NULL, | |||
| template_id bigint, | |||
| size bigint DEFAULT 0 NOT NULL, | |||
| is_fsck_enabled boolean DEFAULT true NOT NULL, | |||
| close_issues_via_commit_in_any_branch boolean DEFAULT false NOT NULL, | |||
| topics text, | |||
| avatar character varying(64), | |||
| created_unix bigint, | |||
| updated_unix bigint, | |||
| contract_address character varying(255), | |||
| block_chain_status integer DEFAULT 0 NOT NULL, | |||
| balance character varying(255) DEFAULT '0'::character varying NOT NULL, | |||
| clone_cnt bigint DEFAULT 0 NOT NULL, | |||
| license character varying(100), | |||
| download_cnt bigint DEFAULT 0 NOT NULL, | |||
| num_commit bigint DEFAULT 0 NOT NULL, | |||
| git_clone_cnt bigint DEFAULT 0 NOT NULL, | |||
| creator_id bigint NOT NULL DEFAULT 0, | |||
| repo_type integer NOT NULL DEFAULT 0, | |||
| lang character varying(2048), | |||
| alias character varying(255), | |||
| lower_alias character varying(255) | |||
| ) SERVER multicorn_es | |||
| OPTIONS | |||
| ( | |||
| host '192.168.207.94', | |||
| port '9200', | |||
| index 'repository-es-index', | |||
| rowid_column 'id', | |||
| default_sort '_id' | |||
| ) | |||
| ; | |||
| delete from public.repository_es; | |||
| INSERT INTO public.repository_es (id, | |||
| owner_id, | |||
| owner_name, | |||
| lower_name, | |||
| name, | |||
| description, | |||
| website, | |||
| original_service_type, | |||
| original_url, | |||
| default_branch, | |||
| num_watches, | |||
| num_stars, | |||
| num_forks, | |||
| num_issues, | |||
| num_closed_issues, | |||
| num_pulls, | |||
| num_closed_pulls, | |||
| num_milestones, | |||
| num_closed_milestones, | |||
| is_private, | |||
| is_empty, | |||
| is_archived, | |||
| is_mirror, | |||
| status, | |||
| is_fork, | |||
| fork_id, | |||
| is_template, | |||
| template_id, | |||
| size, | |||
| is_fsck_enabled, | |||
| close_issues_via_commit_in_any_branch, | |||
| topics, | |||
| avatar, | |||
| created_unix, | |||
| updated_unix, | |||
| contract_address, | |||
| block_chain_status, | |||
| balance, | |||
| clone_cnt, | |||
| num_commit, | |||
| git_clone_cnt, | |||
| creator_id, | |||
| repo_type, | |||
| lang, | |||
| alias, | |||
| lower_alias | |||
| ) | |||
| SELECT | |||
| id, | |||
| owner_id, | |||
| owner_name, | |||
| lower_name, | |||
| name, | |||
| description, | |||
| website, | |||
| original_service_type, | |||
| original_url, | |||
| default_branch, | |||
| num_watches, | |||
| num_stars, | |||
| num_forks, | |||
| num_issues, | |||
| num_closed_issues, | |||
| num_pulls, | |||
| num_closed_pulls, | |||
| num_milestones, | |||
| num_closed_milestones, | |||
| is_private, | |||
| is_empty, | |||
| is_archived, | |||
| is_mirror, | |||
| status, | |||
| is_fork, | |||
| fork_id, | |||
| is_template, | |||
| template_id, | |||
| size, | |||
| is_fsck_enabled, | |||
| close_issues_via_commit_in_any_branch, | |||
| topics, | |||
| avatar, | |||
| created_unix, | |||
| updated_unix, | |||
| contract_address, | |||
| block_chain_status, | |||
| balance, | |||
| clone_cnt, | |||
| num_commit, | |||
| git_clone_cnt, | |||
| creator_id, | |||
| repo_type, | |||
| (select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id), | |||
| alias, | |||
| lower_alias | |||
| FROM public.repository b where b.is_private=false; | |||
| DROP TRIGGER IF EXISTS es_insert_repository on public.repository; | |||
| CREATE OR REPLACE FUNCTION public.insert_repository_data() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| if not NEW.is_private then | |||
| INSERT INTO public.repository_es (id, | |||
| owner_id, | |||
| owner_name, | |||
| lower_name, | |||
| name, | |||
| description, | |||
| website, | |||
| original_service_type, | |||
| original_url, | |||
| default_branch, | |||
| num_watches, | |||
| num_stars, | |||
| num_forks, | |||
| num_issues, | |||
| num_closed_issues, | |||
| num_pulls, | |||
| num_closed_pulls, | |||
| num_milestones, | |||
| num_closed_milestones, | |||
| is_private, | |||
| is_empty, | |||
| is_archived, | |||
| is_mirror, | |||
| status, | |||
| is_fork, | |||
| fork_id, | |||
| is_template, | |||
| template_id, | |||
| size, | |||
| is_fsck_enabled, | |||
| close_issues_via_commit_in_any_branch, | |||
| topics, | |||
| avatar, | |||
| created_unix, | |||
| updated_unix, | |||
| contract_address, | |||
| block_chain_status, | |||
| balance, | |||
| clone_cnt, | |||
| num_commit, | |||
| git_clone_cnt, | |||
| creator_id, | |||
| repo_type, | |||
| alias, | |||
| lower_alias) VALUES | |||
| (NEW.id, | |||
| NEW.owner_id, | |||
| NEW.owner_name, | |||
| NEW.lower_name, | |||
| NEW.name, | |||
| NEW.description, | |||
| NEW.website, | |||
| NEW.original_service_type, | |||
| NEW.original_url, | |||
| NEW.default_branch, | |||
| NEW.num_watches, | |||
| NEW.num_stars, | |||
| NEW.num_forks, | |||
| NEW.num_issues, | |||
| NEW.num_closed_issues, | |||
| NEW.num_pulls, | |||
| NEW.num_closed_pulls, | |||
| NEW.num_milestones, | |||
| NEW.num_closed_milestones, | |||
| NEW.is_private, | |||
| NEW.is_empty, | |||
| NEW.is_archived, | |||
| NEW.is_mirror, | |||
| NEW.status, | |||
| NEW.is_fork, | |||
| NEW.fork_id, | |||
| NEW.is_template, | |||
| NEW.template_id, | |||
| NEW.size, | |||
| NEW.is_fsck_enabled, | |||
| NEW.close_issues_via_commit_in_any_branch, | |||
| NEW.topics, | |||
| NEW.avatar, | |||
| NEW.created_unix, | |||
| NEW.updated_unix, | |||
| NEW.contract_address, | |||
| NEW.block_chain_status, | |||
| NEW.balance, | |||
| NEW.clone_cnt, | |||
| NEW.num_commit, | |||
| NEW.git_clone_cnt, | |||
| NEW.creator_id, | |||
| NEW.repo_type, | |||
| NEW.alias, | |||
| NEW.lower_alias); | |||
| end if; | |||
| RETURN NEW; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_insert_repository | |||
| AFTER INSERT ON public.repository | |||
| FOR EACH ROW EXECUTE PROCEDURE insert_repository_data(); | |||
| ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_insert_repository; | |||
| DROP TRIGGER IF EXISTS es_update_repository on public.repository; | |||
| CREATE OR REPLACE FUNCTION public.update_repository() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| if OLD.is_private != NEW.is_private then | |||
| if OLD.is_private and not NEW.is_private then | |||
| --insert | |||
| INSERT INTO public.repository_es (id, | |||
| owner_id, | |||
| owner_name, | |||
| lower_name, | |||
| name, | |||
| description, | |||
| website, | |||
| original_service_type, | |||
| original_url, | |||
| default_branch, | |||
| num_watches, | |||
| num_stars, | |||
| num_forks, | |||
| num_issues, | |||
| num_closed_issues, | |||
| num_pulls, | |||
| num_closed_pulls, | |||
| num_milestones, | |||
| num_closed_milestones, | |||
| is_private, | |||
| is_empty, | |||
| is_archived, | |||
| is_mirror, | |||
| status, | |||
| is_fork, | |||
| fork_id, | |||
| is_template, | |||
| template_id, | |||
| size, | |||
| is_fsck_enabled, | |||
| close_issues_via_commit_in_any_branch, | |||
| topics, | |||
| avatar, | |||
| created_unix, | |||
| updated_unix, | |||
| contract_address, | |||
| block_chain_status, | |||
| balance, | |||
| clone_cnt, | |||
| num_commit, | |||
| git_clone_cnt, | |||
| creator_id, | |||
| repo_type, | |||
| lang, | |||
| alias, | |||
| lower_alias) | |||
| SELECT | |||
| id, | |||
| owner_id, | |||
| owner_name, | |||
| lower_name, | |||
| name, | |||
| description, | |||
| website, | |||
| original_service_type, | |||
| original_url, | |||
| default_branch, | |||
| num_watches, | |||
| num_stars, | |||
| num_forks, | |||
| num_issues, | |||
| num_closed_issues, | |||
| num_pulls, | |||
| num_closed_pulls, | |||
| num_milestones, | |||
| num_closed_milestones, | |||
| is_private, | |||
| is_empty, | |||
| is_archived, | |||
| is_mirror, | |||
| status, | |||
| is_fork, | |||
| fork_id, | |||
| is_template, | |||
| template_id, | |||
| size, | |||
| is_fsck_enabled, | |||
| close_issues_via_commit_in_any_branch, | |||
| topics, | |||
| avatar, | |||
| created_unix, | |||
| updated_unix, | |||
| contract_address, | |||
| block_chain_status, | |||
| balance, | |||
| clone_cnt, | |||
| num_commit, | |||
| git_clone_cnt, | |||
| creator_id, | |||
| repo_type, | |||
| (select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id), | |||
| alias, | |||
| lower_alias | |||
| FROM public.repository b where b.id=NEW.id; | |||
| INSERT INTO public.dataset_es( | |||
| id, | |||
| title, | |||
| status, | |||
| category, | |||
| description, | |||
| download_times, | |||
| license, task, | |||
| release_id, | |||
| user_id, | |||
| repo_id, | |||
| created_unix, | |||
| updated_unix,file_name) | |||
| SELECT | |||
| b.id, | |||
| b.title, | |||
| b.status, | |||
| b.category, | |||
| b.description, | |||
| b.download_times, | |||
| b.license, | |||
| b.task, | |||
| b.release_id, | |||
| b.user_id, | |||
| b.repo_id, | |||
| b.created_unix, | |||
| b.updated_unix,(select array_to_string(array_agg(name order by created_unix desc),',') from public.attachment a where a.dataset_id=b.id and a.is_private=false) | |||
| FROM public.dataset b where b.repo_id=NEW.id; | |||
| INSERT INTO public.issue_es( | |||
| id, | |||
| repo_id, | |||
| index, | |||
| poster_id, | |||
| original_author, | |||
| original_author_id, | |||
| name, | |||
| content, | |||
| milestone_id, | |||
| priority, | |||
| is_closed, | |||
| is_pull, | |||
| num_comments, | |||
| ref, | |||
| deadline_unix, | |||
| created_unix, | |||
| updated_unix, | |||
| closed_unix, | |||
| is_locked, | |||
| amount, | |||
| is_transformed,comment,pr_id) | |||
| SELECT | |||
| b.id, | |||
| b.repo_id, | |||
| b.index, | |||
| b.poster_id, | |||
| b.original_author, | |||
| b.original_author_id, | |||
| b.name, | |||
| b.content, | |||
| b.milestone_id, | |||
| b.priority, | |||
| b.is_closed, | |||
| b.is_pull, | |||
| b.num_comments, | |||
| b.ref, | |||
| b.deadline_unix, | |||
| b.created_unix, | |||
| b.updated_unix, | |||
| b.closed_unix, | |||
| b.is_locked, | |||
| b.amount, | |||
| b.is_transformed, | |||
| (select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id), | |||
| (select id from public.pull_request d where d.issue_id=b.id) | |||
| FROM public.issue b where b.repo_id=NEW.id; | |||
| end if; | |||
| if not OLD.is_private and NEW.is_private then | |||
| delete from public.issue_es where repo_id=NEW.id; | |||
| delete from public.dataset_es where repo_id=NEW.id; | |||
| delete from public.repository_es where id=NEW.id; | |||
| end if; | |||
| end if; | |||
| if not NEW.is_private then | |||
| raise notice 'update repo,the updated_unix is %',NEW.updated_unix; | |||
| update public.repository_es SET description=NEW.description, | |||
| name=NEW.name, | |||
| lower_name=NEW.lower_name, | |||
| owner_name=NEW.owner_name, | |||
| website=NEW.website, | |||
| updated_unix=NEW.updated_unix, | |||
| num_watches=NEW.num_watches, | |||
| num_stars=NEW.num_stars, | |||
| num_forks=NEW.num_forks, | |||
| topics=NEW.topics, | |||
| alias = NEW.alias, | |||
| lower_alias = NEW.lower_alias, | |||
| avatar=NEW.avatar | |||
| where id=NEW.id; | |||
| end if; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_update_repository | |||
| AFTER UPDATE ON public.repository | |||
| FOR EACH ROW EXECUTE PROCEDURE update_repository(); | |||
| ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_update_repository; | |||
| DROP TRIGGER IF EXISTS es_delete_repository on public.repository; | |||
| CREATE OR REPLACE FUNCTION public.delete_repository() RETURNS trigger AS | |||
| $def$ | |||
| declare | |||
| BEGIN | |||
| delete from public.issue_es where repo_id=OLD.id; | |||
| delete from public.dataset_es where repo_id=OLD.id; | |||
| DELETE FROM public.repository_es where id=OLD.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_delete_repository | |||
| AFTER DELETE ON public.repository | |||
| FOR EACH ROW EXECUTE PROCEDURE delete_repository(); | |||
| ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_delete_repository; | |||
| DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat; | |||
| CREATE OR REPLACE FUNCTION public.udpate_repository_lang() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| if (TG_OP = 'UPDATE') then | |||
| update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id; | |||
| elsif (TG_OP = 'INSERT') then | |||
| update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id; | |||
| elsif (TG_OP = 'DELETE') then | |||
| if exists(select 1 from public.repository where id=OLD.repo_id) then | |||
| update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=OLD.repo_id) where id=OLD.repo_id; | |||
| end if; | |||
| end if; | |||
| return null; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_udpate_repository_lang | |||
| AFTER INSERT OR UPDATE OR DELETE ON public.language_stat | |||
| FOR EACH ROW EXECUTE PROCEDURE udpate_repository_lang(); | |||
| ALTER TABLE public.language_stat ENABLE ALWAYS TRIGGER es_udpate_repository_lang; | |||
| @@ -0,0 +1,317 @@ | |||
| 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 , | |||
| lower_name character varying(255) NULL, | |||
| name character varying(255) NULL, | |||
| full_name character varying(255), | |||
| email character varying(255), | |||
| keep_email_private boolean, | |||
| email_notifications_preference character varying(20) , | |||
| passwd character varying(255) , | |||
| passwd_hash_algo character varying(255) , | |||
| must_change_password boolean NOT NULL DEFAULT false, | |||
| login_type integer, | |||
| login_source bigint NOT NULL DEFAULT 0, | |||
| login_name character varying(255) , | |||
| type integer, | |||
| location character varying(255), | |||
| website character varying(255), | |||
| rands character varying(10), | |||
| salt character varying(10), | |||
| language character varying(5), | |||
| description character varying(255), | |||
| created_unix bigint, | |||
| updated_unix bigint, | |||
| last_login_unix bigint, | |||
| last_repo_visibility boolean, | |||
| max_repo_creation integer, | |||
| is_active boolean, | |||
| is_admin boolean, | |||
| is_restricted boolean NOT NULL DEFAULT false, | |||
| allow_git_hook boolean, | |||
| allow_import_local boolean, | |||
| allow_create_organization boolean DEFAULT true, | |||
| prohibit_login boolean NOT NULL DEFAULT false, | |||
| avatar character varying(2048) , | |||
| avatar_email character varying(255), | |||
| use_custom_avatar boolean, | |||
| num_followers integer, | |||
| num_following integer NOT NULL DEFAULT 0, | |||
| num_stars integer, | |||
| num_repos integer, | |||
| num_teams integer, | |||
| num_members integer, | |||
| visibility integer NOT NULL DEFAULT 0, | |||
| repo_admin_change_team_access boolean NOT NULL DEFAULT false, | |||
| diff_view_style character varying(255), | |||
| theme character varying(255), | |||
| token character varying(1024) , | |||
| public_key character varying(255), | |||
| private_key character varying(255), | |||
| is_operator boolean NOT NULL DEFAULT false, | |||
| num_dataset_stars integer NOT NULL DEFAULT 0 | |||
| ) SERVER multicorn_es | |||
| OPTIONS | |||
| ( | |||
| host '192.168.207.94', | |||
| port '9200', | |||
| index 'user-es-index', | |||
| rowid_column 'id', | |||
| default_sort '_id' | |||
| ) | |||
| ; | |||
| delete from public.user_es; | |||
| INSERT INTO public.user_es( | |||
| id, | |||
| lower_name, | |||
| name, | |||
| full_name, | |||
| email, | |||
| keep_email_private, | |||
| email_notifications_preference, | |||
| must_change_password, | |||
| login_type, | |||
| login_source, | |||
| login_name, | |||
| type, | |||
| location, | |||
| website, | |||
| rands, | |||
| language, | |||
| description, | |||
| created_unix, | |||
| updated_unix, | |||
| last_login_unix, | |||
| last_repo_visibility, | |||
| max_repo_creation, | |||
| is_active, | |||
| is_restricted, | |||
| allow_git_hook, | |||
| allow_import_local, | |||
| allow_create_organization, | |||
| prohibit_login, | |||
| avatar, | |||
| avatar_email, | |||
| use_custom_avatar, | |||
| num_followers, | |||
| num_following, | |||
| num_stars, | |||
| num_repos, | |||
| num_teams, | |||
| num_members, | |||
| visibility, | |||
| repo_admin_change_team_access, | |||
| diff_view_style, | |||
| theme, | |||
| is_operator, | |||
| num_dataset_stars) | |||
| SELECT | |||
| id, | |||
| lower_name, | |||
| name, | |||
| full_name, | |||
| email, | |||
| keep_email_private, | |||
| email_notifications_preference, | |||
| must_change_password, | |||
| login_type, | |||
| login_source, | |||
| login_name, | |||
| type, | |||
| location, | |||
| website, | |||
| rands, | |||
| language, | |||
| description, | |||
| created_unix, | |||
| updated_unix, | |||
| last_login_unix, | |||
| last_repo_visibility, | |||
| max_repo_creation, | |||
| is_active, | |||
| is_restricted, | |||
| allow_git_hook, | |||
| allow_import_local, | |||
| allow_create_organization, | |||
| prohibit_login, | |||
| avatar, | |||
| avatar_email, | |||
| use_custom_avatar, | |||
| num_followers, | |||
| num_following, | |||
| num_stars, | |||
| num_repos, | |||
| num_teams, | |||
| num_members, | |||
| visibility, | |||
| repo_admin_change_team_access, | |||
| diff_view_style, | |||
| theme, | |||
| is_operator, | |||
| num_dataset_stars | |||
| FROM public.user; | |||
| DROP TRIGGER IF EXISTS es_insert_user on public.user; | |||
| CREATE OR REPLACE FUNCTION public.insert_user_data() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| INSERT INTO public."user_es"( | |||
| id, | |||
| lower_name, | |||
| name, | |||
| full_name, | |||
| email, | |||
| keep_email_private, | |||
| email_notifications_preference, | |||
| must_change_password, | |||
| login_type, | |||
| login_source, | |||
| login_name, | |||
| type, | |||
| location, | |||
| website, | |||
| rands, | |||
| language, | |||
| description, | |||
| created_unix, | |||
| updated_unix, | |||
| last_login_unix, | |||
| last_repo_visibility, | |||
| max_repo_creation, | |||
| is_active, | |||
| is_restricted, | |||
| allow_git_hook, | |||
| allow_import_local, | |||
| allow_create_organization, | |||
| prohibit_login, | |||
| avatar, | |||
| avatar_email, | |||
| use_custom_avatar, | |||
| num_followers, | |||
| num_following, | |||
| num_stars, | |||
| num_repos, | |||
| num_teams, | |||
| num_members, | |||
| visibility, | |||
| repo_admin_change_team_access, | |||
| diff_view_style, | |||
| theme, | |||
| is_operator, | |||
| num_dataset_stars) | |||
| VALUES ( | |||
| NEW.id, | |||
| NEW.lower_name, | |||
| NEW.name, | |||
| NEW.full_name, | |||
| NEW.email, | |||
| NEW.keep_email_private, | |||
| NEW.email_notifications_preference, | |||
| NEW.must_change_password, | |||
| NEW.login_type, | |||
| NEW.login_source, | |||
| NEW.login_name, | |||
| NEW.type, | |||
| NEW.location, | |||
| NEW.website, | |||
| NEW.rands, | |||
| NEW.language, | |||
| NEW.description, | |||
| NEW.created_unix, | |||
| NEW.updated_unix, | |||
| NEW.last_login_unix, | |||
| NEW.last_repo_visibility, | |||
| NEW.max_repo_creation, | |||
| NEW.is_active, | |||
| NEW.is_restricted, | |||
| NEW.allow_git_hook, | |||
| NEW.allow_import_local, | |||
| NEW.allow_create_organization, | |||
| NEW.prohibit_login, | |||
| NEW.avatar, | |||
| NEW.avatar_email, | |||
| NEW.use_custom_avatar, | |||
| NEW.num_followers, | |||
| NEW.num_following, | |||
| NEW.num_stars, | |||
| NEW.num_repos, | |||
| NEW.num_teams, | |||
| NEW.num_members, | |||
| NEW.visibility, | |||
| NEW.repo_admin_change_team_access, | |||
| NEW.diff_view_style, | |||
| NEW.theme, | |||
| NEW.is_operator, | |||
| NEW.num_dataset_stars | |||
| ); | |||
| RETURN NEW; | |||
| END; | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_insert_user | |||
| AFTER INSERT ON public.user | |||
| FOR EACH ROW EXECUTE PROCEDURE insert_user_data(); | |||
| ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_insert_user; | |||
| DROP TRIGGER IF EXISTS es_update_user on public.user; | |||
| CREATE OR REPLACE FUNCTION public.update_user() RETURNS trigger AS | |||
| $def$ | |||
| BEGIN | |||
| UPDATE public.user_es | |||
| SET description=NEW.description, | |||
| name=NEW.name, | |||
| full_name=NEW.full_name, | |||
| location=NEW.location, | |||
| website=NEW.website, | |||
| email=NEW.email, | |||
| num_dataset_stars=NEW.num_dataset_stars, | |||
| updated_unix=NEW.updated_unix | |||
| where id=NEW.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_update_user | |||
| AFTER UPDATE ON public.user | |||
| FOR EACH ROW EXECUTE PROCEDURE update_user(); | |||
| ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_update_user; | |||
| DROP TRIGGER IF EXISTS es_delete_user on public.user; | |||
| CREATE OR REPLACE FUNCTION public.delete_user() RETURNS trigger AS | |||
| $def$ | |||
| declare | |||
| BEGIN | |||
| DELETE FROM public.user_es where id=OLD.id; | |||
| return new; | |||
| END | |||
| $def$ | |||
| LANGUAGE plpgsql; | |||
| CREATE TRIGGER es_delete_user | |||
| AFTER DELETE ON public.user | |||
| FOR EACH ROW EXECUTE PROCEDURE delete_user(); | |||
| ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_delete_user; | |||
| @@ -13,11 +13,6 @@ const ( | |||
| FileUploaded | |||
| ) | |||
| const ( | |||
| TypeCloudBrainOne int = iota | |||
| TypeCloudBrainTwo | |||
| ) | |||
| type FileChunk struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| UUID string `xorm:"uuid UNIQUE"` | |||
| @@ -138,6 +138,8 @@ func init() { | |||
| new(OfficialTag), | |||
| new(OfficialTagRepos), | |||
| new(WechatBindLog), | |||
| new(OrgStatistic), | |||
| new(SearchRecord), | |||
| ) | |||
| tablesStatistic = append(tablesStatistic, | |||
| @@ -152,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() { | |||
| @@ -6,13 +6,14 @@ | |||
| package models | |||
| import ( | |||
| "code.gitea.io/gitea/modules/git" | |||
| "context" | |||
| "crypto/md5" | |||
| "errors" | |||
| "fmt" | |||
| "html/template" | |||
| "math/rand" | |||
| "code.gitea.io/gitea/modules/git" | |||
| "xorm.io/xorm" | |||
| "code.gitea.io/gitea/modules/blockchain" | |||
| @@ -1606,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 { | |||
| @@ -190,7 +190,8 @@ type SearchRepoOptions struct { | |||
| // None -> include all repos | |||
| // True -> include just courses | |||
| // False -> include just no courses | |||
| Course util.OptionalBool | |||
| Course util.OptionalBool | |||
| OnlySearchPrivate bool | |||
| } | |||
| //SearchOrderBy is used to sort the result | |||
| @@ -219,12 +220,15 @@ const ( | |||
| SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC" | |||
| SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC" | |||
| SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC" | |||
| SearchOrderByWatches SearchOrderBy = "num_watches DESC" | |||
| ) | |||
| // SearchRepositoryCondition creates a query condition according search repository options | |||
| func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
| var cond = builder.NewCond() | |||
| if opts.OnlySearchPrivate { | |||
| cond = cond.And(builder.Eq{"is_private": true}) | |||
| } | |||
| if opts.Private { | |||
| if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID { | |||
| // OK we're in the context of a User | |||
| @@ -337,7 +341,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
| if !opts.TopicOnly { | |||
| var likes = builder.NewCond() | |||
| for _, v := range strings.Split(opts.Keyword, ",") { | |||
| likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) | |||
| likes = likes.Or(builder.Like{"lower_alias", strings.ToLower(v)}) | |||
| likes = likes.Or(builder.Like{"alias", v}) | |||
| if opts.IncludeDescription { | |||
| likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) | |||
| @@ -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() | |||
| @@ -0,0 +1,83 @@ | |||
| package models | |||
| import ( | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "xorm.io/xorm" | |||
| ) | |||
| type SearchRecord struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| //user | |||
| Keyword string `xorm:"NOT NULL"` | |||
| // | |||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
| } | |||
| func SaveSearchKeywordToDb(keyword string) error { | |||
| record := &SearchRecord{ | |||
| Keyword: keyword, | |||
| } | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| _, err := sess.Insert(record) | |||
| if err != nil { | |||
| log.Info("insert error." + err.Error()) | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| func setIssueQueryCondition(sess *xorm.Session, Keyword string, isPull bool, userId int64) { | |||
| sess.And("issue.poster_id=?", userId) | |||
| sess.And("issue.is_pull=?", isPull) | |||
| sess.And("(issue.name like '%" + Keyword + "%' or issue.content like '%" + Keyword + "%')") | |||
| sess.Join("INNER", "repository", "issue.repo_id = repository.id").And("repository.is_private = ?", true) | |||
| } | |||
| func SearchPrivateIssueOrPr(Page int, PageSize int, Keyword string, isPull bool, userId int64) ([]*Issue, int64, error) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| setIssueQueryCondition(sess, Keyword, isPull, userId) | |||
| count, err := sess.Count(new(Issue)) | |||
| if err != nil { | |||
| return nil, 0, err | |||
| } | |||
| setIssueQueryCondition(sess, Keyword, isPull, userId) | |||
| sess.Desc("issue.created_unix") | |||
| sess.Limit(PageSize, (Page-1)*PageSize) | |||
| issues := make([]*Issue, 0) | |||
| if err := sess.Find(&issues); err != nil { | |||
| return nil, 0, err | |||
| } else { | |||
| return issues, count, nil | |||
| } | |||
| } | |||
| func setDataSetQueryCondition(sess *xorm.Session, Keyword string, userId int64) { | |||
| sess.And("dataset.user_id=?", userId) | |||
| sess.And("(dataset.title like '%" + Keyword + "%' or dataset.description like '%" + Keyword + "%')") | |||
| sess.Join("INNER", "repository", "dataset.repo_id = repository.id").And("repository.is_private = ?", true) | |||
| } | |||
| func SearchDatasetBySQL(Page int, PageSize int, Keyword string, userId int64) ([]*Dataset, int64, error) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| setDataSetQueryCondition(sess, Keyword, userId) | |||
| count, err := sess.Count(new(Dataset)) | |||
| if err != nil { | |||
| return nil, 0, err | |||
| } | |||
| setDataSetQueryCondition(sess, Keyword, userId) | |||
| sess.Desc("dataset.created_unix") | |||
| sess.Limit(PageSize, (Page-1)*PageSize) | |||
| datasets := make([]*Dataset, 0) | |||
| if err := sess.Find(&datasets); err != nil { | |||
| return nil, 0, err | |||
| } else { | |||
| return datasets, count, nil | |||
| } | |||
| } | |||
| @@ -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"` | |||
| } | |||
| @@ -20,6 +20,9 @@ type CreateCloudBrainForm struct { | |||
| ResourceSpecId int `form:"resource_spec_id" binding:"Required"` | |||
| BenchmarkTypeID int `form:"benchmark_types_id"` | |||
| BenchmarkChildTypeID int `form:"benchmark_child_types_id"` | |||
| BootFile string `form:"boot_file"` | |||
| Params string `form:"run_para_list"` | |||
| BranchName string `form:"branch_name"` | |||
| } | |||
| type CommitImageCloudBrainForm struct { | |||
| @@ -15,14 +15,13 @@ import ( | |||
| ) | |||
| const ( | |||
| Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple; | |||
| service ssh stop; | |||
| jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"` | |||
| Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"` | |||
| //CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"` | |||
| CommandBenchmark = `echo "start benchmark";cd /benchmark && bash run_bk.sh;echo "end benchmark"` | |||
| CodeMountPath = "/code" | |||
| DataSetMountPath = "/dataset" | |||
| ModelMountPath = "/model" | |||
| LogFile = "log.txt" | |||
| BenchMarkMountPath = "/benchmark" | |||
| BenchMarkResourceID = 1 | |||
| Snn4imagenetMountPath = "/snn4imagenet" | |||
| @@ -32,10 +31,13 @@ const ( | |||
| SubTaskName = "task1" | |||
| Success = "S000" | |||
| DefaultBranchName = "master" | |||
| ) | |||
| var ( | |||
| ResourceSpecs *models.ResourceSpecs | |||
| ResourceSpecs *models.ResourceSpecs | |||
| TrainResourceSpecs *models.ResourceSpecs | |||
| ) | |||
| func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | |||
| @@ -147,7 +149,7 @@ func AdminOrJobCreaterRightForTrain(ctx *context.Context) { | |||
| } | |||
| func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
| func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description, branchName, bootFile, params string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
| dataActualPath := setting.Attachment.Minio.RealPath + | |||
| setting.Attachment.Minio.Bucket + "/" + | |||
| setting.Attachment.Minio.BasePath + | |||
| @@ -155,13 +157,27 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
| uuid | |||
| var resourceSpec *models.ResourceSpec | |||
| if ResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
| } | |||
| for _, spec := range ResourceSpecs.ResourceSpec { | |||
| if resourceSpecId == spec.Id { | |||
| resourceSpec = spec | |||
| var versionCount int | |||
| if jobType == string(models.JobTypeTrain) { | |||
| versionCount = 1 | |||
| if TrainResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs) | |||
| } | |||
| for _, spec := range TrainResourceSpecs.ResourceSpec { | |||
| if resourceSpecId == spec.Id { | |||
| resourceSpec = spec | |||
| } | |||
| } | |||
| } else { | |||
| if ResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
| } | |||
| for _, spec := range ResourceSpecs.ResourceSpec { | |||
| if resourceSpecId == spec.Id { | |||
| resourceSpec = spec | |||
| } | |||
| } | |||
| } | |||
| if resourceSpec == nil { | |||
| @@ -169,6 +185,15 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
| return errors.New("no such resourceSpec") | |||
| } | |||
| var datasetName string | |||
| attach, err := models.GetAttachmentByUUID(uuid) | |||
| if err != nil { | |||
| //for benchmark, do not return error | |||
| log.Error("GetAttachmentByUUID failed:%v", err) | |||
| } else { | |||
| datasetName = attach.Name | |||
| } | |||
| jobResult, err := CreateJob(jobName, models.CreateJobParams{ | |||
| JobName: jobName, | |||
| RetryCount: 1, | |||
| @@ -263,13 +288,19 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
| BenchmarkTypeID: benchmarkTypeID, | |||
| BenchmarkChildTypeID: benchmarkChildTypeID, | |||
| Description: description, | |||
| IsLatestVersion: "1", | |||
| VersionCount: versionCount, | |||
| BranchName: branchName, | |||
| BootFile: bootFile, | |||
| DatasetName: datasetName, | |||
| Parameters: params, | |||
| }) | |||
| if err != nil { | |||
| return err | |||
| } | |||
| task, err := models.GetCloudbrainByName(jobName) | |||
| task, err := models.GetCloudbrainByJobID(jobID) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByName failed: %v", err.Error()) | |||
| return err | |||
| @@ -278,6 +309,8 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
| if string(models.JobTypeBenchmark) == jobType { | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateBenchMarkTask) | |||
| } else if string(models.JobTypeTrain) == jobType { | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, displayJobName, models.ActionCreateGPUTrainTask) | |||
| } else { | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugGPUTask) | |||
| } | |||
| @@ -407,8 +440,10 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e | |||
| return err | |||
| } | |||
| idString := strconv.FormatInt(newTask.ID, 10) | |||
| *newID = idString | |||
| stringId := strconv.FormatInt(newTask.ID, 10) | |||
| *newID = stringId | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, task.DisplayJobName, models.ActionCreateDebugGPUTask) | |||
| return nil | |||
| } | |||
| @@ -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() | |||
| } | |||
| @@ -56,7 +56,6 @@ const ( | |||
| PerPage = 10 | |||
| IsLatestVersion = "1" | |||
| NotLatestVersion = "0" | |||
| DebugType = -1 | |||
| VersionCount = 1 | |||
| SortByCreateTime = "create_time" | |||
| @@ -281,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, | |||
| @@ -437,7 +437,7 @@ var ( | |||
| //home page | |||
| RecommentRepoAddr string | |||
| ESSearchURL string | |||
| //notice config | |||
| UserNameOfNoticeRepo string | |||
| RepoNameOfNoticeRepo string | |||
| @@ -452,16 +452,18 @@ var ( | |||
| DecompressOBSTaskName string | |||
| //cloudbrain config | |||
| CBAuthUser string | |||
| CBAuthPassword string | |||
| RestServerHost string | |||
| JobPath string | |||
| CBCodePathPrefix string | |||
| JobType string | |||
| GpuTypes string | |||
| DebugServerHost string | |||
| ResourceSpecs string | |||
| MaxDuration int64 | |||
| CBAuthUser string | |||
| CBAuthPassword string | |||
| RestServerHost string | |||
| JobPath string | |||
| CBCodePathPrefix string | |||
| JobType string | |||
| GpuTypes string | |||
| DebugServerHost string | |||
| ResourceSpecs string | |||
| MaxDuration int64 | |||
| TrainGpuTypes string | |||
| TrainResourceSpecs string | |||
| //benchmark config | |||
| IsBenchmarkEnabled bool | |||
| @@ -1265,6 +1267,7 @@ func NewContext() { | |||
| sec = Cfg.Section("homepage") | |||
| RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/") | |||
| ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200") | |||
| sec = Cfg.Section("notice") | |||
| UserNameOfNoticeRepo = sec.Key("USER_NAME").MustString("OpenIOSSG") | |||
| @@ -1285,6 +1288,8 @@ func NewContext() { | |||
| GpuTypes = sec.Key("GPU_TYPES").MustString("") | |||
| ResourceSpecs = sec.Key("RESOURCE_SPECS").MustString("") | |||
| MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) | |||
| TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("") | |||
| TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("") | |||
| sec = Cfg.Section("benchmark") | |||
| IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false) | |||
| @@ -254,6 +254,18 @@ page_dev_yunlao_desc3=Developers can freely choose the corresponding computing r | |||
| page_dev_yunlao_desc4=If your model requires more computing resources, you can also apply for it separately. | |||
| page_dev_yunlao_apply=Apply Separately | |||
| search=Search | |||
| search_repo=Repository | |||
| search_dataset=DataSet | |||
| search_issue=Issue | |||
| search_pr=Pull Request | |||
| search_user=User | |||
| search_org=Organization | |||
| search_finded=Find | |||
| search_related=related | |||
| search_maybe=maybe | |||
| search_ge= | |||
| [explore] | |||
| repos = Repositories | |||
| select_repos = Select the project | |||
| @@ -481,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 | |||
| @@ -899,7 +916,9 @@ 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 | |||
| model_manager = Model | |||
| model_noright=No right | |||
| model_rename=Duplicate model name, please modify model name. | |||
| @@ -1010,7 +1029,8 @@ modelarts.train_job.parameter_value=Parameter Value | |||
| modelarts.train_job.resource_setting=resource_setting | |||
| modelarts.train_job.resource_setting_info=resource_setting_info | |||
| modelarts.train_job.resource_pool=resource_pool | |||
| modelarts.train_job.resource_type=resource_type | |||
| modelarts.train_job.resource_type=Resource Type | |||
| modelarts.train_job.train_dataset=Train Dataset | |||
| modelarts.train_job.standard=Standard | |||
| modelarts.train_job.NAS_address=NAS Address | |||
| modelarts.train_job.NAS_mount_path=NAS Mount Path | |||
| @@ -2182,6 +2202,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. | |||
| @@ -2794,10 +2824,11 @@ reject_pull_request = `suggested changes for <a href="%s/pulls/%s">%s#%[2]s</a>` | |||
| upload_dataset=`upload dataset <a href="%s/datasets?type=%s">%s</a>` | |||
| task_gpudebugjob=`created CPU/GPU type debugging task<a href="%s/cloudbrain/%s">%s</a>` | |||
| task_npudebugjob=`created NPU type debugging task <a href="%s/modelarts/notebook/%s">%s</a>` | |||
| task_trainjob=`created training task<a href="%s/modelarts/train-job/%s">%s</a>` | |||
| task_nputrainjob=`created NPU training task<a href="%s/modelarts/train-job/%s">%s</a>` | |||
| task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
| task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
| task_createmodel=`created new model <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | |||
| task_gputrainjob=`created CPU/GPU training task<a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
| [tool] | |||
| ago = %s ago | |||
| @@ -256,6 +256,18 @@ page_dev_yunlao_desc3=开发者可以根据使用需求,自由选择相应计 | |||
| page_dev_yunlao_desc4=如果您的模型需要更多的计算资源,也可以单独申请 | |||
| page_dev_yunlao_apply=单独申请 | |||
| search=搜索 | |||
| search_repo=项目 | |||
| search_dataset=数据集 | |||
| search_issue=任务 | |||
| search_pr=合并请求 | |||
| search_user=用户 | |||
| search_org=组织 | |||
| search_finded=找到 | |||
| search_related=相关 | |||
| search_maybe=约为 | |||
| search_ge=个 | |||
| [explore] | |||
| repos=项目 | |||
| select_repos=精选项目 | |||
| @@ -484,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=本月 | |||
| @@ -946,7 +963,9 @@ cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字 | |||
| cloudbrain_query_fail=查询云脑任务失败。 | |||
| cloudbrain.mirror_tag = 镜像标签 | |||
| cloudbrain.mirror_description = 镜像描述 | |||
| cloudbrain.exitinfo=退出信息 | |||
| cloudbrain.platform=平台 | |||
| cloudbrain.endtime=结束时间 | |||
| record_begintime_get_err=无法获取统计开始时间。 | |||
| parameter_is_wrong=输入参数错误,请检查输入参数。 | |||
| total_count_get_error=查询总页数失败。 | |||
| @@ -2187,6 +2206,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"。 | |||
| @@ -2800,10 +2829,11 @@ reject_pull_request=`建议变更 <a href="%s/pulls/%s">%s#%[2]s</a>` | |||
| upload_dataset=`上传了数据集文件 <a href="%s/datasets?type=%s">%s</a>` | |||
| task_gpudebugjob=`创建了CPU/GPU类型调试任务 <a href="%s/cloudbrain/%s">%s</a>` | |||
| task_npudebugjob=`创建了NPU类型调试任务 <a href="%s/modelarts/notebook/%s">%s</a>` | |||
| task_trainjob=`创建了训练任务 <a href="%s/modelarts/train-job/%s">%s</a>` | |||
| task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%s">%s</a>` | |||
| task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
| task_benchmark=`创建了评测任务 <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
| task_createmodel=`导入了新模型 <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | |||
| task_gputrainjob=`创建了CPU/GPU类型训练任务 <a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
| [tool] | |||
| ago=%s前 | |||
| @@ -135,7 +135,7 @@ socket.onmessage = function (e) { | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
| } | |||
| else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30"){ | |||
| else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" || record.OpType == "31"){ | |||
| html += recordPrefix + actionName; | |||
| html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
| } | |||
| @@ -175,6 +175,8 @@ function getTaskLink(record){ | |||
| re = re + "/cloudbrain/benchmark/" + record.Content; | |||
| }else if(record.OpType == 30){ | |||
| re = re + "/modelmanage/show_model_info?name=" + record.RefName; | |||
| }else if(record.OpType == 31){ | |||
| re = re + "/cloudbrain/train-job/" + record.Content; | |||
| } | |||
| re = encodeURI(re); | |||
| return re; | |||
| @@ -321,10 +323,11 @@ var actionNameZH={ | |||
| "24":"上传了数据集文件", | |||
| "25":"创建了CPU/GPU类型调试任务", | |||
| "26":"创建了NPU类型调试任务", | |||
| "27":"创建了训练任务", | |||
| "27":"创建了NPU类型训练任务", | |||
| "28":"创建了推理任务", | |||
| "29":"创建了评测任务", | |||
| "30":"导入了新模型" | |||
| "30":"导入了新模型", | |||
| "31":"创建了CPU/GPU类型训练任务" | |||
| }; | |||
| var actionNameEN={ | |||
| @@ -346,10 +349,11 @@ var actionNameEN={ | |||
| "24":" upload dataset ", | |||
| "25":" created CPU/GPU type debugging task ", | |||
| "26":" created NPU type debugging task ", | |||
| "27":" created training task", | |||
| "27":" created NPU type training task", | |||
| "28":" created reasoning task", | |||
| "29":" created profiling task", | |||
| "30":" created new model" | |||
| "30":" created new model", | |||
| "31":" created CPU/GPU type training task", | |||
| }; | |||
| var repoAndOrgZH={ | |||
| @@ -620,10 +620,10 @@ function showfilelist(){ | |||
| for (var i=0;i<labeltastresult.length;i++){ | |||
| var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1); | |||
| console.log(labeltastresult[i]) | |||
| //console.log(labeltastresult[i]) | |||
| if(labeltastresult[i].pic_image_field.length > 70){ | |||
| var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70); | |||
| console.log(tmpIndex) | |||
| //console.log(tmpIndex) | |||
| if(tmpIndex != -1){ | |||
| fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1); | |||
| fname = fname.substring(fname.indexOf('/')+1); | |||
| @@ -679,7 +679,7 @@ function breadFiles(){ | |||
| fname_full_path = tableData[fileindex].pic_image_field.substring(tmp_index + 1); | |||
| } | |||
| var fname_path = fname_full_path.split('/') | |||
| console.log(fname_path) | |||
| //console.log(fname_path) | |||
| // var filename_text = tableData[fileindex].pic_image_field.substring(tableData[fileindex].pic_image_field.lastIndexOf('/')+1) | |||
| var html_breadFile = '' | |||
| // var source_name = filename_title+'.zip' | |||
| @@ -41,7 +41,7 @@ func CloudBrains(ctx *context.Context) { | |||
| if page <= 0 { | |||
| page = 1 | |||
| } | |||
| debugType := modelarts.DebugType | |||
| debugType := models.TypeCloudBrainAll | |||
| if listType == models.GPUResource { | |||
| debugType = models.TypeCloudBrainOne | |||
| } else if listType == models.NPUResource { | |||
| @@ -121,7 +121,7 @@ func DownloadCloudBrains(ctx *context.Context) { | |||
| Page: page, | |||
| PageSize: 1, | |||
| }, | |||
| Type: modelarts.DebugType, | |||
| Type: models.TypeCloudBrainAll, | |||
| NeedRepoInfo: false, | |||
| IsLatestVersion: modelarts.IsLatestVersion, | |||
| }) | |||
| @@ -151,7 +151,7 @@ func DownloadCloudBrains(ctx *context.Context) { | |||
| Page: page, | |||
| PageSize: pageSize, | |||
| }, | |||
| Type: modelarts.DebugType, | |||
| Type: models.TypeCloudBrainAll, | |||
| NeedRepoInfo: true, | |||
| IsLatestVersion: modelarts.IsLatestVersion, | |||
| }) | |||
| @@ -62,10 +62,10 @@ import ( | |||
| "net/http" | |||
| "strings" | |||
| "code.gitea.io/gitea/routers/authentication" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/cloudbrain" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| @@ -77,6 +77,7 @@ import ( | |||
| "code.gitea.io/gitea/routers/api/v1/repo" | |||
| _ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation | |||
| "code.gitea.io/gitea/routers/api/v1/user" | |||
| "code.gitea.io/gitea/routers/authentication" | |||
| repo_ext "code.gitea.io/gitea/routers/repo" | |||
| "gitea.com/macaron/binding" | |||
| @@ -546,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) | |||
| @@ -882,6 +885,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/cloudbrain", func() { | |||
| m.Get("/:id", repo.GetCloudbrainTask) | |||
| m.Get("/:id/log", repo.CloudbrainGetLog) | |||
| m.Group("/train-job", func() { | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", repo.GetModelArtsTrainJobVersion) | |||
| m.Get("/model_list", repo.CloudBrainModelList) | |||
| m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.CloudBrainStop) | |||
| }) | |||
| }) | |||
| }, reqRepoReader(models.UnitTypeCloudBrain)) | |||
| m.Group("/modelarts", func() { | |||
| m.Group("/notebook", func() { | |||
| @@ -6,16 +6,18 @@ | |||
| package repo | |||
| import ( | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "encoding/json" | |||
| "net/http" | |||
| "sort" | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/cloudbrain" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| routerRepo "code.gitea.io/gitea/routers/repo" | |||
| ) | |||
| // cloudbrain get job task by jobid | |||
| @@ -63,7 +65,7 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
| log.Error("GetJob failed:", err) | |||
| return | |||
| } | |||
| result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
| result, _ := models.ConvertToJobResultPayload(jobResult.Payload) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| log.Error("ConvertToJobResultPayload failed:", err) | |||
| @@ -71,24 +73,16 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
| } | |||
| job.Status = result.JobStatus.State | |||
| taskRoles := result.TaskRoles | |||
| taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
| if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { | |||
| taskRoles := result.TaskRoles | |||
| taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
| job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
| job.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
| job.Status = taskRes.TaskStatuses[0].State | |||
| if job.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() { | |||
| job.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix()) | |||
| } | |||
| } | |||
| if result.JobStatus.State != string(models.JobWaiting) { | |||
| if job.EndTime == 0 && models.IsCloudBrainOneDebugJobTerminal(job.Status) { | |||
| job.EndTime = timeutil.TimeStampNow() | |||
| } | |||
| job.ComputeAndSetDuration() | |||
| models.ParseAndSetDurationFromCloudBrainOne(result, job) | |||
| err = models.UpdateJob(job) | |||
| if err != nil { | |||
| log.Error("UpdateJob failed:", err) | |||
| @@ -161,3 +155,55 @@ func CloudbrainGetLog(ctx *context.Context) { | |||
| return | |||
| } | |||
| func CloudBrainModelList(ctx *context.APIContext) { | |||
| var ( | |||
| err error | |||
| ) | |||
| var jobID = ctx.Params(":jobid") | |||
| var versionName = ctx.Query("version_name") | |||
| parentDir := ctx.Query("parentDir") | |||
| dirArray := strings.Split(parentDir, "/") | |||
| task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | |||
| return | |||
| } | |||
| //get dirs | |||
| dirs, err := routerRepo.GetModelDirs(task.JobName, parentDir) | |||
| if err != nil { | |||
| log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) | |||
| ctx.ServerError("GetModelDirs failed:", err) | |||
| return | |||
| } | |||
| var fileInfos []storage.FileInfo | |||
| err = json.Unmarshal([]byte(dirs), &fileInfos) | |||
| if err != nil { | |||
| log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return | |||
| } | |||
| for i, fileInfo := range fileInfos { | |||
| temp, _ := time.Parse("2006-01-02 15:04:05", fileInfo.ModTime) | |||
| fileInfos[i].ModTime = temp.Local().Format("2006-01-02 15:04:05") | |||
| } | |||
| sort.Slice(fileInfos, func(i, j int) bool { | |||
| return fileInfos[i].ModTime > fileInfos[j].ModTime | |||
| }) | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| "JobID": jobID, | |||
| "VersionName": versionName, | |||
| "StatusOK": 0, | |||
| "Path": dirArray, | |||
| "Dirs": fileInfos, | |||
| "task": task, | |||
| "PageIsCloudBrain": true, | |||
| }) | |||
| } | |||
| @@ -6,16 +6,17 @@ | |||
| package repo | |||
| import ( | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "net/http" | |||
| "strconv" | |||
| "strings" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/cloudbrain" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/modelarts" | |||
| "code.gitea.io/gitea/modules/storage" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| routerRepo "code.gitea.io/gitea/routers/repo" | |||
| ) | |||
| @@ -66,8 +67,8 @@ func GetModelArtsNotebook2(ctx *context.APIContext) { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| if job.StartTime == 0 && result.Lease.CreateTime > 0 { | |||
| job.StartTime = timeutil.TimeStamp(result.Lease.CreateTime / 1000) | |||
| if job.StartTime == 0 && result.Lease.UpdateTime > 0 { | |||
| job.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000) | |||
| } | |||
| job.Status = result.Status | |||
| if job.EndTime == 0 && models.IsModelArtsDebugJobTerminal(job.Status) { | |||
| @@ -133,27 +134,61 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(job.VersionID, 10)) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| if job.StartTime == 0 && result.StartTime > 0 { | |||
| job.StartTime = timeutil.TimeStamp(result.StartTime / 1000) | |||
| } | |||
| job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
| job.Duration = result.Duration / 1000 | |||
| job.TrainJobDuration = result.TrainJobDuration | |||
| job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | |||
| if job.Type == models.TypeCloudBrainOne { | |||
| jobResult, err := cloudbrain.GetJob(job.JobID) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| log.Error("GetJob failed:", err) | |||
| return | |||
| } | |||
| result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| log.Error("ConvertToJobResultPayload failed:", err) | |||
| return | |||
| } | |||
| if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 { | |||
| job.EndTime = job.StartTime.Add(job.Duration) | |||
| } | |||
| job.Status = result.JobStatus.State | |||
| if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { | |||
| taskRoles := result.TaskRoles | |||
| taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
| err = models.UpdateTrainJobVersion(job) | |||
| if err != nil { | |||
| log.Error("UpdateJob failed:", err) | |||
| job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
| job.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
| job.Status = taskRes.TaskStatuses[0].State | |||
| } | |||
| if result.JobStatus.State != string(models.JobWaiting) { | |||
| err = models.UpdateJob(job) | |||
| if err != nil { | |||
| log.Error("UpdateJob failed:", err) | |||
| } | |||
| } | |||
| } else { | |||
| result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(job.VersionID, 10)) | |||
| if err != nil { | |||
| ctx.NotFound(err) | |||
| return | |||
| } | |||
| if job.StartTime == 0 && result.StartTime > 0 { | |||
| job.StartTime = timeutil.TimeStamp(result.StartTime / 1000) | |||
| } | |||
| job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
| job.Duration = result.Duration / 1000 | |||
| job.TrainJobDuration = result.TrainJobDuration | |||
| job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | |||
| if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 { | |||
| job.EndTime = job.StartTime.Add(job.Duration) | |||
| } | |||
| err = models.UpdateTrainJobVersion(job) | |||
| if err != nil { | |||
| log.Error("UpdateJob failed:", err) | |||
| } | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
| @@ -377,9 +412,7 @@ func GetModelArtsInferenceJob(ctx *context.APIContext) { | |||
| } | |||
| job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
| job.Duration = result.Duration / 1000 | |||
| job.TrainJobDuration = result.TrainJobDuration | |||
| job.TrainJobDuration = models.ConvertDurationToStr(result.Duration) | |||
| job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | |||
| if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 { | |||
| job.EndTime = job.StartTime.Add(job.Duration) | |||
| @@ -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) | |||
| } | |||
| @@ -71,6 +71,8 @@ func NewServices() { | |||
| log.Info("decompression.NewContext() succeed.") | |||
| labelmsg.Init() | |||
| log.Info("labelmsg.Init() succeed.") | |||
| InitESClient() | |||
| log.Info("ES Client succeed.") | |||
| } | |||
| // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology | |||
| @@ -6,6 +6,7 @@ | |||
| package private | |||
| import ( | |||
| "code.gitea.io/gitea/routers/repo" | |||
| "strings" | |||
| "code.gitea.io/gitea/modules/log" | |||
| @@ -44,7 +45,10 @@ 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) | |||
| }, CheckInternalToken) | |||
| } | |||
| @@ -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" | |||
| @@ -37,6 +38,9 @@ const ( | |||
| tplCloudBrainBenchmarkIndex base.TplName = "repo/cloudbrain/benchmark/index" | |||
| tplCloudBrainBenchmarkNew base.TplName = "repo/cloudbrain/benchmark/new" | |||
| tplCloudBrainBenchmarkShow base.TplName = "repo/cloudbrain/benchmark/show" | |||
| tplCloudBrainTrainJobNew base.TplName = "repo/cloudbrain/trainjob/new" | |||
| tplCloudBrainTrainJobShow base.TplName = "repo/cloudbrain/trainjob/show" | |||
| ) | |||
| var ( | |||
| @@ -45,6 +49,7 @@ var ( | |||
| benchmarkTypes *models.BenchmarkTypes | |||
| benchmarkGpuInfos *models.GpuInfos | |||
| benchmarkResourceSpecs *models.ResourceSpecs | |||
| trainGpuInfos *models.GpuInfos | |||
| ) | |||
| const BENCHMARK_TYPE_CODE = "repo.cloudbrain.benchmark.types" | |||
| @@ -143,6 +148,11 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { | |||
| } | |||
| ctx.Data["gpu_types"] = gpuInfos.GpuInfo | |||
| if trainGpuInfos == nil { | |||
| json.Unmarshal([]byte(setting.TrainGpuTypes), &trainGpuInfos) | |||
| } | |||
| ctx.Data["train_gpu_types"] = trainGpuInfos.GpuInfo | |||
| if benchmarkGpuInfos == nil { | |||
| json.Unmarshal([]byte(setting.BenchmarkGpuTypes), &benchmarkGpuInfos) | |||
| } | |||
| @@ -157,6 +167,14 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { | |||
| json.Unmarshal([]byte(setting.ResourceSpecs), &cloudbrain.ResourceSpecs) | |||
| } | |||
| ctx.Data["resource_specs"] = cloudbrain.ResourceSpecs.ResourceSpec | |||
| if cloudbrain.TrainResourceSpecs == nil { | |||
| json.Unmarshal([]byte(setting.TrainResourceSpecs), &cloudbrain.TrainResourceSpecs) | |||
| } | |||
| ctx.Data["train_resource_specs"] = cloudbrain.TrainResourceSpecs.ResourceSpec | |||
| ctx.Data["params"] = "" | |||
| ctx.Data["branchName"] = ctx.Repo.BranchName | |||
| ctx.Data["snn4imagenet_path"] = cloudbrain.Snn4imagenetMountPath | |||
| ctx.Data["is_snn4imagenet_enabled"] = setting.IsSnn4imagenetEnabled | |||
| @@ -184,38 +202,52 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| image := form.Image | |||
| uuid := form.Attachment | |||
| jobType := form.JobType | |||
| command := cloudbrain.Command | |||
| gpuQueue := form.GpuType | |||
| codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
| resourceSpecId := form.ResourceSpecId | |||
| branchName := form.BranchName | |||
| repo := ctx.Repo.Repository | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName) | |||
| tpl := tplCloudBrainNew | |||
| command := cloudbrain.Command | |||
| if jobType == string(models.JobTypeTrain) { | |||
| tpl = tplCloudBrainTrainJobNew | |||
| commandTrain, err := getTrainJobCommand(form) | |||
| if err != nil { | |||
| log.Error("getTrainJobCommand failed: %v", err) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| command = commandTrain | |||
| } | |||
| tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) | |||
| if err == nil { | |||
| if len(tasks) != 0 { | |||
| log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr("the job name did already exist", tpl, &form) | |||
| return | |||
| } | |||
| } else { | |||
| if !models.IsErrJobNotExist(err) { | |||
| log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| if !jobNamePattern.MatchString(displayJobName) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) | |||
| return | |||
| } | |||
| if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) { | |||
| if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) && jobType != string(models.JobTypeTrain) { | |||
| log.Error("jobtype error:", jobType, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("jobtype error", tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr("jobtype error", tpl, &form) | |||
| return | |||
| } | |||
| @@ -223,18 +255,21 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| if err != nil { | |||
| log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr("system error", tpl, &form) | |||
| return | |||
| } else { | |||
| if count >= 1 { | |||
| log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr("you have already a running or waiting task, can not create more", tpl, &form) | |||
| return | |||
| } | |||
| } | |||
| downloadCode(repo, codePath) | |||
| if branchName == "" { | |||
| branchName = cloudbrain.DefaultBranchName | |||
| } | |||
| downloadCode(repo, codePath, branchName) | |||
| uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") | |||
| modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | |||
| @@ -268,15 +303,19 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
| err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | |||
| 0, 0, resourceSpecId) | |||
| if err != nil { | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||
| ctx.RenderWithErr(err.Error(), tpl, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| if jobType == string(models.JobTypeTrain) { | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=all") | |||
| } else { | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
| } | |||
| } | |||
| func CloudBrainRestart(ctx *context.Context) { | |||
| @@ -307,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"]) | |||
| @@ -342,32 +399,78 @@ func CloudBrainRestart(ctx *context.Context) { | |||
| } | |||
| func CloudBrainBenchMarkShow(ctx *context.Context) { | |||
| cloudBrainShow(ctx, tplCloudBrainBenchmarkShow) | |||
| cloudBrainShow(ctx, tplCloudBrainBenchmarkShow, models.JobTypeBenchmark) | |||
| } | |||
| func CloudBrainShow(ctx *context.Context) { | |||
| cloudBrainShow(ctx, tplCloudBrainShow) | |||
| cloudBrainShow(ctx, tplCloudBrainShow, models.JobTypeDebug) | |||
| } | |||
| func CloudBrainTrainJobShow(ctx *context.Context) { | |||
| cloudBrainShow(ctx, tplCloudBrainTrainJobShow, models.JobTypeTrain) | |||
| } | |||
| func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.JobType) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| var ID = ctx.Params(":id") | |||
| debugListType := ctx.Query("debugListType") | |||
| task, err := models.GetCloudbrainByID(ID) | |||
| var task *models.Cloudbrain | |||
| var err error | |||
| if jobType == models.JobTypeTrain { | |||
| task, err = models.GetCloudbrainByJobID(ctx.Params(":jobid")) | |||
| } else { | |||
| 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") | |||
| spec := "GPU数:" + strconv.Itoa(jobRes.Resource.NvidiaComGpu) + ",CPU数:" + strconv.Itoa(jobRes.Resource.CPU) + ",内存(MB):" + jobRes.Resource.Memory | |||
| ctx.Data["resource_spec"] = spec | |||
| if task.JobType == string(models.JobTypeTrain) { | |||
| if trainGpuInfos == nil { | |||
| json.Unmarshal([]byte(setting.TrainGpuTypes), &trainGpuInfos) | |||
| } | |||
| for _, resourceType := range trainGpuInfos.GpuInfo { | |||
| if resourceType.Queue == jobRes.Config.GpuType { | |||
| 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) { | |||
| @@ -376,12 +479,16 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| task.Status = taskRes.TaskStatuses[0].State | |||
| task.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
| task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
| if task.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() { | |||
| task.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix()) | |||
| } | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| ctx.Data["error"] = err.Error() | |||
| models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) | |||
| 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 | |||
| @@ -398,7 +505,9 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| ctx.Data["result"] = jobRes | |||
| } else { | |||
| log.Info("error:" + err.Error()) | |||
| return | |||
| } | |||
| user, err := models.GetUserByID(task.UserID) | |||
| if err == nil { | |||
| task.User = user | |||
| @@ -419,15 +528,47 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| } | |||
| } | |||
| if task.TrainJobDuration == "" { | |||
| var duration int64 | |||
| if task.Status == string(models.JobRunning) { | |||
| duration = time.Now().Unix() - int64(task.CreatedUnix) | |||
| } else { | |||
| duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | |||
| 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(duration) | |||
| task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
| } | |||
| ctx.Data["duration"] = task.TrainJobDuration | |||
| if len(task.Parameters) > 0 { | |||
| var parameters models.Parameters | |||
| err := json.Unmarshal([]byte(task.Parameters), ¶meters) | |||
| if err != nil { | |||
| log.Error("Failed to Unmarshal Parameters: %s (%v)", task.Parameters, err) | |||
| task.Parameters = "" | |||
| } else { | |||
| if len(parameters.Parameter) > 0 { | |||
| paramTemp := "" | |||
| for _, Parameter := range parameters.Parameter { | |||
| param := Parameter.Label + " = " + Parameter.Value + "; " | |||
| paramTemp = paramTemp + param | |||
| } | |||
| task.Parameters = paramTemp[:len(paramTemp)-2] | |||
| } else { | |||
| task.Parameters = "" | |||
| } | |||
| } | |||
| } | |||
| 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 | |||
| ctx.Data["displayJobName"] = task.DisplayJobName | |||
| @@ -435,6 +576,10 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
| version_list_task = append(version_list_task, task) | |||
| ctx.Data["version_list_task"] = version_list_task | |||
| ctx.Data["debugListType"] = debugListType | |||
| 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) | |||
| } | |||
| @@ -506,11 +651,12 @@ func CloudBrainStop(ctx *context.Context) { | |||
| break | |||
| } | |||
| ctx.JSON(200, map[string]string{ | |||
| ctx.JSON(200, map[string]interface{}{ | |||
| "result_code": resultCode, | |||
| "error_msg": errorMsg, | |||
| "status": status, | |||
| "id": ID, | |||
| "StatusOK": 0, | |||
| }) | |||
| } | |||
| @@ -762,8 +908,8 @@ func GetRate(ctx *context.Context) { | |||
| } | |||
| } | |||
| func downloadCode(repo *models.Repository, codePath string) error { | |||
| if err := git.Clone(repo.RepoPath(), codePath, git.CloneRepoOptions{}); err != nil { | |||
| func downloadCode(repo *models.Repository, codePath, branchName string) error { | |||
| if err := git.Clone(repo.RepoPath(), codePath, git.CloneRepoOptions{Branch: branchName}); err != nil { | |||
| log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) | |||
| return err | |||
| } | |||
| @@ -961,14 +1107,7 @@ func SyncCloudbrainStatus() { | |||
| taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
| task.Status = taskRes.TaskStatuses[0].State | |||
| if task.Status != string(models.JobWaiting) { | |||
| task.Duration = time.Now().Unix() - taskRes.TaskStatuses[0].StartAt.Unix() | |||
| if task.StartTime == 0 && !taskRes.TaskStatuses[0].StartAt.IsZero() { | |||
| task.StartTime = timeutil.TimeStamp(taskRes.TaskStatuses[0].StartAt.Unix()) | |||
| } | |||
| if task.EndTime == 0 && models.IsCloudBrainOneDebugJobTerminal(task.Status) { | |||
| task.EndTime = timeutil.TimeStampNow() | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
| @@ -1011,8 +1150,8 @@ func SyncCloudbrainStatus() { | |||
| if result != nil { | |||
| task.Status = result.Status | |||
| if task.StartTime == 0 && result.Lease.CreateTime > 0 { | |||
| task.StartTime = timeutil.TimeStamp(result.Lease.CreateTime / 1000) | |||
| if task.StartTime == 0 && result.Lease.UpdateTime > 0 { | |||
| task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000) | |||
| } | |||
| if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
| task.EndTime = timeutil.TimeStampNow() | |||
| @@ -1024,7 +1163,7 @@ func SyncCloudbrainStatus() { | |||
| continue | |||
| } | |||
| } | |||
| } else if task.JobType == string(models.JobTypeTrain) { | |||
| } else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) { | |||
| result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10)) | |||
| if err != nil { | |||
| log.Error("GetTrainJob(%s) failed:%v", task.JobName, err) | |||
| @@ -1062,6 +1201,158 @@ func SyncCloudbrainStatus() { | |||
| return | |||
| } | |||
| func HandleTaskWithNoDuration(ctx *context.Context) { | |||
| log.Info("HandleTaskWithNoDuration start") | |||
| count := 0 | |||
| start := time.Now().Unix() | |||
| for { | |||
| cloudBrains, err := models.GetStoppedJobWithNoDurationJob() | |||
| if err != nil { | |||
| log.Error("HandleTaskWithNoTrainJobDuration failed:", err.Error()) | |||
| break | |||
| } | |||
| if len(cloudBrains) == 0 { | |||
| log.Info("HandleTaskWithNoTrainJobDuration:no task need handle") | |||
| break | |||
| } | |||
| handleNoDurationTask(cloudBrains) | |||
| count += len(cloudBrains) | |||
| if len(cloudBrains) < 100 { | |||
| log.Info("HandleTaskWithNoTrainJobDuration:task less than 100") | |||
| break | |||
| } | |||
| if time.Now().Unix()-start > 600 { | |||
| log.Info("HandleTaskWithNoDuration : time out") | |||
| ctx.JSON(200, fmt.Sprintf("task stop for time out,count=%d", count)) | |||
| return | |||
| } | |||
| } | |||
| log.Info("HandleTaskWithNoTrainJobDuration:count=%d", count) | |||
| ctx.JSON(200, fmt.Sprintf("success,count=%d", count)) | |||
| } | |||
| func handleNoDurationTask(cloudBrains []*models.Cloudbrain) { | |||
| for _, task := range cloudBrains { | |||
| time.Sleep(time.Millisecond * 100) | |||
| log.Info("Handle job ,%+v", task) | |||
| if task.Type == models.TypeCloudBrainOne { | |||
| result, err := cloudbrain.GetJob(task.JobID) | |||
| if err != nil { | |||
| log.Error("GetJob(%s) failed:%v", task.JobName, err) | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| if result != nil { | |||
| if result.Msg != "success" { | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| jobRes, err := models.ConvertToJobResultPayload(result.Payload) | |||
| if err != nil || len(jobRes.TaskRoles) == 0 { | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| taskRoles := jobRes.TaskRoles | |||
| taskRes, err := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
| if err != nil || len(taskRes.TaskStatuses) == 0 { | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| task.Status = taskRes.TaskStatuses[0].State | |||
| log.Info("task startTime = %v endTime= %v ,jobId=%d", jobRes.JobStatus.StartTime, jobRes.JobStatus.EndTime, task.ID) | |||
| if jobRes.JobStatus.CreatedTime > 0 { | |||
| task.StartTime = timeutil.TimeStamp(jobRes.JobStatus.CreatedTime / 1000) | |||
| if jobRes.JobStatus.CompletedTime > 0 { | |||
| task.EndTime = timeutil.TimeStamp(jobRes.JobStatus.CompletedTime / 1000) | |||
| } else { | |||
| task.EndTime = task.UpdatedUnix | |||
| } | |||
| } else { | |||
| task.StartTime = 0 | |||
| task.EndTime = 0 | |||
| } | |||
| if task.EndTime < task.StartTime { | |||
| log.Info("endTime[%v] is less than starTime[%v],jobId=%d", task.EndTime, task.StartTime, task.ID) | |||
| st := task.StartTime | |||
| task.StartTime = task.EndTime | |||
| task.EndTime = st | |||
| } | |||
| task.Duration = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | |||
| task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
| } | |||
| } | |||
| } else if task.Type == models.TypeCloudBrainTwo { | |||
| if task.JobType == string(models.JobTypeDebug) { | |||
| //result, err := modelarts.GetJob(task.JobID) | |||
| result, err := modelarts.GetNotebook2(task.JobID) | |||
| if err != nil { | |||
| log.Error("GetJob(%s) failed:%v", task.JobName, err) | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| if result != nil { | |||
| task.Status = result.Status | |||
| startTime := result.Lease.CreateTime | |||
| duration := result.Lease.Duration / 1000 | |||
| if startTime > 0 { | |||
| task.StartTime = timeutil.TimeStamp(startTime / 1000) | |||
| task.EndTime = task.StartTime.Add(duration) | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
| continue | |||
| } | |||
| } | |||
| } else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) { | |||
| result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10)) | |||
| if err != nil { | |||
| log.Error("GetTrainJob(%s) failed:%v", task.JobName, err) | |||
| updateDefaultDuration(task) | |||
| continue | |||
| } | |||
| if result != nil { | |||
| startTime := result.StartTime / 1000 | |||
| if startTime > 0 { | |||
| task.StartTime = timeutil.TimeStamp(startTime) | |||
| task.EndTime = task.StartTime.Add(result.Duration / 1000) | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
| continue | |||
| } | |||
| } | |||
| } else { | |||
| log.Error("task.JobType(%s) is error:%s", task.JobName, task.JobType) | |||
| } | |||
| } else { | |||
| log.Error("task.Type(%s) is error:%d", task.JobName, task.Type) | |||
| } | |||
| } | |||
| } | |||
| func updateDefaultDuration(task *models.Cloudbrain) { | |||
| log.Info("updateDefaultDuration: taskId=%d", task.ID) | |||
| task.StartTime = task.CreatedUnix | |||
| task.EndTime = task.UpdatedUnix | |||
| task.ComputeAndSetDuration() | |||
| err := models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
| } | |||
| } | |||
| func CloudBrainBenchmarkIndex(ctx *context.Context) { | |||
| MustEnableCloudbrain(ctx) | |||
| repo := ctx.Repo.Repository | |||
| @@ -1090,13 +1381,16 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) { | |||
| ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||
| if ciTasks[i].TrainJobDuration == "" { | |||
| var duration int64 | |||
| if task.Status == string(models.JobRunning) { | |||
| duration = time.Now().Unix() - int64(task.Cloudbrain.CreatedUnix) | |||
| } else { | |||
| duration = int64(task.Cloudbrain.UpdatedUnix) - int64(task.Cloudbrain.CreatedUnix) | |||
| if ciTasks[i].Duration == 0 { | |||
| var duration int64 | |||
| if task.Status == string(models.JobRunning) { | |||
| duration = time.Now().Unix() - int64(task.Cloudbrain.CreatedUnix) | |||
| } else { | |||
| duration = int64(task.Cloudbrain.UpdatedUnix) - int64(task.Cloudbrain.CreatedUnix) | |||
| } | |||
| ciTasks[i].Duration = duration | |||
| } | |||
| ciTasks[i].TrainJobDuration = models.ConvertDurationToStr(duration) | |||
| ciTasks[i].TrainJobDuration = models.ConvertDurationToStr(ciTasks[i].Duration) | |||
| } | |||
| ciTasks[i].BenchmarkTypeName = "" | |||
| @@ -1315,7 +1609,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
| } | |||
| os.RemoveAll(codePath) | |||
| if err := downloadCode(repo, codePath); err != nil { | |||
| if err := downloadCode(repo, codePath, cloudbrain.DefaultBranchName); err != nil { | |||
| log.Error("downloadCode failed, %v", err, ctx.Data["MsgID"]) | |||
| cloudBrainNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) | |||
| @@ -1380,7 +1674,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
| err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, childInfo.Attachment, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, | |||
| storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, cloudbrain.DefaultBranchName, "", "", | |||
| benchmarkTypeID, benchmarkChildTypeID, resourceSpecId) | |||
| if err != nil { | |||
| cloudBrainNewDataPrepare(ctx) | |||
| @@ -1406,10 +1700,66 @@ func BenchmarkDel(ctx *context.Context) { | |||
| } | |||
| } | |||
| func CloudBrainTrainJobNew(ctx *context.Context) { | |||
| err := cloudBrainNewDataPrepare(ctx) | |||
| if err != nil { | |||
| ctx.ServerError("get new train-job info failed", err) | |||
| return | |||
| } | |||
| ctx.HTML(http.StatusOK, tplCloudBrainTrainJobNew) | |||
| } | |||
| func getTrainJobCommand(form auth.CreateCloudBrainForm) (string, error) { | |||
| var command string | |||
| bootFile := form.BootFile | |||
| params := form.Params | |||
| if !strings.HasSuffix(bootFile, ".py") { | |||
| log.Error("bootFile(%s) format error", bootFile) | |||
| return command, errors.New("bootFile format error") | |||
| } | |||
| var parameters models.Parameters | |||
| var param string | |||
| if len(params) != 0 { | |||
| err := json.Unmarshal([]byte(params), ¶meters) | |||
| if err != nil { | |||
| log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
| return command, err | |||
| } | |||
| for _, parameter := range parameters.Parameter { | |||
| param += " --" + parameter.Label + "=" + parameter.Value | |||
| } | |||
| } | |||
| command += "python /code/" + bootFile + param + " > " + cloudbrain.ModelMountPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile | |||
| return command, nil | |||
| } | |||
| func CloudBrainTrainJobDel(ctx *context.Context) { | |||
| var listType = ctx.Query("listType") | |||
| if err := deleteCloudbrainJob(ctx); err != nil { | |||
| log.Error("deleteCloudbrainJob failed: %v", err, ctx.Data["msgID"]) | |||
| ctx.ServerError(err.Error(), err) | |||
| return | |||
| } | |||
| var isAdminPage = ctx.Query("isadminpage") | |||
| if ctx.IsUserSiteAdmin() && isAdminPage == "true" { | |||
| ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") | |||
| } else { | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
| } | |||
| } | |||
| func GetBenchmarkTypes(ctx *context.Context) *models.BenchmarkTypes { | |||
| var lang = ctx.Locale.Language() | |||
| if benchmarkTypesMap[lang] == nil { | |||
| var val = i18n.Tr(lang, BENCHMARK_TYPE_CODE) | |||
| //use config | |||
| val = setting.BenchmarkTypes | |||
| var tempType *models.BenchmarkTypes | |||
| if err := json.Unmarshal([]byte(val), &tempType); err != nil { | |||
| log.Error("json.Unmarshal BenchmarkTypes(%s) failed:%v", val, err, ctx.Data["MsgID"]) | |||
| @@ -2,9 +2,9 @@ package repo | |||
| import ( | |||
| "archive/zip" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "encoding/json" | |||
| "errors" | |||
| "fmt" | |||
| "io" | |||
| "io/ioutil" | |||
| "net/http" | |||
| @@ -15,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" | |||
| @@ -47,20 +50,26 @@ const ( | |||
| ) | |||
| func DebugJobIndex(ctx *context.Context) { | |||
| debugListType := ctx.Query("debugListType") | |||
| ctx.Data["ListType"] = debugListType | |||
| listType := ctx.Query("debugListType") | |||
| ctx.Data["ListType"] = listType | |||
| MustEnableCloudbrain(ctx) | |||
| repo := ctx.Repo.Repository | |||
| page := ctx.QueryInt("page") | |||
| if page <= 0 { | |||
| page = 1 | |||
| } | |||
| debugType := modelarts.DebugType | |||
| typeCloudBrain := models.TypeCloudBrainAll | |||
| jobTypeNot := false | |||
| if debugListType == models.GPUResource { | |||
| debugType = models.TypeCloudBrainOne | |||
| } else if debugListType == models.NPUResource { | |||
| debugType = models.TypeCloudBrainTwo | |||
| if listType == models.GPUResource { | |||
| typeCloudBrain = models.TypeCloudBrainOne | |||
| } else if listType == models.NPUResource { | |||
| typeCloudBrain = models.TypeCloudBrainTwo | |||
| } else if listType == models.AllResource { | |||
| typeCloudBrain = models.TypeCloudBrainAll | |||
| } else { | |||
| log.Error("listType(%s) error", listType) | |||
| ctx.ServerError("listType error", errors.New("listType error")) | |||
| return | |||
| } | |||
| var jobTypes []string | |||
| @@ -71,7 +80,7 @@ func DebugJobIndex(ctx *context.Context) { | |||
| PageSize: setting.UI.IssuePagingNum, | |||
| }, | |||
| RepoID: repo.ID, | |||
| Type: debugType, | |||
| Type: typeCloudBrain, | |||
| JobTypeNot: jobTypeNot, | |||
| JobTypes: jobTypes, | |||
| }) | |||
| @@ -93,7 +102,7 @@ func DebugJobIndex(ctx *context.Context) { | |||
| ctx.Data["Tasks"] = ciTasks | |||
| ctx.Data["CanCreate"] = cloudbrain.CanCreateOrDebugJob(ctx) | |||
| ctx.Data["RepoIsEmpty"] = repo.IsEmpty | |||
| ctx.Data["debugListType"] = debugListType | |||
| ctx.Data["debugListType"] = listType | |||
| ctx.HTML(200, tplDebugJobIndex) | |||
| } | |||
| @@ -240,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) | |||
| @@ -255,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 := "-" | |||
| @@ -272,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) | |||
| } | |||
| @@ -410,20 +450,46 @@ func NotebookManage(ctx *context.Context) { | |||
| break | |||
| } | |||
| task.Status = res.Status | |||
| if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
| task.EndTime = timeutil.TimeStampNow() | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| status = res.Status | |||
| if action == models.ActionStart { | |||
| newTask := &models.Cloudbrain{ | |||
| Status: status, | |||
| UserID: task.UserID, | |||
| RepoID: task.RepoID, | |||
| JobID: task.JobID, | |||
| JobName: task.JobName, | |||
| DisplayJobName: task.DisplayJobName, | |||
| JobType: task.JobType, | |||
| Type: task.Type, | |||
| Uuid: task.Uuid, | |||
| Image: task.Image, | |||
| ComputeResource: task.ComputeResource, | |||
| Description: task.Description, | |||
| } | |||
| status = task.Status | |||
| err = models.RestartCloudbrain(task, newTask) | |||
| if err != nil { | |||
| log.Error("RestartCloudbrain(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| ID = strconv.FormatInt(newTask.ID, 10) | |||
| notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, ID, task.DisplayJobName, models.ActionCreateDebugNPUTask) | |||
| } else { | |||
| task.Status = res.Status | |||
| if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
| task.EndTime = timeutil.TimeStampNow() | |||
| } | |||
| task.ComputeAndSetDuration() | |||
| err = models.UpdateJob(task) | |||
| if err != nil { | |||
| log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
| resultCode = "-1" | |||
| errorMsg = "system error" | |||
| break | |||
| } | |||
| } | |||
| break | |||
| } | |||
| @@ -480,6 +546,26 @@ func TrainJobIndex(ctx *context.Context) { | |||
| page = 1 | |||
| } | |||
| listType := ctx.Query("listType") | |||
| if len(listType) == 0 { | |||
| listType = models.AllResource | |||
| } | |||
| ctx.Data["ListType"] = listType | |||
| typeCloudBrain := models.TypeCloudBrainAll | |||
| if listType == models.GPUResource { | |||
| typeCloudBrain = models.TypeCloudBrainOne | |||
| } else if listType == models.NPUResource { | |||
| typeCloudBrain = models.TypeCloudBrainTwo | |||
| } else if listType == models.AllResource { | |||
| typeCloudBrain = models.TypeCloudBrainAll | |||
| } | |||
| //else { | |||
| // log.Error("listType(%s) error", listType) | |||
| // ctx.ServerError("listType error", errors.New("listType error")) | |||
| // return | |||
| //} | |||
| var jobTypes []string | |||
| jobTypes = append(jobTypes, string(models.JobTypeTrain)) | |||
| tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
| @@ -488,7 +574,7 @@ func TrainJobIndex(ctx *context.Context) { | |||
| PageSize: setting.UI.IssuePagingNum, | |||
| }, | |||
| RepoID: repo.ID, | |||
| Type: models.TypeCloudBrainTwo, | |||
| Type: typeCloudBrain, | |||
| JobTypeNot: false, | |||
| JobTypes: jobTypes, | |||
| IsLatestVersion: modelarts.IsLatestVersion, | |||
| @@ -501,11 +587,16 @@ func TrainJobIndex(ctx *context.Context) { | |||
| for i, task := range tasks { | |||
| tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
| tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||
| tasks[i].ComputeResource = models.NPUResource | |||
| if task.Cloudbrain.Type == models.TypeCloudBrainOne { | |||
| tasks[i].ComputeResource = models.GPUResource | |||
| } else if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||
| tasks[i].ComputeResource = models.NPUResource | |||
| } | |||
| } | |||
| pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
| pager.SetDefaultParams(ctx) | |||
| pager.AddParam(ctx, "listType", "ListType") | |||
| ctx.Data["Page"] = pager | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| @@ -1495,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) | |||
| } | |||
| @@ -1555,6 +1646,7 @@ func trainJobGetLog(jobID string) (*models.GetTrainJobLogFileNamesResult, *model | |||
| func TrainJobDel(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var listType = ctx.Query("listType") | |||
| repo := ctx.Repo.Repository | |||
| var jobTypes []string | |||
| @@ -1596,12 +1688,13 @@ func TrainJobDel(ctx *context.Context) { | |||
| if ctx.IsUserSiteAdmin() && isAdminPage == "true" { | |||
| ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") | |||
| } else { | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
| } | |||
| } | |||
| func TrainJobStop(ctx *context.Context) { | |||
| var jobID = ctx.Params(":jobid") | |||
| var listType = ctx.Query("listType") | |||
| task := ctx.Cloudbrain | |||
| _, err := modelarts.StopTrainJob(jobID, strconv.FormatInt(task.VersionID, 10)) | |||
| @@ -1611,7 +1704,7 @@ func TrainJobStop(ctx *context.Context) { | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
| } | |||
| func canUserCreateTrainJob(uid int64) (bool, error) { | |||
| @@ -2124,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) | |||
| @@ -2276,7 +2369,7 @@ func SetJobCount(ctx *context.Context) { | |||
| repoId := ctx.Repo.Repository.ID | |||
| _, jobCount, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
| RepoID: repoId, | |||
| Type: modelarts.DebugType, | |||
| Type: models.TypeCloudBrainAll, | |||
| }) | |||
| if err != nil { | |||
| ctx.ServerError("Get job faild:", err) | |||
| @@ -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) | |||
| @@ -323,6 +323,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Get("/action/notification", routers.ActionNotification) | |||
| m.Get("/recommend/org", routers.RecommendOrgFromPromote) | |||
| m.Get("/recommend/repo", routers.RecommendRepoFromPromote) | |||
| m.Post("/all/search/", routers.Search) | |||
| m.Get("/all/search/", routers.EmptySearch) | |||
| m.Get("/all/dosearch/", routers.SearchApi) | |||
| m.Get("/home/term", routers.HomeTerm) | |||
| m.Group("/explore", func() { | |||
| m.Get("", func(ctx *context.Context) { | |||
| @@ -1035,6 +1038,19 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainBenchmarkCreate) | |||
| m.Get("/get_child_types", repo.GetChildTypes) | |||
| }) | |||
| m.Group("/train-job", func() { | |||
| m.Group("/:jobid", func() { | |||
| m.Get("", reqRepoCloudBrainReader, repo.CloudBrainTrainJobShow) | |||
| m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainTrainJobDel) | |||
| //m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | |||
| m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel) | |||
| //m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion) | |||
| //m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
| }) | |||
| m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.CloudBrainTrainJobNew) | |||
| m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | |||
| }) | |||
| }, context.RepoRef()) | |||
| m.Group("/modelmanage", func() { | |||
| m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | |||
| @@ -10,7 +10,7 @@ import ( | |||
| "github.com/elliotchance/orderedmap" | |||
| ) | |||
| var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 25, 26, 27, 28, 29, 30} | |||
| var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 25, 26, 27, 28, 29, 30, 31} | |||
| type ClientsManager struct { | |||
| Clients *orderedmap.OrderedMap | |||
| @@ -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"}} | |||
| @@ -95,9 +95,9 @@ | |||
| {{if .IsSigned}} | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="hot"> | |||
| @@ -199,9 +199,9 @@ | |||
| <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="hot"> | |||
| @@ -93,9 +93,9 @@ | |||
| {{if .IsSigned}} | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="{{$.SortType}}"> | |||
| @@ -196,9 +196,9 @@ | |||
| <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="{{$.SortType}}"> | |||
| @@ -96,9 +96,9 @@ | |||
| {{if .IsSigned}} | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="{{$.SortType}}"> | |||
| @@ -199,9 +199,9 @@ | |||
| <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
| <div class="right stackable menu"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
| <form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
| <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
| style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="{{$.SortType}}"> | |||
| @@ -3,7 +3,11 @@ | |||
| <div class="inline {{if eq .cloudbraintype 0}} required {{end}} field" id="dataset-base"> | |||
| <label>{{.i18n.Tr "dataset.dataset"}}</label> | |||
| <input type="hidden" name="attachment" :value="dataset_uuid"> | |||
| <input type="text" :value="dataset_name" disabled> | |||
| {{if eq .cloudbraintype 0}} | |||
| <input class="disabled" type="text" :value="dataset_name" required onfocus="this.blur();"> | |||
| {{else}} | |||
| <input class="disabled" type="text" :value="dataset_name"> | |||
| {{end}} | |||
| <el-button type="text" @click="dialogVisible = true" icon="el-icon-plus"> {{.i18n.Tr "dataset.select_dataset"}}</el-button> | |||
| <el-dialog | |||
| title="{{.i18n.Tr "dataset.select_dataset"}}" | |||
| @@ -131,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> | |||
| @@ -10,7 +10,19 @@ | |||
| <div class="ui sixteen wide mobile twelve wide tablet ten wide computer column"> | |||
| {{template "explore/repo_list" .}} | |||
| {{template "base/paginate" .}} | |||
| <div id="app" style="margin-top: 2rem;"> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-sizes="[20]" | |||
| :page-size="20" | |||
| layout="total, sizes, prev, pager, next, jumper" | |||
| :total="{{.Page.Paginater.Total}}"> | |||
| </el-pagination> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="computer only ui three wide computer column"> | |||
| {{template "explore/repo_right" .}} | |||
| @@ -0,0 +1,95 @@ | |||
| {{template "base/head" .}} | |||
| <div class="explore seach"> | |||
| <div class="repos--seach"> | |||
| <div class="ui container"> | |||
| <div id="search_div" class="ui two column centered grid"> | |||
| <div class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem;margin-bottom: 1.2rem;"> | |||
| <div class="ui fluid action input"> | |||
| <input name="q" id="keyword_input" value="{{.Keyword}}" placeholder="{{.i18n.Tr "home.search"}}..." autofocus=""> | |||
| <input type="hidden" name="topic" value=""> | |||
| <input type="hidden" name="tab" value=""> | |||
| <input type="hidden" name="sort" value="hot"> | |||
| <button class="ui green button" onclick="search()">{{.i18n.Tr "home.search"}}</button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div id="search_label_div" style="display:none"> | |||
| </div> | |||
| </div> | |||
| <div class="ui container seachnav"> | |||
| <div class="ui secondary pointing menu"> | |||
| <a id="repo_item" class="item" href="javascript:searchItem(1,10);"> | |||
| {{.i18n.Tr "home.search_repo"}} | |||
| <span class="ui circular mini label" id="repo_total"></span> | |||
| </a> | |||
| <a id="dataset_item" class="item" href="javascript:searchItem(5,50);"> | |||
| {{.i18n.Tr "home.search_dataset"}} | |||
| <span class="ui circular mini label" id="dataset_total"></span> | |||
| </a> | |||
| <a id="issue_item" class="item" href="javascript:searchItem(2,20);"> | |||
| {{.i18n.Tr "home.search_issue"}} | |||
| <span class="ui circular mini label" id="issue_total"></span> | |||
| </a> | |||
| <a id="pr_item" class="item" href="javascript:searchItem(6,60);"> | |||
| {{.i18n.Tr "home.search_pr"}} | |||
| <span class="ui circular mini label" id="pr_total"></span> | |||
| </a> | |||
| <a id="user_item" class="item" href="javascript:searchItem(3,30);"> | |||
| {{.i18n.Tr "home.search_user"}} | |||
| <span class="ui circular mini label" id="user_total"></span> | |||
| </a> | |||
| <a id="org_item" class="item" href="javascript:searchItem(4,40);"> | |||
| {{.i18n.Tr "home.search_org"}} <span class="ui circular mini label" id="org_total"></span> | |||
| </a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="ui container"> | |||
| <span id="find_id">{{.i18n.Tr "home.search_finded"}}</span><span id="find_title"></span> | |||
| <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" id="sort_type"> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="ui divider" style="margin-top: 1.25rem;"></div> | |||
| <div class="ui very relaxed divided list" id="child_search_item"> | |||
| </div><!--seach list end--> | |||
| <div class="center page buttons" style="margin: 0px auto 15px"> | |||
| <div class="ui borderless mini pagination menu" id="page_menu"> | |||
| </div> | |||
| </div> | |||
| <div id="tipmsg"></div> | |||
| </div> | |||
| </div> | |||
| <script src="/self/js/jquery.min.js" type="text/javascript"></script> | |||
| <script src="/home/search.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
| <div class="am-mt-30"></div> | |||
| {{template "base/footer" .}} | |||
| @@ -185,7 +185,19 @@ | |||
| </div> | |||
| --> | |||
| {{template "base/paginate" .}} | |||
| <div id="app" style="margin-top: 2rem;"> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-sizes="[10]" | |||
| :page-size="10" | |||
| layout="total, sizes, prev, pager, next, jumper" | |||
| :total="{{.Page.Paginater.Total}}"> | |||
| </el-pagination> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -196,7 +196,13 @@ td, th { | |||
| <span class="accordion-panel-title-content"> | |||
| <span> | |||
| <div class="ac-display-inblock title_text acc-margin-bottom"> | |||
| <span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
| <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> | |||
| @@ -252,7 +258,13 @@ td, th { | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
| <span style="font-size: 12px;" class=""> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .CreatedUnix}} | |||
| {{end}} | |||
| </span> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -269,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"> | |||
| @@ -280,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"> | |||
| @@ -301,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"> | |||
| @@ -312,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"> | |||
| @@ -348,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"> | |||
| @@ -359,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,100 +1,501 @@ | |||
| {{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: 560px; | |||
| 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> | |||
| <td>{{.JobStatus.StartTime}}</td> | |||
| </tr> | |||
| <tr> | |||
| <td> 结束时间 </td> | |||
| <td>{{.JobStatus.EndTime}}</td> | |||
| </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> | |||
| </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.modelarts.train_job.start_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class=""> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .CreatedUnix}} | |||
| {{end}} | |||
| </span> | |||
| </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 "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 "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.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> | |||
| </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.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"> | |||
| ExitCode | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{$.result.JobStatus.AppExitCode}} | |||
| </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.endtime"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName"> | |||
| {{if not (eq .EndTime 0)}} | |||
| {{TimeSinceUnix1 .EndTime}} | |||
| {{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.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 "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 "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> | |||
| </tbody> | |||
| </table> | |||
| </div> | |||
| </div> | |||
| <div class="ac-grid ac-grid-col2"> | |||
| <div class="ac-grid-col"> | |||
| <span class="ti-text-form-label">{{$.i18n.Tr "repo.cloudbrain.exitinfo"}}</span> | |||
| </div> | |||
| </div> | |||
| <div class="ac-grid-col"> | |||
| <span class="info_text"> | |||
| {{$.result.JobStatus.AppExitDiagnostics}} | |||
| </span> | |||
| </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] | |||
| }) | |||
| function loadLog(version_name){ | |||
| document.getElementById("mask").style.display = "block" | |||
| $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${jobName}/log?version_name=${version_name}&lines=50&order=asc`, (data) => { | |||
| $('input[name=end_line]').val(data.EndLine) | |||
| $('input[name=start_line]').val(data.StartLine) | |||
| $(`#log_file${version_name}`).text(data.Content) | |||
| document.getElementById("mask").style.display = "none" | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| document.getElementById("mask").style.display = "none" | |||
| }); | |||
| } | |||
| </script> | |||
| @@ -0,0 +1,443 @@ | |||
| {{template "base/head" .}} | |||
| <style> | |||
| .unite{ | |||
| font-family: SourceHanSansSC-medium !important; | |||
| color: rgba(16, 16, 16, 100) !important; | |||
| } | |||
| .title{ | |||
| font-size: 16px !important; | |||
| padding-left: 3rem !important; | |||
| } | |||
| .min_title{ | |||
| font-size: 14px !important; | |||
| padding-left: 6rem !important; | |||
| margin-bottom: 2rem !important; | |||
| } | |||
| .width{ | |||
| width:100% !important; | |||
| } | |||
| .width80{ | |||
| width: 80.7% !important; | |||
| margin-left: 10px; | |||
| } | |||
| .width806{ | |||
| width: 80.6% !important; | |||
| margin-left: -2px; | |||
| } | |||
| .width85{ | |||
| width: 85% !important; | |||
| margin-left: 4.5rem !important; | |||
| } | |||
| .width81{ | |||
| margin-left: 1.5rem !important; | |||
| width: 81% !important; | |||
| } | |||
| .add{font-size: 18px; | |||
| padding: 0.5rem; | |||
| border: 1px solid rgba(187, 187, 187, 100); | |||
| border-radius: 0px 5px 5px 0px; | |||
| line-height: 21px; | |||
| text-align: center; | |||
| color: #C2C7CC; | |||
| } | |||
| .min{ | |||
| font-size: 18px; | |||
| padding: 0.5rem; | |||
| border: 1px solid rgba(187, 187, 187, 100); | |||
| border-radius: 5px 0px 0px 5px; | |||
| line-height: 21px; | |||
| text-align: center; | |||
| color: #C2C7CC; | |||
| } | |||
| </style> | |||
| <!-- <div class="ui page dimmer"> | |||
| <div class="ui text loader">{{.i18n.Tr "loading"}}</div> | |||
| </div> --> | |||
| <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="ui container"> | |||
| {{template "base/alert" .}} | |||
| <h4 class="ui top attached header"> | |||
| {{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
| </h4> | |||
| <div class="ui attached segment"> | |||
| <!-- equal width --> | |||
| <form class="ui form" action="{{.Link}}" method="post"> | |||
| {{.CsrfTokenHtml}} | |||
| <input type="hidden" name="action" value="update"> | |||
| <input type="hidden" id="ai_engine_name" name="engine_names" value=""> | |||
| <input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | |||
| <div class="ui blue mini menu compact selectcloudbrain"> | |||
| <a class="active item" href="{{.RepoLink}}/cloudbrain/train-job/create"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
| <path fill="none" d="M0 0h24v24H0z"/> | |||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
| </svg> | |||
| CPU/GPU | |||
| </a> | |||
| <a class="item" href="{{.RepoLink}}/modelarts/train-job/create"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
| <path fill="none" d="M0 0h24v24H0z"/> | |||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
| </svg> | |||
| Ascend NPU</a> | |||
| </div> | |||
| </div> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
| <span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span> | |||
| </div> | |||
| <div class="unite min_title inline field"> | |||
| <label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
| <textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)"></textarea> | |||
| </div> | |||
| <div class="ui divider"></div> | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
| <select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | |||
| {{if .branch_name}} | |||
| <option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | |||
| {{range $k, $v :=.Branches}} | |||
| {{ if ne $v $.branch_name }} | |||
| <option name="branch_name" value="{{$v}}">{{$v}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{else}} | |||
| <option name="branch_name" value="{{.branchName}}">{{.branchName}}</option> | |||
| {{range $k, $v :=.Branches}} | |||
| {{ if ne $v $.branchName }} | |||
| <option name="branch_name" value="{{$v}}">{{$v}}</option> | |||
| {{end}} | |||
| {{end}} | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| <div class="inline required field" style="display: none;"> | |||
| <label>{{.i18n.Tr "cloudbrain.task_type"}}</label> | |||
| <select id="cloudbrain_job_type" class="ui search dropdown" placeholder="选择任务类型" style='width:385px' name="job_type"> | |||
| <option name="job_type" value="TRAIN">TRAIN</option> | |||
| </select> | |||
| </div> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label> | |||
| <select id="cloudbrain_gpu_type" class="ui search width806 dropdown" placeholder="选择GPU类型" style='width:385px' name="gpu_type"> | |||
| {{range .train_gpu_types}} | |||
| <option value="{{.Queue}}">{{.Value}}</option> | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| <div class="required unite min_title inline field" style="position: relative;"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}} </label> | |||
| <input class="width81" type="text" list="cloudbrain_image" placeholder="{{.i18n.Tr "cloudbrain.choose_mirror"}}" name="image" required autofocus maxlength="255"> | |||
| <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
| <datalist class="ui search" id="cloudbrain_image" name="image"> | |||
| {{range .images}} | |||
| <option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
| {{end}} | |||
| {{range .public_images}} | |||
| <option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
| {{end}} | |||
| </datalist> | |||
| </div> | |||
| <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: 35.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
| {{else}} | |||
| <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/MNIST_PytorchExample_GPU" target="_blank">查看样例</a> | |||
| </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> | |||
| <input id="store_run_para" type="hidden" name="run_para_list"> | |||
| <div class="dynamic field" style="margin-top: 1rem;"> | |||
| {{if .params}} | |||
| {{if ne 0 (len .params)}} | |||
| {{range $k ,$v := .params}} | |||
| <div class="two fields width85" id="para{{$k}}"> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||
| </div> | |||
| <div class="field"> | |||
| <input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||
| </div> | |||
| <span> | |||
| <i class="trash icon"></i> | |||
| </span> | |||
| </div> | |||
| {{end}} | |||
| {{end}} | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| <div class="required inline unite min_title field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
| <select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="选择资源规格" style='width:385px' name="resource_spec_id"> | |||
| {{range .train_resource_specs}} | |||
| <option name="resource_spec_id" value="{{.Id}}">GPU数:{{.GpuNum}},CPU数:{{.CpuNum}},内存(MB):{{.MemMiB}},共享内存(MB):{{.ShareMemMiB}}</option> | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| <div class="inline unite min_title field"> | |||
| <button class="ui create_train_job green button"> | |||
| {{.i18n.Tr "repo.cloudbrain.new"}} | |||
| </button> | |||
| <a class="ui button" href="{{.RepoLink}}/modelarts/train-job">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
| </div> | |||
| <!-- 模态框 --> | |||
| </form> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| //let url_href = window.location.pathname.split('create')[0] | |||
| //$(".ui.button").attr('href',url_href) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| $('.menu .item') | |||
| .tab(); | |||
| let sever_num = $('#trainjob_work_server_num') | |||
| $('.add').click(function(){ | |||
| sever_num.val(parseInt(sever_num.val())+1) | |||
| if(sever_num.val()>=26){ | |||
| sever_num.val(parseInt(sever_num.val())-1) | |||
| } | |||
| }) | |||
| $('.min').click(function(){ | |||
| sever_num.val(parseInt(sever_num.val())-1) | |||
| if(sever_num.val()<=0){ | |||
| sever_num.val(parseInt(sever_num.val())+1) | |||
| } | |||
| }) | |||
| // 参数增加、删除、修改、保存 | |||
| function Add_parameter(i){ | |||
| value = '<div class="two fields width85" id= "para'+ i +'">' + | |||
| '<div class="field">' + | |||
| '<input type="text" name="shipping_first-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}> ' + | |||
| '</div> ' + | |||
| '<div class="field"> ' + | |||
| '<input type="text" name="shipping_last-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}>' + | |||
| '</div>'+ | |||
| '<span>' + | |||
| '<i class="trash icon">' + | |||
| '</i>' + | |||
| '</span>' + | |||
| '</div>' | |||
| $(".dynamic.field").append(value) | |||
| } | |||
| $('#add_run_para').click(function(){ | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| }); | |||
| $(".dynamic.field").on("click",".trash.icon", function() { | |||
| var index = $(this).parent().parent().index() | |||
| $(this).parent().parent().remove() | |||
| var len = $(".dynamic.field .two.fields").length | |||
| $(".dynamic.field .two.fields").each(function(){ | |||
| var cur_index = $(this).index() | |||
| $(this).attr('id', 'para' + cur_index) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.green.button').click(function(){ | |||
| var parameters = []; | |||
| $('table tr').each(function() { | |||
| $(this).find('td:eq(1)').each(function(){ | |||
| parameters.push($(this).text()); | |||
| }) | |||
| $(this).find('input').each(function(){ | |||
| parameters.push($(this).text()) | |||
| }) | |||
| }); | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| for(var i = 2; i < parameters.length; i++){ | |||
| switch(i) { | |||
| // 数据集uuid待完成 | |||
| // case (2): | |||
| // console.log(1) | |||
| // break; | |||
| // $("#trainjob_datasets").val(parameters[i]); | |||
| // console.log($("#trainjob_datasets").val()) | |||
| case (3): | |||
| $("input[name='boot_file']").val(parameters[i]); | |||
| break; | |||
| case (4): | |||
| var para = parameters[i].split(" ") | |||
| for(var j = 0; j < para.length; j++){ | |||
| var para_name = para[j].split('=')[0] | |||
| var para_value = para[j].split('=')[1] | |||
| var len = $(".dynamic.field .two.fields").length | |||
| Add_parameter(len) | |||
| var pid = 'para' + len | |||
| $(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_first-name]").val(para_name) | |||
| $(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_last-name]").val(para_value) | |||
| } | |||
| break; | |||
| // 数据集pool_id待完成 | |||
| // case (5): | |||
| // $("select[name='pool_id']").val(parameters[i]); | |||
| // break; | |||
| case (6): | |||
| $("input[name='work_server_number']").val(parameters[i]); | |||
| break; | |||
| } | |||
| } | |||
| }) | |||
| $('.ui.save.checkbox').click(function(){ | |||
| $(this).checkbox({ | |||
| onChange: function(){ | |||
| if ($('.ui.save.checkbox').checkbox('is checked')){ | |||
| $('#save_para').removeClass("disabled") | |||
| }else{ | |||
| $('#save_para').addClass("disabled") | |||
| } | |||
| } | |||
| }); | |||
| }) | |||
| $('.question.circle.icon').hover(function(){ | |||
| $(this).popup('show') | |||
| }); | |||
| $(".item.active.parameter_config").click(function(){ | |||
| $('.ui.parameter.modal') | |||
| .modal('setting', 'closable', false) | |||
| .modal('show'); | |||
| }) | |||
| $('.ui.deny.button').click(function(){ | |||
| $('.ui.parameter.modal') | |||
| .modal('hide'); | |||
| }) | |||
| $('select.dropdown') | |||
| .dropdown(); | |||
| function validate(){ | |||
| $('.ui.form') | |||
| .form({ | |||
| on: 'blur', | |||
| fields: { | |||
| boot_file: { | |||
| identifier : 'boot_file', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/.+\.py$/g]', | |||
| } | |||
| ] | |||
| }, | |||
| display_job_name:{ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| attachment:{ | |||
| identifier : 'attachment', | |||
| rules: [ | |||
| { | |||
| type: 'empty', | |||
| } | |||
| ] | |||
| }, | |||
| work_server_number: { | |||
| identifier : 'work_server_number', | |||
| rules: [ | |||
| { | |||
| type : 'integer[1..25]', | |||
| } | |||
| ] | |||
| } | |||
| }, | |||
| onSuccess: function(){ | |||
| // $('.ui.page.dimmer').dimmer('show') | |||
| document.getElementById("mask").style.display = "block" | |||
| }, | |||
| onFailure: function(e){ | |||
| return false; | |||
| } | |||
| }) | |||
| } | |||
| document.onreadystatechange = function() { | |||
| if (document.readyState === "complete") { | |||
| document.getElementById("mask").style.display = "none" | |||
| } | |||
| } | |||
| function send_run_para(){ | |||
| var run_parameters = [] | |||
| var msg = {} | |||
| $(".dynamic.field .two.fields").each(function(){ | |||
| var para_name = $(this).find('input[name=shipping_first-name]').val() | |||
| var para_value = $(this).find('input[name=shipping_last-name]').val() | |||
| run_parameters.push({"label": para_name, "value": para_value}) | |||
| }) | |||
| msg["parameter"] = run_parameters | |||
| msg = JSON.stringify(msg) | |||
| $('#store_run_para').val(msg) | |||
| } | |||
| function get_name(){ | |||
| let name1=$("#engine_name .text").text() | |||
| let name2=$("#flaver_name .text").text() | |||
| $("input#ai_engine_name").val(name1) | |||
| $("input#ai_flaver_name").val(name2) | |||
| } | |||
| $('.ui.create_train_job.green.button').click(function(e) { | |||
| get_name() | |||
| send_run_para() | |||
| validate() | |||
| }) | |||
| </script> | |||
| @@ -0,0 +1,653 @@ | |||
| {{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: 360px; | |||
| 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; | |||
| } | |||
| .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="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" href="{{$.RepoLink}}/modelarts/train-job"> | |||
| {{$.i18n.Tr "repo.modelarts.train_job"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <div class="active section">{{.displayJobName}}</div> | |||
| </div> | |||
| </h4> | |||
| {{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">{{TimeSinceUnix1 .CreatedUnix}}</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="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||
| <a class="item" data-tab="third{{$k}}" onclick="loadModelFile({{.VersionName}},'','','init')">{{$.i18n.Tr "repo.model_download"}}</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.modelarts.train_job.start_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
| </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.modelarts.train_job.resource_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.modelarts.train_job.standard"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{$.resource_spec}} | |||
| </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"> | |||
| 镜像 | |||
| </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.code_version"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.BranchName}} | |||
| </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_file"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.BootFile}} | |||
| </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.train_dataset"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| {{.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.run_parameter"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" title="{{.Parameters}}"> | |||
| {{.Parameters}} | |||
| </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.description"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" title="{{.Description}}"> | |||
| {{.Description}} | |||
| </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: 300px !important; overflow: auto;"> | |||
| <input type="hidden" name="end_line" value> | |||
| <input type="hidden" name="start_line" value> | |||
| <pre id="log_file{{.VersionName}}"></pre> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="ui tab" data-tab="third{{$k}}"> | |||
| <input type="hidden" name="model{{.VersionName}}" value="-1"> | |||
| <input type="hidden" name="modelback{{.VersionName}}" value="-1"> | |||
| <div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'> | |||
| <div class="active section">{{.VersionName}}</div> | |||
| <div class="divider"> / </div> | |||
| </div> | |||
| <div id="dir_list{{.VersionName}}"> | |||
| </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> 删除任务 | |||
| </div> | |||
| <div class="content"> | |||
| <p>你确认删除该任务么?此任务一旦删除不可恢复。</p> | |||
| </div> | |||
| <div class="actions"> | |||
| <div class="ui red basic inverted cancel button"> | |||
| <i class="remove icon"></i> 取消操作 | |||
| </div> | |||
| <div class="ui green basic inverted ok button"> | |||
| <i class="checkmark icon"></i> 确定操作 | |||
| </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 jobID | |||
| let downlaodFlag = {{$.canDownload}} | |||
| let taskID = {{$.task.ID}} | |||
| let realJobName = {{$.task.JobName}} | |||
| $(document).ready(function(){ | |||
| let url = window.location.href; | |||
| let urlArr = url.split('/') | |||
| userName = urlArr.slice(-5)[0] | |||
| repoPath = urlArr.slice(-4)[0] | |||
| jobID = urlArr.slice(-1)[0] | |||
| }) | |||
| function stopBubbling(e) { | |||
| e = window.event || e; | |||
| if (e.stopPropagation) { | |||
| e.stopPropagation(); //阻止事件 冒泡传播 | |||
| } else { | |||
| e.cancelBubble = true; //ie兼容 | |||
| } | |||
| } | |||
| let timeid = window.setInterval(loadJobStatus, 30000); | |||
| $(document).ready(loadJobStatus); | |||
| function loadLog(version_name){ | |||
| document.getElementById("mask").style.display = "block" | |||
| $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}/log?version_name=${version_name}&lines=50&order=asc`, (data) => { | |||
| $('input[name=end_line]').val(data.EndLine) | |||
| $('input[name=start_line]').val(data.StartLine) | |||
| $(`#log_file${version_name}`).text(data.Content) | |||
| document.getElementById("mask").style.display = "none" | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| document.getElementById("mask").style.display = "none" | |||
| }); | |||
| } | |||
| function loadModelFile(version_name,parents,filename,init){ | |||
| parents = parents || '' | |||
| filename = filename || '' | |||
| init = init || '' | |||
| console.log("start") | |||
| $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/train-job/${jobID}/model_list?version_name=${version_name}&parentDir=${parents}`, (data) => { | |||
| $(`#dir_list${version_name}`).empty() | |||
| renderDir(data,version_name) | |||
| if(init==="init"){ | |||
| $(`input[name=model${version_name}]`).val("") | |||
| $(`input[name=modelback${version_name}]`).val(version_name) | |||
| $(`#file_breadcrumb${version_name}`).empty() | |||
| let htmlBread = "" | |||
| htmlBread += `<div class='active section'>${version_name}</div>` | |||
| htmlBread += "<div class='divider'> / </div>" | |||
| $(`#file_breadcrumb${version_name}`).append(htmlBread) | |||
| }else{ | |||
| renderBrend(version_name,parents,filename,init) | |||
| } | |||
| }).fail(function(err) { | |||
| console.log(err,version_name); | |||
| }); | |||
| } | |||
| function renderBrend(version_name,parents,filename,init){ | |||
| if(init=="folder"){ | |||
| let htmlBrend = "" | |||
| let sectionName=$(`#file_breadcrumb${version_name} .active.section`).text() | |||
| let parents1 = $(`input[name=model${version_name}]`).val() | |||
| let filename1 = $(`input[name=modelback${version_name}]`).val() | |||
| if(parents1===""){ | |||
| $(`#file_breadcrumb${version_name} .active.section`).replaceWith(`<a class='section' onclick="loadModelFile('${version_name}','${parents1}','','init')">${sectionName}</a>`) | |||
| }else{ | |||
| $(`#file_breadcrumb${version_name} .active.section`).replaceWith(`<a class='section' onclick="loadModelFile('${version_name}','${parents1}','${filename1}')">${sectionName}</a>`) | |||
| } | |||
| htmlBrend += `<div class='active section'>${filename}</div>` | |||
| htmlBrend += "<div class='divider'> / </div>" | |||
| $(`#file_breadcrumb${version_name}`).append(htmlBrend) | |||
| $(`input[name=model${version_name}]`).val(parents) | |||
| $(`input[name=modelback${version_name}]`).val(filename) | |||
| }else{ | |||
| $(`input[name=model${version_name}]`).val(parents) | |||
| $(`input[name=modelback${version_name}]`).val(filename) | |||
| $(`#file_breadcrumb${version_name} a.section:contains(${filename})`).nextAll().remove() | |||
| $(`#file_breadcrumb${version_name} a.section:contains(${filename})`).replaceWith(`<div class='active section'>${filename}</div>`) | |||
| $(`#file_breadcrumb${version_name} div.section:contains(${filename})`).append("<div class='divider'> / </div>") | |||
| } | |||
| } | |||
| function renderDir(data,version_name){ | |||
| let html="" | |||
| html += "<div class='ui grid' style='margin:0;'>" | |||
| html += "<div class='row' style='padding: 0;'>" | |||
| html += "<div class='ui sixteen wide column' style='padding:1rem;'>" | |||
| html += "<div class='dir list'>" | |||
| html += "<table id='repo-files-table' class='ui single line table pad20'>" | |||
| html += '<tbody>' | |||
| // html += "</tbody>" | |||
| for(let i=0;i<data.Dirs.length;i++){ | |||
| let dirs_size = renderSize(data.Dirs[i].Size) | |||
| html += "<tr>" | |||
| html += "<td class='name six wid'>" | |||
| html += "<span class='truncate'>" | |||
| html += "<span class='octicon octicon-file-directory'>" | |||
| html += "</span>" | |||
| if(data.Dirs[i].IsDir){ | |||
| html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].FileName}','folder')">` | |||
| html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
| }else{ | |||
| if(downlaodFlag){ | |||
| html += `<a href="${location.href}/download_model?version_name=${version_name}&fileName=${data.Dirs[i].FileName}&parentDir=${data.Dirs[i].ParenDir}&jobName=${realJobName}">` | |||
| } | |||
| else{ | |||
| html += `<a class="disabled">` | |||
| } | |||
| html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
| } | |||
| html += '</a>' | |||
| html += "</span>" | |||
| html += "</td>" | |||
| html += "<td class='message seven wide'>" | |||
| if(data.Dirs[i].IsDir){ | |||
| html += "<span class='truncate has-emoji'></span>" | |||
| }else{ | |||
| html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||
| } | |||
| html += "</td>" | |||
| html += "<td class='text right age three wide'>" | |||
| html += "<span class='truncate has-emoji'>" + data.Dirs[i].ModTime + "</span>" | |||
| html += "</td>" | |||
| html += "</tr>" | |||
| } | |||
| html += "</tbody>" | |||
| html += "</table>" | |||
| html += "</div>" | |||
| html += "</div>" | |||
| html += "</div>" | |||
| html += "</div>" | |||
| $(`#dir_list${version_name}`).append(html) | |||
| } | |||
| function renderSize(value){ | |||
| if(null==value||value==''){ | |||
| return "0 Bytes"; | |||
| } | |||
| var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||
| var index=0; | |||
| var srcsize = parseFloat(value); | |||
| index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||
| var size =srcsize/Math.pow(1024,index); | |||
| size=size.toFixed(0);//保留的小数位数 | |||
| return size+unitArr[index]; | |||
| } | |||
| function loadJobStatus() { | |||
| $(".ui.accordion.border-according").each((index, job) => { | |||
| const jobID = job.dataset.jobid; | |||
| const repoPath = job.dataset.repopath; | |||
| const versionname = job.dataset.version | |||
| // ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'] | |||
| // if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
| // || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
| // || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
| // return | |||
| // } | |||
| let status = $(`#${versionname}-status-span`).text() | |||
| if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED','SUCCEEDED'].includes(status)){ | |||
| return | |||
| } | |||
| let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED","SUCCEEDED"] | |||
| $.get(`/api/v1/repos/${repoPath}/cloudbrain/${taskID}?version_name=${versionname}`, (data) => { | |||
| //$(`#${versionname}-duration-span`).text(data.JobDuration) | |||
| $(`#${versionname}-status-span span`).text(data.JobStatus) | |||
| $(`#${versionname}-status-span i`).attr("class",data.JobStatus) | |||
| // detail status and duration | |||
| //$('#'+versionname+'-duration').text(data.JobDuration) | |||
| $('#'+versionname+'-status').text(data.JobStatus) | |||
| if(stopArray.includes(data.JobStatus)){ | |||
| $('#'+versionname+'-stop').addClass('disabled') | |||
| } | |||
| if(data.JobStatus==="COMPLETED"){ | |||
| $('#'+versionname+'-create-model').removeClass('disabled').addClass('blue') | |||
| } | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| }); | |||
| }); | |||
| }; | |||
| function refreshStatus(version_name){ | |||
| $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}?version_name=${versionname}`,(data)=>{ | |||
| // header status and duration | |||
| //$(`#${version_name}-duration-span`).text(data.JobDuration) | |||
| $(`#${version_name}-status-span span`).text(data.JobStatus) | |||
| $(`#${version_name}-status-span i`).attr("class",data.JobStatus) | |||
| // detail status and duration | |||
| //$('#'+version_name+'-duration').text(data.JobDuration) | |||
| $('#'+version_name+'-status').text(data.JobStatus) | |||
| loadLog(version_name) | |||
| }).fail(function(err) { | |||
| console.log(err); | |||
| }); | |||
| stopBubbling(arguments.callee.caller.arguments[0]) | |||
| } | |||
| </script> | |||
| @@ -131,7 +131,7 @@ | |||
| <a style="margin-left:30px;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}" class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a> | |||
| </span> | |||
| </div> | |||
| {{if and (.dataset.Category) (.dataset.Task) (.dataset.License)}} | |||
| {{if or (.dataset.Category) (.dataset.Task) (.dataset.License)}} | |||
| <div class="column thirteen wide"> | |||
| {{if .dataset.Category}} | |||
| {{$category := .dataset.Category}} | |||
| @@ -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> | |||
| @@ -443,7 +443,20 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} {{template "base/paginate" .}} | |||
| {{end}} | |||
| <div id="app" style="margin-top: 2rem;"> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-sizes="[10]" | |||
| :page-size="10" | |||
| layout="total, sizes, prev, pager, next, jumper" | |||
| :total="{{.Page.Paginater.Total}}"> | |||
| </el-pagination> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -186,7 +186,20 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} {{template "base/paginate" .}} | |||
| {{end}} | |||
| <div id="app" style="margin-top: 2rem;"> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-sizes="[10]" | |||
| :page-size="10" | |||
| layout="total, sizes, prev, pager, next, jumper" | |||
| :total="{{.Page.Paginater.Total}}"> | |||
| </el-pagination> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -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}} | |||
| @@ -232,7 +232,13 @@ td, th { | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
| <span style="font-size: 12px;" class=""> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .CreatedUnix}} | |||
| {{end}} | |||
| </span> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -59,21 +59,7 @@ | |||
| {{end}} | |||
| </select> | |||
| </div> | |||
| <<<<<<< HEAD | |||
| {{template "custom/select_dataset" .}} | |||
| ======= | |||
| <div class="inline field"> | |||
| <label>{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
| <input type="text" list="cloudbrain_dataset" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}" name="" id="answerInput" autofocus maxlength="36"> | |||
| <datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment"> | |||
| {{range .attachments}} | |||
| <option name="attachment" data-value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
| {{end}} | |||
| </datalist> | |||
| <input type="hidden" name="attachment" id="answerInput-hidden"> | |||
| </div> | |||
| >>>>>>> V20220328 | |||
| <!--<div class="inline required field"> | |||
| <label>工作环境</label> | |||
| @@ -1,68 +1,442 @@ | |||
| {{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; | |||
| } | |||
| .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.modelarts.train_job.start_time"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class=""> | |||
| {{if not (eq .StartTime 0)}} | |||
| {{TimeSinceUnix1 .StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .CreatedUnix}} | |||
| {{end}} | |||
| </span> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| {{$.i18n.Tr "admin.auths.updated"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="updateTime"> | |||
| {{if not (eq .EndTime 0)}} | |||
| {{TimeSinceUnix1 .EndTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .UpdatedUnix}} | |||
| {{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.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 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.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 "cloudbrain.description"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w" id="model_storage_path"> | |||
| {{.Description}} | |||
| </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> | |||
| @@ -39,8 +39,18 @@ | |||
| </div> | |||
| </div> | |||
| <div class="column right aligned"> | |||
| <div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
| {{svg "octicon-server" 16}} | |||
| <div class="default text" style="color: rgba(0,0,0,.87);"></div> | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu"> | |||
| <div class="item" data-value="all">{{$.i18n.Tr "repo.gpu_type_all"}}</div> | |||
| <div class="item" data-value="CPU/GPU">CPU/GPU</div> | |||
| <div class="item" data-value="NPU">NPU</div> | |||
| </div> | |||
| </div> | |||
| {{if .Permission.CanWrite $.UnitTypeCloudBrain}} | |||
| <a class="ui green button" href="{{.RepoLink}}/modelarts/train-job/create">{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
| <a class="ui green button" href="{{.RepoLink}}/cloudbrain/train-job/create">{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
| {{else}} | |||
| <a class="ui disabled button" >{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
| {{end}} | |||
| @@ -102,7 +112,7 @@ | |||
| <!-- 任务名 --> | |||
| <div class="three wide column padding0"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <a class="title" href='{{if eq .ComputeResource "NPU" }}{{$.Link}}/{{.JobID}}{{else}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{end}}' title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
| <span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
| </a> | |||
| @@ -143,7 +153,7 @@ | |||
| <div class="ui compact buttons"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <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="{{$.RepoRelPath}}/modelarts/train-job" 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='{{$.RepoRelPath}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}' data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
| {{$.i18n.Tr "repo.stop"}} | |||
| </a> | |||
| {{else}} | |||
| @@ -154,7 +164,8 @@ | |||
| </div> | |||
| <!-- 删除任务 --> | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | |||
| <form class="ui compact buttons" id="delForm-{{.JobID}}" action='{{if eq .ComputeResource "NPU" }}{{$.Link}}/{{.JobID}}{{else}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{end}}/del' method="post"> | |||
| <input type="hidden" name="listType" value="{{$.ListType}}"> | |||
| {{$.CsrfTokenHtml}} | |||
| {{if .CanDel}} | |||
| <a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
| @@ -169,7 +180,20 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} {{template "base/paginate" .}} | |||
| {{end}} | |||
| <div id="app" style="margin-top: 2rem;"> | |||
| <div class="center"> | |||
| <el-pagination | |||
| background | |||
| @current-change="handleCurrentChange" | |||
| :current-page="page" | |||
| :page-sizes="[10]" | |||
| :page-size="10" | |||
| layout="total, sizes, prev, pager, next, jumper" | |||
| :total="{{.Page.Paginater.Total}}"> | |||
| </el-pagination> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -206,3 +230,27 @@ | |||
| </div> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| let url = {{$.RepoLink}}; | |||
| let all = {{$.i18n.Tr "repo.gpu_type_all"}} | |||
| $(document).ready(function(){ | |||
| const params = new URLSearchParams(location.search) | |||
| if(!location.search){ | |||
| $('.default.text').text(all) | |||
| }else{ | |||
| if(params.has('listType') && params.get('listType')=='all'){ | |||
| $('.default.text').text(all) | |||
| } | |||
| else{ | |||
| $('.default.text').text(params.get('listType')) | |||
| } | |||
| } | |||
| $('.ui.selection.dropdown').dropdown({ | |||
| onChange:function(value){ | |||
| location.href = `${url}/modelarts/train-job?listType=${value}` | |||
| } | |||
| }) | |||
| }) | |||
| </script> | |||
| @@ -78,6 +78,24 @@ | |||
| <input type="hidden" id="ai_engine_name" name="engine_names" value=""> | |||
| <input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
| <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | |||
| <div class="ui blue mini menu compact selectcloudbrain"> | |||
| <a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
| <path fill="none" d="M0 0h24v24H0z"/> | |||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
| </svg> | |||
| CPU/GPU | |||
| </a> | |||
| <a class="active item" href="{{.RepoLink}}/modelarts/train-job/create"> | |||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
| <path fill="none" d="M0 0h24v24H0z"/> | |||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
| </svg> | |||
| Ascend NPU</a> | |||
| </div> | |||
| </div> | |||
| <div class="required unite min_title inline field"> | |||
| <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
| <input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
| @@ -140,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> | |||
| @@ -395,7 +402,7 @@ | |||
| identifier : 'display_job_name', | |||
| rules: [ | |||
| { | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[^-]$/]', | |||
| type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]', | |||
| } | |||
| ] | |||
| }, | |||
| @@ -223,7 +223,12 @@ td, th { | |||
| </div> | |||
| <div class="ac-display-inblock title_text acc-margin-bottom"> | |||
| <span class="cti-mgRight-sm">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
| <span class="cti-mgRight-sm"> | |||
| {{if not (eq .Cloudbrain.StartTime 0)}} | |||
| {{TimeSinceUnix1 .Cloudbrain.StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .Cloudbrain.CreatedUnix}} | |||
| {{end}}</span> | |||
| <span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span> | |||
| <span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.parent_version"}}:{{.PreVersionName}}</span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
| @@ -293,7 +298,12 @@ td, th { | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
| <span style="font-size: 12px;" class=""> | |||
| {{if not (eq .Cloudbrain.StartTime 0)}} | |||
| {{TimeSinceUnix1 .Cloudbrain.StartTime}} | |||
| {{else}} | |||
| {{TimeSinceUnix1 .Cloudbrain.CreatedUnix}} | |||
| {{end}}</span> | |||
| </div> | |||
| </td> | |||
| </tr> | |||
| @@ -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"> | |||
| @@ -77,13 +77,15 @@ | |||
| {{else if eq .GetOpType 26}} | |||
| {{$.i18n.Tr "action.task_npudebugjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 27}} | |||
| {{$.i18n.Tr "action.task_trainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{$.i18n.Tr "action.task_nputrainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 28}} | |||
| {{$.i18n.Tr "action.task_inferencejob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 29}} | |||
| {{$.i18n.Tr "action.task_benchmark" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{else if eq .GetOpType 30}} | |||
| {{$.i18n.Tr "action.task_createmodel" .GetRepoLink .RefName .RefName | Str2html}} | |||
| {{else if eq .GetOpType 31}} | |||
| {{$.i18n.Tr "action.task_gputrainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
| {{end}} | |||
| </p> | |||
| {{if or (eq .GetOpType 5) (eq .GetOpType 18)}} | |||
| @@ -129,6 +131,8 @@ | |||
| <span class="text grey"><i class="ri-vip-crown-line icon big"></i></span> | |||
| {{else if eq .GetOpType 30}} | |||
| <span class="text grey"><i class="ri-picture-in-picture-exit-line icon big"></i></span> | |||
| {{else if eq .GetOpType 31}} | |||
| <span class="text grey"><i class="ri-character-recognition-line icon big"></i></span> | |||
| {{else}} | |||
| <span class="text grey">{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32}}</span> | |||
| {{end}} | |||
| @@ -150,21 +150,21 @@ | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="isMirror" | |||
| prop="isFork" | |||
| label="派生" | |||
| align="center"> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.isMirror|changeType}} | |||
| </template> | |||
| </el-table-column> | |||
| {{scope.row.isFork|changeType}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="isFork" | |||
| prop="isMirror" | |||
| label="镜像" | |||
| align="center"> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.isFork|changeType}} | |||
| {{scope.row.isMirror|changeType}} | |||
| </template> | |||
| </el-table-column> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="createUnix" | |||
| label="项目创建时间" | |||
| @@ -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); | |||
| @@ -628,6 +628,32 @@ display: block; | |||
| .a_margin{ | |||
| margin: 0px !important; | |||
| } | |||
| /*pages*/ | |||
| .ui.borderless.pagination {border:none} | |||
| .ui.pagination.menu .item { | |||
| min-width: 32px; | |||
| text-align: center; | |||
| height: 32px; | |||
| border-radius: .28571429rem; | |||
| margin: 0 5px; | |||
| background-color: #F2F2F2; | |||
| } | |||
| .ui.pagination.menu>.item:first-child, .ui.pagination.menu .item:last-child { | |||
| background-color: #FFF !important; | |||
| } | |||
| .ui.ui.menu .item.disabled{ | |||
| background-color: #F2F2F2; | |||
| } | |||
| .ui.pagination.menu .active.item { | |||
| background-color: #3291F8; | |||
| color: #FFF; | |||
| } | |||
| .ui.pagination.menu .item>.input { | |||
| margin: 0em .5em; | |||
| width: 3em; | |||
| height: 32px; | |||
| } | |||
| @media only screen and (max-width: 767px) { | |||
| .following.bar #navbar .brand{ | |||
| padding-top: 6px; | |||
| @@ -783,4 +809,170 @@ display: block; | |||
| border: none !important; | |||
| color: #0366d6 !important; | |||
| 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{ | |||
| overflow-x: auto; | |||
| overflow-y: hidden; | |||
| scrollbar-width: none; /* firefox */ | |||
| -ms-overflow-style: none; /* IE 10+ */ | |||
| } | |||
| .seachnav::-webkit-scrollbar { | |||
| display: none; /* Chrome Safari */ | |||
| } | |||
| .ui.green.button, .ui.green.buttons .button{ | |||
| background-color: #5BB973; | |||
| } | |||
| .seach .repos--seach{ | |||
| padding-bottom: 0; | |||
| border-bottom: none; | |||
| } | |||
| .seach .ui.secondary.pointing.menu{ | |||
| border-bottom: none; | |||
| } | |||
| .seach .ui.secondary.pointing.menu .item > i{ | |||
| margin-right: 5px; | |||
| } | |||
| .seach .ui.secondary.pointing.menu .active.item{ | |||
| border-bottom-width: 2px; | |||
| margin: 0 0 -1px; | |||
| } | |||
| .seach .ui.menu .active.item>.label { | |||
| background: #1684FC; | |||
| color: #FFF; | |||
| } | |||
| .seach .ui.menu .item>.label:not(.active.item>.label) { | |||
| background: #e8e8e8; | |||
| color: rgba(0,0,0,.6); | |||
| } | |||
| .highlight{ | |||
| color: red; | |||
| } | |||
| .ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content { | |||
| width: calc(100% - 4.0em); | |||
| margin-left: 0; | |||
| } | |||
| .seach .ui.list .list>.item .header, .seach .ui.list>.item .header{ | |||
| margin-bottom: 0.5em; | |||
| font-size: 1.4rem !important; | |||
| font-weight: normal; | |||
| } | |||
| .seach .time, .seach .time a{ | |||
| font-size: 12px; | |||
| color: grey; | |||
| } | |||
| .seach .list .item.members .ui.avatar.image { | |||
| width: 3.2em; | |||
| height: 3.2em; | |||
| } | |||
| .ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content { | |||
| width: calc(100% - 4.0em); | |||
| margin-left: 0; | |||
| } | |||
| .searchlabel{ | |||
| color: rgba(16, 16, 16, 100); | |||
| font-size: 24px; | |||
| text-align: left; | |||
| font-family: SourceHanSansSC-medium; | |||
| } | |||
| .hiddenSearch{ | |||
| margin: auto; | |||
| display: none; | |||
| } | |||
| #tipmsg { | |||
| display: none; | |||
| z-index: 9999; | |||
| width:150; | |||
| height: 80; | |||
| } | |||