github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/dashboard.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package db
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"strings"
    25  	"time"
    26  
    27  	"github.com/jackc/pgerrcode"
    28  	"github.com/jackc/pgx/v5/pgconn"
    29  	"github.com/pkg/errors"
    30  	"gorm.io/gorm"
    31  
    32  	"github.com/e154/smart-home/common/apperr"
    33  )
    34  
    35  // Dashboards ...
    36  type Dashboards struct {
    37  	Db *gorm.DB
    38  }
    39  
    40  // Dashboard ...
    41  type Dashboard struct {
    42  	Id          int64 `gorm:"primary_key"`
    43  	Name        string
    44  	Description string
    45  	Enabled     bool
    46  	AreaId      *int64
    47  	Area        *Area
    48  	Tabs        []*DashboardTab
    49  	CreatedAt   time.Time `gorm:"<-:create"`
    50  	UpdatedAt   time.Time
    51  }
    52  
    53  // TableName ...
    54  func (d *Dashboard) TableName() string {
    55  	return "dashboards"
    56  }
    57  
    58  // Add ...
    59  func (n Dashboards) Add(ctx context.Context, board *Dashboard) (id int64, err error) {
    60  	if err = n.Db.WithContext(ctx).Create(&board).Error; err != nil {
    61  		var pgErr *pgconn.PgError
    62  		if errors.As(err, &pgErr) {
    63  			switch pgErr.Code {
    64  			case pgerrcode.UniqueViolation:
    65  				if strings.Contains(pgErr.Message, "name_at_dashboards_unq") {
    66  					err = errors.Wrap(apperr.ErrDashboardAdd, fmt.Sprintf("dashboard name \"%s\" not unique", board.Name))
    67  					return
    68  				}
    69  			default:
    70  				fmt.Printf("unknown code \"%s\"\n", pgErr.Code)
    71  			}
    72  		}
    73  		err = errors.Wrap(apperr.ErrDashboardAdd, err.Error())
    74  		return
    75  	}
    76  	id = board.Id
    77  	return
    78  }
    79  
    80  // GetById ...
    81  func (n Dashboards) GetById(ctx context.Context, id int64) (board *Dashboard, err error) {
    82  	board = &Dashboard{}
    83  	err = n.Db.WithContext(ctx).Model(board).
    84  		Where("id = ?", id).
    85  		Preload("Area").
    86  		Preload("Tabs").
    87  		Preload("Tabs.Cards").
    88  		Preload("Tabs.Cards.Items").
    89  		First(&board).Error
    90  
    91  	if err != nil {
    92  		if errors.Is(err, gorm.ErrRecordNotFound) {
    93  			err = errors.Wrap(apperr.ErrDashboardNotFound, fmt.Sprintf("id \"%d\"", id))
    94  			return
    95  		}
    96  		err = errors.Wrap(apperr.ErrDashboardGet, err.Error())
    97  		return
    98  	}
    99  	return
   100  }
   101  
   102  // Update ...
   103  func (n Dashboards) Update(ctx context.Context, board *Dashboard) (err error) {
   104  	q := map[string]interface{}{
   105  		"name":        board.Name,
   106  		"description": board.Description,
   107  		"enabled":     board.Enabled,
   108  		"area_id":     board.AreaId,
   109  	}
   110  
   111  	if err = n.Db.WithContext(ctx).Model(&Dashboard{Id: board.Id}).Updates(q).Error; err != nil {
   112  		var pgErr *pgconn.PgError
   113  		if errors.As(err, &pgErr) {
   114  			switch pgErr.Code {
   115  			case pgerrcode.UniqueViolation:
   116  				if strings.Contains(pgErr.Message, "name_at_dashboards_unq") {
   117  					err = errors.Wrap(apperr.ErrDashboardUpdate, fmt.Sprintf("dashboard name \"%s\" not unique", board.Name))
   118  					return
   119  				}
   120  			default:
   121  				fmt.Printf("unknown code \"%s\"\n", pgErr.Code)
   122  			}
   123  		}
   124  		err = errors.Wrap(apperr.ErrDashboardUpdate, err.Error())
   125  	}
   126  	return
   127  }
   128  
   129  // Delete ...
   130  func (n Dashboards) Delete(ctx context.Context, id int64) (err error) {
   131  	if id == 0 {
   132  		return
   133  	}
   134  	if err = n.Db.WithContext(ctx).Delete(&Dashboard{Id: id}).Error; err != nil {
   135  		err = errors.Wrap(apperr.ErrDashboardDelete, err.Error())
   136  	}
   137  	return
   138  }
   139  
   140  // List ...
   141  func (n *Dashboards) List(ctx context.Context, limit, offset int, orderBy, sort string) (list []*Dashboard, total int64, err error) {
   142  
   143  	if err = n.Db.WithContext(ctx).Model(Dashboard{}).Count(&total).Error; err != nil {
   144  		err = errors.Wrap(apperr.ErrDashboardGet, err.Error())
   145  		return
   146  	}
   147  
   148  	list = make([]*Dashboard, 0)
   149  	q := n.Db.WithContext(ctx).
   150  		Preload("Area").
   151  		Limit(limit).
   152  		Offset(offset)
   153  
   154  	if sort != "" && orderBy != "" {
   155  		q = q.Order(fmt.Sprintf("%s %s", sort, orderBy))
   156  	}
   157  
   158  	err = q.
   159  		Find(&list).
   160  		Error
   161  
   162  	if err != nil {
   163  		err = errors.Wrap(apperr.ErrDashboardList, err.Error())
   164  	}
   165  
   166  	return
   167  }
   168  
   169  // Search ...
   170  func (d *Dashboards) Search(ctx context.Context, query string, limit, offset int) (list []*Dashboard, total int64, err error) {
   171  
   172  	q := d.Db.Model(&Dashboard{}).
   173  		Where("name LIKE ?", "%"+query+"%")
   174  
   175  	if err = q.Count(&total).Error; err != nil {
   176  		err = errors.Wrap(apperr.ErrDashboardSearch, err.Error())
   177  		return
   178  	}
   179  
   180  	q = q.
   181  		Limit(limit).
   182  		Offset(offset).
   183  		Order("name ASC")
   184  
   185  	list = make([]*Dashboard, 0)
   186  	if err = q.Find(&list).Error; err != nil {
   187  		err = errors.Wrap(apperr.ErrDashboardSearch, err.Error())
   188  	}
   189  	return
   190  }