diff --git a/.drone.yml b/.drone.yml index 9fab517..900ef38 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,9 +7,14 @@ pipeline: pull: true commands: - mkdir -p /go/bin /go/src - - go get github.com/revel/cmd/revel - - revel build github.com/CyCoreSystems/cycore-web ../tmp prod - - mv ../tmp . + - go get -u github.com/golang/dep/cmd/dep/... + - go get -u github.com/alecthomas/gometalinter/... + - go get -u github.com/mjibson/esc + - dep ensure + - go generate + - gometalinter --install + - gometalinter --vendor ./... + - go build publish: image: plugins/docker:17.05 repo: quay.io/cycore/web diff --git a/.gitignore b/.gitignore index fe69af1..7f646c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -test-results/ -tmp/ -routes/ /vendor/ +/cycore-web diff --git a/Dockerfile b/Dockerfile index 074a9fd..88d6799 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ FROM ulexus/go-minimal -COPY tmp/cycore-web /app -COPY tmp/src /src +COPY cycore-web /app +COPY assets /assets diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..a67db44 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,99 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/CyCoreSystems/sendinblue" + packages = ["."] + revision = "9b851c8f8e26b6bfc746aaa0dbaf8f7a78286ee0" + version = "v0.1.1" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" + +[[projects]] + branch = "master" + name = "github.com/jmoiron/sqlx" + packages = [".","reflectx"] + revision = "2aeb6a910c2b94f2d5eb53d9895d80e27264ec41" + +[[projects]] + name = "github.com/labstack/echo" + packages = [".","middleware"] + revision = "6d227dfea4d2e52cb76856120b3c17f758139b4e" + version = "3.3.5" + +[[projects]] + name = "github.com/labstack/gommon" + packages = ["bytes","color","log","random"] + revision = "588f4e8bddc6cb45c27b448e925c7fd6a5545434" + version = "0.2.5" + +[[projects]] + branch = "master" + name = "github.com/lib/pq" + packages = [".","oid"] + revision = "d34b9ff171c21ad295489235aec8b6626023cd04" + +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" + version = "v0.0.9" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + branch = "master" + name = "github.com/valyala/bytebufferpool" + packages = ["."] + revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7" + +[[projects]] + branch = "master" + name = "github.com/valyala/fasttemplate" + packages = ["."] + revision = "dcecefd839c4193db0d35b88ec65b4c12d360ab0" + +[[projects]] + name = "go.uber.org/atomic" + packages = ["."] + revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289" + version = "v1.3.2" + +[[projects]] + name = "go.uber.org/multierr" + packages = ["."] + revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a" + version = "v1.1.0" + +[[projects]] + name = "go.uber.org/zap" + packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"] + revision = "eeedf312bc6c57391d84767a4cd413f02a917974" + version = "v1.8.0" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["acme","acme/autocert"] + revision = "1a580b3eff7814fc9b40602fd35256c63b50f491" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "7c87d13f8e835d2fb3a70a2912c811ed0c1d241b" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "663f98ffe10e2e1074511774007b7ec79196f112e44ab874c8e209c2ee0d9453" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..3ccce21 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,42 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/CyCoreSystems/sendinblue" + version = "0.1.1" + +[[constraint]] + branch = "master" + name = "github.com/jmoiron/sqlx" + +[[constraint]] + name = "github.com/labstack/echo" + version = "3.3.5" + +[[constraint]] + branch = "master" + name = "github.com/lib/pq" + +[[constraint]] + name = "go.uber.org/zap" + version = "1.8.0" diff --git a/app/controllers/app.go b/app/controllers/app.go deleted file mode 100644 index e76d76b..0000000 --- a/app/controllers/app.go +++ /dev/null @@ -1,11 +0,0 @@ -package controllers - -import "github.com/revel/revel" - -type App struct { - *revel.Controller -} - -func (c App) Index() revel.Result { - return c.Render() -} diff --git a/app/controllers/contact.go b/app/controllers/contact.go deleted file mode 100644 index 342a5e8..0000000 --- a/app/controllers/contact.go +++ /dev/null @@ -1,116 +0,0 @@ -package controllers - -import ( - "bytes" - "encoding/json" - "html/template" - "os" - "time" - - "github.com/CyCoreSystems/cycore-web/app/routes" - "github.com/CyCoreSystems/sendinblue" - "github.com/revel/revel" -) - -var contactEmailT *template.Template - -func init() { - contactEmailT = template.Must(template.New("contactEmail").Parse(contactEmailTemplate)) -} - -// Contact controller handles customer contact operations -type Contact struct { - *revel.Controller -} - -// ContactRequest handles a customer contact request -func (c Contact) ContactRequest(name, email string) revel.Result { - - c.Log.Info("received contact request", "name", name, "email", email, "source", c.ClientIP) - - if name == "" { - c.Flash.Error("Please supply a name") - return c.Redirect(routes.App.Index()) - } - if email == "" { - c.Flash.Error("Please supply an email address") - return c.Redirect(routes.App.Index()) - } - - emailBody, err := c.renderContactEmail(name, email) - if err != nil { - c.Log.Error("failed to render contact email", "error", err) - c.Flash.Error("Internal error encountered; please try again") - return c.Redirect(routes.App.Index()) - } - - msg := &sendinblue.Message{ - Sender: &sendinblue.Address{ - Name: "CyCore Systems, Inc", - Email: "sys@cycoresys.com", - }, - To: c.getEmailContacts(), - Subject: "Contact Request", - HTMLContent: emailBody, - Tags: []string{"contact-request"}, - } - if err = msg.Send(os.Getenv("SENDINBLUE_APIKEY")); err != nil { - c.Log.Error("failed to send contact email", "error", err) - c.Flash.Error("Request failed") - - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - enc.Encode(msg) - - return c.Redirect(routes.App.Index()) - } - - c.Flash.Success("Request sent") - return c.Redirect(routes.App.Index()) -} - -func (c Contact) renderContactEmail(name, email string) (string, error) { - buf := new(bytes.Buffer) - err := contactEmailT.Execute(buf, struct { - Name string - Email string - Timestamp string - }{ - Name: name, - Email: email, - Timestamp: time.Now().String(), - }) - if err != nil { - return "", err - } - return buf.String(), nil -} - -func (c Contact) getEmailContacts() []*sendinblue.Address { - - var ret []*sendinblue.Address - if err := json.Unmarshal([]byte(os.Getenv("CONTACT_RECIPIENTS")), &ret); err != nil { - - // Fall back to default if we fail to load from environment - c.Log.Warn("failed to load recipients from environment", "error", err) - ret = append(ret, &sendinblue.Address{ - Name: "System Receiver", - Email: "sys@cycoresys.com", - }) - - } - return ret -} - -var contactEmailTemplate = ` - - -

Web Contact Form

