github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/server/service/instances.go (about) 1 package serverService 2 3 import ( 4 "os" 5 "path/filepath" 6 "strconv" 7 "strings" 8 9 "github.com/easysoft/zendata/internal/pkg/domain" 10 "github.com/easysoft/zendata/internal/pkg/service" 11 12 consts "github.com/easysoft/zendata/internal/pkg/const" 13 "github.com/easysoft/zendata/internal/pkg/helper" 14 "github.com/easysoft/zendata/internal/pkg/model" 15 serverRepo "github.com/easysoft/zendata/internal/server/repo" 16 serverUtils "github.com/easysoft/zendata/internal/server/utils" 17 fileUtils "github.com/easysoft/zendata/pkg/utils/file" 18 "github.com/easysoft/zendata/pkg/utils/vari" 19 "gopkg.in/yaml.v3" 20 "gorm.io/gorm" 21 ) 22 23 type InstancesService struct { 24 InstancesRepo *serverRepo.InstancesRepo `inject:""` 25 ReferRepo *serverRepo.ReferRepo `inject:""` 26 ResService *ResService `inject:""` 27 SectionService *SectionService `inject:""` 28 SectionRepo *serverRepo.SectionRepo `inject:""` 29 30 RangeService *service.RangeService `inject:""` 31 } 32 33 func (s *InstancesService) List(keywords string, page int) (list []*model.ZdInstances, total int) { 34 list, total, _ = s.InstancesRepo.List(strings.TrimSpace(keywords), page) 35 return 36 } 37 38 func (s *InstancesService) Get(id int) (instances model.ZdInstances, dirs []domain.Dir) { 39 instances, _ = s.InstancesRepo.Get(uint(id)) 40 41 serverUtils.GetDirs(consts.ResDirYaml, &dirs) 42 43 return 44 } 45 46 func (s *InstancesService) Save(instances *model.ZdInstances) (err error) { 47 instances.Folder = serverUtils.DealWithPathSepRight(instances.Folder) 48 instances.Path = vari.WorkDir + instances.Folder + serverUtils.AddExt(instances.FileName, ".yaml") 49 instances.ReferName = helper.PathToName(instances.Path, consts.ResDirYaml, consts.ResTypeInstances) 50 51 if instances.ID == 0 { 52 err = s.Create(instances) 53 } else { 54 err = s.Update(instances) 55 } 56 s.updateYaml(instances.ID) 57 58 return 59 } 60 func (s *InstancesService) Create(instances *model.ZdInstances) (err error) { 61 err = s.InstancesRepo.Create(instances) 62 63 return 64 } 65 func (s *InstancesService) Update(instances *model.ZdInstances) (err error) { 66 var old model.ZdInstances 67 old, err = s.InstancesRepo.Get(instances.ID) 68 if err == gorm.ErrRecordNotFound { 69 return 70 } 71 if instances.Path != old.Path { 72 fileUtils.RemoveExist(old.Path) 73 } 74 75 err = s.InstancesRepo.Update(instances) 76 77 return 78 } 79 80 func (s *InstancesService) Remove(id int) (err error) { 81 var old model.ZdInstances 82 old, err = s.InstancesRepo.Get(uint(id)) 83 if err == gorm.ErrRecordNotFound { 84 return 85 } 86 87 fileUtils.RemoveExist(old.Path) 88 err = s.InstancesRepo.Remove(uint(id)) 89 return 90 } 91 92 func (s *InstancesService) updateYamlByItem(itemId uint) (err error) { 93 item, _ := s.InstancesRepo.GetItem(itemId) 94 return s.updateYaml(item.InstancesID) 95 } 96 func (s *InstancesService) updateYaml(id uint) (err error) { 97 var po model.ZdInstances 98 po, _ = s.InstancesRepo.Get(id) 99 100 s.genYaml(&po) 101 err = s.InstancesRepo.UpdateYaml(po) 102 fileUtils.WriteFile(po.Path, po.Yaml) 103 104 return 105 } 106 107 func (s *InstancesService) genYaml(instances *model.ZdInstances) (str string) { 108 //records, err := s.InstancesRepo.GetItems(instances.ID) 109 //if err != nil { 110 // return 111 //} 112 // 113 //yamlObj := model.ResInstances{} 114 //s.InstancesRepo.GenInst(*instances, &yamlObj) 115 // 116 //for _, item := range records { 117 // inst := instancesItemToResInstForExport(*item) 118 // 119 // yamlObj.Instances = append(yamlObj.Instances, inst) 120 //} 121 122 root := s.GetItemTree(instances.ID) 123 for _, item := range root.Fields { 124 instances.Instances = append(instances.Instances, *item) 125 } 126 bytes, _ := yaml.Marshal(instances) 127 instances.Yaml = helper.ConvertYamlStringToMapFormat(bytes) 128 129 return 130 } 131 132 func (s *InstancesService) Sync(files []domain.ResFile) { 133 list := s.InstancesRepo.ListAll() 134 135 mp := map[string]*model.ZdInstances{} 136 for _, item := range list { 137 mp[item.Path] = item 138 } 139 140 for _, fi := range files { 141 _, found := mp[fi.Path] 142 if !found { // no record 143 s.SyncToDB(fi) 144 } else if fi.UpdatedAt.Unix() > mp[fi.Path].UpdatedAt.Unix() { // db is old 145 s.InstancesRepo.Remove(mp[fi.Path].ID) 146 s.SyncToDB(fi) 147 } 148 } 149 150 return 151 } 152 153 func (s *InstancesService) SyncToDB(fi domain.ResFile) (err error) { 154 content, _ := os.ReadFile(fi.Path) 155 yamlContent := helper.ReplaceSpecialChars(content) 156 po := model.ZdInstances{} 157 err = yaml.Unmarshal(yamlContent, &po) 158 159 po.Title = fi.Title 160 po.Desc = fi.Desc 161 po.Path = fi.Path 162 po.Folder = serverUtils.GetRelativePath(po.Path) 163 if strings.Index(po.Path, consts.ResDirYaml) > -1 { 164 po.ReferName = helper.PathToName(po.Path, consts.ResDirYaml, consts.ResTypeInstances) 165 } else { 166 po.ReferName = helper.PathToName(po.Path, consts.ResDirUsers, consts.ResTypeInstances) 167 } 168 po.FileName = fileUtils.GetFileName(po.Path) 169 po.Yaml = string(content) 170 171 s.InstancesRepo.Create(&po) 172 173 for i, item := range po.Instances { 174 item.Ord = i + 1 175 s.saveItemToDB(&item, po, fi.Path, 0, po.ID) 176 } 177 178 return 179 } 180 func (s *InstancesService) saveItemToDB(item *model.ZdInstancesItem, instances model.ZdInstances, currPath string, parentID, instancesID uint) { 181 if item.Froms != nil && len(item.Froms) > 0 { 182 for idx, from := range item.Froms { 183 if from.Field == "" { 184 from.Field = "from" + strconv.Itoa(idx+1) 185 } 186 s.saveItemToDB(from, instances, currPath, parentID, instancesID) 187 } 188 189 return 190 } 191 192 // update field 193 if item.Instance != "" { // instance node 194 item.Field = item.Instance 195 } 196 197 item.InstancesID = instancesID 198 item.ParentID = parentID 199 if item.From == "" && instances.From != "" { 200 item.From = instances.From 201 } 202 if item.Type == "" { 203 item.Type = consts.FieldTypeList 204 } 205 if item.Mode == "" { 206 item.Mode = consts.ModeParallel 207 } 208 item.Range = strings.TrimSpace(item.Range) 209 210 // save item 211 s.InstancesRepo.SaveItem(item) 212 213 // create refer 214 refer := model.ZdRefer{OwnerType: "instances", OwnerID: item.ID} 215 216 needToCreateSections := false 217 if item.Select != "" { // refer to excel 218 refer.Type = consts.ResTypeExcel 219 220 refer.ColName = item.Select 221 refer.Condition = item.Where 222 refer.Rand = item.Rand 223 224 _, sheet := fileUtils.ConvertResExcelPath(item.From, currPath) 225 refer.File = item.From 226 refer.Sheet = sheet 227 228 } else if item.Use != "" { // refer to ranges or instances, need to read yaml to get the type 229 rangeSections := s.RangeService.ParseRangeProperty(item.Use) 230 if len(rangeSections) > 0 { // only get the first one 231 rangeSection := rangeSections[0] 232 desc, _, count, countTag := s.RangeService.ParseRangeSection(rangeSection) // medium{2} 233 refer.ColName = desc 234 refer.Count = count 235 refer.CountTag = countTag 236 } 237 238 path := fileUtils.ConvertReferRangeToPath(item.From, currPath) 239 _, _, refer.Type = helper.ReadYamlInfo(path) 240 refer.File = item.From 241 242 } else if item.Config != "" { // refer to config 243 refer.Type = consts.ResTypeConfig 244 245 rangeSections := s.RangeService.ParseRangeProperty(item.Config) // dir/config.yaml 246 if len(rangeSections) > 0 { // only get the first one 247 rangeSection := rangeSections[0] 248 desc, _, count, countTag := s.RangeService.ParseRangeSection(rangeSection) 249 refer.Count = count 250 refer.CountTag = countTag 251 252 path := fileUtils.ConvertReferRangeToPath(desc, currPath) 253 refer.File = GetRelatedPathWithResDir(path) 254 } 255 256 } else if item.Range != "" { // deal with yaml and text refer using range prop 257 258 rangeSections := s.RangeService.ParseRangeProperty(item.Range) 259 if len(rangeSections) > 0 { // only get the first one 260 rangeSection := rangeSections[0] 261 desc, step, count, countTag := s.RangeService.ParseRangeSection(rangeSection) // dir/users.txt:R{3} 262 if filepath.Ext(desc) == ".txt" || filepath.Ext(desc) == ".yaml" { 263 if filepath.Ext(desc) == ".txt" { // dir/users.txt:2 264 refer.Type = consts.ResTypeText 265 266 if strings.ToLower(step) == "r" { 267 refer.Rand = true 268 } else { 269 refer.Step, _ = strconv.Atoi(step) 270 } 271 272 } else if filepath.Ext(desc) == ".yaml" { // dir/content.yaml{3} 273 refer.Type = consts.ResTypeYaml 274 275 refer.Count = count 276 refer.CountTag = countTag 277 } 278 279 path := fileUtils.ConvertReferRangeToPath(desc, currPath) 280 refer.File = GetRelatedPathWithResDir(path) 281 } else { // like 1-9,a-z 282 needToCreateSections = true 283 } 284 } 285 } 286 287 // save refer 288 refer.OwnerID = item.ID 289 s.ReferRepo.Save(&refer) 290 291 // gen sections if needed 292 if needToCreateSections { 293 rangeSections := s.RangeService.ParseRangeProperty(item.Range) 294 295 for i, rangeSection := range rangeSections { 296 s.SectionService.SaveFieldSectionToDB(rangeSection, i, item.ID, "instances") 297 } 298 } 299 300 // deal with field's children 301 for i, child := range item.Fields { 302 child.Ord = i + 1 303 s.saveItemToDB(child, instances, currPath, item.ID, instancesID) 304 } 305 } 306 307 func NewInstancesService(instancesRepo *serverRepo.InstancesRepo, referRepo *serverRepo.ReferRepo, 308 sectionRepo *serverRepo.SectionRepo) *InstancesService { 309 return &InstancesService{InstancesRepo: instancesRepo, ReferRepo: referRepo, SectionRepo: sectionRepo} 310 }