commit 14b485e2d78aa993962871e0e7b37ba6e3359ae6 Author: Seán C McCord Date: Sat Sep 30 22:12:29 2017 -0400 initial commit diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..c4b8079 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,26 @@ +pipeline: + build: + image: ulexus/drone-revel + pull: true + commands: + - mkdir -p ${GOPATH}/github.com/CyCoreSystems/test-revel + - cp -a * ${GOPATH}/github.com/CyCoreSystems/test-revel/ + - revel build github.com/CyCoreSystems/test-revel tmp + publish: + image: plugins/docker + repo: quay.io/cycore/web + tags: + - "${DRONE_COMMIT}" + registry: quay.io + email: ulexus@gmail.com + secrets: [ docker_username, docker_password ] + deploy: + image: quay.io/honestbee/drone-kubernetes + namespace: web + deployment: cycore + container: web + secrets: [ kubernetes_username, kubernetes_token, kubernetes_server ] + repo: quay.io/cycore/web + tag: + - "${DRONE_COMMIT}" + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dae67d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +test-results/ +tmp/ +routes/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..303beee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM ulexus/go-minimal +COPY tmp/cycore-web /app +COPY tmp/src / diff --git a/README.md b/README.md new file mode 100644 index 0000000..1abb305 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Welcome to Revel + +## Getting Started + +A high-productivity web framework for the [Go language](http://www.golang.org/). + +### Start the web server: + + revel run myapp + + Run with --help for options. + +### Go to http://localhost:9000/ and you'll see: + +"It works" + +### Description of Contents + +The default directory structure of a generated Revel application: + + myapp App root + app App sources + controllers App controllers + init.go Interceptor registration + models App domain models + routes Reverse routes (generated code) + views Templates + tests Test suites + conf Configuration files + app.conf Main configuration file + routes Routes definition + messages Message files + public Public assets + css CSS files + js Javascript files + images Image files + +app + + The app directory contains the source code and templates for your application. + +conf + + The conf directory contains the application’s configuration files. There are two main configuration files: + + * app.conf, the main configuration file for the application, which contains standard configuration parameters + * routes, the routes definition file. + + +messages + + The messages directory contains all localized message files. + +public + + Resources stored in the public directory are static assets that are served directly by the Web server. Typically it is split into three standard sub-directories for images, CSS stylesheets and JavaScript files. + + The names of these directories may be anything; the developer need only update the routes. + +test + + Tests are kept in the tests directory. Revel provides a testing framework that makes it easy to write and run functional tests against your application. + +### Follow the guidelines to start developing your application: + +* The README file created within your application. +* The [Getting Started with Revel](http://revel.github.io/tutorial/index.html). +* The [Revel guides](http://revel.github.io/manual/index.html). +* The [Revel sample apps](http://revel.github.io/samples/index.html). +* The [API documentation](https://godoc.org/github.com/revel/revel). + +## Contributing +We encourage you to contribute to Revel! Please check out the [Contributing to Revel +guide](https://github.com/revel/revel/blob/master/CONTRIBUTING.md) for guidelines about how +to proceed. [Join us](https://groups.google.com/forum/#!forum/revel-framework)! diff --git a/app/controllers/app.go b/app/controllers/app.go new file mode 100644 index 0000000..e76d76b --- /dev/null +++ b/app/controllers/app.go @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000..555ffbf --- /dev/null +++ b/app/controllers/contact.go @@ -0,0 +1,109 @@ +package controllers + +import ( + "bytes" + "encoding/json" + "html/template" + "net/http" + "os" + "time" + + "github.com/CyCoreSystems/test-revel/app/routes" + "github.com/pkg/errors" + "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 +} + +// Request handles a customer contact request +func (c Contact) Request(name, email string) revel.Result { + emailBody, err := renderContactEmail(name, email) + if err != nil { + return c.Controller.RenderError(errors.Wrap(err, "failed to render email for contact request")) + } + + body, err := emailRequestBody(emailBody) + if err != nil { + return c.Controller.RenderError(errors.Wrap(err, "failed to encode email request")) + } + + // Don't sent when in dev mode + if revel.Config.BoolDefault("mode.dev", true) { + revel.INFO.Println("email:", name, email, bytes.NewBuffer(body).String()) + c.Flash.Success("request faked") + return c.Redirect(routes.App.Index()) + } + + mreq, err := http.NewRequest("POST", "https://api.sendinblue.com/v2.0/email", bytes.NewReader(body)) + mreq.Header.Add("api-key", os.Getenv("SENDINBLUE_APIKEY")) + mreq.Header.Add("Content-Type", "application/json") + mreq.Header.Add("X-Mailin-Tag", "contact-request") + + resp, err := http.DefaultClient.Do(mreq) + if err != nil { + revel.ERROR.Println("Failed to send contact request email", name, email, err) + return c.Controller.RenderError(errors.Wrap(err, "failed to send contact request email")) + } + if resp.StatusCode > 299 { + revel.ERROR.Println("Contact request email was rejected:", name, email, resp.Status, bytes.NewBuffer(body).String()) + c.Flash.Error("failed to send context request") + return c.Redirect(routes.App.Index()) + } + + c.Flash.Success("Request sent") + return c.Redirect(routes.App.Index()) +} + +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 emailRequestBody(email string) ([]byte, error) { + body := struct { + To map[string]string `json:"to"` + Subject string `json:"subject"` + From []string `json:"from"` + HTML string `json:"html"` + }{ + To: map[string]string{"ulexus@gmail.com": "Sean C McCord"}, + Subject: "Contact Request", + From: []string{"sys@cycoresys.com", "CyCore Systems Inc"}, + HTML: email, + } + return json.Marshal(&body) +} + +var contactEmailTemplate = ` + + +

