Add feedback widget
This commit is contained in:
@@ -48,6 +48,10 @@ $font-size-large: 1.6em;
|
|||||||
$font-size-x-large: 2.0em;
|
$font-size-x-large: 2.0em;
|
||||||
$font-size-xx-large: 3.0em;
|
$font-size-xx-large: 3.0em;
|
||||||
|
|
||||||
|
$layer-normal: 0;
|
||||||
|
$layer-screen: 5;
|
||||||
|
$layer-dialog: 10;
|
||||||
|
|
||||||
// Common //////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
// Common //////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
body {
|
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 ///////////////////////////////////////////////////////////////////////////////////////////////////
|
// Child Stylesheets ///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@import 'templates/index';
|
@import 'templates/index';
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ All rights reserved.
|
|||||||
|
|
||||||
@import 'crafting_grid';
|
@import 'crafting_grid';
|
||||||
@import 'crafting_table';
|
@import 'crafting_table';
|
||||||
|
@import 'feedback';
|
||||||
@import 'inventory';
|
@import 'inventory';
|
||||||
@import 'item_page';
|
@import 'item_page';
|
||||||
@import 'mod_pack';
|
@import 'mod_pack';
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -10,6 +10,9 @@ extends ./layouts/basic
|
|||||||
append styles
|
append styles
|
||||||
link(rel="stylesheet", type="text/css", href="/css/jquery-ui.css")
|
link(rel="stylesheet", type="text/css", href="/css/jquery-ui.css")
|
||||||
|
|
||||||
|
prepend body
|
||||||
|
.view__feedback
|
||||||
|
|
||||||
block content
|
block content
|
||||||
.page
|
.page
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,18 @@ html
|
|||||||
link(rel="stylesheet", type="text/css", href="/css/main.css")
|
link(rel="stylesheet", type="text/css", href="/css/main.css")
|
||||||
|
|
||||||
body
|
body
|
||||||
.content
|
block body
|
||||||
include ../includes/_header.jade
|
.view__screen
|
||||||
|
.content
|
||||||
|
include ../includes/_header.jade
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
|
||||||
include ../includes/_footer.jade
|
include ../includes/_footer.jade
|
||||||
|
|
||||||
block scripts
|
block scripts
|
||||||
script(src="/js/underscore.js")
|
script(src="/js/underscore.js")
|
||||||
script(src="/js/jquery.js")
|
script(src="/js/jquery.js")
|
||||||
script(src="/js/backbone.js")
|
script(src="/js/backbone.js")
|
||||||
script(src="/js/jade.js")
|
script(src="/js/jade.js")
|
||||||
script(src="/js/when.js")
|
script(src="/js/when.js")
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
###
|
||||||
|
Crafting Guide - feedback_controller.coffee
|
||||||
|
|
||||||
|
Copyright (c) 2015 by Redwood Labs
|
||||||
|
All rights reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
BaseController = require './base_controller'
|
||||||
|
{Duration} = require '../constants'
|
||||||
|
EmailClient = require '../models/email_client'
|
||||||
|
{Key} = require '../constants'
|
||||||
|
|
||||||
|
########################################################################################################################
|
||||||
|
|
||||||
|
module.exports = class FeedbackController extends BaseController
|
||||||
|
|
||||||
|
constructor: (options={})->
|
||||||
|
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'
|
||||||
@@ -8,6 +8,7 @@ All rights reserved.
|
|||||||
require './underscore_mixins'
|
require './underscore_mixins'
|
||||||
|
|
||||||
views = require './views'
|
views = require './views'
|
||||||
|
FeedbackController = require './controllers/feedback_controller'
|
||||||
Logger = require './logger'
|
Logger = require './logger'
|
||||||
CraftingGuideRouter = require './crafting_guide_router'
|
CraftingGuideRouter = require './crafting_guide_router'
|
||||||
|
|
||||||
@@ -22,5 +23,8 @@ global.views = views
|
|||||||
if window.location.hostname is 'localhost'
|
if window.location.hostname is 'localhost'
|
||||||
logger.level = Logger.TRACE
|
logger.level = Logger.TRACE
|
||||||
|
|
||||||
|
feedbackController = new FeedbackController el:'.view__feedback'
|
||||||
|
feedbackController.render()
|
||||||
|
|
||||||
logger.info "CraftingGuide is ready"
|
logger.info "CraftingGuide is ready"
|
||||||
Backbone.history.start pushState:true
|
Backbone.history.start pushState:true
|
||||||
|
|||||||
@@ -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 ?= "[email protected]"
|
||||||
|
options.fromName ?= "Crafting Guide Website"
|
||||||
|
options.subject ?= "(no subject)"
|
||||||
|
options.toAddress ?= "[email protected]"
|
||||||
|
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'
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user