attribute_view.go 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887
  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. val.Number.Content = 0
  2226. val.Number.FormattedContent = ""
  2227. }
  2228. } else if av.KeyTypeDate == val.Type {
  2229. if nil != val.Date && !val.Date.IsNotEmpty {
  2230. val.Date.Content = 0
  2231. val.Date.FormattedContent = ""
  2232. }
  2233. }
  2234. relationChangeMode := 0 // 0:不变(仅排序),1:增加,2:减少
  2235. if av.KeyTypeRelation == val.Type {
  2236. // 关联列得 content 是自动渲染的,所以不需要保存
  2237. val.Relation.Contents = nil
  2238. // 计算关联变更模式
  2239. if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
  2240. relationChangeMode = 0
  2241. } else {
  2242. if len(oldRelationBlockIDs) > len(val.Relation.BlockIDs) {
  2243. relationChangeMode = 2
  2244. } else {
  2245. relationChangeMode = 1
  2246. }
  2247. }
  2248. }
  2249. // val.IsDetached 只有更新主键的时候才会传入,所以下面需要结合 isUpdatingBlockKey 来判断
  2250. if oldIsDetached { // 之前是游离行
  2251. if !val.IsDetached { // 现在绑定了块
  2252. // 将游离行绑定到新建的块上
  2253. bindBlockAv(tx, avID, rowID)
  2254. }
  2255. } else { // 之前绑定了块
  2256. if isUpdatingBlockKey { // 正在更新主键
  2257. if val.IsDetached { // 现在是游离行
  2258. // 将绑定的块从属性视图中移除
  2259. unbindBlockAv(tx, avID, rowID)
  2260. } else { // 现在绑定了块
  2261. if oldBoundBlockID != val.BlockID { // 之前绑定的块和现在绑定的块不一样
  2262. // 换绑块
  2263. unbindBlockAv(tx, avID, oldBoundBlockID)
  2264. bindBlockAv(tx, avID, val.BlockID)
  2265. } else { // 之前绑定的块和现在绑定的块一样
  2266. // 直接返回,因为锚文本不允许更改
  2267. return
  2268. }
  2269. }
  2270. }
  2271. }
  2272. if nil != blockVal {
  2273. blockVal.Block.Updated = time.Now().UnixMilli()
  2274. if isUpdatingBlockKey {
  2275. blockVal.IsDetached = val.IsDetached
  2276. }
  2277. }
  2278. key, _ := attrView.GetKey(val.KeyID)
  2279. if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation {
  2280. destAv, _ := av.ParseAttributeView(key.Relation.AvID)
  2281. if nil != destAv {
  2282. if key.Relation.IsTwoWay {
  2283. // relationChangeMode
  2284. // 0:关联列值不变(仅排序),不影响目标值
  2285. // 1:关联列值增加,增加目标值
  2286. // 2:关联列值减少,减少目标值
  2287. if 1 == relationChangeMode {
  2288. addBlockIDs := val.Relation.BlockIDs
  2289. for _, bID := range oldRelationBlockIDs {
  2290. addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID)
  2291. }
  2292. for _, blockID := range addBlockIDs {
  2293. for _, keyValues := range destAv.KeyValues {
  2294. if keyValues.Key.ID != key.Relation.BackKeyID {
  2295. continue
  2296. }
  2297. destVal := keyValues.GetValue(blockID)
  2298. if nil == destVal {
  2299. destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}}
  2300. keyValues.Values = append(keyValues.Values, destVal)
  2301. }
  2302. destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID)
  2303. destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs)
  2304. break
  2305. }
  2306. }
  2307. } else if 2 == relationChangeMode {
  2308. removeBlockIDs := oldRelationBlockIDs
  2309. for _, bID := range val.Relation.BlockIDs {
  2310. removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID)
  2311. }
  2312. for _, blockID := range removeBlockIDs {
  2313. for _, keyValues := range destAv.KeyValues {
  2314. if keyValues.Key.ID != key.Relation.BackKeyID {
  2315. continue
  2316. }
  2317. for _, value := range keyValues.Values {
  2318. if value.BlockID == blockID {
  2319. value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID)
  2320. break
  2321. }
  2322. }
  2323. }
  2324. }
  2325. }
  2326. av.SaveAttributeView(destAv)
  2327. }
  2328. }
  2329. }
  2330. relatedAvIDs := av.GetSrcAvIDs(avID)
  2331. for _, relatedAvID := range relatedAvIDs {
  2332. util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": relatedAvID})
  2333. }
  2334. if err = av.SaveAttributeView(attrView); nil != err {
  2335. return
  2336. }
  2337. return
  2338. }
  2339. func unbindBlockAv(tx *Transaction, avID, blockID string) {
  2340. node, tree, err := getNodeByBlockID(tx, blockID)
  2341. if nil != err {
  2342. return
  2343. }
  2344. attrs := parse.IAL2Map(node.KramdownIAL)
  2345. if "" == attrs[av.NodeAttrNameAvs] {
  2346. return
  2347. }
  2348. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2349. avIDs = gulu.Str.RemoveElem(avIDs, avID)
  2350. if 0 == len(avIDs) {
  2351. delete(attrs, av.NodeAttrNameAvs)
  2352. node.RemoveIALAttr(av.NodeAttrNameAvs)
  2353. } else {
  2354. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2355. node.SetIALAttr(av.NodeAttrNameAvs, strings.Join(avIDs, ","))
  2356. }
  2357. if nil != tx {
  2358. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2359. } else {
  2360. err = setNodeAttrs(node, tree, attrs)
  2361. }
  2362. if nil != err {
  2363. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  2364. return
  2365. }
  2366. return
  2367. }
  2368. func bindBlockAv(tx *Transaction, avID, blockID string) {
  2369. node, tree, err := getNodeByBlockID(tx, blockID)
  2370. if nil != err {
  2371. return
  2372. }
  2373. attrs := parse.IAL2Map(node.KramdownIAL)
  2374. if "" == attrs[av.NodeAttrNameAvs] {
  2375. attrs[av.NodeAttrNameAvs] = avID
  2376. } else {
  2377. avIDs := strings.Split(attrs[av.NodeAttrNameAvs], ",")
  2378. avIDs = append(avIDs, avID)
  2379. avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
  2380. attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
  2381. }
  2382. if nil != tx {
  2383. err = setNodeAttrsWithTx(tx, node, tree, attrs)
  2384. } else {
  2385. err = setNodeAttrs(node, tree, attrs)
  2386. }
  2387. if nil != err {
  2388. logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err)
  2389. return
  2390. }
  2391. return
  2392. }
  2393. func getNodeByBlockID(tx *Transaction, blockID string) (node *ast.Node, tree *parse.Tree, err error) {
  2394. if nil != tx {
  2395. tree, err = tx.loadTree(blockID)
  2396. } else {
  2397. tree, err = loadTreeByBlockID(blockID)
  2398. }
  2399. if nil != err {
  2400. return
  2401. }
  2402. node = treenode.GetNodeInTree(tree, blockID)
  2403. if nil == node {
  2404. logging.LogWarnf("node [%s] not found in tree [%s]", blockID, tree.ID)
  2405. return
  2406. }
  2407. return
  2408. }
  2409. func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *TxErr) {
  2410. err := updateAttributeViewColumnOptions(operation)
  2411. if nil != err {
  2412. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2413. }
  2414. return
  2415. }
  2416. func updateAttributeViewColumnOptions(operation *Operation) (err error) {
  2417. attrView, err := av.ParseAttributeView(operation.AvID)
  2418. if nil != err {
  2419. return
  2420. }
  2421. jsonData, err := gulu.JSON.MarshalJSON(operation.Data)
  2422. if nil != err {
  2423. return
  2424. }
  2425. options := []*av.SelectOption{}
  2426. if err = gulu.JSON.UnmarshalJSON(jsonData, &options); nil != err {
  2427. return
  2428. }
  2429. for _, keyValues := range attrView.KeyValues {
  2430. if keyValues.Key.ID == operation.ID {
  2431. keyValues.Key.Options = options
  2432. err = av.SaveAttributeView(attrView)
  2433. return
  2434. }
  2435. }
  2436. return
  2437. }
  2438. func (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {
  2439. err := removeAttributeViewColumnOption(operation)
  2440. if nil != err {
  2441. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2442. }
  2443. return
  2444. }
  2445. func removeAttributeViewColumnOption(operation *Operation) (err error) {
  2446. attrView, err := av.ParseAttributeView(operation.AvID)
  2447. if nil != err {
  2448. return
  2449. }
  2450. optName := operation.Data.(string)
  2451. key, err := attrView.GetKey(operation.ID)
  2452. if nil != err {
  2453. return
  2454. }
  2455. for i, opt := range key.Options {
  2456. if optName == opt.Name {
  2457. key.Options = append(key.Options[:i], key.Options[i+1:]...)
  2458. break
  2459. }
  2460. }
  2461. for _, keyValues := range attrView.KeyValues {
  2462. if keyValues.Key.ID != operation.ID {
  2463. continue
  2464. }
  2465. for _, value := range keyValues.Values {
  2466. if nil == value || nil == value.MSelect {
  2467. continue
  2468. }
  2469. for i, opt := range value.MSelect {
  2470. if optName == opt.Content {
  2471. value.MSelect = append(value.MSelect[:i], value.MSelect[i+1:]...)
  2472. break
  2473. }
  2474. }
  2475. }
  2476. break
  2477. }
  2478. err = av.SaveAttributeView(attrView)
  2479. return
  2480. }
  2481. func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) {
  2482. err := updateAttributeViewColumnOption(operation)
  2483. if nil != err {
  2484. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  2485. }
  2486. return
  2487. }
  2488. func updateAttributeViewColumnOption(operation *Operation) (err error) {
  2489. attrView, err := av.ParseAttributeView(operation.AvID)
  2490. if nil != err {
  2491. return
  2492. }
  2493. key, err := attrView.GetKey(operation.ID)
  2494. if nil != err {
  2495. return
  2496. }
  2497. data := operation.Data.(map[string]interface{})
  2498. oldName := data["oldName"].(string)
  2499. newName := data["newName"].(string)
  2500. newColor := data["newColor"].(string)
  2501. for i, opt := range key.Options {
  2502. if oldName == opt.Name {
  2503. key.Options[i].Name = newName
  2504. key.Options[i].Color = newColor
  2505. break
  2506. }
  2507. }
  2508. for _, keyValues := range attrView.KeyValues {
  2509. if keyValues.Key.ID != operation.ID {
  2510. continue
  2511. }
  2512. for _, value := range keyValues.Values {
  2513. if nil == value || nil == value.MSelect {
  2514. continue
  2515. }
  2516. for i, opt := range value.MSelect {
  2517. if oldName == opt.Content {
  2518. value.MSelect[i].Content = newName
  2519. value.MSelect[i].Color = newColor
  2520. break
  2521. }
  2522. }
  2523. }
  2524. break
  2525. }
  2526. err = av.SaveAttributeView(attrView)
  2527. return
  2528. }