| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // package mod_http -- http-движок для архитектуры
- package engine_http
- import (
- "bytes"
- _ "embed"
- "fmt"
- "time"
- svg "github.com/ajstarks/svgo"
- "github.com/gofiber/fiber/v2"
- "gitp78su.ipnodns.ru/svi/kern/v3"
- "gitp78su.ipnodns.ru/svi/kern/v3/kc/log_buf"
- "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
- "gopkg.in/yaml.v3"
- "gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
- "gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
- "gitp78su.ipnodns.ru/svi/goarch/lev0/types"
- "gitp78su.ipnodns.ru/svi/goarch/lev1/coord"
- "gitp78su.ipnodns.ru/svi/goarch/lev1/size"
- "gitp78su.ipnodns.ru/svi/goarch/pkg/elems/canvas"
- )
- //go:embed index.html
- var indexHtml []byte
- // CanvasSize -- размер хоста
- type CanvasSize struct {
- SizeX_ int `form:"w"`
- SizeY_ int `form:"h"`
- }
- func (sf *CanvasSize) String() string {
- return fmt.Sprintf("w:%v; h:%v", sf.SizeX_, sf.SizeY_)
- }
- // EngineHttp -- http-движок для архитектуры
- type EngineHttp struct {
- // fibApp *fiber.App
- kCtx ktypes.IKernelCtx
- log ktypes.ILogBuf
- diaMode string // Режим диаграммы
- oldBinArch []byte // Кеш старой архитектуры
- canvSize CanvasSize // Размер холста
- size types.IViewSize // Размер холста в его координатах
- pos types.IViewCoord // Координаты холста
- mapDrawer types.IMapDrawer // Словарь отрисовщиков
- }
- // NewEngineHttp -- возвращает новый движок HTTP
- func NewEngineHttp() *EngineHttp {
- optTerm := log_buf.OptIsTerm(true)
- optPref := log_buf.OptPrefix("EngineHttp")
- log := log_buf.NewLogBuf(optTerm, optPref)
- sf := &EngineHttp{
- kCtx: kern.GetKernelCtx(),
- log: log,
- diaMode: cons.ModeUseCase,
- size: size.NewSize(800, 600),
- pos: coord.NewCoord(0, 0),
- }
- sHttp := kern.GetKernelServerHttp()
- fibApp := sHttp.Fiber()
- fibApp.Static("/static", "./static", fiber.Static{
- Compress: true,
- Browse: true,
- CacheDuration: time.Second * 10,
- })
- fibApp.Get("/", sf.getIndex)
- fibApp.Get("/api/use_case", sf.postSetModeUseCase)
- fibApp.Post("/api/arch", sf.postArch)
- fibApp.Post("/api/canvas_size", sf.postSetCanvasSize)
- return sf
- }
- // FormArch -- извлекает данные из текстового поля для обновления
- type FormArch struct {
- StrData string `form:"text"`
- }
- // Устанавливает размер холста
- func (sf *EngineHttp) postSetCanvasSize(ctx *fiber.Ctx) error {
- err := ctx.BodyParser(&sf.canvSize)
- if err != nil {
- sf.log.Err("postSetCanvasSize(): on body parser, err=\n\t%v", err)
- }
- var (
- w alias.SizeX
- h alias.SizeY
- )
- if sf.canvSize.SizeX_ > 0 {
- w = alias.SizeX(sf.canvSize.SizeX_ - 10)
- }
- if sf.canvSize.SizeY_ > 0 {
- h = alias.SizeY(sf.canvSize.SizeY_ - 10)
- }
- sf.size = size.NewSize(w, h)
- return ctx.SendString(sf.size.String())
- }
- // Возвращает новый холст
- func (sf *EngineHttp) canvas(wr *bytes.Buffer, lstElem []map[string]interface{}) (*svg.SVG, error) {
- var (
- elem map[string]interface{}
- isFind, isOk bool
- _section interface{}
- )
- for _, elem = range lstElem {
- _section, isOk = elem["type"]
- if !isOk {
- continue
- }
- section, isOk := _section.(string)
- if !isOk {
- return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, type(%#+v) not string<br>%#+v", _section, elem)
- }
- if section == cons.SectionConfig {
- isFind = true
- break
- }
- }
- if !isFind {
- return nil, fmt.Errorf("ServHttp.canvas(): in mapElem, config not found")
- }
- confCanvas := canvas.NewCanvas(sf.diaMode, sf.size, sf.pos)
- sizeX, sizeY := confCanvas.Size().Int()
- canvas := svg.New(wr)
- canvas.Start(sizeX, sizeY)
- confCanvas.Draw(canvas)
- return canvas, nil
- }
- // По запросу парсит, что получилось -- обновляет архитектуру
- func (sf *EngineHttp) postArch(ctx *fiber.Ctx) error {
- form := &FormArch{}
- if err := ctx.BodyParser(form); err != nil {
- return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in BodyParser, err=<br>%v", err))
- }
- binData := []byte(form.StrData)
- if len(binData) == len(sf.oldBinArch) {
- return ctx.Send(sf.oldBinArch)
- }
- mapElem := []map[string]interface{}{}
- err := yaml.Unmarshal(binData, &mapElem)
- if err != nil {
- return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in Decode JSON, err=<br>%v", err))
- }
- wr := bytes.NewBuffer(nil)
- canvas, err := sf.canvas(wr, mapElem)
- if err != nil {
- return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in create canvas, err=<br>%v", err))
- }
- switch sf.diaMode {
- case cons.ModeUseCase: // режим вариантов использования
- if err := sf.useCase(canvas); err != nil {
- return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): in useCase, err=<br>%v", err))
- }
- default: // неизвестный режим
- return ctx.SendString(fmt.Sprintf("ServHttp.archPost(): unknown mode=%q", sf.diaMode))
- }
- canvas.End()
- binData = wr.Bytes()
- return ctx.Send(binData)
- }
- // Формирует варианты использования
- func (sf *EngineHttp) useCase(canvas *svg.SVG) error {
- for _, elem := range sf.mapDrawer.LstDrawers() {
- elem.Draw(canvas)
- }
- return nil
- }
- // Возвращает картинку архитектуры
- func (sf *EngineHttp) postSetModeUseCase(ctx *fiber.Ctx) error {
- sf.diaMode = cons.ModeUseCase
- return ctx.SendString("[mode='" + sf.diaMode + "']")
- }
- // Возвращает главную страницу сервиса
- func (sf *EngineHttp) getIndex(ctx *fiber.Ctx) error {
- ctx.Response().Header.Set("Content-Type", "text/html")
- return ctx.Send(indexHtml)
- }
|