extmpl

package
v0.1.43 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2021 License: BSD-3-Clause Imports: 23 Imported by: 0

README

extmpl - server side templates based on go/templates

Example Setup in a server

In the global config

type GlobalConfigData struct {
	...
	extmpl.ExTmplConfig
	...
}

then the setup for configuration files:

	// ==============================================================================================================================================
	// setup of multi/table master detail = 1:N, M:N, checkbox list tables.
	// if err = extmpl.SetupExTmplModels("./tmpl1/group.json", "./tmpl1/model.json"); err != nil {
	// ==============================================================================================================================================
	extmpl.SetupNoDoc(true)
	if err = extmpl.SetupExTmplModels(gCfg.ExTmplGroup, gCfg.ExTmplModel); err != nil {
		fmt.Fprintf(os.Stderr, "Fatal Error:%s\n", err)
		os.Exit(1)
	}
	// ==============================================================================================================================================
	// setups stuff in ./tmpl1/setup[.json like /index.html and "/" and "" all going to index.html handler.
	// ==============================================================================================================================================
	extmpl.SetupMux(mux, logFilePtr, &(gCfg.ExTmplConfig), DB, &dbOn, &dbOnLock, gCfg.AppName)

3 configuration files are at the top level, ./tmpl1/setup.json determines the simple paths, ./tmp1/group.json determines the master-detail and M:N paths along with ./tmpl1/model.json that holds a copy of the relational database model.

./tmpl1/setup.json

An example. The /index.html is defined in ./tmpl1/index.json. /login.html is defined in ./tmpl1/login.json. Paths are searched in order for each of the templates defined.

{ "api": {
	 "/index.html": { 
		  "page_name": "index.json"
		, "path": "./tmpl1;./tmpl1/index"
		}
...
	,"/login.html": { 
		  "page_name": "login.json"
		, "path": "./tmpl1"
		}
...
} }
./tmp1/login.json

This specifies for the 'partial' == 'page' that the set of template files will be page.html with replacement templates from login.html.

For "partial" == "partial" the set will be partial-page.html with replacements from lgoin.html.

You can specify as many different named sets of templates as you want. The default set is 'page'.

No selects are performed to fetch data from the database.

{
	"TemplateSet": {
		  "page": {
			  "Template": [ "page.html", "login.html" ]
		}
		, "partial": {
			  "Template": [ "partial-page.html", "login.html" ]
		}
	},
	"SelectData": [ ]
}
Example Call
	mdata["data"] = make ( map[string]interface{} )

	// ------------------------------------------------------------------------------------------------------------------------
	// Load template files
	// ------------------------------------------------------------------------------------------------------------------------
	TemplateCtl, err := extmpl.NewTemplate(tmpl_name, templateList...)

	// ------------------------------------------------------------------------------------------------------------------------
	// Render Template
	// ------------------------------------------------------------------------------------------------------------------------
	tmpl_rendered, err = extmpl.TemplateCtl.ByName("render", mdata)
Client Side partial rendering

A function to take the partial that is returned and paint this into a page at the #body id tag.


// ---------------------------------------------------------------------------------------------------------------------
// Rendering of partials into page.
//
// PushParams takes parameters and pushes them into data that is will be passed as a part of the "GET" request.
// ---------------------------------------------------------------------------------------------------------------------

function PushParams() {
	g_data.params = {};
	for ( var i = 0; i < arguments.length; i += 2 ) {
		var n = arguments[i];
		var v = ( (i+1) < arguments.length ) ? arguments[i+1] : "";
		g_data.params[n] = v;
	}
}

function getGData() {
	var ss = "";
	for ( var key in g_data.params ) {
		ss = ss + '&' + key + '=' + encodeURIComponent( g_data.params[key] );
	}
	return ss;
}

function renderPartial(name) {
	var addHtml = ( name.match(/\.html$/ ) ) ? "" : ".html";		// add .html to end if it is not there.
	if ( ! g_data.params ) {
		g_data.params = {};
	}
	for ( var i = 1; i < arguments.length; i += 2 ) {
		var n = arguments[i];
		var v = ( (i+1) < arguments.length ) ? arguments[i+1] : "";
		g_data.params[n] = v;
	}
	// console.log ( "g_daa.params = ", g_data.params, "getGData()=", getGData() );
	var url = "/"+name+addHtml+"?page_type=partial"+getGData();
	// console.log ( "url=", url );
	$.get( url, function( data ) {
		$("#body").html( data );
		g_data.prev_params = $.extend ( {}, g_data.params );	// Save for debuging purposes.
		g_data.params = {};
	});
}

