attribute_view.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  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. "sort"
  19. "strings"
  20. "github.com/88250/gulu"
  21. "github.com/88250/lute/ast"
  22. "github.com/88250/lute/parse"
  23. "github.com/siyuan-note/logging"
  24. "github.com/siyuan-note/siyuan/kernel/av"
  25. "github.com/siyuan-note/siyuan/kernel/sql"
  26. "github.com/siyuan-note/siyuan/kernel/treenode"
  27. "github.com/siyuan-note/siyuan/kernel/util"
  28. )
  29. type BlockAttributeViewKeys struct {
  30. AvID string `json:"avID"`
  31. AvName string `json:"avName"`
  32. KeyValues []*av.KeyValues `json:"keyValues"`
  33. }
  34. func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
  35. waitForSyncingStorages()
  36. ret = []*BlockAttributeViewKeys{}
  37. attrs := GetBlockAttrs(blockID)
  38. avs := attrs[NodeAttrNameAvs]
  39. if "" == avs {
  40. return
  41. }
  42. avIDs := strings.Split(avs, ",")
  43. for _, avID := range avIDs {
  44. attrView, err := av.ParseAttributeView(avID)
  45. if nil != err {
  46. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  47. return
  48. }
  49. if 1 > len(attrView.Views) {
  50. err = av.ErrViewNotFound
  51. return
  52. }
  53. var keyValues []*av.KeyValues
  54. for _, kv := range attrView.KeyValues {
  55. if av.KeyTypeBlock == kv.Key.Type {
  56. continue
  57. }
  58. kValues := &av.KeyValues{Key: kv.Key}
  59. for _, v := range kv.Values {
  60. if v.BlockID == blockID {
  61. kValues.Values = append(kValues.Values, v)
  62. }
  63. }
  64. if 0 < len(kValues.Values) {
  65. keyValues = append(keyValues, kValues)
  66. }
  67. }
  68. ret = append(ret, &BlockAttributeViewKeys{
  69. AvID: avID,
  70. AvName: attrView.Name,
  71. KeyValues: keyValues,
  72. })
  73. }
  74. return
  75. }
  76. func RenderAttributeView(avID, nodeID string) (viewable av.Viewable, attrView *av.AttributeView, err error) {
  77. waitForSyncingStorages()
  78. if avJSONPath := av.GetAttributeViewDataPath(avID); !gulu.File.IsExist(avJSONPath) {
  79. attrView = av.NewAttributeView(avID, nodeID)
  80. if err = av.SaveAttributeView(attrView); nil != err {
  81. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  82. return
  83. }
  84. }
  85. attrView, err = av.ParseAttributeView(avID)
  86. if nil != err {
  87. logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
  88. return
  89. }
  90. if "" == attrView.NodeID {
  91. attrView.NodeID = nodeID
  92. if err = av.SaveAttributeView(attrView); nil != err {
  93. logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
  94. return
  95. }
  96. }
  97. if 1 > len(attrView.Views) {
  98. err = av.ErrViewNotFound
  99. return
  100. }
  101. var view *av.View
  102. if "" != attrView.ViewID {
  103. for _, v := range attrView.Views {
  104. if v.ID == attrView.ViewID {
  105. view = v
  106. break
  107. }
  108. }
  109. } else {
  110. view = attrView.Views[0]
  111. }
  112. switch view.LayoutType {
  113. case av.LayoutTypeTable:
  114. viewable, err = renderAttributeViewTable(attrView, view)
  115. }
  116. viewable.FilterRows()
  117. viewable.SortRows()
  118. viewable.CalcCols()
  119. return
  120. }
  121. func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *av.Table, err error) {
  122. ret = &av.Table{
  123. ID: view.ID,
  124. Name: view.Name,
  125. Columns: []*av.TableColumn{},
  126. Rows: []*av.TableRow{},
  127. Filters: view.Table.Filters,
  128. Sorts: view.Table.Sorts,
  129. }
  130. // 组装列
  131. for _, col := range view.Table.Columns {
  132. key, getErr := attrView.GetKey(col.ID)
  133. if nil != getErr {
  134. err = getErr
  135. return
  136. }
  137. ret.Columns = append(ret.Columns, &av.TableColumn{
  138. ID: key.ID,
  139. Name: key.Name,
  140. Type: key.Type,
  141. Icon: key.Icon,
  142. Options: key.Options,
  143. NumberFormat: key.NumberFormat,
  144. Wrap: col.Wrap,
  145. Hidden: col.Hidden,
  146. Width: col.Width,
  147. Calc: col.Calc,
  148. })
  149. }
  150. // 生成行
  151. rows := map[string][]*av.Value{}
  152. for _, keyValues := range attrView.KeyValues {
  153. for _, val := range keyValues.Values {
  154. rows[val.BlockID] = append(rows[val.BlockID], val)
  155. }
  156. }
  157. // 过滤掉不存在的行
  158. notFound := []string{}
  159. for blockID, _ := range rows {
  160. if treenode.GetBlockTree(blockID) == nil {
  161. notFound = append(notFound, blockID)
  162. }
  163. }
  164. for _, blockID := range notFound {
  165. delete(rows, blockID)
  166. }
  167. // 生成行单元格
  168. for rowID, row := range rows {
  169. var tableRow av.TableRow
  170. for _, col := range ret.Columns {
  171. var tableCell *av.TableCell
  172. for _, val := range row {
  173. if val.KeyID == col.ID {
  174. tableCell = &av.TableCell{
  175. ID: val.ID,
  176. Value: val,
  177. ValueType: col.Type,
  178. }
  179. break
  180. }
  181. }
  182. if nil == tableCell {
  183. tableCell = &av.TableCell{
  184. ID: ast.NewNodeID(),
  185. ValueType: col.Type,
  186. }
  187. }
  188. tableRow.ID = rowID
  189. // 格式化数字
  190. if av.KeyTypeNumber == tableCell.ValueType && nil != tableCell.Value && nil != tableCell.Value.Number {
  191. tableCell.Value.Number.Format = col.NumberFormat
  192. tableCell.Value.Number.FormatNumber()
  193. }
  194. tableRow.Cells = append(tableRow.Cells, tableCell)
  195. }
  196. ret.Rows = append(ret.Rows, &tableRow)
  197. }
  198. // 自定义排序
  199. sortRowIDs := map[string]int{}
  200. if 0 < len(view.Table.RowIDs) {
  201. for i, rowID := range view.Table.RowIDs {
  202. sortRowIDs[rowID] = i
  203. }
  204. }
  205. sort.Slice(ret.Rows, func(i, j int) bool {
  206. iv := sortRowIDs[ret.Rows[i].ID]
  207. jv := sortRowIDs[ret.Rows[j].ID]
  208. if iv == jv {
  209. return ret.Rows[i].ID < ret.Rows[j].ID
  210. }
  211. return iv < jv
  212. })
  213. return
  214. }
  215. func (tx *Transaction) doSetAttrViewName(operation *Operation) (ret *TxErr) {
  216. err := setAttributeViewName(operation)
  217. if nil != err {
  218. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  219. }
  220. return
  221. }
  222. func setAttributeViewName(operation *Operation) (err error) {
  223. attrView, err := av.ParseAttributeView(operation.ID)
  224. if nil != err {
  225. return
  226. }
  227. attrView.Name = operation.Data.(string)
  228. data, err := gulu.JSON.MarshalJSON(attrView)
  229. if nil != err {
  230. return
  231. }
  232. if err = gulu.JSON.UnmarshalJSON(data, attrView); nil != err {
  233. return
  234. }
  235. err = av.SaveAttributeView(attrView)
  236. return
  237. }
  238. func (tx *Transaction) doSetAttrViewFilters(operation *Operation) (ret *TxErr) {
  239. err := setAttributeViewFilters(operation)
  240. if nil != err {
  241. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  242. }
  243. return
  244. }
  245. func setAttributeViewFilters(operation *Operation) (err error) {
  246. attrView, err := av.ParseAttributeView(operation.AvID)
  247. if nil != err {
  248. return
  249. }
  250. view, err := attrView.GetView()
  251. if nil != err {
  252. return
  253. }
  254. operationData := operation.Data.([]interface{})
  255. data, err := gulu.JSON.MarshalJSON(operationData)
  256. if nil != err {
  257. return
  258. }
  259. switch view.LayoutType {
  260. case av.LayoutTypeTable:
  261. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Filters); nil != err {
  262. return
  263. }
  264. }
  265. for _, filter := range view.Table.Filters {
  266. var key *av.Key
  267. key, err = attrView.GetKey(filter.Column)
  268. if nil != err {
  269. return
  270. }
  271. filter.Value.Type = key.Type
  272. }
  273. err = av.SaveAttributeView(attrView)
  274. return
  275. }
  276. func (tx *Transaction) doSetAttrViewSorts(operation *Operation) (ret *TxErr) {
  277. err := setAttributeViewSorts(operation)
  278. if nil != err {
  279. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  280. }
  281. return
  282. }
  283. func setAttributeViewSorts(operation *Operation) (err error) {
  284. attrView, err := av.ParseAttributeView(operation.AvID)
  285. if nil != err {
  286. return
  287. }
  288. view, err := attrView.GetView()
  289. if nil != err {
  290. return
  291. }
  292. operationData := operation.Data.([]interface{})
  293. data, err := gulu.JSON.MarshalJSON(operationData)
  294. if nil != err {
  295. return
  296. }
  297. switch view.LayoutType {
  298. case av.LayoutTypeTable:
  299. if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Sorts); nil != err {
  300. return
  301. }
  302. }
  303. err = av.SaveAttributeView(attrView)
  304. return
  305. }
  306. func (tx *Transaction) doSetAttrViewColCalc(operation *Operation) (ret *TxErr) {
  307. err := setAttributeViewColumnCalc(operation)
  308. if nil != err {
  309. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  310. }
  311. return
  312. }
  313. func setAttributeViewColumnCalc(operation *Operation) (err error) {
  314. attrView, err := av.ParseAttributeView(operation.AvID)
  315. if nil != err {
  316. return
  317. }
  318. view, err := attrView.GetView()
  319. if nil != err {
  320. return
  321. }
  322. operationData := operation.Data.(interface{})
  323. data, err := gulu.JSON.MarshalJSON(operationData)
  324. if nil != err {
  325. return
  326. }
  327. calc := &av.ColumnCalc{}
  328. switch view.LayoutType {
  329. case av.LayoutTypeTable:
  330. if err = gulu.JSON.UnmarshalJSON(data, calc); nil != err {
  331. return
  332. }
  333. for _, column := range view.Table.Columns {
  334. if column.ID == operation.ID {
  335. column.Calc = calc
  336. break
  337. }
  338. }
  339. }
  340. err = av.SaveAttributeView(attrView)
  341. return
  342. }
  343. func (tx *Transaction) doInsertAttrViewBlock(operation *Operation) (ret *TxErr) {
  344. for _, id := range operation.SrcIDs {
  345. tree, err := tx.loadTree(id)
  346. if nil != err {
  347. logging.LogErrorf("load tree [%s] failed: %s", id, err)
  348. return &TxErr{code: TxErrCodeBlockNotFound, id: id, msg: err.Error()}
  349. }
  350. var avErr error
  351. if avErr = addAttributeViewBlock(id, operation, tree, tx); nil != avErr {
  352. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: avErr.Error()}
  353. }
  354. }
  355. return
  356. }
  357. func addAttributeViewBlock(blockID string, operation *Operation, tree *parse.Tree, tx *Transaction) (err error) {
  358. node := treenode.GetNodeInTree(tree, blockID)
  359. if nil == node {
  360. err = ErrBlockNotFound
  361. return
  362. }
  363. if ast.NodeAttributeView == node.Type {
  364. // 不能将一个属性视图拖拽到另一个属性视图中
  365. return
  366. }
  367. block := sql.BuildBlockFromNode(node, tree)
  368. if nil == block {
  369. err = ErrBlockNotFound
  370. return
  371. }
  372. attrView, err := av.ParseAttributeView(operation.AvID)
  373. if nil != err {
  374. return
  375. }
  376. view, err := attrView.GetView()
  377. if nil != err {
  378. return
  379. }
  380. // 不允许重复添加相同的块到属性视图中
  381. blockValues := attrView.GetBlockKeyValues()
  382. for _, blockValue := range blockValues.Values {
  383. if blockValue.Block.ID == blockID {
  384. return
  385. }
  386. }
  387. value := &av.Value{ID: ast.NewNodeID(), KeyID: blockValues.Key.ID, BlockID: blockID, Block: &av.ValueBlock{ID: blockID, Content: getNodeRefText(node)}}
  388. blockValues.Values = append(blockValues.Values, value)
  389. attrs := parse.IAL2Map(node.KramdownIAL)
  390. attrs[NodeAttrNamePrefixAvKey+operation.AvID+"-"+blockValues.Key.ID] = "" // 将列作为属性添加到块中
  391. if "" == attrs[NodeAttrNameAvs] {
  392. attrs[NodeAttrNameAvs] = operation.AvID
  393. } else {
  394. avIDs := strings.Split(attrs[NodeAttrNameAvs], ",")
  395. avIDs = append(avIDs, operation.AvID)
  396. avIDs = gulu.Str.RemoveDuplicatedElem(avIDs)
  397. attrs[NodeAttrNameAvs] = strings.Join(avIDs, ",")
  398. }
  399. if err = setNodeAttrsWithTx(tx, node, tree, attrs); nil != err {
  400. return
  401. }
  402. switch view.LayoutType {
  403. case av.LayoutTypeTable:
  404. if "" != operation.PreviousID {
  405. for i, id := range view.Table.RowIDs {
  406. if id == operation.PreviousID {
  407. view.Table.RowIDs = append(view.Table.RowIDs[:i+1], append([]string{blockID}, view.Table.RowIDs[i+1:]...)...)
  408. break
  409. }
  410. }
  411. } else {
  412. view.Table.RowIDs = append(view.Table.RowIDs, blockID)
  413. }
  414. }
  415. err = av.SaveAttributeView(attrView)
  416. return
  417. }
  418. func (tx *Transaction) doRemoveAttrViewBlock(operation *Operation) (ret *TxErr) {
  419. err := removeAttributeViewBlock(operation)
  420. if nil != err {
  421. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID}
  422. }
  423. return
  424. }
  425. func removeAttributeViewBlock(operation *Operation) (err error) {
  426. attrView, err := av.ParseAttributeView(operation.AvID)
  427. if nil != err {
  428. return
  429. }
  430. view, err := attrView.GetView()
  431. if nil != err {
  432. return
  433. }
  434. for _, keyValues := range attrView.KeyValues {
  435. tmp := keyValues.Values[:0]
  436. for i, values := range keyValues.Values {
  437. if !gulu.Str.Contains(values.BlockID, operation.SrcIDs) {
  438. tmp = append(tmp, keyValues.Values[i])
  439. }
  440. }
  441. keyValues.Values = tmp
  442. }
  443. for _, blockID := range operation.SrcIDs {
  444. view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
  445. }
  446. err = av.SaveAttributeView(attrView)
  447. return
  448. }
  449. func (tx *Transaction) doSetAttrViewColumnWidth(operation *Operation) (ret *TxErr) {
  450. err := setAttributeViewColWidth(operation)
  451. if nil != err {
  452. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  453. }
  454. return
  455. }
  456. func setAttributeViewColWidth(operation *Operation) (err error) {
  457. attrView, err := av.ParseAttributeView(operation.AvID)
  458. if nil != err {
  459. return
  460. }
  461. view, err := attrView.GetView()
  462. if nil != err {
  463. return
  464. }
  465. switch view.LayoutType {
  466. case av.LayoutTypeTable:
  467. for _, column := range view.Table.Columns {
  468. if column.ID == operation.ID {
  469. column.Width = operation.Data.(string)
  470. break
  471. }
  472. }
  473. }
  474. err = av.SaveAttributeView(attrView)
  475. return
  476. }
  477. func (tx *Transaction) doSetAttrViewColumnWrap(operation *Operation) (ret *TxErr) {
  478. err := setAttributeViewColWrap(operation)
  479. if nil != err {
  480. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  481. }
  482. return
  483. }
  484. func setAttributeViewColWrap(operation *Operation) (err error) {
  485. attrView, err := av.ParseAttributeView(operation.AvID)
  486. if nil != err {
  487. return
  488. }
  489. view, err := attrView.GetView()
  490. if nil != err {
  491. return
  492. }
  493. switch view.LayoutType {
  494. case av.LayoutTypeTable:
  495. for _, column := range view.Table.Columns {
  496. if column.ID == operation.ID {
  497. column.Wrap = operation.Data.(bool)
  498. break
  499. }
  500. }
  501. }
  502. err = av.SaveAttributeView(attrView)
  503. return
  504. }
  505. func (tx *Transaction) doSetAttrViewColumnHidden(operation *Operation) (ret *TxErr) {
  506. err := setAttributeViewColHidden(operation)
  507. if nil != err {
  508. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  509. }
  510. return
  511. }
  512. func setAttributeViewColHidden(operation *Operation) (err error) {
  513. attrView, err := av.ParseAttributeView(operation.AvID)
  514. if nil != err {
  515. return
  516. }
  517. view, err := attrView.GetView()
  518. if nil != err {
  519. return
  520. }
  521. switch view.LayoutType {
  522. case av.LayoutTypeTable:
  523. for _, column := range view.Table.Columns {
  524. if column.ID == operation.ID {
  525. column.Hidden = operation.Data.(bool)
  526. break
  527. }
  528. }
  529. }
  530. err = av.SaveAttributeView(attrView)
  531. return
  532. }
  533. func (tx *Transaction) doSortAttrViewRow(operation *Operation) (ret *TxErr) {
  534. err := sortAttributeViewRow(operation)
  535. if nil != err {
  536. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  537. }
  538. return
  539. }
  540. func sortAttributeViewRow(operation *Operation) (err error) {
  541. attrView, err := av.ParseAttributeView(operation.AvID)
  542. if nil != err {
  543. return
  544. }
  545. view, err := attrView.GetView()
  546. if nil != err {
  547. return
  548. }
  549. var rowID string
  550. var index, previousIndex int
  551. for i, r := range view.Table.RowIDs {
  552. if r == operation.ID {
  553. rowID = r
  554. index = i
  555. break
  556. }
  557. }
  558. if "" == rowID {
  559. return
  560. }
  561. switch view.LayoutType {
  562. case av.LayoutTypeTable:
  563. view.Table.RowIDs = append(view.Table.RowIDs[:index], view.Table.RowIDs[index+1:]...)
  564. for i, r := range view.Table.RowIDs {
  565. if r == operation.PreviousID {
  566. previousIndex = i + 1
  567. break
  568. }
  569. }
  570. view.Table.RowIDs = util.InsertElem(view.Table.RowIDs, previousIndex, rowID)
  571. }
  572. err = av.SaveAttributeView(attrView)
  573. return
  574. }
  575. func (tx *Transaction) doSortAttrViewColumn(operation *Operation) (ret *TxErr) {
  576. err := sortAttributeViewColumn(operation)
  577. if nil != err {
  578. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  579. }
  580. return
  581. }
  582. func sortAttributeViewColumn(operation *Operation) (err error) {
  583. attrView, err := av.ParseAttributeView(operation.AvID)
  584. if nil != err {
  585. return
  586. }
  587. view, err := attrView.GetView()
  588. if nil != err {
  589. return
  590. }
  591. switch view.LayoutType {
  592. case av.LayoutTypeTable:
  593. var col *av.ViewTableColumn
  594. var index, previousIndex int
  595. for i, column := range view.Table.Columns {
  596. if column.ID == operation.ID {
  597. col = column
  598. index = i
  599. break
  600. }
  601. }
  602. if nil == col {
  603. return
  604. }
  605. view.Table.Columns = append(view.Table.Columns[:index], view.Table.Columns[index+1:]...)
  606. for i, column := range view.Table.Columns {
  607. if column.ID == operation.PreviousID {
  608. previousIndex = i + 1
  609. break
  610. }
  611. }
  612. view.Table.Columns = util.InsertElem(view.Table.Columns, previousIndex, col)
  613. }
  614. err = av.SaveAttributeView(attrView)
  615. return
  616. }
  617. func (tx *Transaction) doAddAttrViewColumn(operation *Operation) (ret *TxErr) {
  618. err := addAttributeViewColumn(operation)
  619. if nil != err {
  620. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  621. }
  622. return
  623. }
  624. func addAttributeViewColumn(operation *Operation) (err error) {
  625. attrView, err := av.ParseAttributeView(operation.AvID)
  626. if nil != err {
  627. return
  628. }
  629. view, err := attrView.GetView()
  630. if nil != err {
  631. return
  632. }
  633. keyType := av.KeyType(operation.Typ)
  634. switch keyType {
  635. case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone:
  636. key := av.NewKey(operation.ID, operation.Name, keyType)
  637. attrView.KeyValues = append(attrView.KeyValues, &av.KeyValues{Key: key})
  638. switch view.LayoutType {
  639. case av.LayoutTypeTable:
  640. view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{ID: key.ID})
  641. }
  642. }
  643. err = av.SaveAttributeView(attrView)
  644. return
  645. }
  646. func (tx *Transaction) doUpdateAttrViewColNumberFormat(operation *Operation) (ret *TxErr) {
  647. err := updateAttributeViewColNumberFormat(operation)
  648. if nil != err {
  649. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  650. }
  651. return
  652. }
  653. func updateAttributeViewColNumberFormat(operation *Operation) (err error) {
  654. attrView, err := av.ParseAttributeView(operation.AvID)
  655. if nil != err {
  656. return
  657. }
  658. colType := av.KeyType(operation.Typ)
  659. switch colType {
  660. case av.KeyTypeNumber:
  661. for _, keyValues := range attrView.KeyValues {
  662. if keyValues.Key.ID == operation.ID && av.KeyTypeNumber == keyValues.Key.Type {
  663. keyValues.Key.NumberFormat = av.NumberFormat(operation.Format)
  664. break
  665. }
  666. }
  667. }
  668. err = av.SaveAttributeView(attrView)
  669. return
  670. }
  671. func (tx *Transaction) doUpdateAttrViewColumn(operation *Operation) (ret *TxErr) {
  672. err := updateAttributeViewColumn(operation)
  673. if nil != err {
  674. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  675. }
  676. return
  677. }
  678. func updateAttributeViewColumn(operation *Operation) (err error) {
  679. attrView, err := av.ParseAttributeView(operation.AvID)
  680. if nil != err {
  681. return
  682. }
  683. colType := av.KeyType(operation.Typ)
  684. switch colType {
  685. case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, av.KeyTypePhone:
  686. for _, keyValues := range attrView.KeyValues {
  687. if keyValues.Key.ID == operation.ID {
  688. keyValues.Key.Name = operation.Name
  689. keyValues.Key.Type = colType
  690. break
  691. }
  692. }
  693. }
  694. err = av.SaveAttributeView(attrView)
  695. return
  696. }
  697. func (tx *Transaction) doRemoveAttrViewColumn(operation *Operation) (ret *TxErr) {
  698. err := removeAttributeViewColumn(operation)
  699. if nil != err {
  700. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  701. }
  702. return
  703. }
  704. func removeAttributeViewColumn(operation *Operation) (err error) {
  705. attrView, err := av.ParseAttributeView(operation.AvID)
  706. if nil != err {
  707. return
  708. }
  709. for i, keyValues := range attrView.KeyValues {
  710. if keyValues.Key.ID == operation.ID {
  711. attrView.KeyValues = append(attrView.KeyValues[:i], attrView.KeyValues[i+1:]...)
  712. break
  713. }
  714. }
  715. for _, view := range attrView.Views {
  716. switch view.LayoutType {
  717. case av.LayoutTypeTable:
  718. for i, column := range view.Table.Columns {
  719. if column.ID == operation.ID {
  720. view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...)
  721. break
  722. }
  723. }
  724. }
  725. }
  726. err = av.SaveAttributeView(attrView)
  727. return
  728. }
  729. func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) {
  730. err := updateAttributeViewCell(operation, tx)
  731. if nil != err {
  732. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  733. }
  734. return
  735. }
  736. func updateAttributeViewCell(operation *Operation, tx *Transaction) (err error) {
  737. err = UpdateAttributeViewCell(operation.AvID, operation.KeyID, operation.RowID, operation.ID, operation.Data)
  738. return
  739. }
  740. func UpdateAttributeViewCell(avID, keyID, rowID, cellID string, valueData interface{}) (err error) {
  741. attrView, err := av.ParseAttributeView(avID)
  742. if nil != err {
  743. return
  744. }
  745. var val *av.Value
  746. for _, keyValues := range attrView.KeyValues {
  747. if keyID != keyValues.Key.ID {
  748. continue
  749. }
  750. for _, value := range keyValues.Values {
  751. if cellID == value.ID {
  752. val = value
  753. val.Type = keyValues.Key.Type
  754. break
  755. }
  756. }
  757. if nil == val {
  758. val = &av.Value{ID: cellID, KeyID: keyValues.Key.ID, BlockID: rowID, Type: keyValues.Key.Type}
  759. keyValues.Values = append(keyValues.Values, val)
  760. }
  761. break
  762. }
  763. tree, err := loadTreeByBlockID(val.BlockID)
  764. if nil != err {
  765. return
  766. }
  767. node := treenode.GetNodeInTree(tree, val.BlockID)
  768. if nil == node {
  769. return
  770. }
  771. data, err := gulu.JSON.MarshalJSON(valueData)
  772. if nil != err {
  773. return
  774. }
  775. if err = gulu.JSON.UnmarshalJSON(data, &val); nil != err {
  776. return
  777. }
  778. attrs := parse.IAL2Map(node.KramdownIAL)
  779. attrs[NodeAttrNamePrefixAvKey+avID+"-"+val.KeyID] = val.ToJSONString()
  780. if err = setNodeAttrs(node, tree, attrs); nil != err {
  781. return
  782. }
  783. if err = av.SaveAttributeView(attrView); nil != err {
  784. return
  785. }
  786. return
  787. }
  788. func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *TxErr) {
  789. err := updateAttributeViewColumnOptions(operation)
  790. if nil != err {
  791. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  792. }
  793. return
  794. }
  795. func updateAttributeViewColumnOptions(operation *Operation) (err error) {
  796. attrView, err := av.ParseAttributeView(operation.AvID)
  797. if nil != err {
  798. return
  799. }
  800. jsonData, err := gulu.JSON.MarshalJSON(operation.Data)
  801. if nil != err {
  802. return
  803. }
  804. options := []*av.KeySelectOption{}
  805. if err = gulu.JSON.UnmarshalJSON(jsonData, &options); nil != err {
  806. return
  807. }
  808. for _, keyValues := range attrView.KeyValues {
  809. if keyValues.Key.ID == operation.ID {
  810. keyValues.Key.Options = options
  811. err = av.SaveAttributeView(attrView)
  812. return
  813. }
  814. }
  815. return
  816. }
  817. func (tx *Transaction) doRemoveAttrViewColOption(operation *Operation) (ret *TxErr) {
  818. err := removeAttributeViewColumnOption(operation)
  819. if nil != err {
  820. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  821. }
  822. return
  823. }
  824. func removeAttributeViewColumnOption(operation *Operation) (err error) {
  825. attrView, err := av.ParseAttributeView(operation.AvID)
  826. if nil != err {
  827. return
  828. }
  829. optName := operation.Data.(string)
  830. key, err := attrView.GetKey(operation.ID)
  831. if nil != err {
  832. return
  833. }
  834. for i, opt := range key.Options {
  835. if optName == opt.Name {
  836. key.Options = append(key.Options[:i], key.Options[i+1:]...)
  837. break
  838. }
  839. }
  840. for _, keyValues := range attrView.KeyValues {
  841. if keyValues.Key.ID != operation.ID {
  842. continue
  843. }
  844. for _, value := range keyValues.Values {
  845. if nil == value || nil == value.MSelect {
  846. continue
  847. }
  848. for i, opt := range value.MSelect {
  849. if optName == opt.Content {
  850. value.MSelect = append(value.MSelect[:i], value.MSelect[i+1:]...)
  851. break
  852. }
  853. }
  854. }
  855. break
  856. }
  857. err = av.SaveAttributeView(attrView)
  858. return
  859. }
  860. func (tx *Transaction) doUpdateAttrViewColOption(operation *Operation) (ret *TxErr) {
  861. err := updateAttributeViewColumnOption(operation)
  862. if nil != err {
  863. return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
  864. }
  865. return
  866. }
  867. func updateAttributeViewColumnOption(operation *Operation) (err error) {
  868. attrView, err := av.ParseAttributeView(operation.AvID)
  869. if nil != err {
  870. return
  871. }
  872. key, err := attrView.GetKey(operation.ID)
  873. if nil != err {
  874. return
  875. }
  876. data := operation.Data.(map[string]interface{})
  877. oldName := data["oldName"].(string)
  878. newName := data["newName"].(string)
  879. newColor := data["newColor"].(string)
  880. for i, opt := range key.Options {
  881. if oldName == opt.Name {
  882. key.Options[i].Name = newName
  883. key.Options[i].Color = newColor
  884. break
  885. }
  886. }
  887. for _, keyValues := range attrView.KeyValues {
  888. if keyValues.Key.ID != operation.ID {
  889. continue
  890. }
  891. for _, value := range keyValues.Values {
  892. if nil == value || nil == value.MSelect {
  893. continue
  894. }
  895. for i, opt := range value.MSelect {
  896. if oldName == opt.Content {
  897. value.MSelect[i].Content = newName
  898. value.MSelect[i].Color = newColor
  899. break
  900. }
  901. }
  902. }
  903. break
  904. }
  905. err = av.SaveAttributeView(attrView)
  906. return
  907. }
  908. const (
  909. NodeAttrNameAvs = "custom-avs" // 用于标记块所属的属性视图,逗号分隔 av id
  910. NodeAttrNamePrefixAvKey = "custom-av-key-" // 用于标记列
  911. )