add patch widget router
This commit is contained in:
parent
0d4a2d84d9
commit
06b9624c12
@ -63,7 +63,7 @@ func (pg *Postgres) SelectOne(ctx context.Context, query string, args ...interfa
|
||||
}
|
||||
|
||||
func (pg *Postgres) Update(ctx context.Context, query string, args ...interface{}) error {
|
||||
_, err := pg.db.Query(ctx, query, args...)
|
||||
_, err := pg.db.Exec(ctx, query, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// CreateWidget godoc
|
||||
// @Summary Create new widget
|
||||
// @Description Create new widget
|
||||
// @Tags GetWidgetDb
|
||||
// @Tags Widget
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
@ -62,7 +63,7 @@ func CreateWidget(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
// GetStreamersWidgets godoc
|
||||
// @Summary Get all streamer's widgets
|
||||
// @Description Get all streamer's widgets
|
||||
// @Tags GetWidgetDb
|
||||
// @Tags Widget
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
@ -101,6 +102,58 @@ func GetStreamersWidgets(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateWidget godoc
|
||||
// @Summary Update an existing widget
|
||||
// @Description Update an existing widget
|
||||
// @Tags Widget
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param widget_id path int true "Widget ID"
|
||||
// @Param request body model.UpdateWidget true "Update widget"
|
||||
// @Success 200 {string} string "Widget has been updated successfully!"
|
||||
// @Failure 400 {object} echo.HTTPError "Bad request"
|
||||
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
|
||||
// @Failure 422 {object} echo.HTTPError "Validation error"
|
||||
// @Failure 404 {object} echo.HTTPError "Widget not found"
|
||||
// @Router /widgets/{widget_id} [patch]
|
||||
func UpdateWidget(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
return func(request echo.Context) error {
|
||||
ctx := context.Background()
|
||||
widgetIDStr := request.Param("widgetID")
|
||||
|
||||
widgetID, err := strconv.Atoi(widgetIDStr)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Invalid widget ID")
|
||||
}
|
||||
|
||||
var body model.UpdateWidget
|
||||
err = validator.ParseAndValidate(&body, request)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error())
|
||||
}
|
||||
|
||||
authData, err := widgetService.CheckToken(request)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
|
||||
}
|
||||
|
||||
err = widgetService.UpdateWidget(
|
||||
ctx,
|
||||
body,
|
||||
widgetID,
|
||||
authData.AccountID,
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Internal Server Error")
|
||||
}
|
||||
|
||||
return request.JSON(http.StatusOK, "Widget has been updated successfully!")
|
||||
}
|
||||
}
|
||||
|
||||
//func GetWidgetHTML(widgetService model.WidgetService) echo.HandlerFunc {
|
||||
// return func(request echo.Context) error {
|
||||
// ctx := context.Background()
|
||||
|
@ -86,7 +86,7 @@ func IncludeWidgetHandlers(
|
||||
) {
|
||||
server.POST(PREFIX+"/widgets", widget.CreateWidget(widgetService))
|
||||
server.GET(PREFIX+"/widgets", widget.GetStreamersWidgets(widgetService))
|
||||
|
||||
server.PATCH(PREFIX+"/widgets/:widgetID", widget.UpdateWidget(widgetService))
|
||||
//server.GET(PREFIX+"/html/:streamerID", model.GetWidgetHTML(widgetService))
|
||||
//server.GET(PREFIX+"/info/:widgetID", model.GetWidgetInfo(widgetService))
|
||||
//
|
||||
|
@ -628,7 +628,7 @@ const docTemplate = `{
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"GetWidgetDb"
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Get all streamer's widgets",
|
||||
"responses": {
|
||||
@ -675,7 +675,7 @@ const docTemplate = `{
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"GetWidgetDb"
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Create new widget",
|
||||
"parameters": [
|
||||
@ -716,6 +716,76 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/widgets/{widget_id}": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Update an existing widget",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Update an existing widget",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Widget ID",
|
||||
"name": "widget_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update widget",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/donat-widget_internal_model.UpdateWidget"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Widget has been updated successfully!",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized or expired token",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Widget not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -784,6 +854,9 @@ const docTemplate = `{
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "number"
|
||||
},
|
||||
"streamer_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
@ -1015,6 +1088,39 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"donat-widget_internal_model.UpdateWidget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"audio": {
|
||||
"type": "string",
|
||||
"example": "a0f9e244-f61f-4bfe-a7a0-3b5e91fe7364"
|
||||
},
|
||||
"duration": {
|
||||
"type": "integer",
|
||||
"example": 120
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"example": "d2c2f03f-3fe5-4bfc-b963-5478a057149e"
|
||||
},
|
||||
"is_active": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"max_amount": {
|
||||
"type": "integer",
|
||||
"example": 100
|
||||
},
|
||||
"min_amount": {
|
||||
"type": "integer",
|
||||
"example": 10
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Awesome Widget"
|
||||
}
|
||||
}
|
||||
},
|
||||
"donat-widget_internal_model.VoiceSettingsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -621,7 +621,7 @@
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"GetWidgetDb"
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Get all streamer's widgets",
|
||||
"responses": {
|
||||
@ -668,7 +668,7 @@
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"GetWidgetDb"
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Create new widget",
|
||||
"parameters": [
|
||||
@ -709,6 +709,76 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/widgets/{widget_id}": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Update an existing widget",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Widget"
|
||||
],
|
||||
"summary": "Update an existing widget",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Widget ID",
|
||||
"name": "widget_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update widget",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/donat-widget_internal_model.UpdateWidget"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Widget has been updated successfully!",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized or expired token",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Widget not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/echo.HTTPError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -777,6 +847,9 @@
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "number"
|
||||
},
|
||||
"streamer_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
@ -1008,6 +1081,39 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"donat-widget_internal_model.UpdateWidget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"audio": {
|
||||
"type": "string",
|
||||
"example": "a0f9e244-f61f-4bfe-a7a0-3b5e91fe7364"
|
||||
},
|
||||
"duration": {
|
||||
"type": "integer",
|
||||
"example": 120
|
||||
},
|
||||
"image": {
|
||||
"type": "string",
|
||||
"example": "d2c2f03f-3fe5-4bfc-b963-5478a057149e"
|
||||
},
|
||||
"is_active": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"max_amount": {
|
||||
"type": "integer",
|
||||
"example": 100
|
||||
},
|
||||
"min_amount": {
|
||||
"type": "integer",
|
||||
"example": 10
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "Awesome Widget"
|
||||
}
|
||||
}
|
||||
},
|
||||
"donat-widget_internal_model.VoiceSettingsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -48,6 +48,8 @@ definitions:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
size:
|
||||
type: number
|
||||
streamer_id:
|
||||
type: integer
|
||||
type: object
|
||||
@ -209,6 +211,30 @@ definitions:
|
||||
voice_speed:
|
||||
type: integer
|
||||
type: object
|
||||
donat-widget_internal_model.UpdateWidget:
|
||||
properties:
|
||||
audio:
|
||||
example: a0f9e244-f61f-4bfe-a7a0-3b5e91fe7364
|
||||
type: string
|
||||
duration:
|
||||
example: 120
|
||||
type: integer
|
||||
image:
|
||||
example: d2c2f03f-3fe5-4bfc-b963-5478a057149e
|
||||
type: string
|
||||
is_active:
|
||||
example: true
|
||||
type: boolean
|
||||
max_amount:
|
||||
example: 100
|
||||
type: integer
|
||||
min_amount:
|
||||
example: 10
|
||||
type: integer
|
||||
name:
|
||||
example: Awesome Widget
|
||||
type: string
|
||||
type: object
|
||||
donat-widget_internal_model.VoiceSettingsResponse:
|
||||
properties:
|
||||
min_price:
|
||||
@ -649,7 +675,7 @@ paths:
|
||||
- BearerAuth: []
|
||||
summary: Get all streamer's widgets
|
||||
tags:
|
||||
- GetWidgetDb
|
||||
- Widget
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
@ -684,7 +710,52 @@ paths:
|
||||
- BearerAuth: []
|
||||
summary: Create new widget
|
||||
tags:
|
||||
- GetWidgetDb
|
||||
- Widget
|
||||
/widgets/{widget_id}:
|
||||
patch:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Update an existing widget
|
||||
parameters:
|
||||
- description: Widget ID
|
||||
in: path
|
||||
name: widget_id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Update widget
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/donat-widget_internal_model.UpdateWidget'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Widget has been updated successfully!
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Bad request
|
||||
schema:
|
||||
$ref: '#/definitions/echo.HTTPError'
|
||||
"401":
|
||||
description: Unauthorized or expired token
|
||||
schema:
|
||||
$ref: '#/definitions/echo.HTTPError'
|
||||
"404":
|
||||
description: Widget not found
|
||||
schema:
|
||||
$ref: '#/definitions/echo.HTTPError'
|
||||
"422":
|
||||
description: Validation error
|
||||
schema:
|
||||
$ref: '#/definitions/echo.HTTPError'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: Update an existing widget
|
||||
tags:
|
||||
- Widget
|
||||
securityDefinitions:
|
||||
BearerAuth:
|
||||
in: header
|
||||
|
@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"donat-widget/internal/model/api"
|
||||
"github.com/google/uuid"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
@ -25,6 +26,7 @@ type WidgetService interface {
|
||||
name string,
|
||||
) (WidgetID, error)
|
||||
GetWidgetsByStreamer(ctx context.Context, streamerID int) ([]*WidgetWithFileLink, error)
|
||||
UpdateWidget(ctx context.Context, updateWidget UpdateWidget, widgetID, accountID int) error
|
||||
|
||||
//GetWidgetByID(ctx context.Context, widgetID WidgetID) ([]*GetWidgetDb, error)
|
||||
//GetWidgetHTML(ctx context.Context, streamerID StreamerID) (WidgetHTML, error)
|
||||
@ -47,7 +49,18 @@ type WidgetRepo interface {
|
||||
) (WidgetID, error)
|
||||
CheckWidgetName(ctx context.Context, streamerID int, name string) (bool, error)
|
||||
GetWidgetsByStreamerID(ctx context.Context, streamerID int) ([]*GetWidgetDb, error)
|
||||
|
||||
UpdateWidget(
|
||||
ctx context.Context,
|
||||
widgetID int,
|
||||
duration *int,
|
||||
minAmount *int,
|
||||
maxAmount *int,
|
||||
isActive *bool,
|
||||
image *uuid.UUID,
|
||||
audio *uuid.UUID,
|
||||
name *string,
|
||||
) error
|
||||
WidgetByID(ctx context.Context, widgetID, accountID int) error
|
||||
//GetWidgetByID(ctx context.Context, widgetID WidgetID) ([]*GetWidgetDb, error)
|
||||
//GetAllWidget(ctx context.Context, streamerID StreamerID) ([]*GetWidgetDb, error)
|
||||
//GetMediaFile(fileID FileID) (DownloadFile, error)
|
||||
|
@ -46,6 +46,16 @@ type WidgetWithFileLink struct {
|
||||
Widgets []*GetWidgetDb `json:"widgets"`
|
||||
}
|
||||
|
||||
type UpdateWidget struct {
|
||||
IsActive *bool `json:"is_active" example:"true" description:"Indicates whether the widget is active or not"`
|
||||
Name *string `json:"name" example:"Awesome Widget" description:"Name of the widget"`
|
||||
Image *uuid.UUID `json:"image" example:"d2c2f03f-3fe5-4bfc-b963-5478a057149e" description:"UUID of the widget image"`
|
||||
Audio *uuid.UUID `json:"audio" example:"a0f9e244-f61f-4bfe-a7a0-3b5e91fe7364" description:"UUID of the widget audio file"`
|
||||
Duration *int `json:"duration" example:"120" description:"Duration of the widget in seconds"`
|
||||
MinAmount *int `json:"min_amount" example:"10" description:"Minimum amount for the widget"`
|
||||
MaxAmount *int `json:"max_amount" example:"100" description:"Maximum amount for the widget"`
|
||||
}
|
||||
|
||||
type Donat struct {
|
||||
ID DonatID `db:"id"`
|
||||
StreamerID StreamerID `db:"streamer_id"`
|
||||
|
@ -139,3 +139,20 @@ FROM files AS f
|
||||
JOIN widgets AS w ON w.image = f.id
|
||||
WHERE f.streamer_id = (@streamer_id);
|
||||
`
|
||||
|
||||
var UpdateWidget = `
|
||||
UPDATE widgets
|
||||
SET
|
||||
duration = COALESCE(@duration, duration),
|
||||
min_amount = COALESCE(@min_amount, min_amount),
|
||||
max_amount = COALESCE(@max_amount, max_amount),
|
||||
is_active = COALESCE(@is_active, is_active),
|
||||
image = COALESCE(@image, image),
|
||||
audio = COALESCE(@audio, audio),
|
||||
name = COALESCE(@name, name)
|
||||
WHERE id = @id;
|
||||
`
|
||||
|
||||
var GetWidgetById = `
|
||||
SELECT id FROM widgets WHERE id = (@widget_id) AND streamer_id = (@streamer_id);
|
||||
`
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"donat-widget/internal/model"
|
||||
"donat-widget/internal/model/sql"
|
||||
"errors"
|
||||
"github.com/georgysavva/scany/v2/pgxscan"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"log/slog"
|
||||
)
|
||||
@ -97,6 +99,74 @@ func (widgetRepo *RepoWidget) GetWidgetsByStreamerID(
|
||||
return widgets, nil
|
||||
}
|
||||
|
||||
func (widgetRepo *RepoWidget) UpdateWidget(
|
||||
ctx context.Context,
|
||||
widgetID int,
|
||||
duration *int,
|
||||
minAmount *int,
|
||||
maxAmount *int,
|
||||
isActive *bool,
|
||||
image *uuid.UUID,
|
||||
audio *uuid.UUID,
|
||||
name *string,
|
||||
) error {
|
||||
args := pgx.NamedArgs{
|
||||
"id": widgetID,
|
||||
}
|
||||
|
||||
if duration != nil {
|
||||
args["duration"] = *duration
|
||||
}
|
||||
if minAmount != nil {
|
||||
args["min_amount"] = *minAmount
|
||||
}
|
||||
if maxAmount != nil {
|
||||
args["max_amount"] = *maxAmount
|
||||
}
|
||||
if image != nil {
|
||||
args["image"] = *image
|
||||
}
|
||||
if audio != nil {
|
||||
args["audio"] = *audio
|
||||
}
|
||||
if name != nil {
|
||||
args["name"] = *name
|
||||
}
|
||||
if isActive != nil {
|
||||
args["is_active"] = *isActive
|
||||
}
|
||||
|
||||
err := widgetRepo.db.Update(ctx, sql.UpdateWidget, args)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (widgetRepo *RepoWidget) WidgetByID(
|
||||
ctx context.Context,
|
||||
widgetID int,
|
||||
accountID int,
|
||||
) error {
|
||||
args := pgx.NamedArgs{
|
||||
"widget_id": widgetID,
|
||||
"streamer_id": accountID,
|
||||
}
|
||||
|
||||
row, err := widgetRepo.db.SelectOne(ctx, sql.GetWidgetById, args)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if row == nil {
|
||||
return errors.New("Widget not exists!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
//func (widgetRepo *RepoWidget) GetWidgetByID(
|
||||
// ctx context.Context,
|
||||
|
@ -97,6 +97,37 @@ func (widgetService *ServiceWidget) GetWidgetsByStreamer(
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (widgetService *ServiceWidget) UpdateWidget(
|
||||
ctx context.Context,
|
||||
updateWidget model.UpdateWidget,
|
||||
widgetID int,
|
||||
accountID int,
|
||||
) error {
|
||||
err := widgetService.widgetRepo.WidgetByID(ctx, widgetID, accountID)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = widgetService.widgetRepo.UpdateWidget(
|
||||
ctx,
|
||||
widgetID,
|
||||
updateWidget.Duration,
|
||||
updateWidget.MinAmount,
|
||||
updateWidget.MaxAmount,
|
||||
updateWidget.IsActive,
|
||||
updateWidget.Image,
|
||||
updateWidget.Audio,
|
||||
updateWidget.Name,
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
//func (widgetService *ServiceWidget) GetWidgetHTML(
|
||||
// ctx context.Context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user