Documentation

Index

Constants

View Source
const ISO8601 = "2006-01-02T15:04:05.99999Z07:00"

ISO format for date

View Source
const ISO8601output = "2006-01-02T15:04:05.99999-0700"

ISO format for date

Variables

View Source
var DB *sql.DB
View Source
var DbBeginQuote = `"`
View Source
var DbEndQuote = `"`
View Source
var DbOn *map[string]bool
View Source
var DbOnLock *sync.Mutex
View Source
var ValidRelationType = []string{
	"1:N",
	"N:1",
	"1:0..1",
	"1:1..N",
	"1:1",
}

Functions

func HandleRenderPageEndPoint

func HandleRenderPageEndPoint(api_endpoint string, val AnEndpointType) (fx func(www http.ResponseWriter, req *http.Request))

HandleRenderPageEndPoint is a closure returing a http.Handler function - the funtion renders Page and Parital end points (default "page"). This is the main handler for ./tmpl1/setup.json end points. ./tmpl1/setup.json maps an endpoint to a pair of files. A JSON file that contains select(s) and the set of pages that can be rendered.

{ "api": {
...
...
...
, "/create-dev-un-pw-acct.html": {
	  "page_name": "create-dev-un-pw-acct.json"
	, "path": "./tmpl1"
	, "auth_required": true
	}
...
...
...
} }

In this case the end point is `/create-dev-un-pw-acct.html`. This maps to the JSON setup file that is found in using the ./tmpl1 path. This end point requires login.

The JSON setup file specifies the set of pages that can be rendered.

{
	"TemplateSet": {
		  "page": {
			  "Template": [ "page.html", "create-dev-un-pw-acct.html" ]
		}
		, "partial": {
			  "Template": [ "partial-page.html", "create-dev-un-pw-acct.html" ]
		}
	},
	"SelectData": [ ]
}

In this case for a page_type of "partial" the set of templates is ./tmpl1/partial-page.html and ./tmpl1/create-dev-un-pw-acct.html. There is no slect data used.

DebugFlags:

DumpTemplate - tracing informaiton.
DumpTemplateStderr Print complteted template out to Stderr
DumpTemplateLogFile Print complteted template out to LogFile

func HandleRenderPartial

func HandleRenderPartial(www http.ResponseWriter, req *http.Request)

func HasTemplate

func HasTemplate(TemplateCtl *TmplObj, name string) (hasIt bool)

HasTemplate returns true if the tempalte named `name` is in the set of defined templates.

func OpToMethod

func OpToMethod(op string) (method string)

func PathFind

func PathFind(path, fn string) (full_path, file_type string, err error)

full_path, file_type, err := PathFind(path, tmpl_name) PathFind searches each location in the path for the specified file. It returns the first full file name that is found or an error of "Not Found" path - top level directory to search in. fn - file name or pattern to search for.

func ProcessSQL

func ProcessSQL(ds *JsonTemplateRunnerType, getDataForSQL func(name string, tmplIt bool) string, TemplateCtl *TmplObj) (mdata map[string]interface{}, err error)

ProcessSQL will run sql statments and collect the data for use in temlates.

func RenderTemplate

func RenderTemplate(mdata map[string]interface{}, tmplList string, fns ...string) (tmpl_rendered string, err error)

RenderTemplate will take the data in mdata and combine the templates and render the resulting template. The template that is rendered is "render". Each of the files, fns, is a full path to a file to render. Example Call: tmpl_rendered, err = RenderTemplate(mdata, full_path)

func RenderTemplateByName

func RenderTemplateByName(name string, mdata map[string]interface{}, tmplList string, fns ...string) (tmpl_rendered string, err error)

func ReturnHandleRenderPage

func ReturnHandleRenderPage(endPoint string) func(www http.ResponseWriter, req *http.Request)

func RowsToInterface

func RowsToInterface(rows *sql.Rows) ([]map[string]interface{}, string, int)

------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------

func Run1

func Run1(db *sql.DB, q string, arg ...interface{}) error

------------------------------------------------------------------------------------------------- test: t-run1q.go, .sql, .out -------------------------------------------------------------------------------------------------