- - - -` diff --git a/app/init.go b/app/init.go deleted file mode 100644 index 7d2dbc1..0000000 --- a/app/init.go +++ /dev/null @@ -1,59 +0,0 @@ -package app - -import ( - "os" - - "github.com/revel/log15" - "github.com/revel/revel" -) - -func init() { - // Filters is the default set of global filters. - revel.Filters = []revel.Filter{ - revel.PanicFilter, // Recover from panics and display an error page instead. - revel.RouterFilter, // Use the routing table to select the right Action - revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters. - revel.ParamsFilter, // Parse parameters into Controller.Params. - revel.SessionFilter, // Restore and write the session cookie. - revel.FlashFilter, // Restore and write the flash cookie. - revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie. - //revel.I18nFilter, // Resolve the requested language - HeaderFilter, // Add some security based headers - revel.InterceptorFilter, // Run interceptors around the action. - revel.CompressFilter, // Compress the result. - revel.ActionInvoker, // Invoke the action. - } - - // register startup functions with OnAppStart - // ( order dependent ) - // revel.OnAppStart(InitDB) - // revel.OnAppStart(FillCache) - revel.OnAppStart(InitLogger) -} - -// HeaderFilter is a default set of headers to be added -// TODO turn this into revel.HeaderFilter -// should probably also have a filter for CSRF -// not sure if it can go in the same filter or not -var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) { - // Add some common security headers - c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN") - c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block") - c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff") - - fc[0](c, fc[1:]) // Execute the next filter stage. -} - -// InitLogger initializes the logging handler -func InitLogger() { - - // If we are running inside kubernetes, use the oklog logger - if os.Getenv("KUBERNETES_SERVICE_HOST") != "" { - h, err := log15.NetHandler("tcp", "oklog.log:7651", log15.JsonFormat()) - if err != nil { - revel.AppLog.Error("failed to construct network log handler", "error", err) - return - } - revel.RevelLog.SetHandler(h) - } -} diff --git a/app/views/debug.html b/app/views/debug.html deleted file mode 100644 index 5f1013c..0000000 --- a/app/views/debug.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - diff --git a/app/views/footer.html b/app/views/footer.html deleted file mode 100644 index ead527b..0000000 --- a/app/views/footer.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - {{if eq .RunMode "dev"}} - {{template "debug.html" .}} - {{end}} - - diff --git a/assets/css/alert.import.less b/assets/css/alert.import.less new file mode 100644 index 0000000..aad7399 --- /dev/null +++ b/assets/css/alert.import.less @@ -0,0 +1,12 @@ +.alert { + width: 100%; + text-align: center; +} + +.alert-error { + color: @red; +} + +.alert-success { + color: @green; +} diff --git a/assets/css/anim.import.less b/assets/css/anim.import.less new file mode 100644 index 0000000..d578fc0 --- /dev/null +++ b/assets/css/anim.import.less @@ -0,0 +1 @@ +//ANIMATIONS diff --git a/assets/css/base.import.less b/assets/css/base.import.less new file mode 100644 index 0000000..0160eb0 --- /dev/null +++ b/assets/css/base.import.less @@ -0,0 +1,164 @@ + +//PRESETS + +body, div, nav, ul, li, a, label, span, table { + margin: 0; + padding: 0; + float: left; + box-sizing: border-box; + background-clip: border-box; +} + body { + min-height: 100%; + height: 100%; + background: @background; + } + ul { + list-style: none; + } + div { + float: left; + } + a { + text-decoration: none; + font-weight: bold; + padding: 5px 10px; + .border-radius(7px); + .fasttrans; + color: @key; + } + a:hover { .fasttrans; color: @keylight;} + +.hide { display: none; } + +//GRID COLUMNS + +.twelve { .column(12); } +.ten { .column(10); } +.nine { .column(9); } +.eight { .column(8); } +.six { .column(6); } +.five { .column(5); } +.four { .column(4); } +.three { .column(3); } +.two { .column(2); } + +//STRUCTURES + +#page { + width: 100%; + height: 100%; + min-height: 500px; + background: white; +} + +.unit { //used for tables + overflow: hidden; + .background-linear-gradient(#fff 25%, @lightgrey); + border: 1px solid @lightgrey; + .border-radius(5px); + .box-shadow(1px 1px 1px 0 rgba(0, 0, 0, 0.6)); +} +.contentunit { + .background-linear-gradient(white, fadeout(@keylight, 98%)); + .border-radius(10px); + border: 2px solid fadeout(@keylight, 60%); +} +.transcontentunit { + .contentunit; + background: transparent none; + border: 2px solid transparent; +} +.colorcontentunit { + .contentunit; + background: @key; + border: 2px solid @key; + font-size: 1.3em; + color: white; + padding: 20px; +} + +label { + width: 40%; + text-align: right; + margin-left: 7px; +} + + +i { + color: white; + display: block; + text-align: center; + margin: 0 auto; + background-color: @key; + .border-radius(150px); + .box-shadow(0px 1px 2px 0 @darkestgrey); + .fasttrans; +} + i:hover { background-color: @keylight; .fasttrans; } + + .social i { + font-size: 26px; + height: 32px; + width: 42px; + padding-top: 10px; + color: white; + } + + .hide { display: none; } + + .tag { + display: block; + background: fadeout(@keylight, 80%); + .border-radius(2px); + padding: 2px 5px; + margin: 2px 10px 2px 0; + border: 1px solid @lightestgrey; + color: @darkgrey; + font-weight: bold; + + } + +.footer { + position: relative; + + width: 100%; + height: 50px; + padding: 50px 30px 0 30px; + + .copy, .credit { + .sans; + font-size: 16px; + font-weight: normal; + line-height: 30px; + margin: 0; + width: auto; + padding: 0 10px; + } + .credit a { + margin: 0; + padding: 0; + line-height: 30px; + color: @key; + } + .credit a:hover { + color: @keydark; + } + .copy { + color: @darkgrey; + float: right; + } + .login { + float: right; + + a { .sans; } + } + + .social { + float: right; + height: 100%; + padding-right: 50px; + } + +} + diff --git a/assets/css/button.import.less b/assets/css/button.import.less new file mode 100644 index 0000000..4b9fd3a --- /dev/null +++ b/assets/css/button.import.less @@ -0,0 +1,82 @@ + +//BUTTONS + +button { border: 0 none; } + +button.demo { + background-color: @key; + border-top: 1px solid @keylight; + border-bottom: 1px solid @transblack; + .box-shadow( + inset 0 0 20px 5px @transblack, + inset 0 0 0 0 @keylight, + 0 2px 4px 0 @lightblack); + text-shadow: -1px -1px 0 black, 1px 1px 0 @keylight; + + color: white; + + .slowtrans; + + i { + color: @key; + font-size: 85px; + text-shadow: 0 0 0 transparent; + vertical-align: bottom; + position: relative; + top: -11px; + } + +} + button.demo:hover { +// background-color: @keylight; + .box-shadow( + inset 0 0 20px 5px @transblack, + inset 0px 10px 50px 0 fadeout(@keylight, 70%), + 0 2px 4px 0 @lightblack); + text-shadow: -1px -1px 0 black, 1px 1px 0 @key; + + .slowtrans; + + i { + color: white; + text-shadow: 0 0 4px @key; + .fasttrans; + } + } +button.large { + width: 800px; + margin: 0 auto; + height: 100px; + .border-radius(8px); + padding-top: 7px; + + font-size: 80px; + line-height: 100px; + +} +button.medium { + .column(5, 8); + .push(2); + height: 60px; + .border-radius(6px); + margin-top: 20px; + + font-size: 40px; + line-height: 60px; + + i { font-size: 50px; top: -6px; } +} +button.green:hover { background-color: @green; .fasttrans; } +button.small { + .column(2); + .push(2); + margin-top: 100px; + height: 50px; + .border-radius(6px); + font-size: 40px; + line-height: 50px; +} + + button:focus { outline: none; } + + diff --git a/assets/css/fonts.import.less b/assets/css/fonts.import.less new file mode 100644 index 0000000..c82299b --- /dev/null +++ b/assets/css/fonts.import.less @@ -0,0 +1,76 @@ +//CHANGE IMPORT AND open/sans/bold + +@import url(https://fonts.googleapis.com/css?family=Montserrat|Rokkitt:700|Rubik+Mono+One); + +.open { font-family: Verdana, sans-serif; } +.sans { font-family: Monserrat, sans-serif; } +.bold { font-family: Rokkitt, sans-serif; } + +* { + font-size: 16px; + line-height: 24px; +} + +a { + font-weight: bold; +} + .nav a { .open; } + +.brand { + .open; + display: block; + color: @grey; + margin: 0 auto; + text-align: center; + line-height: 48px; +} +.light { + color: white; + text-shadow: 1px 1px 2px @darkgrey, -1px -1px 1px @darkestgrey; +} + +h1, h2, h3, h4, h5, h6 { .open; } + +h1 { + font-size: 5em; + position: relative; + color: @red; + word-wrap: break-word; + font-weight: normal; + line-height: 2em; + text-shadow: -1px -1px 0 black; +} +h2 { + font-size: 3em; + line-height: 1.2em; + color: @key; +} +h3 { + font-size: 1.2em; + padding-left: 10px; padding-right: 10px; +} +h4 { + font-size: 2.2em; + line-height: 1em; + color: @keylight; + text-align: center; +} + h5, h6 { color: @darkergrey; } +h5 { + font-size: 1em; +} +h6 { + font-size: 1.1em; +} +em { + color: @keydark; + font-style: italic; + font-weight: normal; + padding: 2px; + .border-radius(2px); +} + + + +.fix { color: @red; } + diff --git a/assets/css/forms.import.less b/assets/css/forms.import.less new file mode 100644 index 0000000..7f8ba68 --- /dev/null +++ b/assets/css/forms.import.less @@ -0,0 +1,34 @@ +label, .label, input, select, textarea { + font-size: 20px; + line-height: 20px; + display: inline-block; + .border-radius(3px); + vertical-align: top; + padding: 5px 10px; + border: 0 none; + float: left; + width: auto; +} + +input, select, textarea { + +} + +input { + border: 1px solid @lightgrey; +} + input[type=submit] { + .bold; + padding: 7px 20px; + margin-left: 10px; + background: @keylight; + color: white; + .fasttrans; + } + input[type=submit]:hover, input[type=submit]:active { + background: saturate(@contrast, 20%); + .fasttrans; + } + + + diff --git a/assets/css/grid.import.less b/assets/css/grid.import.less new file mode 100644 index 0000000..7119e24 --- /dev/null +++ b/assets/css/grid.import.less @@ -0,0 +1,65 @@ +///////////////// +// Semantic.gs // for LESS: http://lesscss.org/ +///////////////// + +// Defaults which you can freely override +@column-width: 60; +@gutter-width: 0; +@columns: 12; + +// Utility variable — you should never need to modify this +@gridsystem-width: (@column-width*@columns) + (@gutter-width*@columns) * 1px; + +// Set @total-width to 100% for a fluid layout +@total-width: 100%; + +// Uncomment these two lines and the star-hack width/margin lines below to enable sub-pixel fix for IE6 & 7. See http://tylertate.com/blog/2012/01/05/subpixel-rounding.html +// @min-width: 960; +// @correction: 0.5 / @min-width * 100 * 1%; + +// The micro clearfix http://nicolasgallagher.com/micro-clearfix-hack/ +.clearfix() { + *zoom:1; + + &:before, + &:after { + content:""; + display:table; + } + &:after { + clear:both; + } +} + + +////////// +// GRID // +////////// + +body { + width: 100%; + .clearfix; +} + +.row(@columns:@columns) { + display: block; + width: @total-width*((@gutter-width + @gridsystem-width)/@gridsystem-width); + margin: 0 @total-width*(((@gutter-width*.5)/@gridsystem-width)*-1); + // *width: @total-width*((@gutter-width + @gridsystem-width)/@gridsystem-width)-@correction; + // *margin: 0 @total-width*(((@gutter-width*.5)/@gridsystem-width)*-1)-@correction; + .clearfix; +} +.column(@x,@columns:@columns) { + display: inline; + float: left; + width: @total-width*((((@gutter-width+@column-width)*@x)-@gutter-width) / @gridsystem-width); + margin: 0 @total-width*((@gutter-width*.5)/@gridsystem-width); + // *width: @total-width*((((@gutter-width+@column-width)*@x)-@gutter-width) / @gridsystem-width)-@correction; + // *margin: 0 @total-width*((@gutter-width*.5)/@gridsystem-width)-@correction; +} +.push(@offset:1) { + margin-left: @total-width*(((@gutter-width+@column-width)*@offset) / @gridsystem-width) + @total-width*((@gutter-width*.5)/@gridsystem-width); +} +.pull(@offset:1) { + margin-right: @total-width*(((@gutter-width+@column-width)*@offset) / @gridsystem-width) + @total-width*((@gutter-width*.5)/@gridsystem-width); +} diff --git a/assets/css/master.less b/assets/css/master.less new file mode 100644 index 0000000..308fa45 --- /dev/null +++ b/assets/css/master.less @@ -0,0 +1,87 @@ +@import 'grid.import.less'; +@import 'var.import.less'; +@import 'fonts.import.less'; +@import 'rules.import.less'; +@import 'anim.import.less'; + +@import 'base.import.less'; +@import 'nav.import.less'; + +@import 'forms.import.less'; +@import 'tables.import.less'; +@import 'button.import.less'; + +@import 'media.import.less'; + +@import 'alert.import.less'; + +//ADD CUSTOM AND OVERRIDE CODE HERE + + + + +//HOME + +#mainlogo { + background: url('/img/logo/Cycore_web_optimized.jpg') + center center no-repeat; + background-size: contain; + height: 500px; +} +#mainstatement { + color: @keydark; + text-align: center; +} +#maincontact { + h4 { text-align: center; } + form { padding: 20px; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + } + input { margin: 2px; flex: 1 0 auto; } +} +#mainservice { + padding: 0 10px; + ul { .twelve; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-around; + align-content: stretch; + + li { + display: block; + height: 5em; + width: auto; + margin: 10px; + flex: 1 0 auto; + font-size: 1.5em; + font-weight: bold; + color: @darkergrey; + text-align: center; + padding: 1em; + padding-top: 2em; + .stripes; + } + .one {background-color: @contrast; } + .two {background-color: lighten(#2196f3, 10%);} + .three {background-color: fadeout(#4caf50, 10%);} + } + +} + + + + + + + + + + + + + + diff --git a/assets/css/media.import.less b/assets/css/media.import.less new file mode 100644 index 0000000..3207925 --- /dev/null +++ b/assets/css/media.import.less @@ -0,0 +1,14 @@ +//COLUMN RESPONSE + + +//add here + +//ADD BREAKPOINTS IF NECESSARY + +@media all and (max-width: 1180px) { + +} + + + + diff --git a/assets/css/nav.import.less b/assets/css/nav.import.less new file mode 100644 index 0000000..61ead1f --- /dev/null +++ b/assets/css/nav.import.less @@ -0,0 +1,39 @@ + + +//NAV MENUS AND LINKS + +.nav { + position: fixed; + height: 50px; + margin: 0 0; + padding: 0; + z-index: 1000; + background: black ; + background-size: contain; + + display: flex; + justify-content: space-between; + align-items: center; + + .logo { padding: 7px 0 0 0; + width: auto; + } + + a { + display: block; + flex: 0 0 auto; + padding-top: 18px; + + .two; + .slowtrans; + z-index: 1000; + + color: @keylight; + + } + a:hover { + .fasttrans; + } + + +} diff --git a/assets/css/rules.import.less b/assets/css/rules.import.less new file mode 100644 index 0000000..2d57178 --- /dev/null +++ b/assets/css/rules.import.less @@ -0,0 +1,142 @@ +.placeholder (@color) { + input::-webkit-input-placeholder { color: @color; padding: 7px 10px 3px 10px;} + input:-moz-placeholder { color: @color;padding: 7px 10px 3px 10px; } + input::-moz-placeholder { color: @color;padding: 7px 10px 3px 10px; } + input:-ms-input-placeholder { color: @color;padding: 7px 10px 3px 10px; } +} +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; + background-clip: padding-box; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; +} +.background-linear-gradient (@color1, @color2) { + background: linear-gradient(top, @color1, @color2); + background: -moz-linear-gradient(@color1, @color2); //FF3.6- + background: -webkit-linear-gradient(top, @color1, @color2); //S5.1, Chrome 10- + background: -o-linear-gradient(top, @color1, @color2); //O 11.1 + background: -ms-linear-gradient(@color1, @color2); //IE10 + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='@color1', endColorstr='@color2'); //IE6-7 + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='@color1', endColorstr='@color2')"; //IE8-9 +} + .background-linear-gradient (@color1, @color2, @color3) { + background: linear-gradient(top, @color1, @color2, @color3); + background: -moz-linear-gradient(@color1, @color2, @color3); //FF3.6- + background: -webkit-linear-gradient(top, @color1, @color2, @color3); //S5.1, Chrome 10- + background: -o-linear-gradient(top, @color1, @color2, @color3); //O 11.1 + background: -ms-linear-gradient(@color1, @color2, @color3); //IE10 + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='@color1', endColorstr='@color3'); //IE6-7 + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='@color1', endColorstr='@color3')"; //IE8-9 + } + .background-gradient (@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7) { + background-image: linear-gradient(@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7); + background-image: -moz-linear-gradient(@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7); + background-image: -webkit-linear-gradient(@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7); + background-image: -o-linear-gradient(@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7); + background-image: -ms-linear-gradient(@degrees, @color1, @color2, @color3, @color4, @color5, @color6, @color7); + } +.box-shadow (none) { + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + .box-shadow (@shadow) { + box-shadow: @shadow; + -moz-box-shadow: @shadow; + -webkit-box-shadow: @shadow; + } + .box-shadow (@shadow1, @shadow2) { + box-shadow: @shadow1, @shadow2; + -moz-box-shadow: @shadow1, @shadow2; + -webkit-box-shadow: @shadow1, @shadow2; + } + .box-shadow (@shadow1, @shadow2, @shadow3) { + box-shadow: @shadow1, @shadow2, @shadow3; + -moz-box-shadow: @shadow1, @shadow2, @shadow3; + -webkit-box-shadow: @shadow1, @shadow2, @shadow3; + } + +.transition (@property, @duration, @function, @delay) { + -webkit-transition: @property @duration @function @delay; + -moz-transition: @property @duration @function @delay; + -o-transition: @property @duration @function @delay; + -ms-transition: @property @duration @function @delay; + transition: @property @duration @function @delay; +} + .transition (@property1, @duration1, @function1, @delay1, @property2, @duration2, @function2, @delay2) { + -webkit-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2; + -moz-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2; + -o-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2; + -ms-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2; + transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2; + } + .transition (@property1, @duration1, @function1, @delay1, @property2, @duration2, @function2, @delay2, @property3, @duration3, @function3, @delay3) { + -webkit-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3; + -moz-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3; + -o-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3; + -ms-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3; + transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3; + } + .transition (@property1, @duration1, @function1, @delay1, @property2, @duration2, @function2, @delay2, @property3, @duration3, @function3, @delay3, @property4, @duration4, @function4, @delay4) { + -webkit-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3, @property4 @duration4 @function4 @delay4; + -moz-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3, @property4 @duration4 @function4 @delay4; + -o-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3, @property4 @duration4 @function4 @delay4; + -ms-transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3, @property4 @duration4 @function4 @delay4; + transition: @property1 @duration1 @function1 @delay1, @property2 @duration2 @function2 @delay2, @property3 @duration3 @function3 @delay3, @property4 @duration4 @function4 @delay4; + } + + .transition (inherit) { + -webkit-transition: inherit; + -moz-transition: inherit; + -o-transition: inherit; + -ms-transition: inherit; + transition: inherit; + } + .fasttrans { .transition(all, 0.4s, ease, 0s); } + .slowtrans { .transition(all, 2s, ease, 0s); } + + +.rotate (@deg) { + -webkit-transform: rotate(@deg); + -moz-transform: rotate(@deg); + -o-transform: rotate(@deg); + -ms-transform: rotate(@deg); + transform: rotate(@deg); +} + +.scale(@amount) { + -webkit-transform: scale(@amount); + -moz-transform: scale(@amount); + -ms-transform: scale(@amount); + transform: scale(@amount); +} +.flipX { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); +} + +//TEXTURES + +.polka { + background: + radial-gradient(@lighttransblack 15%, transparent 16%) 0 0, + radial-gradient(@lighttransblack 15%, transparent 16%) 8px 8px, + radial-gradient(rgba(255,255,255,.01) 15%, transparent 20%) 0 1px, + radial-gradient(rgba(255,255,255,.01) 15%, transparent 20%) 8px 9px; + background-size: 8px 8px; +} +.stripes { + background: repeating-linear-gradient( + 45deg, + transparent, + transparent 10px, + @transwhite 10px, + @transwhite 20px + ); +} + diff --git a/assets/css/tables.import.less b/assets/css/tables.import.less new file mode 100644 index 0000000..f46f8e8 --- /dev/null +++ b/assets/css/tables.import.less @@ -0,0 +1,49 @@ +//TABLE + +table { + .unit; + border-collapse: collapse; + background-clip: padding-box; +} + td, th { + margin: 0; + text-align: center; + vertical-align: middle; + padding: 7px 5px; + } + +@color1: fadeout(#fff, 40%); +@color2: fadeout(lighten(desaturate(@highlightblue, 20%), 40%), 45%); + + tr:nth-child(2n+1) td { + background: @color1; + } + tr:nth-child(2n) td { + background: @color2; + } + + th { + background: @lightergrey; + color: @darkgrey; + } + tr:hover td:nth-child(1n) { + background-color: @highlightyellow; + } + td.header { + background: transparent !important; + color: @darkergrey; + text-shadow: 1px 1px 1px #fff; + font-weight: bold; + text-align: right; + padding-right: 15px; + } + + table i { + color: @darkergrey; + } + table i:hover { + color: fadeout(@lightlightblue, 30%); + } + +.large { width: 80%; margin-left: 10%; } + diff --git a/assets/css/var.import.less b/assets/css/var.import.less new file mode 100644 index 0000000..628b6ac --- /dev/null +++ b/assets/css/var.import.less @@ -0,0 +1,54 @@ +//COLOR VARIABLES + +@background: white; +@border: @transblack; + +//BRAND COLORS + +@key: #2d65af; //CHANGE ME!! NOT >> +@keylight: #38b4e7; +@keylightest: lighten(@key, 25%); +@keydark: darken(@key, 15%); +@keydarker: darken(@key, 29%); +@keydarkest: darken(@key, 36%); + +@contrast: #ff9900; +@contrastdark: darken(@contrast, 28%); +@contrastlight: lighten(@contrast, 15%); +@contrastlightest: lighten(@contrast, 23%); + +//FUNCTION COLORS + +@lightlightblue: lighten(@highlightblue, 14%); +@highlightblue: #0069ff; +@darkhighlightblue: darken(@highlightblue, 10%); + +@orange: #FF8300; +@highlightyellow: #fcf4b5; +@gold: #FFEF02; + +@red: #aa0000; +@purple: #1100ff; +@green: #008d00; +@darkgreen: darken(desaturate(@green, 10%), 10%); + +//MONO + +@lightestgrey: #eee; +@lightergrey: #ddd; +@lightgrey: #ccc; +@grey: #aaa; +@darkgrey: #888; +@darkergrey: #555; +@darkestgrey: #222; + +@lighttransblack: rgba(0,0,0,0.02); +@transblack: rgba(0, 0, 0, 0.2); +@lightblack: rgba(0, 0, 0, 0.5); +@midblack: rgba(0, 0, 0, 0.8); +@transwhite: rgba(255, 255, 255, 0.05); +@lightwhite: rgba(255, 255, 255, 0.1); +@midwhite: rgba(255, 255, 255, 0.6); + + + diff --git a/assets/img/favicon.png b/assets/img/favicon.png new file mode 100644 index 0000000..0303cba Binary files /dev/null and b/assets/img/favicon.png differ diff --git a/assets/img/logo/Cycore_web_optimized.jpg b/assets/img/logo/Cycore_web_optimized.jpg new file mode 100644 index 0000000..ecc431e Binary files /dev/null and b/assets/img/logo/Cycore_web_optimized.jpg differ diff --git a/assets/js/home.js b/assets/js/home.js new file mode 100644 index 0000000..ab06975 --- /dev/null +++ b/assets/js/home.js @@ -0,0 +1,52 @@ +function getCookie(name) { + if (!document.cookie) { + return null; + } + + const xsrfCookies = document.cookie.split(';') + .map(c => c.trim()) + .filter(c => c.startsWith(name + '=')); + + if (xsrfCookies.length === 0) { + return null; + } + + return decodeURIComponent(xsrfCookies[0].split('=')[1]); +} + +function contactRequest() { + var name = document.querySelector('input[name=name]').value + var email = document.querySelector('input[name=email]').value + var success = document.querySelector('div.alert-success') + var failure = document.querySelector('div.alert-error') + + // Reset response holders + success.innerHTML = '' + failure.innerHTML = '' + + fetch("contact/request", { + body: JSON.stringify({ + name: name, + email: email + }), + headers: new Headers({ + 'Content-Type': 'application/json', + 'X-XSRF-TOKEN': getCookie('_csrf') + }), + method: 'POST' + }) + .then(function(resp) { + + if(resp.ok) { + success.innerHTML = 'Request Sent' + return + } + return resp.json() + }) + .then(function(o) { + failure.innerHTML = o.message + }) + .catch( function(err) { + failure.innerHTML = 'network error' + }) +} diff --git a/conf/app.conf b/conf/app.conf deleted file mode 100644 index 089c9df..0000000 --- a/conf/app.conf +++ /dev/null @@ -1,211 +0,0 @@ -################################################################################ -# Revel configuration file -# See: -# http://revel.github.io/manual/appconf.html -# for more detailed documentation. -################################################################################ - -# This sets the `AppName` variable which can be used in your code as -# `if revel.AppName {...}` -app.name = cycore-web - -# A secret string which is passed to cryptographically sign the cookie to prevent -# (and detect) user modification. -# Keep this string secret or users will be able to inject arbitrary cookie values -# into your application -app.secret = pggqixEuKBuN8nuwrUAkTyrjCnx5YtRNh4Y7TIHvmRKh0SXrqcqPxDny6UtMyxLL - -# Revel running behind proxy like nginx, haproxy, etc -app.behind.proxy = false - - -# The IP address on which to listen. -http.addr = 0.0.0.0 - -# The port on which to listen. -http.port = 9000 - -# Whether to use SSL or not. -http.ssl = false - -# Path to an X509 certificate file, if using SSL. -#http.sslcert = - -# Path to an X509 certificate key, if using SSL. -#http.sslkey = - - -# For any cookies set by Revel (Session,Flash,Error) these properties will set -# the fields of: -# http://golang.org/pkg/net/http/#Cookie -# -# Each cookie set by Revel is prefixed with this string. -cookie.prefix = CYCORE - -# A secure cookie has the secure attribute enabled and is only used via HTTPS, -# ensuring that the cookie is always encrypted when transmitting from client to -# server. This makes the cookie less likely to be exposed to cookie theft via -# eavesdropping. -# -# In dev mode, this will default to false, otherwise it will -# default to true. -# cookie.secure = false - -# Limit cookie access to a given domain -#cookie.domain = - -# Define when your session cookie expires. Possible values: -# "720h" -# A time duration (http://golang.org/pkg/time/#ParseDuration) after which -# the cookie expires and the session is invalid. -# "session" -# Sets a session cookie which invalidates the session when the user close -# the browser. -session.expires = 720h - - -# The date format used by Revel. Possible formats defined by the Go `time` -# package (http://golang.org/pkg/time/#Parse) -format.date = 2006-01-02 -format.datetime = 2006-01-02 15:04 - -# Timeout specifies a time limit for request (in seconds) made by a single client. -# A Timeout of zero means no timeout. -timeout.read = 90 -timeout.write = 60 - - -# Determines whether the template rendering should use chunked encoding. -# Chunked encoding can decrease the time to first byte on the client side by -# sending data before the entire template has been fully rendered. -results.chunked = false - - -# Prefixes for each log message line -# User can override these prefix values within any section -# For e.g: [dev], [prod], etc -log.trace.prefix = "TRACE " -log.info.prefix = "INFO " -log.warn.prefix = "WARN " -log.error.prefix = "ERROR " - - -# The default language of this application. -i18n.default_language = en - -# The default format when message is missing. -# The original message shows in %s -#i18n.unknown_format = "??? %s ???" - - -# Module to serve static content such as CSS, JavaScript and Media files -# Allows Routes like this: -# `Static.ServeModule("modulename","public")` -module.static=github.com/revel/modules/static - - - -################################################################################ -# Section: dev -# This section is evaluated when running Revel in dev mode. Like so: -# `revel run path/to/myapp` -[dev] -# This sets `DevMode` variable to `true` which can be used in your code as -# `if revel.DevMode {...}` -# or in your templates with -# `` -mode.dev = true - - -# Pretty print JSON/XML when calling RenderJson/RenderXml -results.pretty = true - - -# Automatically watches your applicaton files and recompiles on-demand -watch = true - - -# If you set watch.mode = "eager", the server starts to recompile -# your application every time your application's files change. -watch.mode = "normal" - -# Watch the entire $GOPATH for code changes. Default is false. -#watch.gopath = true - - -# Module to run code tests in the browser -# See: -# http://revel.github.io/manual/testing.html -module.testrunner = github.com/revel/modules/testrunner - - -# Where to log the various Revel logs -log.trace.output = off -log.info.output = stderr -log.warn.output = stderr -log.error.output = stderr - - -# Revel log flags. Possible flags defined by the Go `log` package, -# please refer https://golang.org/pkg/log/#pkg-constants -# Go log is "Bits or'ed together to control what's printed" -# Examples: -# 0 => just log the message, turn off the flags -# 3 => log.LstdFlags (log.Ldate|log.Ltime) -# 19 => log.Ldate|log.Ltime|log.Lshortfile -# 23 => log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile -log.trace.flags = 19 -log.info.flags = 19 -log.warn.flags = 19 -log.error.flags = 19 - - -# Revel request access log -# Access log line format: -# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath -# Sample format: -# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET / -log.request.output = stderr - - -################################################################################ -# Section: prod -# This section is evaluated when running Revel in production mode. Like so: -# `revel run path/to/myapp prod` -# See: -# [dev] section for documentation of the various settings -[prod] -mode.dev = false -results.pretty = false -watch = false -module.testrunner = - -log.trace.output = off -log.info.output = off -log.warn.output = stderr -log.error.output = stderr - -# Revel log flags. Possible flags defined by the Go `log` package, -# please refer https://golang.org/pkg/log/#pkg-constants -# Go log is "Bits or'ed together to control what's printed" -# Examples: -# 0 => just log the message, turn off the flags -# 3 => log.LstdFlags (log.Ldate|log.Ltime) -# 19 => log.Ldate|log.Ltime|log.Lshortfile -# 23 => log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile -log.trace.flags = 3 -log.info.flags = 3 -log.warn.flags = 3 -log.error.flags = 3 - - -# Revel request access log -# Access log line format: -# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath -# Sample format: -# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET / -# Example: -# log.request.output = %(app.name)s-request.log -log.request.output = off -app.behind.proxy = true -app.secret = ${COOKIE_SECRET} diff --git a/conf/routes b/conf/routes deleted file mode 100644 index 0b8977f..0000000 --- a/conf/routes +++ /dev/null @@ -1,22 +0,0 @@ -# Routes -# This file defines all application routes (Higher priority routes first) -# ~~~~ - -module:testrunner - -GET / App.Index - -# Handle contact requests -POST /contact/request Contact.ContactRequest - -# Ignore favicon requests -GET /favicon.ico 404 - -# Map static resources from the /app/public folder to the /public path -GET /public/*filepath Static.Serve("public") - -# GPG Public key -GET /scm.asc Static.Serve("public", "scm.asc") - -# Catch all -* /:controller/:action :controller.:action diff --git a/contact.go b/contact.go new file mode 100644 index 0000000..21d1f2b --- /dev/null +++ b/contact.go @@ -0,0 +1,124 @@ +package main + +import ( + "bytes" + "encoding/json" + "errors" + "html/template" + "net/http" + "os" + "time" + + "github.com/CyCoreSystems/sendinblue" + "github.com/labstack/echo" +) + +var contactEmailT *template.Template + +func init() { + contactEmailT = template.Must(template.New("contactEmail").Parse(contactEmailTemplate)) +} + +// ContactRequest describes the parameters of a contact request +type ContactRequest struct { + Name string `json:"name" form:"name" query:"name"` + Email string `json:"email" form:"email" query:"email"` +} + +// contactRequest handles a customer contact request +func contactRequest(c echo.Context) (err error) { + + cc := c.(*Context) + + req := new(ContactRequest) + if err = cc.Bind(req); err != nil { + cc.Log.Warnf("failed to parse input: %s", err.Error()) + return c.JSON(http.StatusBadRequest, NewError(errors.New("failed to read request"))) + } + + cc.Log.Debugf(`received contact request from "%s" <%s> (%s)`, req.Name, req.Email, c.RealIP()) + + if req.Name == "" { + cc.Log.Warn("empty name") + return c.JSON(http.StatusBadRequest, NewError(errors.New("please supply a name"))) + } + if req.Email == "" { + cc.Log.Warn("empty email") + return c.JSON(http.StatusBadRequest, NewError(errors.New("please supply an email"))) + } + + emailBody, err := renderContactEmail(req.Name, req.Email) + if err != nil { + cc.Log.Errorf("failed to render email body: %s", err.Error()) + return c.JSON(http.StatusInternalServerError, NewError(errors.New("internal error; please retry"))) + } + + msg := &sendinblue.Message{ + Sender: &sendinblue.Address{ + Name: "CyCore Systems, Inc", + Email: "sys@cycoresys.com", + }, + To: getEmailContacts(), + Subject: "Contact Request", + HTMLContent: emailBody, + Tags: []string{"contact-request"}, + } + + if err = msg.Send(os.Getenv("SENDINBLUE_APIKEY")); err != nil { + cc.Log.Errorf("failed to send contact email: %s", err.Error()) + + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + enc.Encode(msg) + + return c.JSON(http.StatusBadGateway, NewError(errors.New("internal error; please retry"))) + } + + cc.Log.Debug("contact request sent") + return nil +} + +func renderContactEmail(name, email string) (string, error) { + buf := new(bytes.Buffer) + err := contactEmailT.Execute(buf, struct { + Name string + Email string + Timestamp string + }{ + Name: name, + Email: email, + Timestamp: time.Now().String(), + }) + if err != nil { + return "", err + } + return buf.String(), nil +} + +func getEmailContacts() []*sendinblue.Address { + + var ret []*sendinblue.Address + if err := json.Unmarshal([]byte(os.Getenv("CONTACT_RECIPIENTS")), &ret); err != nil { + + // Fall back to default if we fail to load from environment + ret = append(ret, &sendinblue.Address{ + Name: "System Receiver", + Email: "sys@cycoresys.com", + }) + + } + return ret +} + +var contactEmailTemplate = ` + + +

