attribute_view.go 92 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534
  1. // SiYuan - Refactor your thinking
  2. // Copyright (c) 2020-present, b3log.org
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. package model
  17. import (
  18. "bytes"
  19. "fmt"
  20. "os"
  21. "path/filepath"
  22. "slices"
  23. "sort"
  24. "strconv"
  25. "strings"
  26. "time"
  27. "github.com/88250/gulu"
  28. "github.com/88250/lute/ast"
  29. "github.com/88250/lute/parse"
  30. "github.com/jinzhu/copier"
  31. "github.com/siyuan-note/dejavu/entity"
  32. "github.com/siyuan-note/filelock"
  33. "github.com/siyuan-note/logging"
  34. "github.com/siyuan-note/siyuan/kernel/av"
  35. "github.com/siyuan-note/siyuan/kernel/cache"
  36. "github.com/siyuan-note/siyuan/kernel/filesys"
  37. "github.com/siyuan-note/siyuan/kernel/sql"
  38. "github.com/siyuan-note/siyuan/kernel/treenode"
  39. "github.com/siyuan-note/siyuan/kernel/util"
  40. "github.com/xrash/smetrics"
  41. )
  42. func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*av.Value) (err error) {
  43. attrView, err := av.ParseAttributeView(avID)
  44. if nil != err {
  45. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  46. return
  47. }
  48. now := util.CurrentTimeMillis()
  49. var blockIDs []string
  50. for _, blockValues := range blocksValues {
  51. blockID := ast.NewNodeID()
  52. blockIDs = append(blockIDs, blockID)
  53. for _, v := range blockValues {
  54. keyValues, _ := attrView.GetKeyValues(v.KeyID)
  55. if nil == keyValues {
  56. err = fmt.Errorf("key [%s] not found", v.KeyID)
  57. return
  58. }
  59. v.ID = ast.NewNodeID()
  60. v.BlockID = blockID
  61. v.Type = keyValues.Key.Type
  62. if av.KeyTypeBlock == v.Type {
  63. v.Block.ID = blockID
  64. v.Block.Created = now
  65. v.Block.Updated = now
  66. }
  67. v.IsDetached = true
  68. v.CreatedAt = now
  69. v.UpdatedAt = now
  70. keyValues.Values = append(keyValues.Values, v)
  71. }
  72. }
  73. for _, v := range attrView.Views {
  74. switch v.LayoutType {
  75. case av.LayoutTypeTable:
  76. for _, addingBlockID := range blockIDs {
  77. v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
  78. }
  79. }
  80. }
  81. if err = av.SaveAttributeView(attrView); nil != err {
  82. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  83. return
  84. }
  85. util.PushReloadAttrView(avID)
  86. return
  87. }
  88. func DuplicateDatabaseBlock(avID string) (newAvID, newBlockID string, err error) {
  89. storageAvDir := filepath.Join(util.DataDir, "storage", "av")
  90. oldAvPath := filepath.Join(storageAvDir, avID+".json")
  91. newAvID, newBlockID = ast.NewNodeID(), ast.NewNodeID()
  92. oldAv, err := av.ParseAttributeView(avID)
  93. if nil != err {
  94. return
  95. }
  96. data, err := filelock.ReadFile(oldAvPath)
  97. if nil != err {
  98. logging.LogErrorf("read attribute view [%s] failed: %s", avID, err)
  99. return
  100. }
  101. data = bytes.ReplaceAll(data, []byte(avID), []byte(newAvID))
  102. av.UpsertBlockRel(newAvID, newBlockID)
  103. newAv := &av.AttributeView{}
  104. if err = gulu.JSON.UnmarshalJSON(data, newAv); nil != err {
  105. logging.LogErrorf("unmarshal attribute view [%s] failed: %s", newAvID, err)
  106. return
  107. }
  108. newAv.Name = oldAv.Name + " (Duplicated " + time.Now().Format("2006-01-02 15:04:05") + ")"
  109. for _, keyValues := range newAv.KeyValues {
  110. if nil != keyValues.Key.Relation && keyValues.Key.Relation.IsTwoWay {
  111. // 断开双向关联
  112. keyValues.Key.Relation.IsTwoWay = false
  113. keyValues.Key.Relation.BackKeyID = ""
  114. }
  115. }
  116. data, err = gulu.JSON.MarshalJSON(newAv)
  117. if nil != err {
  118. logging.LogErrorf("marshal attribute view [%s] failed: %s", newAvID, err)
  119. return
  120. }
  121. newAvPath := filepath.Join(storageAvDir, newAvID+".json")
  122. if err = filelock.WriteFile(newAvPath, data); nil != err {
  123. logging.LogErrorf("write attribute view [%s] failed: %s", newAvID, err)
  124. return
  125. }
  126. updateBoundBlockAvsAttribute([]string{newAvID})
  127. return
  128. }
  129. func GetAttributeViewKeysByAvID(avID string) (ret []*av.Key) {
  130. ret = []*av.Key{}
  131. attrView, err := av.ParseAttributeView(avID)
  132. if nil != err {
  133. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  134. return
  135. }
  136. for _, keyValues := range attrView.KeyValues {
  137. key := keyValues.Key
  138. ret = append(ret, key)
  139. }
  140. return ret
  141. }
  142. func SetDatabaseBlockView(blockID, viewID string) (err error) {
  143. node, tree, err := getNodeByBlockID(nil, blockID)
  144. if nil != err {
  145. return
  146. }
  147. attrs := parse.IAL2Map(node.KramdownIAL)
  148. attrs[av.NodeAttrView] = viewID
  149. err = setNodeAttrs(node, tree, attrs)
  150. if nil != err {
  151. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  152. return
  153. }
  154. return
  155. }
  156. func GetAttributeViewPrimaryKeyValues(avID, keyword string, page, pageSize int) (attributeViewName string, databaseBlockIDs []string, keyValues *av.KeyValues, err error) {
  157. waitForSyncingStorages()
  158. attrView, err := av.ParseAttributeView(avID)
  159. if nil != err {
  160. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  161. return
  162. }
  163. attributeViewName = getAttrViewName(attrView)
  164. databaseBlockIDs = treenode.GetMirrorAttrViewBlockIDs(avID)
  165. keyValues = attrView.GetBlockKeyValues()
  166. // 过滤掉不在视图中的值
  167. tmp := map[string]*av.Value{}
  168. for _, kv := range keyValues.Values {
  169. for _, view := range attrView.Views {
  170. switch view.LayoutType {
  171. case av.LayoutTypeTable:
  172. if !kv.IsDetached {
  173. if nil == treenode.GetBlockTree(kv.BlockID) {
  174. break
  175. }
  176. }
  177. tmp[kv.Block.ID] = kv
  178. }
  179. }
  180. }
  181. keyValues.Values = []*av.Value{}
  182. for _, v := range tmp {
  183. if strings.Contains(strings.ToLower(v.String(true)), strings.ToLower(keyword)) {
  184. keyValues.Values = append(keyValues.Values, v)
  185. }
  186. }
  187. if 1 > pageSize {
  188. pageSize = 16
  189. }
  190. start := (page - 1) * pageSize
  191. end := start + pageSize
  192. if len(keyValues.Values) < end {
  193. end = len(keyValues.Values)
  194. }
  195. keyValues.Values = keyValues.Values[start:end]
  196. sort.Slice(keyValues.Values, func(i, j int) bool {
  197. return keyValues.Values[i].Block.Updated > keyValues.Values[j].Block.Updated
  198. })
  199. return
  200. }
  201. func GetAttributeViewFilterSort(avID, blockID string) (filters []*av.ViewFilter, sorts []*av.ViewSort) {
  202. waitForSyncingStorages()
  203. attrView, err := av.ParseAttributeView(avID)
  204. if nil != err {
  205. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  206. return
  207. }
  208. view, err := getAttrViewViewByBlockID(attrView, blockID)
  209. if nil == view {
  210. view, err = attrView.GetCurrentView(attrView.ViewID)
  211. if nil != err {
  212. logging.LogErrorf("get current view failed: %s", err)
  213. return
  214. }
  215. }
  216. filters = []*av.ViewFilter{}
  217. sorts = []*av.ViewSort{}
  218. switch view.LayoutType {
  219. case av.LayoutTypeTable:
  220. filters = view.Table.Filters
  221. sorts = view.Table.Sorts
  222. }
  223. return
  224. }
  225. func SearchAttributeViewNonRelationKey(avID, keyword string) (ret []*av.Key) {
  226. waitForSyncingStorages()
  227. ret = []*av.Key{}
  228. attrView, err := av.ParseAttributeView(avID)
  229. if nil != err {
  230. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  231. return
  232. }
  233. for _, keyValues := range attrView.KeyValues {
  234. if av.KeyTypeRelation != keyValues.Key.Type && av.KeyTypeRollup != keyValues.Key.Type && av.KeyTypeTemplate != keyValues.Key.Type && av.KeyTypeCreated != keyValues.Key.Type && av.KeyTypeUpdated != keyValues.Key.Type && av.KeyTypeLineNumber != keyValues.Key.Type {
  235. if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) {
  236. ret = append(ret, keyValues.Key)
  237. }
  238. }
  239. }
  240. return
  241. }
  242. func SearchAttributeViewRelationKey(avID, keyword string) (ret []*av.Key) {
  243. waitForSyncingStorages()
  244. ret = []*av.Key{}
  245. attrView, err := av.ParseAttributeView(avID)
  246. if nil != err {
  247. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  248. return
  249. }
  250. for _, keyValues := range attrView.KeyValues {
  251. if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation {
  252. if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) {
  253. ret = append(ret, keyValues.Key)
  254. }
  255. }
  256. }
  257. return
  258. }
  259. func GetAttributeView(avID string) (ret *av.AttributeView) {
  260. waitForSyncingStorages()
  261. ret, _ = av.ParseAttributeView(avID)
  262. return
  263. }
  264. type SearchAttributeViewResult struct {
  265. AvID string `json:"avID"`
  266. AvName string `json:"avName"`
  267. BlockID string `json:"blockID"`
  268. HPath string `json:"hPath"`
  269. }
  270. func SearchAttributeView(keyword string, excludeAvIDs []string) (ret []*SearchAttributeViewResult) {
  271. waitForSyncingStorages()
  272. ret = []*SearchAttributeViewResult{}
  273. keyword = strings.TrimSpace(keyword)
  274. keywords := strings.Fields(keyword)
  275. type result struct {
  276. AvID string
  277. AvName string
  278. AvUpdated int64
  279. Score float64
  280. }
  281. var avs []*result
  282. avDir := filepath.Join(util.DataDir, "storage", "av")
  283. entries, err := os.ReadDir(avDir)
  284. if nil != err {
  285. logging.LogErrorf("read directory [%s] failed: %s", avDir, err)
  286. return
  287. }
  288. avBlockRels := av.GetBlockRels()
  289. for _, entry := range entries {
  290. if entry.IsDir() {
  291. continue
  292. }
  293. id := strings.TrimSuffix(entry.Name(), ".json")
  294. if !ast.IsNodeIDPattern(id) {
  295. continue
  296. }
  297. if nil == avBlockRels[id] {
  298. continue
  299. }
  300. name, _ := av.GetAttributeViewNameByPath(filepath.Join(avDir, entry.Name()))
  301. info, _ := entry.Info()
  302. if "" != keyword {
  303. score := 0.0
  304. hit := false
  305. for _, k := range keywords {
  306. if strings.Contains(strings.ToLower(name), strings.ToLower(k)) {
  307. score += smetrics.JaroWinkler(name, k, 0.7, 4)
  308. hit = true
  309. } else {
  310. hit = false
  311. break
  312. }
  313. }
  314. if hit {
  315. a := &result{AvID: id, AvName: name, Score: score}
  316. if nil != info && !info.ModTime().IsZero() {
  317. a.AvUpdated = info.ModTime().UnixMilli()
  318. }
  319. avs = append(avs, a)
  320. }
  321. } else {
  322. a := &result{AvID: id, AvName: name}
  323. if nil != info && !info.ModTime().IsZero() {
  324. a.AvUpdated = info.ModTime().UnixMilli()
  325. }
  326. avs = append(avs, a)
  327. }
  328. }
  329. if "" == keyword {
  330. sort.Slice(avs, func(i, j int) bool { return avs[i].AvUpdated > avs[j].AvUpdated })
  331. } else {
  332. sort.SliceStable(avs, func(i, j int) bool {
  333. if avs[i].Score == avs[j].Score {
  334. return avs[i].AvUpdated > avs[j].AvUpdated
  335. }
  336. return avs[i].Score > avs[j].Score
  337. })
  338. }
  339. if 12 <= len(avs) {
  340. avs = avs[:12]
  341. }
  342. var avIDs []string
  343. for _, a := range avs {
  344. avIDs = append(avIDs, a.AvID)
  345. }
  346. avBlocks := treenode.BatchGetMirrorAttrViewBlocks(avIDs)
  347. var blockIDs []string
  348. for _, avBlock := range avBlocks {
  349. blockIDs = append(blockIDs, avBlock.BlockIDs...)
  350. }
  351. blockIDs = gulu.Str.RemoveDuplicatedElem(blockIDs)
  352. trees := map[string]*parse.Tree{}
  353. for _, blockID := range blockIDs {
  354. bt := treenode.GetBlockTree(blockID)
  355. if nil == bt {
  356. continue
  357. }
  358. tree := trees[bt.RootID]
  359. if nil == tree {
  360. tree, _ = LoadTreeByBlockID(blockID)
  361. if nil != tree {
  362. trees[bt.RootID] = tree
  363. }
  364. }
  365. if nil == tree {
  366. continue
  367. }
  368. node := treenode.GetNodeInTree(tree, blockID)
  369. if nil == node {
  370. continue
  371. }
  372. if "" == node.AttributeViewID {
  373. continue
  374. }
  375. avID := node.AttributeViewID
  376. var existAv *result
  377. for _, av := range avs {
  378. if av.AvID == avID {
  379. existAv = av
  380. break
  381. }
  382. }
  383. if nil == existAv {
  384. continue
  385. }
  386. exist := false
  387. for _, result := range ret {
  388. if result.AvID == avID {
  389. exist = true
  390. break
  391. }
  392. }
  393. if exist {
  394. continue
  395. }
  396. var hPath string
  397. baseBlock := treenode.GetBlockTreeRootByPath(node.Box, node.Path)
  398. if nil != baseBlock {
  399. hPath = baseBlock.HPath
  400. }
  401. box := Conf.Box(node.Box)
  402. if nil != box {
  403. hPath = box.Name + hPath
  404. }
  405. if !gulu.Str.Contains(avID, excludeAvIDs) {
  406. ret = append(ret, &SearchAttributeViewResult{
  407. AvID: avID,
  408. AvName: existAv.AvName,
  409. BlockID: blockID,
  410. HPath: hPath,
  411. })
  412. }
  413. }
  414. return
  415. }
  416. type BlockAttributeViewKeys struct {
  417. AvID string `json:"avID"`
  418. AvName string `json:"avName"`
  419. BlockIDs []string `json:"blockIDs"`
  420. KeyValues []*av.KeyValues `json:"keyValues"`
  421. }
  422. func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
  423. waitForSyncingStorages()
  424. ret = []*BlockAttributeViewKeys{}
  425. attrs := GetBlockAttrsWithoutWaitWriting(blockID)
  426. avs := attrs[av.NodeAttrNameAvs]
  427. if "" == avs {
  428. return
  429. }
  430. avIDs := strings.Split(avs, ",")
  431. for _, avID := range avIDs {
  432. attrView, err := av.ParseAttributeView(avID)
  433. if nil != err {
  434. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  435. unbindBlockAv(nil, avID, blockID)
  436. return
  437. }
  438. if 1 > len(attrView.Views) {
  439. err = av.ErrViewNotFound
  440. unbindBlockAv(nil, avID, blockID)
  441. return
  442. }
  443. if !attrView.ExistBlock(blockID) {
  444. // 比如剪切后粘贴,块 ID 会变,但是属性还在块上,这里做一次数据订正
  445. // Auto verify the database name when clicking the block superscript icon https://github.com/siyuan-note/siyuan/issues/10861
  446. unbindBlockAv(nil, avID, blockID)
  447. return
  448. }
  449. var keyValues []*av.KeyValues
  450. for _, kv := range attrView.KeyValues {
  451. if av.KeyTypeLineNumber == kv.Key.Type {
  452. // 属性面板中不显示行号字段
  453. // The line number field no longer appears in the database attribute panel https://github.com/siyuan-note/siyuan/issues/11319
  454. continue
  455. }
  456. kValues := &av.KeyValues{Key: kv.Key}
  457. for _, v := range kv.Values {
  458. if v.BlockID == blockID {
  459. kValues.Values = append(kValues.Values, v)
  460. }
  461. }
  462. switch kValues.Key.Type {
  463. case av.KeyTypeRollup:
  464. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeRollup, Rollup: &av.ValueRollup{Contents: []*av.Value{}}})
  465. case av.KeyTypeTemplate:
  466. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: ""}})
  467. case av.KeyTypeCreated:
  468. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeCreated})
  469. case av.KeyTypeUpdated:
  470. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeUpdated})
  471. }
  472. if 0 < len(kValues.Values) {
  473. keyValues = append(keyValues, kValues)
  474. } else {
  475. // 如果没有值,那么就补一个默认值
  476. kValues.Values = append(kValues.Values, av.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.ID, blockID, kv.Key.Type))
  477. keyValues = append(keyValues, kValues)
  478. }
  479. }
  480. // 渲染自动生成的列值,比如模板列、关联列、汇总列、创建时间列和更新时间列
  481. // 先处理关联列、汇总列、创建时间列和更新时间列
  482. for _, kv := range keyValues {
  483. switch kv.Key.Type {
  484. case av.KeyTypeRollup:
  485. if nil == kv.Key.Rollup {
  486. break
  487. }
  488. relKey, _ := attrView.GetKey(kv.Key.Rollup.RelationKeyID)
  489. if nil == relKey {
  490. break
  491. }
  492. relVal := attrView.GetValue(kv.Key.Rollup.RelationKeyID, kv.Values[0].BlockID)
  493. if nil != relVal && nil != relVal.Relation {
  494. destAv, _ := av.ParseAttributeView(relKey.Relation.AvID)
  495. destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID)
  496. if nil != destAv && nil != destKey {
  497. for _, bID := range relVal.Relation.BlockIDs {
  498. destVal := destAv.GetValue(kv.Key.Rollup.KeyID, bID)
  499. if nil == destVal {
  500. if destAv.ExistBlock(bID) { // 数据库中存在行但是列值不存在是数据未初始化,这里补一个默认值
  501. destVal = av.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.Rollup.KeyID, bID, destKey.Type)
  502. }
  503. if nil == destVal {
  504. continue
  505. }
  506. }
  507. if av.KeyTypeNumber == destKey.Type {
  508. destVal.Number.Format = destKey.NumberFormat
  509. destVal.Number.FormatNumber()
  510. }
  511. kv.Values[0].Rollup.Contents = append(kv.Values[0].Rollup.Contents, destVal.Clone())
  512. }
  513. kv.Values[0].Rollup.RenderContents(kv.Key.Rollup.Calc, destKey)
  514. }
  515. }
  516. case av.KeyTypeRelation:
  517. if nil == kv.Key.Relation {
  518. break
  519. }
  520. destAv, _ := av.ParseAttributeView(kv.Key.Relation.AvID)
  521. if nil == destAv {
  522. break
  523. }
  524. blocks := map[string]*av.Value{}
  525. for _, blockValue := range destAv.GetBlockKeyValues().Values {
  526. blocks[blockValue.BlockID] = blockValue
  527. }
  528. kv.Values[0].Relation.Contents = nil // 先清空 https://github.com/siyuan-note/siyuan/issues/10670
  529. for _, bID := range kv.Values[0].Relation.BlockIDs {
  530. kv.Values[0].Relation.Contents = append(kv.Values[0].Relation.Contents, blocks[bID])
  531. }
  532. case av.KeyTypeCreated:
  533. createdStr := blockID[:len("20060102150405")]
  534. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  535. if nil == parseErr {
  536. kv.Values[0].Created = av.NewFormattedValueCreated(created.UnixMilli(), 0, av.CreatedFormatNone)
  537. kv.Values[0].Created.IsNotEmpty = true
  538. } else {
  539. logging.LogWarnf("parse created [%s] failed: %s", createdStr, parseErr)
  540. kv.Values[0].Created = av.NewFormattedValueCreated(time.Now().UnixMilli(), 0, av.CreatedFormatNone)
  541. }
  542. case av.KeyTypeUpdated:
  543. ial := GetBlockAttrsWithoutWaitWriting(blockID)
  544. updatedStr := ial["updated"]
  545. updated, parseErr := time.ParseInLocation("20060102150405", updatedStr, time.Local)
  546. if nil == parseErr {
  547. kv.Values[0].Updated = av.NewFormattedValueUpdated(updated.UnixMilli(), 0, av.UpdatedFormatNone)
  548. kv.Values[0].Updated.IsNotEmpty = true
  549. } else {
  550. logging.LogWarnf("parse updated [%s] failed: %s", updatedStr, parseErr)
  551. kv.Values[0].Updated = av.NewFormattedValueUpdated(time.Now().UnixMilli(), 0, av.UpdatedFormatNone)
  552. }
  553. }
  554. }
  555. // 再处理模板列
  556. // 渲染模板
  557. var renderTemplateErr error
  558. for _, kv := range keyValues {
  559. switch kv.Key.Type {
  560. case av.KeyTypeTemplate:
  561. if 0 < len(kv.Values) {
  562. ial := map[string]string{}
  563. block := av.GetKeyBlockValue(keyValues)
  564. if nil != block && !block.IsDetached {
  565. ial = GetBlockAttrsWithoutWaitWriting(block.BlockID)
  566. }
  567. if nil == kv.Values[0].Template {
  568. kv.Values[0] = av.GetAttributeViewDefaultValue(kv.Values[0].ID, kv.Key.ID, blockID, kv.Key.Type)
  569. }
  570. var renderErr error
  571. kv.Values[0].Template.Content, renderErr = sql.RenderTemplateCol(ial, keyValues, kv.Key.Template)
  572. if nil != renderErr {
  573. renderTemplateErr = fmt.Errorf("database [%s] template field [%s] rendering failed: %s", getAttrViewName(attrView), kv.Key.Name, renderErr)
  574. }
  575. }
  576. }
  577. }
  578. if nil != renderTemplateErr {
  579. util.PushErrMsg(fmt.Sprintf(Conf.Language(44), util.EscapeHTML(renderTemplateErr.Error())), 30000)
  580. }
  581. // 字段排序
  582. refreshAttrViewKeyIDs(attrView)
  583. sorts := map[string]int{}
  584. for i, k := range attrView.KeyIDs {
  585. sorts[k] = i
  586. }
  587. sort.Slice(keyValues, func(i, j int) bool {
  588. return sorts[keyValues[i].Key.ID] < sorts[keyValues[j].Key.ID]
  589. })
  590. blockIDs := treenode.GetMirrorAttrViewBlockIDs(avID)
  591. if 1 > len(blockIDs) {
  592. // 老数据兼容处理
  593. avBts := treenode.GetBlockTreesByType("av")
  594. for _, avBt := range avBts {
  595. if nil == avBt {
  596. continue
  597. }
  598. tree, _ := LoadTreeByBlockID(avBt.ID)
  599. if nil == tree {
  600. continue
  601. }
  602. node := treenode.GetNodeInTree(tree, avBt.ID)
  603. if nil == node {
  604. continue
  605. }
  606. if avID == node.AttributeViewID {
  607. blockIDs = append(blockIDs, avBt.ID)
  608. }
  609. }
  610. if 1 > len(blockIDs) {
  611. tree, _ := LoadTreeByBlockID(blockID)
  612. if nil != tree {
  613. node := treenode.GetNodeInTree(tree, blockID)
  614. if nil != node {
  615. if removeErr := removeNodeAvID(node, avID, nil, tree); nil != removeErr {
  616. logging.LogErrorf("remove node avID [%s] failed: %s", avID, removeErr)
  617. }
  618. }
  619. }
  620. continue
  621. }
  622. blockIDs = gulu.Str.RemoveDuplicatedElem(blockIDs)
  623. for _, blockID := range blockIDs {
  624. av.UpsertBlockRel(avID, blockID)
  625. }
  626. }
  627. ret = append(ret, &BlockAttributeViewKeys{
  628. AvID: avID,
  629. AvName: getAttrViewName(attrView),
  630. BlockIDs: blockIDs,
  631. KeyValues: keyValues,
  632. })
  633. }
  634. return
  635. }
  636. func RenderRepoSnapshotAttributeView(indexID, avID string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  637. repo, err := newRepository()
  638. if nil != err {
  639. return
  640. }
  641. index, err := repo.GetIndex(indexID)
  642. if nil != err {
  643. return
  644. }
  645. files, err := repo.GetFiles(index)
  646. if nil != err {
  647. return
  648. }
  649. var avFile *entity.File
  650. for _, f := range files {
  651. if "/storage/av/"+avID+".json" == f.Path {
  652. avFile = f
  653. break
  654. }
  655. }
  656. if nil == avFile {
  657. attrView = av.NewAttributeView(avID)
  658. } else {
  659. data, readErr := repo.OpenFile(avFile)
  660. if nil != readErr {
  661. logging.LogErrorf("read attribute view [%s] failed: %s", avID, readErr)
  662. return
  663. }
  664. attrView = &av.AttributeView{}
  665. if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err {
  666. logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
  667. return
  668. }
  669. }
  670. viewable, err = renderAttributeView(attrView, "", "", 1, -1)
  671. return
  672. }
  673. func RenderHistoryAttributeView(avID, created string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  674. createdUnix, parseErr := strconv.ParseInt(created, 10, 64)
  675. if nil != parseErr {
  676. logging.LogErrorf("parse created [%s] failed: %s", created, parseErr)
  677. return
  678. }
  679. dirPrefix := time.Unix(createdUnix, 0).Format("2006-01-02-150405")
  680. globPath := filepath.Join(util.HistoryDir, dirPrefix+"*")
  681. matches, err := filepath.Glob(globPath)
  682. if nil != err {
  683. logging.LogErrorf("glob [%s] failed: %s", globPath, err)
  684. return
  685. }
  686. if 1 > len(matches) {
  687. return
  688. }
  689. historyDir := matches[0]
  690. avJSONPath := filepath.Join(historyDir, "storage", "av", avID+".json")
  691. if !gulu.File.IsExist(avJSONPath) {
  692. avJSONPath = filepath.Join(util.DataDir, "storage", "av", avID+".json")
  693. }
  694. if !gulu.File.IsExist(avJSONPath) {
  695. attrView = av.NewAttributeView(avID)
  696. } else {
  697. data, readErr := os.ReadFile(avJSONPath)
  698. if nil != readErr {
  699. logging.LogErrorf("read attribute view [%s] failed: %s", avID, readErr)
  700. return
  701. }
  702. attrView = &av.AttributeView{}
  703. if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err {
  704. logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
  705. return
  706. }
  707. }
  708. viewable, err = renderAttributeView(attrView, "", "", 1, -1)
  709. return
  710. }
  711. func RenderAttributeView(avID, viewID, query string, page, pageSize int) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  712. waitForSyncingStorages()
  713. if avJSONPath := av.GetAttributeViewDataPath(avID); !filelock.IsExist(avJSONPath) {
  714. attrView = av.NewAttributeView(avID)
  715. if err = av.SaveAttributeView(attrView); nil != err {
  716. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  717. return
  718. }
  719. }
  720. attrView, err = av.ParseAttributeView(avID)
  721. if nil != err {
  722. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  723. return
  724. }
  725. viewable, err = renderAttributeView(attrView, viewID, query, page, pageSize)
  726. return
  727. }
  728. func renderAttributeView(attrView *av.AttributeView, viewID, query string, page, pageSize int) (viewable av.Viewable, err error) {
  729. if 1 > len(attrView.Views) {
  730. view, _, _ := av.NewTableViewWithBlockKey(ast.NewNodeID())
  731. attrView.Views = append(attrView.Views, view)
  732. attrView.ViewID = view.ID
  733. if err = av.SaveAttributeView(attrView); nil != err {
  734. logging.LogErrorf("save attribute view [%s] failed: %s", attrView.ID, err)
  735. return
  736. }
  737. }
  738. var view *av.View
  739. if "" != viewID {
  740. view, _ = attrView.GetCurrentView(viewID)
  741. if nil != view && view.ID != attrView.ViewID {
  742. attrView.ViewID = view.ID
  743. if err = av.SaveAttributeView(attrView); nil != err {
  744. logging.LogErrorf("save attribute view [%s] failed: %s", attrView.ID, err)
  745. return
  746. }
  747. }
  748. } else {
  749. view = attrView.GetView(attrView.ViewID)
  750. }
  751. if nil == view {
  752. view = attrView.Views[0]
  753. }
  754. // 做一些数据兼容和订正处理,保存的时候也会做 av.SaveAttributeView()
  755. currentTimeMillis := util.CurrentTimeMillis()
  756. for _, kv := range attrView.KeyValues {
  757. switch kv.Key.Type {
  758. case av.KeyTypeBlock: // 补全 block 的创建时间和更新时间
  759. for _, v := range kv.Values {
  760. if 0 == v.Block.Created {
  761. if "" == v.Block.ID {
  762. v.Block.ID = v.BlockID
  763. if "" == v.Block.ID {
  764. v.Block.ID = ast.NewNodeID()
  765. v.BlockID = v.Block.ID
  766. }
  767. }
  768. createdStr := v.Block.ID[:len("20060102150405")]
  769. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  770. if nil == parseErr {
  771. v.Block.Created = created.UnixMilli()
  772. } else {
  773. v.Block.Created = currentTimeMillis
  774. }
  775. }
  776. if 0 == v.Block.Updated {
  777. v.Block.Updated = v.Block.Created
  778. }
  779. }
  780. }
  781. for _, v := range kv.Values {
  782. // 校验日期 IsNotEmpty
  783. if av.KeyTypeDate == kv.Key.Type {
  784. if nil != v.Date && 0 != v.Date.Content && !v.Date.IsNotEmpty {
  785. v.Date.IsNotEmpty = true
  786. }
  787. }
  788. // 校验数字 IsNotEmpty
  789. if av.KeyTypeNumber == kv.Key.Type {
  790. if nil != v.Number && 0 != v.Number.Content && !v.Number.IsNotEmpty {
  791. v.Number.IsNotEmpty = true
  792. }
  793. }
  794. // 补全值的创建时间和更新时间
  795. if "" == v.ID {
  796. v.ID = ast.NewNodeID()
  797. }
  798. if 0 == v.CreatedAt {
  799. createdStr := v.ID[:len("20060102150405")]
  800. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  801. if nil == parseErr {
  802. v.CreatedAt = created.UnixMilli()
  803. } else {
  804. v.CreatedAt = currentTimeMillis
  805. }
  806. }
  807. if 0 == v.UpdatedAt {
  808. v.UpdatedAt = v.CreatedAt
  809. }
  810. }
  811. }
  812. // 补全过滤器 Value
  813. if nil != view.Table {
  814. for _, f := range view.Table.Filters {
  815. if nil != f.Value {
  816. continue
  817. }
  818. if k, _ := attrView.GetKey(f.Column); nil != k {
  819. f.Value = &av.Value{Type: k.Type}
  820. }
  821. }
  822. }
  823. switch view.LayoutType {
  824. case av.LayoutTypeTable:
  825. // 列删除以后需要删除设置的过滤和排序
  826. tmpFilters := []*av.ViewFilter{}
  827. for _, f := range view.Table.Filters {
  828. if k, _ := attrView.GetKey(f.Column); nil != k {
  829. tmpFilters = append(tmpFilters, f)
  830. }
  831. }
  832. view.Table.Filters = tmpFilters
  833. tmpSorts := []*av.ViewSort{}
  834. for _, s := range view.Table.Sorts {
  835. if k, _ := attrView.GetKey(s.Column); nil != k {
  836. tmpSorts = append(tmpSorts, s)
  837. }
  838. }
  839. view.Table.Sorts = tmpSorts
  840. viewable = sql.RenderAttributeViewTable(attrView, view, query, GetBlockAttrsWithoutWaitWriting)
  841. }
  842. viewable.FilterRows(attrView)
  843. viewable.SortRows(attrView)
  844. viewable.CalcCols()
  845. // 分页
  846. switch viewable.GetType() {
  847. case av.LayoutTypeTable:
  848. table := viewable.(*av.Table)
  849. table.RowCount = len(table.Rows)
  850. if 1 > view.Table.PageSize {
  851. view.Table.PageSize = 50
  852. }
  853. table.PageSize = view.Table.PageSize
  854. if 1 > pageSize {
  855. pageSize = table.PageSize
  856. }
  857. start := (page - 1) * pageSize
  858. end := start + pageSize
  859. if len(table.Rows) < end {
  860. end = len(table.Rows)
  861. }
  862. table.Rows = table.Rows[start:end]
  863. }
  864. return
  865. }
  866. func (tx *Transaction) doUnbindAttrViewBlock(operation *Operation) (ret *TxErr) {
  867. err := unbindAttributeViewBlock(operation, tx)
  868. if nil != err {
  869. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  870. }
  871. return
  872. }
  873. func unbindAttributeViewBlock(operation *Operation, tx *Transaction) (err error) {
  874. attrView, err := av.ParseAttributeView(operation.AvID)
  875. if nil != err {
  876. return
  877. }
  878. node, _, _ := getNodeByBlockID(tx, operation.ID)
  879. if nil == node {
  880. return
  881. }
  882. for _, keyValues := range attrView.KeyValues {
  883. for _, value := range keyValues.Values {
  884. if value.BlockID != operation.ID {
  885. continue
  886. }
  887. if av.KeyTypeBlock == value.Type {
  888. unbindBlockAv(tx, operation.AvID, value.BlockID)
  889. }
  890. value.BlockID = operation.NextID
  891. value.IsDetached = true
  892. if nil != value.Block {
  893. value.Block.ID = operation.NextID
  894. }
  895. replaceRelationAvValues(operation.AvID, operation.ID, operation.NextID)
  896. }
  897. }
  898. replacedRowID := false
  899. for _, v := range attrView.Views {
  900. switch v.LayoutType {
  901. case av.LayoutTypeTable:
  902. for i, rowID := range v.Table.RowIDs {
  903. if rowID == operation.ID {
  904. v.Table.RowIDs[i] = operation.NextID
  905. replacedRowID = true
  906. break
  907. }
  908. }
  909. if !replacedRowID {
  910. v.Table.RowIDs = append(v.Table.RowIDs, operation.NextID)
  911. }
  912. }
  913. }
  914. err = av.SaveAttributeView(attrView)
  915. return
  916. }
  917. func (tx *Transaction) doSetAttrViewColDate(operation *Operation) (ret *TxErr) {
  918. err := setAttributeViewColDate(operation)
  919. if nil != err {
  920. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  921. }
  922. return
  923. }
  924. func setAttributeViewColDate(operation *Operation) (err error) {
  925. attrView, err := av.ParseAttributeView(operation.AvID)
  926. if nil != err {
  927. return
  928. }
  929. keyID := operation.ID
  930. key, _ := attrView.GetKey(keyID)
  931. if nil == key || av.KeyTypeDate != key.Type {
  932. return
  933. }
  934. if nil == key.Date {
  935. key.Date = &av.Date{}
  936. }
  937. key.Date.AutoFillNow = operation.Data.(bool)
  938. err = av.SaveAttributeView(attrView)
  939. return
  940. }
  941. func (tx *Transaction) doHideAttrViewName(operation *Operation) (ret *TxErr) {
  942. err := hideAttrViewName(operation)
  943. if nil != err {
  944. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  945. }
  946. return
  947. }
  948. func hideAttrViewName(operation *Operation) (err error) {
  949. attrView, err := av.ParseAttributeView(operation.AvID)
  950. if nil != err {
  951. logging.LogErrorf("parse attribute view [%s] failed: %s", operation.AvID, err)
  952. return
  953. }
  954. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  955. if nil == view {
  956. logging.LogErrorf("get view [%s] failed: %s", operation.BlockID, err)
  957. return
  958. }
  959. view.HideAttrViewName = operation.Data.(bool)
  960. err = av.SaveAttributeView(attrView)
  961. return
  962. }
  963. func (tx *Transaction) doUpdateAttrViewColRollup(operation *Operation) (ret *TxErr) {
  964. err := updateAttributeViewColRollup(operation)
  965. if nil != err {
  966. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  967. }
  968. return
  969. }
  970. func updateAttributeViewColRollup(operation *Operation) (err error) {
  971. // operation.AvID 汇总列所在 av
  972. // operation.ID 汇总列 ID
  973. // operation.ParentID 汇总列基于的关联列 ID
  974. // operation.KeyID 目标列 ID
  975. // operation.Data 计算方式
  976. attrView, err := av.ParseAttributeView(operation.AvID)
  977. if nil != err {
  978. return
  979. }
  980. rollUpKey, _ := attrView.GetKey(operation.ID)
  981. if nil == rollUpKey {
  982. return
  983. }
  984. rollUpKey.Rollup = &av.Rollup{
  985. RelationKeyID: operation.ParentID,
  986. KeyID: operation.KeyID,
  987. }
  988. if nil != operation.Data {
  989. data := operation.Data.(map[string]interface{})
  990. if nil != data["calc"] {
  991. calcData, jsonErr := gulu.JSON.MarshalJSON(data["calc"])
  992. if nil != jsonErr {
  993. err = jsonErr
  994. return
  995. }
  996. if jsonErr = gulu.JSON.UnmarshalJSON(calcData, &rollUpKey.Rollup.Calc); nil != jsonErr {
  997. err = jsonErr
  998. return
  999. }
  1000. }
  1001. }
  1002. err = av.SaveAttributeView(attrView)
  1003. return
  1004. }
  1005. func (tx *Transaction) doUpdateAttrViewColRelation(operation *Operation) (ret *TxErr) {
  1006. err := updateAttributeViewColRelation(operation)
  1007. if nil != err {
  1008. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1009. }
  1010. return
  1011. }
  1012. func updateAttributeViewColRelation(operation *Operation) (err error) {
  1013. // operation.AvID 源 avID
  1014. // operation.ID 目标 avID
  1015. // operation.KeyID 源 av 关联列 ID
  1016. // operation.IsTwoWay 是否双向关联
  1017. // operation.BackRelationKeyID 双向关联的目标关联列 ID
  1018. // operation.Name 双向关联的目标关联列名称
  1019. // operation.Format 源 av 关联列名称
  1020. srcAv, err := av.ParseAttributeView(operation.AvID)
  1021. if nil != err {
  1022. return
  1023. }
  1024. destAv, err := av.ParseAttributeView(operation.ID)
  1025. if nil != err {
  1026. return
  1027. }
  1028. isSameAv := srcAv.ID == destAv.ID
  1029. if isSameAv {
  1030. destAv = srcAv
  1031. }
  1032. for _, keyValues := range srcAv.KeyValues {
  1033. if keyValues.Key.ID != operation.KeyID {
  1034. continue
  1035. }
  1036. srcRel := keyValues.Key.Relation
  1037. // 已经设置过双向关联的话需要先断开双向关联
  1038. if nil != srcRel {
  1039. if srcRel.IsTwoWay {
  1040. oldDestAv, _ := av.ParseAttributeView(srcRel.AvID)
  1041. if nil != oldDestAv {
  1042. isOldSameAv := oldDestAv.ID == destAv.ID
  1043. if isOldSameAv {
  1044. oldDestAv = destAv
  1045. }
  1046. oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID)
  1047. if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay {
  1048. oldDestKey.Relation.IsTwoWay = false
  1049. oldDestKey.Relation.BackKeyID = ""
  1050. }
  1051. if !isOldSameAv {
  1052. err = av.SaveAttributeView(oldDestAv)
  1053. if nil != err {
  1054. return
  1055. }
  1056. }
  1057. }
  1058. }
  1059. av.RemoveAvRel(srcAv.ID, srcRel.AvID)
  1060. }
  1061. srcRel = &av.Relation{
  1062. AvID: operation.ID,
  1063. IsTwoWay: operation.IsTwoWay,
  1064. }
  1065. if operation.IsTwoWay {
  1066. srcRel.BackKeyID = operation.BackRelationKeyID
  1067. } else {
  1068. srcRel.BackKeyID = ""
  1069. }
  1070. keyValues.Key.Relation = srcRel
  1071. keyValues.Key.Name = operation.Format
  1072. break
  1073. }
  1074. destAdded := false
  1075. backRelKey, _ := destAv.GetKey(operation.BackRelationKeyID)
  1076. if nil != backRelKey {
  1077. backRelKey.Relation = &av.Relation{
  1078. AvID: operation.AvID,
  1079. IsTwoWay: operation.IsTwoWay,
  1080. BackKeyID: operation.KeyID,
  1081. }
  1082. destAdded = true
  1083. if operation.IsTwoWay {
  1084. name := strings.TrimSpace(operation.Name)
  1085. if "" == name {
  1086. name = srcAv.Name + " " + operation.Format
  1087. }
  1088. backRelKey.Name = strings.TrimSpace(name)
  1089. } else {
  1090. backRelKey.Relation.BackKeyID = ""
  1091. }
  1092. }
  1093. if !destAdded && operation.IsTwoWay {
  1094. // 新建双向关联目标字段
  1095. name := strings.TrimSpace(operation.Name)
  1096. if "" == name {
  1097. name = srcAv.Name + " " + operation.Format
  1098. name = strings.TrimSpace(name)
  1099. }
  1100. destKeyValues := &av.KeyValues{
  1101. Key: &av.Key{
  1102. ID: operation.BackRelationKeyID,
  1103. Name: name,
  1104. Type: av.KeyTypeRelation,
  1105. Relation: &av.Relation{AvID: operation.AvID, IsTwoWay: operation.IsTwoWay, BackKeyID: operation.KeyID},
  1106. },
  1107. }
  1108. destAv.KeyValues = append(destAv.KeyValues, destKeyValues)
  1109. for _, v := range destAv.Views {
  1110. switch v.LayoutType {
  1111. case av.LayoutTypeTable:
  1112. v.Table.Columns = append(v.Table.Columns, &av.ViewTableColumn{ID: operation.BackRelationKeyID})
  1113. }
  1114. }
  1115. now := time.Now().UnixMilli()
  1116. // 和现有值进行关联
  1117. for _, keyValues := range srcAv.KeyValues {
  1118. if keyValues.Key.ID != operation.KeyID {
  1119. continue
  1120. }
  1121. for _, srcVal := range keyValues.Values {
  1122. for _, blockID := range srcVal.Relation.BlockIDs {
  1123. destVal := destAv.GetValue(destKeyValues.Key.ID, blockID)
  1124. if nil == destVal {
  1125. destVal = &av.Value{ID: ast.NewNodeID(), KeyID: destKeyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}, CreatedAt: now, UpdatedAt: now + 1000}
  1126. } else {
  1127. destVal.Type = keyValues.Key.Type
  1128. if nil == destVal.Relation {
  1129. destVal.Relation = &av.ValueRelation{}
  1130. }
  1131. destVal.UpdatedAt = now
  1132. }
  1133. destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, srcVal.BlockID)
  1134. destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
  1135. destKeyValues.Values = append(destKeyValues.Values, destVal)
  1136. }
  1137. }
  1138. }
  1139. }
  1140. err = av.SaveAttributeView(srcAv)
  1141. if nil != err {
  1142. return
  1143. }
  1144. if !isSameAv {
  1145. err = av.SaveAttributeView(destAv)
  1146. util.PushReloadAttrView(destAv.ID)
  1147. }
  1148. av.UpsertAvBackRel(srcAv.ID, destAv.ID)
  1149. if operation.IsTwoWay && !isSameAv {
  1150. av.UpsertAvBackRel(destAv.ID, srcAv.ID)
  1151. }
  1152. return
  1153. }
  1154. func (tx *Transaction) doSortAttrViewView(operation *Operation) (ret *TxErr) {
  1155. avID := operation.AvID
  1156. attrView, err := av.ParseAttributeView(avID)
  1157. if nil != err {
  1158. logging.LogErrorf("parse attribute view [%s] failed: %s", operation.AvID, err)
  1159. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1160. }
  1161. view := attrView.GetView(operation.ID)
  1162. if nil == view {
  1163. logging.LogErrorf("get view failed: %s", operation.BlockID)
  1164. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1165. }
  1166. viewID := view.ID
  1167. previousViewID := operation.PreviousID
  1168. if viewID == previousViewID {
  1169. return
  1170. }
  1171. var index, previousIndex int
  1172. for i, v := range attrView.Views {
  1173. if v.ID == viewID {
  1174. view = v
  1175. index = i
  1176. break
  1177. }
  1178. }
  1179. if nil == view {
  1180. return
  1181. }
  1182. attrView.Views = append(attrView.Views[:index], attrView.Views[index+1:]...)
  1183. for i, v := range attrView.Views {
  1184. if v.ID == previousViewID {
  1185. previousIndex = i + 1
  1186. break
  1187. }
  1188. }
  1189. attrView.Views = util.InsertElem(attrView.Views, previousIndex, view)
  1190. if err = av.SaveAttributeView(attrView); nil != err {
  1191. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1192. return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: avID}
  1193. }
  1194. return
  1195. }
  1196. func (tx *Transaction) doRemoveAttrViewView(operation *Operation) (ret *TxErr) {
  1197. var err error
  1198. avID := operation.AvID
  1199. attrView, err := av.ParseAttributeView(avID)
  1200. if nil != err {
  1201. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1202. return &TxErr{code: TxErrCodeBlockNotFound, id: avID}
  1203. }
  1204. if 1 >= len(attrView.Views) {
  1205. logging.LogWarnf("can't remove last view [%s] of attribute view [%s]", operation.AvID, avID)
  1206. return
  1207. }
  1208. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1209. if nil == view {
  1210. logging.LogWarnf("get view failed: %s", operation.BlockID)
  1211. return
  1212. }
  1213. viewID := view.ID
  1214. var index int
  1215. for i, view := range attrView.Views {
  1216. if viewID == view.ID {
  1217. attrView.Views = append(attrView.Views[:i], attrView.Views[i+1:]...)
  1218. index = i - 1
  1219. break
  1220. }
  1221. }
  1222. if 0 > index {
  1223. index = 0
  1224. }
  1225. attrView.ViewID = attrView.Views[index].ID
  1226. if err = av.SaveAttributeView(attrView); nil != err {
  1227. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1228. return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: avID}
  1229. }
  1230. trees, nodes := getMirrorBlocksNodes(avID)
  1231. for _, node := range nodes {
  1232. attrs := parse.IAL2Map(node.KramdownIAL)
  1233. blockViewID := attrs[av.NodeAttrView]
  1234. if blockViewID == viewID {
  1235. attrs[av.NodeAttrView] = attrView.ViewID
  1236. oldAttrs, e := setNodeAttrs0(node, attrs)
  1237. if nil != e {
  1238. logging.LogErrorf("set node attrs failed: %s", e)
  1239. continue
  1240. }
  1241. cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL))
  1242. pushBroadcastAttrTransactions(oldAttrs, node)
  1243. }
  1244. }
  1245. for _, tree := range trees {
  1246. if err = indexWriteTreeUpsertQueue(tree); nil != err {
  1247. return
  1248. }
  1249. }
  1250. return
  1251. }
  1252. func getMirrorBlocksNodes(avID string) (trees []*parse.Tree, nodes []*ast.Node) {
  1253. mirrorBlocks := treenode.GetMirrorAttrViewBlockIDs(avID)
  1254. mirrorBlockTree := map[string]*parse.Tree{}
  1255. treeMap := map[string]*parse.Tree{}
  1256. for _, mirrorBlock := range mirrorBlocks {
  1257. bt := treenode.GetBlockTree(mirrorBlock)
  1258. if nil == bt {
  1259. logging.LogErrorf("get block tree by block ID [%s] failed", mirrorBlock)
  1260. continue
  1261. }
  1262. tree := mirrorBlockTree[mirrorBlock]
  1263. if nil == tree {
  1264. tree, _ = LoadTreeByBlockID(mirrorBlock)
  1265. if nil == tree {
  1266. logging.LogErrorf("load tree by block ID [%s] failed", mirrorBlock)
  1267. continue
  1268. }
  1269. treeMap[tree.ID] = tree
  1270. mirrorBlockTree[mirrorBlock] = tree
  1271. }
  1272. }
  1273. for _, mirrorBlock := range mirrorBlocks {
  1274. tree := mirrorBlockTree[mirrorBlock]
  1275. node := treenode.GetNodeInTree(tree, mirrorBlock)
  1276. if nil == node {
  1277. logging.LogErrorf("get node in tree by block ID [%s] failed", mirrorBlock)
  1278. continue
  1279. }
  1280. nodes = append(nodes, node)
  1281. }
  1282. for _, tree := range treeMap {
  1283. trees = append(trees, tree)
  1284. }
  1285. return
  1286. }
  1287. func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr) {
  1288. var err error
  1289. avID := operation.AvID
  1290. attrView, err := av.ParseAttributeView(avID)
  1291. if nil != err {
  1292. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1293. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1294. }
  1295. masterView := attrView.GetView(operation.PreviousID)
  1296. if nil == masterView {
  1297. logging.LogErrorf("get master view failed: %s", avID)
  1298. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1299. }
  1300. node, tree, _ := getNodeByBlockID(nil, operation.BlockID)
  1301. if nil == node {
  1302. logging.LogErrorf("get node by block ID [%s] failed", operation.BlockID)
  1303. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  1304. }
  1305. attrs := parse.IAL2Map(node.KramdownIAL)
  1306. attrs[av.NodeAttrView] = operation.ID
  1307. err = setNodeAttrs(node, tree, attrs)
  1308. if nil != err {
  1309. logging.LogWarnf("set node [%s] attrs failed: %s", operation.BlockID, err)
  1310. return
  1311. }
  1312. view := av.NewTableView()
  1313. view.ID = operation.ID
  1314. attrView.Views = append(attrView.Views, view)
  1315. attrView.ViewID = view.ID
  1316. view.Icon = masterView.Icon
  1317. view.Name = util.GetDuplicateName(masterView.Name)
  1318. view.LayoutType = masterView.LayoutType
  1319. view.HideAttrViewName = masterView.HideAttrViewName
  1320. for _, col := range masterView.Table.Columns {
  1321. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{
  1322. ID: col.ID,
  1323. Wrap: col.Wrap,
  1324. Hidden: col.Hidden,
  1325. Pin: col.Pin,
  1326. Width: col.Width,
  1327. Calc: col.Calc,
  1328. })
  1329. }
  1330. for _, filter := range masterView.Table.Filters {
  1331. view.Table.Filters = append(view.Table.Filters, &av.ViewFilter{
  1332. Column: filter.Column,
  1333. Operator: filter.Operator,
  1334. Value: filter.Value,
  1335. RelativeDate: filter.RelativeDate,
  1336. RelativeDate2: filter.RelativeDate2,
  1337. })
  1338. }
  1339. for _, s := range masterView.Table.Sorts {
  1340. view.Table.Sorts = append(view.Table.Sorts, &av.ViewSort{
  1341. Column: s.Column,
  1342. Order: s.Order,
  1343. })
  1344. }
  1345. view.Table.PageSize = masterView.Table.PageSize
  1346. view.Table.RowIDs = masterView.Table.RowIDs
  1347. if err = av.SaveAttributeView(attrView); nil != err {
  1348. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1349. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1350. }
  1351. return
  1352. }
  1353. func (tx *Transaction) doAddAttrViewView(operation *Operation) (ret *TxErr) {
  1354. var err error
  1355. avID := operation.AvID
  1356. attrView, err := av.ParseAttributeView(avID)
  1357. if nil != err {
  1358. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1359. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1360. }
  1361. if 1 > len(attrView.Views) {
  1362. logging.LogErrorf("no view in attribute view [%s]", avID)
  1363. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1364. }
  1365. firstView := attrView.Views[0]
  1366. if nil == firstView {
  1367. logging.LogErrorf("get first view failed: %s", avID)
  1368. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1369. }
  1370. node, tree, _ := getNodeByBlockID(nil, operation.BlockID)
  1371. if nil == node {
  1372. logging.LogErrorf("get node by block ID [%s] failed", operation.BlockID)
  1373. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  1374. }
  1375. attrs := parse.IAL2Map(node.KramdownIAL)
  1376. attrs[av.NodeAttrView] = operation.ID
  1377. err = setNodeAttrs(node, tree, attrs)
  1378. if nil != err {
  1379. logging.LogWarnf("set node [%s] attrs failed: %s", operation.BlockID, err)
  1380. return
  1381. }
  1382. view := av.NewTableView()
  1383. view.ID = operation.ID
  1384. attrView.Views = append(attrView.Views, view)
  1385. attrView.ViewID = view.ID
  1386. for _, col := range firstView.Table.Columns {
  1387. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: col.ID})
  1388. }
  1389. view.Table.RowIDs = firstView.Table.RowIDs
  1390. if err = av.SaveAttributeView(attrView); nil != err {
  1391. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1392. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1393. }
  1394. return
  1395. }
  1396. func (tx *Transaction) doSetAttrViewViewName(operation *Operation) (ret *TxErr) {
  1397. var err error
  1398. avID := operation.AvID
  1399. attrView, err := av.ParseAttributeView(avID)
  1400. if nil != err {
  1401. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1402. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1403. }
  1404. viewID := operation.ID
  1405. view := attrView.GetView(viewID)
  1406. if nil == view {
  1407. logging.LogErrorf("get view [%s] failed: %s", viewID, err)
  1408. return &TxErr{code: TxErrWriteAttributeView, id: viewID}
  1409. }
  1410. view.Name = strings.TrimSpace(operation.Data.(string))
  1411. if err = av.SaveAttributeView(attrView); nil != err {
  1412. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1413. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1414. }
  1415. return
  1416. }
  1417. func (tx *Transaction) doSetAttrViewViewIcon(operation *Operation) (ret *TxErr) {
  1418. var err error
  1419. avID := operation.AvID
  1420. attrView, err := av.ParseAttributeView(avID)
  1421. if nil != err {
  1422. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1423. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1424. }
  1425. viewID := operation.ID
  1426. view := attrView.GetView(viewID)
  1427. if nil == view {
  1428. logging.LogErrorf("get view [%s] failed: %s", viewID, err)
  1429. return &TxErr{code: TxErrWriteAttributeView, id: viewID}
  1430. }
  1431. view.Icon = operation.Data.(string)
  1432. if err = av.SaveAttributeView(attrView); nil != err {
  1433. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1434. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1435. }
  1436. return
  1437. }
  1438. func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) {
  1439. err := setAttributeViewName(operation)
  1440. if nil != err {
  1441. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1442. }
  1443. return
  1444. }
  1445. const attrAvNameTpl = `<span data-av-id="${avID}" data-popover-url="/api/av/getMirrorDatabaseBlocks" class="popover__block">${avName}</span>`
  1446. func setAttributeViewName(operation *Operation) (err error) {
  1447. avID := operation.ID
  1448. attrView, err := av.ParseAttributeView(avID)
  1449. if nil != err {
  1450. return
  1451. }
  1452. attrView.Name = strings.TrimSpace(operation.Data.(string))
  1453. err = av.SaveAttributeView(attrView)
  1454. nodes := getAttrViewBoundNodes(attrView)
  1455. for _, node := range nodes {
  1456. avNames := getAvNames(node.IALAttr(av.NodeAttrNameAvs))
  1457. oldAttrs := parse.IAL2Map(node.KramdownIAL)
  1458. node.SetIALAttr(av.NodeAttrViewNames, avNames)
  1459. pushBroadcastAttrTransactions(oldAttrs, node)
  1460. }
  1461. return
  1462. }
  1463. func getAvNames(avIDs string) (ret string) {
  1464. if "" == avIDs {
  1465. return
  1466. }
  1467. avNames := bytes.Buffer{}
  1468. nodeAvIDs := strings.Split(avIDs, ",")
  1469. for _, nodeAvID := range nodeAvIDs {
  1470. nodeAvName, getErr := av.GetAttributeViewName(nodeAvID)
  1471. if nil != getErr {
  1472. continue
  1473. }
  1474. if "" == nodeAvName {
  1475. nodeAvName = Conf.language(105)
  1476. }
  1477. tpl := strings.ReplaceAll(attrAvNameTpl, "${avID}", nodeAvID)
  1478. tpl = strings.ReplaceAll(tpl, "${avName}", nodeAvName)
  1479. avNames.WriteString(tpl)
  1480. avNames.WriteString("&nbsp;")
  1481. }
  1482. if 0 < avNames.Len() {
  1483. avNames.Truncate(avNames.Len() - 6)
  1484. ret = avNames.String()
  1485. }
  1486. return
  1487. }
  1488. func getAttrViewBoundNodes(attrView *av.AttributeView) (ret []*ast.Node) {
  1489. blockKeyValues := attrView.GetBlockKeyValues()
  1490. treeMap := map[string]*parse.Tree{}
  1491. for _, blockKeyValue := range blockKeyValues.Values {
  1492. if blockKeyValue.IsDetached {
  1493. continue
  1494. }
  1495. var tree *parse.Tree
  1496. tree = treeMap[blockKeyValue.BlockID]
  1497. if nil == tree {
  1498. tree, _ = LoadTreeByBlockID(blockKeyValue.BlockID)
  1499. }
  1500. if nil == tree {
  1501. continue
  1502. }
  1503. treeMap[blockKeyValue.BlockID] = tree
  1504. node := treenode.GetNodeInTree(tree, blockKeyValue.BlockID)
  1505. if nil == node {
  1506. continue
  1507. }
  1508. ret = append(ret, node)
  1509. }
  1510. return
  1511. }
  1512. func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) {
  1513. err := setAttributeViewFilters(operation)
  1514. if nil != err {
  1515. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1516. }
  1517. return
  1518. }
  1519. func setAttributeViewFilters(operation *Operation) (err error) {
  1520. attrView, err := av.ParseAttributeView(operation.AvID)
  1521. if nil != err {
  1522. return
  1523. }
  1524. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1525. if nil != err {
  1526. return
  1527. }
  1528. operationData := operation.Data.([]interface{})
  1529. data, err := gulu.JSON.MarshalJSON(operationData)
  1530. if nil != err {
  1531. return
  1532. }
  1533. switch view.LayoutType {
  1534. case av.LayoutTypeTable:
  1535. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Filters); nil != err {
  1536. return
  1537. }
  1538. }
  1539. err = av.SaveAttributeView(attrView)
  1540. return
  1541. }
  1542. func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) {
  1543. err := setAttributeViewSorts(operation)
  1544. if nil != err {
  1545. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1546. }
  1547. return
  1548. }
  1549. func setAttributeViewSorts(operation *Operation) (err error) {
  1550. attrView, err := av.ParseAttributeView(operation.AvID)
  1551. if nil != err {
  1552. return
  1553. }
  1554. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1555. if nil != err {
  1556. return
  1557. }
  1558. operationData := operation.Data.([]interface{})
  1559. data, err := gulu.JSON.MarshalJSON(operationData)
  1560. if nil != err {
  1561. return
  1562. }
  1563. switch view.LayoutType {
  1564. case av.LayoutTypeTable:
  1565. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Sorts); nil != err {
  1566. return
  1567. }
  1568. }
  1569. err = av.SaveAttributeView(attrView)
  1570. return
  1571. }
  1572. func (tx *Transaction) doSetAttrViewPageSize(operation *Operation) (ret *TxErr) {
  1573. err := setAttributeViewPageSize(operation)
  1574. if nil != err {
  1575. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1576. }
  1577. return
  1578. }
  1579. func setAttributeViewPageSize(operation *Operation) (err error) {
  1580. attrView, err := av.ParseAttributeView(operation.AvID)
  1581. if nil != err {
  1582. return
  1583. }
  1584. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1585. if nil != err {
  1586. return
  1587. }
  1588. switch view.LayoutType {
  1589. case av.LayoutTypeTable:
  1590. view.Table.PageSize = int(operation.Data.(float64))
  1591. }
  1592. err = av.SaveAttributeView(attrView)
  1593. return
  1594. }
  1595. func (tx *Transaction) doSetAttrViewColCalc(operation *Operation) (ret *TxErr) {
  1596. err := setAttributeViewColumnCalc(operation)
  1597. if nil != err {
  1598. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1599. }
  1600. return
  1601. }
  1602. func setAttributeViewColumnCalc(operation *Operation) (err error) {
  1603. attrView, err := av.ParseAttributeView(operation.AvID)
  1604. if nil != err {
  1605. return
  1606. }
  1607. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1608. if nil != err {
  1609. return
  1610. }
  1611. operationData := operation.Data.(interface{})
  1612. data, err := gulu.JSON.MarshalJSON(operationData)
  1613. if nil != err {
  1614. return
  1615. }
  1616. calc := &av.ColumnCalc{}
  1617. switch view.LayoutType {
  1618. case av.LayoutTypeTable:
  1619. if err = gulu.JSON.UnmarshalJSON(data, calc); nil != err {
  1620. return
  1621. }
  1622. for _, column := range view.Table.Columns {
  1623. if column.ID == operation.ID {
  1624. column.Calc = calc
  1625. break
  1626. }
  1627. }
  1628. }
  1629. err = av.SaveAttributeView(attrView)
  1630. return
  1631. }
  1632. func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
  1633. err := AddAttributeViewBlock(tx, operation.Srcs, operation.AvID, operation.BlockID, operation.PreviousID, operation.IgnoreFillFilterVal)
  1634. if nil != err {
  1635. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1636. }
  1637. return
  1638. }
  1639. func AddAttributeViewBlock(tx *Transaction, srcs []map[string]interface{}, avID, blockID, previousBlockID string, ignoreFillFilter bool) (err error) {
  1640. slices.Reverse(srcs) // https://github.com/siyuan-note/siyuan/issues/11286
  1641. now := time.Now().UnixMilli()
  1642. for _, src := range srcs {
  1643. srcID := src["id"].(string)
  1644. isDetached := src["isDetached"].(bool)
  1645. var tree *parse.Tree
  1646. if !isDetached {
  1647. var loadErr error
  1648. if nil != tx {
  1649. tree, loadErr = tx.loadTree(srcID)
  1650. } else {
  1651. tree, loadErr = LoadTreeByBlockID(srcID)
  1652. }
  1653. if nil != loadErr {
  1654. logging.LogErrorf("load tree [%s] failed: %s", srcID, loadErr)
  1655. return loadErr
  1656. }
  1657. }
  1658. var srcContent string
  1659. if nil != src["content"] {
  1660. srcContent = src["content"].(string)
  1661. }
  1662. if avErr := addAttributeViewBlock(now, avID, blockID, previousBlockID, srcID, srcContent, isDetached, ignoreFillFilter, tree, tx); nil != avErr {
  1663. return avErr
  1664. }
  1665. }
  1666. return
  1667. }
  1668. func addAttributeViewBlock(now int64, avID, blockID, previousBlockID, addingBlockID, addingBlockContent string, isDetached, ignoreFillFilter bool, tree *parse.Tree, tx *Transaction) (err error) {
  1669. var node *ast.Node
  1670. if !isDetached {
  1671. node = treenode.GetNodeInTree(tree, addingBlockID)
  1672. if nil == node {
  1673. err = ErrBlockNotFound
  1674. return
  1675. }
  1676. } else {
  1677. if "" == addingBlockID {
  1678. addingBlockID = ast.NewNodeID()
  1679. logging.LogWarnf("detached block id is empty, generate a new one [%s]", addingBlockID)
  1680. }
  1681. }
  1682. attrView, err := av.ParseAttributeView(avID)
  1683. if nil != err {
  1684. return
  1685. }
  1686. if !isDetached {
  1687. addingBlockContent = getNodeRefText(node)
  1688. }
  1689. // 检查是否重复添加相同的块
  1690. blockValues := attrView.GetBlockKeyValues()
  1691. for _, blockValue := range blockValues.Values {
  1692. if blockValue.Block.ID == addingBlockID {
  1693. if !isDetached {
  1694. // 重复绑定一下,比如剪切数据库块、取消绑定块后再次添加的场景需要
  1695. bindBlockAv0(tx, avID, node, tree)
  1696. blockValue.IsDetached = isDetached
  1697. blockValue.Block.Content = addingBlockContent
  1698. blockValue.UpdatedAt = now
  1699. err = av.SaveAttributeView(attrView)
  1700. }
  1701. return
  1702. }
  1703. }
  1704. blockValue := &av.Value{
  1705. ID: ast.NewNodeID(),
  1706. KeyID: blockValues.Key.ID,
  1707. BlockID: addingBlockID,
  1708. Type: av.KeyTypeBlock,
  1709. IsDetached: isDetached,
  1710. CreatedAt: now,
  1711. UpdatedAt: now,
  1712. Block: &av.ValueBlock{ID: addingBlockID, Content: addingBlockContent, Created: now, Updated: now}}
  1713. blockValues.Values = append(blockValues.Values, blockValue)
  1714. // 如果存在过滤条件,则将过滤条件应用到新添加的块上
  1715. view, _ := getAttrViewViewByBlockID(attrView, blockID)
  1716. if nil != view && 0 < len(view.Table.Filters) && !ignoreFillFilter {
  1717. viewable := sql.RenderAttributeViewTable(attrView, view, "", GetBlockAttrsWithoutWaitWriting)
  1718. viewable.FilterRows(attrView)
  1719. viewable.SortRows(attrView)
  1720. var nearRow *av.TableRow
  1721. if 0 < len(viewable.Rows) {
  1722. if "" != previousBlockID {
  1723. for _, row := range viewable.Rows {
  1724. if row.ID == previousBlockID {
  1725. nearRow = row
  1726. break
  1727. }
  1728. }
  1729. } else {
  1730. if 0 < len(viewable.Rows) {
  1731. nearRow = viewable.Rows[0]
  1732. }
  1733. }
  1734. }
  1735. sameKeyFilterSort := false // 是否在同一个字段上同时存在过滤和排序
  1736. if 0 < len(viewable.Sorts) {
  1737. filterKeys, sortKeys := map[string]bool{}, map[string]bool{}
  1738. for _, f := range view.Table.Filters {
  1739. filterKeys[f.Column] = true
  1740. }
  1741. for _, s := range view.Table.Sorts {
  1742. sortKeys[s.Column] = true
  1743. }
  1744. for key := range filterKeys {
  1745. if sortKeys[key] {
  1746. sameKeyFilterSort = true
  1747. break
  1748. }
  1749. }
  1750. }
  1751. if !sameKeyFilterSort {
  1752. // 如果在同一个字段上仅存在过滤条件,则将过滤条件应用到新添加的块上
  1753. for _, filter := range view.Table.Filters {
  1754. for _, keyValues := range attrView.KeyValues {
  1755. if keyValues.Key.ID == filter.Column {
  1756. var defaultVal *av.Value
  1757. if nil != nearRow {
  1758. defaultVal = nearRow.GetValue(filter.Column)
  1759. }
  1760. newValue := filter.GetAffectValue(keyValues.Key, defaultVal)
  1761. if nil == newValue {
  1762. continue
  1763. }
  1764. if av.KeyTypeBlock == newValue.Type {
  1765. // 如果是主键的话前面已经添加过了,这里仅修改内容
  1766. blockValue.Block.Content = newValue.Block.Content
  1767. break
  1768. }
  1769. newValue.ID = ast.NewNodeID()
  1770. newValue.KeyID = keyValues.Key.ID
  1771. newValue.BlockID = addingBlockID
  1772. newValue.IsDetached = isDetached
  1773. keyValues.Values = append(keyValues.Values, newValue)
  1774. break
  1775. }
  1776. }
  1777. }
  1778. }
  1779. }
  1780. // 处理日期字段默认填充当前创建时间
  1781. // The database date field supports filling the current time by default https://github.com/siyuan-note/siyuan/issues/10823
  1782. for _, keyValues := range attrView.KeyValues {
  1783. if av.KeyTypeDate == keyValues.Key.Type && nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
  1784. dateVal := &av.Value{
  1785. ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: addingBlockID, Type: av.KeyTypeDate, IsDetached: isDetached, CreatedAt: now, UpdatedAt: now + 1000,
  1786. Date: &av.ValueDate{Content: now, IsNotEmpty: true},
  1787. }
  1788. keyValues.Values = append(keyValues.Values, dateVal)
  1789. }
  1790. }
  1791. if !isDetached {
  1792. bindBlockAv0(tx, avID, node, tree)
  1793. }
  1794. for _, v := range attrView.Views {
  1795. switch v.LayoutType {
  1796. case av.LayoutTypeTable:
  1797. if "" != previousBlockID {
  1798. changed := false
  1799. for i, id := range v.Table.RowIDs {
  1800. if id == previousBlockID {
  1801. v.Table.RowIDs = append(v.Table.RowIDs[:i+1], append([]string{addingBlockID}, v.Table.RowIDs[i+1:]...)...)
  1802. changed = true
  1803. break
  1804. }
  1805. }
  1806. if !changed {
  1807. v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
  1808. }
  1809. } else {
  1810. v.Table.RowIDs = append([]string{addingBlockID}, v.Table.RowIDs...)
  1811. }
  1812. }
  1813. }
  1814. err = av.SaveAttributeView(attrView)
  1815. return
  1816. }
  1817. func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) {
  1818. err := removeAttributeViewBlock(operation.SrcIDs, operation.AvID, tx)
  1819. if nil != err {
  1820. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  1821. }
  1822. return
  1823. }
  1824. func RemoveAttributeViewBlock(srcIDs []string, avID string) (err error) {
  1825. err = removeAttributeViewBlock(srcIDs, avID, nil)
  1826. return
  1827. }
  1828. func removeAttributeViewBlock(srcIDs []string, avID string, tx *Transaction) (err error) {
  1829. attrView, err := av.ParseAttributeView(avID)
  1830. if nil != err {
  1831. return
  1832. }
  1833. trees := map[string]*parse.Tree{}
  1834. for _, keyValues := range attrView.KeyValues {
  1835. tmp := keyValues.Values[:0]
  1836. for i, values := range keyValues.Values {
  1837. if !gulu.Str.Contains(values.BlockID, srcIDs) {
  1838. tmp = append(tmp, keyValues.Values[i])
  1839. } else {
  1840. // Remove av block also remove node attr https://github.com/siyuan-note/siyuan/issues/9091#issuecomment-1709824006
  1841. if bt := treenode.GetBlockTree(values.BlockID); nil != bt {
  1842. tree := trees[bt.RootID]
  1843. if nil == tree {
  1844. tree, _ = LoadTreeByBlockID(values.BlockID)
  1845. }
  1846. if nil != tree {
  1847. trees[bt.RootID] = tree
  1848. if node := treenode.GetNodeInTree(tree, values.BlockID); nil != node {
  1849. if err = removeNodeAvID(node, avID, tx, tree); nil != err {
  1850. return
  1851. }
  1852. }
  1853. }
  1854. }
  1855. }
  1856. }
  1857. keyValues.Values = tmp
  1858. }
  1859. for _, view := range attrView.Views {
  1860. for _, blockID := range srcIDs {
  1861. view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
  1862. }
  1863. }
  1864. relatedAvIDs := av.GetSrcAvIDs(avID)
  1865. for _, relatedAvID := range relatedAvIDs {
  1866. util.PushReloadAttrView(relatedAvID)
  1867. }
  1868. err = av.SaveAttributeView(attrView)
  1869. return
  1870. }
  1871. func removeNodeAvID(node *ast.Node, avID string, tx *Transaction, tree *parse.Tree) (err error) {
  1872. attrs := parse.IAL2Map(node.KramdownIAL)
  1873. if ast.NodeDocument == node.Type {
  1874. delete(attrs, "custom-hidden")
  1875. node.RemoveIALAttr("custom-hidden")
  1876. }
  1877. if avs := attrs[av.NodeAttrNameAvs]; "" != avs {
  1878. avIDs := strings.Split(avs, ",")
  1879. avIDs = gulu.Str.RemoveElem(avIDs, avID)
  1880. var existAvIDs []string
  1881. for _, attributeViewID := range avIDs {
  1882. if av.IsAttributeViewExist(attributeViewID) {
  1883. existAvIDs = append(existAvIDs, attributeViewID)
  1884. }
  1885. }
  1886. avIDs = existAvIDs
  1887. if 0 == len(avIDs) {
  1888. attrs[av.NodeAttrNameAvs] = ""
  1889. } else {
  1890. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  1891. node.SetIALAttr(av.NodeAttrNameAvs, strings.Join(avIDs, ","))
  1892. avNames := getAvNames(node.IALAttr(av.NodeAttrNameAvs))
  1893. attrs[av.NodeAttrViewNames] = avNames
  1894. }
  1895. }
  1896. if nil != tx {
  1897. if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
  1898. return
  1899. }
  1900. } else {
  1901. if err = setNodeAttrs(node, tree, attrs); nil != err {
  1902. return
  1903. }
  1904. }
  1905. return
  1906. }
  1907. func (tx *Transaction) doDuplicateAttrViewKey(operation *Operation) (ret *TxErr) {
  1908. err := duplicateAttributeViewKey(operation)
  1909. if nil != err {
  1910. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1911. }
  1912. return
  1913. }
  1914. func duplicateAttributeViewKey(operation *Operation) (err error) {
  1915. attrView, err := av.ParseAttributeView(operation.AvID)
  1916. if nil != err {
  1917. return
  1918. }
  1919. key, _ := attrView.GetKey(operation.KeyID)
  1920. if nil == key {
  1921. return
  1922. }
  1923. if av.KeyTypeBlock == key.Type || av.KeyTypeRelation == key.Type || av.KeyTypeRollup == key.Type {
  1924. return
  1925. }
  1926. copyKey := &av.Key{}
  1927. if err = copier.Copy(copyKey, key); nil != err {
  1928. logging.LogErrorf("clone key failed: %s", err)
  1929. }
  1930. copyKey.ID = operation.NextID
  1931. copyKey.Name = util.GetDuplicateName(key.Name)
  1932. attrView.KeyValues = append(attrView.KeyValues, &av.KeyValues{Key: copyKey})
  1933. for _, view := range attrView.Views {
  1934. switch view.LayoutType {
  1935. case av.LayoutTypeTable:
  1936. for i, column := range view.Table.Columns {
  1937. if column.ID == key.ID {
  1938. view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{
  1939. {
  1940. ID: copyKey.ID,
  1941. Wrap: column.Wrap,
  1942. Hidden: column.Hidden,
  1943. Pin: column.Pin,
  1944. Width: column.Width,
  1945. },
  1946. }, view.Table.Columns[i+1:]...)...)
  1947. break
  1948. }
  1949. }
  1950. }
  1951. }
  1952. err = av.SaveAttributeView(attrView)
  1953. return
  1954. }
  1955. func (tx *Transaction) doSetAttrViewColumnWidth(operation *Operation) (ret *TxErr) {
  1956. err := setAttributeViewColWidth(operation)
  1957. if nil != err {
  1958. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1959. }
  1960. return
  1961. }
  1962. func setAttributeViewColWidth(operation *Operation) (err error) {
  1963. attrView, err := av.ParseAttributeView(operation.AvID)
  1964. if nil != err {
  1965. return
  1966. }
  1967. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1968. if nil != err {
  1969. return
  1970. }
  1971. switch view.LayoutType {
  1972. case av.LayoutTypeTable:
  1973. for _, column := range view.Table.Columns {
  1974. if column.ID == operation.ID {
  1975. column.Width = operation.Data.(string)
  1976. break
  1977. }
  1978. }
  1979. }
  1980. err = av.SaveAttributeView(attrView)
  1981. return
  1982. }
  1983. func (tx *Transaction) doSetAttrViewColumnWrap(operation *Operation) (ret *TxErr) {
  1984. err := setAttributeViewColWrap(operation)
  1985. if nil != err {
  1986. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1987. }
  1988. return
  1989. }
  1990. func setAttributeViewColWrap(operation *Operation) (err error) {
  1991. attrView, err := av.ParseAttributeView(operation.AvID)
  1992. if nil != err {
  1993. return
  1994. }
  1995. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  1996. if nil != err {
  1997. return
  1998. }
  1999. switch view.LayoutType {
  2000. case av.LayoutTypeTable:
  2001. for _, column := range view.Table.Columns {
  2002. if column.ID == operation.ID {
  2003. column.Wrap = operation.Data.(bool)
  2004. break
  2005. }
  2006. }
  2007. }
  2008. err = av.SaveAttributeView(attrView)
  2009. return
  2010. }
  2011. func (tx *Transaction) doSetAttrViewColumnHidden(operation *Operation) (ret *TxErr) {
  2012. err := setAttributeViewColHidden(operation)
  2013. if nil != err {
  2014. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2015. }
  2016. return
  2017. }
  2018. func setAttributeViewColHidden(operation *Operation) (err error) {
  2019. attrView, err := av.ParseAttributeView(operation.AvID)
  2020. if nil != err {
  2021. return
  2022. }
  2023. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  2024. if nil != err {
  2025. return
  2026. }
  2027. switch view.LayoutType {
  2028. case av.LayoutTypeTable:
  2029. for _, column := range view.Table.Columns {
  2030. if column.ID == operation.ID {
  2031. column.Hidden = operation.Data.(bool)
  2032. break
  2033. }
  2034. }
  2035. }
  2036. err = av.SaveAttributeView(attrView)
  2037. return
  2038. }
  2039. func (tx *Transaction) doSetAttrViewColumnPin(operation *Operation) (ret *TxErr) {
  2040. err := setAttributeViewColPin(operation)
  2041. if nil != err {
  2042. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2043. }
  2044. return
  2045. }
  2046. func setAttributeViewColPin(operation *Operation) (err error) {
  2047. attrView, err := av.ParseAttributeView(operation.AvID)
  2048. if nil != err {
  2049. return
  2050. }
  2051. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  2052. if nil != err {
  2053. return
  2054. }
  2055. switch view.LayoutType {
  2056. case av.LayoutTypeTable:
  2057. for _, column := range view.Table.Columns {
  2058. if column.ID == operation.ID {
  2059. column.Pin = operation.Data.(bool)
  2060. break
  2061. }
  2062. }
  2063. }
  2064. err = av.SaveAttributeView(attrView)
  2065. return
  2066. }
  2067. func (tx *Transaction) doSetAttrViewColumnIcon(operation *Operation) (ret *TxErr) {
  2068. err := setAttributeViewColIcon(operation)
  2069. if nil != err {
  2070. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2071. }
  2072. return
  2073. }
  2074. func setAttributeViewColIcon(operation *Operation) (err error) {
  2075. attrView, err := av.ParseAttributeView(operation.AvID)
  2076. if nil != err {
  2077. return
  2078. }
  2079. for _, keyValues := range attrView.KeyValues {
  2080. if keyValues.Key.ID == operation.ID {
  2081. keyValues.Key.Icon = operation.Data.(string)
  2082. break
  2083. }
  2084. }
  2085. err = av.SaveAttributeView(attrView)
  2086. return
  2087. }
  2088. func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) {
  2089. err := sortAttributeViewRow(operation)
  2090. if nil != err {
  2091. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2092. }
  2093. return
  2094. }
  2095. func sortAttributeViewRow(operation *Operation) (err error) {
  2096. if operation.ID == operation.PreviousID {
  2097. // 拖拽到自己的下方,不做任何操作 https://github.com/siyuan-note/siyuan/issues/11048
  2098. return
  2099. }
  2100. attrView, err := av.ParseAttributeView(operation.AvID)
  2101. if nil != err {
  2102. return
  2103. }
  2104. view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
  2105. if nil != err {
  2106. return
  2107. }
  2108. var rowID string
  2109. var idx, previousIndex int
  2110. for i, r := range view.Table.RowIDs {
  2111. if r == operation.ID {
  2112. rowID = r
  2113. idx = i
  2114. break
  2115. }
  2116. }
  2117. if "" == rowID {
  2118. rowID = operation.ID
  2119. view.Table.RowIDs = append(view.Table.RowIDs, rowID)
  2120. idx = len(view.Table.RowIDs) - 1
  2121. }
  2122. switch view.LayoutType {
  2123. case av.LayoutTypeTable:
  2124. view.Table.RowIDs = append(view.Table.RowIDs[:idx], view.Table.RowIDs[idx+1:]...)
  2125. for i, r := range view.Table.RowIDs {
  2126. if r == operation.PreviousID {
  2127. previousIndex = i + 1
  2128. break
  2129. }
  2130. }
  2131. view.Table.RowIDs = util.InsertElem(view.Table.RowIDs, previousIndex, rowID)
  2132. }
  2133. err = av.SaveAttributeView(attrView)
  2134. return
  2135. }
  2136. func (tx *Transaction) doSortAttrViewColumn(operation *Operation) (ret *TxErr) {
  2137. err := SortAttributeViewViewKey(operation.AvID, operation.BlockID, operation.ID, operation.PreviousID)
  2138. if nil != err {
  2139. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2140. }
  2141. return
  2142. }
  2143. func SortAttributeViewViewKey(avID, blockID, keyID, previousKeyID string) (err error) {
  2144. if keyID == previousKeyID {
  2145. // 拖拽到自己的右侧,不做任何操作 https://github.com/siyuan-note/siyuan/issues/11048
  2146. return
  2147. }
  2148. attrView, err := av.ParseAttributeView(avID)
  2149. if nil != err {
  2150. return
  2151. }
  2152. view, err := getAttrViewViewByBlockID(attrView, blockID)
  2153. if nil != err {
  2154. return
  2155. }
  2156. switch view.LayoutType {
  2157. case av.LayoutTypeTable:
  2158. var col *av.ViewTableColumn
  2159. var index, previousIndex int
  2160. for i, column := range view.Table.Columns {
  2161. if column.ID == keyID {
  2162. col = column
  2163. index = i
  2164. break
  2165. }
  2166. }
  2167. if nil == col {
  2168. return
  2169. }
  2170. view.Table.Columns = append(view.Table.Columns[:index], view.Table.Columns[index+1:]...)
  2171. for i, column := range view.Table.Columns {
  2172. if column.ID == previousKeyID {
  2173. previousIndex = i + 1
  2174. break
  2175. }
  2176. }
  2177. view.Table.Columns = util.InsertElem(view.Table.Columns, previousIndex, col)
  2178. }
  2179. err = av.SaveAttributeView(attrView)
  2180. return
  2181. }
  2182. func (tx *Transaction) doSortAttrViewKey(operation *Operation) (ret *TxErr) {
  2183. err := SortAttributeViewKey(operation.AvID, operation.ID, operation.PreviousID)
  2184. if nil != err {
  2185. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2186. }
  2187. return
  2188. }
  2189. func SortAttributeViewKey(avID, keyID, previousKeyID string) (err error) {
  2190. if keyID == previousKeyID {
  2191. return
  2192. }
  2193. attrView, err := av.ParseAttributeView(avID)
  2194. if nil != err {
  2195. return
  2196. }
  2197. refreshAttrViewKeyIDs(attrView)
  2198. var currentKeyID string
  2199. var idx, previousIndex int
  2200. for i, k := range attrView.KeyIDs {
  2201. if k == keyID {
  2202. currentKeyID = k
  2203. idx = i
  2204. break
  2205. }
  2206. }
  2207. if "" == currentKeyID {
  2208. return
  2209. }
  2210. attrView.KeyIDs = append(attrView.KeyIDs[:idx], attrView.KeyIDs[idx+1:]...)
  2211. for i, k := range attrView.KeyIDs {
  2212. if k == previousKeyID {
  2213. previousIndex = i + 1
  2214. break
  2215. }
  2216. }
  2217. attrView.KeyIDs = util.InsertElem(attrView.KeyIDs, previousIndex, currentKeyID)
  2218. err = av.SaveAttributeView(attrView)
  2219. return
  2220. }
  2221. func refreshAttrViewKeyIDs(attrView *av.AttributeView) {
  2222. // 订正 keyIDs 数据
  2223. existKeyIDs := map[string]bool{}
  2224. for _, keyValues := range attrView.KeyValues {
  2225. existKeyIDs[keyValues.Key.ID] = true
  2226. }
  2227. for k, _ := range existKeyIDs {
  2228. if !gulu.Str.Contains(k, attrView.KeyIDs) {
  2229. attrView.KeyIDs = append(attrView.KeyIDs, k)
  2230. }
  2231. }
  2232. var tmp []string
  2233. for _, k := range attrView.KeyIDs {
  2234. if ok := existKeyIDs[k]; ok {
  2235. tmp = append(tmp, k)
  2236. }
  2237. }
  2238. attrView.KeyIDs = tmp
  2239. }
  2240. func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) {
  2241. var icon string
  2242. if nil != operation.Data {
  2243. icon = operation.Data.(string)
  2244. }
  2245. err := AddAttributeViewKey(operation.AvID, operation.ID, operation.Name, operation.Typ, icon, operation.PreviousID)
  2246. if nil != err {
  2247. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2248. }
  2249. return
  2250. }
  2251. func AddAttributeViewKey(avID, keyID, keyName, keyType, keyIcon, previousKeyID string) (err error) {
  2252. attrView, err := av.ParseAttributeView(avID)
  2253. if nil != err {
  2254. return
  2255. }
  2256. keyTyp := av.KeyType(keyType)
  2257. switch keyTyp {
  2258. case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
  2259. av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
  2260. av.KeyTypeRelation, av.KeyTypeRollup, av.KeyTypeLineNumber:
  2261. key := av.NewKey(keyID, keyName, keyIcon, keyTyp)
  2262. if av.KeyTypeRollup == keyTyp {
  2263. key.Rollup = &av.Rollup{Calc: &av.RollupCalc{Operator: av.CalcOperatorNone}}
  2264. }
  2265. attrView.KeyValues = append(attrView.KeyValues, &av.KeyValues{Key: key})
  2266. for _, view := range attrView.Views {
  2267. switch view.LayoutType {
  2268. case av.LayoutTypeTable:
  2269. if "" == previousKeyID {
  2270. view.Table.Columns = append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns...)
  2271. break
  2272. }
  2273. added := false
  2274. for i, column := range view.Table.Columns {
  2275. if column.ID == previousKeyID {
  2276. view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns[i+1:]...)...)
  2277. added = true
  2278. break
  2279. }
  2280. }
  2281. if !added {
  2282. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: key.ID})
  2283. }
  2284. }
  2285. }
  2286. }
  2287. err = av.SaveAttributeView(attrView)
  2288. return
  2289. }
  2290. func (tx *Transaction) doUpdateAttrViewColTemplate(operation *Operation) (ret *TxErr) {
  2291. err := updateAttributeViewColTemplate(operation)
  2292. if nil != err {
  2293. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2294. }
  2295. return
  2296. }
  2297. func updateAttributeViewColTemplate(operation *Operation) (err error) {
  2298. attrView, err := av.ParseAttributeView(operation.AvID)
  2299. if nil != err {
  2300. return
  2301. }
  2302. colType := av.KeyType(operation.Typ)
  2303. switch colType {
  2304. case av.KeyTypeTemplate:
  2305. for _, keyValues := range attrView.KeyValues {
  2306. if keyValues.Key.ID == operation.ID && av.KeyTypeTemplate == keyValues.Key.Type {
  2307. keyValues.Key.Template = operation.Data.(string)
  2308. break
  2309. }
  2310. }
  2311. }
  2312. err = av.SaveAttributeView(attrView)
  2313. return
  2314. }
  2315. func (tx *Transaction) doUpdateAttrViewColNumberFormat(operation *Operation) (ret *TxErr) {
  2316. err := updateAttributeViewColNumberFormat(operation)
  2317. if nil != err {
  2318. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2319. }
  2320. return
  2321. }
  2322. func updateAttributeViewColNumberFormat(operation *Operation) (err error) {
  2323. attrView, err := av.ParseAttributeView(operation.AvID)
  2324. if nil != err {
  2325. return
  2326. }
  2327. colType := av.KeyType(operation.Typ)
  2328. switch colType {
  2329. case av.KeyTypeNumber:
  2330. for _, keyValues := range attrView.KeyValues {
  2331. if keyValues.Key.ID == operation.ID && av.KeyTypeNumber == keyValues.Key.Type {
  2332. keyValues.Key.NumberFormat = av.NumberFormat(operation.Format)
  2333. break
  2334. }
  2335. }
  2336. }
  2337. err = av.SaveAttributeView(attrView)
  2338. return
  2339. }
  2340. func (tx *Transaction) doUpdateAttrViewColumn(operation *Operation) (ret *TxErr) {
  2341. err := updateAttributeViewColumn(operation)
  2342. if nil != err {
  2343. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2344. }
  2345. return
  2346. }
  2347. func updateAttributeViewColumn(operation *Operation) (err error) {
  2348. attrView, err := av.ParseAttributeView(operation.AvID)
  2349. if nil != err {
  2350. return
  2351. }
  2352. colType := av.KeyType(operation.Typ)
  2353. switch colType {
  2354. case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
  2355. av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
  2356. av.KeyTypeRelation, av.KeyTypeRollup, av.KeyTypeLineNumber:
  2357. for _, keyValues := range attrView.KeyValues {
  2358. if keyValues.Key.ID == operation.ID {
  2359. keyValues.Key.Name = strings.TrimSpace(operation.Name)
  2360. keyValues.Key.Type = colType
  2361. for _, value := range keyValues.Values {
  2362. value.Type = colType
  2363. }
  2364. break
  2365. }
  2366. }
  2367. }
  2368. err = av.SaveAttributeView(attrView)
  2369. return
  2370. }
  2371. func (tx *Transaction) doRemoveAttrViewColumn(operation *Operation) (ret *TxErr) {
  2372. err := RemoveAttributeViewKey(operation.AvID, operation.ID)
  2373. if nil != err {
  2374. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2375. }
  2376. return
  2377. }
  2378. func RemoveAttributeViewKey(avID, keyID string) (err error) {
  2379. attrView, err := av.ParseAttributeView(avID)
  2380. if nil != err {
  2381. return
  2382. }
  2383. var removedKey *av.Key
  2384. for i, keyValues := range attrView.KeyValues {
  2385. if keyValues.Key.ID == keyID {
  2386. attrView.KeyValues = append(attrView.KeyValues[:i], attrView.KeyValues[i+1:]...)
  2387. removedKey = keyValues.Key
  2388. break
  2389. }
  2390. }
  2391. if nil != removedKey && av.KeyTypeRelation == removedKey.Type && nil != removedKey.Relation {
  2392. if removedKey.Relation.IsTwoWay {
  2393. // 删除双向关联的目标列
  2394. var destAv *av.AttributeView
  2395. if avID == removedKey.Relation.AvID {
  2396. destAv = attrView
  2397. } else {
  2398. destAv, _ = av.ParseAttributeView(removedKey.Relation.AvID)
  2399. }
  2400. if nil != destAv {
  2401. destAvRelSrcAv := false
  2402. for i, keyValues := range destAv.KeyValues {
  2403. if keyValues.Key.ID == removedKey.Relation.BackKeyID {
  2404. destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...)
  2405. continue
  2406. }
  2407. if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == attrView.ID {
  2408. destAvRelSrcAv = true
  2409. }
  2410. }
  2411. for _, view := range destAv.Views {
  2412. switch view.LayoutType {
  2413. case av.LayoutTypeTable:
  2414. for i, column := range view.Table.Columns {
  2415. if column.ID == removedKey.Relation.BackKeyID {
  2416. view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
  2417. break
  2418. }
  2419. }
  2420. }
  2421. }
  2422. if destAv != attrView {
  2423. av.SaveAttributeView(destAv)
  2424. util.PushReloadAttrView(destAv.ID)
  2425. }
  2426. if !destAvRelSrcAv {
  2427. av.RemoveAvRel(destAv.ID, attrView.ID)
  2428. }
  2429. }
  2430. srcAvRelDestAv := false
  2431. for _, keyValues := range attrView.KeyValues {
  2432. if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation && keyValues.Key.Relation.AvID == removedKey.Relation.AvID {
  2433. srcAvRelDestAv = true
  2434. }
  2435. }
  2436. if !srcAvRelDestAv {
  2437. av.RemoveAvRel(attrView.ID, removedKey.Relation.AvID)
  2438. }
  2439. }
  2440. }
  2441. for _, view := range attrView.Views {
  2442. switch view.LayoutType {
  2443. case av.LayoutTypeTable:
  2444. for i, column := range view.Table.Columns {
  2445. if column.ID == keyID {
  2446. view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
  2447. break
  2448. }
  2449. }
  2450. }
  2451. }
  2452. err = av.SaveAttributeView(attrView)
  2453. return
  2454. }
  2455. func (tx *Transaction) doReplaceAttrViewBlock(operation *Operation) (ret *TxErr) {
  2456. err := replaceAttributeViewBlock(operation, tx)
  2457. if nil != err {
  2458. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  2459. }
  2460. return
  2461. }
  2462. func replaceAttributeViewBlock(operation *Operation, tx *Transaction) (err error) {
  2463. attrView, err := av.ParseAttributeView(operation.AvID)
  2464. if nil != err {
  2465. return
  2466. }
  2467. var node *ast.Node
  2468. if !operation.IsDetached {
  2469. node, _, _ = getNodeByBlockID(tx, operation.NextID)
  2470. }
  2471. // 检查是否已经存在绑定块
  2472. // Improve database primary key binding block https://github.com/siyuan-note/siyuan/issues/10945
  2473. for _, keyValues := range attrView.KeyValues {
  2474. for _, value := range keyValues.Values {
  2475. if value.BlockID == operation.NextID {
  2476. util.PushMsg(Conf.language(242), 3000)
  2477. return
  2478. }
  2479. }
  2480. }
  2481. for _, keyValues := range attrView.KeyValues {
  2482. for _, value := range keyValues.Values {
  2483. if value.BlockID != operation.PreviousID {
  2484. continue
  2485. }
  2486. if av.KeyTypeBlock == value.Type && value.BlockID != operation.NextID {
  2487. // 换绑
  2488. unbindBlockAv(tx, operation.AvID, value.BlockID)
  2489. }
  2490. value.BlockID = operation.NextID
  2491. if av.KeyTypeBlock == value.Type && nil != value.Block {
  2492. value.Block.ID = operation.NextID
  2493. value.IsDetached = operation.IsDetached
  2494. if !operation.IsDetached {
  2495. value.Block.Content = getNodeRefText(node)
  2496. }
  2497. }
  2498. if av.KeyTypeBlock == value.Type && !operation.IsDetached {
  2499. bindBlockAv(tx, operation.AvID, operation.NextID)
  2500. replaceRelationAvValues(operation.AvID, operation.PreviousID, operation.NextID)
  2501. }
  2502. }
  2503. }
  2504. replacedRowID := false
  2505. for _, v := range attrView.Views {
  2506. switch v.LayoutType {
  2507. case av.LayoutTypeTable:
  2508. for i, rowID := range v.Table.RowIDs {
  2509. if rowID == operation.PreviousID {
  2510. v.Table.RowIDs[i] = operation.NextID
  2511. replacedRowID = true
  2512. break
  2513. }
  2514. }
  2515. if !replacedRowID {
  2516. v.Table.RowIDs = append(v.Table.RowIDs, operation.NextID)
  2517. }
  2518. }
  2519. }
  2520. err = av.SaveAttributeView(attrView)
  2521. return
  2522. }
  2523. func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
  2524. err := updateAttributeViewCell(operation, tx)
  2525. if nil != err {
  2526. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2527. }
  2528. return
  2529. }
  2530. func updateAttributeViewCell(operation *Operation, tx *Transaction) (err error) {
  2531. err = UpdateAttributeViewCell(tx, operation.AvID, operation.KeyID, operation.RowID, operation.ID, operation.Data)
  2532. return
  2533. }
  2534. func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string, valueData interface{}) (err error) {
  2535. attrView, err := av.ParseAttributeView(avID)
  2536. if nil != err {
  2537. return
  2538. }
  2539. var blockVal *av.Value
  2540. for _, kv := range attrView.KeyValues {
  2541. if av.KeyTypeBlock == kv.Key.Type {
  2542. for _, v := range kv.Values {
  2543. if rowID == v.Block.ID {
  2544. blockVal = v
  2545. break
  2546. }
  2547. }
  2548. break
  2549. }
  2550. }
  2551. now := time.Now().UnixMilli()
  2552. var val *av.Value
  2553. oldIsDetached := true
  2554. if nil != blockVal {
  2555. oldIsDetached = blockVal.IsDetached
  2556. }
  2557. for _, keyValues := range attrView.KeyValues {
  2558. if keyID != keyValues.Key.ID {
  2559. continue
  2560. }
  2561. for _, value := range keyValues.Values {
  2562. if cellID == value.ID || rowID == value.BlockID {
  2563. val = value
  2564. val.Type = keyValues.Key.Type
  2565. break
  2566. }
  2567. }
  2568. if nil == val {
  2569. val = &av.Value{ID: cellID, KeyID: keyID, BlockID: rowID, Type: keyValues.Key.Type, CreatedAt: now, UpdatedAt: now}
  2570. keyValues.Values = append(keyValues.Values, val)
  2571. }
  2572. break
  2573. }
  2574. isUpdatingBlockKey := av.KeyTypeBlock == val.Type
  2575. oldBoundBlockID := val.BlockID
  2576. var oldRelationBlockIDs []string
  2577. if av.KeyTypeRelation == val.Type {
  2578. if nil != val.Relation {
  2579. for _, bID := range val.Relation.BlockIDs {
  2580. oldRelationBlockIDs = append(oldRelationBlockIDs, bID)
  2581. }
  2582. }
  2583. }
  2584. data, err := gulu.JSON.MarshalJSON(valueData)
  2585. if nil != err {
  2586. return
  2587. }
  2588. if err = gulu.JSON.UnmarshalJSON(data, &val); nil != err {
  2589. return
  2590. }
  2591. key, _ := attrView.GetKey(keyID)
  2592. if av.KeyTypeNumber == val.Type {
  2593. if nil != val.Number && !val.Number.IsNotEmpty {
  2594. val.Number.Content = 0
  2595. val.Number.FormattedContent = ""
  2596. }
  2597. } else if av.KeyTypeDate == val.Type {
  2598. if nil != val.Date && !val.Date.IsNotEmpty {
  2599. val.Date.Content = 0
  2600. val.Date.FormattedContent = ""
  2601. }
  2602. } else if av.KeyTypeSelect == val.Type || av.KeyTypeMSelect == val.Type {
  2603. if nil != key && 0 < len(val.MSelect) {
  2604. // The selection options are inconsistent after pasting data into the database https://github.com/siyuan-note/siyuan/issues/11409
  2605. for _, valOpt := range val.MSelect {
  2606. if opt := key.GetOption(valOpt.Content); nil == opt {
  2607. // 不存在的选项新建保存
  2608. opt = &av.SelectOption{Name: valOpt.Content, Color: valOpt.Color}
  2609. key.Options = append(key.Options, opt)
  2610. } else {
  2611. // 已经存在的选项颜色需要保持不变
  2612. valOpt.Color = opt.Color
  2613. }
  2614. }
  2615. }
  2616. }
  2617. relationChangeMode := 0 // 0:不变(仅排序),1:增加,2:减少
  2618. if av.KeyTypeRelation == val.Type {
  2619. // 关联列得 content 是自动渲染的,所以不需要保存
  2620. val.Relation.Contents = nil
  2621. // 去重
  2622. val.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(val.Relation.BlockIDs)
  2623. // 计算关联变更模式
  2624. if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
  2625. relationChangeMode = 0
  2626. } else {
  2627. if len(oldRelationBlockIDs) > len(val.Relation.BlockIDs) {
  2628. relationChangeMode = 2
  2629. } else {
  2630. relationChangeMode = 1
  2631. }
  2632. }
  2633. }
  2634. // val.IsDetached 只有更新主键的时候才会传入,所以下面需要结合 isUpdatingBlockKey 来判断
  2635. if oldIsDetached {
  2636. // 之前是游离行
  2637. if !val.IsDetached { // 现在绑定了块
  2638. // 将游离行绑定到新建的块上
  2639. bindBlockAv(tx, avID, rowID)
  2640. }
  2641. } else {
  2642. // 之前绑定了块
  2643. if isUpdatingBlockKey { // 正在更新主键
  2644. if val.IsDetached { // 现在是游离行
  2645. // 将绑定的块从属性视图中移除
  2646. unbindBlockAv(tx, avID, rowID)
  2647. } else {
  2648. // 现在绑定了块
  2649. if oldBoundBlockID != val.BlockID { // 之前绑定的块和现在绑定的块不一样
  2650. // 换绑块
  2651. unbindBlockAv(tx, avID, oldBoundBlockID)
  2652. bindBlockAv(tx, avID, val.BlockID)
  2653. } else { // 之前绑定的块和现在绑定的块一样
  2654. // 直接返回,因为锚文本不允许更改
  2655. return
  2656. }
  2657. }
  2658. }
  2659. }
  2660. if nil != blockVal {
  2661. blockVal.Block.Updated = now
  2662. blockVal.SetUpdatedAt(now)
  2663. if isUpdatingBlockKey {
  2664. blockVal.IsDetached = val.IsDetached
  2665. }
  2666. }
  2667. val.SetUpdatedAt(now)
  2668. if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation && key.Relation.IsTwoWay {
  2669. // 双向关联需要同时更新目标字段的值
  2670. var destAv *av.AttributeView
  2671. if avID == key.Relation.AvID {
  2672. destAv = attrView
  2673. } else {
  2674. destAv, _ = av.ParseAttributeView(key.Relation.AvID)
  2675. }
  2676. if nil != destAv {
  2677. // relationChangeMode
  2678. // 0:关联列值不变(仅排序),不影响目标值
  2679. // 1:关联列值增加,增加目标值
  2680. // 2:关联列值减少,减少目标值
  2681. if 1 == relationChangeMode {
  2682. addBlockIDs := val.Relation.BlockIDs
  2683. for _, bID := range oldRelationBlockIDs {
  2684. addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID)
  2685. }
  2686. for _, blockID := range addBlockIDs {
  2687. for _, keyValues := range destAv.KeyValues {
  2688. if keyValues.Key.ID != key.Relation.BackKeyID {
  2689. continue
  2690. }
  2691. destVal := keyValues.GetValue(blockID)
  2692. if nil == destVal {
  2693. destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}, CreatedAt: now, UpdatedAt: now + 1000}
  2694. keyValues.Values = append(keyValues.Values, destVal)
  2695. }
  2696. destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID)
  2697. destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
  2698. break
  2699. }
  2700. }
  2701. } else if 2 == relationChangeMode {
  2702. removeBlockIDs := oldRelationBlockIDs
  2703. for _, bID := range val.Relation.BlockIDs {
  2704. removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID)
  2705. }
  2706. for _, blockID := range removeBlockIDs {
  2707. for _, keyValues := range destAv.KeyValues {
  2708. if keyValues.Key.ID != key.Relation.BackKeyID {
  2709. continue
  2710. }
  2711. for _, value := range keyValues.Values {
  2712. if value.BlockID == blockID {
  2713. value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID)
  2714. value.SetUpdatedAt(now)
  2715. break
  2716. }
  2717. }
  2718. }
  2719. }
  2720. }
  2721. if destAv != attrView {
  2722. av.SaveAttributeView(destAv)
  2723. }
  2724. }
  2725. }
  2726. relatedAvIDs := av.GetSrcAvIDs(avID)
  2727. for _, relatedAvID := range relatedAvIDs {
  2728. util.PushReloadAttrView(relatedAvID)
  2729. }
  2730. if err = av.SaveAttributeView(attrView); nil != err {
  2731. return
  2732. }
  2733. return
  2734. }
  2735. func unbindBlockAv(tx *Transaction, avID, blockID string) {
  2736. node, tree, err := getNodeByBlockID(tx, blockID)
  2737. if nil != err {
  2738. return
  2739. }
  2740. attrs := parse.IAL2Map(node.KramdownIAL)
  2741. if "" == attrs[av.NodeAttrNameAvs] {
  2742. return
  2743. }
  2744. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2745. avIDs = gulu.Str.RemoveElem(avIDs, avID)
  2746. if 0 == len(avIDs) {
  2747. attrs[av.NodeAttrNameAvs] = ""
  2748. } else {
  2749. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2750. }
  2751. avNames := getAvNames(attrs[av.NodeAttrNameAvs])
  2752. if "" != avNames {
  2753. attrs[av.NodeAttrViewNames] = avNames
  2754. }
  2755. if nil != tx {
  2756. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2757. } else {
  2758. err = setNodeAttrs(node, tree, attrs)
  2759. }
  2760. if nil != err {
  2761. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  2762. return
  2763. }
  2764. return
  2765. }
  2766. func bindBlockAv(tx *Transaction, avID, blockID string) {
  2767. node, tree, err := getNodeByBlockID(tx, blockID)
  2768. if nil != err {
  2769. return
  2770. }
  2771. bindBlockAv0(tx, avID, node, tree)
  2772. return
  2773. }
  2774. func bindBlockAv0(tx *Transaction, avID string, node *ast.Node, tree *parse.Tree) {
  2775. attrs := parse.IAL2Map(node.KramdownIAL)
  2776. if "" == attrs[av.NodeAttrNameAvs] {
  2777. attrs[av.NodeAttrNameAvs] = avID
  2778. } else {
  2779. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2780. avIDs = append(avIDs, avID)
  2781. avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
  2782. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2783. }
  2784. avNames := getAvNames(attrs[av.NodeAttrNameAvs])
  2785. if "" != avNames {
  2786. attrs[av.NodeAttrViewNames] = avNames
  2787. }
  2788. var err error
  2789. if nil != tx {
  2790. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2791. } else {
  2792. err = setNodeAttrs(node, tree, attrs)
  2793. }
  2794. if nil != err {
  2795. logging.LogWarnf("set node [%s] attrs failed: %s", node.ID, err)
  2796. return
  2797. }
  2798. return
  2799. }
  2800. func getNodeByBlockID(tx *Transaction, blockID string) (node *ast.Node, tree *parse.Tree, err error) {
  2801. if nil != tx {
  2802. tree, err = tx.loadTree(blockID)
  2803. } else {
  2804. tree, err = LoadTreeByBlockID(blockID)
  2805. }
  2806. if nil != err {
  2807. return
  2808. }
  2809. node = treenode.GetNodeInTree(tree, blockID)
  2810. if nil == node {
  2811. logging.LogWarnf("node [%s] not found in tree [%s]", blockID, tree.ID)
  2812. return
  2813. }
  2814. return
  2815. }
  2816. func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *TxErr) {
  2817. err := updateAttributeViewColumnOptions(operation)
  2818. if nil != err {
  2819. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2820. }
  2821. return
  2822. }
  2823. func updateAttributeViewColumnOptions(operation *Operation) (err error) {
  2824. attrView, err := av.ParseAttributeView(operation.AvID)
  2825. if nil != err {
  2826. return
  2827. }
  2828. jsonData, err := gulu.JSON.MarshalJSON(operation.Data)
  2829. if nil != err {
  2830. return
  2831. }
  2832. options := []*av.SelectOption{}
  2833. if err = gulu.JSON.UnmarshalJSON(jsonData, &options); nil != err {
  2834. return
  2835. }
  2836. for _, keyValues := range attrView.KeyValues {
  2837. if keyValues.Key.ID == operation.ID {
  2838. keyValues.Key.Options = options
  2839. err = av.SaveAttributeView(attrView)
  2840. return
  2841. }
  2842. }
  2843. return
  2844. }
  2845. func (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {
  2846. err := removeAttributeViewColumnOption(operation)
  2847. if nil != err {
  2848. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2849. }
  2850. return
  2851. }
  2852. func removeAttributeViewColumnOption(operation *Operation) (err error) {
  2853. attrView, err := av.ParseAttributeView(operation.AvID)
  2854. if nil != err {
  2855. return
  2856. }
  2857. optName := operation.Data.(string)
  2858. key, err := attrView.GetKey(operation.ID)
  2859. if nil != err {
  2860. return
  2861. }
  2862. for i, opt := range key.Options {
  2863. if optName == opt.Name {
  2864. key.Options = append(key.Options[:i], key.Options[i+1:]...)
  2865. break
  2866. }
  2867. }
  2868. for _, keyValues := range attrView.KeyValues {
  2869. if keyValues.Key.ID != operation.ID {
  2870. continue
  2871. }
  2872. for _, value := range keyValues.Values {
  2873. if nil == value || nil == value.MSelect {
  2874. continue
  2875. }
  2876. for i, opt := range value.MSelect {
  2877. if optName == opt.Content {
  2878. value.MSelect = append(value.MSelect[:i], value.MSelect[i+1:]...)
  2879. break
  2880. }
  2881. }
  2882. }
  2883. break
  2884. }
  2885. err = av.SaveAttributeView(attrView)
  2886. return
  2887. }
  2888. func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) {
  2889. err := updateAttributeViewColumnOption(operation)
  2890. if nil != err {
  2891. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2892. }
  2893. return
  2894. }
  2895. func updateAttributeViewColumnOption(operation *Operation) (err error) {
  2896. attrView, err := av.ParseAttributeView(operation.AvID)
  2897. if nil != err {
  2898. return
  2899. }
  2900. key, err := attrView.GetKey(operation.ID)
  2901. if nil != err {
  2902. return
  2903. }
  2904. data := operation.Data.(map[string]interface{})
  2905. oldName := data["oldName"].(string)
  2906. newName := data["newName"].(string)
  2907. newColor := data["newColor"].(string)
  2908. for i, opt := range key.Options {
  2909. if oldName == opt.Name {
  2910. key.Options[i].Name = newName
  2911. key.Options[i].Color = newColor
  2912. break
  2913. }
  2914. }
  2915. // 如果存在选项对应的值,需要更新值中的选项
  2916. for _, keyValues := range attrView.KeyValues {
  2917. if keyValues.Key.ID != operation.ID {
  2918. continue
  2919. }
  2920. for _, value := range keyValues.Values {
  2921. if nil == value || nil == value.MSelect {
  2922. continue
  2923. }
  2924. for i, opt := range value.MSelect {
  2925. if oldName == opt.Content {
  2926. value.MSelect[i].Content = newName
  2927. value.MSelect[i].Color = newColor
  2928. break
  2929. }
  2930. }
  2931. }
  2932. break
  2933. }
  2934. // 如果存在选项对应的过滤器,需要更新过滤器中设置的选项值
  2935. // Database select field filters follow option editing changes https://github.com/siyuan-note/siyuan/issues/10881
  2936. for _, view := range attrView.Views {
  2937. switch view.LayoutType {
  2938. case av.LayoutTypeTable:
  2939. table := view.Table
  2940. for _, filter := range table.Filters {
  2941. if filter.Column != key.ID {
  2942. continue
  2943. }
  2944. if nil != filter.Value && (av.KeyTypeSelect == filter.Value.Type || av.KeyTypeMSelect == filter.Value.Type) {
  2945. for i, opt := range filter.Value.MSelect {
  2946. if oldName == opt.Content {
  2947. filter.Value.MSelect[i].Content = newName
  2948. filter.Value.MSelect[i].Color = newColor
  2949. break
  2950. }
  2951. }
  2952. }
  2953. }
  2954. }
  2955. }
  2956. err = av.SaveAttributeView(attrView)
  2957. return
  2958. }
  2959. func getAttrViewViewByBlockID(attrView *av.AttributeView, blockID string) (ret *av.View, err error) {
  2960. node, _, _ := getNodeByBlockID(nil, blockID)
  2961. var viewID string
  2962. if nil != node {
  2963. viewID = node.IALAttr(av.NodeAttrView)
  2964. }
  2965. return attrView.GetCurrentView(viewID)
  2966. }
  2967. func getAttrViewName(attrView *av.AttributeView) string {
  2968. ret := strings.TrimSpace(attrView.Name)
  2969. if "" == ret {
  2970. ret = Conf.language(105)
  2971. }
  2972. return ret
  2973. }
  2974. func replaceRelationAvValues(avID, previousID, nextID string) {
  2975. // The database relation fields follow the change after the primary key field is changed https://github.com/siyuan-note/siyuan/issues/11117
  2976. srcAvIDs := av.GetSrcAvIDs(avID)
  2977. for _, srcAvID := range srcAvIDs {
  2978. srcAv, parseErr := av.ParseAttributeView(srcAvID)
  2979. changed := false
  2980. if nil != parseErr {
  2981. continue
  2982. }
  2983. for _, srcKeyValues := range srcAv.KeyValues {
  2984. if av.KeyTypeRelation != srcKeyValues.Key.Type {
  2985. continue
  2986. }
  2987. if nil == srcKeyValues.Key.Relation || avID != srcKeyValues.Key.Relation.AvID {
  2988. continue
  2989. }
  2990. for _, srcValue := range srcKeyValues.Values {
  2991. if nil == srcValue.Relation {
  2992. continue
  2993. }
  2994. srcAvChanged := false
  2995. srcValue.Relation.BlockIDs, srcAvChanged = util.ReplaceStr(srcValue.Relation.BlockIDs, previousID, nextID)
  2996. if srcAvChanged {
  2997. changed = true
  2998. }
  2999. }
  3000. }
  3001. if changed {
  3002. av.SaveAttributeView(srcAv)
  3003. util.PushReloadAttrView(srcAvID)
  3004. }
  3005. }
  3006. }
  3007. func updateBoundBlockAvsAttribute(avIDs []string) {
  3008. // 更新指定 avIDs 中绑定块的 avs 属性
  3009. cachedTrees, saveTrees := map[string]*parse.Tree{}, map[string]*parse.Tree{}
  3010. luteEngine := util.NewLute()
  3011. for _, avID := range avIDs {
  3012. attrView, _ := av.ParseAttributeView(avID)
  3013. if nil == attrView {
  3014. continue
  3015. }
  3016. blockKeyValues := attrView.GetBlockKeyValues()
  3017. for _, blockValue := range blockKeyValues.Values {
  3018. if blockValue.IsDetached {
  3019. continue
  3020. }
  3021. bt := treenode.GetBlockTree(blockValue.BlockID)
  3022. if nil == bt {
  3023. continue
  3024. }
  3025. tree := cachedTrees[bt.RootID]
  3026. if nil == tree {
  3027. tree, _ = filesys.LoadTree(bt.BoxID, bt.Path, luteEngine)
  3028. if nil == tree {
  3029. continue
  3030. }
  3031. cachedTrees[bt.RootID] = tree
  3032. }
  3033. node := treenode.GetNodeInTree(tree, blockValue.BlockID)
  3034. if nil == node {
  3035. continue
  3036. }
  3037. attrs := parse.IAL2Map(node.KramdownIAL)
  3038. if "" == attrs[av.NodeAttrNameAvs] {
  3039. attrs[av.NodeAttrNameAvs] = avID
  3040. } else {
  3041. nodeAvIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  3042. nodeAvIDs = append(nodeAvIDs, avID)
  3043. nodeAvIDs = gulu.Str.RemoveDuplicatedElem(nodeAvIDs)
  3044. attrs[av.NodeAttrNameAvs] = strings.Join(nodeAvIDs, ",")
  3045. saveTrees[bt.RootID] = tree
  3046. }
  3047. avNames := getAvNames(attrs[av.NodeAttrNameAvs])
  3048. if "" != avNames {
  3049. attrs[av.NodeAttrViewNames] = avNames
  3050. }
  3051. oldAttrs, setErr := setNodeAttrs0(node, attrs)
  3052. if nil != setErr {
  3053. continue
  3054. }
  3055. cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL))
  3056. pushBroadcastAttrTransactions(oldAttrs, node)
  3057. }
  3058. }
  3059. for _, saveTree := range saveTrees {
  3060. if treeErr := indexWriteTreeUpsertQueue(saveTree); nil != treeErr {
  3061. logging.LogErrorf("index write tree upsert queue failed: %s", treeErr)
  3062. }
  3063. avNodes := saveTree.Root.ChildrenByType(ast.NodeAttributeView)
  3064. av.BatchUpsertBlockRel(avNodes)
  3065. }
  3066. }