mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-21 13:38:56 +02:00
73d77682ac
* add Boards APIs to services map
427 lines
10 KiB
Go
427 lines
10 KiB
Go
package model
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
type BoardType string
|
|
type BoardRole string
|
|
type BoardSearchField string
|
|
|
|
const (
|
|
BoardTypeOpen BoardType = "O"
|
|
BoardTypePrivate BoardType = "P"
|
|
)
|
|
|
|
const (
|
|
BoardRoleNone BoardRole = ""
|
|
BoardRoleViewer BoardRole = "viewer"
|
|
BoardRoleCommenter BoardRole = "commenter"
|
|
BoardRoleEditor BoardRole = "editor"
|
|
BoardRoleAdmin BoardRole = "admin"
|
|
)
|
|
|
|
const (
|
|
BoardSearchFieldNone BoardSearchField = ""
|
|
BoardSearchFieldTitle BoardSearchField = "title"
|
|
BoardSearchFieldPropertyName BoardSearchField = "property_name"
|
|
)
|
|
|
|
// Board groups a set of blocks and its layout
|
|
// swagger:model
|
|
type Board struct {
|
|
// The ID for the board
|
|
// required: true
|
|
ID string `json:"id"`
|
|
|
|
// The ID of the team that the board belongs to
|
|
// required: true
|
|
TeamID string `json:"teamId"`
|
|
|
|
// The ID of the channel that the board was created from
|
|
// required: false
|
|
ChannelID string `json:"channelId"`
|
|
|
|
// The ID of the user that created the board
|
|
// required: true
|
|
CreatedBy string `json:"createdBy"`
|
|
|
|
// The ID of the last user that updated the board
|
|
// required: true
|
|
ModifiedBy string `json:"modifiedBy"`
|
|
|
|
// The type of the board
|
|
// required: true
|
|
Type BoardType `json:"type"`
|
|
|
|
// The minimum role applied when somebody joins the board
|
|
// required: true
|
|
MinimumRole BoardRole `json:"minimumRole"`
|
|
|
|
// The title of the board
|
|
// required: false
|
|
Title string `json:"title"`
|
|
|
|
// The description of the board
|
|
// required: false
|
|
Description string `json:"description"`
|
|
|
|
// The icon of the board
|
|
// required: false
|
|
Icon string `json:"icon"`
|
|
|
|
// Indicates if the board shows the description on the interface
|
|
// required: false
|
|
ShowDescription bool `json:"showDescription"`
|
|
|
|
// Marks the template boards
|
|
// required: false
|
|
IsTemplate bool `json:"isTemplate"`
|
|
|
|
// Marks the template boards
|
|
// required: false
|
|
TemplateVersion int `json:"templateVersion"`
|
|
|
|
// The properties of the board
|
|
// required: false
|
|
Properties map[string]interface{} `json:"properties"`
|
|
|
|
// The properties of the board cards
|
|
// required: false
|
|
CardProperties []map[string]interface{} `json:"cardProperties"`
|
|
|
|
// The creation time in miliseconds since the current epoch
|
|
// required: true
|
|
CreateAt int64 `json:"createAt"`
|
|
|
|
// The last modified time in miliseconds since the current epoch
|
|
// required: true
|
|
UpdateAt int64 `json:"updateAt"`
|
|
|
|
// The deleted time in miliseconds since the current epoch. Set to indicate this block is deleted
|
|
// required: false
|
|
DeleteAt int64 `json:"deleteAt"`
|
|
}
|
|
|
|
// GetPropertyString returns the value of the specified property as a string,
|
|
// or error if the property does not exist or is not of type string.
|
|
func (b *Board) GetPropertyString(propName string) (string, error) {
|
|
val, ok := b.Properties[propName]
|
|
if !ok {
|
|
return "", NewErrNotFound(propName)
|
|
}
|
|
|
|
s, ok := val.(string)
|
|
if !ok {
|
|
return "", ErrInvalidPropertyValueType
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// BoardPatch is a patch for modify boards
|
|
// swagger:model
|
|
type BoardPatch struct {
|
|
// The type of the board
|
|
// required: false
|
|
Type *BoardType `json:"type"`
|
|
|
|
// The minimum role applied when somebody joins the board
|
|
// required: false
|
|
MinimumRole *BoardRole `json:"minimumRole"`
|
|
|
|
// The title of the board
|
|
// required: false
|
|
Title *string `json:"title"`
|
|
|
|
// The description of the board
|
|
// required: false
|
|
Description *string `json:"description"`
|
|
|
|
// The icon of the board
|
|
// required: false
|
|
Icon *string `json:"icon"`
|
|
|
|
// Indicates if the board shows the description on the interface
|
|
// required: false
|
|
ShowDescription *bool `json:"showDescription"`
|
|
|
|
// Indicates if the board shows the description on the interface
|
|
// required: false
|
|
ChannelID *string `json:"channelId"`
|
|
|
|
// The board updated properties
|
|
// required: false
|
|
UpdatedProperties map[string]interface{} `json:"updatedProperties"`
|
|
|
|
// The board removed properties
|
|
// required: false
|
|
DeletedProperties []string `json:"deletedProperties"`
|
|
|
|
// The board updated card properties
|
|
// required: false
|
|
UpdatedCardProperties []map[string]interface{} `json:"updatedCardProperties"`
|
|
|
|
// The board removed card properties
|
|
// required: false
|
|
DeletedCardProperties []string `json:"deletedCardProperties"`
|
|
}
|
|
|
|
// BoardMember stores the information of the membership of a user on a board
|
|
// swagger:model
|
|
type BoardMember struct {
|
|
// The ID of the board
|
|
// required: true
|
|
BoardID string `json:"boardId"`
|
|
|
|
// The ID of the user
|
|
// required: true
|
|
UserID string `json:"userId"`
|
|
|
|
// The independent roles of the user on the board
|
|
// required: false
|
|
Roles string `json:"roles"`
|
|
|
|
// Minimum role because the board configuration
|
|
// required: false
|
|
MinimumRole string `json:"minimumRole"`
|
|
|
|
// Marks the user as an admin of the board
|
|
// required: true
|
|
SchemeAdmin bool `json:"schemeAdmin"`
|
|
|
|
// Marks the user as an editor of the board
|
|
// required: true
|
|
SchemeEditor bool `json:"schemeEditor"`
|
|
|
|
// Marks the user as an commenter of the board
|
|
// required: true
|
|
SchemeCommenter bool `json:"schemeCommenter"`
|
|
|
|
// Marks the user as an viewer of the board
|
|
// required: true
|
|
SchemeViewer bool `json:"schemeViewer"`
|
|
|
|
// Marks the membership as generated by an access group
|
|
// required: true
|
|
Synthetic bool `json:"synthetic"`
|
|
}
|
|
|
|
// BoardMetadata contains metadata for a Board
|
|
// swagger:model
|
|
type BoardMetadata struct {
|
|
// The ID for the board
|
|
// required: true
|
|
BoardID string `json:"boardId"`
|
|
|
|
// The most recent time a descendant of this board was added, modified, or deleted
|
|
// required: true
|
|
DescendantLastUpdateAt int64 `json:"descendantLastUpdateAt"`
|
|
|
|
// The earliest time a descendant of this board was added, modified, or deleted
|
|
// required: true
|
|
DescendantFirstUpdateAt int64 `json:"descendantFirstUpdateAt"`
|
|
|
|
// The ID of the user that created the board
|
|
// required: true
|
|
CreatedBy string `json:"createdBy"`
|
|
|
|
// The ID of the user that last modified the most recently modified descendant
|
|
// required: true
|
|
LastModifiedBy string `json:"lastModifiedBy"`
|
|
}
|
|
|
|
func BoardFromJSON(data io.Reader) *Board {
|
|
var board *Board
|
|
_ = json.NewDecoder(data).Decode(&board)
|
|
return board
|
|
}
|
|
|
|
func BoardsFromJSON(data io.Reader) []*Board {
|
|
var boards []*Board
|
|
_ = json.NewDecoder(data).Decode(&boards)
|
|
return boards
|
|
}
|
|
|
|
func BoardMemberFromJSON(data io.Reader) *BoardMember {
|
|
var boardMember *BoardMember
|
|
_ = json.NewDecoder(data).Decode(&boardMember)
|
|
return boardMember
|
|
}
|
|
|
|
func BoardMembersFromJSON(data io.Reader) []*BoardMember {
|
|
var boardMembers []*BoardMember
|
|
_ = json.NewDecoder(data).Decode(&boardMembers)
|
|
return boardMembers
|
|
}
|
|
|
|
func BoardMetadataFromJSON(data io.Reader) *BoardMetadata {
|
|
var boardMetadata *BoardMetadata
|
|
_ = json.NewDecoder(data).Decode(&boardMetadata)
|
|
return boardMetadata
|
|
}
|
|
|
|
// Patch returns an updated version of the board.
|
|
func (p *BoardPatch) Patch(board *Board) *Board {
|
|
if p.Type != nil {
|
|
board.Type = *p.Type
|
|
}
|
|
|
|
if p.Title != nil {
|
|
board.Title = *p.Title
|
|
}
|
|
|
|
if p.MinimumRole != nil {
|
|
board.MinimumRole = *p.MinimumRole
|
|
}
|
|
|
|
if p.Description != nil {
|
|
board.Description = *p.Description
|
|
}
|
|
|
|
if p.Icon != nil {
|
|
board.Icon = *p.Icon
|
|
}
|
|
|
|
if p.ShowDescription != nil {
|
|
board.ShowDescription = *p.ShowDescription
|
|
}
|
|
|
|
if p.ChannelID != nil {
|
|
board.ChannelID = *p.ChannelID
|
|
}
|
|
|
|
for key, property := range p.UpdatedProperties {
|
|
board.Properties[key] = property
|
|
}
|
|
|
|
for _, key := range p.DeletedProperties {
|
|
delete(board.Properties, key)
|
|
}
|
|
|
|
if len(p.UpdatedCardProperties) != 0 || len(p.DeletedCardProperties) != 0 {
|
|
// first we accumulate all properties indexed by, and maintain their order
|
|
keyOrder := []string{}
|
|
cardPropertyMap := map[string]map[string]interface{}{}
|
|
for _, prop := range board.CardProperties {
|
|
id, ok := prop["id"].(string)
|
|
if !ok {
|
|
// bad property, skipping
|
|
continue
|
|
}
|
|
|
|
cardPropertyMap[id] = prop
|
|
keyOrder = append(keyOrder, id)
|
|
}
|
|
|
|
// if there are properties marked for removal, we delete them
|
|
for _, propertyID := range p.DeletedCardProperties {
|
|
delete(cardPropertyMap, propertyID)
|
|
}
|
|
|
|
// if there are properties marked for update, we replace the
|
|
// existing ones or add them
|
|
for _, newprop := range p.UpdatedCardProperties {
|
|
id, ok := newprop["id"].(string)
|
|
if !ok {
|
|
// bad new property, skipping
|
|
continue
|
|
}
|
|
|
|
_, exists := cardPropertyMap[id]
|
|
if !exists {
|
|
keyOrder = append(keyOrder, id)
|
|
}
|
|
cardPropertyMap[id] = newprop
|
|
}
|
|
|
|
// and finally we flatten and save the updated properties
|
|
newCardProperties := []map[string]interface{}{}
|
|
for _, key := range keyOrder {
|
|
p, exists := cardPropertyMap[key]
|
|
if exists {
|
|
newCardProperties = append(newCardProperties, p)
|
|
}
|
|
}
|
|
|
|
board.CardProperties = newCardProperties
|
|
}
|
|
|
|
return board
|
|
}
|
|
|
|
func IsBoardTypeValid(t BoardType) bool {
|
|
return t == BoardTypeOpen || t == BoardTypePrivate
|
|
}
|
|
|
|
func IsBoardMinimumRoleValid(r BoardRole) bool {
|
|
return r == BoardRoleNone || r == BoardRoleAdmin || r == BoardRoleEditor || r == BoardRoleCommenter || r == BoardRoleViewer
|
|
}
|
|
|
|
func (p *BoardPatch) IsValid() error {
|
|
if p.Type != nil && !IsBoardTypeValid(*p.Type) {
|
|
return InvalidBoardErr{"invalid-board-type"}
|
|
}
|
|
|
|
if p.MinimumRole != nil && !IsBoardMinimumRoleValid(*p.MinimumRole) {
|
|
return InvalidBoardErr{"invalid-board-minimum-role"}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type InvalidBoardErr struct {
|
|
msg string
|
|
}
|
|
|
|
func (ibe InvalidBoardErr) Error() string {
|
|
return ibe.msg
|
|
}
|
|
|
|
func (b *Board) IsValid() error {
|
|
if b.TeamID == "" {
|
|
return InvalidBoardErr{"empty-team-id"}
|
|
}
|
|
|
|
if !IsBoardTypeValid(b.Type) {
|
|
return InvalidBoardErr{"invalid-board-type"}
|
|
}
|
|
|
|
if !IsBoardMinimumRoleValid(b.MinimumRole) {
|
|
return InvalidBoardErr{"invalid-board-minimum-role"}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// BoardMemberHistoryEntry stores the information of the membership of a user on a board
|
|
// swagger:model
|
|
type BoardMemberHistoryEntry struct {
|
|
// The ID of the board
|
|
// required: true
|
|
BoardID string `json:"boardId"`
|
|
|
|
// The ID of the user
|
|
// required: true
|
|
UserID string `json:"userId"`
|
|
|
|
// The action that added this history entry (created or deleted)
|
|
// required: false
|
|
Action string `json:"action"`
|
|
|
|
// The insertion time
|
|
// required: true
|
|
InsertAt time.Time `json:"insertAt"`
|
|
}
|
|
|
|
func BoardSearchFieldFromString(field string) (BoardSearchField, error) {
|
|
switch field {
|
|
case string(BoardSearchFieldTitle):
|
|
return BoardSearchFieldTitle, nil
|
|
case string(BoardSearchFieldPropertyName):
|
|
return BoardSearchFieldPropertyName, nil
|
|
}
|
|
return BoardSearchFieldNone, ErrInvalidBoardSearchField
|
|
}
|