Web Contact Form

+ + + +` diff --git a/context.go b/context.go new file mode 100644 index 0000000..15b6594 --- /dev/null +++ b/context.go @@ -0,0 +1,18 @@ +package main + +import ( + "github.com/jmoiron/sqlx" + "github.com/labstack/echo" + "go.uber.org/zap" +) + +// Context is the custom context for this web server +type Context struct { + echo.Context + + // DB is the database connection + DB *sqlx.DB + + // Log is the core logger + Log *zap.SugaredLogger +} diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..09af4b2 --- /dev/null +++ b/db/db.go @@ -0,0 +1,45 @@ +package db + +import ( + "fmt" + "os" + "os/user" + + "github.com/jmoiron/sqlx" + + _ "github.com/lib/pq" // load Postgresql driver here, since we have no access to main +) + +var db *sqlx.DB + +// Connect attempts to establish a database connection +func Connect() error { + + if db != nil { + return nil + } + + var username = "nobody" + + u, err := user.Current() + if err == nil { + username = u.Username + } + + dsn := fmt.Sprintf("postgresql://%s@localhost:26257/cycore?sslmode=disable", username) + if os.Getenv("DSN") != "" { + dsn = os.Getenv("DSN") + } + + db, err = sqlx.Open("postgres", dsn) + + return err +} + +// Get returns a database connection handle for the database +func Get() *sqlx.DB { + if err := Connect(); err != nil { + panic("no database connection: " + err.Error()) + } + return db +} diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..5c09d6e --- /dev/null +++ b/dev.sh @@ -0,0 +1,4 @@ +#!/bin/bash +go generate +go build +./cycore-web -debug diff --git a/main.go b/main.go new file mode 100644 index 0000000..d457d94 --- /dev/null +++ b/main.go @@ -0,0 +1,100 @@ +package main + +//go:generate esc -o static.go -prefix assets -ignore \.map$ assets + +import ( + "flag" + "html/template" + "net/http" + + "github.com/CyCoreSystems/cycore-web/db" + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" + "go.uber.org/zap" +) + +var addr string +var debug bool + +// Error indicates an error from processing +type Error struct { + Message string `json:"message"` +} + +// NewError converts a standard error to an error response +func NewError(err error) *Error { + return &Error{ + Message: err.Error(), + } +} + +func init() { + flag.StringVar(&addr, "addr", ":9000", "listen address") + flag.BoolVar(&debug, "debug", false, "run with debug logging") +} + +func main() { + + flag.Parse() + + var err error + + var logger *zap.Logger + if debug { + logger, err = zap.NewDevelopment() + } else { + logger, err = zap.NewProduction() + } + if err != nil { + panic("failed to create logger: " + err.Error()) + } + defer logger.Sync() // nolint + + log := logger.Sugar() + + err = db.Connect() + if err != nil { + log.Panicf("failed to open database: %v", err) + } + defer db.Get().Close() // nolint + + e := echo.New() + //e.Use(middleware.CSRF()) + e.Use(middleware.Gzip()) + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + //e.Use(middleware.Secure()) + + // Create custom context + e.Use(func(h echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + cc := &Context{ + Context: c, + DB: db.Get(), + Log: log, + } + return h(cc) + } + }) + + e.Renderer = &Template{ + templates: template.Must(template.ParseGlob("views/*.html")), + } + + assets := http.FileServer(FS(debug)) + + e.GET("/css/*", echo.WrapHandler(assets)) + e.GET("/img/*", echo.WrapHandler(assets)) + e.GET("/js/*", echo.WrapHandler(assets)) + e.GET("/scm.asc", echo.WrapHandler(assets)) + + e.GET("/", home) + + e.POST("/contact/request", contactRequest) + + log.Fatal(e.Start(addr)) +} + +func home(c echo.Context) error { + return c.Render(http.StatusOK, "index.html", nil) +} diff --git a/static.go b/static.go new file mode 100644 index 0000000..dae271d --- /dev/null +++ b/static.go @@ -0,0 +1,1261 @@ +// Code generated by "esc -o static.go -prefix assets -ignore \.map$ assets"; DO NOT EDIT. + +package main + +import ( + "bytes" + "compress/gzip" + "encoding/base64" + "io/ioutil" + "net/http" + "os" + "path" + "sync" + "time" +) + +type _escLocalFS struct{} + +var _escLocal _escLocalFS + +type _escStaticFS struct{} + +var _escStatic _escStaticFS + +type _escDirectory struct { + fs http.FileSystem + name string +} + +type _escFile struct { + compressed string + size int64 + modtime int64 + local string + isDir bool + + once sync.Once + data []byte + name string +} + +func (_escLocalFS) Open(name string) (http.File, error) { + f, present := _escData[path.Clean(name)] + if !present { + return nil, os.ErrNotExist + } + return os.Open(f.local) +} + +func (_escStaticFS) prepare(name string) (*_escFile, error) { + f, present := _escData[path.Clean(name)] + if !present { + return nil, os.ErrNotExist + } + var err error + f.once.Do(func() { + f.name = path.Base(name) + if f.size == 0 { + return + } + var gr *gzip.Reader + b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(f.compressed)) + gr, err = gzip.NewReader(b64) + if err != nil { + return + } + f.data, err = ioutil.ReadAll(gr) + }) + if err != nil { + return nil, err + } + return f, nil +} + +func (fs _escStaticFS) Open(name string) (http.File, error) { + f, err := fs.prepare(name) + if err != nil { + return nil, err + } + return f.File() +} + +func (dir _escDirectory) Open(name string) (http.File, error) { + return dir.fs.Open(dir.name + name) +} + +func (f *_escFile) File() (http.File, error) { + type httpFile struct { + *bytes.Reader + *_escFile + } + return &httpFile{ + Reader: bytes.NewReader(f.data), + _escFile: f, + }, nil +} + +func (f *_escFile) Close() error { + return nil +} + +func (f *_escFile) Readdir(count int) ([]os.FileInfo, error) { + return nil, nil +} + +func (f *_escFile) Stat() (os.FileInfo, error) { + return f, nil +} + +func (f *_escFile) Name() string { + return f.name +} + +func (f *_escFile) Size() int64 { + return f.size +} + +func (f *_escFile) Mode() os.FileMode { + return 0 +} + +func (f *_escFile) ModTime() time.Time { + return time.Unix(f.modtime, 0) +} + +func (f *_escFile) IsDir() bool { + return f.isDir +} + +func (f *_escFile) Sys() interface{} { + return f +} + +// FS returns a http.Filesystem for the embedded assets. If useLocal is true, +// the filesystem's contents are instead used. +func FS(useLocal bool) http.FileSystem { + if useLocal { + return _escLocal + } + return _escStatic +} + +// Dir returns a http.Filesystem for the embedded assets on a given prefix dir. +// If useLocal is true, the filesystem's contents are instead used. +func Dir(useLocal bool, name string) http.FileSystem { + if useLocal { + return _escDirectory{fs: _escLocal, name: name} + } + return _escDirectory{fs: _escStatic, name: name} +} + +// FSByte returns the named file from the embedded assets. If useLocal is +// true, the filesystem's contents are instead used. +func FSByte(useLocal bool, name string) ([]byte, error) { + if useLocal { + f, err := _escLocal.Open(name) + if err != nil { + return nil, err + } + b, err := ioutil.ReadAll(f) + _ = f.Close() + return b, err + } + f, err := _escStatic.prepare(name) + if err != nil { + return nil, err + } + return f.data, nil +} + +// FSMustByte is the same as FSByte, but panics if name is not present. +func FSMustByte(useLocal bool, name string) []byte { + b, err := FSByte(useLocal, name) + if err != nil { + panic(err) + } + return b +} + +// FSString is the string version of FSByte. +func FSString(useLocal bool, name string) (string, error) { + b, err := FSByte(useLocal, name) + return string(b), err +} + +// FSMustString is the string version of FSMustByte. +func FSMustString(useLocal bool, name string) string { + return string(FSMustByte(useLocal, name)) +} + +var _escData = map[string]*_escFile{ + + "/css/alert.import.less": { + local: "assets/css/alert.import.less", + size: 114, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/9JLzEktKlGo5uIsz0wpybBSMDQwULXm4ixJrSjRTczJTM+zUkhOzStJLbLmquXigijX +TS0qyi8CaUrOz8kvslJwKEpNQZYvLk1OTi0uRlaRXpSamgdSAwgAAP//VrWC+HIAAAA= +`, + }, + + "/css/anim.import.less": { + local: "assets/css/anim.import.less", + size: 13, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/9LXd/Tz9HUM8fT3C+YCBAAA//+rDnNODQAAAA== +`, + }, + + "/css/base.import.less": { + local: "assets/css/base.import.less", + size: 2773, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/4xWa2vjOhP+LP2KgaWQgO046abbdb4U9i0vB86NXn6AYsuOqCoZWblt8H8/6GJbdrKH +s2xb9GikGc0884zxYvH3y/Pr89srxltZnCMo2CECQQ4R7HkEnEVAIuBkS3kETU1EBJpsOYULBvfvk6iK +iQzSTYfUpCiYqCyESi6JzoDTUm8w2spT3LCfdncrVUFVvJUns0Hyj0rJvSjinLN6vNt2N4OJcXDdRcBE +vKOs2ukMlml6t5nsj/dQ4CuDp2GxwQgGT3t+5QeAs0bHjT5zmoGQgg6ehoMFO8AFo8nDAwMCF8AIaXrS +cUFzqYhmUvgLzU4phY6PPuit5CYy1Cd1XZ9gmdYmaSjxWVKkYPtm9q0+zS1ckkZrRURjVrnkUmXw9EHP +G4xajBDJdvJAFVwgsITAjhvfmxbjZMcKChcoWFNzcu6CbAEwXiz+//Lb/+DHX7+///HnK8aJPlJ+MNZJ +Lvn+U8yWq/kGWpxoKkI0dahgIjT+7lD77AB+dHDDTgH44MCSjdytPSr3KkC/+hh2iobG9x4+ygB08eLF +4vXt5f3H2/vL8yvGX2pSUVuzIyv0rufRhFYhC9epK1DItOOOaWq4jJO9YBouCKHFYt/QAkqpXFc1PUlM +fUoujxnsWFFQMTAtCVqFM0GJiitTfyr07EtZlrBa30XwZEtYKXqeb4LuMWzJYFmfoJGcFYFZ6GBEqrUl +VbB5ipsdKeRxZq7pflJQ1ZbM0gj8/+RhPjevTXIpNBXavRmjfwvfpiiCkhRU7vWsZ2IE3x/vzHVTwps+ +mFtZcQ9b9Q+7ccdDeucisnyfhhWsJ4Wz5jVRVGjf9Df8BUb+1Vyq/+7DN+f1vX7DSkLDftIMlsk9/dzg +rq09rQZ9WFnqtRhb0TZ+PW2/Wppa2SGcVSIDZdscIyfhsZGqDL7545iZsxMvvQ5sucw/JtflVGiq+vsy +SIHstZyo+0iNpvVc+4KGNEs9xVaWZk8FUR+06ag90roWI9ZL222fTtlGutdijJJG5oxwYE66h2yvHpzS +dp19v3LrLqd+6bMfa1lnvTpPctdihNGvBBUb2dakcrPhOs/jqXWD3Y+W3ehqJqz8TAgIUp/MELFgV6mV +Hyouyc7fL8TC597adIk1NenBm+MLI2SUr5RSm+pgVMuGubmnKCeaHegGD3ntRvUgqKM8OwDuU0sJ88cM +Tvv6XNbnCJJc0cJ1nQEbPwpHpV360k4iFlJ9Eu42jED1on6fdvbBJ49Z+pg918NUpz0X7Nw14bm4/DfA +6C4PBF9PHrmOwm+Me6l3Mnjpm8Hh4QFTsu6eLjZZn33Gble2/6jphKM7m3BZMdH5GRmBPYf7X+blrh7Q +urwY5vv2cxeMzxtk+gXX95sa06PFRrn+CQAA//992Uoz1QoAAA== +`, + }, + + "/css/button.import.less": { + local: "assets/css/button.import.less", + size: 1371, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/5RUXY7aMBB+tk8xL5VYaRMCWnaR81L1AO1DtwcwxCTWOrZlO0taxN2rsRNIEN22QkJg +fzPz/UxCl8svP15fv339TumuC8FoOMHOuEo4BgVoo0UJ5/Eur0Rr4ETJju/famc6XWV7o4xj8PlN/Cwp +SaVZMJbByvbgjZJVvFSybsIVsTMhmHYGCo5rv1N8/1ZSku9Mn/mGV+a4oIRI7UWAAgpYF7aHje2n+EeY +QfBzGflICSlgbXt4sj1exNNY9lBSEkQfhjkMMmQTvwoYGuOfdDARQcmg+tjIIEpKKMm9MsfICK8lnJDS +3BtyMDpkXv4SDLYb2+PRbHxiHptY7oRGu8i7cEHuucq4krVmkIzDG2u8DNJoBk4oHuQ7MiEkep+tVnHA +mdIzJZP0WGPehYMTXS7JH2Ick7rN4F9CGDHoWsQU0bsDr4TpwuKaCrwUnx4wm4/CIfB/8WAJ8p5lgWHg +nJvI7niPHMY2JD9wH4YmhJzRysFGxV0tsOdRVqFhsC2K6HXLXS01tuJdMCUljUA1DFYDIB923/FKdn6x +tT2KtLyqpK7TM/OCQDrblFSrpBbZbUN64dSKSnYtksr3RnWtXmweYYvtc9v5ZrF+mPB5vkvnOdFJKhIb +jLmEOZ+nO3xSw7T2E+gmlqd9fMaf5yvh2gmhx2WEO4sYASVMYoBLsW+5UlOx6xulUxGjWSPZzUfq/yI0 +1Z7p+Eixg9l3Hk5guoBAdn1j0t8BAAD//1hWpHpbBQAA +`, + }, + + "/css/fonts.import.less": { + local: "assets/css/fonts.import.less", + size: 1184, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/3RTTW/bOBA9a37FHJONPmzHyS4oLDbBtmh7cFIERe+URYuEKJIg6Viuo/9eUB+NoyAG +fNDMmzdv5g2z7P+v9w9fPuO3zffHpx94//AJtWEqc1S5rNCyBLgTjdHW497KC+69cSTLdlp5l1ZaV5JR +I1y61U22de6/HW2EPP67CXlmLfUvT7quhffk78Xi5WlfiPpqo5W+elTsMgdIQzc8YSBMhmKCP5ktqaIx +BhWJY1bscuwgDZ9z7EarodE7dFA/R49i5lj4C08IUQ914hcjuLw1bQ6RFIolnImKe4KrdYh1APQVfRhz +oVnIRamizxgA/WQ9eVpYqko8QTTEICqFM5IeCRZSb+scoq2W2hK8qyw75hA11FZCEVwg3XudQ+RZ6xMq +RaUIbpnyzM7Frf8ZxKUyfIdmI+eBC88mCsdpqQ8El6bt/yvT4l1JbR0ax5iEWDIl+wRzvheFYXC+jJGv +YuTXMfJ1jPwmRn57PmwEfIknwOF3ttAb1uQQGe2EF1oRtExSL57Z2fCWlTlEB23L5GCpIVhYRuskBPLZ +upW2DZXvDOp7vBn0daIFFpKGZXfAV2E/Z+Ku+8I3XMt0YJvE1cGYDvj1rHTCGVqWQlWJZLtQvTBtjlPM +jpSLwSK+nnGsRo63Aubte2M/uIUOoj9eTCW9e3YwrwN+Mxce+DvoS2YTjSnWnJ1RUBAYJyecP0pGUHgq +xfZDe8YNkHBoOURpoW3JbGJpKfbuYmXay/5BAaQ70Z5pD6cQns7vAAAA//+JEQW+oAQAAA== +`, + }, + + "/css/forms.import.less": { + local: "assets/css/forms.import.less", + size: 539, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/3SQQWsbMRCFz5pfMZdCArvGSSkFiYL/R+lhdjXeHaxIQpp11i3+70WbOsW0OQn0Zt57 +3wQaOHS4+/NKzIt2WDnwqB0qr0qFCX+BOaaofZWfbPF5n1cHJkjkfmaZZn3/81JzoItFiZs8hDSeHJjd +kIrn0hfystSHz3l9dGDOXFRGCj0FmaJFTdmByeS9xMnil7zi05vv27rFPcYU2YE5hkRqMfBRHZhX8Tpb +pEWTgyvAxxzvamO6uT7lFWsK4vEQGs5U+NJ8zDb5XS+Zv9VleBH90dYaTfAOzN+qX/N6O4F5oTJJ7Fs1 +e+tvBhpPU0lL9BYPJ75sOU0YU0jF4uss2rjM7khVtVCsDswVjMF/S9g5nbl0+D+JRpUzbzXvQivpUkj5 +4TCmqIWqdvi8//TosE3epZorAMDvAAAA///C+nNAGwIAAA== +`, + }, + + "/css/grid.import.less": { + local: "assets/css/grid.import.less", + size: 2020, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/8xUQW7rNhBdi6cYfKAftvMlSgHyi0obLRIUAbqq2wNQ0kgiQpEGOYqtBgF6iJ6wJyko +2a5lp2nSZvG9MOzR45s38x7Fzz+Mc1hjJzTJMmoccA61sfDT3XqdQku0STlX6FzpXGRs4/HnDJ7iFmvR +K3KwbWXZwmB6KIWG2iKqAcwjWisrZHlpVN/pcCsralP4Gmcsb3oitIeSr0wgl0JynY3sv5JUkgZ4FFaK +QiH8+fsfYw/Xml5VoPERLWjECshAZypZD0CtdCxvrKzc4Ai7Q4fFTMTq0G0JV7CYiTl5tIJks5u0rJEg +J0NCTSjfMYnj78a1CahVLytQYjA9sVNcOqL28+jSdB1qAmrRIdDWgJIaHQhd+Ro4EjZsRfkA42HeCdtI +vQcVqMzW90U9bsP1RbiRO1RQy92o4/7uK3yG7yNYIx5cpEGhJUEYlabjhTINv46Tax4nPL7hri9GitCa +XldSN1FLnfJi804eDfvBO+ZrpbEWS5JGpxBHN3AK89uKY/+9H/eXFqGTpTVQKhTWi9xr0rI0SrhGKCWa +Fu0obYSGB+i4Bc6iw//FEp5YsPrNmC5NMhaw4HNaYG0sfvE/RU1oPQIAoDSaUFP66VM2FSrpNkoMKfm9 +ZSx4vjzi26SFoXZ8/MwYm1+WH3++vwV+eg8YK0w1eIKZ0cFRcuZpImu2i2O0/47WEwsOqqBQpnzIjjyn +8Vkt5uGEK7jI9pJfljIWTNlJIT4nPIt7dPMSwSpMPAnnsPpAWeFJgvbs/1/mGels/9G08EW++/IvJkjt +b1nGgloZQSkorOkfPTkTdzV7tyxX+W4ZzgBLf1PeZdJbhn/Vn4+R+B7D3iJ5zvfMok3v2kVu6tohpclo +ydQg9Aakr4fiYqiJ5+VRfEb/y45HkUq9LNLKpv1GVP4VAAD///fhwWjkBwAA +`, + }, + + "/css/master.less": { + local: "assets/css/master.less", + size: 1368, + modtime: 1526521251, + compressed: ` +H4sIAAAAAAAC/3xSTW+bQBA97/6KkaLKiVTwR5NKhUui2FJ6SC2lH9dogQFvvOyiZTBxLP57tYA/kpr6 +YDTvzZt5Mzu3Mi+MJRhlViZ+F/gKy3IU8gO3EXaISo2mcoi0lcJBUmiZf+COZCRKHBJqsRnUpcbmgx1J +RP/xE1VERg9WzjGRYpAVCi19ZMfju/kc7n///LV8hLsfc1j+WTw9fZ8v4H45X8DD4mnBGePcZT4sHxec +X+RCamUyAzvOIhGvM2sqnQRQWXU5Gss8Gzt2fL+NjcXnGqNnU5DM5Rsm/kuRja44YzFqQgv9RxvPYoGC +wtOKXinfMIDYaBJSh5ytUGYrCuBmMileQ950VkoShDlqcn5io4wN4HaN20TYdcgZ4St5QslMB327g7Kt +HLe61TXs4EwqNJy594IdFCJJpM4CmLnuwBlLZFkosQ0gVfgacsbc16utKAJw/w56qUqS6dZzvVDT0QNj +bSdPEublCdxwJnVREewgFzaTOoCZ6+dqBzCFCYiKTAgNHBaAdiNjdGMcPE5g2u6IVQp24FONaoPhOc+d +6URajEkaHYA19RF/P8y/05SFiNET7Xu1Gd1QR54sUrwKOWdMSWfxxEKkTLxuVYeXxbyNa5nQKugmdfF+ +E/1QnbmTbbSQ0dSfzNTfF2rBuq8eGdWZ3F+JOxG0mcVtC587FcaOS532RXvAI1MEMOtBvyQrCyxd0LSA +0QiwO7nnfVu3HStKaq+LMZ9qcy5POdeoLy9m029f0y+fYTr5dBX2kpVFPCdKRYKmosuL61ikN5OjqOG8 +4e9/fwMAAP//5kWwuVgFAAA= +`, + }, + + "/css/media.import.less": { + local: "assets/css/media.import.less", + size: 108, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/9LXd/b3CfX1UwhyDQ7w9wt25eLi0tdPTElRyEgtSgWxHV1cFJyCXB29A/w9/UKCFTzd +FPxcnV2Dgx2DIrm4HHJTUzITFRJzchQS81IUNHITK3TLM1NKMqwUDA0tDAoqNBWqubhquUAAEAAA///7 +23mFbAAAAA== +`, + }, + + "/css/nav.import.less": { + local: "assets/css/nav.import.less", + size: 448, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/1yQwW6zMBCEz7tPsS8AIYdff2UujdQeqrZcovZuYAEXx0Z4E0gi3r0yUlK1xxmP7W8G +cbMpdp/0/lx87GlXPNHbS/G6R0ydPtGVEAYfjBjvFDVm5jonhI5N24mif9kw5wgHPbbGKcooyxEGXdfG +tWoVl8S4mmdF2yyLutRV347+6GpFpdVVT7/MJJgLK6q8E21cjoBQmzBYfVbUWI6fwdcxiGnOSQyxE0Vh +0BUnJcvEHO+AtqZ1iRE+BEUVO+ExR4TU+tbTle6A/4c5Mq+gMJlaOkX6KD5HWBCBNF0RfgBK66s+RiPJ +2vaWvnVOxA+Ktg9xFQRIZVpP02D9JKN2Iaq/kyBA5a0fFT32fLZx2dVdEAi06vyJxxUE0kYHub+zIOKC +3wEAAP//KQHRh8ABAAA= +`, + }, + + "/css/rules.import.less": { + local: "assets/css/rules.import.less", + size: 8891, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/9yabWvbOhTHX1uf4jAYTcF2YidpN4cLgd0O9uJy4a4X+laJlUTUsYyk0GzF3334QbGS ++DHN0naGgGL9zzm/c+Sj2G7tKMBzsmKBTzj0pnMWMH4Nz8igYbSRnmc9kdkjlVb61dLFz5CKPciMJhBh +36fh0oPbaAvOINrCMB9MYuXPWrOftV5qnEBsFFgv8lPQiBaJ1buKkT1j3Cfc4tinGwG9aTZIqgj5safw +IFdMdvPqSNNqLc6Xpkk/w/PHJWeb0LfmAY08tVDWjG2rECpMaiBqgyRFKgQBDQnm1jIBJaFUl51j5hV3 +90q3s/PgwLAnWaRsNONjSN1Hmt+ho2Mf0OXo979+Hdo3Vn3gvFItk2gZ+PvYdkz4suJsTcAZNCCw80Xv +9/8Fx7GdhmKLc9ca+v1vd87gKOyCBpJwDyLOltT3/n74tsZLcs9xKBaMr+1/6JwzwRbS3pEIibn8kkAI +yf+6ysGuTCChf3javargTHBurNuSPhKWYvrw+6A+TEp4PlmfUbwj6tR6ajDUe/DkXiy8HTflyc2pOT1P +l764W7sStWjbl7RvJ5zKPj61n09dnqrGvlCDD7s2+EU7fVjT6Yc85Z2vtbxPlpwQUXPhqMFIDcZqcKMG +t/UbhEWT/I+3iXMFb7OfKIbyXeU1QCo2lVdhYW8Do2xH+W0c6c361hIr7LMn6IUsJPu36WrOg2Su8ga9 +Uba7NT9UxsjYQ5hmg/SRqwwjn58Us5UoNdISnEJdgZRUPRu5TXSatANog1U1875hM/5ulN7UGEa9y0I9 +QYZhtKA/tGhFvmcUI2TL5LeCSspC6E0jziLC5Q8Tpv6G4+SsCdPFJpznQ58E+EfZFqyiF+482LkrvBXO +cl8V1/oZ3LCzsIgXeOluqf2Glq6Loy2Mo62Mo5YmGSixq4ldTewqsVu2kK0W1NEwNIoyCI1BQ1AE1Xt2 +9WVwieDsFfMWF499qXgXvrw18VATDzXxUImHr98LOq5Gq8Eq1lftmrNgsndRS/GGKd8e2Vvubk080sQj +TTxS4tF72gr0xLS8tLRUVu9k0zhLQuwPWx/xR+TznnOIUfnuRsMV4VR23TJysw492WzBukYQ7QxqRTGC +joe9wEKmPuFZr2UPB4EJA3skTCBYEBMG4npySgARsKfKAO6he2QgmzOJJcneUTY+3S4YX3uQmWQWdQ+x +rdSsi2fRLK4UJE/8Yo4D0pviNduEsmW2+zbN+bYwEG3810hiZC8CGj2k71aqkB96lnM9Qfn7lJpZUTPJ +KucqzscI9fv3dw/3//939x0hO2LBI044tT9qIINjn+JAe/8Y0OUq64xZgOeP4Iw/mlkFIsxJKMG5+XgN +AxiYJxt/irbJp8QBX85wzx2PTfWxB871sRd3kCI4L/aRkHyOthO9KJagP4mnINMlFpLTiIiD4gEnEcGS +hsujt7jIABiNfbI0IRlqcc2D7+n/UqQnp+nZpxWVpPykO4i2yMhW9lcAAAD//3UuIqy7IgAA +`, + }, + + "/css/tables.import.less": { + local: "assets/css/tables.import.less", + size: 951, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/4xTUYvbPBB8ln7FfnwEEhrnkvSOFvklLfStj/0DsrW2xCmS2WwuOYL/e5FlJ7n2Wiow +GGlmNLs7enj48eXr929Ssq48wkWK1TE4LqWoIhmkoo7e6+6ACqa/UkhR6fq5pXgMpqi96xR02hgX2qKK +51L2EvJiswS2SVXsNbUuKFiXUgjGMxfauzYoqDEwUjlRxvWCxK7WfkLtnTEeE3e8ScGn7gxP3bmUopdy +V0cfaaOg0Qbjkef/N02zhMf1bFGOh9vboXetZQxzgwfNR9KM8511rR32K3/EJWzXs0XmL+HxKalcHTKp +wLaorfNmvg0fNgtgA5dfKgC4NUnB6O9WZv8nuX8W274nJkVu+F/puXxqCV/L35CDtoKd0fScEaJPIyNl +4wsSsLmzuwmLYbpvAjEKXBv6it7HU5rdIGRWFrVBggu8ZSpg0uHQacLA8J/bd5FYhxRGIe5tTdbFmKSD +1SaeFGy68/VL8x8QTQxcnDAZUVBFb268MVuUzobdKcWU0Zscr5Qvkd+Hy6bfNTMUl1Fjqy53xqfo5ebf +Be3jENHhkpXX1CJc4OQMWwWf17MS8sMpPDbJUdrppfwZAAD//xypds+3AwAA +`, + }, + + "/css/var.import.less": { + local: "assets/css/var.import.less", + size: 1102, + modtime: 1526518454, + compressed: ` +H4sIAAAAAAAC/3xTYW/aMBD9XP8KV2gSkxB2AmYhkapQBlulNpFYt+9O7AREllQmqOLfT3dxEtJVCGTB +e8/v3p1txtbxc7yjf1a7p9Xj8+YXIWEi02NuqnOpfPq+P9Q6IGFSGaWNT8PayPKUFDI9BoQw9rhbRd8p +esDWo774dOSqhZBZcHfH2PrnKvqxoS+b+3saxa/04QFFxSHf1z4dzbxkrr8FPaZPtU+bX+UY0Al1xZev +jUJJc/QprB3pDEhIOKDd5YAG8wE/WwBPwrQqayOBHmXZcsl5QHtwWLZFJ9T10LwFbE9d+F5oQw6Ew0av +TGeYiLHt72j9+hRH/XBRjUtSnPXV7v0h33f4hDpzLDdAfTrifLHMsoCE0MkHsm3uoxNvxlMZWebgsd16 +M86vzS+6KKp3mFuazRMRkDCvCoXSzZa7sNto+C8l57j17WzeCjBzHM4xUG60LjGhp1ACcSxokyl9kvXZ +yFqPG3kTrovI2Escxe2Q9KnODV5FreH2NqCxmFKqxSySpmkT44JBZR8BAM/zLNBZCCFaqCvlutgt+vav +xKcmT+SYT/Az5S4czSc0td8pCuwZfCoQIPh7UJb+j/e6Cvh4rYErBDylduFTLrpCN3WOLXdTtIAzIORf +AAAA//+Knv/oTgQAAA== +`, + }, + + "/img/favicon.png": { + local: "assets/img/favicon.png", + size: 5639, + modtime: 1475450079, + compressed: ` +H4sIAAAAAAAC/6xUeTjU698ehrFv2fexRcmMmRIGM9nJml2IMUa2MZihyVL2LYXIElLWImuyE5JdlpCs +Yy1rhMhS79U553d+5+2c3/vHe/2+1/X88dyf+/7cz3N/nusbY2yozUTPRw8AAJh0dTRMAACA7M9FCwIA +AJaU36IAACpxV3V1Y111dbCxD97Z1QMLACiwRZjP4ifNOJAxeJM8LhTYSjsq9k2ZualNHT9fSQdINyl/ +4zJX/sr4WfFFhHzMM36ayZXqIqOAEHnQMcWlD0AWHWURJpBjwIevLVW6plFni3R1Aj61s4ic3qA2n2vw +c5Q0bbfdO+xVnFX8qPTx2qSGir3ry4e85tEpxaVZA+IPkgq5kh8ZxA6/GNEDjhSvGMok9vafgrRy7r9d +mxOMpe3dSNz8bvhV7JX/namhGFGjFk9OwSDeA8YrfSPu1Xocr2iODlxrQFM7AlvvLlJRFlOmBmWeIg11 +SqoYiqDo7g2eXeMsoW0EKTeOO0Nr0PZAnq6kOXNP/npR58QXJffRPgNz0HjvGtgPFkiG7+66XZjVUWZ+ +HaaWJWZG+qtZcwzq/ctdgS29cvuyOl30beqD+MPhQEqS8JXdZ/eDiDMfte3tSzhmQDPUAUNehQwGR26+ +sAABnoqhPYm1tC4xhfe+10+9yOMO/mxxUDWO+ZT4tMvUlYwmt14OKkq3f+htsRw+3fvianofpVi806vC +/sVgmmBUVUnjU+r+YYT8+RyuL3qW7p6lz1QnSh9aX2E4gacrXYvvOoNreNCWLNzLXO/3hLeX63LH0Mrp +2yXO/tfZJsapGx5xTyRkTw+vE0E8N8dRjQjoMkhg0m7ExLE6t0X7k4aGmCGXjOPos8tKecaP4MntTVoX +lSXgXeERr3vRMFGj4VMe0zcV4xc6w+MquZtkcq7kK3WWeb3qrrBCmX6gOBZ2fLEuy3+dPa9cfjxjnVav +FdHKTE3vg0Nwnn0XJLW302jka8aFMDT+cnwpSCr6ytsPn/kO++O/Rz4s15PeFTMahF2w2WAH07C7+MoP +Iwvd3VHrzMo9oIaDtxvN7u7EY++du9N3cJ0Xyz07qtsOxssqZI5xJpRKDv6xKU96tvza6Ehigiq2FO8k +mNbwZOvBCZOJitz81W8hg2KnW1FdyL7hurnBou853595PrV/yj0yq+QWzqtUIB50Nkj6RCpIMgh6oh9L +tK4XPRG3e9CcCKFWbPjclC0xHlBmj2afjrVzGXXPlpM0NewJWOReSj5uPK5U5i/nqLMXSipcbNpap/va +z3gi2MRDpH/hZvAyQGabiucCiwQoC/S+w+xNeDGRy3oyO6nA5GJXx/iuWKGfbeZSSiwJ8ShWUifm8x2j +9s7585Q1jxoPrh2cLi8A7n1PYpdFIMi4c/oSXefnsxDeFpq79MSMwX67W6BZ5hzdYr+xiz2clh/KisrO +0AX21MLtRrWjOPsvcA4sSV28UdvUdidXvDlM9N4n1ZmjZk2/aUbcpo1G1I82pTULF5un7EEbrHuv+CYi +twwDl8/n3KHZq2+a/5irswhKNEWUzx4JrujNTxNrhkjB++YDkhpKwvJ8P0rl+ZTsRX9wDWF3UNYAb5IH +vzQ7AACg89KxJgAADOw/FwXgYSYPAEA142pmRbQy0Edg8DgI2gnviIWQcF6An58yCUHCeeGwRDSYhPPw +JCBIKqK/MRCeBMRPGCoK/o1CdFcRtTIwBqvjfbBgOQgMAhdF0oPBYGUfJ2eEiYbWH3IfJ2cVURci0QsB +hd64cQNy4zwE73MdClNUVITKwqFwuIyPk7MM4aYnEU2S8SSI/d7kX300sASMj6sX0RXvCf65RzvifYkq +oqJ/cH7/fjciujr/28mT8Me1MHgc9GcFCoPIQv/s/bP9TxRhgiXgPXx/tjf3dCUiYcrQf4J/VanjcV4+ +WALBFe+JlPtD8lfsV77Vv/sh5eF/CP4K/iow8nHFehLRv9X+daa/Yr/yrf/JwPrvBsrQX0L9/4aNJbn+ +h7B/Vv4e9k8UYexKwnpYabjisJ6/xXRBQRn6j4Vfhep4D7yPqRcag/2Zxq/QP9pY/ycb67/Z/NdCccL8 +GYmXr4/Hb+/cCQPFemBxWE8iAQqDwP53Kk4YBMHX0Q2L+esT+5exGvo69K9k6N/Z/7WTk3Be/zxNEtrr +78Mk4bwQBngnV+ebGmgiFgmXhcFlYLIysvJmMDkETBYBu6AM/YXzi1rdB4sm4n3M8HgP5G9Twf3cguEQ +GAT2u/avjP/ztr+jJhpaSHpl6J//LiT9CW4pCgBgzNbVUDVzoS5J14wz12PvDIhsnRZ09tonCxFDIhLI +5wYlpEOpDi6eA4ufs1IF6wRTt4rURpI9W6fDGgjN30cXbg/vv81Cb1+T+OiXvblaWVpUipSX+UKmPDg5 +qtHT03sRhTY4/9UeWKW5v/KucHPuddRmbyq0I3Lb8U1s3cRL94a2CIYMgTamJZ0dygxKfdFAf//6/h+H +e71L3UmS2tTtyg9C5wSIhNchH1vDaKYHslF2JVdf2q4M59tpaUUeHe4VB3xdT2/wXUspvpIb6T5V6+0m +obxNpUBY1t+df8PAv6PBvtzGzUHjMsrykbDGIHxoU+0R8zYblS2GUGi48fnePWGUp8LVYuofaZOTU0Zp +SwNZSh+X+zOucznQjNOF2Od5luIMSXyp0uuTNQPPJ6tcTV9AGhPEAhOeXB94tNmfIb+5Olq87PNEf4V1 +NMyMif8iMRt120/aspSIunUsK0/PHQy89YmPj2FlcYRbxhZoGSKMIS80DzIJz934PDM9FcOjeoY3MwIk +NHS1emf+zZ2hJEmjHGxviubsq9tGaR/fQKsrbu+8cH9f+mlv7b2WWiMhR9Ky2WtOjfh1/UO43Dazg+Zj +nUTRFKazFs8/IXxXFy96jDssWGmPObSYVnhfVeF7H+AjXfyNh/Bt5+MNCb2UC3pu8knbe2+VjZv8fT8+ +qEZ+kc0W8uQ+j+1N8S00yvbTvifgLec+VnWhmrhiYpNX8o6Pfxel2BS1sIumBVO1AeOKOW+Nwwv7rBpJ +3oRsFmHkOF9GUoroPSyrgDt+tnm6yX+vxyRzgKtaR+mJL2PBqrs+cTT0x8o7yUnXknxzcqg2qp1lm57r +nMvay9OTzI8BIWojNR4fhl96Tk8YZCoMJVs1ByquVWaxVIrqY0sGY9HZezxR01RWuTfHioyK65ywi7Fk +J54HKNTVhPR0V/3ASxlkZLRtzCmJqaP9z1kD3aWWZde2x6LUornCCWGB37682Ra3ffk8F2q9C/GP07vZ +AVfbGIzTHebXVlDd2ZxWYqilpKbnYeIYr8BErU3WlMHQBl2yeZIFbnKdkNvHB0ORvO9qt9osCPMhN8ha +lEpdaYtsxmHPrSraEmVoBegGlMegZk8TdiQxjaDTc/5Dpr315UY5LZohTjV024wiB61pW2rI4JdcwDY0 +7JKKGjgb4dtju/xt56MfnD3QKQHExFcLpGGuVQn4ysMWvcrGNJQ3ysPYGoaMEq9KwzAa69kvVF2e3f88 +eyP/8gNHRIcc9ylgxjYqk/rgaPCJ+nRTwP5Ud5LkXVpG1lDBlemGmgbvhcidqDu5HDqcaaekOCJhM7AE +VLJtvJCKI1pN2WlOsP7spjHgPSdP0A/2sP3ra+8gVuXgL0saiyXCA4WrfdkoFMJvPc1gpV0/ItXN4/NM +E1uhNGBgC93HYIQhm/ovMjkHdXfr8aGGpTy8WXps6KWqG66+dLNIPRpu807wQpYnkxxSJ6px/O/lxCmX +yx3gsm/FbkxU4zKKbesq3YdyNOFFTUkUugLYnuSK5M0I+focHH143yK900O/jQnrw8DdT4k7LxMFwU6s +EJ4D0cIzmyCPiapuOdfh9iK9tLOj3TKM3T+iYaGPqbw+DYrsb0zKp6anr/SkQvEQ9eqbxwcVr3GrI88W +VkeLr9NkclwXrFpXE8thvBxycrSfsad9T8A1PbouE+A8c1dgabvWe8HWwsKijbnrktsT9WztywlSshyU +SY7dZubFFnJh5b3dKdwljNZSZpQgq1SyiN28mlUwZTwg8oy+wwG5FUg442mQJGnkF8UiXH3zLetGOOkS +tyqg4/FrpTaHm0KngJ70ZVp3+XghWg9yyG4qJwfgd+H9h8JVp2fv4zZnmtZK7V9tQuzqORpAGne4ZNxo +hNoYzpoXLY49t14oMMhwBjkITJAxrLyx+8Z0dRyhzYHfhs2fGrfqhEreCGd2d6Ji1afggj2LoqNlbdGO +F/LdmKyRr3HI7GVWaqOQDKZLaQj8VmmdWNJJXdfp4+bIGN45Wlubq8ClxepHRysTN/Da/jIs3oOSN2Rf +gUGXxNUap+7+8W0W13MngUqA55VSW0WCWDJZjxLZG6LhIO8+1seRJueekjUvYLXOTJPtMi801eGVSgEE +pWk+0fRpEXxfaue+n3ARN5H25Mtyv3SdAV14KnwXQ93iSOnupq1jLyAg2xJxcLmFOZp2TDNBP1uF2Mh+ +PplunY/y22SW9dFyf0YBB41VsUVJnJCmYD5dAwAP5z3j35UgkjJdBZyPiusO4uogc2s8sgq8uwheKNcF +lSXMRSxc2+5qMKjymms76OkeX+7PyH1mWjiReu+MaYHGtWCXw92VauLJ4R4MYi/IBb0m8K03uf9blRsN +L5yiCj0LOol/8K5Zrn8QQvVcz0IkP3GBujYsWLBVYvwJu6RhbQWmk09mWTteCEfRz+xd0Jel9N6Pfl88 +jI1hS9zlg4wt8w3gfWxFKwo1l6l7ivkxI0swpSCCKMstKjR+KzT++dbXDRt2ymUBtdr+PN2k9d2OAW8W +PCw37EutiCymg1Ga6oQG2MkLJD8cuUbv/ylCC54ncGve0VAtNw6uloJKKGfEnlPVL6jz27jqIfiWKjS1 +kh9VsBtcxzi/dsY0ttbkZCCwxnO6b9VJhpRAZfwQ+ZiHI8usstf9VI+rdXaErKjsBxOT+XrftTjmULg2 +AKPIwYcMrMUWS1uWWl1s9bfKFlyfqnuxkIzdB7i8jrqUrxwC0nKwfB2H6VI87hrXl2wHAGUv6Qzzeeb4 +pDveO4KVUuYqEpatHuazrg3n31l7X5aNZRsjMDtoeilqj6swUthRvZkYvC5ZSxgps591mb9naydBE3r6 +c2R4qkhlHWtKmMIlPongCrC+lQZbFHhxLaCZXoIVP9u8sTpW4h66IxEWxqDsFxtoyBvKTzcu4hgKvDMg +XytFIwbpMWylUTTmCpE4t7YC5JPnHmaQGYt4bOSdYu6gFqyacPN5FOC7kMN3FcKyvlJfJBP/cv3RwG2a +k1RnjhZaTEccbI6zxVGfQSV4GGgpGvx5qg7TEYxsJAFerq5NX/2BufQWFEjnnsp7e0vj+zWBm/LRjT86 +ufntmTVmKiN7442eJKJCZF4dXXBJBS8rqndtBFtOvGV6RfDu5WlJ3ZLQS+Hpv8svr9V8L5ZMEfxDXicV +i000L7awvqhqU0mFjAnwmK4frc7qU4+l8soaLbZsCAHSPNTz1nSSLJeySJ0kiVRac8yCog7IhqobsxUY +7UncPPNgfeZhn43iXXtV1uAzt9aMjHZ0O6TcdX0Dnw32xwHejO4WUplL74do3uFKP/KSumJI9hlMEX59 +YV09e1Jg++KtYxJBMd9yFcIo/YpGnqpjp++RytFtUR29fjUVOLqNSvrTUxtW8LvsAvMis4rju7eTXugm +OgmcMypasn9QatfwkMwTCpBUWFG3iQ8nZylSChUTlh9fSI9ReEyiamGPjuw4FcojHlsD/J5E10qLvheU +UCHOJWJcwUPfIkBBwyK0frj/GX+weCsW/kVpjFmkCrlwKhJ5gRzzhi3TBAiQ5BS8K2GWe65jgrZ/KQLh +0h7NlnJGJ+tcLLd/G7kykqidnWlk6wX4YvdA8PVAunrCoKAagie09ksIvjHmvNPjC1e04LjvUnlIXCgl +I1iKspUVXcvgFSwSfY4LbpmdwqHvrc1HLa5MqMy7qr6FatSjoFdzg2yykihc0/CG8OefXGQ2UIlH16mo +nlNjuLyjVZMRoLk0I2raVgTVk/aW6TyvIjlyFDi/stGmMiU85FT9nivSNrf5RP01Q9yuDo8tRfZyOAdz ++31hum6Fy+VhE5pjMEhw9aWFq1H8V5q37q3d334so1ySyzkQDgZdYaiitS9IBji8DfwiZstGbamQ0512 +zLs0cl3AoZNiGNrQZck2ZV3lOsryrX0/JEEk/FIkgEq3+NiyJUu+b428BBoMhrSh7b7Xz+NtmbW/316Y +F+qgq2oTTG2Zp5Dp0EjdJqHkRJyuuvbQ0WGmgL0RCX3i3wRtS0QG9lfedYZLWj2r4LC5qi3Q1X/h9K25 +hsOC4OdQjZesOTl55ByBgkwH/UmmR8kjD80+P0fT1EG3tlwjUrKoH0uGKLgbMyJqH34aKhrg21sAO8ty +XgrHFTSSk5eVTm+2eB4zObT5N9Nse8fpMf44HhSWc0sOGnljcMWYnnxtRCtzNU53MIEbwzfABeyObuyd +58AdL/Xo6itSENjuA+b8SzRjVMNAb0zrs87oaAKpvHRnbwO375QlMzrEJKQlbKFDudfk8DNT8xQgcuQY +u2mHJg0fbUT54GOstq9huPvI+1TlGQlgyWFb7glqfuq8DbK9PBYAAAB0NQ01StUcQv8nAAD//7ImEwAH +FgAA +`, + }, + + "/img/logo/Cycore_web_optimized.jpg": { + local: "assets/img/logo/Cycore_web_optimized.jpg", + size: 53523, + modtime: 1476330413, + compressed: ` +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 +`, + }, + + "/js/home.js": { + local: "assets/js/home.js", + size: 1239, + modtime: 1526524154, + compressed: ` +H4sIAAAAAAAC/4xTTW/bMAy9+1dwvcjGGqe7OvAuxYbuqx2SDCtQFIMm07FWWXIlul0w5L8PkuXE69au +FwXhIx+fH8m614Kk0bBBOjXmRmKqeYsZ/EoAQNaQvqiM6FvUlIuARwgALFJvNeheqYUP7RL/CqMdwU9n +64HPQQkPKHLXKUkpW7AsUuUt71IB5WsQOVnZptkeqaUitCPoiFtyXyU1QSe8BFayLFsko9xJ41yh3lAD +ZVnCyf9kx2iFwlT4Zfnu1LSd0ahpynh1cj1qL1l29eo6WyS7JNmbKIwmLmiJtz06SmPPO24hiJ0Ycduj +3a5QoSBjUyZ119OVTyr9c82y/I6rHsdybLlUz6sPqX8RuF4IdO4Jikre5VyhpVnMHYbji2suVW/xWcVo +rbEsC57O57BEhwQWXWe0Q2iMqtA6D8YuudQa7dn600cogTGPxHYPkQAhiSY9ij7P7WD00fF+uN9NtS3g +/eriPHdkpd7IepuOIECYQxHe40MwWFYMPzG6y0a8Qe4lF6DxHs6GP1NGdmo0oabZetshK4DxrlNScL8Q +8x/OaDbpxC5nl6vl29n64sObc1ZMro59E87W+4M49G+RGlMVwD5frNbBn11IyqlBnY6rl3qL/b7FKlmH +SG5uDov/mOlxXWGFmtghd7iIUc+fxxO4/cel2aOKzKHzvyZq8had4xucEAjuxwt7CrT2aRKmke6NvYFh +7SLVLvkdAAD//6u/ggDXBAAA +`, + }, + + "/": { + isDir: true, + local: "assets", + }, + + "/css": { + isDir: true, + local: "assets/css", + }, + + "/img": { + isDir: true, + local: "assets/img", + }, + + "/img/logo": { + isDir: true, + local: "assets/img/logo", + }, + + "/js": { + isDir: true, + local: "assets/js", + }, +} diff --git a/templates.go b/templates.go new file mode 100644 index 0000000..bd4e3e0 --- /dev/null +++ b/templates.go @@ -0,0 +1,18 @@ +package main + +import ( + "html/template" + "io" + + "github.com/labstack/echo" +) + +// Template implements echo.Renderer +type Template struct { + templates *template.Template +} + +// Render executes the selected template with the given data +func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { + return t.templates.ExecuteTemplate(w, name, data) +} diff --git a/tests/apptest.go b/tests/apptest.go deleted file mode 100644 index e81ca3d..0000000 --- a/tests/apptest.go +++ /dev/null @@ -1,21 +0,0 @@ -package tests - -import "github.com/revel/revel/testing" - -type AppTest struct { - testing.TestSuite -} - -func (t *AppTest) Before() { - println("Set up") -} - -func (t *AppTest) TestThatIndexPageWorks() { - t.Get("/") - t.AssertOk() - t.AssertContentType("text/html; charset=utf-8") -} - -func (t *AppTest) After() { - println("Tear down") -} diff --git a/app/views/contact.html b/views/contact.html similarity index 84% rename from app/views/contact.html rename to views/contact.html index 050363b..f1120fb 100644 --- a/app/views/contact.html +++ b/views/contact.html @@ -1,5 +1,5 @@

Set up a no-obligation fifteen minute call now -
+ diff --git a/app/views/errors/404.html b/views/errors/404.html similarity index 100% rename from app/views/errors/404.html rename to views/errors/404.html diff --git a/app/views/errors/500.html b/views/errors/500.html similarity index 100% rename from app/views/errors/500.html rename to views/errors/500.html diff --git a/app/views/flash.html b/views/flash.html similarity index 100% rename from app/views/flash.html rename to views/flash.html diff --git a/views/footer.html b/views/footer.html new file mode 100644 index 0000000..483deb7 --- /dev/null +++ b/views/footer.html @@ -0,0 +1,12 @@ + + + + + diff --git a/app/views/header.html b/views/header.html similarity index 63% rename from app/views/header.html rename to views/header.html index 844e821..6e2c336 100644 --- a/app/views/header.html +++ b/views/header.html @@ -2,18 +2,18 @@ - {{.title}} + CyCore Systems, Inc - - + + {{range .moreStyles}} {{end}} {{range .moreScripts}} - + {{end}} diff --git a/app/views/App/Index.html b/views/index.html similarity index 83% rename from app/views/App/Index.html rename to views/index.html index c2fffb5..e0b57f6 100644 --- a/app/views/App/Index.html +++ b/views/index.html @@ -1,4 +1,3 @@ -{{set . "title" "CyCore Systems"}} {{template "header.html" .}}
@@ -11,7 +10,9 @@

- {{template "flash.html" .}} +
+
+ {{template "contact.html" .}}
@@ -28,4 +29,6 @@
+ + {{template "footer.html" .}}