Web Contact Form

+ + + +` diff --git a/app/init.go b/app/init.go new file mode 100644 index 0000000..2305d73 --- /dev/null +++ b/app/init.go @@ -0,0 +1,38 @@ +package app + +import "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) +} + +// 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. +} diff --git a/app/views/App/Index.html b/app/views/App/Index.html new file mode 100644 index 0000000..c2fffb5 --- /dev/null +++ b/app/views/App/Index.html @@ -0,0 +1,31 @@ +{{set . "title" "CyCore Systems"}} +{{template "header.html" .}} + +
+ +
+

+ Whether you need a design, an MVP, or a finished product: we solve problems. +

+
+
+ {{template "flash.html" .}} + {{template "contact.html" .}} +
+
+
    +
  • Architecture
  • +
  • Design
  • +
  • Performance
  • +
  • Containerizing
  • +
  • UI, UX, Usability
  • +
  • App Development
  • +
  • Voice & IoT
  • +
  • Training
  • +
+
+
+ +{{template "footer.html" .}} diff --git a/app/views/contact.html b/app/views/contact.html new file mode 100644 index 0000000..050363b --- /dev/null +++ b/app/views/contact.html @@ -0,0 +1,7 @@ +

Set up a no-obligation fifteen minute call now +
+ + + +
+

diff --git a/app/views/debug.html b/app/views/debug.html new file mode 100644 index 0000000..5f1013c --- /dev/null +++ b/app/views/debug.html @@ -0,0 +1,64 @@ + + + + + diff --git a/app/views/errors/404.html b/app/views/errors/404.html new file mode 100644 index 0000000..ebdfe10 --- /dev/null +++ b/app/views/errors/404.html @@ -0,0 +1,20 @@ + + + + Not found + + +{{if eq .RunMode "dev"}} +{{template "errors/404-dev.html" .}} +{{else}} + {{with .Error}} +

+ {{.Title}} +

+

+ {{.Description}} +

+ {{end}} +{{end}} + + diff --git a/app/views/errors/500.html b/app/views/errors/500.html new file mode 100644 index 0000000..0cef4de --- /dev/null +++ b/app/views/errors/500.html @@ -0,0 +1,16 @@ + + + + Application error + + + {{if eq .RunMode "dev"}} + {{template "errors/500-dev.html" .}} + {{else}} +

Oops, an error occured

+

+ This exception has been logged. +

+ {{end}} + + diff --git a/app/views/flash.html b/app/views/flash.html new file mode 100644 index 0000000..9c9ade9 --- /dev/null +++ b/app/views/flash.html @@ -0,0 +1,18 @@ +{{if .flash.success}} +
+ {{.flash.success}} +
+{{end}} + +{{if or .errors .flash.error}} +
+ {{if .flash.error}} + {{.flash.error}} + {{end}} + +
+{{end}} diff --git a/app/views/footer.html b/app/views/footer.html new file mode 100644 index 0000000..ead527b --- /dev/null +++ b/app/views/footer.html @@ -0,0 +1,25 @@ + + + + {{if eq .RunMode "dev"}} + {{template "debug.html" .}} + {{end}} + + diff --git a/app/views/header.html b/app/views/header.html new file mode 100644 index 0000000..844e821 --- /dev/null +++ b/app/views/header.html @@ -0,0 +1,19 @@ + + + + + {{.title}} + + + + + + + {{range .moreStyles}} + + {{end}} + {{range .moreScripts}} + + {{end}} + + diff --git a/conf/app.conf b/conf/app.conf new file mode 100644 index 0000000..ffb26a5 --- /dev/null +++ b/conf/app.conf @@ -0,0 +1,218 @@ +################################################################################ +# 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 = + +# 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 = log/%(app.name)s.log +log.error.output = log/%(app.name)s.log + +# 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 new file mode 100644 index 0000000..034b5f5 --- /dev/null +++ b/conf/routes @@ -0,0 +1,22 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +module:testrunner + +GET / App.Index + +# Handle contact requests +POST /contact/request Contact.Request + +# 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/messages/sample.en b/messages/sample.en new file mode 100644 index 0000000..fc447f9 --- /dev/null +++ b/messages/sample.en @@ -0,0 +1,7 @@ +# Sample messages file for the English language (en) +# Message file extensions should be ISO 639-1 codes (http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) +# Sections within each message file can optionally override the defaults using ISO 3166-1 alpha-2 codes (http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) +# See also: +# - http://www.rfc-editor.org/rfc/bcp/bcp47.txt +# - http://www.w3.org/International/questions/qa-accept-lang-locales + diff --git a/public/css/alert.import.less b/public/css/alert.import.less new file mode 100644 index 0000000..aad7399 --- /dev/null +++ b/public/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/public/css/anim.import.less b/public/css/anim.import.less new file mode 100644 index 0000000..d578fc0 --- /dev/null +++ b/public/css/anim.import.less @@ -0,0 +1 @@ +//ANIMATIONS diff --git a/public/css/base.import.less b/public/css/base.import.less new file mode 100644 index 0000000..0160eb0 --- /dev/null +++ b/public/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/public/css/button.import.less b/public/css/button.import.less new file mode 100644 index 0000000..4b9fd3a --- /dev/null +++ b/public/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/public/css/fonts.import.less b/public/css/fonts.import.less new file mode 100644 index 0000000..c82299b --- /dev/null +++ b/public/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/public/css/forms.import.less b/public/css/forms.import.less new file mode 100644 index 0000000..7f8ba68 --- /dev/null +++ b/public/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/public/css/grid.import.less b/public/css/grid.import.less new file mode 100644 index 0000000..7119e24 --- /dev/null +++ b/public/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/public/css/master.less b/public/css/master.less new file mode 100644 index 0000000..9d85086 --- /dev/null +++ b/public/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('/public/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/public/css/media.import.less b/public/css/media.import.less new file mode 100644 index 0000000..3207925 --- /dev/null +++ b/public/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/public/css/nav.import.less b/public/css/nav.import.less new file mode 100644 index 0000000..61ead1f --- /dev/null +++ b/public/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/public/css/rules.import.less b/public/css/rules.import.less new file mode 100644 index 0000000..2d57178 --- /dev/null +++ b/public/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/public/css/tables.import.less b/public/css/tables.import.less new file mode 100644 index 0000000..f46f8e8 --- /dev/null +++ b/public/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/public/css/var.import.less b/public/css/var.import.less new file mode 100644 index 0000000..628b6ac --- /dev/null +++ b/public/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/public/fonts/glyphicons-halflings-regular.ttf b/public/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..1413fc6 Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.ttf differ diff --git a/public/fonts/glyphicons-halflings-regular.woff b/public/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..9e61285 Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.woff differ diff --git a/public/fonts/glyphicons-halflings-regular.woff2 b/public/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/public/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/public/img/favicon.png b/public/img/favicon.png new file mode 100644 index 0000000..0303cba Binary files /dev/null and b/public/img/favicon.png differ diff --git a/public/img/logo/Cycore_web_optimized.jpg b/public/img/logo/Cycore_web_optimized.jpg new file mode 100644 index 0000000..ecc431e Binary files /dev/null and b/public/img/logo/Cycore_web_optimized.jpg differ diff --git a/public/scm.asc b/public/scm.asc new file mode 100644 index 0000000..73e82ed --- /dev/null +++ b/public/scm.asc @@ -0,0 +1,112 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +mQINBFdMggwBEACv2/63qtJF5hCZML+nNdTHS5Hmlu9QSEljtp7ju9oJExbXeMk7 +aOQeUWUoF2IiQBLMSZPtLk4m/gN45AYCBUrh+zgVVlDFDmEIt3PiNQdWKdQlWt3z +CjwS8gXdZU+HPBdg2ytDCNpXdFR8LlUr8uIRJ1zKVtGiaudmwIRWgnjouYg/dxNQ +j2MnRpPg/r7m0uqjlgKXwWLFTm6hEGSDE+f2zFhaVnoAXQgVub5CLtgWeDBhw+Mz +VmUjDQbrh9rSpF/zI+10qL3IdPjVLUgmPV7nHelko4NNxBvSOjmkHE9QkVnVmRPj +WJ0K7t++LxZ1ptzq2Ja+sem1V6yiAJ/gznIFuO+wC/TbmJQx9x+xxYnCVY1mQsqC +zSDieUDTA2+Fqqkmec2U9rVMwHeXnLaDsDZ8QNB3OVVSsv5o1dsiHZrdX4XWaRXx +liGZa+QKcV7c/OW5Ni4eCHoMs7mGz7KuEZdASgEWxS18jKTaGWPFCMOSaJhNxyes +EWWX+qFexUYy0GAbWnQUx4dtfmvnAx/bg5r5CuCaRPjMWEboB0sWvdP902Uhcefn +swLWHBNKrQBiHvEDjjydfl3cNzMbxAXVzyZoGAAiAzGdFqk/p7Rr/fdD+wAOhfVO +JlRH2cwdshtDBoFiLjPQyzyI/6DXZs6akqv5LixAyxI9AR/2AT8mxPSMcQARAQAB +tCFTZcOhbiBDIE1jQ29yZCA8dWxleHVzQGdtYWlsLmNvbT6JAjkEEwEIACMFAldM +ggwCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBQ3KOO/Uf3v0EWD/0Q +We17hanENr/KU30bDLN/Cw7KOFFshOkp7j/oD5m2zl6N+iNeF4+OQVyWFQTAgUms +MZTSb44TAJj/VC9C1PpFSEkKOhVMDzYfLLpSIgvNzbBpRWuWfEpG7yU9E//CKYrF +D2BWIoumA2pjMheTahGwvvgy/YAkVbrydxcKRsKNzsjyYj5j57H4Xo1yX4nj+s0X +nPu4ia09n8ZyqZYi6rijKbusGMFdAmIfe4zbsMcwdSeXOJMctwtOVRolJFGz71D+ +1y9lZUHucoC7mu4p92aZshpHjv9ek3/DRGJ0d0/5ZxVhSW1O/Fk2GbUw9cu4rtxI +XwPG1krBKG2DxRCVrtHTmxlhUaRMwGA5FyO0apa4Rb1aaMgfXl4k8pI0jpUD+bik +156mWkZZNn5bQNNKHvuvbtOGOn3rzhvEGi6FpaI+Wg6M3bdqdEqw3f2KqBw2VMOV +w+7xrDZR78FZ2kcm7CQzGLhAr1DJoe3ClobKpQb90skDV7W60lUTDwkmDq/uzFzY +YZencHy6eA2Y/Y82SrdioW+ISl6ZDWBr0ICfmZK853PXgRj5LoT71XathzS6Gdpc +jUs1RwT5ywLL4+KlqhG/F7ndFrYOBCwB3OC0KAmKmjEIfBFN2G2bjHQJJVKzg57G +kdS53bda515PuEOLiZFANKaDxMosfxa5y0PDrfVchbQ5U2XDoW4gQyBNY0NvcmQg +KGh0dHA6Ly9jeWNvcmVzeXMuY29tKSA8c2NtQGN5Y29yZXN5cy5jb20+iQI5BBMB +CAAjBQJXeW1PAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQUNyjjv1H +9782GhAAqtw31A8vqqDJlrheTOpvB2XzJRUUvN5mljEqumt/t0rF3DBy2tJFYqfG +KhHdyS3jmjQO9y8j4TDDItV1GsYlxhpfFYL9OegIwOW4trMXKRtPTohlK2dvAJrT +VyEiFMuRPZpBa9q9MiT37j/Wf2OyxY4vMSbu/oU2cHDIXf16MOw9Uz+yVGD7VVbl +IdxhueCMY5qUf6OZMFd1+X3tyvs9/fc8RANXb4ecsSmjrNMKK6tEBiJWf5jAbO80 +Hwj7beIb6uZzT6zccGDaPdpijWzCQjrjdm2trJQOPoI66rrKe66zdz23k77AFKEL +w5sFlHhwLuB8yNn6iTquI1++nKUxmxh/KCwV1t0R4m7kAauiFmm18+qGBE7lpumh +F5g5CfNAs/avb/s+kGWFNJte8W7MroNroBJ0E3AoppJWxhqag8IR9HBhq3snnu6I +00T3JMvD88tHS5mCr0ktdQgDimofHNuTZEo7H/tB3uNbLXnJnlDEdNqNchoD+CtE +ZcEoC+vwaPDWobKD5saE1lX+MnK3ffYpom6rfSU4/uF7zlEpiT17TvXpYncBWlei +xeG6ThggqF2uJJ1fS8mOY7L7U8hB7VwC3+OaeP+SMG1xDfqz5M59BiNqKSaZzMEd +/u8nfcyKpGfRg+izN3ker4jbzz7F3MBW3KUpW5hUXetwip9gjre0OVNlw6FuIEMg +TWNDb3JkIChodHRwOi8vY3ljb3Jlc3lzLmNvbSkgPHN5c0BjeWNvcmVzeXMuY29t +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 +dvqfj+9x +=isk0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/apptest.go b/tests/apptest.go new file mode 100644 index 0000000..e81ca3d --- /dev/null +++ b/tests/apptest.go @@ -0,0 +1,21 @@ +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") +}