From c510c5a1da6603c19437d88b6ff97774430fc40c Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Mon, 12 Jan 2015 12:35:36 -0800 Subject: [PATCH] Add feedback widget --- src/css/main.scss | 10 ++ src/css/mixins.scss | 2 +- src/css/templates/feedback.scss | 84 ++++++++++++++ src/css/templates/index.scss | 1 + src/images/paper.png | Bin 0 -> 1229 bytes src/pages/index.jade | 3 + src/pages/layouts/basic.jade | 22 ++-- .../controllers/feedback_controller.coffee | 103 ++++++++++++++++++ src/scripts/main.coffee | 4 + src/scripts/models/email_client.coffee | 57 ++++++++++ src/templates/feedback.jade | 19 ++++ 11 files changed, 294 insertions(+), 11 deletions(-) create mode 100644 src/css/templates/feedback.scss create mode 100644 src/images/paper.png create mode 100644 src/scripts/controllers/feedback_controller.coffee create mode 100644 src/scripts/models/email_client.coffee create mode 100644 src/templates/feedback.jade diff --git a/src/css/main.scss b/src/css/main.scss index 7cc287e20..a50e57582 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -48,6 +48,10 @@ $font-size-large: 1.6em; $font-size-x-large: 2.0em; $font-size-xx-large: 3.0em; +$layer-normal: 0; +$layer-screen: 5; +$layer-dialog: 10; + // Common ////////////////////////////////////////////////////////////////////////////////////////////////////////////// body { @@ -193,6 +197,12 @@ label { } } +.view__screen { + position: fixed; top: 0; right: 0; bottom: 0; left: 0; + display: none; + z-index: $layer-screen; +} + // Child Stylesheets /////////////////////////////////////////////////////////////////////////////////////////////////// @import 'templates/index'; diff --git a/src/css/mixins.scss b/src/css/mixins.scss index 4b8cc9a26..7c476ad9f 100644 --- a/src/css/mixins.scss +++ b/src/css/mixins.scss @@ -23,4 +23,4 @@ All rights reserved. -ms-transform: $transforms; -webkit-transform: $transforms; transform: $transforms; -} \ No newline at end of file +} diff --git a/src/css/templates/feedback.scss b/src/css/templates/feedback.scss new file mode 100644 index 000000000..cc7965adf --- /dev/null +++ b/src/css/templates/feedback.scss @@ -0,0 +1,84 @@ +/* +Crafting Guide - feedback.scss + +Copyright (c) 2014 by Redwood Labs +All rights reserved. +*/ + +.view__feedback { + position: fixed; top: 50%; left: -30em; width: 25em; + @include transform(translateY(-50%)); + + background: white; + border: 0.2em solid $color-gray-dark; + border-left: 0; + border-right: 0.1em solid $color-gray-faint; + box-size: border-box; + box-shadow: 0.3em 0.3em 0.6em 0 $color-gray-shadow; + padding: 2em; + z-index: $layer-dialog; + + .error { + background: white; + clear: both; + display: none; + margin-top: 4em; + text-align: center; + + p { + color: $color-error-new; + font-family: $font-family-normal; + font-size: $font-size-small; + } + } + + .label { + position: absolute; top: -0.2em; right: -4.5em; bottom:-0.2em; width: 4.5em; + + background: $color-gray-faint; + border: 0.2em solid $color-gray-dark; + border-bottom-right-radius: 1.0em; + border-left: 0; + border-top-right-radius: 1.0em; + box-shadow: 0.3em 0.3em 0.6em 0 $color-gray-shadow; + cursor: pointer; + text-align: center; + z-index: $layer-dialog - 1; + + img { + position: absolute; top: 0.5em; left: 50%; height: 3.6em; width: 3.6em; + @include transform(translateX(-50%)); + } + + p { + position: absolute; top: 50%; left: 50%; + @include transform(translateX(-50%) rotate(-90deg)); + + font-family: PressStart; + font-size: $font-size-large; + } + } + + button[name="send"] { + float: right; + margin-top: 0.5em; + } + + input { + position: relative; width: 100%; + + border: 1px solid $color-gray-light; + box-sizing: border-box; + margin-bottom: 1em; + padding: 0.2em; + } + + textarea { + border: 1px solid $color-gray-light; + position: relative; height: 11.5em; width: 100%; + + font-family: $font-family-input; + font-size: $font-size-normal; + resize: vertical; + } +} diff --git a/src/css/templates/index.scss b/src/css/templates/index.scss index cc1c82851..02a78b7a8 100644 --- a/src/css/templates/index.scss +++ b/src/css/templates/index.scss @@ -7,6 +7,7 @@ All rights reserved. @import 'crafting_grid'; @import 'crafting_table'; +@import 'feedback'; @import 'inventory'; @import 'item_page'; @import 'mod_pack'; diff --git a/src/images/paper.png b/src/images/paper.png new file mode 100644 index 0000000000000000000000000000000000000000..13332d9406ee7880d32cd3c470f9c36405096d8f GIT binary patch literal 1229 zcmV;;1Ty=HP)4Tx062|}Ro!pfR1`mnZ(O7nKcKOW4i$^9Ra0BJ8yc;~21%2p=|UR0&DbiW z$#rfTQ`a`O(`{9s_5yDV_yd5l2Of}kLK+Oj_Ok5(v`JGz71bo9J#^YYXp{DWs&KBa zQ@dTpxRI}aIp=pi@6k0t$5)!;m`NF6-tt{FpOKHBn3g+MAqmexC-gw4rh87hTrL7G z#)U`L!(So6-Zux@>;H3gR;i~0B%VTSS3P|m@o9jRsXML@Al^p#@G0Lx-0?i(9WEw_ zSYddU<1E8793KxjQ|c&UmW!mTC>k>?{om1c9S zUx<6_jj_!T&^M{wWM#>IBbOSf*xP<^F{$j$aOQ5Y{cT zROCL1M7^NKKL z&(yA}mSw#iM0^;IB{ZO5!wl{^Sg-*ysE~&Yz8!E;Qv(A`lu*=Clo*MpVGd>OdF6n^ zam1Jntk;<}MrqIC5$=Q>n{*R}?8oOIDUw5En2dl--Xw34!z7E+5pr-OgyQ-soSab)C%saskMla`aQLVzg0+MZf20tJU&K{hZoBrUc+U4e9&3o zw|KmGEe4#xz17wBu{f`SS_4i66?j31EjY7n{zGfhONK~c+td!TS#B}JoR}5UAd7p& z5phTyXSkK0xCeD3xaYP^o&J~#Xp9xFb0C;HHml5fA<%h1eR|qw7wxF+oNL9T1Aits?sKNIwvGaN)^WO$I^cUV)HzL_| z1K?{9p!>B*)`xfEv!4N6IG{J&h49W#Bz^(#YWw%`e_a{8n{G9m5AeR~_yl0%<7V@p zX^z8WGUo + options.model ?= new EmailClient + options.templateName = 'feedback' + super options + + Object.defineProperty this, 'isOpen', get:-> @$el.offset().left is 0 + + # Event Methods ################################################################################ + + onSendClicked: -> + return unless @$commentField.val().length > 0 + @$sendButton.attr 'disabled', 'disabled' + + message = + subject:'Crafting Guide Feedback' + body: + """ + url: #{window.location.href} + name: #{@$nameField.val()} + email: #{@$emailField.val()} + comment: + + #{@$commentField.val()} + """ + + @model.send(message) + .then => + @onToggle() + @$error.slideUp duration:Duration.fast + .catch (error)=> + @$error.slideDown duration:Duration.normal + .finally => + @$sendButton.removeAttr 'disabled' + + onTextChanged: (event)-> + if @$commentField.val().length > 0 + @$sendButton.removeAttr 'disabled' + else + @$sendButton.attr 'disabled', 'disabled' + + if event?.which is Key.Return and @$commentField.val().length > 0 + @onSendClicked() + + onToggle: -> + @$screen.off 'click' + + if @isOpen + @$screen.css display:'none' + @$el.animate {left:-@$el.outerWidth()}, duration:Duration.normal, complete:=> + @$commentField.val '' + @$('input, textarea').blur() + else + @$screen.on 'click', => @onToggle() + @$screen.css display:'block' + + @$el.animate {left:0}, duration:Duration.normal, complete:=> + if @$nameField.val().length is 0 + @$nameField.focus() + else if @$emailField.val().length is 0 + @$emailField.focus() + else + @$commentField.focus() + + # BaseController Overrides ##################################################################### + + onDidRender: -> + @$screen = $('.view__screen') + + @$commentField = @$('textarea[name="comment"]') + @$emailField = @$('input[name="email"]') + @$error = @$('.error') + @$nameField = @$('input[name="name"]') + @$sendButton = @$('button[name="send"]') + + windowHeight = window.innerHeight + @$el.delay(Duration.slow).animate {left:-@$el.outerWidth()}, Duration.slow + @onTextChanged() + + super + + # Backbone.View Methods ######################################################################## + + events: + 'click .label': 'onToggle' + 'click button': 'onSendClicked' + 'input textarea': 'onTextChanged' + 'keyup textarea': 'onTextChanged' diff --git a/src/scripts/main.coffee b/src/scripts/main.coffee index 5de287e6f..d04e55b28 100644 --- a/src/scripts/main.coffee +++ b/src/scripts/main.coffee @@ -8,6 +8,7 @@ All rights reserved. require './underscore_mixins' views = require './views' +FeedbackController = require './controllers/feedback_controller' Logger = require './logger' CraftingGuideRouter = require './crafting_guide_router' @@ -22,5 +23,8 @@ global.views = views if window.location.hostname is 'localhost' logger.level = Logger.TRACE +feedbackController = new FeedbackController el:'.view__feedback' +feedbackController.render() + logger.info "CraftingGuide is ready" Backbone.history.start pushState:true diff --git a/src/scripts/models/email_client.coffee b/src/scripts/models/email_client.coffee new file mode 100644 index 000000000..16545c237 --- /dev/null +++ b/src/scripts/models/email_client.coffee @@ -0,0 +1,57 @@ +### +Crafting Guide - email_client.coffee + +Copyright (c) 2015 by Redwood Labs +All rights reserved. +### + +######################################################################################################################## + +module.exports = class EmailClient + + constructor: -> + @baseUrl = 'https://mandrillapp.com:443/api/1.0' + @key = 'zaERWIuTVJaq0seCjjgVqw' + + # Public Methods ############################################################################### + + send: (options={})-> + options.body ?= "(no body)" + options.fromAddress ?= "wesbite@redwood-labs.com" + options.fromName ?= "Crafting Guide Website" + options.subject ?= "(no subject)" + options.toAddress ?= "crafting-guide@redwood-labs.com" + options.toName ?= "Crafting Guide" + + body = + key: @key + message: + from_email: options.fromAddress + from_name: options.fromName + subject: options.subject + text: options.body + to: [ email:options.toAddress, name:options.toName, type:'to' ] + + logger.info "sending email: #{util.inspect(body)}" + + w.promise (resolve, reject)=> + + onSuccess = (data, status, request)-> + logger.info "sending email result: #{util.inspect(data)}, status:#{status}" + data = if _.isArray data then data[0] else data + if data.status isnt "sent" + reject status:data.status, message:data.reject_reason + else + resolve status:data.status + + onError = (request, status, error)-> + logger.error "sending email failed: #{status}, error:#{error}" + reject status:status, message:error + + $.ajax "#{@baseUrl}/messages/send.json", + cache: false + data: body + dataType: 'json' + error: onError + success: onSuccess + type: 'POST' diff --git a/src/templates/feedback.jade b/src/templates/feedback.jade new file mode 100644 index 000000000..f509949f5 --- /dev/null +++ b/src/templates/feedback.jade @@ -0,0 +1,19 @@ +//- +//- Crafting Guide - feedback.jade +//- +//- Copyright (c) 2015 by Redwood Labs +//- All rights reserved. +//- + +.view__feedback + input(name="name", placeholder="name (optional)") + input(name="email", placeholder="email (optional)") + + label(name="comment") Comment: + textarea(name="comment") + button(name="send") send + .error: p Sending failed. Please try again later. + + .label + img(src="/images/paper.png") + p Feedback \ No newline at end of file