func SelData2

func SelData2(db *sql.DB, q string, data ...interface{}) ([]map[string]interface{}, error)

------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------

func SelQ

func SelQ(db *sql.DB, q string, data ...interface{}) (Rows *sql.Rows, err error)

------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------

func SetDbOn

func SetDbOn(x *map[string]bool, y *sync.Mutex)

func SetGPath

func SetGPath(s string)

func SetupExTmplModels

func SetupExTmplModels(fnGroup, fnModel string) (err error)

func SetupMux

func SetupMux(mux *ymux.ServeMux, lf *os.File, cfg *ExTmplConfig, xDB *sql.DB, dbOn *map[string]bool, dbOnLock *sync.Mutex, AppName string)

func SetupNoDoc

func SetupNoDoc(b bool)

true turns off documents

func SetupTemplate

func SetupTemplate(tmplList string, fns ...string) (tmpl *template.Template, err error)

func TmplProcess

func TmplProcess(
	item string,
	tmpl_name string,
	dataFunc func(name string, tmplIt bool) string,
) (tmpl_rendered string, status int, err error)

func TmplProcessInternal

func TmplProcessInternal(
	item string,
	tmpl_name string,
	path string,
	dataFunc func(s string, tmplIt bool) string,
) (body, data, tmpl_rendered string, status int, err error)

func TmplTest

func TmplTest(
	item string,
	tmpl string,
	test_name string,
)

xyzzy - implement xyzzy - test

Types

type AnEndpointType

type AnEndpointType struct {
	PageName     string   `json:"page_name" default:"app.json"`
	Path         string   `json:"path" default:"./tmpl1"`
	DebugFlags   []string `json:"debug_flags"`
	AuthRequired bool     `json:"auth_required"`

	NoDoc     bool             `json:"NoDoc"`
	DocTag    string           `json:"DocTag"`
	InputList []*ymux.MuxInput `json:"InputList"`
	// contains filtered or unexported fields
}

type BindType

type BindType map[string]string

type BodyConfigType

type BodyConfigType struct {
	ColumnName                    string
	ColumnPos                     int
	IsAction                      bool
	ColumnDataActionTemplate      string   // new
	ColumnDataActionTemplateByCol []string // new
	ColumnDataTemplate            string   // new
	ColumnDataTemplateByCol       []string // new
}

type ColumnType

type ColumnType struct {
	ColName        string            `json:"ColName"`
	Type           string            //
	TmplType       string            `json:"TmplType"` // convert from 's' -> Stringt, but allow setting for other special types like "File"
	MinLen         int               `json:"MinLen"`
	MaxLen         int               `json:"MaxLen"`
	ValidationRE   string            `json:"ValidationRE"`
	ValidationType string            `json:"ValidationType"`
	Name           string            //
	Label          string            //
	SelectValues   []SelectValueType `json:"SelectValues"`
}

type ExTmplConfig

type ExTmplConfig struct {
	TemplatePath      string `json:"template_path" default:"./tmpl1"` // xyzzy2
	BasePage          string `json:"base_page" default:"index.html"`
	TemplateAPIConfig string `json:"tmpl_api_config" default:"./tmpl1/setup.json"`
	ExTmplGroup       string `json:"tmpl_group" default:"./tmpl1/group.json"`
	ExTmplModel       string `json:"tmpl_model" default:"./tmpl1/model.json"`
}

type ExTmplateAPIConfigData

type ExTmplateAPIConfigData struct {
	API map[string]AnEndpointType `json:"api"`
}

type GroupItemType

type GroupItemType struct {
	AnEndpointType
	PrimaryTable     string   `json:"primary_table"`
	RelatedTableList []string `json:"related_table_list"`
	LayoutFormat     string   `json:"layout_format"`
	MetaRelationship string   `json:"MetaRelationship"`
	Stmt             string   `json:"Stmt"`
	Bind             BindType `json:"Bind"`
	StmtDetail       string   `json:"StmtDetail"`
	BindDetail       BindType `json:"BindDetail"`
}

type GroupType

type GroupType map[string]GroupItemType

func ReadGroup

func ReadGroup(fn string) (rv GroupType, err error)

type GroupType map[string][]string

type HeaderConfigType

