A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at upstream/main 962 lines 22 kB view raw
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 17package api 18 19import ( 20 "net/http" 21 22 "github.com/88250/gulu" 23 "github.com/gin-gonic/gin" 24 "github.com/siyuan-note/siyuan/kernel/av" 25 "github.com/siyuan-note/siyuan/kernel/model" 26 "github.com/siyuan-note/siyuan/kernel/treenode" 27 "github.com/siyuan-note/siyuan/kernel/util" 28) 29 30func getAttributeViewItemIDsByBoundIDs(c *gin.Context) { 31 ret := gulu.Ret.NewResult() 32 defer c.JSON(http.StatusOK, ret) 33 34 arg, ok := util.JsonArg(c, ret) 35 if !ok { 36 return 37 } 38 39 avID := arg["avID"].(string) 40 blockIDsArg := arg["blockIDs"].([]interface{}) 41 var blockIDs []string 42 for _, v := range blockIDsArg { 43 blockIDs = append(blockIDs, v.(string)) 44 } 45 46 ret.Data = model.GetAttributeViewItemIDs(avID, blockIDs) 47} 48 49func getAttributeViewBoundBlockIDsByItemIDs(c *gin.Context) { 50 ret := gulu.Ret.NewResult() 51 defer c.JSON(http.StatusOK, ret) 52 53 arg, ok := util.JsonArg(c, ret) 54 if !ok { 55 return 56 } 57 58 avID := arg["avID"].(string) 59 itemIDsArg := arg["itemIDs"].([]interface{}) 60 var itemIDs []string 61 for _, v := range itemIDsArg { 62 itemIDs = append(itemIDs, v.(string)) 63 } 64 65 ret.Data = model.GetAttributeViewBoundBlockIDs(avID, itemIDs) 66} 67 68// getAttributeViewAddingBlockDefaultValues 用于获取添加块时的默认值。 69// 存在过滤或分组条件时,添加块时需要填充默认值到过滤字段或分组字段中,前端需要调用该接口来获取这些默认值以便填充。 70func getAttributeViewAddingBlockDefaultValues(c *gin.Context) { 71 ret := gulu.Ret.NewResult() 72 defer c.JSON(http.StatusOK, ret) 73 74 arg, ok := util.JsonArg(c, ret) 75 if !ok { 76 return 77 } 78 79 avID := arg["avID"].(string) 80 var viewID string 81 if viewIDArg := arg["viewID"]; nil != viewIDArg { 82 viewID = viewIDArg.(string) 83 } 84 var groupID string 85 if groupIDArg := arg["groupID"]; nil != groupIDArg { 86 groupID = groupIDArg.(string) 87 } 88 var previousID string 89 if nil != arg["previousID"] { 90 previousID = arg["previousID"].(string) 91 } 92 var addingBlockID string 93 if nil != arg["addingBlockID"] { 94 addingBlockID = arg["addingBlockID"].(string) 95 } 96 97 values := model.GetAttrViewAddingBlockDefaultValues(avID, viewID, groupID, previousID, addingBlockID) 98 if 1 > len(values) { 99 values = nil 100 } 101 ret.Data = map[string]interface{}{ 102 "values": values, 103 } 104} 105 106func batchReplaceAttributeViewBlocks(c *gin.Context) { 107 // Add kernel API `/api/av/batchReplaceAttributeViewBlocks` https://github.com/siyuan-note/siyuan/issues/15313 108 ret := gulu.Ret.NewResult() 109 defer c.JSON(http.StatusOK, ret) 110 111 arg, ok := util.JsonArg(c, ret) 112 if !ok { 113 return 114 } 115 116 avID := arg["avID"].(string) 117 isDetached := arg["isDetached"].(bool) 118 oldNewArg := arg["oldNew"].([]interface{}) 119 var oldNew []map[string]string 120 for _, v := range oldNewArg { 121 for o, n := range v.(map[string]interface{}) { 122 oldNew = append(oldNew, map[string]string{o: n.(string)}) 123 } 124 } 125 126 err := model.BatchReplaceAttributeViewBlocks(avID, isDetached, oldNew) 127 if err != nil { 128 ret.Code = -1 129 ret.Msg = err.Error() 130 return 131 } 132 133 model.ReloadAttrView(avID) 134} 135 136func setAttrViewGroup(c *gin.Context) { 137 ret := gulu.Ret.NewResult() 138 arg, ok := util.JsonArg(c, ret) 139 if !ok { 140 c.JSON(http.StatusOK, ret) 141 return 142 } 143 144 avID := arg["avID"].(string) 145 blockID := arg["blockID"].(string) 146 groupArg := arg["group"].(map[string]interface{}) 147 148 data, err := gulu.JSON.MarshalJSON(groupArg) 149 if nil != err { 150 ret.Code = -1 151 ret.Msg = err.Error() 152 c.JSON(http.StatusOK, ret) 153 return 154 } 155 group := &av.ViewGroup{} 156 if err = gulu.JSON.UnmarshalJSON(data, group); nil != err { 157 ret.Code = -1 158 ret.Msg = err.Error() 159 c.JSON(http.StatusOK, ret) 160 return 161 } 162 163 err = model.SetAttributeViewGroup(avID, blockID, group) 164 if err != nil { 165 ret.Code = -1 166 ret.Msg = err.Error() 167 168 c.JSON(http.StatusOK, ret) 169 return 170 } 171 172 ret = renderAttrView(blockID, avID, "", "", 1, -1, nil) 173 c.JSON(http.StatusOK, ret) 174} 175 176func changeAttrViewLayout(c *gin.Context) { 177 ret := gulu.Ret.NewResult() 178 arg, ok := util.JsonArg(c, ret) 179 if !ok { 180 c.JSON(http.StatusOK, ret) 181 return 182 } 183 184 blockID := arg["blockID"].(string) 185 avID := arg["avID"].(string) 186 layoutType := arg["layoutType"].(string) 187 err := model.ChangeAttrViewLayout(blockID, avID, av.LayoutType(layoutType)) 188 if err != nil { 189 ret.Code = -1 190 ret.Msg = err.Error() 191 c.JSON(http.StatusOK, ret) 192 return 193 } 194 195 ret = renderAttrView(blockID, avID, "", "", 1, -1, nil) 196 c.JSON(http.StatusOK, ret) 197} 198 199func duplicateAttributeViewBlock(c *gin.Context) { 200 ret := gulu.Ret.NewResult() 201 defer c.JSON(http.StatusOK, ret) 202 203 arg, ok := util.JsonArg(c, ret) 204 if !ok { 205 return 206 } 207 avID := arg["avID"].(string) 208 209 newAvID, newBlockID, err := model.DuplicateDatabaseBlock(avID) 210 if err != nil { 211 ret.Code = -1 212 ret.Msg = err.Error() 213 return 214 } 215 216 ret.Data = map[string]interface{}{ 217 "avID": newAvID, 218 "blockID": newBlockID, 219 } 220} 221 222func getAttributeViewKeysByAvID(c *gin.Context) { 223 ret := gulu.Ret.NewResult() 224 defer c.JSON(http.StatusOK, ret) 225 226 arg, ok := util.JsonArg(c, ret) 227 if !ok { 228 return 229 } 230 avID := arg["avID"].(string) 231 ret.Data = model.GetAttributeViewKeysByID(avID) 232} 233 234func getAttributeViewKeysByID(c *gin.Context) { 235 ret := gulu.Ret.NewResult() 236 defer c.JSON(http.StatusOK, ret) 237 238 arg, ok := util.JsonArg(c, ret) 239 if !ok { 240 return 241 } 242 avID := arg["avID"].(string) 243 keyIDsArg := arg["keyIDs"].([]interface{}) 244 var keyIDs []string 245 for _, v := range keyIDsArg { 246 keyIDs = append(keyIDs, v.(string)) 247 } 248 ret.Data = model.GetAttributeViewKeysByID(avID, keyIDs...) 249} 250 251func getMirrorDatabaseBlocks(c *gin.Context) { 252 ret := gulu.Ret.NewResult() 253 defer c.JSON(http.StatusOK, ret) 254 255 arg, ok := util.JsonArg(c, ret) 256 if !ok { 257 return 258 } 259 260 avID := arg["avID"].(string) 261 blockIDs := treenode.GetMirrorAttrViewBlockIDs(avID) 262 var retRefDefs []model.RefDefs 263 for _, blockID := range blockIDs { 264 retRefDefs = append(retRefDefs, model.RefDefs{RefID: blockID, DefIDs: []string{}}) 265 } 266 if 1 > len(retRefDefs) { 267 retRefDefs = []model.RefDefs{} 268 } 269 270 ret.Data = map[string]any{ 271 "refDefs": retRefDefs, 272 } 273} 274 275func setDatabaseBlockView(c *gin.Context) { 276 ret := gulu.Ret.NewResult() 277 defer c.JSON(http.StatusOK, ret) 278 279 arg, ok := util.JsonArg(c, ret) 280 if !ok { 281 return 282 } 283 284 blockID := arg["id"].(string) 285 viewID := arg["viewID"].(string) 286 avID := arg["avID"].(string) 287 288 err := model.SetDatabaseBlockView(blockID, avID, viewID) 289 if err != nil { 290 ret.Code = -1 291 ret.Msg = err.Error() 292 return 293 } 294} 295 296func getAttributeViewPrimaryKeyValues(c *gin.Context) { 297 ret := gulu.Ret.NewResult() 298 defer c.JSON(http.StatusOK, ret) 299 300 arg, ok := util.JsonArg(c, ret) 301 if !ok { 302 return 303 } 304 305 id := arg["id"].(string) 306 page := 1 307 pageArg := arg["page"] 308 if nil != pageArg { 309 page = int(pageArg.(float64)) 310 } 311 312 pageSize := -1 313 pageSizeArg := arg["pageSize"] 314 if nil != pageSizeArg { 315 pageSize = int(pageSizeArg.(float64)) 316 } 317 318 keyword := "" 319 if keywordArg := arg["keyword"]; nil != keywordArg { 320 keyword = keywordArg.(string) 321 } 322 attributeViewName, databaseBlockIDs, rows, err := model.GetAttributeViewPrimaryKeyValues(id, keyword, page, pageSize) 323 if err != nil { 324 ret.Code = -1 325 ret.Msg = err.Error() 326 return 327 } 328 329 ret.Data = map[string]interface{}{ 330 "name": attributeViewName, 331 "blockIDs": databaseBlockIDs, 332 "rows": rows, 333 } 334} 335 336func appendAttributeViewDetachedBlocksWithValues(c *gin.Context) { 337 // Add an internal kernel API `/api/av/appendAttributeViewDetachedBlocksWithValues` https://github.com/siyuan-note/siyuan/issues/11608 338 339 ret := gulu.Ret.NewResult() 340 defer c.JSON(http.StatusOK, ret) 341 342 arg, _ := util.JsonArg(c, ret) 343 if nil == arg { 344 return 345 } 346 347 avID := arg["avID"].(string) 348 var values [][]*av.Value 349 for _, blocksVals := range arg["blocksValues"].([]interface{}) { 350 vals := blocksVals.([]interface{}) 351 var rowValues []*av.Value 352 for _, val := range vals { 353 data, marshalErr := gulu.JSON.MarshalJSON(val) 354 if nil != marshalErr { 355 ret.Code = -1 356 ret.Msg = marshalErr.Error() 357 return 358 } 359 value := av.Value{} 360 if unmarshalErr := gulu.JSON.UnmarshalJSON(data, &value); nil != unmarshalErr { 361 ret.Code = -1 362 ret.Msg = unmarshalErr.Error() 363 return 364 } 365 rowValues = append(rowValues, &value) 366 } 367 values = append(values, rowValues) 368 } 369 370 err := model.AppendAttributeViewDetachedBlocksWithValues(avID, values) 371 if err != nil { 372 ret.Code = -1 373 ret.Msg = err.Error() 374 return 375 } 376} 377 378func addAttributeViewBlocks(c *gin.Context) { 379 ret := gulu.Ret.NewResult() 380 defer c.JSON(http.StatusOK, ret) 381 382 arg, _ := util.JsonArg(c, ret) 383 if nil == arg { 384 return 385 } 386 387 avID := arg["avID"].(string) 388 var blockID string 389 if blockIDArg := arg["blockID"]; nil != blockIDArg { 390 blockID = blockIDArg.(string) 391 } 392 var viewID string 393 if viewIDArg := arg["viewID"]; nil != viewIDArg { 394 viewID = viewIDArg.(string) 395 } 396 var groupID string 397 if groupIDArg := arg["groupID"]; nil != groupIDArg { 398 groupID = groupIDArg.(string) 399 } 400 var previousID string 401 if nil != arg["previousID"] { 402 previousID = arg["previousID"].(string) 403 } 404 405 var srcs []map[string]interface{} 406 for _, v := range arg["srcs"].([]interface{}) { 407 src := v.(map[string]interface{}) 408 srcs = append(srcs, src) 409 } 410 411 var ignoreDefaultFill bool 412 if nil != arg["ignoreDefaultFill"] { 413 ignoreDefaultFill = arg["ignoreDefaultFill"].(bool) 414 } 415 416 err := model.AddAttributeViewBlock(nil, srcs, avID, blockID, viewID, groupID, previousID, ignoreDefaultFill, map[string]interface{}{}) 417 if err != nil { 418 ret.Code = -1 419 ret.Msg = err.Error() 420 return 421 } 422 423 model.ReloadAttrView(avID) 424} 425 426func removeAttributeViewBlocks(c *gin.Context) { 427 ret := gulu.Ret.NewResult() 428 defer c.JSON(http.StatusOK, ret) 429 430 arg, _ := util.JsonArg(c, ret) 431 if nil == arg { 432 return 433 } 434 435 avID := arg["avID"].(string) 436 var srcIDs []string 437 for _, v := range arg["srcIDs"].([]interface{}) { 438 srcIDs = append(srcIDs, v.(string)) 439 } 440 441 err := model.RemoveAttributeViewBlock(srcIDs, avID) 442 if err != nil { 443 ret.Code = -1 444 ret.Msg = err.Error() 445 return 446 } 447 448 model.ReloadAttrView(avID) 449} 450 451func addAttributeViewKey(c *gin.Context) { 452 ret := gulu.Ret.NewResult() 453 defer c.JSON(http.StatusOK, ret) 454 455 arg, _ := util.JsonArg(c, ret) 456 if nil == arg { 457 return 458 } 459 460 avID := arg["avID"].(string) 461 keyID := arg["keyID"].(string) 462 keyName := arg["keyName"].(string) 463 keyType := arg["keyType"].(string) 464 keyIcon := arg["keyIcon"].(string) 465 previousKeyID := arg["previousKeyID"].(string) 466 467 err := model.AddAttributeViewKey(avID, keyID, keyName, keyType, keyIcon, previousKeyID) 468 if err != nil { 469 ret.Code = -1 470 ret.Msg = err.Error() 471 return 472 } 473 474 model.ReloadAttrView(avID) 475} 476 477func removeAttributeViewKey(c *gin.Context) { 478 ret := gulu.Ret.NewResult() 479 defer c.JSON(http.StatusOK, ret) 480 481 arg, _ := util.JsonArg(c, ret) 482 if nil == arg { 483 return 484 } 485 486 avID := arg["avID"].(string) 487 keyID := arg["keyID"].(string) 488 removeRelationDest := false 489 if nil != arg["removeRelationDest"] { 490 removeRelationDest = arg["removeRelationDest"].(bool) 491 } 492 493 err := model.RemoveAttributeViewKey(avID, keyID, removeRelationDest) 494 if err != nil { 495 ret.Code = -1 496 ret.Msg = err.Error() 497 return 498 } 499 500 model.ReloadAttrView(avID) 501} 502 503func sortAttributeViewViewKey(c *gin.Context) { 504 ret := gulu.Ret.NewResult() 505 defer c.JSON(http.StatusOK, ret) 506 507 arg, ok := util.JsonArg(c, ret) 508 if !ok { 509 return 510 } 511 512 avID := arg["avID"].(string) 513 viewID := "" 514 if viewIDArg := arg["viewID"]; nil != viewIDArg { 515 viewID = viewIDArg.(string) 516 } 517 keyID := arg["keyID"].(string) 518 previousKeyID := arg["previousKeyID"].(string) 519 520 err := model.SortAttributeViewViewKey(avID, viewID, keyID, previousKeyID) 521 if err != nil { 522 ret.Code = -1 523 ret.Msg = err.Error() 524 return 525 } 526 527 model.ReloadAttrView(avID) 528} 529 530func sortAttributeViewKey(c *gin.Context) { 531 ret := gulu.Ret.NewResult() 532 defer c.JSON(http.StatusOK, ret) 533 534 arg, ok := util.JsonArg(c, ret) 535 if !ok { 536 return 537 } 538 539 avID := arg["avID"].(string) 540 keyID := arg["keyID"].(string) 541 previousKeyID := arg["previousKeyID"].(string) 542 543 err := model.SortAttributeViewKey(avID, keyID, previousKeyID) 544 if err != nil { 545 ret.Code = -1 546 ret.Msg = err.Error() 547 return 548 } 549 550 model.ReloadAttrView(avID) 551} 552 553func getAttributeViewFilterSort(c *gin.Context) { 554 ret := gulu.Ret.NewResult() 555 defer c.JSON(http.StatusOK, ret) 556 557 arg, _ := util.JsonArg(c, ret) 558 if nil == arg { 559 return 560 } 561 562 avID := arg["id"].(string) 563 blockID := arg["blockID"].(string) 564 565 filters, sorts := model.GetAttributeViewFilterSort(avID, blockID) 566 ret.Data = map[string]interface{}{ 567 "filters": filters, 568 "sorts": sorts, 569 } 570} 571 572func searchAttributeViewNonRelationKey(c *gin.Context) { 573 ret := gulu.Ret.NewResult() 574 defer c.JSON(http.StatusOK, ret) 575 576 arg, _ := util.JsonArg(c, ret) 577 if nil == arg { 578 return 579 } 580 581 avID := arg["avID"].(string) 582 keyword := arg["keyword"].(string) 583 584 nonRelationKeys := model.SearchAttributeViewNonRelationKey(avID, keyword) 585 ret.Data = map[string]interface{}{ 586 "keys": nonRelationKeys, 587 } 588} 589 590func searchAttributeViewRollupDestKeys(c *gin.Context) { 591 ret := gulu.Ret.NewResult() 592 defer c.JSON(http.StatusOK, ret) 593 594 arg, _ := util.JsonArg(c, ret) 595 if nil == arg { 596 return 597 } 598 599 avID := arg["avID"].(string) 600 keyword := arg["keyword"].(string) 601 602 rollupDestKeys := model.SearchAttributeViewRollupDestKeys(avID, keyword) 603 ret.Data = map[string]interface{}{ 604 "keys": rollupDestKeys, 605 } 606} 607 608func searchAttributeViewRelationKey(c *gin.Context) { 609 ret := gulu.Ret.NewResult() 610 defer c.JSON(http.StatusOK, ret) 611 612 arg, _ := util.JsonArg(c, ret) 613 if nil == arg { 614 return 615 } 616 617 avID := arg["avID"].(string) 618 keyword := arg["keyword"].(string) 619 620 relationKeys := model.SearchAttributeViewRelationKey(avID, keyword) 621 ret.Data = map[string]interface{}{ 622 "keys": relationKeys, 623 } 624} 625 626func getAttributeView(c *gin.Context) { 627 ret := gulu.Ret.NewResult() 628 defer c.JSON(http.StatusOK, ret) 629 630 arg, _ := util.JsonArg(c, ret) 631 if nil == arg { 632 return 633 } 634 635 id := arg["id"].(string) 636 ret.Data = map[string]interface{}{ 637 "av": model.GetAttributeView(id), 638 } 639} 640 641func searchAttributeView(c *gin.Context) { 642 ret := gulu.Ret.NewResult() 643 defer c.JSON(http.StatusOK, ret) 644 645 arg, _ := util.JsonArg(c, ret) 646 if nil == arg { 647 return 648 } 649 650 keyword := arg["keyword"].(string) 651 var excludes []string 652 if nil != arg["excludes"] { 653 for _, e := range arg["excludes"].([]interface{}) { 654 excludes = append(excludes, e.(string)) 655 } 656 } 657 results := model.SearchAttributeView(keyword, excludes) 658 ret.Data = map[string]interface{}{ 659 "results": results, 660 } 661} 662 663func renderSnapshotAttributeView(c *gin.Context) { 664 ret := gulu.Ret.NewResult() 665 defer c.JSON(http.StatusOK, ret) 666 667 arg, ok := util.JsonArg(c, ret) 668 if !ok { 669 return 670 } 671 672 index := arg["snapshot"].(string) 673 id := arg["id"].(string) 674 view, attrView, err := model.RenderRepoSnapshotAttributeView(index, id) 675 if err != nil { 676 ret.Code = -1 677 ret.Msg = err.Error() 678 return 679 } 680 681 var views []map[string]interface{} 682 for _, v := range attrView.Views { 683 view := map[string]interface{}{ 684 "id": v.ID, 685 "icon": v.Icon, 686 "name": v.Name, 687 "hideAttrViewName": v.HideAttrViewName, 688 "type": v.LayoutType, 689 } 690 691 views = append(views, view) 692 } 693 694 ret.Data = map[string]interface{}{ 695 "name": attrView.Name, 696 "id": attrView.ID, 697 "viewType": view.GetType(), 698 "viewID": view.GetID(), 699 "views": views, 700 "view": view, 701 "isMirror": av.IsMirror(attrView.ID), 702 } 703} 704 705func renderHistoryAttributeView(c *gin.Context) { 706 ret := gulu.Ret.NewResult() 707 defer c.JSON(http.StatusOK, ret) 708 709 arg, ok := util.JsonArg(c, ret) 710 if !ok { 711 return 712 } 713 714 id := arg["id"].(string) 715 created := arg["created"].(string) 716 blockIDArg := arg["blockID"] 717 var blockID string 718 if nil != blockIDArg { 719 blockID = blockIDArg.(string) 720 } 721 viewIDArg := arg["viewID"] 722 var viewID string 723 if nil != viewIDArg { 724 viewID = viewIDArg.(string) 725 } 726 page := 1 727 pageArg := arg["page"] 728 if nil != pageArg { 729 page = int(pageArg.(float64)) 730 } 731 732 pageSize := -1 733 pageSizeArg := arg["pageSize"] 734 if nil != pageSizeArg { 735 pageSize = int(pageSizeArg.(float64)) 736 } 737 738 query := "" 739 queryArg := arg["query"] 740 if nil != queryArg { 741 query = queryArg.(string) 742 } 743 744 groupPaging := map[string]interface{}{} 745 groupPagingArg := arg["groupPaging"] 746 if nil != groupPagingArg { 747 groupPaging = groupPagingArg.(map[string]interface{}) 748 } 749 750 view, attrView, err := model.RenderHistoryAttributeView(blockID, id, viewID, query, page, pageSize, groupPaging, created) 751 if err != nil { 752 ret.Code = -1 753 ret.Msg = err.Error() 754 return 755 } 756 757 var views []map[string]interface{} 758 for _, v := range attrView.Views { 759 view := map[string]interface{}{ 760 "id": v.ID, 761 "icon": v.Icon, 762 "name": v.Name, 763 "hideAttrViewName": v.HideAttrViewName, 764 "type": v.LayoutType, 765 } 766 767 views = append(views, view) 768 } 769 770 ret.Data = map[string]interface{}{ 771 "name": attrView.Name, 772 "id": attrView.ID, 773 "viewType": view.GetType(), 774 "viewID": view.GetID(), 775 "views": views, 776 "view": view, 777 "isMirror": av.IsMirror(attrView.ID), 778 } 779} 780 781func renderAttributeView(c *gin.Context) { 782 ret := gulu.Ret.NewResult() 783 arg, ok := util.JsonArg(c, ret) 784 if !ok { 785 c.JSON(http.StatusOK, ret) 786 return 787 } 788 789 id := arg["id"].(string) 790 blockIDArg := arg["blockID"] 791 var blockID string 792 if nil != blockIDArg { 793 blockID = blockIDArg.(string) 794 } 795 viewIDArg := arg["viewID"] 796 var viewID string 797 if nil != viewIDArg { 798 viewID = viewIDArg.(string) 799 } 800 page := 1 801 pageArg := arg["page"] 802 if nil != pageArg { 803 page = int(pageArg.(float64)) 804 } 805 806 pageSize := -1 807 pageSizeArg := arg["pageSize"] 808 if nil != pageSizeArg { 809 pageSize = int(pageSizeArg.(float64)) 810 } 811 812 query := "" 813 queryArg := arg["query"] 814 if nil != queryArg { 815 query = queryArg.(string) 816 } 817 818 groupPaging := map[string]interface{}{} 819 groupPagingArg := arg["groupPaging"] 820 if nil != groupPagingArg { 821 groupPaging = groupPagingArg.(map[string]interface{}) 822 } 823 824 ret = renderAttrView(blockID, id, viewID, query, page, pageSize, groupPaging) 825 c.JSON(http.StatusOK, ret) 826} 827 828func renderAttrView(blockID, avID, viewID, query string, page, pageSize int, groupPaging map[string]interface{}) (ret *gulu.Result) { 829 ret = gulu.Ret.NewResult() 830 view, attrView, err := model.RenderAttributeView(blockID, avID, viewID, query, page, pageSize, groupPaging) 831 if err != nil { 832 ret.Code = -1 833 ret.Msg = err.Error() 834 return 835 } 836 837 var views []map[string]interface{} 838 for _, v := range attrView.Views { 839 view := map[string]interface{}{ 840 "id": v.ID, 841 "icon": v.Icon, 842 "name": v.Name, 843 "desc": v.Desc, 844 "hideAttrViewName": v.HideAttrViewName, 845 "type": v.LayoutType, 846 "pageSize": v.PageSize, 847 } 848 849 views = append(views, view) 850 } 851 852 ret.Data = map[string]interface{}{ 853 "name": attrView.Name, 854 "id": attrView.ID, 855 "viewType": view.GetType(), 856 "viewID": view.GetID(), 857 "views": views, 858 "view": view, 859 "isMirror": av.IsMirror(attrView.ID), 860 } 861 return 862} 863 864func getCurrentAttrViewImages(c *gin.Context) { 865 ret := gulu.Ret.NewResult() 866 defer c.JSON(http.StatusOK, ret) 867 868 arg, ok := util.JsonArg(c, ret) 869 if !ok { 870 return 871 } 872 873 id := arg["id"].(string) 874 viewIDArg := arg["viewID"] 875 var viewID string 876 if nil != viewIDArg { 877 viewID = viewIDArg.(string) 878 } 879 880 query := "" 881 queryArg := arg["query"] 882 if nil != queryArg { 883 query = queryArg.(string) 884 } 885 886 images, err := model.GetCurrentAttributeViewImages(id, viewID, query) 887 if err != nil { 888 ret.Code = -1 889 ret.Msg = err.Error() 890 return 891 } 892 ret.Data = images 893} 894 895func getAttributeViewKeys(c *gin.Context) { 896 ret := gulu.Ret.NewResult() 897 defer c.JSON(http.StatusOK, ret) 898 899 arg, ok := util.JsonArg(c, ret) 900 if !ok { 901 return 902 } 903 904 id := arg["id"].(string) 905 blockAttributeViewKeys := model.GetBlockAttributeViewKeys(id) 906 ret.Data = blockAttributeViewKeys 907} 908 909func setAttributeViewBlockAttr(c *gin.Context) { 910 ret := gulu.Ret.NewResult() 911 defer c.JSON(http.StatusOK, ret) 912 913 arg, ok := util.JsonArg(c, ret) 914 if !ok { 915 return 916 } 917 918 avID := arg["avID"].(string) 919 keyID := arg["keyID"].(string) 920 var itemID string 921 if _, ok := arg["itemID"]; ok { 922 itemID = arg["itemID"].(string) 923 } else if _, ok := arg["rowID"]; ok { 924 // TODO 划于 2026 年 6 月 30 日后删除 https://github.com/siyuan-note/siyuan/issues/15708#issuecomment-3239694546 925 itemID = arg["rowID"].(string) 926 } 927 value := arg["value"].(interface{}) 928 updatedVal, err := model.UpdateAttributeViewCell(nil, avID, keyID, itemID, value) 929 if err != nil { 930 ret.Code = -1 931 ret.Msg = err.Error() 932 return 933 } 934 935 ret.Data = map[string]interface{}{ 936 "value": updatedVal, 937 } 938 939 model.ReloadAttrView(avID) 940} 941 942func batchSetAttributeViewBlockAttrs(c *gin.Context) { 943 // Add kernel API `/api/av/batchSetAttributeViewBlockAttrs` https://github.com/siyuan-note/siyuan/issues/15310 944 ret := gulu.Ret.NewResult() 945 defer c.JSON(http.StatusOK, ret) 946 947 arg, ok := util.JsonArg(c, ret) 948 if !ok { 949 return 950 } 951 952 avID := arg["avID"].(string) 953 values := arg["values"].([]interface{}) 954 err := model.BatchUpdateAttributeViewCells(nil, avID, values) 955 if err != nil { 956 ret.Code = -1 957 ret.Msg = err.Error() 958 return 959 } 960 961 model.ReloadAttrView(avID) 962}