attribute_view.go 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883
  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. "os"
  20. "path/filepath"
  21. "sort"
  22. "strconv"
  23. "strings"
  24. "text/template"
  25. "time"
  26. "github.com/88250/gulu"
  27. "github.com/88250/lute/ast"
  28. "github.com/88250/lute/parse"
  29. "github.com/siyuan-note/dejavu/entity"
  30. "github.com/siyuan-note/filelock"
  31. "github.com/siyuan-note/logging"
  32. "github.com/siyuan-note/siyuan/kernel/av"
  33. "github.com/siyuan-note/siyuan/kernel/sql"
  34. "github.com/siyuan-note/siyuan/kernel/treenode"
  35. "github.com/siyuan-note/siyuan/kernel/util"
  36. )
  37. func GetAttributeViewPrimaryKeyValues(avID string, page, pageSize int) (attributeViewName string, keyValues *av.KeyValues, err error) {
  38. waitForSyncingStorages()
  39. attrView, err := av.ParseAttributeView(avID)
  40. if nil != err {
  41. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  42. return
  43. }
  44. attributeViewName = attrView.Name
  45. keyValues = attrView.GetBlockKeyValues()
  46. // 过滤掉不在视图中的值
  47. tmp := map[string]*av.Value{}
  48. for _, kv := range keyValues.Values {
  49. for _, view := range attrView.Views {
  50. switch view.LayoutType {
  51. case av.LayoutTypeTable:
  52. if !kv.IsDetached {
  53. if nil == treenode.GetBlockTree(kv.BlockID) {
  54. break
  55. }
  56. }
  57. if gulu.Str.Contains(kv.Block.ID, view.Table.RowIDs) {
  58. tmp[kv.Block.ID] = kv
  59. }
  60. }
  61. }
  62. }
  63. keyValues.Values = []*av.Value{}
  64. for _, v := range tmp {
  65. keyValues.Values = append(keyValues.Values, v)
  66. }
  67. if 1 > pageSize {
  68. pageSize = 50
  69. }
  70. start := (page - 1) * pageSize
  71. end := start + pageSize
  72. if len(keyValues.Values) < end {
  73. end = len(keyValues.Values)
  74. }
  75. keyValues.Values = keyValues.Values[start:end]
  76. return
  77. }
  78. func GetAttributeViewFilterSort(id string) (filters []*av.ViewFilter, sorts []*av.ViewSort) {
  79. waitForSyncingStorages()
  80. attrView, err := av.ParseAttributeView(id)
  81. if nil != err {
  82. logging.LogErrorf("parse attribute view [%s] failed: %s", id, err)
  83. return
  84. }
  85. filters = []*av.ViewFilter{}
  86. sorts = []*av.ViewSort{}
  87. for _, view := range attrView.Views {
  88. switch view.LayoutType {
  89. case av.LayoutTypeTable:
  90. filters = view.Table.Filters
  91. sorts = view.Table.Sorts
  92. }
  93. }
  94. return
  95. }
  96. func SearchAttributeViewNonRelationKey(avID, keyword string) (ret []*av.Key) {
  97. waitForSyncingStorages()
  98. ret = []*av.Key{}
  99. attrView, err := av.ParseAttributeView(avID)
  100. if nil != err {
  101. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  102. return
  103. }
  104. for _, keyValues := range attrView.KeyValues {
  105. 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 {
  106. if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) {
  107. ret = append(ret, keyValues.Key)
  108. }
  109. }
  110. }
  111. return
  112. }
  113. func SearchAttributeViewRelationKey(avID, keyword string) (ret []*av.Key) {
  114. waitForSyncingStorages()
  115. ret = []*av.Key{}
  116. attrView, err := av.ParseAttributeView(avID)
  117. if nil != err {
  118. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  119. return
  120. }
  121. for _, keyValues := range attrView.KeyValues {
  122. if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation {
  123. if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) {
  124. ret = append(ret, keyValues.Key)
  125. }
  126. }
  127. }
  128. return
  129. }
  130. func GetAttributeView(avID string) (ret *av.AttributeView) {
  131. waitForSyncingStorages()
  132. ret, _ = av.ParseAttributeView(avID)
  133. return
  134. }
  135. type SearchAttributeViewResult struct {
  136. AvID string `json:"avID"`
  137. AvName string `json:"avName"`
  138. BlockID string `json:"blockID"`
  139. HPath string `json:"hPath"`
  140. }
  141. func SearchAttributeView(keyword string, page int, pageSize int) (ret []*SearchAttributeViewResult, pageCount int) {
  142. waitForSyncingStorages()
  143. ret = []*SearchAttributeViewResult{}
  144. var blocks []*Block
  145. keyword = strings.TrimSpace(keyword)
  146. if "" == keyword {
  147. sqlBlocks := sql.SelectBlocksRawStmt("SELECT * FROM blocks WHERE type = 'av' ORDER BY updated DESC LIMIT 10", page, pageSize)
  148. blocks = fromSQLBlocks(&sqlBlocks, "", 36)
  149. pageCount = 1
  150. } else {
  151. var matchedBlockCount int
  152. blocks, matchedBlockCount, _ = fullTextSearchByKeyword(keyword, "", "", "('av')", "", 36, page, pageSize)
  153. pageCount = (matchedBlockCount + pageSize - 1) / pageSize
  154. }
  155. trees := map[string]*parse.Tree{}
  156. for _, block := range blocks {
  157. tree := trees[block.RootID]
  158. if nil == tree {
  159. tree, _ = loadTreeByBlockID(block.ID)
  160. if nil != tree {
  161. trees[block.RootID] = tree
  162. }
  163. }
  164. if nil == tree {
  165. continue
  166. }
  167. node := treenode.GetNodeInTree(tree, block.ID)
  168. if nil == node {
  169. continue
  170. }
  171. if "" == node.AttributeViewID {
  172. continue
  173. }
  174. avID := node.AttributeViewID
  175. attrView, _ := av.ParseAttributeView(avID)
  176. if nil == attrView {
  177. continue
  178. }
  179. exist := false
  180. for _, result := range ret {
  181. if result.AvID == avID {
  182. exist = true
  183. break
  184. }
  185. }
  186. var hPath string
  187. baseBlock := treenode.GetBlockTreeRootByPath(node.Box, node.Path)
  188. if nil != baseBlock {
  189. hPath = baseBlock.HPath
  190. }
  191. box := Conf.Box(node.Box)
  192. if nil != box {
  193. hPath = box.Name + hPath
  194. }
  195. if !exist {
  196. ret = append(ret, &SearchAttributeViewResult{
  197. AvID: avID,
  198. AvName: attrView.Name,
  199. BlockID: block.ID,
  200. HPath: hPath,
  201. })
  202. }
  203. }
  204. return
  205. }
  206. type BlockAttributeViewKeys struct {
  207. AvID string `json:"avID"`
  208. AvName string `json:"avName"`
  209. BlockIDs []string `json:"blockIDs"`
  210. KeyValues []*av.KeyValues `json:"keyValues"`
  211. }
  212. func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
  213. waitForSyncingStorages()
  214. ret = []*BlockAttributeViewKeys{}
  215. attrs := GetBlockAttrsWithoutWaitWriting(blockID)
  216. avs := attrs[av.NodeAttrNameAvs]
  217. if "" == avs {
  218. return
  219. }
  220. avIDs := strings.Split(avs, ",")
  221. for _, avID := range avIDs {
  222. attrView, err := av.ParseAttributeView(avID)
  223. if nil != err {
  224. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  225. return
  226. }
  227. if 1 > len(attrView.Views) {
  228. err = av.ErrViewNotFound
  229. return
  230. }
  231. var keyValues []*av.KeyValues
  232. for _, kv := range attrView.KeyValues {
  233. kValues := &av.KeyValues{Key: kv.Key}
  234. for _, v := range kv.Values {
  235. if v.BlockID == blockID {
  236. kValues.Values = append(kValues.Values, v)
  237. }
  238. }
  239. switch kValues.Key.Type {
  240. case av.KeyTypeRollup:
  241. 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{}}})
  242. case av.KeyTypeTemplate:
  243. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: ""}})
  244. case av.KeyTypeCreated:
  245. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeCreated})
  246. case av.KeyTypeUpdated:
  247. kValues.Values = append(kValues.Values, &av.Value{ID: ast.NewNodeID(), KeyID: kValues.Key.ID, BlockID: blockID, Type: av.KeyTypeUpdated})
  248. }
  249. if 0 < len(kValues.Values) {
  250. keyValues = append(keyValues, kValues)
  251. } else {
  252. // 如果没有值,那么就补一个默认值
  253. kValues.Values = append(kValues.Values, treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.ID, blockID, kv.Key.Type))
  254. keyValues = append(keyValues, kValues)
  255. }
  256. }
  257. // 渲染自动生成的列值,比如模板列、关联列、汇总列、创建时间列和更新时间列
  258. // 先处理关联列、汇总列、创建时间列和更新时间列
  259. for _, kv := range keyValues {
  260. switch kv.Key.Type {
  261. case av.KeyTypeRollup:
  262. if nil == kv.Key.Rollup {
  263. break
  264. }
  265. relKey, _ := attrView.GetKey(kv.Key.Rollup.RelationKeyID)
  266. if nil == relKey {
  267. break
  268. }
  269. relVal := attrView.GetValue(kv.Key.Rollup.RelationKeyID, kv.Values[0].BlockID)
  270. if nil != relVal && nil != relVal.Relation {
  271. destAv, _ := av.ParseAttributeView(relKey.Relation.AvID)
  272. destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID)
  273. if nil != destAv && nil != destKey {
  274. for _, bID := range relVal.Relation.BlockIDs {
  275. destVal := destAv.GetValue(kv.Key.Rollup.KeyID, bID)
  276. if nil == destVal {
  277. destVal = treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.Rollup.KeyID, blockID, destKey.Type)
  278. }
  279. if av.KeyTypeNumber == destKey.Type {
  280. destVal.Number.Format = destKey.NumberFormat
  281. destVal.Number.FormatNumber()
  282. }
  283. kv.Values[0].Rollup.Contents = append(kv.Values[0].Rollup.Contents, destVal.Clone())
  284. }
  285. kv.Values[0].Rollup.RenderContents(kv.Key.Rollup.Calc, destKey)
  286. }
  287. }
  288. case av.KeyTypeRelation:
  289. if nil == kv.Key.Relation {
  290. break
  291. }
  292. destAv, _ := av.ParseAttributeView(kv.Key.Relation.AvID)
  293. if nil == destAv {
  294. break
  295. }
  296. blocks := map[string]string{}
  297. for _, blockValue := range destAv.GetBlockKeyValues().Values {
  298. blocks[blockValue.BlockID] = blockValue.Block.Content
  299. }
  300. for _, bID := range kv.Values[0].Relation.BlockIDs {
  301. kv.Values[0].Relation.Contents = append(kv.Values[0].Relation.Contents, blocks[bID])
  302. }
  303. case av.KeyTypeCreated:
  304. createdStr := blockID[:len("20060102150405")]
  305. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  306. if nil == parseErr {
  307. kv.Values[0].Created = av.NewFormattedValueCreated(created.UnixMilli(), 0, av.CreatedFormatNone)
  308. kv.Values[0].Created.IsNotEmpty = true
  309. } else {
  310. logging.LogWarnf("parse created [%s] failed: %s", createdStr, parseErr)
  311. kv.Values[0].Created = av.NewFormattedValueCreated(time.Now().UnixMilli(), 0, av.CreatedFormatNone)
  312. }
  313. case av.KeyTypeUpdated:
  314. ial := GetBlockAttrsWithoutWaitWriting(blockID)
  315. updatedStr := ial["updated"]
  316. updated, parseErr := time.ParseInLocation("20060102150405", updatedStr, time.Local)
  317. if nil == parseErr {
  318. kv.Values[0].Updated = av.NewFormattedValueUpdated(updated.UnixMilli(), 0, av.UpdatedFormatNone)
  319. kv.Values[0].Updated.IsNotEmpty = true
  320. } else {
  321. logging.LogWarnf("parse updated [%s] failed: %s", updatedStr, parseErr)
  322. kv.Values[0].Updated = av.NewFormattedValueUpdated(time.Now().UnixMilli(), 0, av.UpdatedFormatNone)
  323. }
  324. }
  325. }
  326. // 再处理模板列
  327. for _, kv := range keyValues {
  328. switch kv.Key.Type {
  329. case av.KeyTypeTemplate:
  330. if 0 < len(kv.Values) {
  331. ial := map[string]string{}
  332. block := getRowBlockValue(keyValues)
  333. if nil != block && !block.IsDetached {
  334. ial = GetBlockAttrsWithoutWaitWriting(blockID)
  335. }
  336. kv.Values[0].Template.Content = renderTemplateCol(ial, kv.Key.Template, keyValues)
  337. }
  338. }
  339. }
  340. // Attribute Panel - Database sort attributes by view column order https://github.com/siyuan-note/siyuan/issues/9319
  341. view, _ := attrView.GetCurrentView()
  342. if nil != view {
  343. sorts := map[string]int{}
  344. for i, col := range view.Table.Columns {
  345. sorts[col.ID] = i
  346. }
  347. sort.Slice(keyValues, func(i, j int) bool {
  348. return sorts[keyValues[i].Key.ID] < sorts[keyValues[j].Key.ID]
  349. })
  350. }
  351. blockIDs := av.GetMirrorBlockIDs(avID)
  352. if 1 > len(blockIDs) {
  353. // 老数据兼容处理
  354. avBts := treenode.GetBlockTreesByType("av")
  355. for _, avBt := range avBts {
  356. if nil == avBt {
  357. continue
  358. }
  359. tree, _ := loadTreeByBlockID(avBt.ID)
  360. if nil == tree {
  361. continue
  362. }
  363. node := treenode.GetNodeInTree(tree, avBt.ID)
  364. if nil == node {
  365. continue
  366. }
  367. if avID == node.AttributeViewID {
  368. blockIDs = append(blockIDs, avBt.ID)
  369. }
  370. }
  371. if 1 > len(blockIDs) {
  372. tree, _ := loadTreeByBlockID(blockID)
  373. if nil != tree {
  374. node := treenode.GetNodeInTree(tree, blockID)
  375. if nil != node {
  376. if removeErr := removeNodeAvID(node, avID, nil, tree); nil != removeErr {
  377. logging.LogErrorf("remove node avID [%s] failed: %s", avID, removeErr)
  378. }
  379. }
  380. }
  381. continue
  382. }
  383. blockIDs = gulu.Str.RemoveDuplicatedElem(blockIDs)
  384. for _, blockID := range blockIDs {
  385. av.UpsertBlockRel(avID, blockID)
  386. }
  387. }
  388. ret = append(ret, &BlockAttributeViewKeys{
  389. AvID: avID,
  390. AvName: attrView.Name,
  391. BlockIDs: blockIDs,
  392. KeyValues: keyValues,
  393. })
  394. }
  395. return
  396. }
  397. func RenderRepoSnapshotAttributeView(indexID, avID string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  398. repo, err := newRepository()
  399. if nil != err {
  400. return
  401. }
  402. index, err := repo.GetIndex(indexID)
  403. if nil != err {
  404. return
  405. }
  406. files, err := repo.GetFiles(index)
  407. if nil != err {
  408. return
  409. }
  410. var avFile *entity.File
  411. for _, f := range files {
  412. if "/storage/av/"+avID+".json" == f.Path {
  413. avFile = f
  414. break
  415. }
  416. }
  417. if nil == avFile {
  418. attrView = av.NewAttributeView(avID)
  419. } else {
  420. data, readErr := repo.OpenFile(avFile)
  421. if nil != readErr {
  422. logging.LogErrorf("read attribute view [%s] failed: %s", avID, readErr)
  423. return
  424. }
  425. attrView = &av.AttributeView{}
  426. if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err {
  427. logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
  428. return
  429. }
  430. }
  431. viewable, err = renderAttributeView(attrView, "", 1, -1)
  432. return
  433. }
  434. func RenderHistoryAttributeView(avID, created string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  435. createdUnix, parseErr := strconv.ParseInt(created, 10, 64)
  436. if nil != parseErr {
  437. logging.LogErrorf("parse created [%s] failed: %s", created, parseErr)
  438. return
  439. }
  440. dirPrefix := time.Unix(createdUnix, 0).Format("2006-01-02-150405")
  441. globPath := filepath.Join(util.HistoryDir, dirPrefix+"*")
  442. matches, err := filepath.Glob(globPath)
  443. if nil != err {
  444. logging.LogErrorf("glob [%s] failed: %s", globPath, err)
  445. return
  446. }
  447. if 1 > len(matches) {
  448. return
  449. }
  450. historyDir := matches[0]
  451. avJSONPath := filepath.Join(historyDir, "storage", "av", avID+".json")
  452. if !gulu.File.IsExist(avJSONPath) {
  453. avJSONPath = filepath.Join(util.DataDir, "storage", "av", avID+".json")
  454. }
  455. if !gulu.File.IsExist(avJSONPath) {
  456. attrView = av.NewAttributeView(avID)
  457. } else {
  458. data, readErr := os.ReadFile(avJSONPath)
  459. if nil != readErr {
  460. logging.LogErrorf("read attribute view [%s] failed: %s", avID, readErr)
  461. return
  462. }
  463. attrView = &av.AttributeView{}
  464. if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err {
  465. logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
  466. return
  467. }
  468. }
  469. viewable, err = renderAttributeView(attrView, "", 1, -1)
  470. return
  471. }
  472. func RenderAttributeView(avID, viewID string, page, pageSize int) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  473. waitForSyncingStorages()
  474. if avJSONPath := av.GetAttributeViewDataPath(avID); !filelock.IsExist(avJSONPath) {
  475. attrView = av.NewAttributeView(avID)
  476. if err = av.SaveAttributeView(attrView); nil != err {
  477. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  478. return
  479. }
  480. }
  481. attrView, err = av.ParseAttributeView(avID)
  482. if nil != err {
  483. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  484. return
  485. }
  486. viewable, err = renderAttributeView(attrView, viewID, page, pageSize)
  487. return
  488. }
  489. func renderAttributeView(attrView *av.AttributeView, viewID string, page, pageSize int) (viewable av.Viewable, err error) {
  490. if 1 > len(attrView.Views) {
  491. view, _ := av.NewTableViewWithBlockKey(ast.NewNodeID())
  492. attrView.Views = append(attrView.Views, view)
  493. attrView.ViewID = view.ID
  494. if err = av.SaveAttributeView(attrView); nil != err {
  495. logging.LogErrorf("save attribute view [%s] failed: %s", attrView.ID, err)
  496. return
  497. }
  498. }
  499. var view *av.View
  500. if "" != viewID {
  501. view = attrView.GetView(viewID)
  502. if nil != view && viewID != attrView.ViewID {
  503. attrView.ViewID = viewID
  504. if err = av.SaveAttributeView(attrView); nil != err {
  505. logging.LogErrorf("save attribute view [%s] failed: %s", attrView.ID, err)
  506. return
  507. }
  508. }
  509. } else {
  510. if "" != attrView.ViewID {
  511. view, _ = attrView.GetCurrentView()
  512. }
  513. }
  514. if nil == view {
  515. view = attrView.Views[0]
  516. }
  517. // 做一些数据兼容和订正处理,保存的时候也会做 av.SaveAttributeView()
  518. currentTimeMillis := util.CurrentTimeMillis()
  519. for _, kv := range attrView.KeyValues {
  520. switch kv.Key.Type {
  521. case av.KeyTypeBlock: // 补全 block 的创建时间和更新时间
  522. for _, v := range kv.Values {
  523. if 0 == v.Block.Created {
  524. if "" == v.Block.ID {
  525. v.Block.ID = v.BlockID
  526. if "" == v.Block.ID {
  527. v.Block.ID = ast.NewNodeID()
  528. v.BlockID = v.Block.ID
  529. }
  530. }
  531. createdStr := v.Block.ID[:len("20060102150405")]
  532. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  533. if nil == parseErr {
  534. v.Block.Created = created.UnixMilli()
  535. } else {
  536. v.Block.Created = currentTimeMillis
  537. }
  538. }
  539. if 0 == v.Block.Updated {
  540. v.Block.Updated = currentTimeMillis
  541. }
  542. }
  543. }
  544. }
  545. switch view.LayoutType {
  546. case av.LayoutTypeTable:
  547. // 列删除以后需要删除设置的过滤和排序
  548. tmpFilters := []*av.ViewFilter{}
  549. for _, f := range view.Table.Filters {
  550. if k, _ := attrView.GetKey(f.Column); nil != k {
  551. tmpFilters = append(tmpFilters, f)
  552. }
  553. }
  554. view.Table.Filters = tmpFilters
  555. tmpSorts := []*av.ViewSort{}
  556. for _, s := range view.Table.Sorts {
  557. if k, _ := attrView.GetKey(s.Column); nil != k {
  558. tmpSorts = append(tmpSorts, s)
  559. }
  560. }
  561. view.Table.Sorts = tmpSorts
  562. viewable, err = renderAttributeViewTable(attrView, view)
  563. }
  564. viewable.FilterRows(attrView)
  565. viewable.SortRows()
  566. viewable.CalcCols()
  567. // 分页
  568. switch viewable.GetType() {
  569. case av.LayoutTypeTable:
  570. table := viewable.(*av.Table)
  571. table.RowCount = len(table.Rows)
  572. if 1 > view.Table.PageSize {
  573. view.Table.PageSize = 50
  574. }
  575. table.PageSize = view.Table.PageSize
  576. if 1 > pageSize {
  577. pageSize = table.PageSize
  578. }
  579. start := (page - 1) * pageSize
  580. end := start + pageSize
  581. if len(table.Rows) < end {
  582. end = len(table.Rows)
  583. }
  584. table.Rows = table.Rows[start:end]
  585. }
  586. return
  587. }
  588. func renderTemplateCol(ial map[string]string, tplContent string, rowValues []*av.KeyValues) string {
  589. if "" == ial["id"] {
  590. block := getRowBlockValue(rowValues)
  591. if nil != block && nil != block.Block {
  592. ial["id"] = block.Block.ID
  593. }
  594. }
  595. if "" == ial["updated"] {
  596. block := getRowBlockValue(rowValues)
  597. if nil != block && nil != block.Block {
  598. ial["updated"] = time.UnixMilli(block.Block.Updated).Format("20060102150405")
  599. }
  600. }
  601. goTpl := template.New("").Delims(".action{", "}")
  602. tplFuncMap := util.BuiltInTemplateFuncs()
  603. SQLTemplateFuncs(&tplFuncMap)
  604. goTpl = goTpl.Funcs(tplFuncMap)
  605. tpl, tplErr := goTpl.Parse(tplContent)
  606. if nil != tplErr {
  607. logging.LogWarnf("parse template [%s] failed: %s", tplContent, tplErr)
  608. return ""
  609. }
  610. buf := &bytes.Buffer{}
  611. dataModel := map[string]interface{}{} // 复制一份 IAL 以避免修改原始数据
  612. for k, v := range ial {
  613. dataModel[k] = v
  614. // Database template column supports `created` and `updated` built-in variables https://github.com/siyuan-note/siyuan/issues/9364
  615. createdStr := ial["id"]
  616. if "" != createdStr {
  617. createdStr = createdStr[:len("20060102150405")]
  618. }
  619. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  620. if nil == parseErr {
  621. dataModel["created"] = created
  622. } else {
  623. logging.LogWarnf("parse created [%s] failed: %s", createdStr, parseErr)
  624. dataModel["created"] = time.Now()
  625. }
  626. updatedStr := ial["updated"]
  627. updated, parseErr := time.ParseInLocation("20060102150405", updatedStr, time.Local)
  628. if nil == parseErr {
  629. dataModel["updated"] = updated
  630. } else {
  631. dataModel["updated"] = time.Now()
  632. }
  633. }
  634. for _, rowValue := range rowValues {
  635. if 0 < len(rowValue.Values) {
  636. v := rowValue.Values[0]
  637. if av.KeyTypeNumber == v.Type {
  638. dataModel[rowValue.Key.Name] = v.Number.Content
  639. } else if av.KeyTypeDate == v.Type {
  640. dataModel[rowValue.Key.Name] = time.UnixMilli(v.Date.Content)
  641. } else {
  642. dataModel[rowValue.Key.Name] = v.String()
  643. }
  644. }
  645. }
  646. if err := tpl.Execute(buf, dataModel); nil != err {
  647. logging.LogWarnf("execute template [%s] failed: %s", tplContent, err)
  648. }
  649. return buf.String()
  650. }
  651. func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) {
  652. ret = &av.Table{
  653. ID: view.ID,
  654. Icon: view.Icon,
  655. Name: view.Name,
  656. Columns: []*av.TableColumn{},
  657. Rows: []*av.TableRow{},
  658. Filters: view.Table.Filters,
  659. Sorts: view.Table.Sorts,
  660. }
  661. // 组装列
  662. for _, col := range view.Table.Columns {
  663. key, getErr := attrView.GetKey(col.ID)
  664. if nil != getErr {
  665. err = getErr
  666. return
  667. }
  668. ret.Columns = append(ret.Columns, &av.TableColumn{
  669. ID: key.ID,
  670. Name: key.Name,
  671. Type: key.Type,
  672. Icon: key.Icon,
  673. Options: key.Options,
  674. NumberFormat: key.NumberFormat,
  675. Template: key.Template,
  676. Relation: key.Relation,
  677. Rollup: key.Rollup,
  678. Wrap: col.Wrap,
  679. Hidden: col.Hidden,
  680. Width: col.Width,
  681. Pin: col.Pin,
  682. Calc: col.Calc,
  683. })
  684. }
  685. // 生成行
  686. rows := map[string][]*av.KeyValues{}
  687. for _, keyValues := range attrView.KeyValues {
  688. for _, val := range keyValues.Values {
  689. values := rows[val.BlockID]
  690. if nil == values {
  691. values = []*av.KeyValues{{Key: keyValues.Key, Values: []*av.Value{val}}}
  692. } else {
  693. values = append(values, &av.KeyValues{Key: keyValues.Key, Values: []*av.Value{val}})
  694. }
  695. rows[val.BlockID] = values
  696. }
  697. // 数据订正,补全关联
  698. if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation {
  699. av.UpsertAvBackRel(attrView.ID, keyValues.Key.Relation.AvID)
  700. if keyValues.Key.Relation.IsTwoWay {
  701. av.UpsertAvBackRel(keyValues.Key.Relation.AvID, attrView.ID)
  702. }
  703. }
  704. }
  705. // 过滤掉不存在的行
  706. var notFound []string
  707. for blockID, keyValues := range rows {
  708. blockValue := getRowBlockValue(keyValues)
  709. if nil == blockValue {
  710. notFound = append(notFound, blockID)
  711. continue
  712. }
  713. if blockValue.IsDetached {
  714. continue
  715. }
  716. if nil != blockValue.Block && "" == blockValue.Block.ID {
  717. notFound = append(notFound, blockID)
  718. continue
  719. }
  720. if treenode.GetBlockTree(blockID) == nil {
  721. notFound = append(notFound, blockID)
  722. }
  723. }
  724. for _, blockID := range notFound {
  725. delete(rows, blockID)
  726. }
  727. // 生成行单元格
  728. for rowID, row := range rows {
  729. var tableRow av.TableRow
  730. for _, col := range ret.Columns {
  731. var tableCell *av.TableCell
  732. for _, keyValues := range row {
  733. if keyValues.Key.ID == col.ID {
  734. tableCell = &av.TableCell{
  735. ID: keyValues.Values[0].ID,
  736. Value: keyValues.Values[0],
  737. ValueType: col.Type,
  738. }
  739. break
  740. }
  741. }
  742. if nil == tableCell {
  743. tableCell = &av.TableCell{
  744. ID: ast.NewNodeID(),
  745. ValueType: col.Type,
  746. }
  747. }
  748. tableRow.ID = rowID
  749. switch tableCell.ValueType {
  750. case av.KeyTypeNumber: // 格式化数字
  751. if nil != tableCell.Value && nil != tableCell.Value.Number && tableCell.Value.Number.IsNotEmpty {
  752. tableCell.Value.Number.Format = col.NumberFormat
  753. tableCell.Value.Number.FormatNumber()
  754. }
  755. case av.KeyTypeTemplate: // 渲染模板列
  756. tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: col.Template}}
  757. case av.KeyTypeCreated: // 填充创建时间列值,后面再渲染
  758. tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeCreated}
  759. case av.KeyTypeUpdated: // 填充更新时间列值,后面再渲染
  760. tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeUpdated}
  761. case av.KeyTypeRelation: // 清空关联列值,后面再渲染 https://ld246.com/article/1703831044435
  762. if nil != tableCell.Value && nil != tableCell.Value.Relation {
  763. tableCell.Value.Relation.Contents = nil
  764. }
  765. }
  766. treenode.FillAttributeViewTableCellNilValue(tableCell, rowID, col.ID)
  767. tableRow.Cells = append(tableRow.Cells, tableCell)
  768. }
  769. ret.Rows = append(ret.Rows, &tableRow)
  770. }
  771. // 渲染自动生成的列值,比如关联列、汇总列、创建时间列和更新时间列
  772. for _, row := range ret.Rows {
  773. for _, cell := range row.Cells {
  774. switch cell.ValueType {
  775. case av.KeyTypeRollup: // 渲染汇总列
  776. rollupKey, _ := attrView.GetKey(cell.Value.KeyID)
  777. if nil == rollupKey || nil == rollupKey.Rollup {
  778. break
  779. }
  780. relKey, _ := attrView.GetKey(rollupKey.Rollup.RelationKeyID)
  781. if nil == relKey || nil == relKey.Relation {
  782. break
  783. }
  784. relVal := attrView.GetValue(relKey.ID, row.ID)
  785. if nil == relVal || nil == relVal.Relation {
  786. break
  787. }
  788. destAv, _ := av.ParseAttributeView(relKey.Relation.AvID)
  789. if nil == destAv {
  790. break
  791. }
  792. destKey, _ := destAv.GetKey(rollupKey.Rollup.KeyID)
  793. if nil == destKey {
  794. continue
  795. }
  796. for _, blockID := range relVal.Relation.BlockIDs {
  797. destVal := destAv.GetValue(rollupKey.Rollup.KeyID, blockID)
  798. if nil == destVal {
  799. destVal = treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), rollupKey.Rollup.KeyID, blockID, destKey.Type)
  800. }
  801. if av.KeyTypeNumber == destKey.Type {
  802. destVal.Number.Format = destKey.NumberFormat
  803. destVal.Number.FormatNumber()
  804. }
  805. cell.Value.Rollup.Contents = append(cell.Value.Rollup.Contents, destVal.Clone())
  806. }
  807. cell.Value.Rollup.RenderContents(rollupKey.Rollup.Calc, destKey)
  808. // 将汇总列的值保存到 rows 中,后续渲染模板列的时候会用到,下同
  809. // Database table view template columns support reading relation, rollup, created and updated columns https://github.com/siyuan-note/siyuan/issues/10442
  810. keyValues := rows[row.ID]
  811. keyValues = append(keyValues, &av.KeyValues{Key: rollupKey, Values: []*av.Value{{ID: cell.Value.ID, KeyID: rollupKey.ID, BlockID: row.ID, Type: av.KeyTypeRollup, Rollup: cell.Value.Rollup}}})
  812. rows[row.ID] = keyValues
  813. case av.KeyTypeRelation: // 渲染关联列
  814. relKey, _ := attrView.GetKey(cell.Value.KeyID)
  815. if nil != relKey && nil != relKey.Relation {
  816. destAv, _ := av.ParseAttributeView(relKey.Relation.AvID)
  817. if nil != destAv {
  818. blocks := map[string]string{}
  819. for _, blockValue := range destAv.GetBlockKeyValues().Values {
  820. blocks[blockValue.BlockID] = blockValue.Block.Content
  821. }
  822. for _, blockID := range cell.Value.Relation.BlockIDs {
  823. cell.Value.Relation.Contents = append(cell.Value.Relation.Contents, blocks[blockID])
  824. }
  825. }
  826. }
  827. keyValues := rows[row.ID]
  828. keyValues = append(keyValues, &av.KeyValues{Key: relKey, Values: []*av.Value{{ID: cell.Value.ID, KeyID: relKey.ID, BlockID: row.ID, Type: av.KeyTypeRelation, Relation: cell.Value.Relation}}})
  829. rows[row.ID] = keyValues
  830. case av.KeyTypeCreated: // 渲染创建时间
  831. createdStr := row.ID[:len("20060102150405")]
  832. created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local)
  833. if nil == parseErr {
  834. cell.Value.Created = av.NewFormattedValueCreated(created.UnixMilli(), 0, av.CreatedFormatNone)
  835. cell.Value.Created.IsNotEmpty = true
  836. } else {
  837. cell.Value.Created = av.NewFormattedValueCreated(time.Now().UnixMilli(), 0, av.CreatedFormatNone)
  838. }
  839. keyValues := rows[row.ID]
  840. createdKey, _ := attrView.GetKey(cell.Value.KeyID)
  841. keyValues = append(keyValues, &av.KeyValues{Key: createdKey, Values: []*av.Value{{ID: cell.Value.ID, KeyID: createdKey.ID, BlockID: row.ID, Type: av.KeyTypeCreated, Created: cell.Value.Created}}})
  842. rows[row.ID] = keyValues
  843. case av.KeyTypeUpdated: // 渲染更新时间
  844. ial := map[string]string{}
  845. block := row.GetBlockValue()
  846. if nil != block && !block.IsDetached {
  847. ial = GetBlockAttrsWithoutWaitWriting(row.ID)
  848. }
  849. updatedStr := ial["updated"]
  850. if "" == updatedStr && nil != block {
  851. cell.Value.Updated = av.NewFormattedValueUpdated(block.Block.Updated, 0, av.UpdatedFormatNone)
  852. cell.Value.Updated.IsNotEmpty = true
  853. } else {
  854. updated, parseErr := time.ParseInLocation("20060102150405", updatedStr, time.Local)
  855. if nil == parseErr {
  856. cell.Value.Updated = av.NewFormattedValueUpdated(updated.UnixMilli(), 0, av.UpdatedFormatNone)
  857. cell.Value.Updated.IsNotEmpty = true
  858. } else {
  859. cell.Value.Updated = av.NewFormattedValueUpdated(time.Now().UnixMilli(), 0, av.UpdatedFormatNone)
  860. }
  861. }
  862. keyValues := rows[row.ID]
  863. updatedKey, _ := attrView.GetKey(cell.Value.KeyID)
  864. keyValues = append(keyValues, &av.KeyValues{Key: updatedKey, Values: []*av.Value{{ID: cell.Value.ID, KeyID: updatedKey.ID, BlockID: row.ID, Type: av.KeyTypeUpdated, Updated: cell.Value.Updated}}})
  865. rows[row.ID] = keyValues
  866. }
  867. }
  868. }
  869. // 最后单独渲染模板列,这样模板列就可以使用汇总、关联、创建时间和更新时间列的值了
  870. // Database table view template columns support reading relation, rollup, created and updated columns https://github.com/siyuan-note/siyuan/issues/10442
  871. for _, row := range ret.Rows {
  872. for _, cell := range row.Cells {
  873. switch cell.ValueType {
  874. case av.KeyTypeTemplate: // 渲染模板列
  875. keyValues := rows[row.ID]
  876. ial := map[string]string{}
  877. block := row.GetBlockValue()
  878. if nil != block && !block.IsDetached {
  879. ial = GetBlockAttrsWithoutWaitWriting(row.ID)
  880. }
  881. content := renderTemplateCol(ial, cell.Value.Template.Content, keyValues)
  882. cell.Value.Template.Content = content
  883. }
  884. }
  885. }
  886. // 自定义排序
  887. sortRowIDs := map[string]int{}
  888. if 0 < len(view.Table.RowIDs) {
  889. for i, rowID := range view.Table.RowIDs {
  890. sortRowIDs[rowID] = i
  891. }
  892. }
  893. sort.Slice(ret.Rows, func(i, j int) bool {
  894. iv := sortRowIDs[ret.Rows[i].ID]
  895. jv := sortRowIDs[ret.Rows[j].ID]
  896. if iv == jv {
  897. return ret.Rows[i].ID < ret.Rows[j].ID
  898. }
  899. return iv < jv
  900. })
  901. return
  902. }
  903. func getRowBlockValue(keyValues []*av.KeyValues) (ret *av.Value) {
  904. for _, kv := range keyValues {
  905. if av.KeyTypeBlock == kv.Key.Type && 0 < len(kv.Values) {
  906. ret = kv.Values[0]
  907. break
  908. }
  909. }
  910. return
  911. }
  912. func (tx *Transaction) doUpdateAttrViewColRollup(operation *Operation) (ret *TxErr) {
  913. err := updateAttributeViewColRollup(operation)
  914. if nil != err {
  915. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  916. }
  917. return
  918. }
  919. func updateAttributeViewColRollup(operation *Operation) (err error) {
  920. // operation.AvID 汇总列所在 av
  921. // operation.ID 汇总列 ID
  922. // operation.ParentID 汇总列基于的关联列 ID
  923. // operation.KeyID 目标列 ID
  924. // operation.Data 计算方式
  925. attrView, err := av.ParseAttributeView(operation.AvID)
  926. if nil != err {
  927. return
  928. }
  929. rollUpKey, _ := attrView.GetKey(operation.ID)
  930. if nil == rollUpKey {
  931. return
  932. }
  933. rollUpKey.Rollup = &av.Rollup{
  934. RelationKeyID: operation.ParentID,
  935. KeyID: operation.KeyID,
  936. }
  937. if nil != operation.Data {
  938. data := operation.Data.(map[string]interface{})
  939. if nil != data["calc"] {
  940. calcData, jsonErr := gulu.JSON.MarshalJSON(data["calc"])
  941. if nil != jsonErr {
  942. err = jsonErr
  943. return
  944. }
  945. if jsonErr = gulu.JSON.UnmarshalJSON(calcData, &rollUpKey.Rollup.Calc); nil != jsonErr {
  946. err = jsonErr
  947. return
  948. }
  949. }
  950. }
  951. err = av.SaveAttributeView(attrView)
  952. return
  953. }
  954. func (tx *Transaction) doUpdateAttrViewColRelation(operation *Operation) (ret *TxErr) {
  955. err := updateAttributeViewColRelation(operation)
  956. if nil != err {
  957. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  958. }
  959. return
  960. }
  961. func updateAttributeViewColRelation(operation *Operation) (err error) {
  962. // operation.AvID 源 avID
  963. // operation.ID 目标 avID
  964. // operation.KeyID 源 av 关联列 ID
  965. // operation.IsTwoWay 是否双向关联
  966. // operation.BackRelationKeyID 双向关联的目标关联列 ID
  967. // operation.Name 双向关联的目标关联列名称
  968. // operation.Format 源 av 关联列名称
  969. srcAv, err := av.ParseAttributeView(operation.AvID)
  970. if nil != err {
  971. return
  972. }
  973. destAv, err := av.ParseAttributeView(operation.ID)
  974. if nil != err {
  975. return
  976. }
  977. isSameAv := srcAv.ID == destAv.ID
  978. if isSameAv {
  979. destAv = srcAv
  980. }
  981. for _, keyValues := range srcAv.KeyValues {
  982. if keyValues.Key.ID != operation.KeyID {
  983. continue
  984. }
  985. srcRel := keyValues.Key.Relation
  986. // 已经设置过双向关联的话需要先断开双向关联
  987. if nil != srcRel {
  988. if srcRel.IsTwoWay {
  989. oldDestAv, _ := av.ParseAttributeView(srcRel.AvID)
  990. if nil != oldDestAv {
  991. isOldSameAv := oldDestAv.ID == destAv.ID
  992. if isOldSameAv {
  993. oldDestAv = destAv
  994. }
  995. oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID)
  996. if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay {
  997. oldDestKey.Relation.IsTwoWay = false
  998. oldDestKey.Relation.BackKeyID = ""
  999. }
  1000. if !isOldSameAv {
  1001. err = av.SaveAttributeView(oldDestAv)
  1002. if nil != err {
  1003. return
  1004. }
  1005. }
  1006. }
  1007. }
  1008. av.RemoveAvRel(srcAv.ID, srcRel.AvID)
  1009. }
  1010. srcRel = &av.Relation{
  1011. AvID: operation.ID,
  1012. IsTwoWay: operation.IsTwoWay,
  1013. }
  1014. if operation.IsTwoWay {
  1015. srcRel.BackKeyID = operation.BackRelationKeyID
  1016. } else {
  1017. srcRel.BackKeyID = ""
  1018. }
  1019. keyValues.Key.Relation = srcRel
  1020. keyValues.Key.Name = operation.Format
  1021. break
  1022. }
  1023. destAdded := false
  1024. backRelKey, _ := destAv.GetKey(operation.BackRelationKeyID)
  1025. if nil != backRelKey {
  1026. backRelKey.Relation = &av.Relation{
  1027. AvID: operation.AvID,
  1028. IsTwoWay: operation.IsTwoWay,
  1029. BackKeyID: operation.KeyID,
  1030. }
  1031. destAdded = true
  1032. if operation.IsTwoWay {
  1033. name := strings.TrimSpace(operation.Name)
  1034. if "" == name {
  1035. name = srcAv.Name + " " + operation.Format
  1036. }
  1037. backRelKey.Name = strings.TrimSpace(name)
  1038. }
  1039. }
  1040. if !destAdded {
  1041. if operation.IsTwoWay {
  1042. name := strings.TrimSpace(operation.Name)
  1043. if "" == name {
  1044. name = srcAv.Name + " " + operation.Format
  1045. }
  1046. destAv.KeyValues = append(destAv.KeyValues, &av.KeyValues{
  1047. Key: &av.Key{
  1048. ID: operation.BackRelationKeyID,
  1049. Name: name,
  1050. Type: av.KeyTypeRelation,
  1051. Relation: &av.Relation{AvID: operation.AvID, IsTwoWay: operation.IsTwoWay, BackKeyID: operation.KeyID},
  1052. },
  1053. })
  1054. for _, v := range destAv.Views {
  1055. switch v.LayoutType {
  1056. case av.LayoutTypeTable:
  1057. v.Table.Columns = append(v.Table.Columns, &av.ViewTableColumn{ID: operation.BackRelationKeyID})
  1058. }
  1059. }
  1060. }
  1061. }
  1062. err = av.SaveAttributeView(srcAv)
  1063. if nil != err {
  1064. return
  1065. }
  1066. if !isSameAv {
  1067. err = av.SaveAttributeView(destAv)
  1068. util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
  1069. }
  1070. av.UpsertAvBackRel(srcAv.ID, destAv.ID)
  1071. return
  1072. }
  1073. func (tx *Transaction) doSortAttrViewView(operation *Operation) (ret *TxErr) {
  1074. avID := operation.AvID
  1075. attrView, err := av.ParseAttributeView(avID)
  1076. if nil != err {
  1077. logging.LogErrorf("parse attribute view [%s] failed: %s", operation.AvID, err)
  1078. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1079. }
  1080. viewID := operation.ID
  1081. previewViewID := operation.PreviousID
  1082. if viewID == previewViewID {
  1083. return
  1084. }
  1085. var view *av.View
  1086. var index, previousIndex int
  1087. for i, v := range attrView.Views {
  1088. if v.ID == viewID {
  1089. view = v
  1090. index = i
  1091. break
  1092. }
  1093. }
  1094. if nil == view {
  1095. return
  1096. }
  1097. attrView.Views = append(attrView.Views[:index], attrView.Views[index+1:]...)
  1098. for i, v := range attrView.Views {
  1099. if v.ID == previewViewID {
  1100. previousIndex = i + 1
  1101. break
  1102. }
  1103. }
  1104. attrView.Views = util.InsertElem(attrView.Views, previousIndex, view)
  1105. if err = av.SaveAttributeView(attrView); nil != err {
  1106. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1107. return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: avID}
  1108. }
  1109. return
  1110. }
  1111. func (tx *Transaction) doRemoveAttrViewView(operation *Operation) (ret *TxErr) {
  1112. var err error
  1113. avID := operation.AvID
  1114. attrView, err := av.ParseAttributeView(avID)
  1115. if nil != err {
  1116. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1117. return &TxErr{code: TxErrCodeBlockNotFound, id: avID}
  1118. }
  1119. if 1 >= len(attrView.Views) {
  1120. logging.LogWarnf("can't remove last view [%s] of attribute view [%s]", operation.ID, avID)
  1121. return
  1122. }
  1123. viewID := operation.ID
  1124. var index int
  1125. for i, view := range attrView.Views {
  1126. if viewID == view.ID {
  1127. attrView.Views = append(attrView.Views[:i], attrView.Views[i+1:]...)
  1128. index = i - 1
  1129. break
  1130. }
  1131. }
  1132. if 0 > index {
  1133. index = 0
  1134. }
  1135. attrView.ViewID = attrView.Views[index].ID
  1136. if err = av.SaveAttributeView(attrView); nil != err {
  1137. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1138. return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: avID}
  1139. }
  1140. return
  1141. }
  1142. func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr) {
  1143. var err error
  1144. avID := operation.AvID
  1145. attrView, err := av.ParseAttributeView(avID)
  1146. if nil != err {
  1147. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1148. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1149. }
  1150. masterView := attrView.GetView(operation.PreviousID)
  1151. if nil == masterView {
  1152. logging.LogErrorf("get master view failed: %s", avID)
  1153. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1154. }
  1155. view := av.NewTableView()
  1156. view.ID = operation.ID
  1157. attrView.Views = append(attrView.Views, view)
  1158. attrView.ViewID = view.ID
  1159. view.Icon = masterView.Icon
  1160. view.Name = attrView.GetDuplicateViewName(masterView.Name)
  1161. view.LayoutType = masterView.LayoutType
  1162. for _, col := range masterView.Table.Columns {
  1163. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{
  1164. ID: col.ID,
  1165. Wrap: col.Wrap,
  1166. Hidden: col.Hidden,
  1167. Pin: col.Pin,
  1168. Width: col.Width,
  1169. Calc: col.Calc,
  1170. })
  1171. }
  1172. for _, filter := range masterView.Table.Filters {
  1173. view.Table.Filters = append(view.Table.Filters, &av.ViewFilter{
  1174. Column: filter.Column,
  1175. Operator: filter.Operator,
  1176. Value: filter.Value,
  1177. })
  1178. }
  1179. for _, s := range masterView.Table.Sorts {
  1180. view.Table.Sorts = append(view.Table.Sorts, &av.ViewSort{
  1181. Column: s.Column,
  1182. Order: s.Order,
  1183. })
  1184. }
  1185. view.Table.PageSize = masterView.Table.PageSize
  1186. view.Table.RowIDs = masterView.Table.RowIDs
  1187. if err = av.SaveAttributeView(attrView); nil != err {
  1188. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1189. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1190. }
  1191. return
  1192. }
  1193. func (tx *Transaction) doAddAttrViewView(operation *Operation) (ret *TxErr) {
  1194. var err error
  1195. avID := operation.AvID
  1196. attrView, err := av.ParseAttributeView(avID)
  1197. if nil != err {
  1198. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1199. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1200. }
  1201. firstView := attrView.Views[0]
  1202. if nil == firstView {
  1203. logging.LogErrorf("get first view failed: %s", avID)
  1204. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1205. }
  1206. view := av.NewTableView()
  1207. view.ID = operation.ID
  1208. attrView.Views = append(attrView.Views, view)
  1209. attrView.ViewID = view.ID
  1210. for _, col := range firstView.Table.Columns {
  1211. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: col.ID})
  1212. }
  1213. view.Table.RowIDs = firstView.Table.RowIDs
  1214. if err = av.SaveAttributeView(attrView); nil != err {
  1215. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1216. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1217. }
  1218. return
  1219. }
  1220. func (tx *Transaction) doSetAttrViewViewName(operation *Operation) (ret *TxErr) {
  1221. var err error
  1222. avID := operation.AvID
  1223. attrView, err := av.ParseAttributeView(avID)
  1224. if nil != err {
  1225. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1226. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1227. }
  1228. viewID := operation.ID
  1229. view := attrView.GetView(viewID)
  1230. if nil == view {
  1231. logging.LogErrorf("get view [%s] failed: %s", viewID, err)
  1232. return &TxErr{code: TxErrWriteAttributeView, id: viewID}
  1233. }
  1234. view.Name = strings.TrimSpace(operation.Data.(string))
  1235. if err = av.SaveAttributeView(attrView); nil != err {
  1236. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1237. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1238. }
  1239. return
  1240. }
  1241. func (tx *Transaction) doSetAttrViewViewIcon(operation *Operation) (ret *TxErr) {
  1242. var err error
  1243. avID := operation.AvID
  1244. attrView, err := av.ParseAttributeView(avID)
  1245. if nil != err {
  1246. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  1247. return &TxErr{code: TxErrWriteAttributeView, id: avID}
  1248. }
  1249. viewID := operation.ID
  1250. view := attrView.GetView(viewID)
  1251. if nil == view {
  1252. logging.LogErrorf("get view [%s] failed: %s", viewID, err)
  1253. return &TxErr{code: TxErrWriteAttributeView, id: viewID}
  1254. }
  1255. view.Icon = operation.Data.(string)
  1256. if err = av.SaveAttributeView(attrView); nil != err {
  1257. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  1258. return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
  1259. }
  1260. return
  1261. }
  1262. func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) {
  1263. err := setAttributeViewName(operation)
  1264. if nil != err {
  1265. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1266. }
  1267. return
  1268. }
  1269. func setAttributeViewName(operation *Operation) (err error) {
  1270. attrView, err := av.ParseAttributeView(operation.ID)
  1271. if nil != err {
  1272. return
  1273. }
  1274. attrView.Name = strings.TrimSpace(operation.Data.(string))
  1275. err = av.SaveAttributeView(attrView)
  1276. return
  1277. }
  1278. func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) {
  1279. err := setAttributeViewFilters(operation)
  1280. if nil != err {
  1281. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1282. }
  1283. return
  1284. }
  1285. func setAttributeViewFilters(operation *Operation) (err error) {
  1286. attrView, err := av.ParseAttributeView(operation.AvID)
  1287. if nil != err {
  1288. return
  1289. }
  1290. view, err := attrView.GetCurrentView()
  1291. if nil != err {
  1292. return
  1293. }
  1294. operationData := operation.Data.([]interface{})
  1295. data, err := gulu.JSON.MarshalJSON(operationData)
  1296. if nil != err {
  1297. return
  1298. }
  1299. switch view.LayoutType {
  1300. case av.LayoutTypeTable:
  1301. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Filters); nil != err {
  1302. return
  1303. }
  1304. }
  1305. for _, filter := range view.Table.Filters {
  1306. var key *av.Key
  1307. key, err = attrView.GetKey(filter.Column)
  1308. if nil != err {
  1309. return
  1310. }
  1311. filter.Value.Type = key.Type
  1312. }
  1313. err = av.SaveAttributeView(attrView)
  1314. return
  1315. }
  1316. func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) {
  1317. err := setAttributeViewSorts(operation)
  1318. if nil != err {
  1319. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1320. }
  1321. return
  1322. }
  1323. func setAttributeViewSorts(operation *Operation) (err error) {
  1324. attrView, err := av.ParseAttributeView(operation.AvID)
  1325. if nil != err {
  1326. return
  1327. }
  1328. view, err := attrView.GetCurrentView()
  1329. if nil != err {
  1330. return
  1331. }
  1332. operationData := operation.Data.([]interface{})
  1333. data, err := gulu.JSON.MarshalJSON(operationData)
  1334. if nil != err {
  1335. return
  1336. }
  1337. switch view.LayoutType {
  1338. case av.LayoutTypeTable:
  1339. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Sorts); nil != err {
  1340. return
  1341. }
  1342. }
  1343. err = av.SaveAttributeView(attrView)
  1344. return
  1345. }
  1346. func (tx *Transaction) doSetAttrViewPageSize(operation *Operation) (ret *TxErr) {
  1347. err := setAttributeViewPageSize(operation)
  1348. if nil != err {
  1349. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1350. }
  1351. return
  1352. }
  1353. func setAttributeViewPageSize(operation *Operation) (err error) {
  1354. attrView, err := av.ParseAttributeView(operation.AvID)
  1355. if nil != err {
  1356. return
  1357. }
  1358. view, err := attrView.GetCurrentView()
  1359. if nil != err {
  1360. return
  1361. }
  1362. switch view.LayoutType {
  1363. case av.LayoutTypeTable:
  1364. view.Table.PageSize = int(operation.Data.(float64))
  1365. }
  1366. err = av.SaveAttributeView(attrView)
  1367. return
  1368. }
  1369. func (tx *Transaction) doSetAttrViewColCalc(operation *Operation) (ret *TxErr) {
  1370. err := setAttributeViewColumnCalc(operation)
  1371. if nil != err {
  1372. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1373. }
  1374. return
  1375. }
  1376. func setAttributeViewColumnCalc(operation *Operation) (err error) {
  1377. attrView, err := av.ParseAttributeView(operation.AvID)
  1378. if nil != err {
  1379. return
  1380. }
  1381. view, err := attrView.GetCurrentView()
  1382. if nil != err {
  1383. return
  1384. }
  1385. operationData := operation.Data.(interface{})
  1386. data, err := gulu.JSON.MarshalJSON(operationData)
  1387. if nil != err {
  1388. return
  1389. }
  1390. calc := &av.ColumnCalc{}
  1391. switch view.LayoutType {
  1392. case av.LayoutTypeTable:
  1393. if err = gulu.JSON.UnmarshalJSON(data, calc); nil != err {
  1394. return
  1395. }
  1396. for _, column := range view.Table.Columns {
  1397. if column.ID == operation.ID {
  1398. column.Calc = calc
  1399. break
  1400. }
  1401. }
  1402. }
  1403. err = av.SaveAttributeView(attrView)
  1404. return
  1405. }
  1406. func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
  1407. err := AddAttributeViewBlock(tx, operation.SrcIDs, operation.AvID, operation.PreviousID, operation.IsDetached)
  1408. if nil != err {
  1409. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1410. }
  1411. return
  1412. }
  1413. func AddAttributeViewBlock(tx *Transaction, srcIDs []string, avID, previousBlockID string, isDetached bool) (err error) {
  1414. for _, id := range srcIDs {
  1415. var tree *parse.Tree
  1416. if !isDetached {
  1417. var loadErr error
  1418. if nil != tx {
  1419. tree, loadErr = tx.loadTree(id)
  1420. } else {
  1421. tree, loadErr = loadTreeByBlockID(id)
  1422. }
  1423. if nil != loadErr {
  1424. logging.LogErrorf("load tree [%s] failed: %s", id, err)
  1425. return loadErr
  1426. }
  1427. }
  1428. if avErr := addAttributeViewBlock(avID, previousBlockID, id, isDetached, tree, tx); nil != avErr {
  1429. return avErr
  1430. }
  1431. }
  1432. return
  1433. }
  1434. func addAttributeViewBlock(avID, previousBlockID, blockID string, isDetached bool, tree *parse.Tree, tx *Transaction) (err error) {
  1435. var node *ast.Node
  1436. if !isDetached {
  1437. node = treenode.GetNodeInTree(tree, blockID)
  1438. if nil == node {
  1439. err = ErrBlockNotFound
  1440. return
  1441. }
  1442. if ast.NodeAttributeView == node.Type {
  1443. // 不能将一个属性视图拖拽到另一个属性视图中
  1444. return
  1445. }
  1446. } else {
  1447. if "" == blockID {
  1448. blockID = ast.NewNodeID()
  1449. logging.LogWarnf("detached block id is empty, generate a new one [%s]", blockID)
  1450. }
  1451. }
  1452. attrView, err := av.ParseAttributeView(avID)
  1453. if nil != err {
  1454. return
  1455. }
  1456. // 不允许重复添加相同的块到属性视图中
  1457. blockValues := attrView.GetBlockKeyValues()
  1458. for _, blockValue := range blockValues.Values {
  1459. if blockValue.Block.ID == blockID {
  1460. return
  1461. }
  1462. }
  1463. var content string
  1464. if !isDetached {
  1465. content = getNodeRefText(node)
  1466. }
  1467. now := time.Now().UnixMilli()
  1468. blockValue := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Type: av.KeyTypeBlock, IsDetached: isDetached, Block: &av.ValueBlock{ID: blockID, Content: content, Created: now, Updated: now}}
  1469. blockValues.Values = append(blockValues.Values, blockValue)
  1470. // 如果存在排序和过滤条件,则将排序和过滤条件应用到新添加的块上
  1471. view, _ := attrView.GetCurrentView()
  1472. if nil != view && (0 < len(view.Table.Filters) || 0 < len(view.Table.Sorts)) {
  1473. viewable, _ := renderAttributeViewTable(attrView, view)
  1474. viewable.FilterRows(attrView)
  1475. viewable.SortRows()
  1476. affectKeyIDs := map[string]bool{}
  1477. for _, f := range view.Table.Filters {
  1478. affectKeyIDs[f.Column] = true
  1479. }
  1480. for _, s := range view.Table.Sorts {
  1481. affectKeyIDs[s.Column] = true
  1482. }
  1483. addedValues := map[string]bool{}
  1484. if 0 < len(viewable.Rows) {
  1485. row := GetLastSortRow(viewable.Rows)
  1486. if nil != row {
  1487. for affectKeyID := range affectKeyIDs {
  1488. for _, cell := range row.Cells {
  1489. if nil != cell.Value && cell.Value.KeyID == affectKeyID {
  1490. if av.KeyTypeBlock == cell.ValueType {
  1491. blockValue.Block.Content = cell.Value.Block.Content
  1492. continue
  1493. }
  1494. newValue := cell.Value.Clone()
  1495. newValue.ID = ast.NewNodeID()
  1496. newValue.BlockID = blockID
  1497. newValue.IsDetached = isDetached
  1498. values, _ := attrView.GetKeyValues(affectKeyID)
  1499. values.Values = append(values.Values, newValue)
  1500. addedValues[affectKeyID] = true
  1501. break
  1502. }
  1503. }
  1504. }
  1505. }
  1506. }
  1507. notAddedValues := map[string]bool{}
  1508. for affectKeyID := range affectKeyIDs {
  1509. if !addedValues[affectKeyID] {
  1510. notAddedValues[affectKeyID] = true
  1511. break
  1512. }
  1513. }
  1514. if 0 < len(notAddedValues) {
  1515. for _, filter := range view.Table.Filters {
  1516. if !notAddedValues[filter.Column] {
  1517. continue
  1518. }
  1519. for _, keyValues := range attrView.KeyValues {
  1520. if keyValues.Key.ID == filter.Column {
  1521. newValue := filter.GetAffectValue(keyValues.Key)
  1522. newValue.ID = ast.NewNodeID()
  1523. newValue.KeyID = keyValues.Key.ID
  1524. newValue.BlockID = blockID
  1525. newValue.IsDetached = isDetached
  1526. keyValues.Values = append(keyValues.Values, newValue)
  1527. break
  1528. }
  1529. }
  1530. }
  1531. // 仅使用上面的过滤条件计算受影响的值并插入兜底,受影响的排序条件不进行计算值插入
  1532. }
  1533. }
  1534. if !isDetached {
  1535. attrs := parse.IAL2Map(node.KramdownIAL)
  1536. if "" == attrs[av.NodeAttrNameAvs] {
  1537. attrs[av.NodeAttrNameAvs] = avID
  1538. } else {
  1539. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  1540. avIDs = append(avIDs, avID)
  1541. avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
  1542. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  1543. }
  1544. if nil != tx {
  1545. if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
  1546. return
  1547. }
  1548. } else {
  1549. if err = setNodeAttrs(node, tree, attrs); nil != err {
  1550. return
  1551. }
  1552. }
  1553. }
  1554. for _, view := range attrView.Views {
  1555. switch view.LayoutType {
  1556. case av.LayoutTypeTable:
  1557. if "" != previousBlockID {
  1558. changed := false
  1559. for i, id := range view.Table.RowIDs {
  1560. if id == previousBlockID {
  1561. view.Table.RowIDs = append(view.Table.RowIDs[:i+1], append([]string{blockID}, view.Table.RowIDs[i+1:]...)...)
  1562. changed = true
  1563. break
  1564. }
  1565. }
  1566. if !changed {
  1567. view.Table.RowIDs = append(view.Table.RowIDs, blockID)
  1568. }
  1569. } else {
  1570. view.Table.RowIDs = append([]string{blockID}, view.Table.RowIDs...)
  1571. }
  1572. }
  1573. }
  1574. err = av.SaveAttributeView(attrView)
  1575. return
  1576. }
  1577. func GetLastSortRow(rows []*av.TableRow) *av.TableRow {
  1578. for i := len(rows) - 1; i >= 0; i-- {
  1579. row := rows[i]
  1580. blockVal := row.GetBlockValue()
  1581. if nil != blockVal {
  1582. if nil != blockVal.Block && blockVal.Block.Created == blockVal.Block.Updated {
  1583. // 说明是刚刚创建的块,跳过
  1584. continue
  1585. }
  1586. return row
  1587. }
  1588. }
  1589. return nil
  1590. }
  1591. func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) {
  1592. err := removeAttributeViewBlock(operation.SrcIDs, operation.AvID, tx)
  1593. if nil != err {
  1594. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  1595. }
  1596. return
  1597. }
  1598. func RemoveAttributeViewBlock(srcIDs []string, avID string) (err error) {
  1599. err = removeAttributeViewBlock(srcIDs, avID, nil)
  1600. return
  1601. }
  1602. func removeAttributeViewBlock(srcIDs []string, avID string, tx *Transaction) (err error) {
  1603. attrView, err := av.ParseAttributeView(avID)
  1604. if nil != err {
  1605. return
  1606. }
  1607. trees := map[string]*parse.Tree{}
  1608. for _, keyValues := range attrView.KeyValues {
  1609. tmp := keyValues.Values[:0]
  1610. for i, values := range keyValues.Values {
  1611. if !gulu.Str.Contains(values.BlockID, srcIDs) {
  1612. tmp = append(tmp, keyValues.Values[i])
  1613. } else {
  1614. // Remove av block also remove node attr https://github.com/siyuan-note/siyuan/issues/9091#issuecomment-1709824006
  1615. if bt := treenode.GetBlockTree(values.BlockID); nil != bt {
  1616. tree := trees[bt.RootID]
  1617. if nil == tree {
  1618. tree, _ = loadTreeByBlockID(values.BlockID)
  1619. }
  1620. if nil != tree {
  1621. trees[bt.RootID] = tree
  1622. if node := treenode.GetNodeInTree(tree, values.BlockID); nil != node {
  1623. if err = removeNodeAvID(node, avID, tx, tree); nil != err {
  1624. return
  1625. }
  1626. }
  1627. }
  1628. }
  1629. }
  1630. }
  1631. keyValues.Values = tmp
  1632. }
  1633. for _, view := range attrView.Views {
  1634. for _, blockID := range srcIDs {
  1635. view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
  1636. }
  1637. }
  1638. err = av.SaveAttributeView(attrView)
  1639. return
  1640. }
  1641. func removeNodeAvID(node *ast.Node, avID string, tx *Transaction, tree *parse.Tree) (err error) {
  1642. attrs := parse.IAL2Map(node.KramdownIAL)
  1643. if ast.NodeDocument == node.Type {
  1644. delete(attrs, "custom-hidden")
  1645. node.RemoveIALAttr("custom-hidden")
  1646. }
  1647. if avs := attrs[av.NodeAttrNameAvs]; "" != avs {
  1648. avIDs := strings.Split(avs, ",")
  1649. avIDs = gulu.Str.RemoveElem(avIDs, avID)
  1650. var existAvIDs []string
  1651. for _, attributeViewID := range avIDs {
  1652. if av.IsAttributeViewExist(attributeViewID) {
  1653. existAvIDs = append(existAvIDs, attributeViewID)
  1654. }
  1655. }
  1656. avIDs = existAvIDs
  1657. if 0 == len(avIDs) {
  1658. delete(attrs, av.NodeAttrNameAvs)
  1659. node.RemoveIALAttr(av.NodeAttrNameAvs)
  1660. } else {
  1661. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  1662. node.SetIALAttr(av.NodeAttrNameAvs, strings.Join(avIDs, ","))
  1663. }
  1664. }
  1665. if nil != tx {
  1666. if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
  1667. return
  1668. }
  1669. } else {
  1670. if err = setNodeAttrs(node, tree, attrs); nil != err {
  1671. return
  1672. }
  1673. }
  1674. return
  1675. }
  1676. func (tx *Transaction) doSetAttrViewColumnWidth(operation *Operation) (ret *TxErr) {
  1677. err := setAttributeViewColWidth(operation)
  1678. if nil != err {
  1679. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1680. }
  1681. return
  1682. }
  1683. func setAttributeViewColWidth(operation *Operation) (err error) {
  1684. attrView, err := av.ParseAttributeView(operation.AvID)
  1685. if nil != err {
  1686. return
  1687. }
  1688. view, err := attrView.GetCurrentView()
  1689. if nil != err {
  1690. return
  1691. }
  1692. switch view.LayoutType {
  1693. case av.LayoutTypeTable:
  1694. for _, column := range view.Table.Columns {
  1695. if column.ID == operation.ID {
  1696. column.Width = operation.Data.(string)
  1697. break
  1698. }
  1699. }
  1700. }
  1701. err = av.SaveAttributeView(attrView)
  1702. return
  1703. }
  1704. func (tx *Transaction) doSetAttrViewColumnWrap(operation *Operation) (ret *TxErr) {
  1705. err := setAttributeViewColWrap(operation)
  1706. if nil != err {
  1707. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1708. }
  1709. return
  1710. }
  1711. func setAttributeViewColWrap(operation *Operation) (err error) {
  1712. attrView, err := av.ParseAttributeView(operation.AvID)
  1713. if nil != err {
  1714. return
  1715. }
  1716. view, err := attrView.GetCurrentView()
  1717. if nil != err {
  1718. return
  1719. }
  1720. switch view.LayoutType {
  1721. case av.LayoutTypeTable:
  1722. for _, column := range view.Table.Columns {
  1723. if column.ID == operation.ID {
  1724. column.Wrap = operation.Data.(bool)
  1725. break
  1726. }
  1727. }
  1728. }
  1729. err = av.SaveAttributeView(attrView)
  1730. return
  1731. }
  1732. func (tx *Transaction) doSetAttrViewColumnHidden(operation *Operation) (ret *TxErr) {
  1733. err := setAttributeViewColHidden(operation)
  1734. if nil != err {
  1735. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1736. }
  1737. return
  1738. }
  1739. func setAttributeViewColHidden(operation *Operation) (err error) {
  1740. attrView, err := av.ParseAttributeView(operation.AvID)
  1741. if nil != err {
  1742. return
  1743. }
  1744. view, err := attrView.GetCurrentView()
  1745. if nil != err {
  1746. return
  1747. }
  1748. switch view.LayoutType {
  1749. case av.LayoutTypeTable:
  1750. for _, column := range view.Table.Columns {
  1751. if column.ID == operation.ID {
  1752. column.Hidden = operation.Data.(bool)
  1753. break
  1754. }
  1755. }
  1756. }
  1757. err = av.SaveAttributeView(attrView)
  1758. return
  1759. }
  1760. func (tx *Transaction) doSetAttrViewColumnPin(operation *Operation) (ret *TxErr) {
  1761. err := setAttributeViewColPin(operation)
  1762. if nil != err {
  1763. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1764. }
  1765. return
  1766. }
  1767. func setAttributeViewColPin(operation *Operation) (err error) {
  1768. attrView, err := av.ParseAttributeView(operation.AvID)
  1769. if nil != err {
  1770. return
  1771. }
  1772. view, err := attrView.GetCurrentView()
  1773. if nil != err {
  1774. return
  1775. }
  1776. switch view.LayoutType {
  1777. case av.LayoutTypeTable:
  1778. for _, column := range view.Table.Columns {
  1779. if column.ID == operation.ID {
  1780. column.Pin = operation.Data.(bool)
  1781. break
  1782. }
  1783. }
  1784. }
  1785. err = av.SaveAttributeView(attrView)
  1786. return
  1787. }
  1788. func (tx *Transaction) doSetAttrViewColumnIcon(operation *Operation) (ret *TxErr) {
  1789. err := setAttributeViewColIcon(operation)
  1790. if nil != err {
  1791. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1792. }
  1793. return
  1794. }
  1795. func setAttributeViewColIcon(operation *Operation) (err error) {
  1796. attrView, err := av.ParseAttributeView(operation.AvID)
  1797. if nil != err {
  1798. return
  1799. }
  1800. for _, keyValues := range attrView.KeyValues {
  1801. if keyValues.Key.ID == operation.ID {
  1802. keyValues.Key.Icon = operation.Data.(string)
  1803. break
  1804. }
  1805. }
  1806. err = av.SaveAttributeView(attrView)
  1807. return
  1808. }
  1809. func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) {
  1810. err := sortAttributeViewRow(operation)
  1811. if nil != err {
  1812. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1813. }
  1814. return
  1815. }
  1816. func sortAttributeViewRow(operation *Operation) (err error) {
  1817. attrView, err := av.ParseAttributeView(operation.AvID)
  1818. if nil != err {
  1819. return
  1820. }
  1821. view, err := attrView.GetCurrentView()
  1822. if nil != err {
  1823. return
  1824. }
  1825. var rowID string
  1826. var index, previousIndex int
  1827. for i, r := range view.Table.RowIDs {
  1828. if r == operation.ID {
  1829. rowID = r
  1830. index = i
  1831. break
  1832. }
  1833. }
  1834. if "" == rowID {
  1835. rowID = operation.ID
  1836. view.Table.RowIDs = append(view.Table.RowIDs, rowID)
  1837. index = len(view.Table.RowIDs) - 1
  1838. }
  1839. switch view.LayoutType {
  1840. case av.LayoutTypeTable:
  1841. view.Table.RowIDs = append(view.Table.RowIDs[:index], view.Table.RowIDs[index+1:]...)
  1842. for i, r := range view.Table.RowIDs {
  1843. if r == operation.PreviousID {
  1844. previousIndex = i + 1
  1845. break
  1846. }
  1847. }
  1848. view.Table.RowIDs = util.InsertElem(view.Table.RowIDs, previousIndex, rowID)
  1849. }
  1850. err = av.SaveAttributeView(attrView)
  1851. return
  1852. }
  1853. func (tx *Transaction) doSortAttrViewColumn(operation *Operation) (ret *TxErr) {
  1854. err := SortAttributeViewKey(operation.AvID, operation.ID, operation.PreviousID)
  1855. if nil != err {
  1856. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1857. }
  1858. return
  1859. }
  1860. func SortAttributeViewKey(avID, keyID, previousKeyID string) (err error) {
  1861. attrView, err := av.ParseAttributeView(avID)
  1862. if nil != err {
  1863. return
  1864. }
  1865. view, err := attrView.GetCurrentView()
  1866. if nil != err {
  1867. return
  1868. }
  1869. switch view.LayoutType {
  1870. case av.LayoutTypeTable:
  1871. var col *av.ViewTableColumn
  1872. var index, previousIndex int
  1873. for i, column := range view.Table.Columns {
  1874. if column.ID == keyID {
  1875. col = column
  1876. index = i
  1877. break
  1878. }
  1879. }
  1880. if nil == col {
  1881. return
  1882. }
  1883. view.Table.Columns = append(view.Table.Columns[:index], view.Table.Columns[index+1:]...)
  1884. for i, column := range view.Table.Columns {
  1885. if column.ID == previousKeyID {
  1886. previousIndex = i + 1
  1887. break
  1888. }
  1889. }
  1890. view.Table.Columns = util.InsertElem(view.Table.Columns, previousIndex, col)
  1891. }
  1892. err = av.SaveAttributeView(attrView)
  1893. return
  1894. }
  1895. func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) {
  1896. var icon string
  1897. if nil != operation.Data {
  1898. icon = operation.Data.(string)
  1899. }
  1900. err := AddAttributeViewKey(operation.AvID, operation.ID, operation.Name, operation.Typ, icon, operation.PreviousID)
  1901. if nil != err {
  1902. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1903. }
  1904. return
  1905. }
  1906. func AddAttributeViewKey(avID, keyID, keyName, keyType, keyIcon, previousKeyID string) (err error) {
  1907. attrView, err := av.ParseAttributeView(avID)
  1908. if nil != err {
  1909. return
  1910. }
  1911. keyTyp := av.KeyType(keyType)
  1912. switch keyTyp {
  1913. case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
  1914. av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
  1915. av.KeyTypeRelation, av.KeyTypeRollup:
  1916. key := av.NewKey(keyID, keyName, keyIcon, keyTyp)
  1917. if av.KeyTypeRollup == keyTyp {
  1918. key.Rollup = &av.Rollup{Calc: &av.RollupCalc{Operator: av.CalcOperatorNone}}
  1919. }
  1920. attrView.KeyValues = append(attrView.KeyValues, &av.KeyValues{Key: key})
  1921. for _, view := range attrView.Views {
  1922. switch view.LayoutType {
  1923. case av.LayoutTypeTable:
  1924. if "" == previousKeyID {
  1925. view.Table.Columns = append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns...)
  1926. break
  1927. }
  1928. added := false
  1929. for i, column := range view.Table.Columns {
  1930. if column.ID == previousKeyID {
  1931. view.Table.Columns = append(view.Table.Columns[:i+1], append([]*av.ViewTableColumn{{ID: key.ID}}, view.Table.Columns[i+1:]...)...)
  1932. added = true
  1933. break
  1934. }
  1935. }
  1936. if !added {
  1937. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: key.ID})
  1938. }
  1939. }
  1940. }
  1941. }
  1942. err = av.SaveAttributeView(attrView)
  1943. return
  1944. }
  1945. func (tx *Transaction) doUpdateAttrViewColTemplate(operation *Operation) (ret *TxErr) {
  1946. err := updateAttributeViewColTemplate(operation)
  1947. if nil != err {
  1948. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1949. }
  1950. return
  1951. }
  1952. func updateAttributeViewColTemplate(operation *Operation) (err error) {
  1953. attrView, err := av.ParseAttributeView(operation.AvID)
  1954. if nil != err {
  1955. return
  1956. }
  1957. colType := av.KeyType(operation.Typ)
  1958. switch colType {
  1959. case av.KeyTypeTemplate:
  1960. for _, keyValues := range attrView.KeyValues {
  1961. if keyValues.Key.ID == operation.ID && av.KeyTypeTemplate == keyValues.Key.Type {
  1962. keyValues.Key.Template = operation.Data.(string)
  1963. break
  1964. }
  1965. }
  1966. }
  1967. err = av.SaveAttributeView(attrView)
  1968. return
  1969. }
  1970. func (tx *Transaction) doUpdateAttrViewColNumberFormat(operation *Operation) (ret *TxErr) {
  1971. err := updateAttributeViewColNumberFormat(operation)
  1972. if nil != err {
  1973. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1974. }
  1975. return
  1976. }
  1977. func updateAttributeViewColNumberFormat(operation *Operation) (err error) {
  1978. attrView, err := av.ParseAttributeView(operation.AvID)
  1979. if nil != err {
  1980. return
  1981. }
  1982. colType := av.KeyType(operation.Typ)
  1983. switch colType {
  1984. case av.KeyTypeNumber:
  1985. for _, keyValues := range attrView.KeyValues {
  1986. if keyValues.Key.ID == operation.ID && av.KeyTypeNumber == keyValues.Key.Type {
  1987. keyValues.Key.NumberFormat = av.NumberFormat(operation.Format)
  1988. break
  1989. }
  1990. }
  1991. }
  1992. err = av.SaveAttributeView(attrView)
  1993. return
  1994. }
  1995. func (tx *Transaction) doUpdateAttrViewColumn(operation *Operation) (ret *TxErr) {
  1996. err := updateAttributeViewColumn(operation)
  1997. if nil != err {
  1998. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  1999. }
  2000. return
  2001. }
  2002. func updateAttributeViewColumn(operation *Operation) (err error) {
  2003. attrView, err := av.ParseAttributeView(operation.AvID)
  2004. if nil != err {
  2005. return
  2006. }
  2007. colType := av.KeyType(operation.Typ)
  2008. switch colType {
  2009. case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
  2010. av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
  2011. av.KeyTypeRelation, av.KeyTypeRollup:
  2012. for _, keyValues := range attrView.KeyValues {
  2013. if keyValues.Key.ID == operation.ID {
  2014. keyValues.Key.Name = strings.TrimSpace(operation.Name)
  2015. keyValues.Key.Type = colType
  2016. break
  2017. }
  2018. }
  2019. }
  2020. err = av.SaveAttributeView(attrView)
  2021. return
  2022. }
  2023. func (tx *Transaction) doRemoveAttrViewColumn(operation *Operation) (ret *TxErr) {
  2024. err := RemoveAttributeViewKey(operation.AvID, operation.ID)
  2025. if nil != err {
  2026. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2027. }
  2028. return
  2029. }
  2030. func RemoveAttributeViewKey(avID, keyID string) (err error) {
  2031. attrView, err := av.ParseAttributeView(avID)
  2032. if nil != err {
  2033. return
  2034. }
  2035. var removedKey *av.Key
  2036. for i, keyValues := range attrView.KeyValues {
  2037. if keyValues.Key.ID == keyID {
  2038. attrView.KeyValues = append(attrView.KeyValues[:i], attrView.KeyValues[i+1:]...)
  2039. removedKey = keyValues.Key
  2040. break
  2041. }
  2042. }
  2043. if nil != removedKey && av.KeyTypeRelation == removedKey.Type && nil != removedKey.Relation {
  2044. if removedKey.Relation.IsTwoWay {
  2045. // 删除双向关联的目标列
  2046. destAv, _ := av.ParseAttributeView(removedKey.Relation.AvID)
  2047. if nil != destAv {
  2048. destAvRelSrcAv := false
  2049. for i, keyValues := range destAv.KeyValues {
  2050. if keyValues.Key.ID == removedKey.Relation.BackKeyID {
  2051. destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...)
  2052. continue
  2053. }
  2054. if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == attrView.ID {
  2055. destAvRelSrcAv = true
  2056. }
  2057. }
  2058. for _, view := range destAv.Views {
  2059. switch view.LayoutType {
  2060. case av.LayoutTypeTable:
  2061. for i, column := range view.Table.Columns {
  2062. if column.ID == removedKey.Relation.BackKeyID {
  2063. view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
  2064. break
  2065. }
  2066. }
  2067. }
  2068. }
  2069. av.SaveAttributeView(destAv)
  2070. util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID})
  2071. if !destAvRelSrcAv {
  2072. av.RemoveAvRel(destAv.ID, attrView.ID)
  2073. }
  2074. }
  2075. srcAvRelDestAv := false
  2076. for _, keyValues := range attrView.KeyValues {
  2077. if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation && keyValues.Key.Relation.AvID == removedKey.Relation.AvID {
  2078. srcAvRelDestAv = true
  2079. }
  2080. }
  2081. if !srcAvRelDestAv {
  2082. av.RemoveAvRel(attrView.ID, removedKey.Relation.AvID)
  2083. }
  2084. }
  2085. }
  2086. for _, view := range attrView.Views {
  2087. switch view.LayoutType {
  2088. case av.LayoutTypeTable:
  2089. for i, column := range view.Table.Columns {
  2090. if column.ID == keyID {
  2091. view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
  2092. break
  2093. }
  2094. }
  2095. }
  2096. }
  2097. err = av.SaveAttributeView(attrView)
  2098. return
  2099. }
  2100. func (tx *Transaction) doReplaceAttrViewBlock(operation *Operation) (ret *TxErr) {
  2101. err := replaceAttributeViewBlock(operation, tx)
  2102. if nil != err {
  2103. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  2104. }
  2105. return
  2106. }
  2107. func replaceAttributeViewBlock(operation *Operation, tx *Transaction) (err error) {
  2108. attrView, err := av.ParseAttributeView(operation.AvID)
  2109. if nil != err {
  2110. return
  2111. }
  2112. var node *ast.Node
  2113. if !operation.IsDetached {
  2114. node, _, _ = getNodeByBlockID(tx, operation.NextID)
  2115. }
  2116. for _, keyValues := range attrView.KeyValues {
  2117. for _, value := range keyValues.Values {
  2118. if value.BlockID == operation.PreviousID {
  2119. if value.BlockID != operation.NextID {
  2120. // 换绑
  2121. unbindBlockAv(tx, operation.AvID, value.BlockID)
  2122. }
  2123. value.BlockID = operation.NextID
  2124. if nil != value.Block {
  2125. value.Block.ID = operation.NextID
  2126. value.IsDetached = operation.IsDetached
  2127. if !operation.IsDetached {
  2128. value.Block.Content = getNodeRefText(node)
  2129. }
  2130. }
  2131. if !operation.IsDetached {
  2132. bindBlockAv(tx, operation.AvID, operation.NextID)
  2133. }
  2134. }
  2135. }
  2136. }
  2137. replacedRowID := false
  2138. for _, v := range attrView.Views {
  2139. switch v.LayoutType {
  2140. case av.LayoutTypeTable:
  2141. for i, rowID := range v.Table.RowIDs {
  2142. if rowID == operation.PreviousID {
  2143. v.Table.RowIDs[i] = operation.NextID
  2144. replacedRowID = true
  2145. break
  2146. }
  2147. }
  2148. if !replacedRowID {
  2149. v.Table.RowIDs = append(v.Table.RowIDs, operation.NextID)
  2150. }
  2151. }
  2152. }
  2153. err = av.SaveAttributeView(attrView)
  2154. return
  2155. }
  2156. func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
  2157. err := updateAttributeViewCell(operation, tx)
  2158. if nil != err {
  2159. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2160. }
  2161. return
  2162. }
  2163. func updateAttributeViewCell(operation *Operation, tx *Transaction) (err error) {
  2164. err = UpdateAttributeViewCell(tx, operation.AvID, operation.KeyID, operation.RowID, operation.ID, operation.Data)
  2165. return
  2166. }
  2167. func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string, valueData interface{}) (err error) {
  2168. attrView, err := av.ParseAttributeView(avID)
  2169. if nil != err {
  2170. return
  2171. }
  2172. var blockVal *av.Value
  2173. for _, kv := range attrView.KeyValues {
  2174. if av.KeyTypeBlock == kv.Key.Type {
  2175. for _, v := range kv.Values {
  2176. if rowID == v.Block.ID {
  2177. blockVal = v
  2178. break
  2179. }
  2180. }
  2181. break
  2182. }
  2183. }
  2184. var val *av.Value
  2185. oldIsDetached := true
  2186. if nil != blockVal {
  2187. oldIsDetached = blockVal.IsDetached
  2188. }
  2189. for _, keyValues := range attrView.KeyValues {
  2190. if keyID != keyValues.Key.ID {
  2191. continue
  2192. }
  2193. for _, value := range keyValues.Values {
  2194. if cellID == value.ID {
  2195. val = value
  2196. val.Type = keyValues.Key.Type
  2197. break
  2198. }
  2199. }
  2200. if nil == val {
  2201. val = &av.Value{ID: cellID, KeyID: keyValues.Key.ID, BlockID: rowID, Type: keyValues.Key.Type}
  2202. keyValues.Values = append(keyValues.Values, val)
  2203. }
  2204. break
  2205. }
  2206. isUpdatingBlockKey := av.KeyTypeBlock == val.Type
  2207. oldBoundBlockID := val.BlockID
  2208. var oldRelationBlockIDs []string
  2209. if av.KeyTypeRelation == val.Type {
  2210. if nil != val.Relation {
  2211. for _, bID := range val.Relation.BlockIDs {
  2212. oldRelationBlockIDs = append(oldRelationBlockIDs, bID)
  2213. }
  2214. }
  2215. }
  2216. data, err := gulu.JSON.MarshalJSON(valueData)
  2217. if nil != err {
  2218. return
  2219. }
  2220. if err = gulu.JSON.UnmarshalJSON(data, &val); nil != err {
  2221. return
  2222. }
  2223. if av.KeyTypeNumber == val.Type {
  2224. if nil != val.Number && !val.Number.IsNotEmpty {
  2225. // 删除内容为空值
  2226. val.Number.Content = 0
  2227. val.Number.FormattedContent = ""
  2228. }
  2229. }
  2230. relationChangeMode := 0 // 0:不变(仅排序),1:增加,2:减少
  2231. if av.KeyTypeRelation == val.Type {
  2232. // 关联列得 content 是自动渲染的,所以不需要保存
  2233. val.Relation.Contents = nil
  2234. // 计算关联变更模式
  2235. if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
  2236. relationChangeMode = 0
  2237. } else {
  2238. if len(oldRelationBlockIDs) > len(val.Relation.BlockIDs) {
  2239. relationChangeMode = 2
  2240. } else {
  2241. relationChangeMode = 1
  2242. }
  2243. }
  2244. }
  2245. // val.IsDetached 只有更新主键的时候才会传入,所以下面需要结合 isUpdatingBlockKey 来判断
  2246. if oldIsDetached { // 之前是游离行
  2247. if !val.IsDetached { // 现在绑定了块
  2248. // 将游离行绑定到新建的块上
  2249. bindBlockAv(tx, avID, rowID)
  2250. }
  2251. } else { // 之前绑定了块
  2252. if isUpdatingBlockKey { // 正在更新主键
  2253. if val.IsDetached { // 现在是游离行
  2254. // 将绑定的块从属性视图中移除
  2255. unbindBlockAv(tx, avID, rowID)
  2256. } else { // 现在绑定了块
  2257. if oldBoundBlockID != val.BlockID { // 之前绑定的块和现在绑定的块不一样
  2258. // 换绑块
  2259. unbindBlockAv(tx, avID, oldBoundBlockID)
  2260. bindBlockAv(tx, avID, val.BlockID)
  2261. } else { // 之前绑定的块和现在绑定的块一样
  2262. // 直接返回,因为锚文本不允许更改
  2263. return
  2264. }
  2265. }
  2266. }
  2267. }
  2268. if nil != blockVal {
  2269. blockVal.Block.Updated = time.Now().UnixMilli()
  2270. if isUpdatingBlockKey {
  2271. blockVal.IsDetached = val.IsDetached
  2272. }
  2273. }
  2274. key, _ := attrView.GetKey(val.KeyID)
  2275. if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation {
  2276. destAv, _ := av.ParseAttributeView(key.Relation.AvID)
  2277. if nil != destAv {
  2278. if key.Relation.IsTwoWay {
  2279. // relationChangeMode
  2280. // 0:关联列值不变(仅排序),不影响目标值
  2281. // 1:关联列值增加,增加目标值
  2282. // 2:关联列值减少,减少目标值
  2283. if 1 == relationChangeMode {
  2284. addBlockIDs := val.Relation.BlockIDs
  2285. for _, bID := range oldRelationBlockIDs {
  2286. addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID)
  2287. }
  2288. for _, blockID := range addBlockIDs {
  2289. for _, keyValues := range destAv.KeyValues {
  2290. if keyValues.Key.ID != key.Relation.BackKeyID {
  2291. continue
  2292. }
  2293. destVal := keyValues.GetValue(blockID)
  2294. if nil == destVal {
  2295. destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}}
  2296. keyValues.Values = append(keyValues.Values, destVal)
  2297. }
  2298. destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID)
  2299. destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
  2300. break
  2301. }
  2302. }
  2303. } else if 2 == relationChangeMode {
  2304. removeBlockIDs := oldRelationBlockIDs
  2305. for _, bID := range val.Relation.BlockIDs {
  2306. removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID)
  2307. }
  2308. for _, blockID := range removeBlockIDs {
  2309. for _, keyValues := range destAv.KeyValues {
  2310. if keyValues.Key.ID != key.Relation.BackKeyID {
  2311. continue
  2312. }
  2313. for _, value := range keyValues.Values {
  2314. if value.BlockID == blockID {
  2315. value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID)
  2316. break
  2317. }
  2318. }
  2319. }
  2320. }
  2321. }
  2322. av.SaveAttributeView(destAv)
  2323. }
  2324. }
  2325. }
  2326. relatedAvIDs := av.GetSrcAvIDs(avID)
  2327. for _, relatedAvID := range relatedAvIDs {
  2328. util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": relatedAvID})
  2329. }
  2330. if err = av.SaveAttributeView(attrView); nil != err {
  2331. return
  2332. }
  2333. return
  2334. }
  2335. func unbindBlockAv(tx *Transaction, avID, blockID string) {
  2336. node, tree, err := getNodeByBlockID(tx, blockID)
  2337. if nil != err {
  2338. return
  2339. }
  2340. attrs := parse.IAL2Map(node.KramdownIAL)
  2341. if "" == attrs[av.NodeAttrNameAvs] {
  2342. return
  2343. }
  2344. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2345. avIDs = gulu.Str.RemoveElem(avIDs, avID)
  2346. if 0 == len(avIDs) {
  2347. delete(attrs, av.NodeAttrNameAvs)
  2348. node.RemoveIALAttr(av.NodeAttrNameAvs)
  2349. } else {
  2350. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2351. node.SetIALAttr(av.NodeAttrNameAvs, strings.Join(avIDs, ","))
  2352. }
  2353. if nil != tx {
  2354. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2355. } else {
  2356. err = setNodeAttrs(node, tree, attrs)
  2357. }
  2358. if nil != err {
  2359. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  2360. return
  2361. }
  2362. return
  2363. }
  2364. func bindBlockAv(tx *Transaction, avID, blockID string) {
  2365. node, tree, err := getNodeByBlockID(tx, blockID)
  2366. if nil != err {
  2367. return
  2368. }
  2369. attrs := parse.IAL2Map(node.KramdownIAL)
  2370. if "" == attrs[av.NodeAttrNameAvs] {
  2371. attrs[av.NodeAttrNameAvs] = avID
  2372. } else {
  2373. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2374. avIDs = append(avIDs, avID)
  2375. avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
  2376. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2377. }
  2378. if nil != tx {
  2379. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2380. } else {
  2381. err = setNodeAttrs(node, tree, attrs)
  2382. }
  2383. if nil != err {
  2384. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  2385. return
  2386. }
  2387. return
  2388. }
  2389. func getNodeByBlockID(tx *Transaction, blockID string) (node *ast.Node, tree *parse.Tree, err error) {
  2390. if nil != tx {
  2391. tree, err = tx.loadTree(blockID)
  2392. } else {
  2393. tree, err = loadTreeByBlockID(blockID)
  2394. }
  2395. if nil != err {
  2396. return
  2397. }
  2398. node = treenode.GetNodeInTree(tree, blockID)
  2399. if nil == node {
  2400. logging.LogWarnf("node [%s] not found in tree [%s]", blockID, tree.ID)
  2401. return
  2402. }
  2403. return
  2404. }
  2405. func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *TxErr) {
  2406. err := updateAttributeViewColumnOptions(operation)
  2407. if nil != err {
  2408. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2409. }
  2410. return
  2411. }
  2412. func updateAttributeViewColumnOptions(operation *Operation) (err error) {
  2413. attrView, err := av.ParseAttributeView(operation.AvID)
  2414. if nil != err {
  2415. return
  2416. }
  2417. jsonData, err := gulu.JSON.MarshalJSON(operation.Data)
  2418. if nil != err {
  2419. return
  2420. }
  2421. options := []*av.SelectOption{}
  2422. if err = gulu.JSON.UnmarshalJSON(jsonData, &options); nil != err {
  2423. return
  2424. }
  2425. for _, keyValues := range attrView.KeyValues {
  2426. if keyValues.Key.ID == operation.ID {
  2427. keyValues.Key.Options = options
  2428. err = av.SaveAttributeView(attrView)
  2429. return
  2430. }
  2431. }
  2432. return
  2433. }
  2434. func (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {
  2435. err := removeAttributeViewColumnOption(operation)
  2436. if nil != err {
  2437. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2438. }
  2439. return
  2440. }
  2441. func removeAttributeViewColumnOption(operation *Operation) (err error) {
  2442. attrView, err := av.ParseAttributeView(operation.AvID)
  2443. if nil != err {
  2444. return
  2445. }
  2446. optName := operation.Data.(string)
  2447. key, err := attrView.GetKey(operation.ID)
  2448. if nil != err {
  2449. return
  2450. }
  2451. for i, opt := range key.Options {
  2452. if optName == opt.Name {
  2453. key.Options = append(key.Options[:i], key.Options[i+1:]...)
  2454. break
  2455. }
  2456. }
  2457. for _, keyValues := range attrView.KeyValues {
  2458. if keyValues.Key.ID != operation.ID {
  2459. continue
  2460. }
  2461. for _, value := range keyValues.Values {
  2462. if nil == value || nil == value.MSelect {
  2463. continue
  2464. }
  2465. for i, opt := range value.MSelect {
  2466. if optName == opt.Content {
  2467. value.MSelect = append(value.MSelect[:i], value.MSelect[i+1:]...)
  2468. break
  2469. }
  2470. }
  2471. }
  2472. break
  2473. }
  2474. err = av.SaveAttributeView(attrView)
  2475. return
  2476. }
  2477. func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) {
  2478. err := updateAttributeViewColumnOption(operation)
  2479. if nil != err {
  2480. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2481. }
  2482. return
  2483. }
  2484. func updateAttributeViewColumnOption(operation *Operation) (err error) {
  2485. attrView, err := av.ParseAttributeView(operation.AvID)
  2486. if nil != err {
  2487. return
  2488. }
  2489. key, err := attrView.GetKey(operation.ID)
  2490. if nil != err {
  2491. return
  2492. }
  2493. data := operation.Data.(map[string]interface{})
  2494. oldName := data["oldName"].(string)
  2495. newName := data["newName"].(string)
  2496. newColor := data["newColor"].(string)
  2497. for i, opt := range key.Options {
  2498. if oldName == opt.Name {
  2499. key.Options[i].Name = newName
  2500. key.Options[i].Color = newColor
  2501. break
  2502. }
  2503. }
  2504. for _, keyValues := range attrView.KeyValues {
  2505. if keyValues.Key.ID != operation.ID {
  2506. continue
  2507. }
  2508. for _, value := range keyValues.Values {
  2509. if nil == value || nil == value.MSelect {
  2510. continue
  2511. }
  2512. for i, opt := range value.MSelect {
  2513. if oldName == opt.Content {
  2514. value.MSelect[i].Content = newName
  2515. value.MSelect[i].Color = newColor
  2516. break
  2517. }
  2518. }
  2519. }
  2520. break
  2521. }
  2522. err = av.SaveAttributeView(attrView)
  2523. return
  2524. }