type HeaderConfigType struct {
	ColumnTitle      string
	ColumnName       string
	ColumnPos        int
	IsAdd            bool
	AddTemplate      string   // new
	AddTemplateByCol []string // new
	HdrTemplate      string   // new
	HdrTemplateByCol []string // new
}
  1. Run multiple selects

    select: [ { "to": "name" "stmt": "select..." "errror_on": 0 rows etc. } , { "to": "name...x" "stmt": "select..." "errror_on": 0 rows etc. "bind": [ "$1": "{{.name}}" ] } ]

    Bind values by name from GET/POST and previous queries

    Run Template at the end

    "template": [ "base.html", "tmpl1.html" ... ]

    Set of request for template

    "TemplateSet": { "page_name": { "template": [ "full_page.html", "extend1.tmpl" ] } , "partial": { "template": [ "section.html", "extend1.tmpl" ] , "target": "body" } }

    Layout Info "jsonLayout": { -- data for layout / style of layout }

    Testing "test": [ { "data": { "user_id": "123" } , "expect": ... } ]

Notes:

.MuxName														-- Name of page we are displaying
.HeaderInfo[]													-- slice of column header info
.HeaderInfo[].ColumnTitle									-- title for column
.HeaderInfo[]. ?? sort info ??								-- todo - future - sort/filter info for a column

$row.id															-- Per row (t_ymux_documents) - Unique PK/Id for the column
$row.data														-- The set of data in a column (may have more than displayed)
.data["MuxName"][$row.pos]										-- The data for a particular table/row
.data["MuxName"][$row.pos][$col.name]							-- A single data item

$row.BodyInfo[]											-- Data for the displayed columns
$row.BodyInfo[].coldata									-- a single data item to be displayed

.t_ymux_documents				[[ primary table name ]]

type JsonTemplateRunnerType

type JsonTemplateRunnerType struct {
	TemplateList []string                   `json:"Template"`
	TemplateSet  map[string]TemplateSetType `json:"TemplateSet"`
	SelectData   []SelectDataType           `json:"SelectData"`
}

func ReadJsonTemplateConfigFile

func ReadJsonTemplateConfigFile(fn string) (ds JsonTemplateRunnerType, err error)

ds, err := ReadJsonTemplateConfigFile(full_paty)

type LayoutItemType

type LayoutItemType struct {
	MatchTo     string `json:"match"`
	TemplateFor string `json:"for"`
}

type ModelTable

type ModelTable struct {
	Table     string
	Api       string
	SelectApi string
	Relations []RelationsToType
	Columns   []ColumnType
}

Example Data // ---------------------------------------------------------------------------------------------- xyzzy4

type ModelType

type ModelType struct {
	Primary map[string]ModelTable
}

func ReadModel

func ReadModel(fn string) (rv ModelType, err error)

type MyDb

type MyDb struct {
	Db     *sql.DB
	DbType string
}

func ConnectToAnyDb

func ConnectToAnyDb(db_type string, auth string, dbName string) *MyDb

type RelationsToType

type RelationsToType struct {
	TableName    string `json:"to_table_name"`
	RelationType string `json:"relation_type"` // check on 1:N, N:1, 1:1, 1:1..N, etc.
	Sequenced    string
	Fk           []string
	PkUk         []string
}

type SelectDataType

type SelectDataType struct {
	To            string             // Name of data item to place data in.	 (MuxData?)
	Stmt          string             // SQL ro run
	Bind          map[string]string  //
	ErrOn         string             // Xyzzy - needs work
	UpdateAPI     string             // what to call for Update/Delete/Insert
	UpdateColumns []string           //
	InsertColumns []string           //
	MuxName       string             `json:"MuxName"`    // Primary Table Name
	DetailName    string             `json:"DetailName"` //
	HeaderInfo    []HeaderConfigType `json:"HeaderInfo"` //
	BodyInfo      []BodyConfigType   `json:"BodyInfo"`   //
}

type SelectValueType

type SelectValueType struct {
	Tag     string
	Value   string
	Default bool
}

type TemplateSetType

type TemplateSetType struct {
	TemplateList []string `json:"Template"`
}

type TmplObj

type TmplObj struct {
	Tmpl *template.Template
}

func NewTemplate

func NewTemplate(tmplList string, fns ...string) (rv *TmplObj, err error)

func (*TmplObj) ByName

func (tt *TmplObj) ByName(name string, mdata map[string]interface{}) (tmpl_rendered string, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL